""" POST /api/user/delete — حذفِ حسابِ خود (۲۰۲۶-۱۰-۰۲). راه‌های شکستن: حذف با توکنِ تنها (بی‌کد)، حدسِ کد، حذفِ حسابِ دمو، و پاک شدنِ سندِ مالی. """ from django.core.cache import cache from django.test import TestCase, override_settings from django.utils import timezone from rest_framework.test import APIClient from accounts.authentication import issue_access_token from accounts.models import OTPCode, User from payment.models import Order from progress.models import UserStats def _client(user): client = APIClient() client.credentials(HTTP_AUTHORIZATION=f'Bearer {issue_access_token(user.id)}') return client class DeleteAccountTests(TestCase): def setUp(self): cache.clear() self.user = User.objects.create(phone='09121115001') UserStats.objects.create(user_id=self.user.id, xp=50) self.client = _client(self.user) def code(self, value='482913'): OTPCode.objects.create(phone=self.user.phone, code=value, expires_at=timezone.now() + timezone.timedelta(minutes=5)) return value def delete(self, **body): return self.client.post('/api/user/delete', body, format='json') def test_a_token_alone_is_not_enough(self): self.assertEqual(self.delete().status_code, 400) self.assertTrue(User.objects.filter(pk=self.user.pk).exists()) def test_a_wrong_code_deletes_nothing(self): self.code() self.assertEqual(self.delete(otp='111111').status_code, 400) self.assertTrue(User.objects.filter(pk=self.user.pk).exists()) def test_the_right_code_deletes_everything_but_payment_records(self): Order.objects.create(user_id=self.user.id, amount=99000, status='paid', idempotency_key='k') response = self.delete(otp=self.code()) self.assertEqual(response.status_code, 200, response.content) self.assertFalse(User.objects.filter(pk=self.user.pk).exists()) self.assertFalse(UserStats.objects.filter(user_id=self.user.pk).exists()) self.assertTrue(Order.objects.filter(user_id=self.user.pk).exists()) # توکنِ قبلی دیگر به هیچ کاربری نمی‌رسد. self.assertIn(self.client.get('/api/user/profile').status_code, (401, 403)) @override_settings(TEST_LOGIN_PHONES={'09121115001': '4321'}) def test_demo_accounts_cannot_be_deleted(self): self.assertEqual(self.delete(otp='4321').status_code, 403) self.assertTrue(User.objects.filter(pk=self.user.pk).exists())