mirror of
https://github.com/fastapi-practices/fastapi_best_architecture.git
synced 2026-03-13 09:31:31 +08:00
* Optimize routes to better align with RESTful * Add codes endpoint description * Update jinja templates * fix typo * fix sql
85 lines
3.1 KiB
Python
85 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
from typing import Annotated, Any
|
|
|
|
from fastapi import APIRouter, Depends, File, Path, UploadFile
|
|
from fastapi.params import Query
|
|
from starlette.responses import StreamingResponse
|
|
|
|
from backend.app.admin.service.plugin_service import plugin_service
|
|
from backend.common.enums import PluginType
|
|
from backend.common.response.response_code import CustomResponseCode
|
|
from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base
|
|
from backend.common.security.jwt import DependsJwtAuth
|
|
from backend.common.security.permission import RequestPermission
|
|
from backend.common.security.rbac import DependsRBAC
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get('', summary='获取所有插件', dependencies=[DependsJwtAuth])
|
|
async def get_all_plugins() -> ResponseSchemaModel[list[dict[str, Any]]]:
|
|
plugins = await plugin_service.get_all()
|
|
return response_base.success(data=plugins)
|
|
|
|
|
|
@router.get('/changed', summary='是否存在插件变更', dependencies=[DependsJwtAuth])
|
|
async def plugin_changed() -> ResponseSchemaModel[bool]:
|
|
plugins = await plugin_service.changed()
|
|
return response_base.success(data=bool(plugins))
|
|
|
|
|
|
@router.post(
|
|
'',
|
|
summary='安装插件',
|
|
description='使用插件 zip 压缩包或 git 仓库地址进行安装',
|
|
dependencies=[
|
|
Depends(RequestPermission('sys:plugin:install')),
|
|
DependsRBAC,
|
|
],
|
|
)
|
|
async def install_plugin(
|
|
type: Annotated[PluginType, Query(description='插件类型')],
|
|
file: Annotated[UploadFile | None, File()] = None,
|
|
repo_url: Annotated[str | None, Query(description='插件 git 仓库地址')] = None,
|
|
) -> ResponseModel:
|
|
await plugin_service.install(type=type, file=file, repo_url=repo_url)
|
|
return response_base.success(res=CustomResponseCode.PLUGIN_INSTALL_SUCCESS)
|
|
|
|
|
|
@router.delete(
|
|
'/{plugin}',
|
|
summary='卸载插件',
|
|
description='此操作会直接删除插件依赖,但不会直接删除插件,而是将插件移动到备份目录',
|
|
dependencies=[
|
|
Depends(RequestPermission('sys:plugin:uninstall')),
|
|
DependsRBAC,
|
|
],
|
|
)
|
|
async def uninstall_plugin(plugin: Annotated[str, Path(description='插件名称')]) -> ResponseModel:
|
|
await plugin_service.uninstall(plugin=plugin)
|
|
return response_base.success(res=CustomResponseCode.PLUGIN_UNINSTALL_SUCCESS)
|
|
|
|
|
|
@router.put(
|
|
'/{plugin}/status',
|
|
summary='更新插件状态',
|
|
dependencies=[
|
|
Depends(RequestPermission('sys:plugin:edit')),
|
|
DependsRBAC,
|
|
],
|
|
)
|
|
async def update_plugin_status(plugin: Annotated[str, Path(description='插件名称')]) -> ResponseModel:
|
|
await plugin_service.update_status(plugin=plugin)
|
|
return response_base.success()
|
|
|
|
|
|
@router.get('/{plugin}', summary='下载插件', dependencies=[DependsJwtAuth])
|
|
async def download_plugin(plugin: Annotated[str, Path(description='插件名称')]) -> StreamingResponse:
|
|
bio = await plugin_service.build(plugin=plugin)
|
|
return StreamingResponse(
|
|
bio,
|
|
media_type='application/x-zip-compressed',
|
|
headers={'Content-Disposition': f'attachment; filename={plugin}.zip'},
|
|
)
|