diff --git a/frontend/admin.py b/frontend/admin.py index cee93ba..62ca49f 100644 --- a/frontend/admin.py +++ b/frontend/admin.py @@ -9,9 +9,9 @@ from server.terms.models import Terms from server.trigger.models import Trigger from server.user.models import User -from .models import Page, Account, Code, UstcSnos, UstcEligible, Qa, Credits +from .models import Page, Account, Code, AccountLog, SpecialProfileUsedRecord, Qa, Credits -admin.site.register([Page, Account, Code, UstcSnos, UstcEligible, Qa, Credits]) +admin.site.register([Page, Account, Code, Qa, Credits, SpecialProfileUsedRecord]) class PermissionListFilter(admin.SimpleListFilter): @@ -57,3 +57,8 @@ def has_delete_permission(self, request, obj=None): def has_view_permission(self, request, obj=None): return False + + +@admin.register(AccountLog) +class AccountLogAdmin(admin.ModelAdmin): + search_fields = ["account__pk", "contents"] diff --git a/frontend/auth_providers/ustc.py b/frontend/auth_providers/ustc.py index 211cb8c..1005026 100644 --- a/frontend/auth_providers/ustc.py +++ b/frontend/auth_providers/ustc.py @@ -7,7 +7,7 @@ from django.shortcuts import redirect from django.urls import path -from ..models import UstcSnos +from ..models import AccountLog from .base import BaseLoginView @@ -53,13 +53,13 @@ def to_set(s): def from_set(vs): return ','.join(sorted(vs)) try: - o = account.ustcsnos - new_snos = from_set(to_set(o.snos) | {self.sno}) - if new_snos != o.snos: - o.snos = new_snos + o = AccountLog.objects.get(account=account, content_type='学号') + new_snos = from_set(to_set(o.contents) | {self.sno}) + if new_snos != o.contents: + o.contents = new_snos o.save() - except UstcSnos.DoesNotExist: - UstcSnos.objects.create(account=account, snos=self.sno) + except AccountLog.DoesNotExist: + AccountLog.objects.create(account=account, contents=f"{self.sno}", content_type='学号') return account diff --git a/frontend/migrations/0007_accountlog_specialprofileusedrecord_and_more.py b/frontend/migrations/0007_accountlog_specialprofileusedrecord_and_more.py new file mode 100644 index 0000000..bca3a30 --- /dev/null +++ b/frontend/migrations/0007_accountlog_specialprofileusedrecord_and_more.py @@ -0,0 +1,62 @@ +# Generated by Django 4.2.5 on 2023-10-12 17:46 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + dependencies = [ + ("auth", "0012_alter_user_first_name_max_length"), + ("frontend", "0006_credits"), + ] + + operations = [ + migrations.CreateModel( + name="AccountLog", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("contents", models.TextField()), + ("content_type", models.CharField(default="学号", max_length=32)), + ( + "account", + models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, + to="frontend.account", + ), + ), + ], + ), + migrations.CreateModel( + name="SpecialProfileUsedRecord", + fields=[ + ( + "user", + models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, + primary_key=True, + serialize=False, + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + migrations.RemoveField( + model_name="ustcsnos", + name="account", + ), + migrations.DeleteModel( + name="UstcEligible", + ), + migrations.DeleteModel( + name="UstcSnos", + ), + ] diff --git a/frontend/migrations/0008_accountlog_unique_account_log_for_each_type.py b/frontend/migrations/0008_accountlog_unique_account_log_for_each_type.py new file mode 100644 index 0000000..5f9f20b --- /dev/null +++ b/frontend/migrations/0008_accountlog_unique_account_log_for_each_type.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.5 on 2023-10-12 18:06 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("frontend", "0007_accountlog_specialprofileusedrecord_and_more"), + ] + + operations = [ + migrations.AddConstraint( + model_name="accountlog", + constraint=models.UniqueConstraint( + fields=("account", "content_type"), + name="unique_account_log_for_each_type", + ), + ), + ] diff --git a/frontend/models.py b/frontend/models.py index 0ea3ed1..7feaa9a 100644 --- a/frontend/models.py +++ b/frontend/models.py @@ -28,6 +28,9 @@ class Account(models.Model): identity = models.TextField() user = models.ForeignKey(get_user_model(), models.CASCADE, null=True) + def __str__(self): + return f'User {self.user.pk} ({self.provider}:{self.identity})' + class Meta: unique_together = ('provider', 'identity') @@ -71,14 +74,29 @@ def authenticate(cls, provider, identity, code): return False -class UstcSnos(models.Model): - account = models.OneToOneField(Account, models.CASCADE, primary_key=True) - snos = models.TextField() +# 记录特殊登录方式(例如 USTC CAS)的用户,其登录方式返回的「可靠」信息 +class AccountLog(models.Model): + account = models.OneToOneField(Account, models.CASCADE, db_index=True) + contents = models.TextField() + content_type = models.CharField(max_length=32, default='学号') + + def __str__(self): + return f"Account {self.account.pk} ({self.content_type} {self.contents})" + + class Meta: + constraints = [ + models.UniqueConstraint(fields=['account', 'content_type'], + name='unique_account_log_for_each_type'), + ] -class UstcEligible(models.Model): +# 记录需要在首次登录后显示换组页面并且已经换组的用户 +# 目前只有 USTC 有这个需求 +class SpecialProfileUsedRecord(models.Model): user = models.OneToOneField(get_user_model(), models.CASCADE, primary_key=True) - eligible = models.BooleanField() + + def __str__(self) -> str: + return f"A used record of User id {self.user.pk}" class Qa(models.Model): diff --git a/frontend/templates/admin_user.html b/frontend/templates/admin_user.html index 14d0b86..2f48ba1 100644 --- a/frontend/templates/admin_user.html +++ b/frontend/templates/admin_user.html @@ -21,7 +21,10 @@

