Skip to content

Commit 2a00d3c

Browse files
committed
feat: Improve workspace resource authorization
1 parent f7a4aca commit 2a00d3c

File tree

5 files changed

+270
-48
lines changed

5 files changed

+270
-48
lines changed

apps/common/auth/authenticate.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def authenticate(self, request):
8888
return handle.handle(request, token, token_details.get_token_details)
8989
raise AppAuthenticationFailed(1002, _('Authentication information is incorrect! illegal user'))
9090
except Exception as e:
91-
traceback.format_exc()
91+
traceback.print_stack()
9292
if isinstance(e, AppEmbedIdentityFailed) or isinstance(e, AppChatNumOutOfBoundsFailed) or isinstance(e,
9393
AppApiException):
9494
raise e

apps/common/auth/handle/impl/user_token.py

+120-36
Original file line numberDiff line numberDiff line change
@@ -8,44 +8,116 @@
88
"""
99
import datetime
1010
from functools import reduce
11+
from typing import List
1112

1213
from django.core.cache import cache
1314
from django.db.models import QuerySet
1415
from django.utils.translation import gettext_lazy as _
1516

1617
from common.auth.handle.auth_base_handle import AuthBaseHandle
1718
from common.constants.cache_version import Cache_Version
18-
from common.constants.permission_constants import Auth, RoleConstants, get_default_permission_list_by_role, \
19-
PermissionConstants
19+
from common.constants.permission_constants import Auth, PermissionConstants, ResourcePermissionGroup, \
20+
get_permission_list_by_resource_group, ResourceAuthType, \
21+
ResourcePermissionRole, get_default_role_permission_mapping_list, get_default_workspace_user_role_mapping_list
2022
from common.database_model_manage.database_model_manage import DatabaseModelManage
2123
from common.exception.app_exception import AppAuthenticationFailed
2224
from common.utils.common import group_by
23-
from system_manage.models.workspace_user_permission import WorkspaceUserPermission
25+
from system_manage.models.workspace_user_permission import WorkspaceUserResourcePermission
2426
from users.models import User
2527

2628

2729
def get_permission(permission_id):
30+
"""
31+
获取权限字符串
32+
@param permission_id: 权限id
33+
@return: 权限字符串
34+
"""
2835
if isinstance(permission_id, PermissionConstants):
2936
permission_id = permission_id.value
3037
return f"{permission_id}"
3138

3239

3340
def get_workspace_permission(permission_id, workspace_id):
41+
"""
42+
获取工作空间权限字符串
43+
@param permission_id: 权限id
44+
@param workspace_id: 工作空间id
45+
@return:
46+
"""
3447
if isinstance(permission_id, PermissionConstants):
3548
permission_id = permission_id.value
3649
return f"{permission_id}:/WORKSPACE/{workspace_id}"
3750

3851

39-
def get_workspace_resource_permission_list(permission_id, workspace_id, workspace_user_permission_dict):
40-
workspace_user_permission_list = workspace_user_permission_dict.get(workspace_id)
41-
if workspace_user_permission_list is None:
52+
def get_workspace_permission_list(role_permission_mapping_dict, workspace_user_role_mapping_list):
53+
"""
54+
获取工作空间下所有的权限
55+
@param role_permission_mapping_dict: 角色权限关联字典
56+
@param workspace_user_role_mapping_list: 工作空间用户角色关联列表
57+
@return: 工作空间下的权限
58+
"""
59+
workspace_permission_list = [
60+
[get_workspace_permission(role_permission_mapping.permission_id, w_u_r.workspace_id) for role_permission_mapping
61+
in
62+
role_permission_mapping_dict.get(w_u_r.role_id, [])] for w_u_r in workspace_user_role_mapping_list]
63+
return reduce(lambda x, y: [*x, *y], workspace_permission_list, [])
64+
65+
66+
def get_workspace_resource_permission_list(
67+
workspace_user_resource_permission_list: List[WorkspaceUserResourcePermission],
68+
role_permission_mapping_dict,
69+
workspace_user_role_mapping_dict):
70+
"""
71+
72+
@param workspace_user_resource_permission_list: 工作空间用户资源权限列表
73+
@param role_permission_mapping_dict: 角色权限关联字典 key为role_id
74+
@param workspace_user_role_mapping_dict: 工作空间用户角色映射字典 key为role_id
75+
@return: 工作空间资源权限列表
76+
"""
77+
resource_permission_list = [
78+
get_workspace_resource_permission_list_by_workspace_user_permission(workspace_user_resource_permission,
79+
role_permission_mapping_dict,
80+
workspace_user_role_mapping_dict) for
81+
workspace_user_resource_permission in workspace_user_resource_permission_list]
82+
# 将二维数组扁平为一维
83+
return reduce(lambda x, y: [*x, *y], resource_permission_list, [])
84+
85+
86+
def get_workspace_resource_permission_list_by_workspace_user_permission(
87+
workspace_user_resource_permission: WorkspaceUserResourcePermission,
88+
role_permission_mapping_dict,
89+
workspace_user_role_mapping_dict):
90+
"""
91+
92+
@param workspace_user_resource_permission: 工作空间用户资源权限对象
93+
@param role_permission_mapping_dict: 角色权限关联字典 key为role_id
94+
@param workspace_user_role_mapping_dict: 工作空间用户角色关联字典 key为role_id
95+
@return: 工作空间用户资源的权限列表
96+
"""
97+
98+
role_permission_mapping_list = [role_permission_mapping_dict.get(workspace_user_role_mapping.role_id) for
99+
workspace_user_role_mapping in
100+
workspace_user_role_mapping_dict.get(
101+
workspace_user_resource_permission.workspace_id)]
102+
role_permission_mapping_list = reduce(lambda x, y: [*x, *y], role_permission_mapping_list, [])
103+
# 如果是根据角色
104+
if (workspace_user_resource_permission.auth_target_type == ResourceAuthType.ROLE
105+
and workspace_user_resource_permission.permission_list.__contains__(
106+
ResourcePermissionRole.ROLE)):
42107
return [
43-
get_workspace_permission(permission_id, workspace_id), get_permission(permission_id)]
44-
return [
45-
f"{permission_id}:/WORKSPACE/{workspace_id}/{workspace_user_permission.auth_target_type}/{workspace_user_permission.target}"
46-
for workspace_user_permission in
47-
workspace_user_permission_list if workspace_user_permission.is_auth] + [
48-
get_workspace_permission(permission_id, workspace_id), get_permission(permission_id)]
108+
f"{role_permission_mapping.permission_id}:/WORKSPACE/{workspace_user_resource_permission.workspace_id}/{workspace_user_resource_permission.auth_target_type}/{workspace_user_resource_permission.target}"
109+
for role_permission_mapping in role_permission_mapping_list]
110+
111+
elif workspace_user_resource_permission.auth_target_type == ResourceAuthType.RESOURCE_PERMISSION_GROUP:
112+
resource_permission_list = [
113+
[
114+
f"{permission}:/WORKSPACE/{workspace_user_resource_permission.workspace_id}/{workspace_user_resource_permission.auth_target_type}/{workspace_user_resource_permission.target}"
115+
for permission in get_permission_list_by_resource_group(ResourcePermissionGroup[resource_permission])]
116+
for resource_permission in workspace_user_resource_permission.permission_list if
117+
ResourcePermissionGroup.values.__contains__(resource_permission)]
118+
# 将二维数组扁平为一维
119+
return reduce(lambda x, y: [*x, *y], resource_permission_list, [])
120+
return []
49121

50122

51123
def get_permission_list(user,
@@ -63,41 +135,53 @@ def get_permission_list(user,
63135
if is_query_model:
64136
# 获取工作空间 用户 角色映射数据
65137
workspace_user_role_mapping_list = QuerySet(workspace_user_role_mapping_model).filter(user_id=user_id)
138+
workspace_user_role_mapping_dict = group_by(workspace_user_role_mapping_list,
139+
lambda item: item.role_id)
66140
# 获取角色权限映射数据
67141
role_permission_mapping_list = QuerySet(role_permission_mapping_model).filter(
68142
role_id__in=[workspace_user_role_mapping.role_id for workspace_user_role_mapping in
69143
workspace_user_role_mapping_list])
70-
role_dict = group_by(role_permission_mapping_list, lambda item: item.get('role_id'))
144+
role_permission_mapping_dict = group_by(role_permission_mapping_list, lambda item: item.role_id)
71145

72-
workspace_user_permission_list = QuerySet(WorkspaceUserPermission).filter(
146+
workspace_user_permission_list = QuerySet(WorkspaceUserResourcePermission).filter(
73147
workspace_id__in=[workspace_user_role.workspace_id for workspace_user_role in
74148
workspace_user_role_mapping_list])
75-
workspace_user_permission_dict = group_by(workspace_user_permission_list,
76-
key=lambda item: item.workspace_id)
77-
permission_list = [
78-
get_workspace_resource_permission_list(role_permission_mapping.permission_id,
79-
role_dict.get(role_permission_mapping.role_id).workspace_id,
80-
workspace_user_permission_dict)
81-
for role_permission_mapping in
82-
role_permission_mapping_list]
83-
84-
# 将二维数组扁平为一维
85-
permission_list = reduce(lambda x, y: [*x, *y], permission_list, [])
149+
150+
# 资源权限
151+
workspace_resource_permission_list = get_workspace_resource_permission_list(workspace_user_permission_list,
152+
role_permission_mapping_dict,
153+
workspace_user_role_mapping_dict)
154+
155+
workspace_permission_list = get_workspace_permission_list(role_permission_mapping_dict,
156+
workspace_user_role_mapping_list)
157+
# 系统权限
158+
system_permission_list = [role_permission_mapping.permission_id for role_permission_mapping in
159+
role_permission_mapping_list]
160+
# 合并权限
161+
permission_list = system_permission_list + workspace_permission_list + workspace_resource_permission_list
86162
cache.set(key, permission_list, version=version)
87163
else:
88164
workspace_id_list = ['default']
89-
workspace_user_permission_list = QuerySet(WorkspaceUserPermission).filter(
165+
workspace_user_resource_permission_list = QuerySet(WorkspaceUserResourcePermission).filter(
90166
workspace_id__in=workspace_id_list)
91-
92-
workspace_user_permission_dict = group_by(workspace_user_permission_list,
93-
key=lambda item: item.workspace_id)
94-
permission_list = get_default_permission_list_by_role(RoleConstants[user.role])
95-
permission_list = [
96-
get_workspace_resource_permission_list(permission, 'default', workspace_user_permission_dict) for
97-
permission
98-
in permission_list]
99-
# 将二维数组扁平为一维
100-
permission_list = reduce(lambda x, y: [*x, *y], permission_list, [])
167+
role_permission_mapping_list = get_default_role_permission_mapping_list()
168+
role_permission_mapping_dict = group_by(role_permission_mapping_list, lambda item: item.role_id)
169+
workspace_user_role_mapping_list = get_default_workspace_user_role_mapping_list([user.role])
170+
workspace_user_role_mapping_dict = group_by(workspace_user_role_mapping_list,
171+
lambda item: item.role_id)
172+
# 资源权限
173+
workspace_resource_permission_list = get_workspace_resource_permission_list(
174+
workspace_user_resource_permission_list,
175+
role_permission_mapping_dict,
176+
workspace_user_role_mapping_dict)
177+
178+
workspace_permission_list = get_workspace_permission_list(role_permission_mapping_dict,
179+
workspace_user_role_mapping_list)
180+
# 系统权限
181+
system_permission_list = [role_permission_mapping.permission_id for role_permission_mapping in
182+
role_permission_mapping_list]
183+
# 合并权限
184+
permission_list = system_permission_list + workspace_permission_list + workspace_resource_permission_list
101185
cache.set(key, permission_list, version=version)
102186
return permission_list
103187

apps/common/constants/permission_constants.py

+97-6
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
@desc: 权限,角色 常量
77
"""
88
from enum import Enum
9+
from functools import reduce
910
from typing import List
1011

