-
Notifications
You must be signed in to change notification settings - Fork 2.8k
feat: add Appstore tool retrieval and store tool API endpoint #4015
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| # Generated by Django 5.2.4 on 2025-09-09 04:07 | ||
|
|
||
| from django.db import migrations, models | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
|
|
||
| dependencies = [ | ||
| ('tools', '0002_alter_tool_tool_type'), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.AlterField( | ||
| model_name='tool', | ||
| name='template_id', | ||
| field=models.CharField(db_index=True, default=None, max_length=128, null=True, verbose_name='模版id'), | ||
| ), | ||
| migrations.AddField( | ||
| model_name='tool', | ||
| name='version', | ||
| field=models.CharField(default=None, max_length=64, null=True, verbose_name='版本号'), | ||
| ), | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -407,3 +407,84 @@ def post(self, request: Request, tool_id: str, workspace_id: str): | |
| 'user_id': request.user.id, | ||
| 'workspace_id': workspace_id | ||
| }).add(request.data)) | ||
|
|
||
| class StoreTool(APIView): | ||
| authentication_classes = [TokenAuth] | ||
|
|
||
| @extend_schema( | ||
| methods=['GET'], | ||
| description=_("Get Appstore tools"), | ||
| summary=_("Get Appstore tools"), | ||
| operation_id=_("Get Appstore tools"), # type: ignore | ||
| responses=GetInternalToolAPI.get_response(), | ||
| tags=[_("Tool")] # type: ignore | ||
| ) | ||
| def get(self, request: Request): | ||
| return result.success(ToolSerializer.StoreTool(data={ | ||
| 'user_id': request.user.id, | ||
| 'name': request.query_params.get('name', ''), | ||
| }).get_appstore_tools()) | ||
|
|
||
| class AddStoreTool(APIView): | ||
| authentication_classes = [TokenAuth] | ||
|
|
||
| @extend_schema( | ||
| methods=['POST'], | ||
| description=_("Add Appstore tool"), | ||
| summary=_("Add Appstore tool"), | ||
| operation_id=_("Add Appstore tool"), # type: ignore | ||
| parameters=AddInternalToolAPI.get_parameters(), | ||
| request=AddInternalToolAPI.get_request(), | ||
| responses=AddInternalToolAPI.get_response(), | ||
| tags=[_("Tool")] # type: ignore | ||
| ) | ||
| @has_permissions( | ||
| PermissionConstants.TOOL_CREATE.get_workspace_permission(), | ||
| PermissionConstants.TOOL_CREATE.get_workspace_permission_workspace_manage_role(), | ||
| RoleConstants.WORKSPACE_MANAGE.get_workspace_role(), | ||
| RoleConstants.USER.get_workspace_role(), | ||
| ) | ||
| @log( | ||
| menu='Tool', operate="Add Appstore tool", | ||
| get_operation_object=lambda r, k: get_tool_operation_object(k.get('tool_id')), | ||
| ) | ||
| def post(self, request: Request, tool_id: str, workspace_id: str): | ||
| return result.success(ToolSerializer.AddStoreTool(data={ | ||
| 'tool_id': tool_id, | ||
| 'user_id': request.user.id, | ||
| 'workspace_id': workspace_id, | ||
| }).add(request.data)) | ||
|
|
||
| class UpdateStoreTool(APIView): | ||
| authentication_classes = [TokenAuth] | ||
|
|
||
| @extend_schema( | ||
| methods=['POST'], | ||
| description=_("Update Appstore tool"), | ||
| summary=_("Update Appstore tool"), | ||
| operation_id=_("Update Appstore tool"), # type: ignore | ||
| parameters=AddInternalToolAPI.get_parameters(), | ||
| request=AddInternalToolAPI.get_request(), | ||
| responses=AddInternalToolAPI.get_response(), | ||
| tags=[_("Tool")] # type: ignore | ||
| ) | ||
| @has_permissions( | ||
| PermissionConstants.TOOL_CREATE.get_workspace_permission(), | ||
| PermissionConstants.TOOL_CREATE.get_workspace_permission_workspace_manage_role(), | ||
| RoleConstants.WORKSPACE_MANAGE.get_workspace_role(), | ||
| RoleConstants.USER.get_workspace_role(), | ||
| ) | ||
| @log( | ||
| menu='Tool', operate="Update Appstore tool", | ||
| get_operation_object=lambda r, k: get_tool_operation_object(k.get('tool_id')), | ||
| ) | ||
| def post(self, request: Request, tool_id: str, workspace_id: str): | ||
| return result.success(ToolSerializer.UpdateStoreTool(data={ | ||
| 'tool_id': tool_id, | ||
| 'user_id': request.user.id, | ||
| 'workspace_id': workspace_id, | ||
| 'download_url': request.data.get('download_url'), | ||
| 'download_callback_url': request.data.get('download_callback_url'), | ||
| 'icon': request.data.get('icon'), | ||
| 'versions': request.data.get('versions'), | ||
| }).update_tool(request.data)) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are no obvious irregularities in the provided code. However, here are some optimizations and considerations:
Here is a revised version with some added comments: from rest_framework.authentication import TokenAuth
from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiResponses
class StoreTool(APIView):
authentication_classes = [TokenAuth]
@extend_schema(
methods=['GET'],
description=_("Get Appstore tools"),
summary=_("Get Appstore tools"),
operation_id=_("Get Appstore tools"), # type: ignore
responses=GetInternalToolAPI.get_response(),
tags=[_("Tool")] # type: ignore
)
def get(self, request: Request):
name_param = request.query_params.get('name', '')
return result.success(ToolSerializer.StoreTool(data={
'user_id': request.user.id,
'name': name_param,
}).get_appstore_tools())
class AddStoreTool(APIView):
authentication_classes = [TokenAuth]
@extend_schema(
methods=['POST'],
description=_("Add Appstore tool"),
summary=_("Add Appstore tool"),
operation_id=_("Add Appstore tool"), # type: ignore
parameters=AddInternalToolAPI.get_parameters(),
request=AddInternalToolAPI.get_request(),
responses=AddInternalToolAPI.get_response(),
tags=[_("Tool")] # type: ignore
)
@has_permissions(
PermissionConstants.TOOL_CREATE.get_workspace_permission(),
PermissionConstants.TOOL_CREATE.get_workspace_permission_workspace_manage_role(),
RoleConstants.WORKSPACE_MANAGE.get_workspace_role(),
RoleConstants.USER.get_workspace_role(),
)
@log(
menu='Tool',
operate="Add Appstore tool",
get_operation_object=lambda r, k: get_tool_operation_object(k.get('tool_id')),
)
def post(self, request: Request, tool_id: str, workspace_id: str):
tool_data = {
'tool_id': tool_id,
'user_id': request.user.id,
'workspace_id': workspace_id,
}
tool_data.update(request.data)
download_url = tool_data.get('download_url')
download_callback_url = tool_data.get('download_callback_url')
icon = tool_data.get('icon')
versions = tool_data.get('versions')
return result.success(ToolSerializer.AddStoreTool(data=tool_data).add(tool_data))
class UpdateStoreTool(APIView):
authentication_classes = [TokenAuth]
@extend_schema(
methods=['POST'],
description=_("Update Appstore tool"),
summary=_("Update Appstore tool"),
operation_id=_("Update Appstore tool"), # type: ignore
parameters=AddInternalToolAPI.get_parameters(),
request=AddInternalToolAPI.get_request(),
responses=AddInternalToolAPI.get_response(),
tags=[_("Tool")] # type: ignore
)
@has_permissions(
PermissionConstants.TOOL_CREATE.get_workspace_permission(),
PermissionConstants.TOOL_CREATE.get_workspace_permission_workspace_manage_role(),
RoleConstants.WORKSPACE_MANAGE.get_workspace_role(),
RoleConstants.USER.get_workspace_role(),
)
@log(
menu='Tool',
operate="Update Appstore tool",
get_operation_object=lambda r, k: get_tool_operation_object(k.get('tool_id')),
)
def post(self, request: Request, tool_id: str, workspace_id: str):
tool_data = {
'tool_id': tool_id,
'user_id': request.user.id,
'workspace_id': workspace_id,
}
tool_data.update(request.data)
return result.success(ToolSerializer.UpdateStoreTool(data=tool_data).update_tool(request.data))This revision includes minor improvements such as clearer variable names and improved readability. |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code provided seems correct overall but has several improvements can be made:
Logging Configuration: Ensure that
maxkb_loggeris properly configured to handle log messages effectively. Consider setting up logging configurations at different levels such as DEBUG, INFO, WARNING, ERROR, and CRITICAL.Input Validation: Use Django REST Framework (DRF) validation more extensively within each serializer. This will help ensure data integrity before saving entities to the database.
Error Handling and Logging: Enhance error handling by using custom exceptions or libraries like
python-loguru. Also, consider using Python's built-in logging utilities for detailed and comprehensive logging throughout your application.Performance Improvements: Optimize network requests by adding headers for caching control (
if-none-match,cache-control) where possible.Security Measures: Implement security best practices, such as input sanitization and escaping special characters when dealing with user inputs that could contain HTML or JavaScript payloads.
Documentation: Add comprehensive documentation of APIs and their expected usage patterns. This can include endpoint descriptions, parameters, return values, examples, and any known limitations.
Code Consistency: Ensure consistent coding style across all parts of the codebase, including formatting conventions for comments, spaces, braces, indentation, etc.
Here’s an example of how you might incorporate some of these suggestions into the code:
Updated Code Snippet
By following these guidelines, you can improve the robustness, maintainability, and performance of your codebase while ensuring it adheres to industry standards for software development.