后台可以筛选管理员

This commit is contained in:
2025-04-30 09:51:19 +08:00
parent 1fd36ef617
commit 09e693bf25
5 changed files with 124 additions and 28 deletions

View File

@@ -60,7 +60,9 @@ class User(AbstractBaseUser):
return self.problem_permission == ProblemPermission.ALL return self.problem_permission == ProblemPermission.ALL
def is_contest_admin(self, contest): def is_contest_admin(self, contest):
return self.is_authenticated and (contest.created_by == self or self.admin_type == AdminType.SUPER_ADMIN) return self.is_authenticated and (
contest.created_by == self or self.admin_type == AdminType.SUPER_ADMIN
)
class Meta: class Meta:
db_table = "user" db_table = "user"

View File

@@ -43,9 +43,10 @@ class GenerateUserSerializer(serializers.Serializer):
password_length = serializers.IntegerField(max_value=16, default=8) password_length = serializers.IntegerField(max_value=16, default=8)
class ImportUserSeralizer(serializers.Serializer): class ImportUserSerializer(serializers.Serializer):
users = serializers.ListField( users = serializers.ListField(
child=serializers.ListField(child=serializers.CharField(max_length=64))) child=serializers.ListField(child=serializers.CharField(max_length=64))
)
class UserAdminSerializer(serializers.ModelSerializer): class UserAdminSerializer(serializers.ModelSerializer):
@@ -53,8 +54,19 @@ class UserAdminSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = User model = User
fields = ["id", "username", "email", "admin_type", "problem_permission", "real_name", fields = [
"create_time", "last_login", "two_factor_auth", "open_api", "is_disabled"] "id",
"username",
"email",
"admin_type",
"problem_permission",
"real_name",
"create_time",
"last_login",
"two_factor_auth",
"open_api",
"is_disabled",
]
def get_real_name(self, obj): def get_real_name(self, obj):
return obj.userprofile.real_name return obj.userprofile.real_name
@@ -63,8 +75,18 @@ class UserAdminSerializer(serializers.ModelSerializer):
class UserSerializer(serializers.ModelSerializer): class UserSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = User model = User
fields = ["id", "username", "email", "admin_type", "problem_permission", fields = [
"create_time", "last_login", "two_factor_auth", "open_api", "is_disabled"] "id",
"username",
"email",
"admin_type",
"problem_permission",
"create_time",
"last_login",
"two_factor_auth",
"open_api",
"is_disabled",
]
class UserProfileSerializer(serializers.ModelSerializer): class UserProfileSerializer(serializers.ModelSerializer):
@@ -87,11 +109,16 @@ class EditUserSerializer(serializers.Serializer):
id = serializers.IntegerField() id = serializers.IntegerField()
username = serializers.CharField(max_length=32) username = serializers.CharField(max_length=32)
real_name = serializers.CharField(max_length=32, allow_blank=True, allow_null=True) real_name = serializers.CharField(max_length=32, allow_blank=True, allow_null=True)
password = serializers.CharField(min_length=6, allow_blank=True, required=False, default=None) password = serializers.CharField(
min_length=6, allow_blank=True, required=False, default=None
)
email = serializers.EmailField(max_length=64) email = serializers.EmailField(max_length=64)
admin_type = serializers.ChoiceField(choices=(AdminType.REGULAR_USER, AdminType.ADMIN, AdminType.SUPER_ADMIN)) admin_type = serializers.ChoiceField(
problem_permission = serializers.ChoiceField(choices=(ProblemPermission.NONE, ProblemPermission.OWN, choices=(AdminType.REGULAR_USER, AdminType.ADMIN, AdminType.SUPER_ADMIN)
ProblemPermission.ALL)) )
problem_permission = serializers.ChoiceField(
choices=(ProblemPermission.NONE, ProblemPermission.OWN, ProblemPermission.ALL)
)
open_api = serializers.BooleanField() open_api = serializers.BooleanField()
two_factor_auth = serializers.BooleanField() two_factor_auth = serializers.BooleanField()
is_disabled = serializers.BooleanField() is_disabled = serializers.BooleanField()

View File

