mirror of
https://github.com/fastapi-practices/fastapi-best-architecture.git
synced 2026-09-21 21:15:13 +00:00
Optimize codes and comments with cursor (#550)
This commit is contained in:
@@ -36,7 +36,7 @@ async def user_login(
|
||||
|
||||
|
||||
@router.post('/token/new', summary='创建新 token')
|
||||
async def create_new_token(request: Request, response: Response) -> ResponseSchemaModel[GetNewToken]:
|
||||
async def create_new_token(request: Request) -> ResponseSchemaModel[GetNewToken]:
|
||||
data = await auth_service.new_token(request=request)
|
||||
return response_base.success(data=data)
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ router = APIRouter()
|
||||
|
||||
@router.get(
|
||||
'',
|
||||
summary='(模糊条件)分页获取登录日志',
|
||||
summary='分页获取登录日志',
|
||||
dependencies=[
|
||||
DependsJwtAuth,
|
||||
DependsPagination,
|
||||
@@ -26,9 +26,9 @@ router = APIRouter()
|
||||
)
|
||||
async def get_pagination_login_logs(
|
||||
db: CurrentSession,
|
||||
username: Annotated[str | None, Query()] = None,
|
||||
status: Annotated[int | None, Query()] = None,
|
||||
ip: Annotated[str | None, Query()] = None,
|
||||
username: Annotated[str | None, Query(description='用户名')] = None,
|
||||
status: Annotated[int | None, Query(description='状态')] = None,
|
||||
ip: Annotated[str | None, Query(description='IP 地址')] = None,
|
||||
) -> ResponseSchemaModel[PageData[GetLoginLogDetail]]:
|
||||
log_select = await login_log_service.get_select(username=username, status=status, ip=ip)
|
||||
page_data = await paging_data(db, log_select)
|
||||
@@ -37,13 +37,13 @@ async def get_pagination_login_logs(
|
||||
|
||||
@router.delete(
|
||||
'',
|
||||
summary='(批量)删除登录日志',
|
||||
summary='批量删除登录日志',
|
||||
dependencies=[
|
||||
Depends(RequestPermission('log:login:del')),
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def delete_login_log(pk: Annotated[list[int], Query(...)]) -> ResponseModel:
|
||||
async def delete_login_log(pk: Annotated[list[int], Query(description='登录日志 ID 列表')]) -> ResponseModel:
|
||||
count = await login_log_service.delete(pk=pk)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
|
||||
@@ -18,7 +18,7 @@ router = APIRouter()
|
||||
|
||||
@router.get(
|
||||
'',
|
||||
summary='(模糊条件)分页获取操作日志',
|
||||
summary='分页获取操作日志',
|
||||
dependencies=[
|
||||
DependsJwtAuth,
|
||||
DependsPagination,
|
||||
@@ -26,9 +26,9 @@ router = APIRouter()
|
||||
)
|
||||
async def get_pagination_opera_logs(
|
||||
db: CurrentSession,
|
||||
username: Annotated[str | None, Query()] = None,
|
||||
status: Annotated[int | None, Query()] = None,
|
||||
ip: Annotated[str | None, Query()] = None,
|
||||
username: Annotated[str | None, Query(description='用户名')] = None,
|
||||
status: Annotated[int | None, Query(description='状态')] = None,
|
||||
ip: Annotated[str | None, Query(description='IP 地址')] = None,
|
||||
) -> ResponseSchemaModel[PageData[GetOperaLogDetail]]:
|
||||
log_select = await opera_log_service.get_select(username=username, status=status, ip=ip)
|
||||
page_data = await paging_data(db, log_select)
|
||||
@@ -37,13 +37,13 @@ async def get_pagination_opera_logs(
|
||||
|
||||
@router.delete(
|
||||
'',
|
||||
summary='(批量)删除操作日志',
|
||||
summary='批量删除操作日志',
|
||||
dependencies=[
|
||||
Depends(RequestPermission('log:opera:del')),
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def delete_opera_log(pk: Annotated[list[int], Query(...)]) -> ResponseModel:
|
||||
async def delete_opera_log(pk: Annotated[list[int], Query(description='操作日志 ID 列表')]) -> ResponseModel:
|
||||
count = await opera_log_service.delete(pk=pk)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
|
||||
@@ -19,5 +19,8 @@ router = APIRouter()
|
||||
],
|
||||
)
|
||||
async def get_redis_info() -> ResponseModel:
|
||||
data = {'info': await redis_info.get_info(), 'stats': await redis_info.get_stats()}
|
||||
data = {
|
||||
'info': await redis_info.get_info(),
|
||||
'stats': await redis_info.get_stats(),
|
||||
}
|
||||
return response_base.success(data=data)
|
||||
|
||||
@@ -19,7 +19,7 @@ _linux_do_client = LinuxDoOAuth20(
|
||||
_linux_do_oauth2 = FastAPIOAuth20(_linux_do_client, admin_settings.OAUTH2_LINUX_DO_REDIRECT_URI)
|
||||
|
||||
|
||||
@router.get('', summary='获取 Linux Do 授权链接')
|
||||
@router.get('', summary='获取 LinuxDo 授权链接')
|
||||
async def linux_do_auth2() -> ResponseSchemaModel[str]:
|
||||
auth_url = await _linux_do_client.get_authorization_url(redirect_uri=admin_settings.OAUTH2_LINUX_DO_REDIRECT_URI)
|
||||
return response_base.success(data=auth_url)
|
||||
@@ -27,8 +27,8 @@ async def linux_do_auth2() -> ResponseSchemaModel[str]:
|
||||
|
||||
@router.get(
|
||||
'/callback',
|
||||
summary='Linux Do 授权自动重定向',
|
||||
description='Linux Do 授权后,自动重定向到当前地址并获取用户信息,通过用户信息自动创建系统用户',
|
||||
summary='LinuxDo 授权自动重定向',
|
||||
description='LinuxDo 授权后,自动重定向到当前地址并获取用户信息,通过用户信息自动创建系统用户',
|
||||
dependencies=[Depends(RateLimiter(times=5, minutes=1))],
|
||||
)
|
||||
async def linux_do_login(
|
||||
@@ -45,6 +45,6 @@ async def linux_do_login(
|
||||
response=response,
|
||||
background_tasks=background_tasks,
|
||||
user=user,
|
||||
social=UserSocialType.linuxdo,
|
||||
social=UserSocialType.linux_do,
|
||||
)
|
||||
return RedirectResponse(url=f'{admin_settings.OAUTH2_FRONTEND_REDIRECT_URI}?access_token={data.access_token}')
|
||||
|
||||
@@ -16,7 +16,7 @@ from backend.app.admin.api.v1.sys.user import router as user_router
|
||||
|
||||
router = APIRouter(prefix='/sys')
|
||||
|
||||
router.include_router(config_router, prefix='/configs', tags=['系统配置'])
|
||||
router.include_router(config_router, prefix='/configs', tags=['系统参数配置'])
|
||||
router.include_router(dept_router, prefix='/depts', tags=['系统部门'])
|
||||
router.include_router(dict_data_router, prefix='/dict-datas', tags=['系统字典数据'])
|
||||
router.include_router(dict_type_router, prefix='/dict-types', tags=['系统字典类型'])
|
||||
|
||||
@@ -21,7 +21,7 @@ from backend.database.db import CurrentSession
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get('/website', summary='获取网站配置信息', dependencies=[DependsJwtAuth])
|
||||
@router.get('/website', summary='获取网站参数配置', dependencies=[DependsJwtAuth])
|
||||
async def get_website_config() -> ResponseSchemaModel[list[GetConfigDetail]]:
|
||||
config = await config_service.get_built_in_config('website')
|
||||
return response_base.success(data=config)
|
||||
@@ -29,7 +29,7 @@ async def get_website_config() -> ResponseSchemaModel[list[GetConfigDetail]]:
|
||||
|
||||
@router.post(
|
||||
'/website',
|
||||
summary='保存网站配置信息',
|
||||
summary='保存网站参数配置',
|
||||
dependencies=[
|
||||
Depends(RequestPermission('sys:config:website:add')),
|
||||
DependsRBAC,
|
||||
@@ -78,23 +78,23 @@ async def save_policy_config(objs: list[SaveBuiltInConfigParam]) -> ResponseMode
|
||||
return response_base.success()
|
||||
|
||||
|
||||
@router.get('/{pk}', summary='获取系统参数配置详情', dependencies=[DependsJwtAuth])
|
||||
async def get_config(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetConfigDetail]:
|
||||
@router.get('/{pk}', summary='获取参数配置详情', dependencies=[DependsJwtAuth])
|
||||
async def get_config(pk: Annotated[int, Path(description='参数配置 ID')]) -> ResponseSchemaModel[GetConfigDetail]:
|
||||
config = await config_service.get(pk)
|
||||
return response_base.success(data=config)
|
||||
|
||||
|
||||
@router.get(
|
||||
'',
|
||||
summary='(模糊条件)分页获取所有系统参数配置',
|
||||
summary='分页获取所有参数配置',
|
||||
dependencies=[
|
||||
DependsJwtAuth,
|
||||
DependsPagination,
|
||||
],
|
||||
)
|
||||
async def get_pagination_config(
|
||||
async def get_pagination_configs(
|
||||
db: CurrentSession,
|
||||
name: Annotated[str | None, Query()] = None,
|
||||
name: Annotated[str | None, Query(description='参数配置名称')] = None,
|
||||
type: Annotated[str | None, Query()] = None,
|
||||
) -> ResponseSchemaModel[PageData[GetConfigDetail]]:
|
||||
config_select = await config_service.get_select(name=name, type=type)
|
||||
@@ -104,7 +104,7 @@ async def get_pagination_config(
|
||||
|
||||
@router.post(
|
||||
'',
|
||||
summary='创建系统参数配置',
|
||||
summary='创建参数配置',
|
||||
dependencies=[
|
||||
Depends(RequestPermission('sys:config:add')),
|
||||
DependsRBAC,
|
||||
@@ -117,13 +117,13 @@ async def create_config(obj: CreateConfigParam) -> ResponseModel:
|
||||
|
||||
@router.put(
|
||||
'/{pk}',
|
||||
summary='更新系统参数配置',
|
||||
summary='更新参数配置',
|
||||
dependencies=[
|
||||
Depends(RequestPermission('sys:config:edit')),
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def update_config(pk: Annotated[int, Path(...)], obj: UpdateConfigParam) -> ResponseModel:
|
||||
async def update_config(pk: Annotated[int, Path(description='参数配置 ID')], obj: UpdateConfigParam) -> ResponseModel:
|
||||
count = await config_service.update(pk=pk, obj=obj)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
@@ -132,13 +132,13 @@ async def update_config(pk: Annotated[int, Path(...)], obj: UpdateConfigParam) -
|
||||
|
||||
@router.delete(
|
||||
'',
|
||||
summary='(批量)删除系统参数配置',
|
||||
summary='批量删除参数配置',
|
||||
dependencies=[
|
||||
Depends(RequestPermission('sys:config:del')),
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def delete_config(pk: Annotated[list[int], Query(...)]) -> ResponseModel:
|
||||
async def delete_config(pk: Annotated[list[int], Query(description='参数配置 ID 列表')]) -> ResponseModel:
|
||||
count = await config_service.delete(pk=pk)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
|
||||
@@ -23,33 +23,37 @@ async def get_data_rule_models() -> ResponseSchemaModel[list[str]]:
|
||||
|
||||
|
||||
@router.get('/model/{model}/columns', summary='获取支持过滤的数据库模型列', dependencies=[DependsJwtAuth])
|
||||
async def get_data_rule_model_columns(model: Annotated[str, Path()]) -> ResponseSchemaModel[list[str]]:
|
||||
async def get_data_rule_model_columns(
|
||||
model: Annotated[str, Path(description='模型名称')],
|
||||
) -> ResponseSchemaModel[list[str]]:
|
||||
models = await data_rule_service.get_columns(model=model)
|
||||
return response_base.success(data=models)
|
||||
|
||||
|
||||
@router.get('/all', summary='获取所有数据规则', dependencies=[DependsJwtAuth])
|
||||
async def get_all_data_rule() -> ResponseSchemaModel[list[GetDataRuleDetail]]:
|
||||
async def get_all_data_rules() -> ResponseSchemaModel[list[GetDataRuleDetail]]:
|
||||
data = await data_rule_service.get_all()
|
||||
return response_base.success(data=data)
|
||||
|
||||
|
||||
@router.get('/{pk}', summary='获取数据权限规则详情', dependencies=[DependsJwtAuth])
|
||||
async def get_data_rule(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetDataRuleDetail]:
|
||||
async def get_data_rule(
|
||||
pk: Annotated[int, Path(description='数据规则 ID')],
|
||||
) -> ResponseSchemaModel[GetDataRuleDetail]:
|
||||
data = await data_rule_service.get(pk=pk)
|
||||
return response_base.success(data=data)
|
||||
|
||||
|
||||
@router.get(
|
||||
'',
|
||||
summary='(模糊条件)分页获取所有数据权限规则',
|
||||
summary='分页获取所有数据权限规则',
|
||||
dependencies=[
|
||||
DependsJwtAuth,
|
||||
DependsPagination,
|
||||
],
|
||||
)
|
||||
async def get_pagination_data_rule(
|
||||
db: CurrentSession, name: Annotated[str | None, Query()] = None
|
||||
async def get_pagination_data_rules(
|
||||
db: CurrentSession, name: Annotated[str | None, Query(description='规则名称')] = None
|
||||
) -> ResponseSchemaModel[PageData[GetDataRuleDetail]]:
|
||||
data_rule_select = await data_rule_service.get_select(name=name)
|
||||
page_data = await paging_data(db, data_rule_select)
|
||||
@@ -77,7 +81,9 @@ async def create_data_rule(obj: CreateDataRuleParam) -> ResponseModel:
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def update_data_rule(pk: Annotated[int, Path(...)], obj: UpdateDataRuleParam) -> ResponseModel:
|
||||
async def update_data_rule(
|
||||
pk: Annotated[int, Path(description='数据规则 ID')], obj: UpdateDataRuleParam
|
||||
) -> ResponseModel:
|
||||
count = await data_rule_service.update(pk=pk, obj=obj)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
@@ -86,13 +92,15 @@ async def update_data_rule(pk: Annotated[int, Path(...)], obj: UpdateDataRulePar
|
||||
|
||||
@router.delete(
|
||||
'',
|
||||
summary='(批量)删除数据权限规则',
|
||||
summary='批量删除数据权限规则',
|
||||
dependencies=[
|
||||
Depends(RequestPermission('data:rule:del')),
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def delete_data_rule(request: Request, pk: Annotated[list[int], Query(...)]) -> ResponseModel:
|
||||
async def delete_data_rule(
|
||||
request: Request, pk: Annotated[list[int], Query(description='数据规则 ID 列表')]
|
||||
) -> ResponseModel:
|
||||
count = await data_rule_service.delete(request=request, pk=pk)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
|
||||
@@ -15,17 +15,17 @@ router = APIRouter()
|
||||
|
||||
|
||||
@router.get('/{pk}', summary='获取部门详情', dependencies=[DependsJwtAuth])
|
||||
async def get_dept(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetDeptDetail]:
|
||||
async def get_dept(pk: Annotated[int, Path(description='部门 ID')]) -> ResponseSchemaModel[GetDeptDetail]:
|
||||
data = await dept_service.get(pk=pk)
|
||||
return response_base.success(data=data)
|
||||
|
||||
|
||||
@router.get('', summary='获取所有部门展示树', dependencies=[DependsJwtAuth])
|
||||
async def get_all_depts_tree(
|
||||
name: Annotated[str | None, Query()] = None,
|
||||
leader: Annotated[str | None, Query()] = None,
|
||||
phone: Annotated[str | None, Query()] = None,
|
||||
status: Annotated[int | None, Query()] = None,
|
||||
async def get_all_depts(
|
||||
name: Annotated[str | None, Query(description='部门名称')] = None,
|
||||
leader: Annotated[str | None, Query(description='部门负责人')] = None,
|
||||
phone: Annotated[str | None, Query(description='联系电话')] = None,
|
||||
status: Annotated[int | None, Query(description='状态')] = None,
|
||||
) -> ResponseSchemaModel[list[dict[str, Any]]]:
|
||||
dept = await dept_service.get_dept_tree(name=name, leader=leader, phone=phone, status=status)
|
||||
return response_base.success(data=dept)
|
||||
@@ -52,7 +52,7 @@ async def create_dept(obj: CreateDeptParam) -> ResponseModel:
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def update_dept(pk: Annotated[int, Path(...)], obj: UpdateDeptParam) -> ResponseModel:
|
||||
async def update_dept(pk: Annotated[int, Path(description='部门 ID')], obj: UpdateDeptParam) -> ResponseModel:
|
||||
count = await dept_service.update(pk=pk, obj=obj)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
@@ -67,7 +67,7 @@ async def update_dept(pk: Annotated[int, Path(...)], obj: UpdateDeptParam) -> Re
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def delete_dept(request: Request, pk: Annotated[int, Path(...)]) -> ResponseModel:
|
||||
async def delete_dept(request: Request, pk: Annotated[int, Path(description='部门 ID')]) -> ResponseModel:
|
||||
count = await dept_service.delete(request=request, pk=pk)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
|
||||
@@ -22,14 +22,16 @@ router = APIRouter()
|
||||
|
||||
|
||||
@router.get('/{pk}', summary='获取字典详情', dependencies=[DependsJwtAuth])
|
||||
async def get_dict_data(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetDictDataWithRelation]:
|
||||
async def get_dict_data(
|
||||
pk: Annotated[int, Path(description='字典数据 ID')],
|
||||
) -> ResponseSchemaModel[GetDictDataWithRelation]:
|
||||
data = await dict_data_service.get(pk=pk)
|
||||
return response_base.success(data=data)
|
||||
|
||||
|
||||
@router.get(
|
||||
'',
|
||||
summary='(模糊条件)分页获取所有字典',
|
||||
summary='分页获取所有字典',
|
||||
dependencies=[
|
||||
DependsJwtAuth,
|
||||
DependsPagination,
|
||||
@@ -37,9 +39,9 @@ async def get_dict_data(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[Ge
|
||||
)
|
||||
async def get_pagination_dict_datas(
|
||||
db: CurrentSession,
|
||||
label: Annotated[str | None, Query()] = None,
|
||||
value: Annotated[str | None, Query()] = None,
|
||||
status: Annotated[int | None, Query()] = None,
|
||||
label: Annotated[str | None, Query(description='字典数据标签')] = None,
|
||||
value: Annotated[str | None, Query(description='字典数据键值')] = None,
|
||||
status: Annotated[int | None, Query(description='状态')] = None,
|
||||
) -> ResponseSchemaModel[PageData[GetDictDataDetail]]:
|
||||
dict_data_select = await dict_data_service.get_select(label=label, value=value, status=status)
|
||||
page_data = await paging_data(db, dict_data_select)
|
||||
@@ -67,7 +69,9 @@ async def create_dict_data(obj: CreateDictDataParam) -> ResponseModel:
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def update_dict_data(pk: Annotated[int, Path(...)], obj: UpdateDictDataParam) -> ResponseModel:
|
||||
async def update_dict_data(
|
||||
pk: Annotated[int, Path(description='字典数据 ID')], obj: UpdateDictDataParam
|
||||
) -> ResponseModel:
|
||||
count = await dict_data_service.update(pk=pk, obj=obj)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
@@ -76,13 +80,13 @@ async def update_dict_data(pk: Annotated[int, Path(...)], obj: UpdateDictDataPar
|
||||
|
||||
@router.delete(
|
||||
'',
|
||||
summary='(批量)删除字典',
|
||||
summary='批量删除字典',
|
||||
dependencies=[
|
||||
Depends(RequestPermission('sys:dict:data:del')),
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def delete_dict_data(pk: Annotated[list[int], Query(...)]) -> ResponseModel:
|
||||
async def delete_dict_data(pk: Annotated[list[int], Query(description='字典数据 ID 列表')]) -> ResponseModel:
|
||||
count = await dict_data_service.delete(pk=pk)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
|
||||
@@ -18,7 +18,7 @@ router = APIRouter()
|
||||
|
||||
@router.get(
|
||||
'',
|
||||
summary='(模糊条件)分页获取所有字典类型',
|
||||
summary='分页获取所有字典类型',
|
||||
dependencies=[
|
||||
DependsJwtAuth,
|
||||
DependsPagination,
|
||||
@@ -26,9 +26,9 @@ router = APIRouter()
|
||||
)
|
||||
async def get_pagination_dict_types(
|
||||
db: CurrentSession,
|
||||
name: Annotated[str | None, Query()] = None,
|
||||
code: Annotated[str | None, Query()] = None,
|
||||
status: Annotated[int | None, Query()] = None,
|
||||
name: Annotated[str | None, Query(description='字典类型名称')] = None,
|
||||
code: Annotated[str | None, Query(description='字典类型编码')] = None,
|
||||
status: Annotated[int | None, Query(description='状态')] = None,
|
||||
) -> ResponseSchemaModel[PageData[GetDictTypeDetail]]:
|
||||
dict_type_select = await dict_type_service.get_select(name=name, code=code, status=status)
|
||||
page_data = await paging_data(db, dict_type_select)
|
||||
@@ -56,7 +56,9 @@ async def create_dict_type(obj: CreateDictTypeParam) -> ResponseModel:
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def update_dict_type(pk: Annotated[int, Path(...)], obj: UpdateDictTypeParam) -> ResponseModel:
|
||||
async def update_dict_type(
|
||||
pk: Annotated[int, Path(description='字典类型 ID')], obj: UpdateDictTypeParam
|
||||
) -> ResponseModel:
|
||||
count = await dict_type_service.update(pk=pk, obj=obj)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
@@ -65,13 +67,13 @@ async def update_dict_type(pk: Annotated[int, Path(...)], obj: UpdateDictTypePar
|
||||
|
||||
@router.delete(
|
||||
'',
|
||||
summary='(批量)删除字典类型',
|
||||
summary='批量删除字典类型',
|
||||
dependencies=[
|
||||
Depends(RequestPermission('sys:dict:type:del')),
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def delete_dict_type(pk: Annotated[list[int], Query(...)]) -> ResponseModel:
|
||||
async def delete_dict_type(pk: Annotated[list[int], Query(description='字典类型 ID 列表')]) -> ResponseModel:
|
||||
count = await dict_type_service.delete(pk=pk)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
|
||||
@@ -14,21 +14,22 @@ from backend.common.security.rbac import DependsRBAC
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get('/sidebar', summary='获取用户菜单展示树', dependencies=[DependsJwtAuth])
|
||||
async def get_user_sidebar_tree(request: Request) -> ResponseSchemaModel[list[dict[str, Any]]]:
|
||||
@router.get('/sidebar', summary='获取用户侧边栏', dependencies=[DependsJwtAuth])
|
||||
async def get_user_sidebar(request: Request) -> ResponseSchemaModel[list[dict[str, Any]]]:
|
||||
menu = await menu_service.get_user_menu_tree(request=request)
|
||||
return response_base.success(data=menu)
|
||||
|
||||
|
||||
@router.get('/{pk}', summary='获取菜单详情', dependencies=[DependsJwtAuth])
|
||||
async def get_menu(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetMenuDetail]:
|
||||
async def get_menu(pk: Annotated[int, Path(description='菜单 ID')]) -> ResponseSchemaModel[GetMenuDetail]:
|
||||
data = await menu_service.get(pk=pk)
|
||||
return response_base.success(data=data)
|
||||
|
||||
|
||||
@router.get('', summary='获取所有菜单展示树', dependencies=[DependsJwtAuth])
|
||||
async def get_all_menus(
|
||||
title: Annotated[str | None, Query()] = None, status: Annotated[int | None, Query()] = None
|
||||
title: Annotated[str | None, Query(description='菜单标题')] = None,
|
||||
status: Annotated[int | None, Query(description='状体')] = None,
|
||||
) -> ResponseSchemaModel[list[dict[str, Any]]]:
|
||||
menu = await menu_service.get_menu_tree(title=title, status=status)
|
||||
return response_base.success(data=menu)
|
||||
@@ -55,7 +56,7 @@ async def create_menu(obj: CreateMenuParam) -> ResponseModel:
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def update_menu(pk: Annotated[int, Path(...)], obj: UpdateMenuParam) -> ResponseModel:
|
||||
async def update_menu(pk: Annotated[int, Path(description='菜单 ID')], obj: UpdateMenuParam) -> ResponseModel:
|
||||
count = await menu_service.update(pk=pk, obj=obj)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
@@ -70,7 +71,7 @@ async def update_menu(pk: Annotated[int, Path(...)], obj: UpdateMenuParam) -> Re
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def delete_menu(request: Request, pk: Annotated[int, Path(...)]) -> ResponseModel:
|
||||
async def delete_menu(request: Request, pk: Annotated[int, Path(description='菜单 ID 列表')]) -> ResponseModel:
|
||||
count = await menu_service.delete(request=request, pk=pk)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
|
||||
@@ -52,16 +52,17 @@ async def install_plugin(file: Annotated[UploadFile, File()]) -> ResponseModel:
|
||||
full_plugin_path = os.path.join(PLUGIN_DIR, plugin_name)
|
||||
if os.path.exists(full_plugin_path):
|
||||
raise errors.ForbiddenError(msg='此插件已安装')
|
||||
os.makedirs(full_plugin_path)
|
||||
else:
|
||||
os.makedirs(full_plugin_path, exist_ok=True)
|
||||
|
||||
# 解压安装
|
||||
# 解压(安装)
|
||||
members = []
|
||||
for member in zf.infolist():
|
||||
if member.filename.startswith(plugin_dir_in_zip):
|
||||
member.filename = member.filename.replace(plugin_dir_in_zip, '')
|
||||
if not member.filename:
|
||||
continue
|
||||
members.append(member)
|
||||
new_filename = member.filename.replace(plugin_dir_in_zip, '')
|
||||
if new_filename:
|
||||
member.filename = new_filename
|
||||
members.append(member)
|
||||
zf.extractall(PLUGIN_DIR, members)
|
||||
if os.path.exists(os.path.join(full_plugin_path, 'requirements.txt')):
|
||||
await install_requirements_async()
|
||||
@@ -77,10 +78,11 @@ async def install_plugin(file: Annotated[UploadFile, File()]) -> ResponseModel:
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def build_plugin_zip(plugin: Annotated[str, Query()]):
|
||||
async def build_plugin(plugin: Annotated[str, Query(description='插件名称')]) -> StreamingResponse:
|
||||
plugin_dir = os.path.join(PLUGIN_DIR, plugin)
|
||||
if not os.path.exists(plugin_dir):
|
||||
raise errors.ForbiddenError(msg='插件不存在')
|
||||
|
||||
bio = io.BytesIO()
|
||||
with zipfile.ZipFile(bio, 'w') as zf:
|
||||
for root, dirs, files in os.walk(plugin_dir):
|
||||
@@ -89,6 +91,7 @@ async def build_plugin_zip(plugin: Annotated[str, Query()]):
|
||||
file_path = os.path.join(root, file)
|
||||
arcname = os.path.relpath(file_path, start=plugin_dir)
|
||||
zf.write(file_path, arcname)
|
||||
|
||||
bio.seek(0)
|
||||
return StreamingResponse(
|
||||
bio,
|
||||
|
||||
@@ -32,32 +32,38 @@ async def get_all_roles() -> ResponseSchemaModel[list[GetRoleDetail]]:
|
||||
|
||||
|
||||
@router.get('/{pk}/all', summary='获取用户所有角色', dependencies=[DependsJwtAuth])
|
||||
async def get_user_all_roles(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[list[GetRoleDetail]]:
|
||||
async def get_user_all_roles(
|
||||
pk: Annotated[int, Path(description='用户 ID')],
|
||||
) -> ResponseSchemaModel[list[GetRoleDetail]]:
|
||||
data = await role_service.get_by_user(pk=pk)
|
||||
return response_base.success(data=data)
|
||||
|
||||
|
||||
@router.get('/{pk}/menus', summary='获取角色所有菜单', dependencies=[DependsJwtAuth])
|
||||
async def get_role_all_menus(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[list[dict[str, Any]]]:
|
||||
async def get_role_all_menus(
|
||||
pk: Annotated[int, Path(description='角色 ID')],
|
||||
) -> ResponseSchemaModel[list[dict[str, Any]]]:
|
||||
menu = await menu_service.get_role_menu_tree(pk=pk)
|
||||
return response_base.success(data=menu)
|
||||
|
||||
|
||||
@router.get('/{pk}/rules', summary='获取角色所有数据规则', dependencies=[DependsJwtAuth])
|
||||
async def get_role_all_rules(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[list[int]]:
|
||||
async def get_role_all_rules(pk: Annotated[int, Path(description='角色 ID')]) -> ResponseSchemaModel[list[int]]:
|
||||
rule = await data_rule_service.get_role_rules(pk=pk)
|
||||
return response_base.success(data=rule)
|
||||
|
||||
|
||||
@router.get('/{pk}', summary='获取角色详情', dependencies=[DependsJwtAuth])
|
||||
async def get_role(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetRoleWithRelationDetail]:
|
||||
async def get_role(
|
||||
pk: Annotated[int, Path(description='角色 ID')],
|
||||
) -> ResponseSchemaModel[GetRoleWithRelationDetail]:
|
||||
data = await role_service.get(pk=pk)
|
||||
return response_base.success(data=data)
|
||||
|
||||
|
||||
@router.get(
|
||||
'',
|
||||
summary='(模糊条件)分页获取所有角色',
|
||||
summary='分页获取所有角色',
|
||||
dependencies=[
|
||||
DependsJwtAuth,
|
||||
DependsPagination,
|
||||
@@ -65,8 +71,8 @@ async def get_role(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetRole
|
||||
)
|
||||
async def get_pagination_roles(
|
||||
db: CurrentSession,
|
||||
name: Annotated[str | None, Query()] = None,
|
||||
status: Annotated[int | None, Query()] = None,
|
||||
name: Annotated[str | None, Query(description='角色名称')] = None,
|
||||
status: Annotated[int | None, Query(description='状态')] = None,
|
||||
) -> ResponseSchemaModel[PageData[GetRoleDetail]]:
|
||||
role_select = await role_service.get_select(name=name, status=status)
|
||||
page_data = await paging_data(db, role_select)
|
||||
@@ -94,7 +100,7 @@ async def create_role(obj: CreateRoleParam) -> ResponseModel:
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def update_role(pk: Annotated[int, Path(...)], obj: UpdateRoleParam) -> ResponseModel:
|
||||
async def update_role(pk: Annotated[int, Path(description='角色 ID')], obj: UpdateRoleParam) -> ResponseModel:
|
||||
count = await role_service.update(pk=pk, obj=obj)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
@@ -110,7 +116,7 @@ async def update_role(pk: Annotated[int, Path(...)], obj: UpdateRoleParam) -> Re
|
||||
],
|
||||
)
|
||||
async def update_role_menus(
|
||||
request: Request, pk: Annotated[int, Path(...)], menu_ids: UpdateRoleMenuParam
|
||||
request: Request, pk: Annotated[int, Path(description='角色 ID')], menu_ids: UpdateRoleMenuParam
|
||||
) -> ResponseModel:
|
||||
count = await role_service.update_role_menu(request=request, pk=pk, menu_ids=menu_ids)
|
||||
if count > 0:
|
||||
@@ -127,7 +133,7 @@ async def update_role_menus(
|
||||
],
|
||||
)
|
||||
async def update_role_rules(
|
||||
request: Request, pk: Annotated[int, Path(...)], rule_ids: UpdateRoleRuleParam
|
||||
request: Request, pk: Annotated[int, Path(description='角色 ID')], rule_ids: UpdateRoleRuleParam
|
||||
) -> ResponseModel:
|
||||
count = await role_service.update_role_rule(request=request, pk=pk, rule_ids=rule_ids)
|
||||
if count > 0:
|
||||
@@ -137,13 +143,13 @@ async def update_role_rules(
|
||||
|
||||
@router.delete(
|
||||
'',
|
||||
summary='(批量)删除角色',
|
||||
summary='批量删除角色',
|
||||
dependencies=[
|
||||
Depends(RequestPermission('sys:role:del')),
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def delete_role(request: Request, pk: Annotated[list[int], Query(...)]) -> ResponseModel:
|
||||
async def delete_role(request: Request, pk: Annotated[list[int], Query(description='角色 ID 列表')]) -> ResponseModel:
|
||||
count = await role_service.delete(request=request, pk=pk)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
|
||||
@@ -9,7 +9,7 @@ from fastapi import APIRouter, Depends, Path, Query, Request
|
||||
from backend.app.admin.schema.token import GetTokenDetail, KickOutToken
|
||||
from backend.common.enums import StatusType
|
||||
from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base
|
||||
from backend.common.security.jwt import DependsJwtAuth, jwt_decode, superuser_verify
|
||||
from backend.common.security.jwt import DependsJwtAuth, jwt_decode, revoke_token, superuser_verify
|
||||
from backend.common.security.permission import RequestPermission
|
||||
from backend.common.security.rbac import DependsRBAC
|
||||
from backend.core.conf import settings
|
||||
@@ -19,10 +19,28 @@ router = APIRouter()
|
||||
|
||||
|
||||
@router.get('', summary='获取令牌列表', dependencies=[DependsJwtAuth])
|
||||
async def get_tokens(username: Annotated[str | None, Query()] = None) -> ResponseSchemaModel[list[GetTokenDetail]]:
|
||||
async def get_tokens(
|
||||
username: Annotated[str | None, Query(description='用户名')] = None,
|
||||
) -> ResponseSchemaModel[list[GetTokenDetail]]:
|
||||
token_keys = await redis_client.keys(f'{settings.TOKEN_REDIS_PREFIX}:*')
|
||||
token_online = await redis_client.smembers(settings.TOKEN_ONLINE_REDIS_PREFIX)
|
||||
data = []
|
||||
online_clients = await redis_client.smembers(settings.TOKEN_ONLINE_REDIS_PREFIX)
|
||||
data: list[GetTokenDetail] = []
|
||||
|
||||
def append_token_detail() -> None:
|
||||
data.append(
|
||||
token_detail.model_copy(
|
||||
update={
|
||||
'username': extra_info.get('username', '未知'),
|
||||
'nickname': extra_info.get('nickname', '未知'),
|
||||
'ip': extra_info.get('ip', '未知'),
|
||||
'os': extra_info.get('os', '未知'),
|
||||
'browser': extra_info.get('browser', '未知'),
|
||||
'device': extra_info.get('device', '未知'),
|
||||
'last_login_time': extra_info.get('last_login_time', '未知'),
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
for key in token_keys:
|
||||
token = await redis_client.get(key)
|
||||
token_payload = jwt_decode(token)
|
||||
@@ -36,31 +54,15 @@ async def get_tokens(username: Annotated[str | None, Query()] = None) -> Respons
|
||||
os='未知',
|
||||
browser='未知',
|
||||
device='未知',
|
||||
status=StatusType.disable if session_uuid not in token_online else StatusType.enable,
|
||||
status=StatusType.enable if session_uuid in online_clients else StatusType.disable,
|
||||
last_login_time='未知',
|
||||
expire_time=token_payload.expire_time,
|
||||
)
|
||||
extra_info = await redis_client.get(f'{settings.TOKEN_EXTRA_INFO_REDIS_PREFIX}:{session_uuid}')
|
||||
if extra_info:
|
||||
|
||||
def append_token_detail():
|
||||
data.append(
|
||||
token_detail.model_copy(
|
||||
update={
|
||||
'username': extra_info.get('username'),
|
||||
'nickname': extra_info.get('nickname'),
|
||||
'ip': extra_info.get('ip'),
|
||||
'os': extra_info.get('os'),
|
||||
'browser': extra_info.get('browser'),
|
||||
'device': extra_info.get('device'),
|
||||
'last_login_time': extra_info.get('last_login_time'),
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
extra_info = json.loads(extra_info)
|
||||
if extra_info.get('login_type') != 'swagger':
|
||||
if username:
|
||||
if username is not None:
|
||||
if username == extra_info.get('username'):
|
||||
append_token_detail()
|
||||
else:
|
||||
@@ -78,7 +80,9 @@ async def get_tokens(username: Annotated[str | None, Query()] = None) -> Respons
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def kick_out(request: Request, pk: Annotated[int, Path(...)], session_uuid: KickOutToken) -> ResponseModel:
|
||||
async def kick_out(
|
||||
request: Request, pk: Annotated[int, Path(description='用户 ID')], obj: KickOutToken
|
||||
) -> ResponseModel:
|
||||
superuser_verify(request)
|
||||
await redis_client.delete(f'{settings.TOKEN_REDIS_PREFIX}:{pk}:{session_uuid}')
|
||||
await revoke_token(str(pk), obj.session_uuid)
|
||||
return response_base.success()
|
||||
|
||||
@@ -46,20 +46,24 @@ async def password_reset(request: Request, obj: ResetPasswordParam) -> ResponseM
|
||||
return response_base.fail()
|
||||
|
||||
|
||||
@router.get('/me', summary='获取当前用户信息', dependencies=[DependsJwtAuth], response_model_exclude={'password'})
|
||||
@router.get('/me', summary='获取当前用户信息', dependencies=[DependsJwtAuth])
|
||||
async def get_current_user(request: Request) -> ResponseSchemaModel[GetCurrentUserInfoWithRelationDetail]:
|
||||
data = request.user.model_dump()
|
||||
return response_base.success(data=data)
|
||||
|
||||
|
||||
@router.get('/{username}', summary='查看用户信息', dependencies=[DependsJwtAuth])
|
||||
async def get_user(username: Annotated[str, Path(...)]) -> ResponseSchemaModel[GetUserInfoWithRelationDetail]:
|
||||
async def get_user(
|
||||
username: Annotated[str, Path(description='用户名')],
|
||||
) -> ResponseSchemaModel[GetUserInfoWithRelationDetail]:
|
||||
data = await user_service.get_userinfo(username=username)
|
||||
return response_base.success(data=data)
|
||||
|
||||
|
||||
@router.put('/{username}', summary='更新用户信息', dependencies=[DependsJwtAuth])
|
||||
async def update_user(request: Request, username: Annotated[str, Path(...)], obj: UpdateUserParam) -> ResponseModel:
|
||||
async def update_user(
|
||||
request: Request, username: Annotated[str, Path(description='用户名')], obj: UpdateUserParam
|
||||
) -> ResponseModel:
|
||||
count = await user_service.update(request=request, username=username, obj=obj)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
@@ -75,14 +79,16 @@ async def update_user(request: Request, username: Annotated[str, Path(...)], obj
|
||||
],
|
||||
)
|
||||
async def update_user_role(
|
||||
request: Request, username: Annotated[str, Path(...)], obj: UpdateUserRoleParam
|
||||
request: Request, username: Annotated[str, Path(description='用户名')], obj: UpdateUserRoleParam
|
||||
) -> ResponseModel:
|
||||
await user_service.update_roles(request=request, username=username, obj=obj)
|
||||
return response_base.success()
|
||||
|
||||
|
||||
@router.put('/{username}/avatar', summary='更新头像', dependencies=[DependsJwtAuth])
|
||||
async def update_avatar(request: Request, username: Annotated[str, Path(...)], avatar: AvatarParam) -> ResponseModel:
|
||||
async def update_avatar(
|
||||
request: Request, username: Annotated[str, Path(description='用户名')], avatar: AvatarParam
|
||||
) -> ResponseModel:
|
||||
count = await user_service.update_avatar(request=request, username=username, avatar=avatar)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
@@ -91,7 +97,7 @@ async def update_avatar(request: Request, username: Annotated[str, Path(...)], a
|
||||
|
||||
@router.get(
|
||||
'',
|
||||
summary='(模糊条件)分页获取所有用户',
|
||||
summary='分页获取所有用户',
|
||||
dependencies=[
|
||||
DependsJwtAuth,
|
||||
DependsPagination,
|
||||
@@ -99,10 +105,10 @@ async def update_avatar(request: Request, username: Annotated[str, Path(...)], a
|
||||
)
|
||||
async def get_pagination_users(
|
||||
db: CurrentSession,
|
||||
dept: Annotated[int | None, Query()] = None,
|
||||
username: Annotated[str | None, Query()] = None,
|
||||
phone: Annotated[str | None, Query()] = None,
|
||||
status: Annotated[int | None, Query()] = None,
|
||||
dept: Annotated[int | None, Query(description='部门 ID')] = None,
|
||||
username: Annotated[str | None, Query(description='用户名')] = None,
|
||||
phone: Annotated[str | None, Query(description='手机号')] = None,
|
||||
status: Annotated[int | None, Query(description='状态')] = None,
|
||||
) -> ResponseSchemaModel[PageData[GetUserInfoWithRelationDetail]]:
|
||||
user_select = await user_service.get_select(dept=dept, username=username, phone=phone, status=status)
|
||||
page_data = await paging_data(db, user_select)
|
||||
@@ -110,7 +116,7 @@ async def get_pagination_users(
|
||||
|
||||
|
||||
@router.put('/{pk}/super', summary='修改用户超级权限', dependencies=[DependsRBAC])
|
||||
async def super_set(request: Request, pk: Annotated[int, Path(...)]) -> ResponseModel:
|
||||
async def super_set(request: Request, pk: Annotated[int, Path(description='用户 ID')]) -> ResponseModel:
|
||||
count = await user_service.update_permission(request=request, pk=pk)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
@@ -118,7 +124,7 @@ async def super_set(request: Request, pk: Annotated[int, Path(...)]) -> Response
|
||||
|
||||
|
||||
@router.put('/{pk}/staff', summary='修改用户后台登录权限', dependencies=[DependsRBAC])
|
||||
async def staff_set(request: Request, pk: Annotated[int, Path(...)]) -> ResponseModel:
|
||||
async def staff_set(request: Request, pk: Annotated[int, Path(description='用户 ID')]) -> ResponseModel:
|
||||
count = await user_service.update_staff(request=request, pk=pk)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
@@ -126,15 +132,15 @@ async def staff_set(request: Request, pk: Annotated[int, Path(...)]) -> Response
|
||||
|
||||
|
||||
@router.put('/{pk}/status', summary='修改用户状态', dependencies=[DependsRBAC])
|
||||
async def status_set(request: Request, pk: Annotated[int, Path(...)]) -> ResponseModel:
|
||||
async def status_set(request: Request, pk: Annotated[int, Path(description='用户 ID')]) -> ResponseModel:
|
||||
count = await user_service.update_status(request=request, pk=pk)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
return response_base.fail()
|
||||
|
||||
|
||||
@router.put('/{pk}/multi', summary='修改用户多点登录状态', dependencies=[DependsRBAC])
|
||||
async def multi_set(request: Request, pk: Annotated[int, Path(...)]) -> ResponseModel:
|
||||
@router.put('/{pk}/multi', summary='修改用户多端登录状态', dependencies=[DependsRBAC])
|
||||
async def multi_set(request: Request, pk: Annotated[int, Path(description='用户 ID')]) -> ResponseModel:
|
||||
count = await user_service.update_multi_login(request=request, pk=pk)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
@@ -150,7 +156,7 @@ async def multi_set(request: Request, pk: Annotated[int, Path(...)]) -> Response
|
||||
DependsRBAC,
|
||||
],
|
||||
)
|
||||
async def delete_user(username: Annotated[str, Path(...)]) -> ResponseModel:
|
||||
async def delete_user(username: Annotated[str, Path(description='用户名')]) -> ResponseModel:
|
||||
count = await user_service.delete(username=username)
|
||||
if count > 0:
|
||||
return response_base.success()
|
||||
|
||||
Reference in New Issue
Block a user