diff --git a/TempLate/index.html b/TempLate/index.html
index 7a4b4866..a979603b 100644
--- a/TempLate/index.html
+++ b/TempLate/index.html
@@ -5,7 +5,7 @@
银河锋锐(GVSDS)
-
+
diff --git a/backup/www/index.html b/backup/www/index.html
index 023ef771..7a4b4866 100644
--- a/backup/www/index.html
+++ b/backup/www/index.html
@@ -5,8 +5,8 @@
银河锋锐(GVSDS)
-
-
+
+
diff --git a/gvsds/apps/core/migrations/0004_add_default_role_uuid.py b/gvsds/apps/core/migrations/0004_add_default_role_uuid.py
new file mode 100644
index 00000000..f6ebab50
--- /dev/null
+++ b/gvsds/apps/core/migrations/0004_add_default_role_uuid.py
@@ -0,0 +1,18 @@
+from django.db import migrations
+
+import gvsds.apps.core.models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('core', '0003_remove_ephemeraltoken'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='user',
+ name='DefaultRoleUUID',
+ field=gvsds.apps.core.models.UUIDField(blank=True, null=True, verbose_name='默认角色UUID'),
+ ),
+ ]
\ No newline at end of file
diff --git a/gvsds/apps/core/models.py b/gvsds/apps/core/models.py
index 1d979d08..5c192517 100644
--- a/gvsds/apps/core/models.py
+++ b/gvsds/apps/core/models.py
@@ -137,6 +137,8 @@ class User(QModel):
UserLastLoginDate = models.DateTimeField(default=datetime.datetime.utcnow, verbose_name='最后登录')
IsStaff = models.BooleanField(default=False, verbose_name='是否员工')
IsSuperuser = models.BooleanField(default=False, verbose_name='是否超级用户')
+ # 默认登录角色:登录/注册后自动激活的角色(空 = 取用户首个角色)
+ DefaultRoleUUID = UUIDField(null=True, blank=True, verbose_name='默认角色UUID')
objects = UserManager()
diff --git a/gvsds/apps/ugm/serializers.py b/gvsds/apps/ugm/serializers.py
index 41c9bc18..cf5304fe 100644
--- a/gvsds/apps/ugm/serializers.py
+++ b/gvsds/apps/ugm/serializers.py
@@ -33,6 +33,10 @@ class SwitchRoleSerializer(PascalCaseSerializer):
RoleUUID = serializers.CharField()
+class SetDefaultRoleSerializer(PascalCaseSerializer):
+ RoleUUID = serializers.CharField(required=False, allow_blank=True, default='')
+
+
class ModifyPasswordSerializer(PascalCaseSerializer):
OldPassword = serializers.CharField(max_length=256, required=False)
NewPassword = serializers.CharField(max_length=256, required=False)
diff --git a/gvsds/apps/ugm/urls.py b/gvsds/apps/ugm/urls.py
index 0510c92e..b76d0be5 100644
--- a/gvsds/apps/ugm/urls.py
+++ b/gvsds/apps/ugm/urls.py
@@ -6,6 +6,7 @@ urlpatterns = [
path('register/', views.RegisterView.as_view(), name='register'),
path('verify-2fa/', views.Verify2FAView.as_view(), name='verify_2fa'),
path('switch-role/', views.SwitchRoleView.as_view(), name='switch_role'),
+ path('set-default-role/', views.SetDefaultRoleView.as_view(), name='set_default_role'),
path('user-roles/', views.GetUserRolesView.as_view(), name='user_roles'),
path('user-info/', views.GetUserInfoView.as_view(), name='user_info'),
path('user-avatar/', views.GetUserAvatarView.as_view(), name='user_avatar'),
diff --git a/gvsds/apps/ugm/views.py b/gvsds/apps/ugm/views.py
index 6e3c0909..89c5503a 100644
--- a/gvsds/apps/ugm/views.py
+++ b/gvsds/apps/ugm/views.py
@@ -14,7 +14,7 @@ from gvsdsdk.model_utils import UUIDObj
from gvsds.app_config import getlist as _app_getlist
from .serializers import (
LoginSerializer, RegisterSerializer, Verify2FASerializer,
- SwitchRoleSerializer, ModifyPasswordSerializer,
+ SwitchRoleSerializer, ModifyPasswordSerializer, SetDefaultRoleSerializer,
)
_ALLOWED_DOMAINS = set(_app_getlist('domain', 'KNOWN_DOMAINS', fallback=[
@@ -82,13 +82,22 @@ def _ClearJwtCookies(response):
def _SetCurrentRoleCookie(response, user):
- """查询用户首个角色并设置 CurrentRoleUUID cookie"""
+ """设置 CurrentRoleUUID cookie:优先用户默认角色(DefaultRoleUUID,须持有且启用),否则取首个角色"""
from gvsdsdk.auth.managers import RoleManager
- first_role = RoleManager.GetRolesForUser(user.UserUUID).first()
- if first_role and first_role.RoleUUID:
+ role_uuid = ''
+ default_uuid = getattr(user, 'DefaultRoleUUID', None)
+ if default_uuid:
+ role = RoleManager.GetRoleByUUID(default_uuid)
+ if role and role.RoleStatus == 1 and RoleManager.HasRole(user.UserUUID, default_uuid):
+ role_uuid = UUIDObj(default_uuid).str
+ if not role_uuid:
+ first_role = RoleManager.GetRolesForUser(user.UserUUID).first()
+ if first_role and first_role.RoleUUID:
+ role_uuid = UUIDObj(first_role.RoleUUID).str
+ if role_uuid:
max_age = int(settings.SIMPLE_JWT['REFRESH_TOKEN_LIFETIME'].total_seconds())
response.set_cookie(
- 'CurrentRoleUUID', UUIDObj(first_role.RoleUUID).str,
+ 'CurrentRoleUUID', role_uuid,
domain=settings.SESSION_COOKIE_DOMAIN, max_age=max_age,
secure=True, httponly=False, samesite='None',
)
@@ -273,6 +282,22 @@ class SwitchRoleView(APIView):
return response
+class SetDefaultRoleView(APIView):
+ permission_classes = [IsAuthenticated]
+
+ def post(self, request):
+ data = request.data.copy()
+ serializer = SetDefaultRoleSerializer(data=data)
+ serializer.IsValid(raise_exception=True)
+ role_uuid = serializer.ValidatedData['RoleUUID'].strip()
+ from gvsdsdk.auth.managers import RoleManager
+ if role_uuid and not RoleManager.HasRole(request.user.UserUUID, role_uuid):
+ return Response({'code': 1, 'msg': '无权设置该角色为默认'}, status=403)
+ request.user.DefaultRoleUUID = UUIDObj(role_uuid).bytes if role_uuid else None
+ request.user.save(update_fields=['DefaultRoleUUID'])
+ return Response({'code': 0, 'msg': '默认登录角色已更新'})
+
+
class GetUserRolesView(APIView):
permission_classes = [IsAuthenticated]
@@ -281,6 +306,8 @@ class GetUserRolesView(APIView):
# 角色不绑定公司/部门,通过 UserRole.CompanyUUID 获取关联公司
user_roles = RoleManager.GetUserRoleDetails(request.user.UserUUID)
current_role_uuid = request.COOKIES.get('CurrentRoleUUID', '')
+ default_uuid = getattr(request.user, 'DefaultRoleUUID', None)
+ default_role_uuid = UUIDObj(default_uuid).str if default_uuid else ''
roles = []
for ur in user_roles:
# 两步查询:UserRole.RoleUUID 是 UUIDField,需先查 Role 表
@@ -309,6 +336,7 @@ class GetUserRolesView(APIView):
'CompanyShort': company_short,
'CompanyUUID': company_uuid_str,
'active': UUIDObj(role.RoleUUID).str == current_role_uuid,
+ 'IsDefault': UUIDObj(role.RoleUUID).str == default_role_uuid,
})
return Response({'code': 0, 'data': {'roles': roles}})