@@ -13,12 +13,16 @@ from utils.shortcuts import rand_str
from ..decorators import super_admin_required from ..decorators import super_admin_required
from ..models import AdminType, ProblemPermission, User, UserProfile from ..models import AdminType, ProblemPermission, User, UserProfile
from ..serializers import EditUserSerializer, UserAdminSerializer, GenerateUserSerializer from ..serializers import (
from ..serializers import ImportUserSeralizer EditUserSerializer,
UserAdminSerializer,
GenerateUserSerializer,
)
from ..serializers import ImportUserSerializer
class UserAdminAPI(APIView): class UserAdminAPI(APIView):
@validate_serializer(ImportUserSeralizer) @validate_serializer(ImportUserSerializer)
@super_admin_required @super_admin_required
def post(self, request): def post(self, request):
""" """
@@ -30,12 +34,23 @@ class UserAdminAPI(APIView):
for user_data in data: for user_data in data:
if len(user_data) != 4 or len(user_data[0]) > 32: if len(user_data) != 4 or len(user_data[0]) > 32:
return self.error(f"Error occurred while processing data '{user_data}'") return self.error(f"Error occurred while processing data '{user_data}'")
user_list.append(User(username=user_data[0], password=make_password(user_data[1]), email=user_data[2])) user_list.append(
User(
username=user_data[0],
password=make_password(user_data[1]),
email=user_data[2],
)
)
try: try:
with transaction.atomic(): with transaction.atomic():
ret = User.objects.bulk_create(user_list) ret = User.objects.bulk_create(user_list)
UserProfile.objects.bulk_create([UserProfile(user=ret[i], real_name=data[i][3]) for i in range(len(ret))]) UserProfile.objects.bulk_create(
[
UserProfile(user=ret[i], real_name=data[i][3])
for i in range(len(ret))
]
)
return self.success() return self.success()
except IntegrityError as e: except IntegrityError as e:
# Extract detail from exception message # Extract detail from exception message
@@ -54,9 +69,17 @@ class UserAdminAPI(APIView):
user = User.objects.get(id=data["id"]) user = User.objects.get(id=data["id"])
except User.DoesNotExist: except User.DoesNotExist:
return self.error("User does not exist") return self.error("User does not exist")
if User.objects.filter(username=data["username"].lower()).exclude(id=user.id).exists(): if (
User.objects.filter(username=data["username"].lower())
.exclude(id=user.id)
.exists()
):
return self.error("Username already exists") return self.error("Username already exists")
if User.objects.filter(email=data["email"].lower()).exclude(id=user.id).exists(): if (
User.objects.filter(email=data["email"].lower())
.exclude(id=user.id)
.exists()
):
return self.error("Email already exists") return self.error("Email already exists")
pre_username = user.username pre_username = user.username
@@ -94,7 +117,9 @@ class UserAdminAPI(APIView):
user.save() user.save()
if pre_username != user.username: if pre_username != user.username:
Submission.objects.filter(username=pre_username).update(username=user.username) Submission.objects.filter(username=pre_username).update(
username=user.username
)
UserProfile.objects.filter(user=user).update(real_name=data["real_name"]) UserProfile.objects.filter(user=user).update(real_name=data["real_name"])
return self.success(UserAdminSerializer(user).data) return self.success(UserAdminSerializer(user).data)
@@ -114,11 +139,18 @@ class UserAdminAPI(APIView):
user = User.objects.all().order_by("-create_time") user = User.objects.all().order_by("-create_time")
is_admin = request.GET.get("admin", False)
if is_admin:
user = user.exclude(admin_type=AdminType.REGULAR_USER)
keyword = request.GET.get("keyword", None) keyword = request.GET.get("keyword", None)
if keyword: if keyword:
user = user.filter(Q(username__icontains=keyword) | user = user.filter(
Q(userprofile__real_name__icontains=keyword) | Q(username__icontains=keyword)
Q(email__icontains=keyword)) | Q(userprofile__real_name__icontains=keyword)
| Q(email__icontains=keyword)
)
return self.success(self.paginate_data(request, user, UserAdminSerializer)) return self.success(self.paginate_data(request, user, UserAdminSerializer))
@super_admin_required @super_admin_required
@@ -162,7 +194,9 @@ class GenerateUserAPI(APIView):
Generate User Generate User
""" """
data = request.data data = request.data
number_max_length = max(len(str(data["number_from"])), len(str(data["number_to"]))) number_max_length = max(
len(str(data["number_from"])), len(str(data["number_to"]))
)
if number_max_length + len(data["prefix"]) + len(data["suffix"]) > 32: if number_max_length + len(data["prefix"]) + len(data["suffix"]) > 32:
return self.error("Username should not more than 32 characters") return self.error("Username should not more than 32 characters")
if data["number_from"] > data["number_to"]: if data["number_from"] > data["number_to"]:
@@ -180,15 +214,19 @@ class GenerateUserAPI(APIView):
user_list = [] user_list = []
for number in range(data["number_from"], data["number_to"] + 1): for number in range(data["number_from"], data["number_to"] + 1):
raw_password = rand_str(data["password_length"]) raw_password = rand_str(data["password_length"])
user = User(username=f"{data['prefix']}{number}{data['suffix']}", password=make_password(raw_password)) user = User(
username=f"{data['prefix']}{number}{data['suffix']}",
password=make_password(raw_password),
)
user.raw_password = raw_password user.raw_password = raw_password
user_list.append(user) user_list.append(user)
try: try:
with transaction.atomic(): with transaction.atomic():
ret = User.objects.bulk_create(user_list) ret = User.objects.bulk_create(user_list)
UserProfile.objects.bulk_create([UserProfile(user=user) for user in ret]) UserProfile.objects.bulk_create(
[UserProfile(user=user) for user in ret]
)
for item in user_list: for item in user_list:
worksheet.write_string(i, 0, item.username) worksheet.write_string(i, 0, item.username)
worksheet.write_string(i, 1, item.raw_password) worksheet.write_string(i, 1, item.raw_password)

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.0.6 on 2025-04-30 01:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('problem', '0015_alter_problem_io_mode_alter_problem_languages_and_more'),
]
operations = [
migrations.AlterField(
model_name='problem',
name='last_update_time',
field=models.DateTimeField(auto_now=True),
),
]

