diff --git a/api/v1/pages/mine/grant_manage.py b/api/v1/pages/mine/grant_manage.py index 313e63b6b..e9fd3ae35 100644 --- a/api/v1/pages/mine/grant_manage.py +++ b/api/v1/pages/mine/grant_manage.py @@ -7,18 +7,20 @@ name = _("授权管理") -page = pages.TablePage( +page = pages.TreePage( name=name, tag=tag ) -permission_page = pages.TablePage( - name=_("申请权限"), - select=True, -) +app_permission_page = pages.TablePage(name=_("该应用权限")) +# permission_page = pages.TablePage( +# name=_("申请权限"), +# select=True, +# ) pages.register_front_pages(page) -pages.register_front_pages(permission_page) +pages.register_front_pages(app_permission_page) +# pages.register_front_pages(permission_page) router = routers.FrontRouter( path=tag, @@ -29,25 +31,19 @@ page.create_actions( init_action=actions.DirectAction( - path='/api/v1/mine/tenant/{tenant_id}/permissions/', + path='/api/v1/tenant/{tenant_id}/all_apps_in_arkid/', method=actions.FrontActionMethod.GET, ), - global_actions={ - 'open': actions.OpenAction( - name=("申请权限"), - page=permission_page + node_actions=[ + actions.CascadeAction( + page=app_permission_page ) - } + ] ) -permission_page.create_actions( +app_permission_page.create_actions( init_action=actions.DirectAction( - path='/api/v1/mine/tenant/{tenant_id}/all_permissions/', - method=actions.FrontActionMethod.GET, + path='/api/v1/mine/tenant/{tenant_id}/permissions/?app_id={app_id}', + method=actions.FrontActionMethod.GET ), - global_actions={ - 'confirm': actions.ConfirmAction( - path="/api/v1/mine/tenant/{tenant_id}/permissions/" - ), - } ) \ No newline at end of file diff --git a/api/v1/schema/mine.py b/api/v1/schema/mine.py index 0917a8b72..7b99aaca2 100644 --- a/api/v1/schema/mine.py +++ b/api/v1/schema/mine.py @@ -2,8 +2,9 @@ from arkid.core.schema import ResponseSchema from ninja import ModelSchema, Schema from typing import List, Optional -from arkid.core.models import App, Tenant, User +from arkid.core.models import App, Tenant, User, Permission from pydantic import Field +from arkid.core import pages,actions from arkid.core.translation import gettext_default as _ @@ -36,6 +37,21 @@ class Config: model = Tenant model_fields = ["id", "name", "slug", "icon"] +class MinePermissionListSchemaOut(Schema): + + id: UUID = Field(hidden=True) + name: str + # app_name: str = Field(default=None, alias="app.name", title=_("应用名称")) + category: str + sort_id: int = Field(hidden=True) + in_current: bool = Field(item_action={"path":"/api/v1/mine/tenant/{tenant_id}/permissions/{permission_id}/add_permisssion", "method":actions.FrontActionMethod.GET.value, "close": False}) + # is_system: bool + # is_open: bool = Field(item_action={"path":"/api/v1/tenant/{tenant_id}/permission/{id}/toggle_open", "method":actions.FrontActionMethod.POST.value}) + + # class Config: + # model = Permission + # model_fields = ['id', 'name', 'category', 'is_system'] + class MineTenantListOut(ResponseSchema): data: List[MineTenantListItemOut] diff --git a/api/v1/views/approve_action.py b/api/v1/views/approve_action.py index 2fdeb2006..59fe0d5f5 100644 --- a/api/v1/views/approve_action.py +++ b/api/v1/views/approve_action.py @@ -57,7 +57,7 @@ def create_approve_action(request, tenant_id: str, data: ApproveActionCreateIn): """创建审批动作""" extension = Extension.valid_objects.get(id=data.extension_id) action = ApproveAction.valid_objects.filter( - path=data.path, method=data.method, extension=extension, tenant=request.tenant + path=data.path, method=data.method, tenant=request.tenant ).first() if action: return ErrorDict(ErrorCode.APPROVE_ACTION_DUPLICATED) diff --git a/api/v1/views/mine.py b/api/v1/views/mine.py index dd9a53667..915bcc5f6 100644 --- a/api/v1/views/mine.py +++ b/api/v1/views/mine.py @@ -1,13 +1,14 @@ from typing import List from django.shortcuts import render from arkid.core.api import api, operation +from arkid.core.error import ErrorCode, ErrorDict from arkid.core.translation import gettext_default as _ from arkid.core.pagenation import CustomPagination from arkid.core.models import App, Tenant, ApproveRequest, User from arkid.core.constants import NORMAL_USER, TENANT_ADMIN, PLATFORM_ADMIN from ninja.pagination import paginate from django.db.models import Q -from ..schema.mine import MineAppsOut, MineLogoutOut, MineTenantListItemOut, ProfileSchemaOut, ProfileSchemaIn, MineTenantListOut +from ..schema.mine import * @api.get("/mine/tenant/{tenant_id}/apps/", tags=["我的"], response=MineAppsOut) @@ -47,25 +48,51 @@ def update_mine_profile(request, tenant_id: str, data: ProfileSchemaIn): return user -@api.get("/mine/tenant/{tenant_id}/permissions/", tags=["我的"]) +@api.get("/mine/tenant/{tenant_id}/permissions/", response=List[MinePermissionListSchemaOut], tags=["我的"]) @operation(roles=[NORMAL_USER, TENANT_ADMIN, PLATFORM_ADMIN]) -def get_mine_permissions(request, tenant_id: str): - """我的权限列表,TODO""" - return [] - - -@api.post("/mine/tenant/{tenant_id}/permissions/", tags=["我的"]) -@operation(roles=[NORMAL_USER, TENANT_ADMIN, PLATFORM_ADMIN]) -def update_mine_permissions(request, tenant_id: str): - """更新我的权限列表,TODO""" - return [] - - -@api.get("/mine/tenant/{tenant_id}/all_permissions/", tags=["我的"]) -@operation(roles=[NORMAL_USER, TENANT_ADMIN, PLATFORM_ADMIN]) -def get_mine_all_permissions(request, tenant_id: str): - """获取所有权限并附带是否已授权给我的状态""" - return [] +@paginate(CustomPagination) +def get_mine_permissions(request, tenant_id: str, app_id: str = None, app_name: str = None, category: str = None): + """我的权限列表""" + login_user = request.user + from arkid.core.perm.permission_data import PermissionData + permissiondata = PermissionData() + items = permissiondata.get_permissions_by_mine_search(tenant_id, app_id, None, None, login_user, app_name=app_name, category=category) + return items + + +# @api.get("/mine/tenant/{tenant_id}/permissions/{permission_id}/open", tags=["我的"]) +# @operation(roles=[NORMAL_USER, TENANT_ADMIN, PLATFORM_ADMIN]) +# def update_mine_permissions(request, tenant_id: str, permission_id: str, in_current: bool): +# """更新我的权限列表""" +# if in_current is False: +# return ErrorDict(ErrorCode.PERMISSION_NOT_CLOSE) +# # 需要申请更新权限列表 + +# return {'error': ErrorCode.OK.value} + + +@api.get("/mine/tenant/{tenant_id}/permissions/{permission_id}/add_permisssion", tags=['权限']) +@operation(roles=[NORMAL_USER]) +def mine_add_permission(request, tenant_id: str, permission_id: str): + ''' + 添加用户权限 + ''' + from arkid.core.event import Event, dispatch_event + from arkid.core.event import ADD_USER_MANY_PERMISSION + user = request.user + if user: + dispatch_event(Event(tag=ADD_USER_MANY_PERMISSION, tenant=request.tenant, request=request, data={ + 'user_ids': [str(user.id)], + 'tenant_id': tenant_id, + 'data_arr': [permission_id] + })) + return {'error': ErrorCode.OK.value} + +# @api.get("/mine/tenant/{tenant_id}/all_permissions/", tags=["我的"]) +# @operation(roles=[NORMAL_USER, TENANT_ADMIN, PLATFORM_ADMIN]) +# def get_mine_all_permissions(request, tenant_id: str): +# """获取所有权限并附带是否已授权给我的状态""" +# return [] from api.v1.schema.approve_request import ( diff --git a/arkid/core/approve.py b/arkid/core/approve.py index 0a661bc2a..216690ff7 100644 --- a/arkid/core/approve.py +++ b/arkid/core/approve.py @@ -2,7 +2,8 @@ from arkid.common.logger import logger from django.core.handlers.wsgi import WSGIRequest from django.urls import resolve -from arkid.core.models import ApproveRequest +from arkid.core.models import ApproveRequest, ApproveAction +from arkid.extension.models import Extension def restore_approve_request(approve_request): @@ -35,3 +36,36 @@ def create_approve_request(http_request, user, approve_action): body=http_request.body, ) return approve_request + + +def create_approve_action( + name, + path, + method, + description=None, + extension=None, + tenant=None, +): + """ + 如果tenant为None, 则为平台级别审批动作,对所有租户起作用 + """ + action = ApproveAction.valid_objects.filter( + path=path, method=method, tenant=tenant + ).first() + if action: + return action + + if not extension: + extension = Extension.valid_objects.get( + package='com.longgui.approve.system.arkid' + ) + + action = ApproveAction.valid_objects.create( + name=name, + description=description, + path=path, + method=method, + extension=extension, + tenant=tenant, + ) + return action diff --git a/arkid/core/approve_request_middleware.py b/arkid/core/approve_request_middleware.py index c4c8b9c8b..3e5a04968 100644 --- a/arkid/core/approve_request_middleware.py +++ b/arkid/core/approve_request_middleware.py @@ -37,10 +37,16 @@ def process_view(self, request, view_func, view_args, view_kwargs): path = ('/' + request.resolver_match.route).replace("<", "{").replace(">", "}") method = request.method - approve_action = ApproveAction.valid_objects.filter( tenant=tenant, path=path, method=method ).first() + if not approve_action: + approve_action = ApproveAction.valid_objects.filter( + tenant=None, + path=path, + method=method, + ).first() + if not approve_action or not approve_action.extension: return None diff --git a/arkid/core/apps.py b/arkid/core/apps.py index d125faa05..9586108ef 100644 --- a/arkid/core/apps.py +++ b/arkid/core/apps.py @@ -25,9 +25,9 @@ def ready(self): tenant.create_tenant_user_admin_permission(user) tenant.users.add(user) tenant.save() - except Exception as e: print(e) # 监听 from arkid.core import listener + from arkid.core import preset_approve_action diff --git a/arkid/core/error.py b/arkid/core/error.py index 0407c0827..771b09fc4 100644 --- a/arkid/core/error.py +++ b/arkid/core/error.py @@ -42,6 +42,7 @@ class ErrorCode(Enum): PERMISSION_EXISTS_ERROR = ('10033', _('the permission not exists', '该权限不存在')) # APP_EXISTS_ERROR = '10032' PERMISSION_NOT_EDIT = ('10033', _('the permission not edit', '该权限不允许编辑')) + PERMISSION_NOT_CLOSE = ('10033', _('the permission not edit', '该权限不允许关闭')) # PERMISSION_NOT_DELETE = ('10034', _('the permission not delete', '该权限不允许删除')) BAN_REMOVE_GROUP_PERMISSION = ('10035', _('ban remove group permission', '该分组权限或范围不允许移除')) BAN_REMOVE_GROUP_SCOPE = ('10036', _('ban remove group permission', '该分组范围不允许移除')) diff --git a/arkid/core/migrations/0017_alter_approveaction_tenant.py b/arkid/core/migrations/0017_alter_approveaction_tenant.py new file mode 100644 index 000000000..e25c4f416 --- /dev/null +++ b/arkid/core/migrations/0017_alter_approveaction_tenant.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.13 on 2022-07-14 08:26 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0016_grouppermissionresult'), + ] + + operations = [ + migrations.AlterField( + model_name='approveaction', + name='tenant', + field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='approve_action_set', related_query_name='actions', to='core.tenant', verbose_name='Tenant'), + ), + ] diff --git a/arkid/core/models.py b/arkid/core/models.py index 50f8382ad..5654e50d7 100644 --- a/arkid/core/models.py +++ b/arkid/core/models.py @@ -522,6 +522,7 @@ class Meta(object): tenant = models.ForeignKey( 'Tenant', default=None, + null=True, on_delete=models.CASCADE, verbose_name=_('Tenant', '租户'), related_name="approve_action_set", diff --git a/arkid/core/perm/permission_data.py b/arkid/core/perm/permission_data.py index b278ea141..d582ace64 100644 --- a/arkid/core/perm/permission_data.py +++ b/arkid/core/perm/permission_data.py @@ -1243,6 +1243,160 @@ def get_permissions_by_search(self, tenant_id, app_id, user_id, group_id, login_ systempermissions = systempermissions.filter(Q(tenant__isnull=True)|Q(tenant_id=tenant_id)) return list(systempermissions.all())+list(permissions.all()) + def get_permissions_by_mine_search(self, tenant_id, app_id, user_id, group_id, login_user, parent_id=None, is_only_show_group=False, app_name=None, category=None): + ''' + 根据应用,用户,分组查权限(要根据用户身份显示正确的列表) + ''' + permissions = Permission.valid_objects.filter( + Q(tenant_id=tenant_id)|Q(is_open=True), + app__is_del=False + ) + systempermissions = SystemPermission.objects.filter( + is_del=False + ) + if is_only_show_group: + permissions = permissions.filter( + category='group' + ) + systempermissions = systempermissions.filter( + category='group' + ).filter(Q(code__startswith='group_role')|Q(code__startswith='other')) + if parent_id: + systempermissions = systempermissions.filter(parent_id=parent_id) + permissions = permissions.filter(parent_id=parent_id) + else: + systempermissions = systempermissions.filter(parent_id__isnull=True) + permissions = permissions.filter(parent_id__isnull=True) + if app_id and app_id == 'arkid': + # arkid没有应用权限 + app_id = None + systempermissions = systempermissions.filter(Q(tenant_id=tenant_id)|Q(tenant_id=None)) + permissions = permissions.filter(app_id=None) + compress = Compress() + if user_id is None and group_id is None and login_user: + # 需要正确展现用户的id + user_id = str(login_user.id) + if app_name: + permissions = permissions.filter(app__name=app_name) + if category: + permissions = permissions.filter(category=category) + systempermissions = systempermissions.filter(category=category) + if app_id or user_id or group_id: + if app_id: + app = App.valid_objects.filter( + id=app_id + ).first() + tenant_uid = uuid.UUID(tenant_id) + if app and app.entry_permission: + systempermissions = systempermissions.filter(id=app.entry_permission.id) + permissions = permissions.filter(app_id=app_id) + if app.tenant.id != tenant_uid: + # 只展示为1的系统权限(这里属于开放的权限) + userpermissionresult = UserPermissionResult.valid_objects.filter( + app=None, + user=login_user, + tenant_id=tenant_id + ).first() + permission_sort_ids = [] + if userpermissionresult: + permission_result = compress.decrypt(userpermissionresult.result) + permission_result_arr = list(permission_result) + for index, item in enumerate(permission_result_arr): + if int(item) == 1: + permission_sort_ids.append(index) + if len(permission_sort_ids) == 0: + systempermissions = systempermissions.filter(id__isnull=True) + else: + systempermissions = systempermissions.filter(sort_id__in=permission_sort_ids) + # 只展示为1的应用权限 + userpermissionresult = UserPermissionResult.valid_objects.filter( + app=app, + user=login_user, + tenant_id=tenant_id + ).first() + permission_sort_ids = [] + if userpermissionresult: + permission_result = compress.decrypt(userpermissionresult.result) + permission_result_arr = list(permission_result) + for index, item in enumerate(permission_result_arr): + if int(item) == 1: + permission_sort_ids.append(index) + if len(permission_sort_ids) == 0: + permissions = permissions.filter(id__isnull=True) + else: + permissions = permissions.filter(sort_id__in=permission_sort_ids) + elif app and app.entry_permission is None: + systempermissions = systempermissions.filter(id__isnull=True) + permissions = permissions.filter(id__isnull=True) + if user_id: + # 系统权限 + userpermissionresult = UserPermissionResult.valid_objects.filter( + user_id=user_id, + tenant_id=tenant_id, + app=None + ).first() + permission_sort_ids = [] + if userpermissionresult: + permission_result = compress.decrypt(userpermissionresult.result) + permission_result_arr = list(permission_result) + for index, item in enumerate(permission_result_arr): + if int(item) == 1: + permission_sort_ids.append(index) + # if len(permission_sort_ids) == 0: + # systempermissions = systempermissions.filter(id__isnull=True) + # else: + # systempermissions = systempermissions.filter(sort_id__in=permission_sort_ids) + for systempermission in systempermissions: + sort_id = systempermission.sort_id + if sort_id in permission_sort_ids: + systempermission.in_current = True + else: + systempermission.in_current = False + # 应用权限 + userpermissionresults = UserPermissionResult.valid_objects.filter( + user_id=user_id, + tenant_id=tenant_id, + app__isnull=False + ) + flag = True + for userpermissionresult in userpermissionresults: + permission_sort_ids = [] + if userpermissionresult: + permission_result = compress.decrypt(userpermissionresult.result) + permission_result_arr = list(permission_result) + for index, item in enumerate(permission_result_arr): + if int(item) == 1: + permission_sort_ids.append(index) + if permission_sort_ids: + flag = False + # permissions = permissions.filter(sort_id__in=permission_sort_ids) + for permission in permissions: + sort_id = permission.sort_id + if sort_id in permission_sort_ids: + permission.in_current = True + else: + permission.in_current = False + if flag: + for permission in permissions: + sort_id = permission.sort_id + if sort_id in permission_sort_ids: + permission.in_current = True + else: + permission.in_current = False + if group_id: + usergroup = UserGroup.valid_objects.filter(id=group_id).first() + if usergroup: + group_permission = usergroup.permission + if group_permission is None: + systempermissions = systempermissions.filter(id__isnull=True) + else: + systempermissions = systempermissions.filter(id=group_permission.id) + # 没有应用分组,只有系统分组 + permissions = permissions.filter(id__isnull=True) + else: + systempermissions = systempermissions.filter(Q(tenant__isnull=True)|Q(tenant_id=tenant_id)) + return list(systempermissions)+list(permissions) + def get_permissions_by_childmanager(self, tenant_id, login_user, only_show_group, user_id=None): ''' 子管理员可选择的权限(要根据用户身份显示正确的列表) diff --git a/arkid/core/preset_approve_action.py b/arkid/core/preset_approve_action.py new file mode 100644 index 000000000..e3a3c433a --- /dev/null +++ b/arkid/core/preset_approve_action.py @@ -0,0 +1,3 @@ +from arkid.core.approve import create_approve_action + +create_approve_action('添加用户权限', '/api/v1/mine/tenant/{tenant_id}/permissions/{permission_id}/add_permisssion', 'GET') \ No newline at end of file