feat: implement CRUD operations for tools with API views
This commit is contained in:
parent
f89e18578f
commit
0b8f5d7597
@ -133,6 +133,12 @@ class PermissionConstants(Enum):
|
|||||||
|
|
||||||
TOOL_CREATE = Permission(group=Group.TOOL, operate=Operate.CREATE, role_list=[RoleConstants.ADMIN,
|
TOOL_CREATE = Permission(group=Group.TOOL, operate=Operate.CREATE, role_list=[RoleConstants.ADMIN,
|
||||||
RoleConstants.USER])
|
RoleConstants.USER])
|
||||||
|
TOOL_EDIT = Permission(group=Group.TOOL, operate=Operate.EDIT, role_list=[RoleConstants.ADMIN,
|
||||||
|
RoleConstants.USER])
|
||||||
|
TOOL_READ = Permission(group=Group.TOOL, operate=Operate.READ, role_list=[RoleConstants.ADMIN,
|
||||||
|
RoleConstants.USER])
|
||||||
|
TOOL_DELETE = Permission(group=Group.TOOL, operate=Operate.DELETE, role_list=[RoleConstants.ADMIN,
|
||||||
|
RoleConstants.USER])
|
||||||
|
|
||||||
def get_workspace_application_permission(self):
|
def get_workspace_application_permission(self):
|
||||||
return lambda r, kwargs: Permission(group=self.value.group, operate=self.value.operate,
|
return lambda r, kwargs: Permission(group=self.value.group, operate=self.value.operate,
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
from drf_spectacular.types import OpenApiTypes
|
||||||
|
from drf_spectacular.utils import OpenApiParameter
|
||||||
|
|
||||||
from common.mixins.api_mixin import APIMixin
|
from common.mixins.api_mixin import APIMixin
|
||||||
from common.result import ResultSerializer
|
from common.result import ResultSerializer
|
||||||
@ -11,6 +13,18 @@ class ToolCreateResponse(ResultSerializer):
|
|||||||
|
|
||||||
|
|
||||||
class ToolCreateAPI(APIMixin):
|
class ToolCreateAPI(APIMixin):
|
||||||
|
@staticmethod
|
||||||
|
def get_parameters():
|
||||||
|
return [
|
||||||
|
OpenApiParameter(
|
||||||
|
name="workspace_id",
|
||||||
|
description="工作空间id",
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
location='path',
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_request():
|
def get_request():
|
||||||
return ToolCreateRequest
|
return ToolCreateRequest
|
||||||
@ -18,3 +32,39 @@ class ToolCreateAPI(APIMixin):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def get_response():
|
def get_response():
|
||||||
return ToolCreateResponse
|
return ToolCreateResponse
|
||||||
|
|
||||||
|
|
||||||
|
class ToolReadAPI(APIMixin):
|
||||||
|
@staticmethod
|
||||||
|
def get_parameters():
|
||||||
|
return [
|
||||||
|
OpenApiParameter(
|
||||||
|
name="workspace_id",
|
||||||
|
description="工作空间id",
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
location='path',
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
OpenApiParameter(
|
||||||
|
name="tool_id",
|
||||||
|
description="工具id",
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
location='path',
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_response():
|
||||||
|
return ToolCreateResponse
|
||||||
|
|
||||||
|
|
||||||
|
class ToolEditAPI(ToolReadAPI):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_request():
|
||||||
|
return ToolCreateRequest
|
||||||
|
|
||||||
|
|
||||||
|
class ToolDeleteAPI(ToolReadAPI):
|
||||||
|
pass
|
||||||
|
|||||||
@ -66,13 +66,13 @@ class Migration(migrations.Migration):
|
|||||||
models.CharField(choices=[('INTERNAL', '内置'), ('PUBLIC', '公开')], default='PUBLIC', max_length=20,
|
models.CharField(choices=[('INTERNAL', '内置'), ('PUBLIC', '公开')], default='PUBLIC', max_length=20,
|
||||||
verbose_name='函数类型')),
|
verbose_name='函数类型')),
|
||||||
('template_id', models.UUIDField(default=None, null=True, verbose_name='模版id')),
|
('template_id', models.UUIDField(default=None, null=True, verbose_name='模版id')),
|
||||||
('workspace_id', models.CharField(default='default', max_length=64, verbose_name='工作空间id')),
|
('workspace_id', models.CharField(default='default', max_length=64, verbose_name='工作空间id', db_index=True)),
|
||||||
('init_params', models.CharField(max_length=102400, null=True, verbose_name='初始化参数')),
|
('init_params', models.CharField(max_length=102400, null=True, verbose_name='初始化参数')),
|
||||||
('create_time', models.DateTimeField(auto_now_add=True, null=True, verbose_name='创建时间')),
|
('create_time', models.DateTimeField(auto_now_add=True, null=True, verbose_name='创建时间')),
|
||||||
('update_time', models.DateTimeField(auto_now=True, null=True, verbose_name='修改时间')),
|
('update_time', models.DateTimeField(auto_now=True, null=True, verbose_name='修改时间')),
|
||||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.user',
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.user',
|
||||||
verbose_name='用户id')),
|
verbose_name='用户id')),
|
||||||
('module_id',
|
('module',
|
||||||
models.ForeignKey(default='root', on_delete=django.db.models.deletion.CASCADE, to='tools.toolmodule',
|
models.ForeignKey(default='root', on_delete=django.db.models.deletion.CASCADE, to='tools.toolmodule',
|
||||||
verbose_name='模块id')),
|
verbose_name='模块id')),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -30,8 +30,8 @@ class Tool(models.Model):
|
|||||||
tool_type = models.CharField(max_length=20, verbose_name='函数类型', choices=ToolType.choices,
|
tool_type = models.CharField(max_length=20, verbose_name='函数类型', choices=ToolType.choices,
|
||||||
default=ToolType.PUBLIC)
|
default=ToolType.PUBLIC)
|
||||||
template_id = models.UUIDField(max_length=128, verbose_name="模版id", null=True, default=None)
|
template_id = models.UUIDField(max_length=128, verbose_name="模版id", null=True, default=None)
|
||||||
module_id = models.ForeignKey(ToolModule, on_delete=models.CASCADE, verbose_name="模块id", default='root')
|
module = models.ForeignKey(ToolModule, on_delete=models.CASCADE, verbose_name="模块id", default='root')
|
||||||
workspace_id = models.CharField(max_length=64, verbose_name="工作空间id", default="default")
|
workspace_id = models.CharField(max_length=64, verbose_name="工作空间id", default="default", db_index=True)
|
||||||
init_params = models.CharField(max_length=102400, verbose_name="初始化参数", null=True)
|
init_params = models.CharField(max_length=102400, verbose_name="初始化参数", null=True)
|
||||||
create_time = models.DateTimeField(verbose_name="创建时间", auto_now_add=True, null=True)
|
create_time = models.DateTimeField(verbose_name="创建时间", auto_now_add=True, null=True)
|
||||||
update_time = models.DateTimeField(verbose_name="修改时间", auto_now=True, null=True)
|
update_time = models.DateTimeField(verbose_name="修改时间", auto_now=True, null=True)
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import re
|
|||||||
|
|
||||||
import uuid_utils.compat as uuid
|
import uuid_utils.compat as uuid
|
||||||
from django.core import validators
|
from django.core import validators
|
||||||
|
from django.db.models import QuerySet
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
@ -30,6 +31,17 @@ class ToolInputField(serializers.Serializer):
|
|||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
class InitField(serializers.Serializer):
|
||||||
|
field = serializers.CharField(required=True, label=_('field name'))
|
||||||
|
label = serializers.CharField(required=True, label=_('field label'))
|
||||||
|
required = serializers.BooleanField(required=True, label=_('required'))
|
||||||
|
input_type = serializers.CharField(required=True, label=_('input type'))
|
||||||
|
default_value = serializers.CharField(required=False, allow_null=True, allow_blank=True)
|
||||||
|
show_default_value = serializers.BooleanField(required=False, default=False)
|
||||||
|
props_info = serializers.DictField(required=False, default=dict)
|
||||||
|
attrs = serializers.DictField(required=False, default=dict)
|
||||||
|
|
||||||
|
|
||||||
class ToolCreateRequest(serializers.Serializer):
|
class ToolCreateRequest(serializers.Serializer):
|
||||||
name = serializers.CharField(required=True, label=_('tool name'))
|
name = serializers.CharField(required=True, label=_('tool name'))
|
||||||
|
|
||||||
@ -38,9 +50,10 @@ class ToolCreateRequest(serializers.Serializer):
|
|||||||
|
|
||||||
code = serializers.CharField(required=True, label=_('tool content'))
|
code = serializers.CharField(required=True, label=_('tool content'))
|
||||||
|
|
||||||
input_field_list = serializers.ListField(child=ToolInputField(), required=False, label=_('input field list'))
|
input_field_list = serializers.ListField(child=ToolInputField(), required=False, default=list,
|
||||||
|
label=_('input field list'))
|
||||||
|
|
||||||
init_field_list = serializers.ListField(required=False, default=list, label=_('init field list'))
|
init_field_list = serializers.ListField(child=InitField(), required=False, default=list, label=_('init field list'))
|
||||||
|
|
||||||
is_active = serializers.BooleanField(required=False, label=_('Is active'))
|
is_active = serializers.BooleanField(required=False, label=_('Is active'))
|
||||||
|
|
||||||
@ -50,6 +63,7 @@ class ToolCreateRequest(serializers.Serializer):
|
|||||||
class ToolSerializer(serializers.Serializer):
|
class ToolSerializer(serializers.Serializer):
|
||||||
class Create(serializers.Serializer):
|
class Create(serializers.Serializer):
|
||||||
user_id = serializers.UUIDField(required=True, label=_('user id'))
|
user_id = serializers.UUIDField(required=True, label=_('user id'))
|
||||||
|
workspace_id = serializers.UUIDField(required=True, label=_('workspace id'))
|
||||||
|
|
||||||
def insert(self, instance, with_valid=True):
|
def insert(self, instance, with_valid=True):
|
||||||
if with_valid:
|
if with_valid:
|
||||||
@ -66,3 +80,32 @@ class ToolSerializer(serializers.Serializer):
|
|||||||
is_active=False)
|
is_active=False)
|
||||||
tool.save()
|
tool.save()
|
||||||
return ToolModelSerializer(tool).data
|
return ToolModelSerializer(tool).data
|
||||||
|
|
||||||
|
class Operate(serializers.Serializer):
|
||||||
|
id = serializers.UUIDField(required=True, label=_('tool id'))
|
||||||
|
workspace_id = serializers.CharField(required=True, label=_('workspace id'))
|
||||||
|
|
||||||
|
def edit(self, instance, with_valid=True):
|
||||||
|
if with_valid:
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
ToolCreateRequest(data=instance).is_valid(raise_exception=True)
|
||||||
|
if not QuerySet(Tool).filter(id=self.data.get('id')).exists():
|
||||||
|
raise serializers.ValidationError(_('Tool not found'))
|
||||||
|
|
||||||
|
edit_field_list = ['name', 'desc', 'code', 'icon', 'input_field_list', 'init_field_list', 'init_params',
|
||||||
|
'is_active']
|
||||||
|
edit_dict = {field: instance.get(field) for field in edit_field_list if (
|
||||||
|
field in instance and instance.get(field) is not None)}
|
||||||
|
|
||||||
|
QuerySet(Tool).filter(id=self.data.get('id')).update(**edit_dict)
|
||||||
|
|
||||||
|
return self.one()
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
QuerySet(Tool).filter(id=self.data.get('id')).delete()
|
||||||
|
|
||||||
|
def one(self):
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
tool = QuerySet(Tool).filter(id=self.data.get('id')).first()
|
||||||
|
return ToolModelSerializer(tool).data
|
||||||
|
|||||||
@ -4,5 +4,6 @@ from . import views
|
|||||||
|
|
||||||
app_name = "tool"
|
app_name = "tool"
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('workspace/<str:workspace_id>/tool/create', views.ToolCreateView.as_view()),
|
path('workspace/<str:workspace_id>/tool', views.ToolView.Create.as_view()),
|
||||||
|
path('workspace/<str:workspace_id>/tool/<str:tool_id>', views.ToolView.Operate.as_view()),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -7,22 +7,62 @@ from common.auth import TokenAuth
|
|||||||
from common.auth.authentication import has_permissions
|
from common.auth.authentication import has_permissions
|
||||||
from common.constants.permission_constants import PermissionConstants
|
from common.constants.permission_constants import PermissionConstants
|
||||||
from common.result import result
|
from common.result import result
|
||||||
from tools.api.tool import ToolCreateAPI
|
from tools.api.tool import ToolCreateAPI, ToolEditAPI, ToolReadAPI, ToolDeleteAPI
|
||||||
from tools.serializers.tool import ToolSerializer
|
from tools.serializers.tool import ToolSerializer
|
||||||
|
|
||||||
|
|
||||||
class ToolCreateView(APIView):
|
class ToolView(APIView):
|
||||||
authentication_classes = [TokenAuth]
|
class Create(APIView):
|
||||||
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
@extend_schema(methods=['POST'],
|
@extend_schema(methods=['POST'],
|
||||||
description=_('Create tool'),
|
description=_('Create tool'),
|
||||||
operation_id=_('Create tool'),
|
operation_id=_('Create tool'),
|
||||||
request=ToolCreateAPI.get_request(),
|
parameters=ToolCreateAPI.get_parameters(),
|
||||||
responses=ToolCreateAPI.get_response(),
|
request=ToolCreateAPI.get_request(),
|
||||||
tags=[_('Tool')])
|
responses=ToolCreateAPI.get_response(),
|
||||||
@has_permissions(PermissionConstants.TOOL_CREATE)
|
tags=[_('Tool')])
|
||||||
# @log(menu='Tool', operate="Create tool",
|
@has_permissions(PermissionConstants.TOOL_CREATE.get_workspace_permission())
|
||||||
# get_operation_object=lambda r, k: r.data.get('name'))
|
def post(self, request: Request, workspace_id: str):
|
||||||
def post(self, request: Request, workspace_id: str):
|
return result.success(ToolSerializer.Create(
|
||||||
print(workspace_id)
|
data={'user_id': request.user.id, 'workspace_id': workspace_id}
|
||||||
return result.success(ToolSerializer.Create(data={'user_id': request.user.id}).insert(request.data))
|
).insert(request.data))
|
||||||
|
|
||||||
|
class Operate(APIView):
|
||||||
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
|
@extend_schema(methods=['PUT'],
|
||||||
|
description=_('Update tool'),
|
||||||
|
operation_id=_('Update tool'),
|
||||||
|
parameters=ToolEditAPI.get_parameters(),
|
||||||
|
request=ToolEditAPI.get_request(),
|
||||||
|
responses=ToolEditAPI.get_response(),
|
||||||
|
tags=[_('Tool')])
|
||||||
|
@has_permissions(PermissionConstants.TOOL_EDIT.get_workspace_permission())
|
||||||
|
def put(self, request: Request, workspace_id: str, tool_id: str):
|
||||||
|
return result.success(ToolSerializer.Operate(
|
||||||
|
data={'id': tool_id, 'workspace_id': workspace_id}
|
||||||
|
).edit(request.data))
|
||||||
|
|
||||||
|
@extend_schema(methods=['GET'],
|
||||||
|
description=_('Update tool'),
|
||||||
|
operation_id=_('Update tool'),
|
||||||
|
parameters=ToolReadAPI.get_parameters(),
|
||||||
|
responses=ToolReadAPI.get_response(),
|
||||||
|
tags=[_('Tool')])
|
||||||
|
@has_permissions(PermissionConstants.TOOL_READ.get_workspace_permission())
|
||||||
|
def get(self, request: Request, workspace_id: str, tool_id: str):
|
||||||
|
return result.success(ToolSerializer.Operate(
|
||||||
|
data={'id': tool_id, 'workspace_id': workspace_id}
|
||||||
|
).one())
|
||||||
|
|
||||||
|
@extend_schema(methods=['DELETE'],
|
||||||
|
description=_('Delete tool'),
|
||||||
|
operation_id=_('Delete tool'),
|
||||||
|
parameters=ToolDeleteAPI.get_parameters(),
|
||||||
|
tags=[_('Tool')])
|
||||||
|
@has_permissions(PermissionConstants.TOOL_DELETE.get_workspace_permission())
|
||||||
|
def delete(self, request: Request, workspace_id: str, tool_id: str):
|
||||||
|
return result.success(ToolSerializer.Operate(
|
||||||
|
data={'id': tool_id, 'workspace_id': workspace_id}
|
||||||
|
).delete())
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user