正在创建

- 跳转到 Django 用户模型页面…… + 跳转到 Django 用户模型页面(配置权限)…… +
+
+ 跳转到 Account 模型页面(查看登录方式信息)……
diff --git a/frontend/views.py b/frontend/views.py index 5de5567..f8078a1 100644 --- a/frontend/views.py +++ b/frontend/views.py @@ -18,7 +18,7 @@ from server.context import Context from server.exceptions import Error, NotFound, WrongFormat -from frontend.models import Account, Credits, Qa, UstcEligible +from frontend.models import Account, Credits, Qa, SpecialProfileUsedRecord # noinspection PyMethodMayBeStatic @@ -27,8 +27,8 @@ def get(self, request): if request.user.is_authenticated: if Account.objects.filter(provider='ustc', user=request.user).exists(): try: - request.user.ustceligible - except UstcEligible.DoesNotExist: + request.user.specialprofileusedrecord + except SpecialProfileUsedRecord.DoesNotExist: return redirect('ustcprofile') context = Context.from_request(request) try: @@ -228,9 +228,9 @@ def check(self): if request.user.is_authenticated: if Account.objects.filter(provider='ustc', user=request.user).exists(): try: - request.user.ustceligible + request.user.specialprofileusedrecord return False - except UstcEligible.DoesNotExist: + except SpecialProfileUsedRecord.DoesNotExist: return True return False @@ -244,11 +244,11 @@ def post(self, request): return redirect('hub') eligible = request.POST['eligible'] if eligible == 'yes': - UstcEligible.objects.create(user=request.user, eligible=True) + SpecialProfileUsedRecord.objects.create(user=request.user) user = User.get(Context.from_request(request).copy(elevated=True), request.user.pk) user.update(group='ustc') elif eligible == 'no': - UstcEligible.objects.create(user=request.user, eligible=False) + SpecialProfileUsedRecord.objects.create(user=request.user) return redirect('hub')