Signed payment links, hashed refresh tokens, login-only leaderboard, load test tools
- /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>
This commit is contained in:
@@ -269,7 +269,21 @@ class FourCompanionsCatalogTests(TestCase):
|
||||
|
||||
|
||||
class LeaderboardPeriodValidationTests(TestCase):
|
||||
def test_unknown_period_is_a_400(self):
|
||||
def setUp(self):
|
||||
from accounts.authentication import issue_access_token
|
||||
from accounts.models import User
|
||||
from rest_framework.test import APIClient
|
||||
self.assertEqual(APIClient().get('/api/leaderboard?period=xyz').status_code, 400)
|
||||
self.assertEqual(APIClient().get('/api/leaderboard?period=all_time').status_code, 200)
|
||||
|
||||
self.client = APIClient()
|
||||
user = User.objects.create(device_id='lb-dev', is_guest=True)
|
||||
self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {issue_access_token(user.id)}')
|
||||
|
||||
def test_unknown_period_is_a_400(self):
|
||||
self.assertEqual(self.client.get('/api/leaderboard?period=xyz').status_code, 400)
|
||||
self.assertEqual(self.client.get('/api/leaderboard?period=all_time').status_code, 200)
|
||||
|
||||
def test_requires_login(self):
|
||||
# نامِ کاربران (بیشترشان کودک) نباید بیورود قابلِ جمعآوری باشد؛ مهمان هم توکن دارد.
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
self.assertEqual(APIClient().get('/api/leaderboard').status_code, 401)
|
||||
|
||||
@@ -91,7 +91,7 @@ class ActivityFeedsStreakAndLeaderboardTests(TestCase):
|
||||
)
|
||||
|
||||
for period in ('weekly', 'all_time'):
|
||||
entries = self.client.get(f'/api/leaderboard?period={period}').json()['entries']
|
||||
entries = self.client.get(f'/api/leaderboard?period={period}', **self.auth).json()['entries']
|
||||
self.assertEqual(entries[0]['userId'], str(self.user.id), period)
|
||||
self.assertEqual(entries[0]['name'], 'سارا')
|
||||
self.assertEqual(entries[0]['xpInPeriod'], 30, period)
|
||||
|
||||
@@ -127,8 +127,14 @@ LEADERBOARD_CACHE_TTL = 60
|
||||
|
||||
|
||||
class LeaderboardView(APIView):
|
||||
"""GET /api/leaderboard?period= — رتبهبندی هفتگی/ماهانه"""
|
||||
"""
|
||||
GET /api/leaderboard?period= — رتبهبندی هفتگی/ماهانه
|
||||
|
||||
فقط برای کاربرِ واردشده (مهمان هم توکن دارد): پاسخ نامِ کاربران، که بیشترشان کودکاند،
|
||||
و شناسهی داخلیشان را دارد و بدونِ ورود برای هر کسی در اینترنت قابلِ جمعآوری بود.
|
||||
"""
|
||||
|
||||
permission_classes = [IsAuthenticated]
|
||||
throttle_scope = 'read'
|
||||
throttle_classes = [GuestAwareReadThrottle]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user