View File

@@ -1,3 +1,4 @@
from django.conf import settings
from django.db import models from django.db import models
from utils.models import JSONField from utils.models import JSONField
@@ -59,7 +60,7 @@ class Problem(models.Model):
template = JSONField() template = JSONField()
create_time = models.DateTimeField(auto_now_add=True) create_time = models.DateTimeField(auto_now_add=True)
# we can not use auto_now here # we can not use auto_now here
last_update_time = models.DateTimeField(null=True) last_update_time = models.DateTimeField(auto_now=True)
created_by = models.ForeignKey(User, on_delete=models.CASCADE) created_by = models.ForeignKey(User, on_delete=models.CASCADE)
# ms # ms
time_limit = models.IntegerField() time_limit = models.IntegerField()
@@ -82,7 +83,7 @@ class Problem(models.Model):
total_score = models.IntegerField(default=0) total_score = models.IntegerField(default=0)
submission_number = models.BigIntegerField(default=0) submission_number = models.BigIntegerField(default=0)
accepted_number = models.BigIntegerField(default=0) accepted_number = models.BigIntegerField(default=0)
# {JudgeStatus.ACCEPTED: 3, JudgeStaus.WRONG_ANSWER: 11}, the number means count # {JudgeStatus.ACCEPTED: 3, JudgeStatus.WRONG_ANSWER: 11}, the number means count
statistic_info = JSONField(default=dict) statistic_info = JSONField(default=dict)
share_submission = models.BooleanField(default=False) share_submission = models.BooleanField(default=False)
@@ -98,3 +99,13 @@ class Problem(models.Model):
def add_ac_number(self): def add_ac_number(self):
self.accepted_number = models.F("accepted_number") + 1 self.accepted_number = models.F("accepted_number") + 1
self.save(update_fields=["accepted_number"]) self.save(update_fields=["accepted_number"])
# class ProblemSet(models):
# title = models.CharField(max_length=20)
# subtitle = models.CharField(max_length=50)
# problems = models.ManyToManyField(Problem)
# badge = models.FilePathField(path=settings.UPLOAD_DIR)
# overviews = models.JSONField()
# create_time = models.DateTimeField(auto_now_add=True)
# update_time = models.DateTimeField(auto_now=True)