diff --git a/apps/application/serializers/application.py b/apps/application/serializers/application.py index 80eecae8a..ff43ecbb4 100644 --- a/apps/application/serializers/application.py +++ b/apps/application/serializers/application.py @@ -34,7 +34,7 @@ from common.database_model_manage.database_model_manage import DatabaseModelMana from common.db.search import native_search, native_page_search from common.exception.app_exception import AppApiException from common.field.common import UploadedFileField -from common.utils.common import get_file_content, valid_license, restricted_loads, generate_uuid +from common.utils.common import get_file_content, restricted_loads, generate_uuid from knowledge.models import Knowledge, KnowledgeScope from knowledge.serializers.knowledge import KnowledgeSerializer, KnowledgeModelSerializer from maxkb.conf import PROJECT_DIR @@ -377,6 +377,7 @@ class Query(serializers.Serializer): class ApplicationImportRequest(serializers.Serializer): file = UploadedFileField(required=True, label=_("file")) + folder_id = serializers.CharField(required=True, label=_("Folder ID")) class ApplicationEditSerializer(serializers.Serializer): @@ -478,16 +479,14 @@ class ApplicationSerializer(serializers.Serializer): QuerySet(ApplicationKnowledgeMapping).bulk_create(application_knowledge_mapping_model_list) return ApplicationCreateSerializer.ApplicationResponse(application_model).data - @valid_license(model=Application, count=5, - message=_( - 'The community version supports up to 5 applications. If you need more applications, please contact us (https://fit2cloud.com/).')) @transaction.atomic - def import_(self, instance: dict, with_valid=True): + def import_(self, instance: dict, is_import_tool, with_valid=True): if with_valid: self.is_valid() ApplicationImportRequest(data=instance).is_valid(raise_exception=True) user_id = self.data.get('user_id') workspace_id = self.data.get("workspace_id") + folder_id = instance.get('folder_id') mk_instance_bytes = instance.get('file').read() try: mk_instance = restricted_loads(mk_instance_bytes) @@ -498,7 +497,7 @@ class ApplicationSerializer(serializers.Serializer): update_tool_map = {} if len(tool_list) > 0: tool_id_list = reduce(lambda x, y: [*x, *y], - [[tool.get('id'), generate_uuid((tool.get('id') + tool.get('workspace_id') or ''))] + [[tool.get('id'), generate_uuid((tool.get('id') + workspace_id or ''))] for tool in tool_list], []) @@ -506,7 +505,7 @@ class ApplicationSerializer(serializers.Serializer): exits_tool_id_list = [str(tool.id) for tool in QuerySet(Tool).filter(id__in=tool_id_list, workspace_id=workspace_id)] # 需要更新的工具集合 - update_tool_map = {tool.get('id'): generate_uuid((tool.get('id') + tool.get('workspace_id') or '')) for tool + update_tool_map = {tool.get('id'): generate_uuid((tool.get('id') + workspace_id or '')) for tool in tool_list if not exits_tool_id_list.__contains__( @@ -515,8 +514,8 @@ class ApplicationSerializer(serializers.Serializer): tool_list = [{**tool, 'id': update_tool_map.get(tool.get('id'))} for tool in tool_list if not exits_tool_id_list.__contains__( tool.get('id')) and not exits_tool_id_list.__contains__( - generate_uuid((tool.get('id') + tool.get('workspace_id') or '')))] - application_model = self.to_application(application, workspace_id, user_id, update_tool_map) + generate_uuid((tool.get('id') + workspace_id or '')))] + application_model = self.to_application(application, workspace_id, user_id, update_tool_map, folder_id) tool_model_list = [self.to_tool(f, workspace_id, user_id) for f in tool_list] application_model.save() # 插入授权数据 @@ -528,7 +527,14 @@ class ApplicationSerializer(serializers.Serializer): # 插入认证信息 ApplicationAccessToken(application_id=application_model.id, access_token=hashlib.md5(str(uuid.uuid7()).encode()).hexdigest()[8:24]).save() - QuerySet(Tool).bulk_create(tool_model_list) if len(tool_model_list) > 0 else None + if is_import_tool: + if len(tool_model_list) > 0: + QuerySet(Tool).bulk_create(tool_model_list) + UserResourcePermissionSerializer(data={ + 'workspace_id': self.data.get('workspace_id'), + 'user_id': self.data.get('user_id'), + 'auth_target_type': AuthTargetType.APPLICATION.value + }).auth_resource_batch([t.id for t in tool_model_list]) return True @staticmethod @@ -550,7 +556,7 @@ class ApplicationSerializer(serializers.Serializer): workspace_id=workspace_id) @staticmethod - def to_application(application, workspace_id, user_id, update_tool_map): + def to_application(application, workspace_id, user_id, update_tool_map, folder_id): work_flow = application.get('work_flow') for node in work_flow.get('nodes', []): if node.get('type') == 'tool-lib-node': @@ -563,7 +569,7 @@ class ApplicationSerializer(serializers.Serializer): user_id=user_id, name=application.get('name'), workspace_id=workspace_id, - folder_id=workspace_id, + folder_id=folder_id, desc=application.get('desc'), prologue=application.get('prologue'), dialogue_number=application.get('dialogue_number'), knowledge_setting=application.get('knowledge_setting'), diff --git a/apps/application/urls.py b/apps/application/urls.py index 0a4e44d9b..6b9f58b37 100644 --- a/apps/application/urls.py +++ b/apps/application/urls.py @@ -7,7 +7,7 @@ app_name = 'application' urlpatterns = [ path('workspace//application', views.ApplicationAPI.as_view(), name='application'), - path('workspace//application/import', views.ApplicationAPI.Import.as_view()), + path('workspace//application/folder//import', views.ApplicationAPI.Import.as_view()), path('workspace//application//', views.ApplicationAPI.Page.as_view(), name='application_page'), path('workspace//application/', views.ApplicationAPI.Operate.as_view()), path('workspace//application//publish', views.ApplicationAPI.Publish.as_view()), diff --git a/apps/application/views/application.py b/apps/application/views/application.py index 80f23e613..66560b916 100644 --- a/apps/application/views/application.py +++ b/apps/application/views/application.py @@ -21,7 +21,7 @@ from application.models import Application from application.serializers.application import ApplicationSerializer, Query, ApplicationOperateSerializer from common import result from common.auth import TokenAuth -from common.auth.authentication import has_permissions +from common.auth.authentication import has_permissions, get_is_permissions from common.constants.permission_constants import PermissionConstants, RoleConstants, ViewPermission, CompareConstants from common.log.log import log @@ -112,10 +112,15 @@ class ApplicationAPI(APIView): RoleConstants.USER.get_workspace_role(), RoleConstants.WORKSPACE_MANAGE.get_workspace_role()) @log(menu='Application', operate="Import Application", ) - def post(self, request: Request, workspace_id: str): + def post(self, request: Request, workspace_id: str, folder_id: str): + is_import_tool = get_is_permissions(request, workspace_id=workspace_id, folder_id=folder_id)( + PermissionConstants.TOOL_IMPORT.get_workspace_permission(), + PermissionConstants.TOOL_IMPORT.get_workspace_permission_workspace_manage_role(), + RoleConstants.WORKSPACE_MANAGE.get_workspace_role(), RoleConstants.USER.get_workspace_role() + ) return result.success(ApplicationSerializer( data={'user_id': request.user.id, 'workspace_id': workspace_id, - }).import_({'file': request.FILES.get('file')})) + }).import_({'file': request.FILES.get('file'), 'folder_id': folder_id}, is_import_tool)) class Export(APIView): authentication_classes = [TokenAuth] diff --git a/apps/common/auth/authentication.py b/apps/common/auth/authentication.py index 36e368c94..b1c45092f 100644 --- a/apps/common/auth/authentication.py +++ b/apps/common/auth/authentication.py @@ -49,10 +49,10 @@ def exist_permissions_by_view_permission(user_role: List[RoleConstants], :return: 是否存在 True False """ - role_list = [user_r(request, kwargs) if callable(user_r) else user_r for user_r in - permission.roleList] + role_list = [user_r(request, kwargs) if callable(user_r) else user_r for user_r in + permission.roleList] role_ok = any(list(map(lambda up: role_list.__contains__(up), - user_role))) + user_role))) permission_list = [user_p(request, kwargs) if callable(user_p) else user_p for user_p in permission.permissionList ] @@ -79,10 +79,20 @@ def exist_permissions(user_role: List[RoleConstants], user_permission: List[Perm def exist(user_role: List[RoleConstants], user_permission: List[PermissionConstants], permission, request, **kwargs): if callable(permission): p = permission(request, kwargs) - return exist_permissions(user_role, user_permission, p, request,**kwargs) + return exist_permissions(user_role, user_permission, p, request, **kwargs) return exist_permissions(user_role, user_permission, permission, request, **kwargs) +def get_is_permissions(request, **kwargs): + def is_permissions(*permission, compare=CompareConstants.OR): + exit_list = list( + map(lambda p: exist(request.auth.role_list, request.auth.permission_list, p, request, **kwargs), + permission)) + return any(exit_list) if compare == CompareConstants.OR else all(exit_list) + + return is_permissions + + def has_permissions(*permission, compare=CompareConstants.OR): """ 权限 role or permission diff --git a/apps/system_manage/serializers/user_resource_permission.py b/apps/system_manage/serializers/user_resource_permission.py index b22b41f21..8fe6c28f5 100644 --- a/apps/system_manage/serializers/user_resource_permission.py +++ b/apps/system_manage/serializers/user_resource_permission.py @@ -130,6 +130,32 @@ class UserResourcePermissionSerializer(serializers.Serializer): else: return wurp.permission_list.__contains__(ResourcePermission.VIEW.value) + def auth_resource_batch(self, resource_id_list: list): + self.is_valid(raise_exception=True) + auth_target_type = self.data.get('auth_target_type') + workspace_id = self.data.get('workspace_id') + user_id = self.data.get('user_id') + wurp = QuerySet(WorkspaceUserResourcePermission).filter(auth_target_type=auth_target_type, + workspace_id=workspace_id, user_id=user_id).first() + auth_type = wurp.auth_type if wurp else ( + ResourceAuthType.RESOURCE_PERMISSION_GROUP if edition == 'CE' else ResourceAuthType.ROLE) + workspace_user_resource_permission = [WorkspaceUserResourcePermission( + target=resource_id, + auth_target_type=auth_target_type, + permission_list=[ResourcePermission.VIEW, + ResourcePermission.MANAGE] if auth_type == ResourceAuthType.RESOURCE_PERMISSION_GROUP else [ + ResourcePermissionRole.ROLE], + workspace_id=workspace_id, + user_id=user_id, + auth_type=auth_type + ) for resource_id in resource_id_list] + QuerySet(WorkspaceUserResourcePermission).bulk_create(workspace_user_resource_permission) + # 刷新缓存 + version = Cache_Version.PERMISSION_LIST.get_version() + key = Cache_Version.PERMISSION_LIST.get_key(user_id=user_id) + cache.delete(key, version=version) + return True + def auth_resource(self, resource_id: str): self.is_valid(raise_exception=True) auth_target_type = self.data.get('auth_target_type') diff --git a/ui/src/api/application/application.ts b/ui/src/api/application/application.ts index 583f1c721..0183dce16 100644 --- a/ui/src/api/application/application.ts +++ b/ui/src/api/application/application.ts @@ -140,7 +140,6 @@ const putXpackAccessToken: ( return put(`${prefix.value}/${application_id}/setting`, data, undefined, loading) } - /** * 导出应用 */ @@ -161,11 +160,12 @@ const exportApplication = ( /** * 导入应用 */ -const importApplication: (data: any, loading?: Ref) => Promise> = ( - data, - loading, -) => { - return post(`${prefix.value}/import`, data, undefined, loading) +const importApplication: ( + folder_id: string, + data: any, + loading?: Ref, +) => Promise> = (folder_id, data, loading) => { + return post(`${prefix.value}/folder/${folder_id}/import`, data, undefined, loading) } /** diff --git a/ui/src/views/application/index.vue b/ui/src/views/application/index.vue index 59a8731b5..edd27c3c3 100644 --- a/ui/src/views/application/index.vue +++ b/ui/src/views/application/index.vue @@ -13,7 +13,7 @@