Skip to content

Commit 345e588

Browse files
authored
feat: application list (#3160)
1 parent 743b04a commit 345e588

File tree

7 files changed

+273
-8
lines changed

7 files changed

+273
-8
lines changed

apps/application/api/application_api.py

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
from drf_spectacular.utils import OpenApiParameter
1212
from rest_framework import serializers
1313

14-
from application.serializers.application import ApplicationCreateSerializer
14+
from application.serializers.application import ApplicationCreateSerializer, ApplicationListResponse, \
15+
ApplicationQueryRequest
1516
from common.mixins.api_mixin import APIMixin
16-
from common.result import ResultSerializer
17+
from common.result import ResultSerializer, ResultPageSerializer
1718

1819

1920
class ApplicationCreateRequest(ApplicationCreateSerializer.SimplateRequest):
@@ -25,6 +26,80 @@ def get_data(self):
2526
return ApplicationCreateSerializer.ApplicationResponse()
2627

2728

29+
class ApplicationListResult(ResultSerializer):
30+
def get_data(self):
31+
return ApplicationListResponse(many=True)
32+
33+
34+
class ApplicationPageResult(ResultPageSerializer):
35+
def get_data(self):
36+
return ApplicationListResponse(many=True)
37+
38+
39+
class ApplicationQueryAPI(APIMixin):
40+
@staticmethod
41+
def get_parameters():
42+
return [
43+
OpenApiParameter(
44+
name="workspace_id",
45+
description="工作空间id",
46+
type=OpenApiTypes.STR,
47+
location='path',
48+
required=True,
49+
),
50+
OpenApiParameter(
51+
name="current_page",
52+
description=_("Current page"),
53+
type=OpenApiTypes.INT,
54+
location='path',
55+
required=True,
56+
),
57+
OpenApiParameter(
58+
name="page_size",
59+
description=_("Page size"),
60+
type=OpenApiTypes.INT,
61+
location='path',
62+
required=True,
63+
),
64+
OpenApiParameter(
65+
name="folder_id",
66+
description=_("folder id"),
67+
type=OpenApiTypes.STR,
68+
location='query',
69+
required=False,
70+
),
71+
OpenApiParameter(
72+
name="name",
73+
description=_("Application Name"),
74+
type=OpenApiTypes.STR,
75+
location='query',
76+
required=False,
77+
),
78+
OpenApiParameter(
79+
name="desc",
80+
description=_("Application Description"),
81+
type=OpenApiTypes.STR,
82+
location='query',
83+
required=False,
84+
),
85+
OpenApiParameter(
86+
name="user_id",
87+
description=_("User ID"),
88+
type=OpenApiTypes.STR,
89+
location='query',
90+
required=False,
91+
)
92+
]
93+
94+
@staticmethod
95+
def get_response():
96+
return ApplicationListResult
97+
98+
@staticmethod
99+
def get_page_response():
100+
return ApplicationPageResult
101+
102+
28103
class ApplicationCreateAPI(APIMixin):
29104
@staticmethod
30105
def get_parameters():

apps/application/serializers/application.py

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
@desc:
88
"""
99
import hashlib
10+
import os
1011
import re
1112
from typing import Dict
1213

@@ -17,10 +18,15 @@
1718
from django.utils.translation import gettext_lazy as _
1819
from rest_framework import serializers
1920

20-
from application.models.application import Application, ApplicationTypeChoices, ApplicationKnowledgeMapping
21+
from application.models.application import Application, ApplicationTypeChoices, ApplicationKnowledgeMapping, \
22+
ApplicationFolder
2123
from application.models.application_access_token import ApplicationAccessToken
24+
from common.database_model_manage.database_model_manage import DatabaseModelManage
25+
from common.db.search import native_search, native_page_search
2226
from common.exception.app_exception import AppApiException
27+
from common.utils.common import get_file_content
2328
from knowledge.models import Knowledge
29+
from maxkb.conf import PROJECT_DIR
2430
from models_provider.models import Model
2531

2632

@@ -227,11 +233,85 @@ def to_application_model(user_id: str, application: Dict):
227233
)
228234

229235

236+
class ApplicationQueryRequest(serializers.Serializer):
237+
folder_id = serializers.CharField(required=False, label=_("folder id"))
238+
name = serializers.CharField(required=False, label=_('Application Name'))
239+
desc = serializers.CharField(required=False, label=_("Application Description"))
240+
user_id = serializers.UUIDField(required=False, label=_("User ID"))
241+
242+
243+
class ApplicationListResponse(serializers.Serializer):
244+
id = serializers.CharField(required=True, label=_("Primary key id"), help_text=_("Primary key id"))
245+
name = serializers.CharField(required=True, label=_("Application Name"), help_text=_("Application Name"))
246+
desc = serializers.CharField(required=True, label=_("Application Description"),
247+
help_text=_("Application Description"))
248+
is_publish = serializers.BooleanField(required=True, label=_("Model id"), help_text=_("Model id"))
249+
type = serializers.CharField(required=True, label=_("Application type"), help_text=_("Application type"))
250+
resource_type = serializers.CharField(required=True, label=_("Resource type"), help_text=_("Resource type"))
251+
user_id = serializers.CharField(required=True, label=_('Affiliation user'), help_text=_("Affiliation user"))
252+
create_time = serializers.CharField(required=True, label=_('Creation time'), help_text=_("Creation time"))
253+
update_time = serializers.CharField(required=True, label=_('Modification time'), help_text=_("Modification time"))
254+
255+
256+
class Query(serializers.Serializer):
257+
workspace_id = serializers.CharField(required=False, label=_('workspace id'))
258+
259+
def get_query_set(self, instance: Dict):
260+
folder_query_set = QuerySet(ApplicationFolder)
261+
application_query_set = QuerySet(Application)
262+
workspace_id = self.data.get('workspace_id')
263+
user_id = instance.get('user_id')
264+
desc = instance.get('desc')
265+
name = instance.get('name')
266+
if workspace_id is not None:
267+
folder_query_set = folder_query_set.filter(workspace_id=workspace_id)
268+
application_query_set = application_query_set.filter(workspace_id=workspace_id)
269+
if user_id is not None:
270+
folder_query_set = folder_query_set.filter(user_id=user_id)
271+
application_query_set = application_query_set.filter(user_id=user_id)
272+
folder_id = instance.get('folder_id')
273+
if folder_id is not None:
274+
folder_query_set = folder_query_set.filter(parent=folder_id)
275+
application_query_set = application_query_set.filter(folder_id=folder_id)
276+
if name is not None:
277+
folder_query_set = folder_query_set.filter(name__contains=name)
278+
application_query_set = application_query_set.filter(name__contains=name)
279+
if desc is not None:
280+
folder_query_set = folder_query_set.filter(desc__contains=desc)
281+
application_query_set = application_query_set.filter(desc__contains=desc)
282+
application_query_set = application_query_set.order_by("-update_time")
283+
return {
284+
'folder_query_set': folder_query_set,
285+
'application_query_set': application_query_set
286+
}
287+
288+
@staticmethod
289+
def is_x_pack_ee():
290+
workspace_user_role_mapping_model = DatabaseModelManage.get_model("workspace_user_role_mapping")
291+
role_permission_mapping_model = DatabaseModelManage.get_model("role_permission_mapping_model")
292+
return workspace_user_role_mapping_model is not None and role_permission_mapping_model is not None
293+
294+
def list(self, instance: Dict):
295+
self.is_valid(raise_exception=True)
296+
ApplicationQueryRequest(data=instance).is_valid(raise_exception=True)
297+
return native_search(self.get_query_set(instance), select_string=get_file_content(
298+
os.path.join(PROJECT_DIR, "apps", "application", 'sql',
299+
'list_application_ee.sql' if self.is_x_pack_ee() else 'list_application.sql')))
300+
301+
def page(self, current_page: int, page_size: int, instance: Dict):
302+
self.is_valid(raise_exception=True)
303+
ApplicationQueryRequest(data=instance).is_valid(raise_exception=True)
304+
return native_page_search(current_page, page_size, self.get_query_set(instance), get_file_content(
305+
os.path.join(PROJECT_DIR, "apps", "application", 'sql',
306+
'list_application_ee.sql' if self.is_x_pack_ee() else 'list_application.sql')),
307+
)
308+
309+
230310
class ApplicationSerializer(serializers.Serializer):
231311
workspace_id = serializers.CharField(required=True, label=_('workspace id'))
232312
user_id = serializers.UUIDField(required=True, label=_("User ID"))
233313

234-
def insert(self, instance: Dict, with_valid=True):
314+
def insert(self, instance: Dict):
235315
application_type = instance.get('type')
236316
if 'WORK_FLOW' == application_type:
237317
return self.insert_workflow(instance)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
select *
2+
from (select "id"::text,
3+
"name",
4+
"desc",
5+
"is_publish",
6+
"type",
7+
'application' as "resource_type",
8+
"workspace_id",
9+
"folder_id",
10+
"user_id",
11+
"create_time",
12+
"update_time"
13+
from application
14+
where id in (select target
15+
from workspace_user_resource_permission
16+
where auth_target_type = 'APPLICATION'
17+
and 'VIEW' = any (permission_list))
18+
UNION
19+
select "id",
20+
"name",
21+
"desc",
22+
true as "is_publish",
23+
'folder' as "type",
24+
'folder' as "resource_type",
25+
"workspace_id",
26+
"parent_id" as "folder_id",
27+
"user_id",
28+
"create_time",
29+
"update_time"
30+
from application_folder ${folder_query_set}) temp
31+
${application_query_set}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
select *
2+
from (select "id"::text,
3+
"name",
4+
"desc",
5+
"is_publish",
6+
"type",
7+
'application' as "resource_type",
8+
"workspace_id",
9+
"folder_id",
10+
"user_id",
11+
"create_time",
12+
"update_time"
13+
from application
14+
where id in (select target
15+
from workspace_user_resource_permission
16+
where auth_target_type = 'APPLICATION'
17+
and case
18+
when auth_type = 'ROLE' then
19+
'APPLICATION_READ' in (select permission_id
20+
from role_permission
21+
where role_id in (select role_id
22+
from user_role_relation))
23+
else
24+
'VIEW' = any (permission_list)
25+
end)
26+
UNION
27+
select "id",
28+
"name",
29+
"desc",
30+
true as "is_publish",
31+
'folder' as "type",
32+
'folder' as "resource_type",
33+
"workspace_id",
34+
"parent_id" as "folder_id",
35+
"user_id",
36+
"create_time",
37+
"update_time"
38+
from application_folder ${folder_query_set}) temp
39+
${application_query_set}

apps/application/urls.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,7 @@
66

77
urlpatterns = [
88
path('workspace/<str:workspace_id>/application', views.Application.as_view(), name='application'),
9+
path('workspace/<str:workspace_id>/application/<int:current_page>/<int:page_size>',
10+
views.Application.Page.as_view(), name='application_page'),
911
path('workspace/<str:workspace_id>/application/<str:application_id>/application_key',
1012
views.ApplicationKey.as_view())]

apps/application/views/application.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
from rest_framework.request import Request
1212
from rest_framework.views import APIView
1313

14-
from application.api.application_api import ApplicationCreateAPI
15-
from application.serializers.application import ApplicationSerializer
14+
from application.api.application_api import ApplicationCreateAPI, ApplicationQueryAPI
15+
from application.serializers.application import ApplicationSerializer, Query
1616
from common import result
1717
from common.auth import TokenAuth
18+
from common.auth.authentication import has_permissions
19+
from common.constants.permission_constants import PermissionConstants
1820

1921

2022
class Application(APIView):
@@ -30,6 +32,38 @@ class Application(APIView):
3032
responses=ApplicationCreateAPI.get_response(),
3133
tags=[_('Application')] # type: ignore
3234
)
35+
@has_permissions(PermissionConstants.APPLICATION_READ.get_workspace_permission())
3336
def post(self, request: Request, workspace_id: str):
3437
return result.success(
3538
ApplicationSerializer(data={'workspace_id': workspace_id, 'user_id': request.user.id}).insert(request.data))
39+
40+
@extend_schema(
41+
methods=['GET'],
42+
description=_('Get the application list'),
43+
summary=_('Get the application list'),
44+
operation_id=_('Get the application list'), # type: ignore
45+
parameters=ApplicationQueryAPI.get_parameters(),
46+
responses=ApplicationQueryAPI.get_response(),
47+
tags=[_('Application')] # type: ignore
48+
)
49+
@has_permissions(PermissionConstants.APPLICATION_READ.get_workspace_permission())
50+
def get(self, request: Request, workspace_id: str):
51+
return result.success(Query(data={'workspace_id': workspace_id, 'user_id': request.user.id}).list(request.data))
52+
53+
class Page(APIView):
54+
authentication_classes = [TokenAuth]
55+
56+
@extend_schema(
57+
methods=['GET'],
58+
description=_('Get the application list by page'),
59+
summary=_('Get the application list by page'),
60+
operation_id=_('Get the application list by page'), # type: ignore
61+
parameters=ApplicationQueryAPI.get_parameters(),
62+
responses=ApplicationQueryAPI.get_page_response(),
63+
tags=[_('Application')] # type: ignore
64+
)
65+
@has_permissions(PermissionConstants.APPLICATION_READ.get_workspace_permission())
66+
def get(self, request: Request, workspace_id: str, current_page: int, page_size: int):
67+
return result.success(
68+
Query(data={'workspace_id': workspace_id, 'user_id': request.user.id}).page(current_page, page_size,
69+
request.query_params))

apps/common/constants/permission_constants.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class SystemGroup(Enum):
5858
SYSTEM_SETTING = "SYSTEM_SETTING"
5959
OPERATION_LOG = "OPERATION_LOG"
6060
OTHER = "OTHER"
61+
APPLICATION = "APPLICATION"
6162

6263

6364
class WorkspaceGroup(Enum):
@@ -514,8 +515,11 @@ class PermissionConstants(Enum):
514515
group=Group.LOGIN_AUTH, operate=Operate.EDIT, role_list=[RoleConstants.ADMIN],
515516
parent_group=[SystemGroup.SYSTEM_SETTING]
516517
)
517-
518-
518+
APPLICATION_READ = Permission(group=Group.APPLICATION, operate=Operate.READ,
519+
role_list=[RoleConstants.ADMIN, RoleConstants.USER],
520+
parent_group=[SystemGroup.APPLICATION],
521+
resource_permission_group_list=[ResourcePermissionGroup.VIEW],
522+
)
519523

520524
def get_workspace_application_permission(self):
521525
return lambda r, kwargs: Permission(group=self.value.group, operate=self.value.operate,

0 commit comments

Comments
 (0)