From f6f5a8af7e6c5359e13d7c75172adb0bc6cac555 Mon Sep 17 00:00:00 2001
From: hyb <kk_huangyangbo@163.com>
Date: Fri, 23 Jan 2026 01:53:11 +0000
Subject: [PATCH] feat: 添加用户登录功能、添加注册功能、注册审批功能,参考:注册审批功能测试指南.md、驱动代码模块增加插入其他项目代码功能,驱动代码模块增加插入其他项目代码功能,优化测试报告模块前端布局和美化 - 实现超级用户管理系统用户,可进行增删改查,其他用户只可查看本人的数据,不可进行增删改 - 将Django后台管理中的用户配置相关功能迁移到系统中进行适配、可配置禁用、是否管理员、是否超级用户 - 增加用户管理的分组字段、可直接进行分组操作,实现用户管理即可通过分组配置实现各项目的访问权限 - 实现登录页面注册 - 实现管理员首页点击注册用户审批可实现通过不通过 - 实现未审核用户的登录提示与审核未通过的用户登录提示 - 实现一键插入其他本人可访问项目的脚本代码

---
 测试组/Test_platform/Interface_automation/backend/apps/lunaruser/serializers.py |  170 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 170 insertions(+), 0 deletions(-)

diff --git "a/\346\265\213\350\257\225\347\273\204/Test_platform/Interface_automation/backend/apps/lunaruser/serializers.py" "b/\346\265\213\350\257\225\347\273\204/Test_platform/Interface_automation/backend/apps/lunaruser/serializers.py"
index 0f05856..5bcac19 100644
--- "a/\346\265\213\350\257\225\347\273\204/Test_platform/Interface_automation/backend/apps/lunaruser/serializers.py"
+++ "b/\346\265\213\350\257\225\347\273\204/Test_platform/Interface_automation/backend/apps/lunaruser/serializers.py"
@@ -10,6 +10,7 @@
 
 from rest_framework import serializers
 from django.contrib.auth import get_user_model
+from django.contrib.auth.models import Group
 
 from lunarlink.models import LoginLog
 
@@ -67,3 +68,172 @@
         if attrs['new_password'] != attrs['confirm_password']:
             raise serializers.ValidationError("两次输入的新密码不一致")
         return attrs
