diff --git a/backend/apps/swagger/i18n.py b/backend/apps/swagger/i18n.py index 30aa423d..8f508377 100644 --- a/backend/apps/swagger/i18n.py +++ b/backend/apps/swagger/i18n.py @@ -47,6 +47,13 @@ def load_translation(lang: str) -> Dict[str, str]: "description": f"{PLACEHOLDER_PREFIX}ds_api" }, { + "name": "system_user", + "description": f"{PLACEHOLDER_PREFIX}system_user_api" + }, + { + "name": "system_ws", + "description": f"{PLACEHOLDER_PREFIX}system_ws_api" + } "name": "Table Relation", "description": f"{PLACEHOLDER_PREFIX}tr_api" }, diff --git a/backend/apps/swagger/locales/en.json b/backend/apps/swagger/locales/en.json index 84b22f85..53262a8d 100644 --- a/backend/apps/swagger/locales/en.json +++ b/backend/apps/swagger/locales/en.json @@ -23,6 +23,52 @@ "ds_upload_excel": "Upload Excel", "ds_excel": "File", + "system": "System Management", + "system_user_api": "User APIs", + "system_user_current_user": "Get Current User", + "system_user_current_user_desc": "Retrieve information of the currently logged-in user", + "system_user_grid": "Get User List", + "user_name": "Username", + "user_account": "Account", + "user_email": "User Email", + "page_num": "Page Number", + "page_size": "Page Size", + "keyword": "Search Keyword", + "status": "Status", + "origin": "Origin", + "oid": "Workspace ID", + "grid_items": "List Data", + "grid_total": "Total Count", + "grid_total_pages": "Total Pages", + "create_time": "Creation Time", + "language": "Language", + "switch_oid_api": "Switch Workspace", + "user_detail_api": "Get User Details", + "uid": "User ID", + "user_create_api": "Create User", + "user_update_api": "Update User", + "user_del_api": "Delete User", + "user_batchdel_api": "Batch Delete Users", + "language_change": "Change Language", + "reset_pwd": "Reset Password", + "update_pwd": "Update Password", + "update_status": "Toggle Status", + "origin_pwd": "Original Password", + "new_pwd": "New Password", + + "system_ws_api": "Workspace APIs", + "ws_user_grid_api": "Get Workspace User List", + "ws_user_bind_api": "Bind User to Workspace", + "ws_user_unbind_api": "Remove User from Workspace", + "ws_user_status_api": "Toggle User Role", + "ws_all_api": "Get All Workspaces", + "ws_create_api": "Create Workspace", + "ws_update_api": "Update Workspace", + "ws_query_api": "Get Workspace Details", + "ws_del_api": "Delete Workspace", + + "weight": "Weight (1: Admin, 0: Regular User)" + "per_api": "Data Permission", "per_save": "Save Permission", "per_delete": "Delete Permission", diff --git a/backend/apps/swagger/locales/zh.json b/backend/apps/swagger/locales/zh.json index c324e78c..5b1f7d2f 100644 --- a/backend/apps/swagger/locales/zh.json +++ b/backend/apps/swagger/locales/zh.json @@ -23,6 +23,52 @@ "ds_upload_excel": "上传Excel", "ds_excel": "文件", + "system": "系统管理", + "system_user_api": "用户接口", + "system_user_current_user": "查询当前用户", + "system_user_current_user_desc": "查询当前登录的用户信息", + "system_user_grid": "查询用户列表", + "user_name": "用户名", + "user_account": "账号", + "user_email": "用户邮箱", + "page_num": "页码", + "page_size": "页容量", + "keyword": "搜索关键字", + "status": "状态", + "origin": "来源", + "oid": "空间ID", + "grid_items": "列表数据", + "grid_total": "总数量", + "grid_total_pages": "总页数", + "create_time": "创建时间", + "language": "语言", + "switch_oid_api": "切换工作空间", + "user_detail_api": "查询用户详情", + "uid": "用户ID", + "user_create_api": "创建用户", + "user_update_api": "修改用户", + "user_del_api": "删除用户", + "user_batchdel_api": "批量删除用户", + "language_change": "切换语言", + "reset_pwd": "重置密码", + "update_pwd": "修改密码", + "update_status": "切换状态", + "origin_pwd": "原始密码", + "new_pwd": "新密码", + + "system_ws_api": "工作空间接口", + "ws_user_grid_api": "查询工作空间下用户列表", + "ws_user_bind_api": "工作空间绑定用户", + "ws_user_unbind_api": "工作空间移除用户", + "ws_user_status_api": "切换用户角色", + "ws_all_api": "查询所有工作空间", + "ws_create_api": "创建工作空间", + "ws_update_api": "修改工作空间", + "ws_query_api": "查询工作空间详情", + "ws_del_api": "删除工作空间", + + "weight": "权重(1: 管理员, 0: 普通用户)" + "per_api": "数据权限", "per_save": "保存权限", "per_delete": "删除权限", @@ -33,4 +79,4 @@ "tr_api": "表关联关系", "tr_save": "保存关联关系", "tr_get": "查询关联关系" -} \ No newline at end of file +} diff --git a/backend/apps/system/api/user.py b/backend/apps/system/api/user.py index adc5096c..078754a3 100644 --- a/backend/apps/system/api/user.py +++ b/backend/apps/system/api/user.py @@ -1,42 +1,44 @@ from collections import defaultdict from typing import Optional -from fastapi import APIRouter, Query +from fastapi import APIRouter, Path, Query +from pydantic import Field from sqlmodel import SQLModel, or_, select, delete as sqlmodel_delete from apps.system.crud.user import check_account_exists, check_email_exists, check_email_format, check_pwd_format, get_db_user, single_delete, user_ws_options from apps.system.models.system_model import UserWsModel, WorkspaceModel from apps.system.models.user import UserModel from apps.system.schemas.auth import CacheName, CacheNamespace from apps.system.schemas.permission import SqlbotPermission, require_permissions -from apps.system.schemas.system_schema import PwdEditor, UserCreator, UserEditor, UserGrid, UserLanguage, UserStatus, UserWs +from apps.system.schemas.system_schema import PwdEditor, UserCreator, UserEditor, UserGrid, UserInfoDTO, UserLanguage, UserStatus, UserWs from common.core.deps import CurrentUser, SessionDep, Trans from common.core.pagination import Paginator from common.core.schemas import PaginatedResponse, PaginationParams from common.core.security import default_md5_pwd, md5pwd, verify_md5pwd from common.core.sqlbot_cache import clear_cache from common.core.config import settings +from apps.swagger.i18n import PLACEHOLDER_PREFIX -router = APIRouter(tags=["user"], prefix="/user") +router = APIRouter(tags=["system_user"], prefix="/user") -@router.get("/info") -async def user_info(current_user: CurrentUser): +@router.get("/info", summary=f"{PLACEHOLDER_PREFIX}system_user_current_user", description=f"{PLACEHOLDER_PREFIX}system_user_current_user_desc") +async def user_info(current_user: CurrentUser) -> UserInfoDTO: return current_user -@router.get("/defaultPwd") +@router.get("/defaultPwd", include_in_schema=False) @require_permissions(permission=SqlbotPermission(role=['admin'])) async def default_pwd() -> str: return settings.DEFAULT_PWD -@router.get("/pager/{pageNum}/{pageSize}", response_model=PaginatedResponse[UserGrid]) +@router.get("/pager/{pageNum}/{pageSize}", response_model=PaginatedResponse[UserGrid], summary=f"{PLACEHOLDER_PREFIX}system_user_grid", description=f"{PLACEHOLDER_PREFIX}system_user_grid") @require_permissions(permission=SqlbotPermission(role=['admin'])) async def pager( session: SessionDep, - pageNum: int, - pageSize: int, - keyword: Optional[str] = Query(None, description="搜索关键字(可选)"), - status: Optional[int] = Query(None, description="状态"), - origins: Optional[list[int]] = Query(None, description="来源"), - oidlist: Optional[list[int]] = Query(None, description="空间ID集合(可选)"), + pageNum: int = Path(..., title=f"{PLACEHOLDER_PREFIX}page_num", description=f"{PLACEHOLDER_PREFIX}page_num"), + pageSize: int = Path(..., title=f"{PLACEHOLDER_PREFIX}page_size", description=f"{PLACEHOLDER_PREFIX}page_size"), + keyword: Optional[str] = Query(None, description=f"{PLACEHOLDER_PREFIX}keyword"), + status: Optional[int] = Query(None, description=f"{PLACEHOLDER_PREFIX}status"), + origins: Optional[list[int]] = Query(None, description=f"{PLACEHOLDER_PREFIX}origin"), + oidlist: Optional[list[int]] = Query(None, description=f"{PLACEHOLDER_PREFIX}oid"), ): pagination = PaginationParams(page=pageNum, size=pageSize) paginator = Paginator(session) @@ -108,13 +110,14 @@ def format_user_dict(row) -> dict: result_dict[key] = item return result_dict -@router.get("/ws") + +@router.get("/ws", include_in_schema=False) async def ws_options(session: SessionDep, current_user: CurrentUser, trans: Trans) -> list[UserWs]: return await user_ws_options(session, current_user.id, trans) -@router.put("/ws/{oid}") +@router.put("/ws/{oid}", summary=f"{PLACEHOLDER_PREFIX}switch_oid_api", description=f"{PLACEHOLDER_PREFIX}switch_oid_api") @clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id") -async def ws_change(session: SessionDep, current_user: CurrentUser, trans:Trans, oid: int): +async def ws_change(session: SessionDep, current_user: CurrentUser, trans:Trans, oid: int = Path(description=f"{PLACEHOLDER_PREFIX}oid")): ws_list: list[UserWs] = await user_ws_options(session, current_user.id) if not any(x.id == oid for x in ws_list): db_ws = session.get(WorkspaceModel, oid) @@ -126,9 +129,9 @@ async def ws_change(session: SessionDep, current_user: CurrentUser, trans:Trans, session.add(user_model) session.commit() -@router.get("/{id}", response_model=UserEditor) +@router.get("/{id}", response_model=UserEditor, summary=f"{PLACEHOLDER_PREFIX}user_detail_api", description=f"{PLACEHOLDER_PREFIX}user_detail_api") @require_permissions(permission=SqlbotPermission(role=['admin'])) -async def query(session: SessionDep, trans: Trans, id: int) -> UserEditor: +async def query(session: SessionDep, trans: Trans, id: int = Path(description=f"{PLACEHOLDER_PREFIX}uid")) -> UserEditor: db_user: UserModel = get_db_user(session = session, user_id = id) u_ws_options = await user_ws_options(session, id, trans) result = UserEditor.model_validate(db_user.model_dump()) @@ -137,7 +140,7 @@ async def query(session: SessionDep, trans: Trans, id: int) -> UserEditor: return result -@router.post("") +@router.post("", summary=f"{PLACEHOLDER_PREFIX}user_create_api", description=f"{PLACEHOLDER_PREFIX}user_create_api") @require_permissions(permission=SqlbotPermission(role=['admin'])) async def create(session: SessionDep, creator: UserCreator, trans: Trans): if check_account_exists(session=session, account=creator.account): @@ -167,7 +170,7 @@ async def create(session: SessionDep, creator: UserCreator, trans: Trans): session.commit() -@router.put("") +@router.put("", summary=f"{PLACEHOLDER_PREFIX}user_update_api", description=f"{PLACEHOLDER_PREFIX}user_update_api") @require_permissions(permission=SqlbotPermission(role=['admin'])) @clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="editor.id") async def update(session: SessionDep, editor: UserEditor, trans: Trans): @@ -203,18 +206,18 @@ async def update(session: SessionDep, editor: UserEditor, trans: Trans): session.add(user_model) session.commit() -@router.delete("/{id}") +@router.delete("/{id}", summary=f"{PLACEHOLDER_PREFIX}user_del_api", description=f"{PLACEHOLDER_PREFIX}user_del_api") @require_permissions(permission=SqlbotPermission(role=['admin'])) -async def delete(session: SessionDep, id: int): +async def delete(session: SessionDep, id: int = Path(description=f"{PLACEHOLDER_PREFIX}uid")): await single_delete(session, id) -@router.delete("") +@router.delete("", summary=f"{PLACEHOLDER_PREFIX}user_batchdel_api", description=f"{PLACEHOLDER_PREFIX}user_batchdel_api") @require_permissions(permission=SqlbotPermission(role=['admin'])) async def batch_del(session: SessionDep, id_list: list[int]): for id in id_list: await single_delete(session, id) -@router.put("/language") +@router.put("/language", summary=f"{PLACEHOLDER_PREFIX}language_change", description=f"{PLACEHOLDER_PREFIX}language_change") @clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id") async def langChange(session: SessionDep, current_user: CurrentUser, trans: Trans, language: UserLanguage): lang = language.language @@ -226,10 +229,10 @@ async def langChange(session: SessionDep, current_user: CurrentUser, trans: Tran session.commit() -@router.patch("/pwd/{id}") +@router.patch("/pwd/{id}", summary=f"{PLACEHOLDER_PREFIX}reset_pwd", description=f"{PLACEHOLDER_PREFIX}reset_pwd") @require_permissions(permission=SqlbotPermission(role=['admin'])) @clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="id") -async def pwdReset(session: SessionDep, current_user: CurrentUser, trans: Trans, id: int): +async def pwdReset(session: SessionDep, current_user: CurrentUser, trans: Trans, id: int = Path(description=f"{PLACEHOLDER_PREFIX}uid")): if not current_user.isAdmin: raise Exception(trans('i18n_permission.no_permission', url = " patch[/user/pwd/id],", msg = trans('i18n_permission.only_admin'))) db_user: UserModel = get_db_user(session=session, user_id=id) @@ -237,7 +240,7 @@ async def pwdReset(session: SessionDep, current_user: CurrentUser, trans: Trans, session.add(db_user) session.commit() -@router.put("/pwd") +@router.put("/pwd", summary=f"{PLACEHOLDER_PREFIX}update_pwd", description=f"{PLACEHOLDER_PREFIX}update_pwd") @clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id") async def pwdUpdate(session: SessionDep, current_user: CurrentUser, trans: Trans, editor: PwdEditor): new_pwd = editor.new_pwd @@ -251,10 +254,10 @@ async def pwdUpdate(session: SessionDep, current_user: CurrentUser, trans: Trans session.commit() -@router.patch("/status") +@router.patch("/status", summary=f"{PLACEHOLDER_PREFIX}update_status", description=f"{PLACEHOLDER_PREFIX}update_status") @require_permissions(permission=SqlbotPermission(role=['admin'])) @clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="statusDto.id") -async def langChange(session: SessionDep, current_user: CurrentUser, trans: Trans, statusDto: UserStatus): +async def statusChange(session: SessionDep, current_user: CurrentUser, trans: Trans, statusDto: UserStatus): if not current_user.isAdmin: raise Exception(trans('i18n_permission.no_permission', url = ", ", msg = trans('i18n_permission.only_admin'))) status = statusDto.status diff --git a/backend/apps/system/api/workspace.py b/backend/apps/system/api/workspace.py index 1dd9a091..aa5f6fa2 100644 --- a/backend/apps/system/api/workspace.py +++ b/backend/apps/system/api/workspace.py @@ -1,6 +1,7 @@ from typing import Optional -from fastapi import APIRouter, HTTPException, Query +from fastapi import APIRouter, HTTPException, Path, Query from sqlmodel import exists, or_, select, delete as sqlmodel_delete, update as sqlmodel_update +from apps.swagger.i18n import PLACEHOLDER_PREFIX from apps.system.crud.user import clean_user_cache from apps.system.crud.workspace import reset_single_user_oid, reset_user_oid from apps.system.models.system_model import UserWsModel, WorkspaceBase, WorkspaceEditor, WorkspaceModel @@ -12,18 +13,18 @@ from common.core.schemas import PaginatedResponse, PaginationParams from common.utils.time import get_timestamp -router = APIRouter(tags=["system/workspace"], prefix="/system/workspace") +router = APIRouter(tags=["system_ws"], prefix="/system/workspace") -@router.get("/uws/option/pager/{pageNum}/{pageSize}", response_model=PaginatedResponse[UserWsOption]) +@router.get("/uws/option/pager/{pageNum}/{pageSize}", response_model=PaginatedResponse[UserWsOption], summary=f"{PLACEHOLDER_PREFIX}ws_user_grid_api", description=f"{PLACEHOLDER_PREFIX}ws_user_grid_api") @require_permissions(permission=SqlbotPermission(role=['ws_admin'])) async def option_pager( session: SessionDep, current_user: CurrentUser, trans: Trans, - pageNum: int, - pageSize: int, - oid: int = Query(description="空间ID"), - keyword: Optional[str] = Query(None, description="搜索关键字(可选)"), + pageNum: int = Path(description=f"{PLACEHOLDER_PREFIX}page_num"), + pageSize: int = Path(description=f"{PLACEHOLDER_PREFIX}page_size"), + oid: int = Query(description=f"{PLACEHOLDER_PREFIX}oid"), + keyword: Optional[str] = Query(None, description=f"{PLACEHOLDER_PREFIX}keyword"), ): if not current_user.isAdmin: raise Exception(trans('i18n_permission.no_permission', url = ", ", msg = trans('i18n_permission.only_admin'))) @@ -49,7 +50,7 @@ async def option_pager( pagination=pagination, ) -@router.get("/uws/option", response_model=UserWsOption | None) +@router.get("/uws/option", response_model=UserWsOption | None, include_in_schema=False) @require_permissions(permission=SqlbotPermission(role=['ws_admin'])) async def option_user( session: SessionDep, @@ -78,7 +79,7 @@ async def option_user( return session.exec(stmt).first() -@router.get("/uws/pager/{pageNum}/{pageSize}", response_model=PaginatedResponse[WorkspaceUser]) +@router.get("/uws/pager/{pageNum}/{pageSize}", response_model=PaginatedResponse[WorkspaceUser], include_in_schema=False) @require_permissions(permission=SqlbotPermission(role=['ws_admin'])) async def pager( session: SessionDep, @@ -119,7 +120,7 @@ async def pager( ) -@router.post("/uws") +@router.post("/uws", summary=f"{PLACEHOLDER_PREFIX}ws_user_bind_api", description=f"{PLACEHOLDER_PREFIX}ws_user_bind_api") @require_permissions(permission=SqlbotPermission(role=['ws_admin'])) async def create(session: SessionDep, current_user: CurrentUser, trans: Trans, creator: UserWsDTO): if not current_user.isAdmin and current_user.weight == 0: @@ -142,7 +143,7 @@ async def create(session: SessionDep, current_user: CurrentUser, trans: Trans, c session.add_all(db_model_list) session.commit() -@router.put("/uws") +@router.put("/uws", summary=f"{PLACEHOLDER_PREFIX}ws_user_status_api", description=f"{PLACEHOLDER_PREFIX}ws_user_status_api") @require_permissions(permission=SqlbotPermission(role=['admin'])) async def edit(session: SessionDep, trans: Trans, editor: UserWsEditor): if not editor.oid or not editor.uid: @@ -159,7 +160,7 @@ async def edit(session: SessionDep, trans: Trans, editor: UserWsEditor): await clean_user_cache(editor.uid) session.commit() -@router.delete("/uws") +@router.delete("/uws", summary=f"{PLACEHOLDER_PREFIX}ws_user_unbind_api", description=f"{PLACEHOLDER_PREFIX}ws_user_unbind_api") @require_permissions(permission=SqlbotPermission(role=['ws_admin'])) async def delete(session: SessionDep, current_user: CurrentUser, trans: Trans, dto: UserWsBase): if not current_user.isAdmin and current_user.weight == 0: @@ -177,7 +178,7 @@ async def delete(session: SessionDep, current_user: CurrentUser, trans: Trans, d session.commit() -@router.get("", response_model=list[WorkspaceModel]) +@router.get("", response_model=list[WorkspaceModel], summary=f"{PLACEHOLDER_PREFIX}ws_all_api", description=f"{PLACEHOLDER_PREFIX}ws_all_api") @require_permissions(permission=SqlbotPermission(role=['admin'])) async def query(session: SessionDep, trans: Trans): list_result = session.exec(select(WorkspaceModel)).all() @@ -187,7 +188,7 @@ async def query(session: SessionDep, trans: Trans): list_result.sort(key=lambda x: x.name) return list_result -@router.post("") +@router.post("", summary=f"{PLACEHOLDER_PREFIX}ws_create_api", description=f"{PLACEHOLDER_PREFIX}ws_create_api") @require_permissions(permission=SqlbotPermission(role=['admin'])) async def add(session: SessionDep, creator: WorkspaceBase): db_model = WorkspaceModel.model_validate(creator) @@ -195,7 +196,7 @@ async def add(session: SessionDep, creator: WorkspaceBase): session.add(db_model) session.commit() -@router.put("") +@router.put("", summary=f"{PLACEHOLDER_PREFIX}ws_update_api", description=f"{PLACEHOLDER_PREFIX}ws_update_api") @require_permissions(permission=SqlbotPermission(role=['admin'])) async def update(session: SessionDep, editor: WorkspaceEditor): id = editor.id @@ -206,9 +207,9 @@ async def update(session: SessionDep, editor: WorkspaceEditor): session.add(db_model) session.commit() -@router.get("/{id}", response_model=WorkspaceModel) +@router.get("/{id}", response_model=WorkspaceModel, summary=f"{PLACEHOLDER_PREFIX}ws_query_api", description=f"{PLACEHOLDER_PREFIX}ws_query_api") @require_permissions(permission=SqlbotPermission(role=['admin'])) -async def get_one(session: SessionDep, trans: Trans, id: int): +async def get_one(session: SessionDep, trans: Trans, id: int = Path(description=f"{PLACEHOLDER_PREFIX}oid")): db_model = session.get(WorkspaceModel, id) if not db_model: raise HTTPException(f"WorkspaceModel with id {id} not found") @@ -216,9 +217,9 @@ async def get_one(session: SessionDep, trans: Trans, id: int): db_model.name = trans(db_model.name) return db_model -@router.delete("/{id}") +@router.delete("/{id}", summary=f"{PLACEHOLDER_PREFIX}ws_del_api", description=f"{PLACEHOLDER_PREFIX}ws_del_api") @require_permissions(permission=SqlbotPermission(role=['admin'])) -async def single_delete(session: SessionDep, current_user: CurrentUser, id: int): +async def single_delete(session: SessionDep, current_user: CurrentUser, id: int = Path(description=f"{PLACEHOLDER_PREFIX}oid")): if not current_user.isAdmin: raise HTTPException("only admin can delete workspace") if id == 1: diff --git a/backend/apps/system/schemas/system_schema.py b/backend/apps/system/schemas/system_schema.py index 60247c3c..b23361e9 100644 --- a/backend/apps/system/schemas/system_schema.py +++ b/backend/apps/system/schemas/system_schema.py @@ -3,6 +3,7 @@ from pydantic import BaseModel, Field, field_validator +from apps.swagger.i18n import PLACEHOLDER_PREFIX from common.core.schemas import BaseCreatorDTO EMAIL_REGEX = re.compile( @@ -18,11 +19,11 @@ class UserStatus(BaseCreatorDTO): - status: int = 1 + status: int = Field(default=1, description=f"{PLACEHOLDER_PREFIX}status") class UserLanguage(BaseModel): - language: str + language: str = Field(description=f"{PLACEHOLDER_PREFIX}language") class BaseUser(BaseModel): @@ -51,11 +52,11 @@ def validate_language(cls, lang: str) -> str: class UserCreator(BaseUser): - name: str = Field(min_length=1, max_length=100, description="用户名") - email: str = Field(min_length=1, max_length=100, description="用户邮箱") - status: int = 1 - origin: Optional[int] = 0 - oid_list: Optional[list[int]] = None + name: str = Field(min_length=1, max_length=100, description=f"{PLACEHOLDER_PREFIX}user_name") + email: str = Field(min_length=1, max_length=100, description=f"{PLACEHOLDER_PREFIX}user_email") + status: int = Field(default=1, description=f"{PLACEHOLDER_PREFIX}status") + origin: Optional[int] = Field(default=0, description=f"{PLACEHOLDER_PREFIX}origin") + oid_list: Optional[list[int]] = Field(default=None, description=f"{PLACEHOLDER_PREFIX}oid") """ @field_validator("email") def validate_email(cls, lang: str) -> str: @@ -69,30 +70,30 @@ class UserEditor(UserCreator, BaseCreatorDTO): class UserGrid(UserEditor): - create_time: int - language: str = "zh-CN" + create_time: int = Field(description=f"{PLACEHOLDER_PREFIX}create_time") + language: str = Field(default="zh-CN" ,description=f"{PLACEHOLDER_PREFIX}language") # space_name: Optional[str] = None # origin: str = '' class PwdEditor(BaseModel): - pwd: str - new_pwd: str + pwd: str = Field(description=f"{PLACEHOLDER_PREFIX}origin_pwd") + new_pwd: str = Field(description=f"{PLACEHOLDER_PREFIX}new_pwd") class UserWsBase(BaseModel): - uid_list: list[int] - oid: Optional[int] = None + uid_list: list[int] = Field(description=f"{PLACEHOLDER_PREFIX}uid") + oid: Optional[int] = Field(default=None, description=f"{PLACEHOLDER_PREFIX}oid") class UserWsDTO(UserWsBase): - weight: Optional[int] = 0 + weight: Optional[int] = Field(default=0, description=f"{PLACEHOLDER_PREFIX}weight") class UserWsEditor(BaseModel): - uid: int - oid: int - weight: int = 0 + uid: int = Field(description=f"{PLACEHOLDER_PREFIX}uid") + oid: int = Field(description=f"{PLACEHOLDER_PREFIX}oid") + weight: int = Field(default=0, description=f"{PLACEHOLDER_PREFIX}weight") class UserInfoDTO(UserEditor): @@ -149,11 +150,11 @@ class WorkspaceUser(UserEditor): class UserWs(BaseCreatorDTO): - name: str + name: str = Field(description="user_name") class UserWsOption(UserWs): - account: str + account: str = Field(description="user_account") class AssistantFieldSchema(BaseModel): diff --git a/backend/common/core/schemas.py b/backend/common/core/schemas.py index 48b4e57e..04c3d5ea 100644 --- a/backend/common/core/schemas.py +++ b/backend/common/core/schemas.py @@ -1,8 +1,9 @@ from fastapi import HTTPException, Request from fastapi.security import OAuth2PasswordBearer -from pydantic import BaseModel +from pydantic import BaseModel, Field from sqlmodel import SQLModel from starlette.status import HTTP_403_FORBIDDEN, HTTP_401_UNAUTHORIZED +from apps.swagger.i18n import PLACEHOLDER_PREFIX from common.core.config import settings from fastapi.security.utils import get_authorization_scheme_param from typing import Generic, TypeVar, Optional @@ -46,15 +47,15 @@ class PaginationParams(BaseModel): desc: bool = False class PaginatedResponse(BaseModel, Generic[T]): - items: list[T] - total: int - page: int - size: int - total_pages: int + items: list[T] = Field(description=f"{PLACEHOLDER_PREFIX}grid_items") + total: int = Field(description=f"{PLACEHOLDER_PREFIX}grid_total") + page: int = Field(description=f"{PLACEHOLDER_PREFIX}page_num") + size: int = Field(description=f"{PLACEHOLDER_PREFIX}page_size") + total_pages: int = Field(description=f"{PLACEHOLDER_PREFIX}grid_total_pages") class BaseCreatorDTO(BaseModel): - id: int + id: int = Field(description="ID") class Config: json_encoders = { int: lambda v: str(v) if isinstance(v, int) and v > (2**53 - 1) else v