12+
from django.db import models
13+
1114

1215
class Group(Enum):
1316
"""
@@ -45,6 +48,40 @@ class RoleGroup(Enum):
4548
CHAT_USER = "CHAT_USER"
4649

4750

51+
class ResourcePermissionRole(models.TextChoices):
52+
"""
53+
资源权限根据角色
54+
"""
55+
ROLE = "ROLE"
56+
57+
def __eq__(self, other):
58+
return str(self) == str(other)
59+
60+
61+
class ResourcePermissionGroup(models.TextChoices):
62+
"""
63+
资源权限组
64+
"""
65+
# 查看
66+
VIEW = "VIEW"
67+
# 管理
68+
MANAGE = "MANAGE"
69+
70+
def __eq__(self, other):
71+
return str(self) == str(other)
72+
73+
74+
class ResourceAuthType(models.TextChoices):
75+
"""
76+
资源授权类型
77+
"""
78+
"当授权类型是Role时候"
79+
ROLE = "ROLE"
80+
81+
"""资源权限组"""
82+
RESOURCE_PERMISSION_GROUP = "RESOURCE_PERMISSION_GROUP"
83+
84+
4885
class Role:
4986
def __init__(self, name: str, decs: str, group: RoleGroup, resource_path=None):
5087
self.name = name
@@ -78,14 +115,19 @@ class Permission:
78115
权限信息
79116
"""
80117

