初始提交
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Path, Request, Response
|
||||
|
||||
from common.annotation.rate_limit_annotation import ApiRateLimit, ApiRateLimitPreset
|
||||
from common.aspect.interface_auth import UserInterfaceAuthDependency
|
||||
from common.aspect.pre_auth import PreAuthDependency
|
||||
from common.constant import ApiNamespace
|
||||
from common.router import APIRouterPro
|
||||
from common.vo import DataResponseModel, ResponseBaseModel
|
||||
from module_admin.entity.vo.cache_vo import CacheInfoModel, CacheMonitorModel
|
||||
from module_admin.service.cache_service import CacheService
|
||||
from utils.log_util import logger
|
||||
from utils.response_util import ResponseUtil
|
||||
|
||||
cache_controller = APIRouterPro(
|
||||
prefix='/monitor/cache', order_num=15, tags=['系统监控-缓存监控'], dependencies=[PreAuthDependency()]
|
||||
)
|
||||
|
||||
|
||||
@cache_controller.get(
|
||||
'',
|
||||
summary='获取缓存监控信息接口',
|
||||
description='用于获取缓存监控信息',
|
||||
response_model=DataResponseModel[CacheMonitorModel],
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:cache:list')],
|
||||
)
|
||||
async def get_monitor_cache_info(request: Request) -> Response:
|
||||
# 获取全量数据
|
||||
cache_info_query_result = await CacheService.get_cache_monitor_statistical_info_services(request)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(data=cache_info_query_result)
|
||||
|
||||
|
||||
@cache_controller.get(
|
||||
'/getNames',
|
||||
summary='获取缓存名称列表接口',
|
||||
description='用于获取缓存名称列表',
|
||||
response_model=DataResponseModel[list[CacheInfoModel]],
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:cache:list')],
|
||||
)
|
||||
async def get_monitor_cache_name(request: Request) -> Response:
|
||||
# 获取全量数据
|
||||
cache_name_list_result = await CacheService.get_cache_monitor_cache_name_services()
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(data=cache_name_list_result)
|
||||
|
||||
|
||||
@cache_controller.get(
|
||||
'/getKeys/{cache_name}',
|
||||
summary='获取缓存键列表接口',
|
||||
description='用于获取指定缓存名称下的所有缓存键列表',
|
||||
response_model=DataResponseModel[list[str]],
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:cache:list')],
|
||||
)
|
||||
async def get_monitor_cache_key(request: Request, cache_name: Annotated[str, Path(description='缓存名称')]) -> Response:
|
||||
# 获取全量数据
|
||||
cache_key_list_result = await CacheService.get_cache_monitor_cache_key_services(request, cache_name)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(data=cache_key_list_result)
|
||||
|
||||
|
||||
@cache_controller.get(
|
||||
'/getValue/{cache_name}/{cache_key}',
|
||||
summary='获取缓存值接口',
|
||||
description='用于获取指定缓存名称下的指定缓存键对应的值',
|
||||
response_model=DataResponseModel[CacheInfoModel],
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:cache:list')],
|
||||
)
|
||||
async def get_monitor_cache_value(
|
||||
request: Request,
|
||||
cache_name: Annotated[str, Path(description='缓存名称')],
|
||||
cache_key: Annotated[str, Path(description='缓存键')],
|
||||
) -> Response:
|
||||
# 获取全量数据
|
||||
cache_value_list_result = await CacheService.get_cache_monitor_cache_value_services(request, cache_name, cache_key)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(data=cache_value_list_result)
|
||||
|
||||
|
||||
@cache_controller.delete(
|
||||
'/clearCacheName/{cache_name}',
|
||||
summary='清除缓存名称接口',
|
||||
description='用于清除指定缓存名称下的所有缓存键值对',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:cache:list')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.MONITOR_CACHE_CLEAR_NAME, preset=ApiRateLimitPreset.USER_DESTRUCTIVE_MUTATION)
|
||||
async def clear_monitor_cache_name(
|
||||
request: Request, cache_name: Annotated[str, Path(description='缓存名称')]
|
||||
) -> Response:
|
||||
clear_cache_name_result = await CacheService.clear_cache_monitor_cache_name_services(request, cache_name)
|
||||
logger.info(clear_cache_name_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=clear_cache_name_result.message)
|
||||
|
||||
|
||||
@cache_controller.delete(
|
||||
'/clearCacheKey/{cache_key}',
|
||||
summary='清除缓存键接口',
|
||||
description='用于清除指定缓存键对应的值',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:cache:list')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.MONITOR_CACHE_CLEAR_KEY, preset=ApiRateLimitPreset.USER_DESTRUCTIVE_MUTATION)
|
||||
async def clear_monitor_cache_key(request: Request, cache_key: Annotated[str, Path(description='缓存键')]) -> Response:
|
||||
clear_cache_key_result = await CacheService.clear_cache_monitor_cache_key_services(request, cache_key)
|
||||
logger.info(clear_cache_key_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=clear_cache_key_result.message)
|
||||
|
||||
|
||||
@cache_controller.delete(
|
||||
'/clearCacheAll',
|
||||
summary='清除所有缓存接口',
|
||||
description='用于清除所有缓存键值对',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:cache:list')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.MONITOR_CACHE_CLEAR_ALL, preset=ApiRateLimitPreset.USER_DESTRUCTIVE_MUTATION)
|
||||
async def clear_monitor_cache_all(request: Request) -> Response:
|
||||
clear_cache_all_result = await CacheService.clear_cache_monitor_all_services(request)
|
||||
logger.info(clear_cache_all_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=clear_cache_all_result.message)
|
||||
@@ -0,0 +1,46 @@
|
||||
import uuid
|
||||
from datetime import timedelta
|
||||
|
||||
from fastapi import Request, Response
|
||||
|
||||
from common.annotation.rate_limit_annotation import ApiRateLimit, ApiRateLimitPreset
|
||||
from common.constant import ApiNamespace
|
||||
from common.enums import RedisInitKeyConfig
|
||||
from common.router import APIRouterPro
|
||||
from common.vo import DynamicResponseModel
|
||||
from module_admin.entity.vo.login_vo import CaptchaCode
|
||||
from module_admin.service.captcha_service import CaptchaService
|
||||
from utils.log_util import logger
|
||||
from utils.response_util import ResponseUtil
|
||||
|
||||
captcha_controller = APIRouterPro(order_num=2, tags=['验证码模块'])
|
||||
|
||||
|
||||
@captcha_controller.get(
|
||||
'/captchaImage',
|
||||
summary='获取图片验证码接口',
|
||||
description='用于获取图片验证码',
|
||||
response_model=DynamicResponseModel[CaptchaCode],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.CAPTCHA_IMAGE, preset=ApiRateLimitPreset.ANON_AUTH_CAPTCHA)
|
||||
async def get_captcha_image(request: Request) -> Response:
|
||||
captcha_enabled = (
|
||||
await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.account.captchaEnabled') == 'true'
|
||||
)
|
||||
register_enabled = (
|
||||
await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.account.registerUser') == 'true'
|
||||
)
|
||||
session_id = str(uuid.uuid4())
|
||||
captcha_result = await CaptchaService.create_captcha_image_service()
|
||||
image = captcha_result[0]
|
||||
computed_result = captcha_result[1]
|
||||
await request.app.state.redis.set(
|
||||
f'{RedisInitKeyConfig.CAPTCHA_CODES.key}:{session_id}', computed_result, ex=timedelta(minutes=2)
|
||||
)
|
||||
logger.info(f'编号为{session_id}的会话获取图片验证码成功')
|
||||
|
||||
return ResponseUtil.success(
|
||||
model_content=CaptchaCode(
|
||||
captchaEnabled=captcha_enabled, registerEnabled=register_enabled, img=image, uuid=session_id
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,77 @@
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import BackgroundTasks, File, Query, Request, Response, UploadFile
|
||||
from fastapi.responses import StreamingResponse
|
||||
|
||||
from common.annotation.rate_limit_annotation import ApiRateLimit, ApiRateLimitPreset
|
||||
from common.aspect.pre_auth import PreAuthDependency
|
||||
from common.constant import ApiNamespace
|
||||
from common.router import APIRouterPro
|
||||
from common.vo import DynamicResponseModel
|
||||
from module_admin.entity.vo.common_vo import UploadResponseModel
|
||||
from module_admin.service.common_service import CommonService
|
||||
from utils.log_util import logger
|
||||
from utils.response_util import ResponseUtil
|
||||
|
||||
common_controller = APIRouterPro(prefix='/common', order_num=16, tags=['通用模块'], dependencies=[PreAuthDependency()])
|
||||
|
||||
|
||||
@common_controller.post(
|
||||
'/upload',
|
||||
summary='通用文件上传接口',
|
||||
description='用于上传文件',
|
||||
response_model=DynamicResponseModel[UploadResponseModel],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.COMMON_UPLOAD, preset=ApiRateLimitPreset.COMMON_UPLOAD)
|
||||
async def common_upload(request: Request, file: Annotated[UploadFile, File(...)]) -> Response:
|
||||
upload_result = await CommonService.upload_service(request, file)
|
||||
logger.info('上传成功')
|
||||
|
||||
return ResponseUtil.success(model_content=upload_result.result)
|
||||
|
||||
|
||||
@common_controller.get(
|
||||
'/download',
|
||||
summary='通用文件下载接口',
|
||||
description='用于下载下载目录中的文件',
|
||||
response_class=StreamingResponse,
|
||||
responses={
|
||||
200: {
|
||||
'description': '流式返回文件',
|
||||
'content': {
|
||||
'application/octet-stream': {},
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
async def common_download(
|
||||
request: Request,
|
||||
background_tasks: BackgroundTasks,
|
||||
file_name: Annotated[str, Query(alias='fileName')],
|
||||
delete: Annotated[bool, Query()],
|
||||
) -> Response:
|
||||
download_result = await CommonService.download_services(background_tasks, file_name, delete)
|
||||
logger.info(download_result.message)
|
||||
|
||||
return ResponseUtil.streaming(data=download_result.result)
|
||||
|
||||
|
||||
@common_controller.get(
|
||||
'/download/resource',
|
||||
summary='通用资源文件下载接口',
|
||||
description='用于下载上传目录中的资源文件',
|
||||
response_class=StreamingResponse,
|
||||
responses={
|
||||
200: {
|
||||
'description': '流式返回文件',
|
||||
'content': {
|
||||
'application/octet-stream': {},
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
async def common_download_resource(request: Request, resource: Annotated[str, Query()]) -> Response:
|
||||
download_resource_result = await CommonService.download_resource_services(resource)
|
||||
logger.info(download_resource_result.message)
|
||||
|
||||
return ResponseUtil.streaming(data=download_resource_result.result)
|
||||
@@ -0,0 +1,201 @@
|
||||
from datetime import datetime
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Form, Path, Query, Request, Response
|
||||
from fastapi.responses import StreamingResponse
|
||||
from pydantic_validation_decorator import ValidateFields
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.annotation.cache_annotation import ApiCache, ApiCacheEvict
|
||||
from common.annotation.log_annotation import Log
|
||||
from common.annotation.rate_limit_annotation import ApiRateLimit, ApiRateLimitPreset
|
||||
from common.aspect.db_seesion import DBSessionDependency
|
||||
from common.aspect.interface_auth import UserInterfaceAuthDependency
|
||||
from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency
|
||||
from common.constant import ApiGroup, ApiNamespace
|
||||
from common.enums import BusinessType
|
||||
from common.router import APIRouterPro
|
||||
from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel
|
||||
from module_admin.entity.vo.config_vo import ConfigModel, ConfigPageQueryModel, DeleteConfigModel
|
||||
from module_admin.entity.vo.user_vo import CurrentUserModel
|
||||
from module_admin.service.config_service import ConfigService
|
||||
from utils.common_util import bytes2file_response
|
||||
from utils.log_util import logger
|
||||
from utils.response_util import ResponseUtil
|
||||
|
||||
config_controller = APIRouterPro(
|
||||
prefix='/system/config', order_num=9, tags=['系统管理-参数管理'], dependencies=[PreAuthDependency()]
|
||||
)
|
||||
|
||||
|
||||
@config_controller.get(
|
||||
'/list',
|
||||
summary='获取参数分页列表接口',
|
||||
description='用于获取参数分页列表',
|
||||
response_model=PageResponseModel[ConfigModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:config:list')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_CONFIG_LIST)
|
||||
async def get_system_config_list(
|
||||
request: Request,
|
||||
config_page_query: Annotated[ConfigPageQueryModel, Query()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取分页数据
|
||||
config_page_query_result = await ConfigService.get_config_list_services(query_db, config_page_query, is_page=True)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(model_content=config_page_query_result)
|
||||
|
||||
|
||||
@config_controller.post(
|
||||
'',
|
||||
summary='新增参数接口',
|
||||
description='用于新增参数',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:config:add')],
|
||||
)
|
||||
@ValidateFields(validate_model='add_config')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.CONFIG_MUTATION)
|
||||
@Log(title='参数管理', business_type=BusinessType.INSERT)
|
||||
async def add_system_config(
|
||||
request: Request,
|
||||
add_config: ConfigModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
add_config.create_by = current_user.user.user_name
|
||||
add_config.create_time = datetime.now()
|
||||
add_config.update_by = current_user.user.user_name
|
||||
add_config.update_time = datetime.now()
|
||||
add_config_result = await ConfigService.add_config_services(request, query_db, add_config)
|
||||
logger.info(add_config_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=add_config_result.message)
|
||||
|
||||
|
||||
@config_controller.put(
|
||||
'',
|
||||
summary='编辑参数接口',
|
||||
description='用于编辑参数',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:config:edit')],
|
||||
)
|
||||
@ValidateFields(validate_model='edit_config')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.CONFIG_MUTATION)
|
||||
@Log(title='参数管理', business_type=BusinessType.UPDATE)
|
||||
async def edit_system_config(
|
||||
request: Request,
|
||||
edit_config: ConfigModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
edit_config.update_by = current_user.user.user_name
|
||||
edit_config.update_time = datetime.now()
|
||||
edit_config_result = await ConfigService.edit_config_services(request, query_db, edit_config)
|
||||
logger.info(edit_config_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=edit_config_result.message)
|
||||
|
||||
|
||||
@config_controller.delete(
|
||||
'/refreshCache',
|
||||
summary='刷新参数缓存接口',
|
||||
description='用于刷新参数缓存',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:config:remove')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.SYSTEM_CONFIG_REFRESH_CACHE, preset=ApiRateLimitPreset.USER_COMMON_MUTATION)
|
||||
@Log(title='参数管理', business_type=BusinessType.UPDATE)
|
||||
async def refresh_system_config(
|
||||
request: Request,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
refresh_config_result = await ConfigService.refresh_sys_config_services(request, query_db)
|
||||
logger.info(refresh_config_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=refresh_config_result.message)
|
||||
|
||||
|
||||
@config_controller.delete(
|
||||
'/{config_ids}',
|
||||
summary='删除参数接口',
|
||||
description='用于删除参数',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:config:remove')],
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.CONFIG_MUTATION)
|
||||
@Log(title='参数管理', business_type=BusinessType.DELETE)
|
||||
async def delete_system_config(
|
||||
request: Request,
|
||||
config_ids: Annotated[str, Path(description='需要删除的参数主键')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
delete_config = DeleteConfigModel(configIds=config_ids)
|
||||
delete_config_result = await ConfigService.delete_config_services(request, query_db, delete_config)
|
||||
logger.info(delete_config_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=delete_config_result.message)
|
||||
|
||||
|
||||
@config_controller.get(
|
||||
'/{config_id}',
|
||||
summary='获取参数详情接口',
|
||||
description='用于获取指定参数的详细信息',
|
||||
response_model=DataResponseModel[ConfigModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:config:query')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_CONFIG_DETAIL)
|
||||
async def query_detail_system_config(
|
||||
request: Request,
|
||||
config_id: Annotated[int, Path(description='参数主键')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
config_detail_result = await ConfigService.config_detail_services(query_db, config_id)
|
||||
logger.info(f'获取config_id为{config_id}的信息成功')
|
||||
|
||||
return ResponseUtil.success(data=config_detail_result)
|
||||
|
||||
|
||||
@config_controller.get(
|
||||
'/configKey/{config_key}',
|
||||
summary='根据参数键查询参数值接口',
|
||||
description='用于根据参数键从缓存中查询参数值',
|
||||
response_model=ResponseBaseModel,
|
||||
)
|
||||
async def query_system_config(request: Request, config_key: str) -> Response:
|
||||
# 获取全量数据
|
||||
config_query_result = await ConfigService.query_config_list_from_cache_services(request.app.state.redis, config_key)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(msg=config_query_result)
|
||||
|
||||
|
||||
@config_controller.post(
|
||||
'/export',
|
||||
summary='导出参数列表接口',
|
||||
description='用于导出当前符合查询条件的参数列表数据',
|
||||
response_class=StreamingResponse,
|
||||
responses={
|
||||
200: {
|
||||
'description': '流式返回参数列表excel文件',
|
||||
'content': {
|
||||
'application/octet-stream': {},
|
||||
},
|
||||
}
|
||||
},
|
||||
dependencies=[UserInterfaceAuthDependency('system:config:export')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.SYSTEM_CONFIG_EXPORT, preset=ApiRateLimitPreset.USER_RESOURCE_EXPORT)
|
||||
@Log(title='参数管理', business_type=BusinessType.EXPORT)
|
||||
async def export_system_config_list(
|
||||
request: Request,
|
||||
config_page_query: Annotated[ConfigPageQueryModel, Form()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取全量数据
|
||||
config_query_result = await ConfigService.get_config_list_services(query_db, config_page_query, is_page=False)
|
||||
config_export_result = await ConfigService.export_config_list_services(config_query_result)
|
||||
logger.info('导出成功')
|
||||
|
||||
return ResponseUtil.streaming(data=bytes2file_response(config_export_result))
|
||||
@@ -0,0 +1,175 @@
|
||||
from datetime import datetime
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Path, Query, Request, Response
|
||||
from pydantic_validation_decorator import ValidateFields
|
||||
from sqlalchemy import ColumnElement
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.annotation.cache_annotation import ApiCache, ApiCacheEvict
|
||||
from common.annotation.log_annotation import Log
|
||||
from common.aspect.data_scope import DataScopeDependency
|
||||
from common.aspect.db_seesion import DBSessionDependency
|
||||
from common.aspect.interface_auth import UserInterfaceAuthDependency
|
||||
from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency
|
||||
from common.constant import ApiGroup, ApiNamespace
|
||||
from common.enums import BusinessType
|
||||
from common.router import APIRouterPro
|
||||
from common.vo import DataResponseModel, ResponseBaseModel
|
||||
from module_admin.entity.do.dept_do import SysDept
|
||||
from module_admin.entity.vo.dept_vo import DeleteDeptModel, DeptModel, DeptQueryModel
|
||||
from module_admin.entity.vo.user_vo import CurrentUserModel
|
||||
from module_admin.service.dept_service import DeptService
|
||||
from utils.log_util import logger
|
||||
from utils.response_util import ResponseUtil
|
||||
|
||||
dept_controller = APIRouterPro(
|
||||
prefix='/system/dept', order_num=6, tags=['系统管理-部门管理'], dependencies=[PreAuthDependency()]
|
||||
)
|
||||
|
||||
|
||||
@dept_controller.get(
|
||||
'/list/exclude/{dept_id}',
|
||||
summary='获取编辑部门的下拉树接口',
|
||||
description='用于获取部门下拉树,不包含指定部门及其子部门',
|
||||
response_model=DataResponseModel[list[DeptModel]],
|
||||
dependencies=[UserInterfaceAuthDependency('system:dept:list')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_DEPT_EDIT_TREE)
|
||||
async def get_system_dept_tree_for_edit_option(
|
||||
request: Request,
|
||||
dept_id: Annotated[int, Path(description='部门id')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
dept_query = DeptModel(deptId=dept_id)
|
||||
dept_query_result = await DeptService.get_dept_for_edit_option_services(query_db, dept_query, data_scope_sql)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(data=dept_query_result)
|
||||
|
||||
|
||||
@dept_controller.get(
|
||||
'/list',
|
||||
summary='获取部门列表接口',
|
||||
description='用于获取部门列表',
|
||||
response_model=DataResponseModel[list[DeptModel]],
|
||||
dependencies=[UserInterfaceAuthDependency('system:dept:list')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_DEPT_LIST)
|
||||
async def get_system_dept_list(
|
||||
request: Request,
|
||||
dept_query: Annotated[DeptQueryModel, Query()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
dept_query_result = await DeptService.get_dept_list_services(query_db, dept_query, data_scope_sql)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(data=dept_query_result)
|
||||
|
||||
|
||||
@dept_controller.post(
|
||||
'',
|
||||
summary='新增部门接口',
|
||||
description='用于新增部门',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:dept:add')],
|
||||
)
|
||||
@ValidateFields(validate_model='add_dept')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.DATA_SCOPE_MUTATION)
|
||||
@Log(title='部门管理', business_type=BusinessType.INSERT)
|
||||
async def add_system_dept(
|
||||
request: Request,
|
||||
add_dept: DeptModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
add_dept.create_by = current_user.user.user_name
|
||||
add_dept.create_time = datetime.now()
|
||||
add_dept.update_by = current_user.user.user_name
|
||||
add_dept.update_time = datetime.now()
|
||||
add_dept_result = await DeptService.add_dept_services(query_db, add_dept)
|
||||
logger.info(add_dept_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=add_dept_result.message)
|
||||
|
||||
|
||||
@dept_controller.put(
|
||||
'',
|
||||
summary='编辑部门接口',
|
||||
description='用于编辑部门',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:dept:edit')],
|
||||
)
|
||||
@ValidateFields(validate_model='edit_dept')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.DATA_SCOPE_MUTATION)
|
||||
@Log(title='部门管理', business_type=BusinessType.UPDATE)
|
||||
async def edit_system_dept(
|
||||
request: Request,
|
||||
edit_dept: DeptModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
if not current_user.user.admin:
|
||||
await DeptService.check_dept_data_scope_services(query_db, edit_dept.dept_id, data_scope_sql)
|
||||
edit_dept.update_by = current_user.user.user_name
|
||||
edit_dept.update_time = datetime.now()
|
||||
edit_dept_result = await DeptService.edit_dept_services(query_db, edit_dept)
|
||||
logger.info(edit_dept_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=edit_dept_result.message)
|
||||
|
||||
|
||||
@dept_controller.delete(
|
||||
'/{dept_ids}',
|
||||
summary='删除部门接口',
|
||||
description='用于删除部门',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:dept:remove')],
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.DATA_SCOPE_MUTATION)
|
||||
@Log(title='部门管理', business_type=BusinessType.DELETE)
|
||||
async def delete_system_dept(
|
||||
request: Request,
|
||||
dept_ids: Annotated[str, Path(description='需要删除的部门id')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
dept_id_list = dept_ids.split(',') if dept_ids else []
|
||||
if dept_id_list:
|
||||
for dept_id in dept_id_list:
|
||||
if not current_user.user.admin:
|
||||
await DeptService.check_dept_data_scope_services(query_db, int(dept_id), data_scope_sql)
|
||||
delete_dept = DeleteDeptModel(deptIds=dept_ids)
|
||||
delete_dept.update_by = current_user.user.user_name
|
||||
delete_dept.update_time = datetime.now()
|
||||
delete_dept_result = await DeptService.delete_dept_services(query_db, delete_dept)
|
||||
logger.info(delete_dept_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=delete_dept_result.message)
|
||||
|
||||
|
||||
@dept_controller.get(
|
||||
'/{dept_id}',
|
||||
summary='获取部门详情接口',
|
||||
description='用于获取指定部门的详情信息',
|
||||
response_model=DataResponseModel[DeptModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:dept:query')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_DEPT_DETAIL)
|
||||
async def query_detail_system_dept(
|
||||
request: Request,
|
||||
dept_id: Annotated[int, Path(description='部门id')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
if not current_user.user.admin:
|
||||
await DeptService.check_dept_data_scope_services(query_db, dept_id, data_scope_sql)
|
||||
detail_dept_result = await DeptService.dept_detail_services(query_db, dept_id)
|
||||
logger.info(f'获取dept_id为{dept_id}的信息成功')
|
||||
|
||||
return ResponseUtil.success(data=detail_dept_result)
|
||||
@@ -0,0 +1,377 @@
|
||||
from datetime import datetime
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Form, Path, Query, Request, Response
|
||||
from fastapi.responses import StreamingResponse
|
||||
from pydantic_validation_decorator import ValidateFields
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.annotation.cache_annotation import ApiCache, ApiCacheEvict
|
||||
from common.annotation.log_annotation import Log
|
||||
from common.annotation.rate_limit_annotation import ApiRateLimit, ApiRateLimitPreset
|
||||
from common.aspect.db_seesion import DBSessionDependency
|
||||
from common.aspect.interface_auth import UserInterfaceAuthDependency
|
||||
from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency
|
||||
from common.constant import ApiGroup, ApiNamespace
|
||||
from common.enums import BusinessType
|
||||
from common.router import APIRouterPro
|
||||
from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel
|
||||
from module_admin.entity.vo.dict_vo import (
|
||||
DeleteDictDataModel,
|
||||
DeleteDictTypeModel,
|
||||
DictDataModel,
|
||||
DictDataPageQueryModel,
|
||||
DictTypeModel,
|
||||
DictTypePageQueryModel,
|
||||
)
|
||||
from module_admin.entity.vo.user_vo import CurrentUserModel
|
||||
from module_admin.service.dict_service import DictDataService, DictTypeService
|
||||
from utils.common_util import bytes2file_response
|
||||
from utils.log_util import logger
|
||||
from utils.response_util import ResponseUtil
|
||||
|
||||
dict_controller = APIRouterPro(
|
||||
prefix='/system/dict', order_num=8, tags=['系统管理-字典管理'], dependencies=[PreAuthDependency()]
|
||||
)
|
||||
|
||||
|
||||
@dict_controller.get(
|
||||
'/type/list',
|
||||
summary='获取字典类型分页列表接口',
|
||||
description='用于获取字典类型分页列表',
|
||||
response_model=PageResponseModel[DictTypeModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:dict:list')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_DICT_TYPE_LIST)
|
||||
async def get_system_dict_type_list(
|
||||
request: Request,
|
||||
dict_type_page_query: Annotated[DictTypePageQueryModel, Query()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取分页数据
|
||||
dict_type_page_query_result = await DictTypeService.get_dict_type_list_services(
|
||||
query_db, dict_type_page_query, is_page=True
|
||||
)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(model_content=dict_type_page_query_result)
|
||||
|
||||
|
||||
@dict_controller.post(
|
||||
'/type',
|
||||
summary='新增字典类型接口',
|
||||
description='用于新增字典类型',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:dict:add')],
|
||||
)
|
||||
@ValidateFields(validate_model='add_dict_type')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.DICT_TYPE_MUTATION)
|
||||
@Log(title='字典类型', business_type=BusinessType.INSERT)
|
||||
async def add_system_dict_type(
|
||||
request: Request,
|
||||
add_dict_type: DictTypeModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
add_dict_type.create_by = current_user.user.user_name
|
||||
add_dict_type.create_time = datetime.now()
|
||||
add_dict_type.update_by = current_user.user.user_name
|
||||
add_dict_type.update_time = datetime.now()
|
||||
add_dict_type_result = await DictTypeService.add_dict_type_services(request, query_db, add_dict_type)
|
||||
logger.info(add_dict_type_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=add_dict_type_result.message)
|
||||
|
||||
|
||||
@dict_controller.put(
|
||||
'/type',
|
||||
summary='编辑字典类型接口',
|
||||
description='用于编辑字典类型',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:dict:edit')],
|
||||
)
|
||||
@ValidateFields(validate_model='edit_dict_type')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.DICT_TYPE_MUTATION)
|
||||
@Log(title='字典类型', business_type=BusinessType.UPDATE)
|
||||
async def edit_system_dict_type(
|
||||
request: Request,
|
||||
edit_dict_type: DictTypeModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
edit_dict_type.update_by = current_user.user.user_name
|
||||
edit_dict_type.update_time = datetime.now()
|
||||
edit_dict_type_result = await DictTypeService.edit_dict_type_services(request, query_db, edit_dict_type)
|
||||
logger.info(edit_dict_type_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=edit_dict_type_result.message)
|
||||
|
||||
|
||||
@dict_controller.delete(
|
||||
'/type/refreshCache',
|
||||
summary='刷新字典缓存接口',
|
||||
description='用于刷新字典缓存',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:dict:remove')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.SYSTEM_DICT_REFRESH_CACHE, preset=ApiRateLimitPreset.USER_COMMON_MUTATION)
|
||||
@Log(title='字典类型', business_type=BusinessType.UPDATE)
|
||||
async def refresh_system_dict(request: Request, query_db: Annotated[AsyncSession, DBSessionDependency()]) -> Response:
|
||||
refresh_dict_result = await DictTypeService.refresh_sys_dict_services(request, query_db)
|
||||
logger.info(refresh_dict_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=refresh_dict_result.message)
|
||||
|
||||
|
||||
@dict_controller.delete(
|
||||
'/type/{dict_ids}',
|
||||
summary='删除字典类型接口',
|
||||
description='用于删除字典类型',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:dict:remove')],
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.DICT_TYPE_MUTATION)
|
||||
@Log(title='字典类型', business_type=BusinessType.DELETE)
|
||||
async def delete_system_dict_type(
|
||||
request: Request,
|
||||
dict_ids: Annotated[str, Path(description='需要删除的字典主键')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
delete_dict_type = DeleteDictTypeModel(dictIds=dict_ids)
|
||||
delete_dict_type_result = await DictTypeService.delete_dict_type_services(request, query_db, delete_dict_type)
|
||||
logger.info(delete_dict_type_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=delete_dict_type_result.message)
|
||||
|
||||
|
||||
@dict_controller.get(
|
||||
'/type/optionselect',
|
||||
summary='获取字典类型下拉列表接口',
|
||||
description='用于获取字典类型下拉列表',
|
||||
response_model=DataResponseModel[list[DictTypeModel]],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_DICT_TYPE_OPTIONS)
|
||||
async def query_system_dict_type_options(
|
||||
request: Request, query_db: Annotated[AsyncSession, DBSessionDependency()]
|
||||
) -> Response:
|
||||
dict_type_query_result = await DictTypeService.get_dict_type_list_services(
|
||||
query_db, DictTypePageQueryModel(), is_page=False
|
||||
)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(data=dict_type_query_result)
|
||||
|
||||
|
||||
@dict_controller.get(
|
||||
'/type/{dict_id}',
|
||||
summary='获取字典类型详情接口',
|
||||
description='用于获取指定字典类型的详细信息',
|
||||
response_model=DataResponseModel[DictTypeModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:dict:query')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_DICT_TYPE_DETAIL)
|
||||
async def query_detail_system_dict_type(
|
||||
request: Request,
|
||||
dict_id: Annotated[int, Path(description='字典主键')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
dict_type_detail_result = await DictTypeService.dict_type_detail_services(query_db, dict_id)
|
||||
logger.info(f'获取dict_id为{dict_id}的信息成功')
|
||||
|
||||
return ResponseUtil.success(data=dict_type_detail_result)
|
||||
|
||||
|
||||
@dict_controller.post(
|
||||
'/type/export',
|
||||
summary='导出字典类型列表接口',
|
||||
description='用于导出当前符合查询条件的字典类型列表数据',
|
||||
response_class=StreamingResponse,
|
||||
responses={
|
||||
200: {
|
||||
'description': '流式返回字典类型列表excel文件',
|
||||
'content': {
|
||||
'application/octet-stream': {},
|
||||
},
|
||||
}
|
||||
},
|
||||
dependencies=[UserInterfaceAuthDependency('system:dict:export')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.SYSTEM_DICT_TYPE_EXPORT, preset=ApiRateLimitPreset.USER_RESOURCE_EXPORT)
|
||||
@Log(title='字典类型', business_type=BusinessType.EXPORT)
|
||||
async def export_system_dict_type_list(
|
||||
request: Request,
|
||||
dict_type_page_query: Annotated[DictTypePageQueryModel, Form()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取全量数据
|
||||
dict_type_query_result = await DictTypeService.get_dict_type_list_services(
|
||||
query_db, dict_type_page_query, is_page=False
|
||||
)
|
||||
dict_type_export_result = await DictTypeService.export_dict_type_list_services(dict_type_query_result)
|
||||
logger.info('导出成功')
|
||||
|
||||
return ResponseUtil.streaming(data=bytes2file_response(dict_type_export_result))
|
||||
|
||||
|
||||
@dict_controller.get(
|
||||
'/data/type/{dict_type}',
|
||||
summary='获取指定字典类型的数据列表接口',
|
||||
description='用于从缓存中获取指定字典类型的所有数据项',
|
||||
response_model=DataResponseModel[list[DictDataModel]],
|
||||
)
|
||||
async def query_system_dict_type_data(
|
||||
request: Request,
|
||||
dict_type: Annotated[str, Path(description='字典类型')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取全量数据
|
||||
dict_data_query_result = await DictDataService.query_dict_data_list_from_cache_services(
|
||||
request.app.state.redis, dict_type
|
||||
)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(data=dict_data_query_result)
|
||||
|
||||
|
||||
@dict_controller.get(
|
||||
'/data/list',
|
||||
summary='获取字典数据分页列表接口',
|
||||
description='用于获取字典数据分页列表',
|
||||
response_model=PageResponseModel[DictDataModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:dict:list')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_DICT_DATA_LIST)
|
||||
async def get_system_dict_data_list(
|
||||
request: Request,
|
||||
dict_data_page_query: Annotated[DictDataPageQueryModel, Query()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取分页数据
|
||||
dict_data_page_query_result = await DictDataService.get_dict_data_list_services(
|
||||
query_db, dict_data_page_query, is_page=True
|
||||
)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(model_content=dict_data_page_query_result)
|
||||
|
||||
|
||||
@dict_controller.post(
|
||||
'/data',
|
||||
summary='新增字典数据接口',
|
||||
description='用于新增字典数据',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:dict:add')],
|
||||
)
|
||||
@ValidateFields(validate_model='add_dict_data')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.DICT_DATA_MUTATION)
|
||||
@Log(title='字典数据', business_type=BusinessType.INSERT)
|
||||
async def add_system_dict_data(
|
||||
request: Request,
|
||||
add_dict_data: DictDataModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
add_dict_data.create_by = current_user.user.user_name
|
||||
add_dict_data.create_time = datetime.now()
|
||||
add_dict_data.update_by = current_user.user.user_name
|
||||
add_dict_data.update_time = datetime.now()
|
||||
add_dict_data_result = await DictDataService.add_dict_data_services(request, query_db, add_dict_data)
|
||||
logger.info(add_dict_data_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=add_dict_data_result.message)
|
||||
|
||||
|
||||
@dict_controller.put(
|
||||
'/data',
|
||||
summary='编辑字典数据接口',
|
||||
description='用于编辑字典数据',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:dict:edit')],
|
||||
)
|
||||
@ValidateFields(validate_model='edit_dict_data')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.DICT_DATA_MUTATION)
|
||||
@Log(title='字典数据', business_type=BusinessType.UPDATE)
|
||||
async def edit_system_dict_data(
|
||||
request: Request,
|
||||
edit_dict_data: DictDataModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
edit_dict_data.update_by = current_user.user.user_name
|
||||
edit_dict_data.update_time = datetime.now()
|
||||
edit_dict_data_result = await DictDataService.edit_dict_data_services(request, query_db, edit_dict_data)
|
||||
logger.info(edit_dict_data_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=edit_dict_data_result.message)
|
||||
|
||||
|
||||
@dict_controller.delete(
|
||||
'/data/{dict_codes}',
|
||||
summary='删除字典数据接口',
|
||||
description='用于删除字典数据',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:dict:remove')],
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.DICT_DATA_MUTATION)
|
||||
@Log(title='字典数据', business_type=BusinessType.DELETE)
|
||||
async def delete_system_dict_data(
|
||||
request: Request,
|
||||
dict_codes: Annotated[str, Path(description='需要删除的字典编码')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
delete_dict_data = DeleteDictDataModel(dictCodes=dict_codes)
|
||||
delete_dict_data_result = await DictDataService.delete_dict_data_services(request, query_db, delete_dict_data)
|
||||
logger.info(delete_dict_data_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=delete_dict_data_result.message)
|
||||
|
||||
|
||||
@dict_controller.get(
|
||||
'/data/{dict_code}',
|
||||
summary='获取字典数据详情接口',
|
||||
description='用于获取指定字典数据的详细信息',
|
||||
response_model=DataResponseModel[DictDataModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:dict:query')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_DICT_DATA_DETAIL)
|
||||
async def query_detail_system_dict_data(
|
||||
request: Request,
|
||||
dict_code: Annotated[int, Path(description='字典编码')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
detail_dict_data_result = await DictDataService.dict_data_detail_services(query_db, dict_code)
|
||||
logger.info(f'获取dict_code为{dict_code}的信息成功')
|
||||
|
||||
return ResponseUtil.success(data=detail_dict_data_result)
|
||||
|
||||
|
||||
@dict_controller.post(
|
||||
'/data/export',
|
||||
summary='导出字典数据列表接口',
|
||||
description='用于导出当前符合查询条件的字典数据列表数据',
|
||||
response_class=StreamingResponse,
|
||||
responses={
|
||||
200: {
|
||||
'description': '流式返回字典数据列表excel文件',
|
||||
'content': {
|
||||
'application/octet-stream': {},
|
||||
},
|
||||
}
|
||||
},
|
||||
dependencies=[UserInterfaceAuthDependency('system:dict:export')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.SYSTEM_DICT_DATA_EXPORT, preset=ApiRateLimitPreset.USER_RESOURCE_EXPORT)
|
||||
@Log(title='字典数据', business_type=BusinessType.EXPORT)
|
||||
async def export_system_dict_data_list(
|
||||
request: Request,
|
||||
dict_data_page_query: Annotated[DictDataPageQueryModel, Form()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取全量数据
|
||||
dict_data_query_result = await DictDataService.get_dict_data_list_services(
|
||||
query_db, dict_data_page_query, is_page=False
|
||||
)
|
||||
dict_data_export_result = await DictDataService.export_dict_data_list_services(dict_data_query_result)
|
||||
logger.info('导出成功')
|
||||
|
||||
return ResponseUtil.streaming(data=bytes2file_response(dict_data_export_result))
|
||||
@@ -0,0 +1,318 @@
|
||||
from datetime import datetime
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Form, Path, Query, Request, Response
|
||||
from fastapi.responses import StreamingResponse
|
||||
from pydantic_validation_decorator import ValidateFields
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.annotation.cache_annotation import ApiCache, ApiCacheEvict
|
||||
from common.annotation.log_annotation import Log
|
||||
from common.annotation.rate_limit_annotation import ApiRateLimit, ApiRateLimitPreset
|
||||
from common.aspect.db_seesion import DBSessionDependency
|
||||
from common.aspect.interface_auth import UserInterfaceAuthDependency
|
||||
from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency
|
||||
from common.constant import ApiGroup, ApiNamespace
|
||||
from common.enums import BusinessType
|
||||
from common.router import APIRouterPro
|
||||
from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel
|
||||
from module_admin.entity.vo.job_vo import (
|
||||
DeleteJobLogModel,
|
||||
DeleteJobModel,
|
||||
EditJobModel,
|
||||
JobLogModel,
|
||||
JobLogPageQueryModel,
|
||||
JobModel,
|
||||
JobPageQueryModel,
|
||||
)
|
||||
from module_admin.entity.vo.user_vo import CurrentUserModel
|
||||
from module_admin.service.job_log_service import JobLogService
|
||||
from module_admin.service.job_service import JobService
|
||||
from utils.common_util import bytes2file_response
|
||||
from utils.log_util import logger
|
||||
from utils.response_util import ResponseUtil
|
||||
|
||||
job_controller = APIRouterPro(
|
||||
prefix='/monitor', order_num=13, tags=['系统监控-定时任务'], dependencies=[PreAuthDependency()]
|
||||
)
|
||||
|
||||
|
||||
@job_controller.get(
|
||||
'/job/list',
|
||||
summary='获取定时任务分页列表接口',
|
||||
description='用于获取定时任务分页列表',
|
||||
response_model=PageResponseModel[JobModel],
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:job:list')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.MONITOR_JOB_LIST)
|
||||
async def get_system_job_list(
|
||||
request: Request,
|
||||
job_page_query: Annotated[JobPageQueryModel, Query()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取分页数据
|
||||
job_page_query_result = await JobService.get_job_list_services(query_db, job_page_query, is_page=True)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(model_content=job_page_query_result)
|
||||
|
||||
|
||||
@job_controller.post(
|
||||
'/job',
|
||||
summary='新增定时任务接口',
|
||||
description='用于新增定时任务',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:job:add')],
|
||||
)
|
||||
@ValidateFields(validate_model='add_job')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.JOB_MUTATION)
|
||||
@Log(title='定时任务', business_type=BusinessType.INSERT)
|
||||
async def add_system_job(
|
||||
request: Request,
|
||||
add_job: JobModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
add_job.create_by = current_user.user.user_name
|
||||
add_job.create_time = datetime.now()
|
||||
add_job.update_by = current_user.user.user_name
|
||||
add_job.update_time = datetime.now()
|
||||
add_job_result = await JobService.add_job_services(query_db, add_job)
|
||||
logger.info(add_job_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=add_job_result.message)
|
||||
|
||||
|
||||
@job_controller.put(
|
||||
'/job',
|
||||
summary='编辑定时任务接口',
|
||||
description='用于编辑定时任务',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:job:edit')],
|
||||
)
|
||||
@ValidateFields(validate_model='edit_job')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.JOB_MUTATION)
|
||||
@Log(title='定时任务', business_type=BusinessType.UPDATE)
|
||||
async def edit_system_job(
|
||||
request: Request,
|
||||
edit_job: EditJobModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
edit_job.update_by = current_user.user.user_name
|
||||
edit_job.update_time = datetime.now()
|
||||
edit_job_result = await JobService.edit_job_services(query_db, edit_job)
|
||||
logger.info(edit_job_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=edit_job_result.message)
|
||||
|
||||
|
||||
@job_controller.put(
|
||||
'/job/changeStatus',
|
||||
summary='修改定时任务状态接口',
|
||||
description='用于修改定时任务状态',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:job:changeStatus')],
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.JOB_MUTATION)
|
||||
@Log(title='定时任务', business_type=BusinessType.UPDATE)
|
||||
async def change_system_job_status(
|
||||
request: Request,
|
||||
change_job: EditJobModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
edit_job = EditJobModel(
|
||||
jobId=change_job.job_id,
|
||||
status=change_job.status,
|
||||
updateBy=current_user.user.user_name,
|
||||
updateTime=datetime.now(),
|
||||
type='status',
|
||||
)
|
||||
edit_job_result = await JobService.edit_job_services(query_db, edit_job)
|
||||
logger.info(edit_job_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=edit_job_result.message)
|
||||
|
||||
|
||||
@job_controller.put(
|
||||
'/job/run',
|
||||
summary='执行定时任务接口',
|
||||
description='用于执行指定的定时任务',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:job:changeStatus')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.MONITOR_JOB_RUN, preset=ApiRateLimitPreset.USER_RESOURCE_EXECUTION)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.JOB_MUTATION)
|
||||
@Log(title='定时任务', business_type=BusinessType.UPDATE)
|
||||
async def execute_system_job(
|
||||
request: Request,
|
||||
execute_job: JobModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
execute_job_result = await JobService.execute_job_once_services(query_db, execute_job)
|
||||
logger.info(execute_job_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=execute_job_result.message)
|
||||
|
||||
|
||||
@job_controller.delete(
|
||||
'/job/{job_ids}',
|
||||
summary='删除定时任务接口',
|
||||
description='用于删除定时任务',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:job:remove')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.MONITOR_JOB_DELETE, preset=ApiRateLimitPreset.USER_DESTRUCTIVE_MUTATION)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.JOB_MUTATION)
|
||||
@Log(title='定时任务', business_type=BusinessType.DELETE)
|
||||
async def delete_system_job(
|
||||
request: Request,
|
||||
job_ids: Annotated[str, Path(description='需要删除的定时任务ID')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
delete_job = DeleteJobModel(jobIds=job_ids)
|
||||
delete_job_result = await JobService.delete_job_services(query_db, delete_job)
|
||||
logger.info(delete_job_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=delete_job_result.message)
|
||||
|
||||
|
||||
@job_controller.get(
|
||||
'/job/{job_id}',
|
||||
summary='获取定时任务详情接口',
|
||||
description='用于获取指定定时任务的详情信息',
|
||||
response_model=DataResponseModel[JobModel],
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:job:query')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.MONITOR_JOB_DETAIL)
|
||||
async def query_detail_system_job(
|
||||
request: Request,
|
||||
job_id: Annotated[int, Path(description='任务ID')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
job_detail_result = await JobService.job_detail_services(query_db, job_id)
|
||||
logger.info(f'获取job_id为{job_id}的信息成功')
|
||||
|
||||
return ResponseUtil.success(data=job_detail_result)
|
||||
|
||||
|
||||
@job_controller.post(
|
||||
'/job/export',
|
||||
summary='导出定时任务列表接口',
|
||||
description='用于导出当前符合查询条件的定时任务列表数据',
|
||||
response_class=StreamingResponse,
|
||||
responses={
|
||||
200: {
|
||||
'description': '流式返回定时任务列表excel文件',
|
||||
'content': {
|
||||
'application/octet-stream': {},
|
||||
},
|
||||
}
|
||||
},
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:job:export')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.MONITOR_JOB_EXPORT, preset=ApiRateLimitPreset.USER_RESOURCE_EXPORT)
|
||||
@Log(title='定时任务', business_type=BusinessType.EXPORT)
|
||||
async def export_system_job_list(
|
||||
request: Request,
|
||||
job_page_query: Annotated[JobPageQueryModel, Form()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取全量数据
|
||||
job_query_result = await JobService.get_job_list_services(query_db, job_page_query, is_page=False)
|
||||
job_export_result = await JobService.export_job_list_services(request, job_query_result)
|
||||
logger.info('导出成功')
|
||||
|
||||
return ResponseUtil.streaming(data=bytes2file_response(job_export_result))
|
||||
|
||||
|
||||
@job_controller.get(
|
||||
'/jobLog/list',
|
||||
summary='获取定时任务调度日志分页列表接口',
|
||||
description='用于获取定时任务调度日志分页列表',
|
||||
response_model=PageResponseModel[JobLogModel],
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:job:list')],
|
||||
)
|
||||
async def get_system_job_log_list(
|
||||
request: Request,
|
||||
job_log_page_query: Annotated[JobLogPageQueryModel, Query()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取分页数据
|
||||
job_log_page_query_result = await JobLogService.get_job_log_list_services(
|
||||
query_db, job_log_page_query, is_page=True
|
||||
)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(model_content=job_log_page_query_result)
|
||||
|
||||
|
||||
@job_controller.delete(
|
||||
'/jobLog/clean',
|
||||
summary='清空定时任务调度日志接口',
|
||||
description='用于清空所有定时任务调度日志',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:job:remove')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.MONITOR_JOB_LOG_CLEAN, preset=ApiRateLimitPreset.USER_DESTRUCTIVE_MUTATION)
|
||||
@Log(title='定时任务调度日志', business_type=BusinessType.CLEAN)
|
||||
async def clear_system_job_log(
|
||||
request: Request,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
clear_job_log_result = await JobLogService.clear_job_log_services(query_db)
|
||||
logger.info(clear_job_log_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=clear_job_log_result.message)
|
||||
|
||||
|
||||
@job_controller.delete(
|
||||
'/jobLog/{job_log_ids}',
|
||||
summary='删除定时任务调度日志接口',
|
||||
description='用于删除定时任务调度日志',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:job:remove')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.MONITOR_JOB_LOG_DELETE, preset=ApiRateLimitPreset.USER_DESTRUCTIVE_MUTATION)
|
||||
@Log(title='定时任务调度日志', business_type=BusinessType.DELETE)
|
||||
async def delete_system_job_log(
|
||||
request: Request,
|
||||
job_log_ids: Annotated[str, Path(description='需要删除的定时任务日志ID')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
delete_job_log = DeleteJobLogModel(jobLogIds=job_log_ids)
|
||||
delete_job_log_result = await JobLogService.delete_job_log_services(query_db, delete_job_log)
|
||||
logger.info(delete_job_log_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=delete_job_log_result.message)
|
||||
|
||||
|
||||
@job_controller.post(
|
||||
'/jobLog/export',
|
||||
summary='导出定时任务调度日志列表接口',
|
||||
description='用于导出当前符合查询条件的定时任务调度日志列表数据',
|
||||
response_class=StreamingResponse,
|
||||
responses={
|
||||
200: {
|
||||
'description': '流式返回定时任务日志列表excel文件',
|
||||
'content': {
|
||||
'application/octet-stream': {},
|
||||
},
|
||||
}
|
||||
},
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:job:export')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.MONITOR_JOB_LOG_EXPORT, preset=ApiRateLimitPreset.USER_RESOURCE_EXPORT)
|
||||
@Log(title='定时任务调度日志', business_type=BusinessType.EXPORT)
|
||||
async def export_system_job_log_list(
|
||||
request: Request,
|
||||
job_log_page_query: Annotated[JobLogPageQueryModel, Form()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取全量数据
|
||||
job_log_query_result = await JobLogService.get_job_log_list_services(query_db, job_log_page_query, is_page=False)
|
||||
job_log_export_result = await JobLogService.export_job_log_list_services(request, job_log_query_result)
|
||||
logger.info('导出成功')
|
||||
|
||||
return ResponseUtil.streaming(data=bytes2file_response(job_log_export_result))
|
||||
@@ -0,0 +1,241 @@
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Form, Path, Query, Request, Response
|
||||
from fastapi.responses import StreamingResponse
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.annotation.log_annotation import Log
|
||||
from common.annotation.rate_limit_annotation import ApiRateLimit, ApiRateLimitPreset
|
||||
from common.aspect.db_seesion import DBSessionDependency
|
||||
from common.aspect.interface_auth import UserInterfaceAuthDependency
|
||||
from common.aspect.pre_auth import PreAuthDependency
|
||||
from common.constant import ApiNamespace
|
||||
from common.enums import BusinessType
|
||||
from common.router import APIRouterPro
|
||||
from common.vo import PageResponseModel, ResponseBaseModel
|
||||
from module_admin.entity.vo.log_vo import (
|
||||
DeleteLoginLogModel,
|
||||
DeleteOperLogModel,
|
||||
LogininforModel,
|
||||
LoginLogPageQueryModel,
|
||||
OperLogModel,
|
||||
OperLogPageQueryModel,
|
||||
UnlockUser,
|
||||
)
|
||||
from module_admin.service.log_service import LoginLogService, OperationLogService
|
||||
from utils.common_util import bytes2file_response
|
||||
from utils.log_util import logger
|
||||
from utils.response_util import ResponseUtil
|
||||
|
||||
log_controller = APIRouterPro(
|
||||
prefix='/monitor', order_num=11, tags=['系统管理-日志管理'], dependencies=[PreAuthDependency()]
|
||||
)
|
||||
|
||||
|
||||
@log_controller.get(
|
||||
'/operlog/list',
|
||||
summary='获取操作日志分页列表接口',
|
||||
description='用于获取操作日志分页列表',
|
||||
response_model=PageResponseModel[OperLogModel],
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:operlog:list')],
|
||||
)
|
||||
async def get_system_operation_log_list(
|
||||
request: Request,
|
||||
operation_log_page_query: Annotated[OperLogPageQueryModel, Query()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取分页数据
|
||||
operation_log_page_query_result = await OperationLogService.get_operation_log_list_services(
|
||||
query_db, operation_log_page_query, is_page=True
|
||||
)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(model_content=operation_log_page_query_result)
|
||||
|
||||
|
||||
@log_controller.delete(
|
||||
'/operlog/clean',
|
||||
summary='清空操作日志接口',
|
||||
description='用于清空所有操作日志',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:operlog:remove')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.MONITOR_OPERLOG_CLEAN, preset=ApiRateLimitPreset.USER_DESTRUCTIVE_MUTATION)
|
||||
@Log(title='操作日志', business_type=BusinessType.CLEAN)
|
||||
async def clear_system_operation_log(
|
||||
request: Request, query_db: Annotated[AsyncSession, DBSessionDependency()]
|
||||
) -> Response:
|
||||
clear_operation_log_result = await OperationLogService.clear_operation_log_services(query_db)
|
||||
logger.info(clear_operation_log_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=clear_operation_log_result.message)
|
||||
|
||||
|
||||
@log_controller.delete(
|
||||
'/operlog/{oper_ids}',
|
||||
summary='删除操作日志接口',
|
||||
description='用于删除操作日志',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:operlog:remove')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.MONITOR_OPERLOG_DELETE, preset=ApiRateLimitPreset.USER_DESTRUCTIVE_MUTATION)
|
||||
@Log(title='操作日志', business_type=BusinessType.DELETE)
|
||||
async def delete_system_operation_log(
|
||||
request: Request,
|
||||
oper_ids: Annotated[str, Path(description='需要删除的日志主键')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
delete_operation_log = DeleteOperLogModel(operIds=oper_ids)
|
||||
delete_operation_log_result = await OperationLogService.delete_operation_log_services(
|
||||
query_db, delete_operation_log
|
||||
)
|
||||
logger.info(delete_operation_log_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=delete_operation_log_result.message)
|
||||
|
||||
|
||||
@log_controller.post(
|
||||
'/operlog/export',
|
||||
summary='导出操作日志接口',
|
||||
description='用于导出当前符合查询条件的操作日志数据',
|
||||
response_class=StreamingResponse,
|
||||
responses={
|
||||
200: {
|
||||
'description': '流式返回操作日志列表excel文件',
|
||||
'content': {
|
||||
'application/octet-stream': {},
|
||||
},
|
||||
}
|
||||
},
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:operlog:export')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.MONITOR_OPERLOG_EXPORT, preset=ApiRateLimitPreset.USER_RESOURCE_EXPORT)
|
||||
@Log(title='操作日志', business_type=BusinessType.EXPORT)
|
||||
async def export_system_operation_log_list(
|
||||
request: Request,
|
||||
operation_log_page_query: Annotated[OperLogPageQueryModel, Form()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取全量数据
|
||||
operation_log_query_result = await OperationLogService.get_operation_log_list_services(
|
||||
query_db, operation_log_page_query, is_page=False
|
||||
)
|
||||
operation_log_export_result = await OperationLogService.export_operation_log_list_services(
|
||||
request, operation_log_query_result
|
||||
)
|
||||
logger.info('导出成功')
|
||||
|
||||
return ResponseUtil.streaming(data=bytes2file_response(operation_log_export_result))
|
||||
|
||||
|
||||
@log_controller.get(
|
||||
'/logininfor/list',
|
||||
summary='获取登录日志分页列表接口',
|
||||
description='用于获取登录日志分页列表',
|
||||
response_model=PageResponseModel[LogininforModel],
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:logininfor:list')],
|
||||
)
|
||||
async def get_system_login_log_list(
|
||||
request: Request,
|
||||
login_log_page_query: Annotated[LoginLogPageQueryModel, Query()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取分页数据
|
||||
login_log_page_query_result = await LoginLogService.get_login_log_list_services(
|
||||
query_db, login_log_page_query, is_page=True
|
||||
)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(model_content=login_log_page_query_result)
|
||||
|
||||
|
||||
@log_controller.delete(
|
||||
'/logininfor/clean',
|
||||
summary='清空登录日志接口',
|
||||
description='用于清空所有登录日志',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:logininfor:remove')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.MONITOR_LOGININFO_CLEAN, preset=ApiRateLimitPreset.USER_DESTRUCTIVE_MUTATION)
|
||||
@Log(title='登录日志', business_type=BusinessType.CLEAN)
|
||||
async def clear_system_login_log(
|
||||
request: Request, query_db: Annotated[AsyncSession, DBSessionDependency()]
|
||||
) -> Response:
|
||||
clear_login_log_result = await LoginLogService.clear_login_log_services(query_db)
|
||||
logger.info(clear_login_log_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=clear_login_log_result.message)
|
||||
|
||||
|
||||
@log_controller.delete(
|
||||
'/logininfor/{info_ids}',
|
||||
summary='删除登录日志接口',
|
||||
description='用于删除登录日志',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:logininfor:remove')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.MONITOR_LOGININFO_DELETE, preset=ApiRateLimitPreset.USER_DESTRUCTIVE_MUTATION)
|
||||
@Log(title='登录日志', business_type=BusinessType.DELETE)
|
||||
async def delete_system_login_log(
|
||||
request: Request,
|
||||
info_ids: Annotated[str, Path(description='需要删除的访问ID')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
delete_login_log = DeleteLoginLogModel(infoIds=info_ids)
|
||||
delete_login_log_result = await LoginLogService.delete_login_log_services(query_db, delete_login_log)
|
||||
logger.info(delete_login_log_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=delete_login_log_result.message)
|
||||
|
||||
|
||||
@log_controller.get(
|
||||
'/logininfor/unlock/{user_name}',
|
||||
summary='解锁账户接口',
|
||||
description='用于解锁指定用户账户',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:logininfor:unlock')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.MONITOR_LOGININFO_UNLOCK, preset=ApiRateLimitPreset.USER_SECURITY_MUTATION)
|
||||
@Log(title='账户解锁', business_type=BusinessType.OTHER)
|
||||
async def unlock_system_user(
|
||||
request: Request,
|
||||
user_name: Annotated[str, Path(description='用户名称')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
unlock_user = UnlockUser(userName=user_name)
|
||||
unlock_user_result = await LoginLogService.unlock_user_services(request, unlock_user)
|
||||
logger.info(unlock_user_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=unlock_user_result.message)
|
||||
|
||||
|
||||
@log_controller.post(
|
||||
'/logininfor/export',
|
||||
summary='导出登录日志接口',
|
||||
description='用于导出当前符合查询条件的登录日志数据',
|
||||
response_class=StreamingResponse,
|
||||
responses={
|
||||
200: {
|
||||
'description': '流式返回登录日志列表excel文件',
|
||||
'content': {
|
||||
'application/octet-stream': {},
|
||||
},
|
||||
}
|
||||
},
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:logininfor:export')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.MONITOR_LOGININFO_EXPORT, preset=ApiRateLimitPreset.USER_RESOURCE_EXPORT)
|
||||
@Log(title='登录日志', business_type=BusinessType.EXPORT)
|
||||
async def export_system_login_log_list(
|
||||
request: Request,
|
||||
login_log_page_query: Annotated[LoginLogPageQueryModel, Form()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取全量数据
|
||||
login_log_query_result = await LoginLogService.get_login_log_list_services(
|
||||
query_db, login_log_page_query, is_page=False
|
||||
)
|
||||
login_log_export_result = await LoginLogService.export_login_log_list_services(login_log_query_result)
|
||||
logger.info('导出成功')
|
||||
|
||||
return ResponseUtil.streaming(data=bytes2file_response(login_log_export_result))
|
||||
@@ -0,0 +1,192 @@
|
||||
import uuid
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Annotated
|
||||
|
||||
import jwt
|
||||
from fastapi import Depends, Request, Response
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.annotation.cache_annotation import ApiCache, ApiCacheEvict
|
||||
from common.annotation.log_annotation import Log
|
||||
from common.annotation.rate_limit_annotation import ApiRateLimit, ApiRateLimitPreset
|
||||
from common.aspect.db_seesion import DBSessionDependency
|
||||
from common.aspect.pre_auth import CurrentUserDependency
|
||||
from common.constant import ApiGroup, ApiNamespace
|
||||
from common.enums import BusinessType, RedisInitKeyConfig
|
||||
from common.router import APIRouterPro
|
||||
from common.vo import CrudResponseModel, DataResponseModel, DynamicResponseModel, ResponseBaseModel
|
||||
from config.env import AppConfig, JwtConfig
|
||||
from module_admin.entity.vo.login_vo import LoginToken, RouterModel, Token, UserLogin, UserRegister
|
||||
from module_admin.entity.vo.user_vo import CurrentUserModel, EditUserModel
|
||||
from module_admin.service.login_service import CustomOAuth2PasswordRequestForm, LoginService, oauth2_scheme
|
||||
from module_admin.service.user_service import UserService
|
||||
from utils.log_util import logger
|
||||
from utils.response_util import ResponseUtil
|
||||
|
||||
login_controller = APIRouterPro(order_num=1, tags=['登录模块'])
|
||||
|
||||
|
||||
@login_controller.post(
|
||||
'/login',
|
||||
summary='登录接口',
|
||||
description='用于用户登录',
|
||||
response_model=DynamicResponseModel[LoginToken] | Token,
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.LOGIN, preset=ApiRateLimitPreset.ANON_AUTH_LOGIN)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.LOGIN_SUCCESS_MUTATION)
|
||||
@Log(title='用户登录', business_type=BusinessType.OTHER, log_type='login')
|
||||
async def login(
|
||||
request: Request,
|
||||
form_data: Annotated[CustomOAuth2PasswordRequestForm, Depends()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
captcha_enabled = (
|
||||
await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.account.captchaEnabled') == 'true'
|
||||
)
|
||||
user = UserLogin(
|
||||
userName=form_data.username,
|
||||
password=form_data.password,
|
||||
code=form_data.code,
|
||||
uuid=form_data.uuid,
|
||||
loginInfo=form_data.login_info,
|
||||
captchaEnabled=captcha_enabled,
|
||||
)
|
||||
result = await LoginService.authenticate_user(request, query_db, user)
|
||||
access_token_expires = timedelta(minutes=JwtConfig.jwt_expire_minutes)
|
||||
session_id = str(uuid.uuid4())
|
||||
access_token = await LoginService.create_access_token(
|
||||
data={
|
||||
'user_id': str(result[0].user_id),
|
||||
'user_name': result[0].user_name,
|
||||
'dept_name': result[1].dept_name if result[1] else None,
|
||||
'session_id': session_id,
|
||||
'login_info': user.login_info,
|
||||
},
|
||||
expires_delta=access_token_expires,
|
||||
)
|
||||
if AppConfig.app_same_time_login:
|
||||
await request.app.state.redis.set(
|
||||
f'{RedisInitKeyConfig.ACCESS_TOKEN.key}:{session_id}',
|
||||
access_token,
|
||||
ex=timedelta(minutes=JwtConfig.jwt_redis_expire_minutes),
|
||||
)
|
||||
else:
|
||||
# 此方法可实现同一账号同一时间只能登录一次
|
||||
await request.app.state.redis.set(
|
||||
f'{RedisInitKeyConfig.ACCESS_TOKEN.key}:{result[0].user_id}',
|
||||
access_token,
|
||||
ex=timedelta(minutes=JwtConfig.jwt_redis_expire_minutes),
|
||||
)
|
||||
await UserService.edit_user_services(
|
||||
query_db, EditUserModel(userId=result[0].user_id, loginDate=datetime.now(), type='status')
|
||||
)
|
||||
logger.info('登录成功')
|
||||
# 判断请求是否来自于api文档,如果是返回指定格式的结果,用于修复api文档认证成功后token显示undefined的bug
|
||||
request_from_swagger = request.headers.get('referer').endswith('docs') if request.headers.get('referer') else False
|
||||
request_from_redoc = request.headers.get('referer').endswith('redoc') if request.headers.get('referer') else False
|
||||
if request_from_swagger or request_from_redoc:
|
||||
return {'access_token': access_token, 'token_type': 'Bearer'}
|
||||
return ResponseUtil.success(msg='登录成功', dict_content={'token': access_token})
|
||||
|
||||
|
||||
@login_controller.get(
|
||||
'/getInfo',
|
||||
summary='获取用户信息接口',
|
||||
description='用于获取当前登录用户的信息',
|
||||
response_model=DynamicResponseModel[CurrentUserModel],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.LOGIN_USER_INFO)
|
||||
async def get_login_user_info(
|
||||
request: Request, current_user: Annotated[CurrentUserModel, CurrentUserDependency()]
|
||||
) -> Response:
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(model_content=current_user)
|
||||
|
||||
|
||||
@login_controller.get(
|
||||
'/getRouters',
|
||||
summary='获取用户路由接口',
|
||||
description='用于获取当前登录用户的路由信息',
|
||||
response_model=DataResponseModel[list[RouterModel]],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.LOGIN_USER_ROUTERS)
|
||||
async def get_login_user_routers(
|
||||
request: Request,
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
logger.info('获取成功')
|
||||
user_routers = await LoginService.get_current_user_routers(current_user.user.user_id, query_db)
|
||||
|
||||
return ResponseUtil.success(data=user_routers)
|
||||
|
||||
|
||||
@login_controller.post(
|
||||
'/register',
|
||||
summary='注册接口',
|
||||
description='用于用户注册',
|
||||
response_model=DataResponseModel[CrudResponseModel],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.REGISTER, preset=ApiRateLimitPreset.ANON_AUTH_REGISTER)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.USER_ENTITY_MUTATION)
|
||||
async def register_user(
|
||||
request: Request,
|
||||
user_register: UserRegister,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
user_register_result = await LoginService.register_user_services(request, query_db, user_register)
|
||||
logger.info(user_register_result.message)
|
||||
|
||||
return ResponseUtil.success(data=user_register_result, msg=user_register_result.message)
|
||||
|
||||
|
||||
# @login_controller.post("/getSmsCode", response_model=SmsCode)
|
||||
# async def get_sms_code(request: Request, user: ResetUserModel, query_db: AsyncSession = DBSessionDependency()):
|
||||
# try:
|
||||
# sms_result = await LoginService.get_sms_code_services(request, query_db, user)
|
||||
# if sms_result.is_success:
|
||||
# logger.info('获取成功')
|
||||
# return ResponseUtil.success(data=sms_result)
|
||||
# else:
|
||||
# logger.warning(sms_result.message)
|
||||
# return ResponseUtil.failure(msg=sms_result.message)
|
||||
# except Exception as e:
|
||||
# logger.exception(e)
|
||||
# return ResponseUtil.error(msg=str(e))
|
||||
#
|
||||
#
|
||||
# @login_controller.post("/forgetPwd", response_model=CrudResponseModel)
|
||||
# async def forget_user_pwd(request: Request, forget_user: ResetUserModel, query_db: AsyncSession = DBSessionDependency()):
|
||||
# try:
|
||||
# forget_user_result = await LoginService.forget_user_services(request, query_db, forget_user)
|
||||
# if forget_user_result.is_success:
|
||||
# logger.info(forget_user_result.message)
|
||||
# return ResponseUtil.success(data=forget_user_result, msg=forget_user_result.message)
|
||||
# else:
|
||||
# logger.warning(forget_user_result.message)
|
||||
# return ResponseUtil.failure(msg=forget_user_result.message)
|
||||
# except Exception as e:
|
||||
# logger.exception(e)
|
||||
# return ResponseUtil.error(msg=str(e))
|
||||
|
||||
|
||||
@login_controller.post(
|
||||
'/logout',
|
||||
summary='退出登录接口',
|
||||
description='用于用户退出登录',
|
||||
response_model=ResponseBaseModel,
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.LOGOUT_MUTATION)
|
||||
async def logout(request: Request, token: Annotated[str | None, Depends(oauth2_scheme)]) -> Response:
|
||||
payload = jwt.decode(
|
||||
token, JwtConfig.jwt_secret_key, algorithms=[JwtConfig.jwt_algorithm], options={'verify_exp': False}
|
||||
)
|
||||
if AppConfig.app_same_time_login:
|
||||
token_id: str = payload.get('session_id')
|
||||
else:
|
||||
token_id: str = payload.get('user_id')
|
||||
await LoginService.logout_services(request, token_id)
|
||||
logger.info('退出成功')
|
||||
|
||||
return ResponseUtil.success(msg='退出成功')
|
||||
@@ -0,0 +1,173 @@
|
||||
from datetime import datetime
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Path, Query, Request, Response
|
||||
from pydantic_validation_decorator import ValidateFields
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.annotation.cache_annotation import ApiCache, ApiCacheEvict
|
||||
from common.annotation.log_annotation import Log
|
||||
from common.aspect.db_seesion import DBSessionDependency
|
||||
from common.aspect.interface_auth import UserInterfaceAuthDependency
|
||||
from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency
|
||||
from common.constant import ApiGroup, ApiNamespace
|
||||
from common.enums import BusinessType
|
||||
from common.router import APIRouterPro
|
||||
from common.vo import DataResponseModel, DynamicResponseModel, ResponseBaseModel
|
||||
from module_admin.entity.vo.menu_vo import DeleteMenuModel, MenuModel, MenuQueryModel, MenuTreeModel
|
||||
from module_admin.entity.vo.role_vo import RoleMenuQueryModel
|
||||
from module_admin.entity.vo.user_vo import CurrentUserModel
|
||||
from module_admin.service.menu_service import MenuService
|
||||
from utils.log_util import logger
|
||||
from utils.response_util import ResponseUtil
|
||||
|
||||
menu_controller = APIRouterPro(
|
||||
prefix='/system/menu', order_num=5, tags=['系统管理-菜单管理'], dependencies=[PreAuthDependency()]
|
||||
)
|
||||
|
||||
|
||||
@menu_controller.get(
|
||||
'/treeselect',
|
||||
summary='获取菜单树接口',
|
||||
description='用于获取当前用户可见的菜单树',
|
||||
response_model=DataResponseModel[list[MenuTreeModel]],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_MENU_TREE)
|
||||
async def get_system_menu_tree(
|
||||
request: Request,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
menu_query_result = await MenuService.get_menu_tree_services(query_db, current_user)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(data=menu_query_result)
|
||||
|
||||
|
||||
@menu_controller.get(
|
||||
'/roleMenuTreeselect/{role_id}',
|
||||
summary='获取角色菜单树接口',
|
||||
description='用于获取指定角色可见的菜单树',
|
||||
response_model=DynamicResponseModel[RoleMenuQueryModel],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_MENU_ROLE_TREE)
|
||||
async def get_system_role_menu_tree(
|
||||
request: Request,
|
||||
role_id: Annotated[int, Path(description='角色ID')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
role_menu_query_result = await MenuService.get_role_menu_tree_services(query_db, role_id, current_user)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(model_content=role_menu_query_result)
|
||||
|
||||
|
||||
@menu_controller.get(
|
||||
'/list',
|
||||
summary='获取菜单列表接口',
|
||||
description='用于获取当前用户可见的菜单列表',
|
||||
response_model=DataResponseModel[list[MenuModel]],
|
||||
dependencies=[UserInterfaceAuthDependency('system:menu:list')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_MENU_LIST)
|
||||
async def get_system_menu_list(
|
||||
request: Request,
|
||||
menu_query: Annotated[MenuQueryModel, Query()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
menu_query_result = await MenuService.get_menu_list_services(query_db, menu_query, current_user)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(data=menu_query_result)
|
||||
|
||||
|
||||
@menu_controller.post(
|
||||
'',
|
||||
summary='新增菜单接口',
|
||||
description='用于新增菜单',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:menu:add')],
|
||||
)
|
||||
@ValidateFields(validate_model='add_menu')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.MENU_MUTATION)
|
||||
@Log(title='菜单管理', business_type=BusinessType.INSERT)
|
||||
async def add_system_menu(
|
||||
request: Request,
|
||||
add_menu: MenuModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
add_menu.create_by = current_user.user.user_name
|
||||
add_menu.create_time = datetime.now()
|
||||
add_menu.update_by = current_user.user.user_name
|
||||
add_menu.update_time = datetime.now()
|
||||
add_menu_result = await MenuService.add_menu_services(query_db, add_menu)
|
||||
logger.info(add_menu_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=add_menu_result.message)
|
||||
|
||||
|
||||
@menu_controller.put(
|
||||
'',
|
||||
summary='编辑菜单接口',
|
||||
description='用于编辑菜单',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:menu:edit')],
|
||||
)
|
||||
@ValidateFields(validate_model='edit_menu')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.MENU_MUTATION)
|
||||
@Log(title='菜单管理', business_type=BusinessType.UPDATE)
|
||||
async def edit_system_menu(
|
||||
request: Request,
|
||||
edit_menu: MenuModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
edit_menu.update_by = current_user.user.user_name
|
||||
edit_menu.update_time = datetime.now()
|
||||
edit_menu_result = await MenuService.edit_menu_services(query_db, edit_menu)
|
||||
logger.info(edit_menu_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=edit_menu_result.message)
|
||||
|
||||
|
||||
@menu_controller.delete(
|
||||
'/{menu_ids}',
|
||||
summary='删除菜单接口',
|
||||
description='用于删除菜单',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:menu:remove')],
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.MENU_MUTATION)
|
||||
@Log(title='菜单管理', business_type=BusinessType.DELETE)
|
||||
async def delete_system_menu(
|
||||
request: Request,
|
||||
menu_ids: Annotated[str, Path(description='需要删除的菜单ID')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
delete_menu = DeleteMenuModel(menuIds=menu_ids)
|
||||
delete_menu_result = await MenuService.delete_menu_services(query_db, delete_menu)
|
||||
logger.info(delete_menu_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=delete_menu_result.message)
|
||||
|
||||
|
||||
@menu_controller.get(
|
||||
'/{menu_id}',
|
||||
summary='获取菜单详情接口',
|
||||
description='用于获取指定菜单的详情信息',
|
||||
response_model=DataResponseModel[MenuModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:menu:query')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_MENU_DETAIL)
|
||||
async def query_detail_system_menu(
|
||||
request: Request,
|
||||
menu_id: Annotated[int, Path(description='菜单ID')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
menu_detail_result = await MenuService.menu_detail_services(query_db, menu_id)
|
||||
logger.info(f'获取menu_id为{menu_id}的信息成功')
|
||||
|
||||
return ResponseUtil.success(data=menu_detail_result)
|
||||
@@ -0,0 +1,135 @@
|
||||
from datetime import datetime
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Path, Query, Request, Response
|
||||
from pydantic_validation_decorator import ValidateFields
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.annotation.cache_annotation import ApiCache, ApiCacheEvict
|
||||
from common.annotation.log_annotation import Log
|
||||
from common.aspect.db_seesion import DBSessionDependency
|
||||
from common.aspect.interface_auth import UserInterfaceAuthDependency
|
||||
from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency
|
||||
from common.constant import ApiGroup, ApiNamespace
|
||||
from common.enums import BusinessType
|
||||
from common.router import APIRouterPro
|
||||
from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel
|
||||
from module_admin.entity.vo.notice_vo import DeleteNoticeModel, NoticeModel, NoticePageQueryModel
|
||||
from module_admin.entity.vo.user_vo import CurrentUserModel
|
||||
from module_admin.service.notice_service import NoticeService
|
||||
from utils.log_util import logger
|
||||
from utils.response_util import ResponseUtil
|
||||
|
||||
notice_controller = APIRouterPro(
|
||||
prefix='/system/notice', order_num=10, tags=['系统管理-通知公告管理'], dependencies=[PreAuthDependency()]
|
||||
)
|
||||
|
||||
|
||||
@notice_controller.get(
|
||||
'/list',
|
||||
summary='获取通知公告分页列表接口',
|
||||
description='用于获取通知公告分页列表',
|
||||
response_model=PageResponseModel[NoticeModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:notice:list')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_NOTICE_LIST)
|
||||
async def get_system_notice_list(
|
||||
request: Request,
|
||||
notice_page_query: Annotated[NoticePageQueryModel, Query()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取分页数据
|
||||
notice_page_query_result = await NoticeService.get_notice_list_services(query_db, notice_page_query, is_page=True)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(model_content=notice_page_query_result)
|
||||
|
||||
|
||||
@notice_controller.post(
|
||||
'',
|
||||
summary='新增通知公告接口',
|
||||
description='用于新增通知公告',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:notice:add')],
|
||||
)
|
||||
@ValidateFields(validate_model='add_notice')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.NOTICE_MUTATION)
|
||||
@Log(title='通知公告', business_type=BusinessType.INSERT)
|
||||
async def add_system_notice(
|
||||
request: Request,
|
||||
add_notice: NoticeModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
add_notice.create_by = current_user.user.user_name
|
||||
add_notice.create_time = datetime.now()
|
||||
add_notice.update_by = current_user.user.user_name
|
||||
add_notice.update_time = datetime.now()
|
||||
add_notice_result = await NoticeService.add_notice_services(query_db, add_notice)
|
||||
logger.info(add_notice_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=add_notice_result.message)
|
||||
|
||||
|
||||
@notice_controller.put(
|
||||
'',
|
||||
summary='编辑通知公告接口',
|
||||
description='用于编辑通知公告',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:notice:edit')],
|
||||
)
|
||||
@ValidateFields(validate_model='edit_notice')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.NOTICE_MUTATION)
|
||||
@Log(title='通知公告', business_type=BusinessType.UPDATE)
|
||||
async def edit_system_notice(
|
||||
request: Request,
|
||||
edit_notice: NoticeModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
edit_notice.update_by = current_user.user.user_name
|
||||
edit_notice.update_time = datetime.now()
|
||||
edit_notice_result = await NoticeService.edit_notice_services(query_db, edit_notice)
|
||||
logger.info(edit_notice_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=edit_notice_result.message)
|
||||
|
||||
|
||||
@notice_controller.delete(
|
||||
'/{notice_ids}',
|
||||
summary='删除通知公告接口',
|
||||
description='用于删除通知公告',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:notice:remove')],
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.NOTICE_MUTATION)
|
||||
@Log(title='通知公告', business_type=BusinessType.DELETE)
|
||||
async def delete_system_notice(
|
||||
request: Request,
|
||||
notice_ids: Annotated[str, Path(description='需要删除的公告ID')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
delete_notice = DeleteNoticeModel(noticeIds=notice_ids)
|
||||
delete_notice_result = await NoticeService.delete_notice_services(query_db, delete_notice)
|
||||
logger.info(delete_notice_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=delete_notice_result.message)
|
||||
|
||||
|
||||
@notice_controller.get(
|
||||
'/{notice_id}',
|
||||
summary='获取通知公告详情接口',
|
||||
description='用于获取指定通知公告的详细信息',
|
||||
response_model=DataResponseModel[NoticeModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:notice:query')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_NOTICE_DETAIL)
|
||||
async def query_detail_system_post(
|
||||
request: Request,
|
||||
notice_id: Annotated[int, Path(description='公告ID')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
notice_detail_result = await NoticeService.notice_detail_services(query_db, notice_id)
|
||||
logger.info(f'获取notice_id为{notice_id}的信息成功')
|
||||
|
||||
return ResponseUtil.success(data=notice_detail_result)
|
||||
@@ -0,0 +1,63 @@
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Path, Query, Request, Response
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.annotation.log_annotation import Log
|
||||
from common.annotation.rate_limit_annotation import ApiRateLimit, ApiRateLimitPreset
|
||||
from common.aspect.db_seesion import DBSessionDependency
|
||||
from common.aspect.interface_auth import UserInterfaceAuthDependency
|
||||
from common.aspect.pre_auth import PreAuthDependency
|
||||
from common.constant import ApiNamespace
|
||||
from common.enums import BusinessType
|
||||
from common.router import APIRouterPro
|
||||
from common.vo import ResponseBaseModel
|
||||
from module_admin.entity.vo.online_vo import DeleteOnlineModel, OnlinePageResponseModel, OnlineQueryModel
|
||||
from module_admin.service.online_service import OnlineService
|
||||
from utils.log_util import logger
|
||||
from utils.response_util import ResponseUtil
|
||||
|
||||
online_controller = APIRouterPro(
|
||||
prefix='/monitor/online', order_num=12, tags=['系统监控-在线用户'], dependencies=[PreAuthDependency()]
|
||||
)
|
||||
|
||||
|
||||
@online_controller.get(
|
||||
'/list',
|
||||
summary='获取在线用户分页列表接口',
|
||||
description='用于获取在线用户分页列表',
|
||||
response_model=OnlinePageResponseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:online:list')],
|
||||
)
|
||||
async def get_monitor_online_list(
|
||||
request: Request,
|
||||
online_page_query: Annotated[OnlineQueryModel, Query()],
|
||||
) -> Response:
|
||||
# 获取全量数据
|
||||
online_query_result = await OnlineService.get_online_list_services(request, online_page_query)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(
|
||||
model_content=OnlinePageResponseModel(rows=online_query_result, total=len(online_query_result))
|
||||
)
|
||||
|
||||
|
||||
@online_controller.delete(
|
||||
'/{token_ids}',
|
||||
summary='强退在线用户接口',
|
||||
description='用于强退指定会话编号的在线用户',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:online:forceLogout')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.MONITOR_ONLINE_FORCE_LOGOUT, preset=ApiRateLimitPreset.USER_SECURITY_MUTATION)
|
||||
@Log(title='在线用户', business_type=BusinessType.FORCE)
|
||||
async def delete_monitor_online(
|
||||
request: Request,
|
||||
token_ids: Annotated[str, Path(description='需要强退的会话编号')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
delete_online = DeleteOnlineModel(tokenIds=token_ids)
|
||||
delete_online_result = await OnlineService.delete_online_services(request, delete_online)
|
||||
logger.info(delete_online_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=delete_online_result.message)
|
||||
@@ -0,0 +1,168 @@
|
||||
from datetime import datetime
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Form, Path, Query, Request, Response
|
||||
from fastapi.responses import StreamingResponse
|
||||
from pydantic_validation_decorator import ValidateFields
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.annotation.cache_annotation import ApiCache, ApiCacheEvict
|
||||
from common.annotation.log_annotation import Log
|
||||
from common.annotation.rate_limit_annotation import ApiRateLimit, ApiRateLimitPreset
|
||||
from common.aspect.db_seesion import DBSessionDependency
|
||||
from common.aspect.interface_auth import UserInterfaceAuthDependency
|
||||
from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency
|
||||
from common.constant import ApiGroup, ApiNamespace
|
||||
from common.enums import BusinessType
|
||||
from common.router import APIRouterPro
|
||||
from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel
|
||||
from module_admin.entity.vo.post_vo import DeletePostModel, PostModel, PostPageQueryModel
|
||||
from module_admin.entity.vo.user_vo import CurrentUserModel
|
||||
from module_admin.service.post_service import PostService
|
||||
from utils.common_util import bytes2file_response
|
||||
from utils.log_util import logger
|
||||
from utils.response_util import ResponseUtil
|
||||
|
||||
post_controller = APIRouterPro(
|
||||
prefix='/system/post', order_num=7, tags=['系统管理-岗位管理'], dependencies=[PreAuthDependency()]
|
||||
)
|
||||
|
||||
|
||||
@post_controller.get(
|
||||
'/list',
|
||||
summary='获取岗位分页列表接口',
|
||||
description='用于获取岗位分页列表',
|
||||
response_model=PageResponseModel[PostModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:post:list')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_POST_LIST)
|
||||
async def get_system_post_list(
|
||||
request: Request,
|
||||
post_page_query: Annotated[PostPageQueryModel, Query()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取分页数据
|
||||
post_page_query_result = await PostService.get_post_list_services(query_db, post_page_query, is_page=True)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(model_content=post_page_query_result)
|
||||
|
||||
|
||||
@post_controller.post(
|
||||
'',
|
||||
summary='新增岗位接口',
|
||||
description='用于新增岗位',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:post:add')],
|
||||
)
|
||||
@ValidateFields(validate_model='add_post')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.POST_MUTATION)
|
||||
@Log(title='岗位管理', business_type=BusinessType.INSERT)
|
||||
async def add_system_post(
|
||||
request: Request,
|
||||
add_post: PostModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
add_post.create_by = current_user.user.user_name
|
||||
add_post.create_time = datetime.now()
|
||||
add_post.update_by = current_user.user.user_name
|
||||
add_post.update_time = datetime.now()
|
||||
add_post_result = await PostService.add_post_services(query_db, add_post)
|
||||
logger.info(add_post_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=add_post_result.message)
|
||||
|
||||
|
||||
@post_controller.put(
|
||||
'',
|
||||
summary='编辑岗位接口',
|
||||
description='用于编辑岗位',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:post:edit')],
|
||||
)
|
||||
@ValidateFields(validate_model='edit_post')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.POST_MUTATION)
|
||||
@Log(title='岗位管理', business_type=BusinessType.UPDATE)
|
||||
async def edit_system_post(
|
||||
request: Request,
|
||||
edit_post: PostModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
edit_post.update_by = current_user.user.user_name
|
||||
edit_post.update_time = datetime.now()
|
||||
edit_post_result = await PostService.edit_post_services(query_db, edit_post)
|
||||
logger.info(edit_post_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=edit_post_result.message)
|
||||
|
||||
|
||||
@post_controller.delete(
|
||||
'/{post_ids}',
|
||||
summary='删除岗位接口',
|
||||
description='用于删除岗位',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:post:remove')],
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.POST_MUTATION)
|
||||
@Log(title='岗位管理', business_type=BusinessType.DELETE)
|
||||
async def delete_system_post(
|
||||
request: Request,
|
||||
post_ids: Annotated[str, Path(description='需要删除的岗位ID')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
delete_post = DeletePostModel(postIds=post_ids)
|
||||
delete_post_result = await PostService.delete_post_services(query_db, delete_post)
|
||||
logger.info(delete_post_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=delete_post_result.message)
|
||||
|
||||
|
||||
@post_controller.get(
|
||||
'/{post_id}',
|
||||
summary='获取岗位详情接口',
|
||||
description='用于获取指定岗位的详细信息',
|
||||
response_model=DataResponseModel[PostModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:post:query')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_POST_DETAIL)
|
||||
async def query_detail_system_post(
|
||||
request: Request,
|
||||
post_id: Annotated[int, Path(description='岗位ID')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
post_detail_result = await PostService.post_detail_services(query_db, post_id)
|
||||
logger.info(f'获取post_id为{post_id}的信息成功')
|
||||
|
||||
return ResponseUtil.success(data=post_detail_result)
|
||||
|
||||
|
||||
@post_controller.post(
|
||||
'/export',
|
||||
summary='导出岗位列表接口',
|
||||
description='用于导出当前符合查询条件的岗位列表数据',
|
||||
response_class=StreamingResponse,
|
||||
responses={
|
||||
200: {
|
||||
'description': '流式返回岗位列表excel文件',
|
||||
'content': {
|
||||
'application/octet-stream': {},
|
||||
},
|
||||
}
|
||||
},
|
||||
dependencies=[UserInterfaceAuthDependency('system:post:export')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.SYSTEM_POST_EXPORT, preset=ApiRateLimitPreset.USER_RESOURCE_EXPORT)
|
||||
@Log(title='岗位管理', business_type=BusinessType.EXPORT)
|
||||
async def export_system_post_list(
|
||||
request: Request,
|
||||
post_page_query: Annotated[PostPageQueryModel, Form()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
# 获取全量数据
|
||||
post_query_result = await PostService.get_post_list_services(query_db, post_page_query, is_page=False)
|
||||
post_export_result = await PostService.export_post_list_services(post_query_result)
|
||||
logger.info('导出成功')
|
||||
|
||||
return ResponseUtil.streaming(data=bytes2file_response(post_export_result))
|
||||
@@ -0,0 +1,400 @@
|
||||
from datetime import datetime
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Form, Path, Query, Request, Response
|
||||
from fastapi.responses import StreamingResponse
|
||||
from pydantic_validation_decorator import ValidateFields
|
||||
from sqlalchemy import ColumnElement
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.annotation.cache_annotation import ApiCache, ApiCacheEvict
|
||||
from common.annotation.log_annotation import Log
|
||||
from common.annotation.rate_limit_annotation import ApiRateLimit, ApiRateLimitPreset
|
||||
from common.aspect.data_scope import DataScopeDependency
|
||||
from common.aspect.db_seesion import DBSessionDependency
|
||||
from common.aspect.interface_auth import UserInterfaceAuthDependency
|
||||
from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency
|
||||
from common.constant import ApiGroup, ApiNamespace
|
||||
from common.enums import BusinessType
|
||||
from common.router import APIRouterPro
|
||||
from common.vo import DataResponseModel, DynamicResponseModel, PageResponseModel, ResponseBaseModel
|
||||
from module_admin.entity.do.dept_do import SysDept
|
||||
from module_admin.entity.do.user_do import SysUser
|
||||
from module_admin.entity.vo.dept_vo import DeptModel
|
||||
from module_admin.entity.vo.role_vo import (
|
||||
AddRoleModel,
|
||||
DeleteRoleModel,
|
||||
RoleDeptQueryModel,
|
||||
RoleModel,
|
||||
RolePageQueryModel,
|
||||
)
|
||||
from module_admin.entity.vo.user_vo import CrudUserRoleModel, CurrentUserModel, UserInfoModel, UserRolePageQueryModel
|
||||
from module_admin.service.dept_service import DeptService
|
||||
from module_admin.service.role_service import RoleService
|
||||
from module_admin.service.user_service import UserService
|
||||
from utils.common_util import bytes2file_response
|
||||
from utils.log_util import logger
|
||||
from utils.response_util import ResponseUtil
|
||||
|
||||
role_controller = APIRouterPro(
|
||||
prefix='/system/role', order_num=4, tags=['系统管理-角色管理'], dependencies=[PreAuthDependency()]
|
||||
)
|
||||
|
||||
|
||||
@role_controller.get(
|
||||
'/deptTree/{role_id}',
|
||||
summary='获取自定义数据权限时可见的部门树接口',
|
||||
description='用于自定义数据权限时获取当前用户可见的部门树',
|
||||
response_model=DynamicResponseModel[RoleDeptQueryModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:role:query')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_ROLE_DEPT_TREE)
|
||||
async def get_system_role_dept_tree(
|
||||
request: Request,
|
||||
role_id: Annotated[int, Path(description='角色ID')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
dept_query_result = await DeptService.get_dept_tree_services(query_db, DeptModel(), data_scope_sql)
|
||||
role_dept_query_result = await RoleService.get_role_dept_tree_services(query_db, role_id)
|
||||
role_dept_query_result.depts = dept_query_result
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(model_content=role_dept_query_result)
|
||||
|
||||
|
||||
@role_controller.get(
|
||||
'/list',
|
||||
summary='获取角色分页列表接口',
|
||||
description='用于获取角色分页列表',
|
||||
response_model=PageResponseModel[RoleModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:role:list')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_ROLE_LIST)
|
||||
async def get_system_role_list(
|
||||
request: Request,
|
||||
role_page_query: Annotated[RolePageQueryModel, Query()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
role_page_query_result = await RoleService.get_role_list_services(
|
||||
query_db, role_page_query, data_scope_sql, is_page=True
|
||||
)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(model_content=role_page_query_result)
|
||||
|
||||
|
||||
@role_controller.post(
|
||||
'',
|
||||
summary='新增角色接口',
|
||||
description='用于新增角色',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:role:add')],
|
||||
)
|
||||
@ValidateFields(validate_model='add_role')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.ROLE_ENTITY_MUTATION)
|
||||
@Log(title='角色管理', business_type=BusinessType.INSERT)
|
||||
async def add_system_role(
|
||||
request: Request,
|
||||
add_role: AddRoleModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
add_role.create_by = current_user.user.user_name
|
||||
add_role.create_time = datetime.now()
|
||||
add_role.update_by = current_user.user.user_name
|
||||
add_role.update_time = datetime.now()
|
||||
add_role_result = await RoleService.add_role_services(query_db, add_role)
|
||||
logger.info(add_role_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=add_role_result.message)
|
||||
|
||||
|
||||
@role_controller.put(
|
||||
'',
|
||||
summary='编辑角色接口',
|
||||
description='用于编辑角色',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:role:edit')],
|
||||
)
|
||||
@ValidateFields(validate_model='edit_role')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.ROLE_PERMISSION_MUTATION)
|
||||
@Log(title='角色管理', business_type=BusinessType.UPDATE)
|
||||
async def edit_system_role(
|
||||
request: Request,
|
||||
edit_role: AddRoleModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
await RoleService.check_role_allowed_services(edit_role)
|
||||
if not current_user.user.admin:
|
||||
await RoleService.check_role_data_scope_services(query_db, str(edit_role.role_id), data_scope_sql)
|
||||
edit_role.update_by = current_user.user.user_name
|
||||
edit_role.update_time = datetime.now()
|
||||
edit_role_result = await RoleService.edit_role_services(query_db, edit_role)
|
||||
logger.info(edit_role_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=edit_role_result.message)
|
||||
|
||||
|
||||
@role_controller.put(
|
||||
'/dataScope',
|
||||
summary='编辑角色数据权限接口',
|
||||
description='用于编辑角色数据权限',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:role:edit')],
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.DATA_SCOPE_MUTATION)
|
||||
@Log(title='角色管理', business_type=BusinessType.GRANT)
|
||||
async def edit_system_role_datascope(
|
||||
request: Request,
|
||||
role_data_scope: AddRoleModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
await RoleService.check_role_allowed_services(role_data_scope)
|
||||
if not current_user.user.admin:
|
||||
await RoleService.check_role_data_scope_services(query_db, str(role_data_scope.role_id), data_scope_sql)
|
||||
edit_role = AddRoleModel(
|
||||
roleId=role_data_scope.role_id,
|
||||
dataScope=role_data_scope.data_scope,
|
||||
deptIds=role_data_scope.dept_ids,
|
||||
deptCheckStrictly=role_data_scope.dept_check_strictly,
|
||||
updateBy=current_user.user.user_name,
|
||||
updateTime=datetime.now(),
|
||||
)
|
||||
role_data_scope_result = await RoleService.role_datascope_services(query_db, edit_role)
|
||||
logger.info(role_data_scope_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=role_data_scope_result.message)
|
||||
|
||||
|
||||
@role_controller.delete(
|
||||
'/{role_ids}',
|
||||
summary='删除角色接口',
|
||||
description='用于删除角色',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:role:remove')],
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.ROLE_ENTITY_MUTATION)
|
||||
@Log(title='角色管理', business_type=BusinessType.DELETE)
|
||||
async def delete_system_role(
|
||||
request: Request,
|
||||
role_ids: Annotated[str, Path(description='需要删除的角色ID')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
role_id_list = role_ids.split(',') if role_ids else []
|
||||
if role_id_list:
|
||||
for role_id in role_id_list:
|
||||
await RoleService.check_role_allowed_services(RoleModel(roleId=int(role_id)))
|
||||
if not current_user.user.admin:
|
||||
await RoleService.check_role_data_scope_services(query_db, role_id, data_scope_sql)
|
||||
delete_role = DeleteRoleModel(roleIds=role_ids, updateBy=current_user.user.user_name, updateTime=datetime.now())
|
||||
delete_role_result = await RoleService.delete_role_services(query_db, delete_role)
|
||||
logger.info(delete_role_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=delete_role_result.message)
|
||||
|
||||
|
||||
@role_controller.get(
|
||||
'/{role_id}',
|
||||
summary='获取角色详情接口',
|
||||
description='用于获取指定角色的详细信息',
|
||||
response_model=DataResponseModel[RoleModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:role:query')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_ROLE_DETAIL)
|
||||
async def query_detail_system_role(
|
||||
request: Request,
|
||||
role_id: Annotated[int, Path(description='角色ID')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
if not current_user.user.admin:
|
||||
await RoleService.check_role_data_scope_services(query_db, str(role_id), data_scope_sql)
|
||||
role_detail_result = await RoleService.role_detail_services(query_db, role_id)
|
||||
logger.info(f'获取role_id为{role_id}的信息成功')
|
||||
|
||||
return ResponseUtil.success(data=role_detail_result.model_dump(by_alias=True))
|
||||
|
||||
|
||||
@role_controller.post(
|
||||
'/export',
|
||||
summary='导出角色列表接口',
|
||||
description='用于导出当前符合查询条件的角色列表数据',
|
||||
response_class=StreamingResponse,
|
||||
responses={
|
||||
200: {
|
||||
'description': '流式返回角色列表excel文件',
|
||||
'content': {
|
||||
'application/octet-stream': {},
|
||||
},
|
||||
}
|
||||
},
|
||||
dependencies=[UserInterfaceAuthDependency('system:role:export')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.SYSTEM_ROLE_EXPORT, preset=ApiRateLimitPreset.USER_RESOURCE_EXPORT)
|
||||
@Log(title='角色管理', business_type=BusinessType.EXPORT)
|
||||
async def export_system_role_list(
|
||||
request: Request,
|
||||
role_page_query: Annotated[RolePageQueryModel, Form()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
# 获取全量数据
|
||||
role_query_result = await RoleService.get_role_list_services(
|
||||
query_db, role_page_query, data_scope_sql, is_page=False
|
||||
)
|
||||
role_export_result = await RoleService.export_role_list_services(role_query_result)
|
||||
logger.info('导出成功')
|
||||
|
||||
return ResponseUtil.streaming(data=bytes2file_response(role_export_result))
|
||||
|
||||
|
||||
@role_controller.put(
|
||||
'/changeStatus',
|
||||
summary='修改角色状态接口',
|
||||
description='用于修改角色状态',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:role:edit')],
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.ROLE_MUTATION)
|
||||
@Log(title='角色管理', business_type=BusinessType.UPDATE)
|
||||
async def reset_system_role_status(
|
||||
request: Request,
|
||||
change_role: AddRoleModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
await RoleService.check_role_allowed_services(change_role)
|
||||
if not current_user.user.admin:
|
||||
await RoleService.check_role_data_scope_services(query_db, str(change_role.role_id), data_scope_sql)
|
||||
edit_role = AddRoleModel(
|
||||
roleId=change_role.role_id,
|
||||
status=change_role.status,
|
||||
updateBy=current_user.user.user_name,
|
||||
updateTime=datetime.now(),
|
||||
type='status',
|
||||
)
|
||||
edit_role_result = await RoleService.edit_role_services(query_db, edit_role)
|
||||
logger.info(edit_role_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=edit_role_result.message)
|
||||
|
||||
|
||||
@role_controller.get(
|
||||
'/authUser/allocatedList',
|
||||
summary='获取已分配用户分页列表接口',
|
||||
description='用于获取指定角色已分配的用户分页列表',
|
||||
response_model=PageResponseModel[UserInfoModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:role:list')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_ROLE_ALLOCATED_USER_LIST)
|
||||
async def get_system_allocated_user_list(
|
||||
request: Request,
|
||||
user_role: Annotated[UserRolePageQueryModel, Query()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysUser)],
|
||||
) -> Response:
|
||||
role_user_allocated_page_query_result = await RoleService.get_role_user_allocated_list_services(
|
||||
query_db, user_role, data_scope_sql, is_page=True
|
||||
)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(model_content=role_user_allocated_page_query_result)
|
||||
|
||||
|
||||
@role_controller.get(
|
||||
'/authUser/unallocatedList',
|
||||
summary='获取未分配用户分页列表接口',
|
||||
description='用于获取指定角色未分配的用户分页列表',
|
||||
response_model=PageResponseModel[UserInfoModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:role:list')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_ROLE_UNALLOCATED_USER_LIST)
|
||||
async def get_system_unallocated_user_list(
|
||||
request: Request,
|
||||
user_role: Annotated[UserRolePageQueryModel, Query()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysUser)],
|
||||
) -> Response:
|
||||
role_user_unallocated_page_query_result = await RoleService.get_role_user_unallocated_list_services(
|
||||
query_db, user_role, data_scope_sql, is_page=True
|
||||
)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(model_content=role_user_unallocated_page_query_result)
|
||||
|
||||
|
||||
@role_controller.put(
|
||||
'/authUser/selectAll',
|
||||
summary='分配用户给角色接口',
|
||||
description='用于给指定角色分配用户',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:role:edit')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.SYSTEM_ROLE_AUTH_USER_SELECT_ALL, preset=ApiRateLimitPreset.USER_SECURITY_MUTATION)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.ROLE_MUTATION)
|
||||
@Log(title='角色管理', business_type=BusinessType.GRANT)
|
||||
async def add_system_role_user(
|
||||
request: Request,
|
||||
add_role_user: Annotated[CrudUserRoleModel, Query()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
if not current_user.user.admin:
|
||||
await RoleService.check_role_data_scope_services(query_db, str(add_role_user.role_id), data_scope_sql)
|
||||
add_role_user_result = await UserService.add_user_role_services(query_db, add_role_user)
|
||||
logger.info(add_role_user_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=add_role_user_result.message)
|
||||
|
||||
|
||||
@role_controller.put(
|
||||
'/authUser/cancel',
|
||||
summary='取消分配用户给角色接口',
|
||||
description='用于取消指定用户分配给角色',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:role:edit')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.SYSTEM_ROLE_AUTH_USER_CANCEL, preset=ApiRateLimitPreset.USER_SECURITY_MUTATION)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.ROLE_MUTATION)
|
||||
@Log(title='角色管理', business_type=BusinessType.GRANT)
|
||||
async def cancel_system_role_user(
|
||||
request: Request,
|
||||
cancel_user_role: CrudUserRoleModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
cancel_user_role_result = await UserService.delete_user_role_services(query_db, cancel_user_role)
|
||||
logger.info(cancel_user_role_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=cancel_user_role_result.message)
|
||||
|
||||
|
||||
@role_controller.put(
|
||||
'/authUser/cancelAll',
|
||||
summary='批量取消分配用户给角色接口',
|
||||
description='用于批量取消用户分配给角色',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:role:edit')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.SYSTEM_ROLE_AUTH_USER_CANCEL_ALL, preset=ApiRateLimitPreset.USER_SECURITY_MUTATION)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.ROLE_MUTATION)
|
||||
@Log(title='角色管理', business_type=BusinessType.GRANT)
|
||||
async def batch_cancel_system_role_user(
|
||||
request: Request,
|
||||
batch_cancel_user_role: Annotated[CrudUserRoleModel, Query()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
batch_cancel_user_role_result = await UserService.delete_user_role_services(query_db, batch_cancel_user_role)
|
||||
logger.info(batch_cancel_user_role_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=batch_cancel_user_role_result.message)
|
||||
@@ -0,0 +1,32 @@
|
||||
from fastapi import Request, Response
|
||||
|
||||
from common.annotation.cache_annotation import ApiCache
|
||||
from common.aspect.interface_auth import UserInterfaceAuthDependency
|
||||
from common.aspect.pre_auth import PreAuthDependency
|
||||
from common.constant import ApiNamespace
|
||||
from common.router import APIRouterPro
|
||||
from common.vo import DataResponseModel
|
||||
from module_admin.entity.vo.server_vo import ServerMonitorModel
|
||||
from module_admin.service.server_service import ServerService
|
||||
from utils.log_util import logger
|
||||
from utils.response_util import ResponseUtil
|
||||
|
||||
server_controller = APIRouterPro(
|
||||
prefix='/monitor/server', order_num=14, tags=['系统监控-服务监控'], dependencies=[PreAuthDependency()]
|
||||
)
|
||||
|
||||
|
||||
@server_controller.get(
|
||||
'',
|
||||
summary='获取服务器监控信息接口',
|
||||
description='用于获取当前服务器的监控信息',
|
||||
response_model=DataResponseModel[ServerMonitorModel],
|
||||
dependencies=[UserInterfaceAuthDependency('monitor:server:list')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.MONITOR_SERVER_INFO)
|
||||
async def get_monitor_server_info(request: Request) -> Response:
|
||||
# 获取全量数据
|
||||
server_info_query_result = await ServerService.get_server_monitor_info()
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(data=server_info_query_result)
|
||||
@@ -0,0 +1,78 @@
|
||||
from fastapi import Request, Response
|
||||
|
||||
from common.annotation.rate_limit_annotation import ApiRateLimit, ApiRateLimitPreset
|
||||
from common.aspect.interface_auth import UserInterfaceAuthDependency
|
||||
from common.aspect.pre_auth import PreAuthDependency
|
||||
from common.constant import ApiNamespace
|
||||
from common.router import APIRouterPro
|
||||
from common.vo import DataResponseModel
|
||||
from module_admin.entity.vo.transport_crypto_vo import (
|
||||
TransportCryptoFrontendConfigModel,
|
||||
TransportCryptoMonitorModel,
|
||||
TransportCryptoPublicKeyModel,
|
||||
)
|
||||
from module_admin.service.transport_crypto_service import TransportCryptoService
|
||||
from utils.log_util import logger
|
||||
from utils.response_util import ResponseUtil
|
||||
|
||||
transport_crypto_controller = APIRouterPro(prefix='/transport/crypto', order_num=15, tags=['传输加密模块'])
|
||||
|
||||
|
||||
@transport_crypto_controller.get(
|
||||
'/frontend-config',
|
||||
summary='获取前端传输加密配置接口',
|
||||
description='公开接口,用于向前端下发当前传输层加解密启用状态与运行模式,供前端统一跟随后端策略',
|
||||
response_model=DataResponseModel[TransportCryptoFrontendConfigModel],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.TRANSPORT_CRYPTO_FRONTEND_CONFIG, preset=ApiRateLimitPreset.ANON_PUBLIC_METADATA)
|
||||
async def get_transport_frontend_config(request: Request) -> Response:
|
||||
"""
|
||||
获取当前前端传输层加解密运行配置
|
||||
|
||||
:param request: 当前请求对象
|
||||
:return: 前端传输层加解密运行配置响应
|
||||
"""
|
||||
transport_frontend_config = await TransportCryptoService.get_transport_frontend_config_services()
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(data=transport_frontend_config)
|
||||
|
||||
|
||||
@transport_crypto_controller.get(
|
||||
'/public-key',
|
||||
summary='获取传输加密公钥接口',
|
||||
description='公开接口,用于向前端下发当前可用的传输层加密公钥,已配置匿名限流保护',
|
||||
response_model=DataResponseModel[TransportCryptoPublicKeyModel],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.TRANSPORT_CRYPTO_PUBLIC_KEY, preset=ApiRateLimitPreset.ANON_PUBLIC_METADATA)
|
||||
async def get_transport_public_key(request: Request) -> Response:
|
||||
"""
|
||||
获取当前传输层加密公钥
|
||||
|
||||
:param request: 当前请求对象
|
||||
:return: 公钥下发响应
|
||||
"""
|
||||
transport_public_key = await TransportCryptoService.get_transport_public_key_services()
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(data=transport_public_key)
|
||||
|
||||
|
||||
@transport_crypto_controller.get(
|
||||
'/monitor',
|
||||
summary='获取传输层加解密监控信息接口',
|
||||
description='用于获取基于Redis聚合的传输层加解密运行状态与统计信息',
|
||||
response_model=DataResponseModel[TransportCryptoMonitorModel],
|
||||
dependencies=[PreAuthDependency(), UserInterfaceAuthDependency('monitor:transportCrypto:list')],
|
||||
)
|
||||
async def get_transport_crypto_monitor_info(request: Request) -> Response:
|
||||
"""
|
||||
获取基于Redis聚合的传输层加解密监控信息
|
||||
|
||||
:param request: 当前请求对象
|
||||
:return: 传输层加解密监控信息响应
|
||||
"""
|
||||
transport_crypto_monitor_info = await TransportCryptoService.get_transport_crypto_monitor_info_services(request)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(data=transport_crypto_monitor_info)
|
||||
@@ -0,0 +1,550 @@
|
||||
import os
|
||||
from datetime import datetime
|
||||
from typing import Annotated, Literal
|
||||
|
||||
import aiofiles
|
||||
from fastapi import File, Form, Path, Query, Request, Response, UploadFile
|
||||
from fastapi.responses import StreamingResponse
|
||||
from pydantic_validation_decorator import ValidateFields
|
||||
from sqlalchemy import ColumnElement
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.annotation.cache_annotation import ApiCache, ApiCacheEvict
|
||||
from common.annotation.log_annotation import Log
|
||||
from common.annotation.rate_limit_annotation import ApiRateLimit, ApiRateLimitBypassConfig, ApiRateLimitPreset
|
||||
from common.aspect.data_scope import DataScopeDependency
|
||||
from common.aspect.db_seesion import DBSessionDependency
|
||||
from common.aspect.interface_auth import UserInterfaceAuthDependency
|
||||
from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency
|
||||
from common.constant import ApiGroup, ApiNamespace
|
||||
from common.enums import BusinessType
|
||||
from common.router import APIRouterPro
|
||||
from common.vo import DataResponseModel, DynamicResponseModel, PageResponseModel, ResponseBaseModel
|
||||
from config.env import UploadConfig
|
||||
from module_admin.entity.do.dept_do import SysDept
|
||||
from module_admin.entity.do.user_do import SysUser
|
||||
from module_admin.entity.vo.dept_vo import DeptModel, DeptTreeModel
|
||||
from module_admin.entity.vo.user_vo import (
|
||||
AddUserModel,
|
||||
AvatarModel,
|
||||
CrudUserRoleModel,
|
||||
CurrentUserModel,
|
||||
DeleteUserModel,
|
||||
EditUserModel,
|
||||
ResetPasswordModel,
|
||||
ResetUserModel,
|
||||
UserDetailModel,
|
||||
UserInfoModel,
|
||||
UserModel,
|
||||
UserPageQueryModel,
|
||||
UserProfileModel,
|
||||
UserRoleQueryModel,
|
||||
UserRoleResponseModel,
|
||||
UserRowModel,
|
||||
)
|
||||
from module_admin.service.dept_service import DeptService
|
||||
from module_admin.service.role_service import RoleService
|
||||
from module_admin.service.user_service import UserService
|
||||
from utils.common_util import bytes2file_response
|
||||
from utils.log_util import logger
|
||||
from utils.pwd_util import PwdUtil
|
||||
from utils.response_util import ResponseUtil
|
||||
from utils.upload_util import UploadUtil
|
||||
|
||||
user_controller = APIRouterPro(
|
||||
prefix='/system/user', order_num=3, tags=['系统管理-用户管理'], dependencies=[PreAuthDependency()]
|
||||
)
|
||||
|
||||
|
||||
@user_controller.get(
|
||||
'/deptTree',
|
||||
summary='获取部门树接口',
|
||||
description='用于获取当前登录用户可见的部门树',
|
||||
response_model=DataResponseModel[list[DeptTreeModel]],
|
||||
dependencies=[UserInterfaceAuthDependency('system:user:list')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_USER_DEPT_TREE)
|
||||
async def get_system_dept_tree(
|
||||
request: Request,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
dept_query_result = await DeptService.get_dept_tree_services(query_db, DeptModel(), data_scope_sql)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(data=dept_query_result)
|
||||
|
||||
|
||||
@user_controller.get(
|
||||
'/list',
|
||||
summary='获取用户分页列表接口',
|
||||
description='用于获取用户分页列表',
|
||||
response_model=PageResponseModel[UserRowModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:user:list')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_USER_LIST)
|
||||
async def get_system_user_list(
|
||||
request: Request,
|
||||
user_page_query: Annotated[UserPageQueryModel, Query()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysUser)],
|
||||
) -> Response:
|
||||
# 获取分页数据
|
||||
user_page_query_result = await UserService.get_user_list_services(
|
||||
query_db, user_page_query, data_scope_sql, is_page=True
|
||||
)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(model_content=user_page_query_result)
|
||||
|
||||
|
||||
@user_controller.post(
|
||||
'',
|
||||
summary='新增用户接口',
|
||||
description='用于新增用户',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:user:add')],
|
||||
)
|
||||
@ValidateFields(validate_model='add_user')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.USER_ENTITY_MUTATION)
|
||||
@Log(title='用户管理', business_type=BusinessType.INSERT)
|
||||
async def add_system_user(
|
||||
request: Request,
|
||||
add_user: AddUserModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
dept_data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
role_data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
if not current_user.user.admin:
|
||||
await DeptService.check_dept_data_scope_services(query_db, add_user.dept_id, dept_data_scope_sql)
|
||||
await RoleService.check_role_data_scope_services(
|
||||
query_db, ','.join([str(item) for item in add_user.role_ids]), role_data_scope_sql
|
||||
)
|
||||
add_user.password = PwdUtil.get_password_hash(add_user.password)
|
||||
add_user.create_by = current_user.user.user_name
|
||||
add_user.create_time = datetime.now()
|
||||
add_user.update_by = current_user.user.user_name
|
||||
add_user.update_time = datetime.now()
|
||||
add_user_result = await UserService.add_user_services(query_db, add_user)
|
||||
logger.info(add_user_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=add_user_result.message)
|
||||
|
||||
|
||||
@user_controller.put(
|
||||
'',
|
||||
summary='编辑用户接口',
|
||||
description='用于编辑用户',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:user:edit')],
|
||||
)
|
||||
@ValidateFields(validate_model='edit_user')
|
||||
@ApiCacheEvict(namespaces=ApiGroup.USER_PERMISSION_MUTATION)
|
||||
@Log(title='用户管理', business_type=BusinessType.UPDATE)
|
||||
async def edit_system_user(
|
||||
request: Request,
|
||||
edit_user: EditUserModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
user_data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysUser)],
|
||||
dept_data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
role_data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
await UserService.check_user_allowed_services(edit_user)
|
||||
if not current_user.user.admin:
|
||||
await UserService.check_user_data_scope_services(query_db, edit_user.user_id, user_data_scope_sql)
|
||||
await DeptService.check_dept_data_scope_services(query_db, edit_user.dept_id, dept_data_scope_sql)
|
||||
await RoleService.check_role_data_scope_services(
|
||||
query_db, ','.join([str(item) for item in edit_user.role_ids]), role_data_scope_sql
|
||||
)
|
||||
edit_user.update_by = current_user.user.user_name
|
||||
edit_user.update_time = datetime.now()
|
||||
edit_user_result = await UserService.edit_user_services(query_db, edit_user)
|
||||
logger.info(edit_user_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=edit_user_result.message)
|
||||
|
||||
|
||||
@user_controller.delete(
|
||||
'/{user_ids}',
|
||||
summary='删除用户接口',
|
||||
description='用于删除用户',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:user:remove')],
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.USER_ENTITY_MUTATION)
|
||||
@Log(title='用户管理', business_type=BusinessType.DELETE)
|
||||
async def delete_system_user(
|
||||
request: Request,
|
||||
user_ids: Annotated[str, Path(description='需要删除的用户ID')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysUser)],
|
||||
) -> Response:
|
||||
user_id_list = user_ids.split(',') if user_ids else []
|
||||
if user_id_list:
|
||||
if current_user.user.user_id in list(map(int, user_id_list)):
|
||||
logger.warning('当前登录用户不能删除')
|
||||
|
||||
return ResponseUtil.failure(msg='当前登录用户不能删除')
|
||||
for user_id in user_id_list:
|
||||
await UserService.check_user_allowed_services(UserModel(userId=int(user_id)))
|
||||
if not current_user.user.admin:
|
||||
await UserService.check_user_data_scope_services(query_db, int(user_id), data_scope_sql)
|
||||
delete_user = DeleteUserModel(userIds=user_ids, updateBy=current_user.user.user_name, updateTime=datetime.now())
|
||||
delete_user_result = await UserService.delete_user_services(query_db, delete_user)
|
||||
logger.info(delete_user_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=delete_user_result.message)
|
||||
|
||||
|
||||
@user_controller.put(
|
||||
'/resetPwd',
|
||||
summary='重置用户密码接口',
|
||||
description='用于重置用户密码',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:user:resetPwd')],
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.USER_INFO_MUTATION)
|
||||
@Log(title='用户管理', business_type=BusinessType.UPDATE)
|
||||
async def reset_system_user_pwd(
|
||||
request: Request,
|
||||
reset_user: EditUserModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysUser)],
|
||||
) -> Response:
|
||||
await UserService.check_user_allowed_services(reset_user)
|
||||
if not current_user.user.admin:
|
||||
await UserService.check_user_data_scope_services(query_db, reset_user.user_id, data_scope_sql)
|
||||
edit_user = EditUserModel(
|
||||
userId=reset_user.user_id,
|
||||
password=PwdUtil.get_password_hash(reset_user.password),
|
||||
pwdUpdateDate=datetime.now(),
|
||||
updateBy=current_user.user.user_name,
|
||||
updateTime=datetime.now(),
|
||||
type='pwd',
|
||||
)
|
||||
edit_user_result = await UserService.edit_user_services(query_db, edit_user)
|
||||
logger.info(edit_user_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=edit_user_result.message)
|
||||
|
||||
|
||||
@user_controller.put(
|
||||
'/changeStatus',
|
||||
summary='修改用户状态接口',
|
||||
description='用于修改用户状态',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:user:edit')],
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.USER_INFO_MUTATION)
|
||||
@Log(title='用户管理', business_type=BusinessType.UPDATE)
|
||||
async def change_system_user_status(
|
||||
request: Request,
|
||||
change_user: EditUserModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysUser)],
|
||||
) -> Response:
|
||||
await UserService.check_user_allowed_services(change_user)
|
||||
if not current_user.user.admin:
|
||||
await UserService.check_user_data_scope_services(query_db, change_user.user_id, data_scope_sql)
|
||||
edit_user = EditUserModel(
|
||||
userId=change_user.user_id,
|
||||
status=change_user.status,
|
||||
updateBy=current_user.user.user_name,
|
||||
updateTime=datetime.now(),
|
||||
type='status',
|
||||
)
|
||||
edit_user_result = await UserService.edit_user_services(query_db, edit_user)
|
||||
logger.info(edit_user_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=edit_user_result.message)
|
||||
|
||||
|
||||
@user_controller.get(
|
||||
'/profile',
|
||||
summary='获取用户个人信息接口',
|
||||
description='用于获取当前登录用户的个人信息',
|
||||
response_model=DynamicResponseModel[UserProfileModel],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_USER_PROFILE)
|
||||
async def query_detail_system_user_profile(
|
||||
request: Request,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
profile_user_result = await UserService.user_profile_services(query_db, current_user.user.user_id)
|
||||
logger.info(f'获取user_id为{current_user.user.user_id}的信息成功')
|
||||
|
||||
return ResponseUtil.success(model_content=profile_user_result)
|
||||
|
||||
|
||||
@user_controller.get(
|
||||
'/{user_id}',
|
||||
summary='获取用户详情接口',
|
||||
description='用于获取指定用户的详情信息',
|
||||
response_model=DynamicResponseModel[UserDetailModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:user:query')],
|
||||
)
|
||||
@user_controller.get(
|
||||
'/',
|
||||
summary='获取用户岗位和角色列表接口',
|
||||
description='用于获取当前登录用户可见的岗位和角色列表',
|
||||
response_model=DynamicResponseModel[UserDetailModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:user:query')],
|
||||
)
|
||||
@ApiCache(namespace=ApiNamespace.SYSTEM_USER_DETAIL)
|
||||
async def query_detail_system_user(
|
||||
request: Request,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysUser)],
|
||||
user_id: int | Literal[''] | None = '',
|
||||
) -> Response:
|
||||
if user_id and not current_user.user.admin:
|
||||
await UserService.check_user_data_scope_services(query_db, user_id, data_scope_sql)
|
||||
detail_user_result = await UserService.user_detail_services(query_db, user_id)
|
||||
logger.info(f'获取user_id为{user_id}的信息成功')
|
||||
|
||||
return ResponseUtil.success(model_content=detail_user_result)
|
||||
|
||||
|
||||
@user_controller.post(
|
||||
'/profile/avatar',
|
||||
summary='修改用户头像接口',
|
||||
description='用于修改当前登录用户的头像',
|
||||
response_model=DynamicResponseModel[AvatarModel],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.SYSTEM_USER_PROFILE_AVATAR, preset=ApiRateLimitPreset.USER_RESOURCE_UPLOAD)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.USER_INFO_MUTATION)
|
||||
@Log(title='个人信息', business_type=BusinessType.UPDATE)
|
||||
async def change_system_user_profile_avatar(
|
||||
request: Request,
|
||||
avatarfile: Annotated[bytes, File()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
if avatarfile:
|
||||
relative_path = (
|
||||
f'avatar/{datetime.now().strftime("%Y")}/{datetime.now().strftime("%m")}/{datetime.now().strftime("%d")}'
|
||||
)
|
||||
dir_path = os.path.join(UploadConfig.UPLOAD_PATH, relative_path)
|
||||
try:
|
||||
os.makedirs(dir_path)
|
||||
except FileExistsError:
|
||||
pass
|
||||
avatar_name = f'avatar_{datetime.now().strftime("%Y%m%d%H%M%S")}{UploadConfig.UPLOAD_MACHINE}{UploadUtil.generate_random_number()}.png'
|
||||
avatar_path = os.path.join(dir_path, avatar_name)
|
||||
async with aiofiles.open(avatar_path, 'wb') as f:
|
||||
await f.write(avatarfile)
|
||||
edit_user = EditUserModel(
|
||||
userId=current_user.user.user_id,
|
||||
avatar=f'{UploadConfig.UPLOAD_PREFIX}/{relative_path}/{avatar_name}',
|
||||
updateBy=current_user.user.user_name,
|
||||
updateTime=datetime.now(),
|
||||
type='avatar',
|
||||
)
|
||||
edit_user_result = await UserService.edit_user_services(query_db, edit_user)
|
||||
logger.info(edit_user_result.message)
|
||||
|
||||
return ResponseUtil.success(model_content=AvatarModel(imgUrl=edit_user.avatar), msg=edit_user_result.message)
|
||||
return ResponseUtil.failure(msg='上传图片异常,请联系管理员')
|
||||
|
||||
|
||||
@user_controller.put(
|
||||
'/profile',
|
||||
summary='修改用户个人信息接口',
|
||||
description='用于修改当前登录用户的个人信息',
|
||||
response_model=ResponseBaseModel,
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.USER_INFO_MUTATION)
|
||||
@Log(title='个人信息', business_type=BusinessType.UPDATE)
|
||||
async def change_system_user_profile_info(
|
||||
request: Request,
|
||||
user_info: UserInfoModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
edit_user = EditUserModel(
|
||||
**user_info.model_dump(exclude_unset=True, by_alias=True, exclude={'role_ids', 'post_ids'}),
|
||||
userId=current_user.user.user_id,
|
||||
userName=current_user.user.user_name,
|
||||
updateBy=current_user.user.user_name,
|
||||
updateTime=datetime.now(),
|
||||
roleIds=current_user.user.role_ids.split(',') if current_user.user.role_ids else [],
|
||||
postIds=current_user.user.post_ids.split(',') if current_user.user.post_ids else [],
|
||||
role=current_user.user.role,
|
||||
)
|
||||
edit_user_result = await UserService.edit_user_services(query_db, edit_user)
|
||||
logger.info(edit_user_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=edit_user_result.message)
|
||||
|
||||
|
||||
@user_controller.put(
|
||||
'/profile/updatePwd',
|
||||
summary='修改用户密码接口',
|
||||
description='用于修改当前登录用户的密码',
|
||||
response_model=ResponseBaseModel,
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.USER_INFO_MUTATION)
|
||||
@Log(title='个人信息', business_type=BusinessType.UPDATE)
|
||||
async def reset_system_user_password(
|
||||
request: Request,
|
||||
reset_password: ResetPasswordModel,
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
) -> Response:
|
||||
reset_user = ResetUserModel(
|
||||
userId=current_user.user.user_id,
|
||||
oldPassword=reset_password.old_password,
|
||||
password=reset_password.new_password,
|
||||
pwdUpdateDate=datetime.now(),
|
||||
updateBy=current_user.user.user_name,
|
||||
updateTime=datetime.now(),
|
||||
)
|
||||
reset_user_result = await UserService.reset_user_services(query_db, reset_user)
|
||||
logger.info(reset_user_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=reset_user_result.message)
|
||||
|
||||
|
||||
@user_controller.post(
|
||||
'/importData',
|
||||
summary='批量导入用户接口',
|
||||
description='用于批量导入用户数据',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:user:import')],
|
||||
)
|
||||
@ApiRateLimit(
|
||||
namespace=ApiNamespace.SYSTEM_USER_IMPORT,
|
||||
preset=ApiRateLimitPreset.USER_RESOURCE_IMPORT,
|
||||
bypass=ApiRateLimitBypassConfig(roles=('admin',)),
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.DATA_SCOPE_MUTATION)
|
||||
@Log(title='用户管理', business_type=BusinessType.IMPORT)
|
||||
async def batch_import_system_user(
|
||||
request: Request,
|
||||
file: Annotated[UploadFile, File(...)],
|
||||
update_support: Annotated[bool, Query(alias='updateSupport')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
user_data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysUser)],
|
||||
dept_data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
batch_import_result = await UserService.batch_import_user_services(
|
||||
request, query_db, file, update_support, current_user, user_data_scope_sql, dept_data_scope_sql
|
||||
)
|
||||
logger.info(batch_import_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=batch_import_result.message)
|
||||
|
||||
|
||||
@user_controller.post(
|
||||
'/importTemplate',
|
||||
summary='获取用户导入模板接口',
|
||||
description='用于获取用户导入模板excel文件',
|
||||
response_class=StreamingResponse,
|
||||
responses={
|
||||
200: {
|
||||
'description': '流式返回导入用户模板excel文件',
|
||||
'content': {
|
||||
'application/octet-stream': {},
|
||||
},
|
||||
}
|
||||
},
|
||||
dependencies=[UserInterfaceAuthDependency('system:user:import')],
|
||||
)
|
||||
async def export_system_user_template(
|
||||
request: Request, query_db: Annotated[AsyncSession, DBSessionDependency()]
|
||||
) -> Response:
|
||||
user_import_template_result = await UserService.get_user_import_template_services()
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.streaming(data=bytes2file_response(user_import_template_result))
|
||||
|
||||
|
||||
@user_controller.post(
|
||||
'/export',
|
||||
summary='导出用户列表接口',
|
||||
description='用于导出当前符合查询条件的用户列表数据',
|
||||
response_class=StreamingResponse,
|
||||
responses={
|
||||
200: {
|
||||
'description': '流式返回用户列表excel文件',
|
||||
'content': {
|
||||
'application/octet-stream': {},
|
||||
},
|
||||
}
|
||||
},
|
||||
dependencies=[UserInterfaceAuthDependency('system:user:export')],
|
||||
)
|
||||
@ApiRateLimit(namespace=ApiNamespace.SYSTEM_USER_EXPORT, preset=ApiRateLimitPreset.USER_RESOURCE_EXPORT)
|
||||
@Log(title='用户管理', business_type=BusinessType.EXPORT)
|
||||
async def export_system_user_list(
|
||||
request: Request,
|
||||
user_page_query: Annotated[UserPageQueryModel, Form()],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysUser)],
|
||||
) -> Response:
|
||||
# 获取全量数据
|
||||
user_query_result = await UserService.get_user_list_services(
|
||||
query_db, user_page_query, data_scope_sql, is_page=False
|
||||
)
|
||||
user_export_result = await UserService.export_user_list_services(user_query_result)
|
||||
logger.info('导出成功')
|
||||
|
||||
return ResponseUtil.streaming(data=bytes2file_response(user_export_result))
|
||||
|
||||
|
||||
@user_controller.get(
|
||||
'/authRole/{user_id}',
|
||||
summary='获取用户已分配角色列表接口',
|
||||
description='用于获取指定用户已分配的角色列表',
|
||||
response_model=DynamicResponseModel[UserRoleResponseModel],
|
||||
dependencies=[UserInterfaceAuthDependency('system:user:query')],
|
||||
)
|
||||
async def get_system_allocated_role_list(
|
||||
request: Request,
|
||||
user_id: Annotated[int, Path(description='用户ID')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
) -> Response:
|
||||
user_role_query = UserRoleQueryModel(userId=user_id)
|
||||
user_role_allocated_query_result = await UserService.get_user_role_allocated_list_services(
|
||||
query_db, user_role_query
|
||||
)
|
||||
logger.info('获取成功')
|
||||
|
||||
return ResponseUtil.success(model_content=user_role_allocated_query_result)
|
||||
|
||||
|
||||
@user_controller.put(
|
||||
'/authRole',
|
||||
summary='给用户分配角色接口',
|
||||
description='用于给指定用户分配角色',
|
||||
response_model=ResponseBaseModel,
|
||||
dependencies=[UserInterfaceAuthDependency('system:user:edit')],
|
||||
)
|
||||
@ApiCacheEvict(namespaces=ApiGroup.USER_PERMISSION_MUTATION)
|
||||
@Log(title='用户管理', business_type=BusinessType.GRANT)
|
||||
async def update_system_role_user(
|
||||
request: Request,
|
||||
user_id: Annotated[int, Query(alias='userId')],
|
||||
role_ids: Annotated[str, Query(alias='roleIds')],
|
||||
query_db: Annotated[AsyncSession, DBSessionDependency()],
|
||||
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
|
||||
user_data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysUser)],
|
||||
role_data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
|
||||
) -> Response:
|
||||
if not current_user.user.admin:
|
||||
await UserService.check_user_data_scope_services(query_db, user_id, user_data_scope_sql)
|
||||
await RoleService.check_role_data_scope_services(query_db, role_ids, role_data_scope_sql)
|
||||
add_user_role_result = await UserService.add_user_role_services(
|
||||
query_db, CrudUserRoleModel(userId=user_id, roleIds=role_ids)
|
||||
)
|
||||
logger.info(add_user_role_result.message)
|
||||
|
||||
return ResponseUtil.success(msg=add_user_role_result.message)
|
||||
Reference in New Issue
Block a user