- /api/payment/orders/{id}/pay requires the short-lived signature that paymentUrl carries;
without it (or with another order's) it is the same 404 as an unknown order
- Session.refresh_token stores the SHA-256 of the token; migration accounts.0007 hashes the
existing rows so tokens clients already hold keep working
- /api/leaderboard requires a token (guests have one); names of children were scrapable
- RAG mock only for `manage.py test`, not any command with an argument named "test"
- tools/loadtest: user factory, load generator, fake GapGPT+Qdrant, with method notes
- security-before-production.md lists only open items; closed ones become a guards table
with the tests that hold them. Comments describe current behaviour, not history
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
31 lines
1.4 KiB
Python
31 lines
1.4 KiB
Python
# Run with: manage.py shell -c "exec(open('tools/loadtest/mkusers.py').read())" env: LT_N, LT_PREFIX, LT_SEED
|
|
# Creates N non-guest test users (fake 0900… numbers, no signals, no SMS) and prints
|
|
# [{userId, token, grade, asks:[{lessonId, question}], nodeId, questionIds}] as JSON.
|
|
import json
|
|
import os
|
|
import random
|
|
|
|
from accounts.authentication import issue_access_token
|
|
from accounts.models import User
|
|
from content.models import Lesson, Question
|
|
|
|
N = int(os.environ['LT_N'])
|
|
PREFIX = os.environ.get('LT_PREFIX', '0900990')
|
|
GRADES = [8, 9, 10, 11, 12, 4, 5, 6, 7, 3]
|
|
rnd = random.Random(int(os.environ.get('LT_SEED', '7')))
|
|
|
|
out = []
|
|
for i in range(N):
|
|
grade = GRADES[i % len(GRADES)]
|
|
phone = f'{PREFIX}{i:04d}'
|
|
user, _ = User.objects.get_or_create(phone=phone, defaults={'is_guest': False, 'name': f'تست بار {i}', 'grade_id': grade})
|
|
qs = list(Question.objects.filter(lesson__node__unit__grade_id=grade).select_related('lesson__node')
|
|
.values_list('id', 'prompt', 'lesson_id', 'lesson__node_id')[:4000])
|
|
picks = rnd.sample(qs, 6)
|
|
out.append({
|
|
'userId': user.id, 'token': issue_access_token(user.id), 'grade': grade,
|
|
'asks': [{'lessonId': p[2], 'question': f'این سوال رو قدم به قدم توضیح بده: {p[1][:300]}'} for p in picks[:3]],
|
|
'nodeId': picks[3][3], 'answerQuestionIds': [p[0] for p in picks[3:]],
|
|
})
|
|
print('LTJSON' + json.dumps(out, ensure_ascii=False))
|