81-
def __init__(self, group: Group, operate: Operate, resource_path=None, role_list=None):
118+
def __init__(self, group: Group, operate: Operate, resource_path=None, role_list=None,
119+
resource_permission_group_list=None):
82120
if role_list is None:
83121
role_list = []
122+
if resource_permission_group_list is None:
123+
resource_permission_group_list = []
84124
self.group = group
85125
self.operate = operate
86126
self.resource_path = resource_path
87127
# 用于获取角色与权限的关系,只适用于没有权限管理的
88128
self.role_list = role_list
129+
# 用于资源权限权限分组
130+
self.resource_permission_group_list = resource_permission_group_list
89131

90132
@staticmethod
91133
def new_instance(permission_str: str):
@@ -149,15 +191,31 @@ class PermissionConstants(Enum):
149191
KNOWLEDGE_MODULE_CREATE = Permission(group=Group.KNOWLEDGE, operate=Operate.CREATE, role_list=[RoleConstants.ADMIN,
150192
RoleConstants.USER])
151193
KNOWLEDGE_MODULE_READ = Permission(group=Group.KNOWLEDGE, operate=Operate.READ, role_list=[RoleConstants.ADMIN,
152-
RoleConstants.USER])
194+
RoleConstants.USER],
195+
resource_permission_group_list=[
196+
ResourcePermissionGroup.VIEW
197+
])
153198
KNOWLEDGE_MODULE_EDIT = Permission(group=Group.KNOWLEDGE, operate=Operate.EDIT, role_list=[RoleConstants.ADMIN,
154-
RoleConstants.USER])
199+
RoleConstants.USER],
200+
resource_permission_group_list=[
201+
ResourcePermissionGroup.MANAGE
202+
]
203+
)
155204
KNOWLEDGE_MODULE_DELETE = Permission(group=Group.KNOWLEDGE, operate=Operate.DELETE, role_list=[RoleConstants.ADMIN,
156-
RoleConstants.USER])
205+
RoleConstants.USER],
206+
resource_permission_group_list=[
207+
ResourcePermissionGroup.MANAGE
208+
]
209+
)
157210
KNOWLEDGE_READ = Permission(group=Group.KNOWLEDGE, operate=Operate.READ, role_list=[RoleConstants.ADMIN,
158-
RoleConstants.USER])
211+
RoleConstants.USER],
212+
resource_permission_group_list=[
213+
ResourcePermissionGroup.VIEW
214+
]
215+
)
159216
KNOWLEDGE_CREATE = Permission(group=Group.KNOWLEDGE, operate=Operate.CREATE, role_list=[RoleConstants.ADMIN,
160-
RoleConstants.USER])
217+
RoleConstants.USER])
218+
161219
def get_workspace_application_permission(self):
162220
return lambda r, kwargs: Permission(group=self.value.group, operate=self.value.operate,
163221
resource_path=
@@ -191,6 +249,39 @@ def get_default_permission_list_by_role(role: RoleConstants):
191249
PermissionConstants.__members__))))
192250

