public user IDs, plans priced by tutor cost, age-based tutor tone, self-service account deletion
- profile publicId ("User482917", accounts/public_id.py); admin shows and searches it
- plans API reports aiDailyQuota per plan and freeAiDailyQuota; migration 0007 sets the
temporary prices (monthly 99,000 / yearly 990,000 toman, 5 tutor questions a day) unless
an admin already edited the yearly plan
- tutor tone follows the learner's age (18+ gets an adult tone at any grade); notation
still follows the grade's book; answer cache keyed by tone (prompt tutor-v12-age-tone)
- POST /api/user/delete: phone users confirm with a fresh SMS code (same checks as login,
now shared in verify_phone_otp), guests type "حذف"; payment records are kept, demo
accounts refused
- delete_users --skip-paid
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -88,3 +88,17 @@ class ProfileBirthDateApiTests(TestCase):
|
||||
|
||||
def test_parent_phone_is_gone(self):
|
||||
self.assertNotIn('parentPhone', self.client.get('/api/user/profile').json())
|
||||
|
||||
|
||||
class PublicIdTests(TestCase):
|
||||
def test_profile_shows_a_six_digit_code_that_maps_back_to_the_user(self):
|
||||
from accounts.public_id import decode
|
||||
|
||||
user = User.objects.create(device_id='public-id-device', is_guest=True)
|
||||
client = APIClient()
|
||||
client.credentials(HTTP_AUTHORIZATION=f'Bearer {issue_access_token(user.id)}')
|
||||
code = client.get('/api/user/profile').json()['publicId']
|
||||
self.assertRegex(code, r'^User\d{6}$')
|
||||
self.assertEqual(decode(code), user.id)
|
||||
self.assertEqual(decode(code[4:]), user.id)
|
||||
self.assertIsNone(decode('User12'))
|
||||
|
||||
Reference in New Issue
Block a user