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

@@ -49,36 +49,10 @@ class SendSMSForm(forms.Form):
return cleaned_data
class DeviceIdForSuperuserOnly:
"""
شناسه‌ی دستگاهِ حساب‌های مهمانِ قدیمی (که دیگر ساخته نمی‌شوند) تنها رمزِ ورودشان بود؛ پس فقط ابرکاربر
آن را در فهرست، جستجو و فرم می‌بیند، نه کارمندی با اجازه‌ی دیدن (گروهِ Supervisor).
"""
def get_list_display(self, request):
cols = super().get_list_display(request)
return cols if request.user.is_superuser else tuple(c for c in cols if c != 'device_id')
def get_search_fields(self, request):
cols = super().get_search_fields(request)
return cols if request.user.is_superuser else tuple(c for c in cols if c != 'device_id')
def get_exclude(self, request, obj=None):
exclude = tuple(super().get_exclude(request, obj) or ())
return exclude if request.user.is_superuser else exclude + ('device_id',)
def lookup_allowed(self, lookup, value, request=None):
# جنگو هر فیلترِ querystring روی فیلدِ خودِ مدل را می‌پذیرد (?device_id__startswith=a)؛
# بی‌این، با شمردنِ نتیجه شناسه حرف‌به‌حرف درمی‌آید. جنگو برای فیلترِ ردشده ۴۰۰ می‌دهد.
if lookup.split('__')[0] == 'device_id' and not (request and request.user.is_superuser):
return False
return super().lookup_allowed(lookup, value, request)
@admin.register(User)
class UserAdmin(DeviceIdForSuperuserOnly, admin.ModelAdmin):
list_display = ('id', 'public_id', 'name', 'phone', 'device_id', 'is_guest', 'grade_id', 'created_at')
search_fields = ('name', 'phone', 'device_id')
class UserAdmin(admin.ModelAdmin):
list_display = ('id', 'public_id', 'name', 'phone', 'grade_id', 'created_at')
search_fields = ('name', 'phone')
@admin.display(description='شناسه‌ی نمایشی')
def public_id(self, obj):
@@ -94,15 +68,13 @@ class UserAdmin(DeviceIdForSuperuserOnly, admin.ModelAdmin):
if user_id:
results |= queryset.filter(pk=user_id)
return results, may_have_duplicates
list_filter = ('is_guest',)
actions = ['send_sms_to_selected']
def get_readonly_fields(self, request, obj=None):
# شماره کلیدِ ورود است: کارمندی با change_user که شماره‌ی کاربری را به شماره‌ی خودش عوض
# کند، کد می‌گیرد و واردِ همان حساب می‌شود. is_guest هم همین‌طور ورود با شناسه‌ی دستگاه را
# روی حسابِ شماره‌دار باز می‌کند. هر دو فقط برای ابرکاربر قابلِ تغییرند.
# کند، کد می‌گیرد و واردِ همان حساب می‌شود؛ پس فقط ابرکاربر آن را عوض می‌کند.
fields = tuple(super().get_readonly_fields(request, obj))
return fields if request.user.is_superuser else fields + ('phone', 'is_guest')
return fields if request.user.is_superuser else fields + ('phone',)
# permissions=['change']: بدونِ این، کاربرِ فقط-view (گروهِ Supervisor)
# می‌تونست با POSTِ مستقیم این اکشن رو صدا بزنه بدونِ دیدنِ دکمه در UI؛
@@ -198,8 +170,8 @@ class ProfileAdmin(admin.ModelAdmin):
@admin.register(Session)
class SessionAdmin(DeviceIdForSuperuserOnly, admin.ModelAdmin):
list_display = ('id', 'user', 'device_id', 'expires_at', 'revoked')
class SessionAdmin(admin.ModelAdmin):
list_display = ('id', 'user', 'expires_at', 'revoked')
list_filter = ('revoked',)