193251

252+
class RolePermissionMapping:
253+
def __init__(self, role_id, permission_id):
254+
self.role_id = role_id
255+
self.permission_id = permission_id
256+
257+
258+
class WorkspaceUserRoleMapping:
259+
def __init__(self, workspace_id, role_id, user_id):
260+
self.workspace_id = workspace_id
261+
self.role_id = role_id
262+
self.user_id = user_id
263+
264+
265+
def get_default_role_permission_mapping_list():
266+
role_permission_mapping_list = [
267+
[RolePermissionMapping(role.value.name, PermissionConstants[k].value.__str__()) for role in
268+
PermissionConstants[k].value.role_list] for k in PermissionConstants.__members__]
269+
return reduce(lambda x, y: [*x, *y], role_permission_mapping_list, [])
270+
271+
272+
def get_default_workspace_user_role_mapping_list(user_role_list: list):
273+
return [WorkspaceUserRoleMapping('default', role.value.name, 'default') for role in RoleConstants if
274+
user_role_list.__contains__(role.value.name)]
275+
276+
277+
def get_permission_list_by_resource_group(resource_group: ResourcePermissionGroup):
278+
"""
279+
根据资源组获取权限
280+
"""
281+
return [PermissionConstants[k] for k in PermissionConstants.__members__ if
282+
PermissionConstants[k].value.resource_permission_group_list.__contains__(resource_group)]
283+
284+
194285
class Auth:
195286
"""
196287
用于存储当前用户的角色和权限

0 commit comments

Comments
 (0)