+
+
+class UserCreateSerializer(serializers.ModelSerializer):
+    """
+    创建用户序列化
+    """
+    password = serializers.CharField(required=True, min_length=6, max_length=128, write_only=True)
+    confirm_password = serializers.CharField(required=True, max_length=128, write_only=True)
+    groups = serializers.PrimaryKeyRelatedField(
+        many=True,
+        queryset=Group.objects.all(),
+        required=False
+    )
+
+    class Meta:
+        model = User
+        fields = ['id', 'username', 'password', 'confirm_password', 'name', 'phone', 'is_staff', 'is_superuser', 'is_active', 'groups', 'show_hosts']
+
+    def validate(self, attrs):
+        if attrs['password'] != attrs['confirm_password']:
+            raise serializers.ValidationError("两次输入的密码不一致")
+        return attrs
+
+    def create(self, validated_data):
+        validated_data.pop('confirm_password')
+        password = validated_data.pop('password')
+        groups = validated_data.pop('groups', None)
+        user = User(**validated_data)
+        user.set_password(password)
+        user.save()
+        if groups:
+            user.groups.set(groups)
+        return user
+
+
+class UserUpdateSerializer(serializers.ModelSerializer):
+    """
+    更新用户序列化
+    """
+    groups = serializers.PrimaryKeyRelatedField(
+        many=True,
+        queryset=Group.objects.all(),
+        required=False
+    )
+
+    class Meta:
+        model = User
+        fields = ['id', 'username', 'name', 'phone', 'is_staff', 'is_superuser', 'is_active', 'groups', 'show_hosts']
+
+    def update(self, instance, validated_data):
+        groups = validated_data.pop('groups', None)
+        for attr, value in validated_data.items():
+            setattr(instance, attr, value)
+        instance.save()
+        if groups is not None:
+            instance.groups.set(groups)
+        return instance
+
+
+class UserDetailSerializer(serializers.ModelSerializer):
+    """
+    用户详情序列化
+    """
+    groups = serializers.SerializerMethodField()
+    accessible_projects = serializers.SerializerMethodField()
+    status_display = serializers.CharField(source='get_status_display', read_only=True)
+
+    class Meta:
+        model = User
+        fields = ['id', 'username', 'name', 'phone', 'is_staff', 'is_superuser', 'is_active', 'groups', 'show_hosts', 'date_joined', 'last_login', 'accessible_projects', 'status', 'status_display']
+
+    def get_groups(self, obj):
+        return [g.name for g in obj.groups.all()]
+
+    def get_accessible_projects(self, obj):
+        from lunarlink.models import Project
+        user_groups = obj.groups.all()
+        return list(Project.objects.filter(groups__in=user_groups).distinct().values_list("name", flat=True))
+
+
+class UserRegisterSerializer(serializers.ModelSerializer):
+    """
+    用户注册序列化
+    """
+    password = serializers.CharField(required=True, min_length=6, max_length=128, write_only=True)
+    confirm_password = serializers.CharField(required=True, max_length=128, write_only=True)
+    groups = serializers.PrimaryKeyRelatedField(
+        many=True,
+        queryset=Group.objects.all(),
+        required=False
+    )
+
+    class Meta:
+        model = User
+        fields = ['username', 'password', 'confirm_password', 'name', 'phone', 'groups']
+        extra_kwargs = {
+            'username': {'validators': []},
+            'phone': {'validators': []}
+        }
+
+    def validate_username(self, value):
+        existing_user = User.objects.filter(username=value).first()
+        if existing_user and existing_user.status != 'rejected':
+            raise serializers.ValidationError("用户名已存在")
+        return value
+
+    def validate_phone(self, value):
+        if value:
+            existing_user = User.objects.filter(phone=value).first()
+            if existing_user and existing_user.status != 'rejected':
+                raise serializers.ValidationError("手机号已存在")
+        return value
+
+    def validate(self, attrs):
+        if attrs['password'] != attrs['confirm_password']:
+            raise serializers.ValidationError("两次输入的密码不一致")
+        return attrs
+
+    def create(self, validated_data):
+        validated_data.pop('confirm_password')
+        password = validated_data.pop('password')
+        groups = validated_data.pop('groups', None)
+        
+        username = validated_data['username']
+        phone = validated_data.get('phone')
+        
+        existing_user = User.objects.filter(username=username).first()
+        if existing_user and existing_user.status == 'rejected':
+            user = existing_user
+            user.name = validated_data.get('name', user.name)
+            user.phone = phone
+            user.set_password(password)
+            user.status = 'pending'
+            user.is_active = False
+            user.save()
+            if groups:
+                user.groups.set(groups)
+            return user
+        
+        if phone:
+            existing_phone_user = User.objects.filter(phone=phone).first()
+            if existing_phone_user and existing_phone_user.status == 'rejected':
+                user = existing_phone_user
+                user.username = username
+                user.name = validated_data.get('name', user.name)
+                user.set_password(password)
+                user.status = 'pending'
+                user.is_active = False
+                user.save()
+                if groups:
+                    user.groups.set(groups)
+                return user
+        
+        user = User(**validated_data)
+        user.set_password(password)
+        user.status = 'pending'
+        user.is_active = False
+        user.save()
+        if groups:
+            user.groups.set(groups)
+        return user
+
+
+class UserApprovalSerializer(serializers.Serializer):
+    """
+    用户审批序列化
+    """
+    action = serializers.ChoiceField(choices=['approve', 'reject'])
+    reason = serializers.CharField(required=False, allow_blank=True, max_length=500)

--
Gitblit v1.9.1