feat(admin): Phase 3 平台团队+用户管理 — 列/启停/详情/强制改密 + 团队停用拦登录
后端:adminpanel 增 teams(列/详情/启停)+ users(列/启停/强制改密),AdminTeam/User 序列化器; login 校验团队 status,停用团队成员拒登;停用用户清 token、禁停平台超管;全程 IsPlatformAdmin + 审计。 前端:adminApi teams/users 系列;Admin 团队页(筛选+搜索+详情弹窗+启停)、用户页(启停+改密弹窗,超管行禁操作)。 测试:adminpanel 19 + accounts 22 = 41 单测过;无头 e2e _admin-p3.mjs 7 断言过 + 0 console error (UI 停用团队→成员登录 400→启用→200;UI 改密→新密码登录 200);tsc+build 绿。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
45a4ceae51
commit
6560633959
@@ -0,0 +1,47 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from apps.accounts.models import Team, TeamMember, User
|
||||
|
||||
|
||||
class AdminTeamSerializer(serializers.ModelSerializer):
|
||||
owner_username = serializers.CharField(source="owner.username", read_only=True, default=None)
|
||||
member_count = serializers.SerializerMethodField()
|
||||
balance = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Team
|
||||
fields = ["id", "name", "status", "owner", "owner_username", "member_count", "balance", "created_at"]
|
||||
read_only_fields = fields
|
||||
|
||||
def get_member_count(self, obj):
|
||||
anno = getattr(obj, "member_count_anno", None)
|
||||
return anno if anno is not None else obj.members.count()
|
||||
|
||||
def get_balance(self, obj):
|
||||
acct = getattr(obj, "credit_account", None)
|
||||
return str(acct.balance) if acct is not None else "0"
|
||||
|
||||
|
||||
class AdminTeamMemberSerializer(serializers.ModelSerializer):
|
||||
username = serializers.CharField(source="user.username", read_only=True)
|
||||
user_status = serializers.CharField(source="user.status", read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = TeamMember
|
||||
fields = ["id", "username", "role", "status", "user_status", "monthly_credit_limit"]
|
||||
read_only_fields = fields
|
||||
|
||||
|
||||
class AdminUserSerializer(serializers.ModelSerializer):
|
||||
teams = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ["id", "username", "status", "is_platform_admin", "date_joined", "teams"]
|
||||
read_only_fields = fields
|
||||
|
||||
def get_teams(self, obj):
|
||||
return [
|
||||
{"team_id": str(m.team_id), "team_name": m.team.name, "role": m.role}
|
||||
for m in obj.team_memberships.select_related("team").all()
|
||||
]
|
||||
Reference in New Issue
Block a user