Remove guest login: every user registers with a phone number
POST /api/auth/session is gone (404). Existing is_guest rows keep refresh and upgrade-by-phone until the demo/guest rows are purged; the code that serves them is listed in docs/security-before-production.md §10. Tests that used the endpoint as a fixture now use accounts/testing.guest_session. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -21,8 +21,6 @@ from .services import OTPDeliveryError, send_otp_sms
|
||||
from .serializers import (
|
||||
DeleteAccountRequestSerializer,
|
||||
DeleteAccountResponseSerializer,
|
||||
GuestSessionRequestSerializer,
|
||||
GuestSessionResponseSerializer,
|
||||
LoginRequestSerializer,
|
||||
LoginResponseSerializer,
|
||||
LogoutRequestSerializer,
|
||||
@@ -43,7 +41,7 @@ logger = logging.getLogger(__name__)
|
||||
class GuestAwareAccountThrottle(ScopedRateThrottle):
|
||||
"""
|
||||
همان الگویِ GuestAwareContentThrottle (content/views.py)،
|
||||
GuestAwareAIThrottle (ai_tutor/views.py) و بقیه؛ چون GuestSessionView
|
||||
GuestAwareAIThrottle (ai_tutor/views.py) و بقیه؛ چون ورودِ مهمان (حذفشده؛ حسابهای مهمانِ قبلی هنوز هستند)
|
||||
با هر deviceId جدید یک کاربرِ مهمانِ تازه (pk جدید) میسازه، یک
|
||||
ScopedRateThrottleِ سادهٔ per-user توسطِ چرخشِ حساب مهمان دورزدنی
|
||||
بود. اینجا برای SetUserGradeView (که مهمانها هم میتونن صداش بزنن)
|
||||
@@ -64,58 +62,6 @@ class GuestAwareAccountThrottle(ScopedRateThrottle):
|
||||
return self.cache_format % {'scope': self.scope, 'ident': ident}
|
||||
|
||||
|
||||
class GuestSessionView(APIView):
|
||||
"""POST /api/auth/session — ایجاد سشن مهمان"""
|
||||
|
||||
throttle_scope = 'guest_session'
|
||||
throttle_classes = [ScopedRateThrottle]
|
||||
|
||||
@extend_schema(
|
||||
request=GuestSessionRequestSerializer,
|
||||
responses=GuestSessionResponseSerializer,
|
||||
tags=['Identity & Profile (accounts)'],
|
||||
)
|
||||
def post(self, request):
|
||||
serializer = GuestSessionRequestSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
device_id = serializer.validated_data['deviceId']
|
||||
|
||||
user, is_new_user = User.objects.get_or_create(
|
||||
device_id=device_id,
|
||||
is_guest=True,
|
||||
defaults={'name': ''},
|
||||
)
|
||||
|
||||
# ثبتِ فعالیتِ کاربر: ایجاد/استفادهی سشنِ مهمان یک سشنِ واقعیِ
|
||||
# کاربره، پس last_activity_at بهروزرسانی میشه (بدونِ تأثیر روی
|
||||
# سایرِ رفتارِ endpoint).
|
||||
user.last_activity_at = timezone.now()
|
||||
user.save(update_fields=['last_activity_at'])
|
||||
|
||||
token = issue_access_token(user.id)
|
||||
|
||||
# مهمان هم refresh token میگیرد. قبلاً فقط توکنِ یکساعته داشت؛ بعد از
|
||||
# یک ساعت همهی درخواستها ۴۰۱ میشدند درحالیکه اپ هنوز خودش را
|
||||
# واردشده میدید. امنیتی کم نمیشود: خودِ deviceId از قبل برای گرفتنِ
|
||||
# توکنِ تازه کافی بود.
|
||||
refresh_token = secrets.token_hex(32)
|
||||
Session.objects.create(
|
||||
user=user,
|
||||
refresh_token=hash_refresh_token(refresh_token),
|
||||
device_id=device_id,
|
||||
expires_at=timezone.now() + timezone.timedelta(days=settings.REFRESH_TOKEN_TTL_DAYS),
|
||||
)
|
||||
|
||||
data = {
|
||||
'userId': str(user.id),
|
||||
'token': token,
|
||||
'refreshToken': refresh_token,
|
||||
'isNewUser': is_new_user,
|
||||
'isGuest': True,
|
||||
}
|
||||
return Response(GuestSessionResponseSerializer(data).data)
|
||||
|
||||
|
||||
class RequestOTPView(APIView):
|
||||
"""
|
||||
POST /api/auth/otp/request — درخواستِ کدِ ورود.
|
||||
@@ -650,7 +596,7 @@ class UserProfileView(APIView):
|
||||
def get(self, request):
|
||||
user = request.user
|
||||
# مدل Profile بهصورت lazy ساخته میشه چون هیچجای دیگهای (نه
|
||||
# GuestSessionView، نه LoginView) رکورد Profile رو از قبل نمیسازه؛
|
||||
# LoginView) رکورد Profile رو از قبل نمیسازه؛
|
||||
# get_or_create اینجا امن است چون فقط توسطِ کاربرِ همون رکورد صدا
|
||||
# زده میشه (OneToOne روی user_id جاری، نه ورودیِ خارجی).
|
||||
profile, _ = Profile.objects.get_or_create(user_id=user.id)
|
||||
|
||||
Reference in New Issue
Block a user