Remove the guest system entirely: no is_guest/device_id, no guest throttles, phone login is the only way in

accounts.0008 drops the columns and refuses to run while guest rows exist.
Docs describe the current state; tests that only proved guest behaviour are gone.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-05 18:20:10 +03:30
parent 8835e01595
commit 663252a260
61 changed files with 357 additions and 1518 deletions

View File

@@ -462,7 +462,7 @@ REST_FRAMEWORK = {
],
# بدونِ NUM_PROXIES، DRF هدرِ X-Forwarded-For رو بدون‌چک به‌عنوانِ IP
# کلاینت قبول می‌کنه؛ یعنی هر کلاینت می‌تونست با XFF دلخواه، bucket
# تازه از GuestAware*Throttleها بگیره (bypassِ چرخشِ حساب مهمان). این
# تازه از throttleهای IP-محور بگیره. این
# مقدار باید دقیقاً با تعدادِ لایه‌ی پراکسی/LB جلوی اپ یکی باشه (مثلاً
# Cloudflare+Nginx=۲)، وگرنه IP واقعی اشتباه خونده می‌شه.
#
@@ -579,7 +579,7 @@ SPECTACULAR_SETTINGS = {
'\n'
'## قراردادها\n'
'\n'
'- نامِ فیلدها `camelCase` است (`deviceId`, `refreshToken`, `nodeId`).\n'
'- نامِ فیلدها `camelCase` است (`refreshToken`, `nodeId`).\n'
'- زمان‌ها ISO 8601 با منطقه‌ی زمانی‌اند.\n'
'- متنِ رو به کاربر فارسی است؛ شناسه‌ها و نامِ فیلدها انگلیسی.\n'
'- این اسکیما **مرجعِ قرارداد** است. کلاینت را از روی حافظه ننویسید — '
@@ -724,11 +724,6 @@ def _parse_test_login_phones(raw: str) -> dict[str, str]:
TEST_LOGIN_PHONES = _parse_test_login_phones(os.environ.get('TEST_LOGIN_PHONES', ''))
# مهمان‌های نمایشی که با حذفِ حساب پاک نمی‌شوند (همان کاری که TEST_LOGIN_PHONES برای شماره‌ها می‌کند).
# پیش‌فرض: حسابِ مهمانِ تستِ فرانت (کاربرِ ۶ روی سرور)، که شناسه‌اش در ریپو و مستندات آمده و هر کسی
# می‌تواند با آن وارد شود. با پاک شدنِ داده‌ی دمو پیش از کاربرِ واقعی، این پیش‌فرض هم برداشته شود.
DEMO_GUEST_DEVICE_IDS = _env_list('DEMO_GUEST_DEVICE_IDS') or ['frontend-test-device']
# -----------------------------------------------------------------------
# OTP SMS delivery (accounts/services.py: send_otp_sms)
# -----------------------------------------------------------------------

View File

@@ -171,7 +171,7 @@ class APIRequestLoggingMiddlewareTests(TestCase):
self.client = APIClient()
def test_authenticated_api_request_is_logged_with_user_id_and_no_secrets(self):
user = User.objects.create(device_id='device-mw-log-1', is_guest=True, name='')
user = User.objects.create(phone='09000000005', name='')
token = issue_access_token(user.id)
from content.models import Grade

View File

@@ -30,7 +30,7 @@ def _client(user):
class _Base(TestCase):
def setUp(self):
cache.clear()
self.user = User.objects.create(phone='09120008001', is_guest=False)
self.user = User.objects.create(phone='09120008001')
self.client = _client(self.user)
self.year = Plan.objects.create(title='سالانه', price=299000, duration_days=365)
@@ -57,18 +57,6 @@ class OfferNeverShortensSubscription(_Base):
self.assertEqual(response.status_code, 200, response.content)
self.assertEqual(Subscription.objects.get(user_id=self.user.id).expires_at, before)
@override_settings(DEV_MASTER_OTP='000000')
def test_guest_who_paid_keeps_the_year_after_registering(self):
Offer.objects.create(name='هفته رایگان', kind='trial', duration_days=7,
auto_assign_on_signup=True)
guest = User.objects.create(device_id='audit-2-device', is_guest=True)
guest_client = _client(guest)
self.pay(self.buy(guest_client), ref='R2')
response = guest_client.post('/api/auth/login', {'phone': '09125550001', 'otp': '000000'},
format='json')
self.assertEqual(response.status_code, 200, response.content)
days = (Subscription.objects.get(user_id=guest.id).expires_at - timezone.now()).days
self.assertGreater(days, 360)
def test_trial_still_works_for_a_user_without_subscription(self):
Offer.objects.create(name='هفته رایگان', kind='trial', duration_days=7, code='WEEK')