Skip to content

Commit 941167c

Browse files
feat: API documentation for user and workspace (#615)
1 parent 589c85b commit 941167c

File tree

7 files changed

+180
-75
lines changed

7 files changed

+180
-75
lines changed

backend/apps/swagger/i18n.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ def load_translation(lang: str) -> Dict[str, str]:
4747
"description": f"{PLACEHOLDER_PREFIX}ds_api"
4848
},
4949
{
50+
"name": "system_user",
51+
"description": f"{PLACEHOLDER_PREFIX}system_user_api"
52+
},
53+
{
54+
"name": "system_ws",
55+
"description": f"{PLACEHOLDER_PREFIX}system_ws_api"
56+
}
5057
"name": "Table Relation",
5158
"description": f"{PLACEHOLDER_PREFIX}tr_api"
5259
},

backend/apps/swagger/locales/en.json

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,52 @@
2323
"ds_upload_excel": "Upload Excel",
2424
"ds_excel": "File",
2525

26+
"system": "System Management",
27+
"system_user_api": "User APIs",
28+
"system_user_current_user": "Get Current User",
29+
"system_user_current_user_desc": "Retrieve information of the currently logged-in user",
30+
"system_user_grid": "Get User List",
31+
"user_name": "Username",
32+
"user_account": "Account",
33+
"user_email": "User Email",
34+
"page_num": "Page Number",
35+
"page_size": "Page Size",
36+
"keyword": "Search Keyword",
37+
"status": "Status",
38+
"origin": "Origin",
39+
"oid": "Workspace ID",
40+
"grid_items": "List Data",
41+
"grid_total": "Total Count",
42+
"grid_total_pages": "Total Pages",
43+
"create_time": "Creation Time",
44+
"language": "Language",
45+
"switch_oid_api": "Switch Workspace",
46+
"user_detail_api": "Get User Details",
47+
"uid": "User ID",
48+
"user_create_api": "Create User",
49+
"user_update_api": "Update User",
50+
"user_del_api": "Delete User",
51+
"user_batchdel_api": "Batch Delete Users",
52+
"language_change": "Change Language",
53+
"reset_pwd": "Reset Password",
54+
"update_pwd": "Update Password",
55+
"update_status": "Toggle Status",
56+
"origin_pwd": "Original Password",
57+
"new_pwd": "New Password",
58+
59+
"system_ws_api": "Workspace APIs",
60+
"ws_user_grid_api": "Get Workspace User List",
61+
"ws_user_bind_api": "Bind User to Workspace",
62+
"ws_user_unbind_api": "Remove User from Workspace",
63+
"ws_user_status_api": "Toggle User Role",
64+
"ws_all_api": "Get All Workspaces",
65+
"ws_create_api": "Create Workspace",
66+
"ws_update_api": "Update Workspace",
67+
"ws_query_api": "Get Workspace Details",
68+
"ws_del_api": "Delete Workspace",
69+
70+
"weight": "Weight (1: Admin, 0: Regular User)"
71+
2672
"per_api": "Data Permission",
2773
"per_save": "Save Permission",
2874
"per_delete": "Delete Permission",

backend/apps/swagger/locales/zh.json

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,52 @@
2323
"ds_upload_excel": "上传Excel",
2424
"ds_excel": "文件",
2525

26+
"system": "系统管理",
27+
"system_user_api": "用户接口",
28+
"system_user_current_user": "查询当前用户",
29+
"system_user_current_user_desc": "查询当前登录的用户信息",
30+
"system_user_grid": "查询用户列表",
31+
"user_name": "用户名",
32+
"user_account": "账号",
33+
"user_email": "用户邮箱",
34+
"page_num": "页码",
35+
"page_size": "页容量",
36+
"keyword": "搜索关键字",
37+
"status": "状态",
38+
"origin": "来源",
39+
"oid": "空间ID",
40+
"grid_items": "列表数据",
41+
"grid_total": "总数量",
42+
"grid_total_pages": "总页数",
43+
"create_time": "创建时间",
44+
"language": "语言",
45+
"switch_oid_api": "切换工作空间",
46+
"user_detail_api": "查询用户详情",
47+
"uid": "用户ID",
48+
"user_create_api": "创建用户",
49+
"user_update_api": "修改用户",
50+
"user_del_api": "删除用户",
51+
"user_batchdel_api": "批量删除用户",
52+
"language_change": "切换语言",
53+
"reset_pwd": "重置密码",
54+
"update_pwd": "修改密码",
55+
"update_status": "切换状态",
56+
"origin_pwd": "原始密码",
57+
"new_pwd": "新密码",
58+
59+
"system_ws_api": "工作空间接口",
60+
"ws_user_grid_api": "查询工作空间下用户列表",
61+
"ws_user_bind_api": "工作空间绑定用户",
62+
"ws_user_unbind_api": "工作空间移除用户",
63+
"ws_user_status_api": "切换用户角色",
64+
"ws_all_api": "查询所有工作空间",
65+
"ws_create_api": "创建工作空间",
66+
"ws_update_api": "修改工作空间",
67+
"ws_query_api": "查询工作空间详情",
68+
"ws_del_api": "删除工作空间",
69+
70+
"weight": "权重(1: 管理员, 0: 普通用户)"
71+
2672
"per_api": "数据权限",
2773
"per_save": "保存权限",
2874
"per_delete": "删除权限",
@@ -33,4 +79,4 @@
3379
"tr_api": "表关联关系",
3480
"tr_save": "保存关联关系",
3581
"tr_get": "查询关联关系"
36-
}
82+
}

backend/apps/system/api/user.py

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,44 @@
11
from collections import defaultdict
22
from typing import Optional
3-
from fastapi import APIRouter, Query
3+
from fastapi import APIRouter, Path, Query
4+
from pydantic import Field
45
from sqlmodel import SQLModel, or_, select, delete as sqlmodel_delete
56
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
67
from apps.system.models.system_model import UserWsModel, WorkspaceModel
78
from apps.system.models.user import UserModel
89
from apps.system.schemas.auth import CacheName, CacheNamespace
910
from apps.system.schemas.permission import SqlbotPermission, require_permissions
10-
from apps.system.schemas.system_schema import PwdEditor, UserCreator, UserEditor, UserGrid, UserLanguage, UserStatus, UserWs
11+
from apps.system.schemas.system_schema import PwdEditor, UserCreator, UserEditor, UserGrid, UserInfoDTO, UserLanguage, UserStatus, UserWs
1112
from common.core.deps import CurrentUser, SessionDep, Trans
1213
from common.core.pagination import Paginator
1314
from common.core.schemas import PaginatedResponse, PaginationParams
1415
from common.core.security import default_md5_pwd, md5pwd, verify_md5pwd
1516
from common.core.sqlbot_cache import clear_cache
1617
from common.core.config import settings
18+
from apps.swagger.i18n import PLACEHOLDER_PREFIX
1719

18-
router = APIRouter(tags=["user"], prefix="/user")
20+
router = APIRouter(tags=["system_user"], prefix="/user")
1921

20-
@router.get("/info")
21-
async def user_info(current_user: CurrentUser):
22+
@router.get("/info", summary=f"{PLACEHOLDER_PREFIX}system_user_current_user", description=f"{PLACEHOLDER_PREFIX}system_user_current_user_desc")
23+
async def user_info(current_user: CurrentUser) -> UserInfoDTO:
2224
return current_user
2325

2426

25-
@router.get("/defaultPwd")
27+
@router.get("/defaultPwd", include_in_schema=False)
2628
@require_permissions(permission=SqlbotPermission(role=['admin']))
2729
async def default_pwd() -> str:
2830
return settings.DEFAULT_PWD
2931

30-
@router.get("/pager/{pageNum}/{pageSize}", response_model=PaginatedResponse[UserGrid])
32+
@router.get("/pager/{pageNum}/{pageSize}", response_model=PaginatedResponse[UserGrid], summary=f"{PLACEHOLDER_PREFIX}system_user_grid", description=f"{PLACEHOLDER_PREFIX}system_user_grid")
3133
@require_permissions(permission=SqlbotPermission(role=['admin']))
3234
async def pager(
3335
session: SessionDep,
34-
pageNum: int,
35-
pageSize: int,
36-
keyword: Optional[str] = Query(None, description="搜索关键字(可选)"),
37-
status: Optional[int] = Query(None, description="状态"),
38-
origins: Optional[list[int]] = Query(None, description="来源"),
39-
oidlist: Optional[list[int]] = Query(None, description="空间ID集合(可选)"),
36+
pageNum: int = Path(..., title=f"{PLACEHOLDER_PREFIX}page_num", description=f"{PLACEHOLDER_PREFIX}page_num"),
37+
pageSize: int = Path(..., title=f"{PLACEHOLDER_PREFIX}page_size", description=f"{PLACEHOLDER_PREFIX}page_size"),
38+
keyword: Optional[str] = Query(None, description=f"{PLACEHOLDER_PREFIX}keyword"),
39+
status: Optional[int] = Query(None, description=f"{PLACEHOLDER_PREFIX}status"),
40+
origins: Optional[list[int]] = Query(None, description=f"{PLACEHOLDER_PREFIX}origin"),
41+
oidlist: Optional[list[int]] = Query(None, description=f"{PLACEHOLDER_PREFIX}oid"),
4042
):
4143
pagination = PaginationParams(page=pageNum, size=pageSize)
4244
paginator = Paginator(session)
@@ -108,13 +110,14 @@ def format_user_dict(row) -> dict:
108110
result_dict[key] = item
109111

110112
return result_dict
111-
@router.get("/ws")
113+
114+
@router.get("/ws", include_in_schema=False)
112115
async def ws_options(session: SessionDep, current_user: CurrentUser, trans: Trans) -> list[UserWs]:
113116
return await user_ws_options(session, current_user.id, trans)
114117

115-
@router.put("/ws/{oid}")
118+
@router.put("/ws/{oid}", summary=f"{PLACEHOLDER_PREFIX}switch_oid_api", description=f"{PLACEHOLDER_PREFIX}switch_oid_api")
116119
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id")
117-
async def ws_change(session: SessionDep, current_user: CurrentUser, trans:Trans, oid: int):
120+
async def ws_change(session: SessionDep, current_user: CurrentUser, trans:Trans, oid: int = Path(description=f"{PLACEHOLDER_PREFIX}oid")):
118121
ws_list: list[UserWs] = await user_ws_options(session, current_user.id)
119122
if not any(x.id == oid for x in ws_list):
120123
db_ws = session.get(WorkspaceModel, oid)
@@ -126,9 +129,9 @@ async def ws_change(session: SessionDep, current_user: CurrentUser, trans:Trans,
126129
session.add(user_model)
127130
session.commit()
128131

129-
@router.get("/{id}", response_model=UserEditor)
132+
@router.get("/{id}", response_model=UserEditor, summary=f"{PLACEHOLDER_PREFIX}user_detail_api", description=f"{PLACEHOLDER_PREFIX}user_detail_api")
130133
@require_permissions(permission=SqlbotPermission(role=['admin']))
131-
async def query(session: SessionDep, trans: Trans, id: int) -> UserEditor:
134+
async def query(session: SessionDep, trans: Trans, id: int = Path(description=f"{PLACEHOLDER_PREFIX}uid")) -> UserEditor:
132135
db_user: UserModel = get_db_user(session = session, user_id = id)
133136
u_ws_options = await user_ws_options(session, id, trans)
134137
result = UserEditor.model_validate(db_user.model_dump())
@@ -137,7 +140,7 @@ async def query(session: SessionDep, trans: Trans, id: int) -> UserEditor:
137140
return result
138141

139142

140-
@router.post("")
143+
@router.post("", summary=f"{PLACEHOLDER_PREFIX}user_create_api", description=f"{PLACEHOLDER_PREFIX}user_create_api")
141144
@require_permissions(permission=SqlbotPermission(role=['admin']))
142145
async def create(session: SessionDep, creator: UserCreator, trans: Trans):
143146
if check_account_exists(session=session, account=creator.account):
@@ -167,7 +170,7 @@ async def create(session: SessionDep, creator: UserCreator, trans: Trans):
167170
session.commit()
168171

169172

170-
@router.put("")
173+
@router.put("", summary=f"{PLACEHOLDER_PREFIX}user_update_api", description=f"{PLACEHOLDER_PREFIX}user_update_api")
171174
@require_permissions(permission=SqlbotPermission(role=['admin']))
172175
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="editor.id")
173176
async def update(session: SessionDep, editor: UserEditor, trans: Trans):
@@ -203,18 +206,18 @@ async def update(session: SessionDep, editor: UserEditor, trans: Trans):
203206
session.add(user_model)
204207
session.commit()
205208

206-
@router.delete("/{id}")
209+
@router.delete("/{id}", summary=f"{PLACEHOLDER_PREFIX}user_del_api", description=f"{PLACEHOLDER_PREFIX}user_del_api")
207210
@require_permissions(permission=SqlbotPermission(role=['admin']))
208-
async def delete(session: SessionDep, id: int):
211+
async def delete(session: SessionDep, id: int = Path(description=f"{PLACEHOLDER_PREFIX}uid")):
209212
await single_delete(session, id)
210213

211-
@router.delete("")
214+
@router.delete("", summary=f"{PLACEHOLDER_PREFIX}user_batchdel_api", description=f"{PLACEHOLDER_PREFIX}user_batchdel_api")
212215
@require_permissions(permission=SqlbotPermission(role=['admin']))
213216
async def batch_del(session: SessionDep, id_list: list[int]):
214217
for id in id_list:
215218
await single_delete(session, id)
216219

217-
@router.put("/language")
220+
@router.put("/language", summary=f"{PLACEHOLDER_PREFIX}language_change", description=f"{PLACEHOLDER_PREFIX}language_change")
218221
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id")
219222
async def langChange(session: SessionDep, current_user: CurrentUser, trans: Trans, language: UserLanguage):
220223
lang = language.language
@@ -226,18 +229,18 @@ async def langChange(session: SessionDep, current_user: CurrentUser, trans: Tran
226229
session.commit()
227230

228231

229-
@router.patch("/pwd/{id}")
232+
@router.patch("/pwd/{id}", summary=f"{PLACEHOLDER_PREFIX}reset_pwd", description=f"{PLACEHOLDER_PREFIX}reset_pwd")
230233
@require_permissions(permission=SqlbotPermission(role=['admin']))
231234
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="id")
232-
async def pwdReset(session: SessionDep, current_user: CurrentUser, trans: Trans, id: int):
235+
async def pwdReset(session: SessionDep, current_user: CurrentUser, trans: Trans, id: int = Path(description=f"{PLACEHOLDER_PREFIX}uid")):
233236
if not current_user.isAdmin:
234237
raise Exception(trans('i18n_permission.no_permission', url = " patch[/user/pwd/id],", msg = trans('i18n_permission.only_admin')))
235238
db_user: UserModel = get_db_user(session=session, user_id=id)
236239
db_user.password = default_md5_pwd()
237240
session.add(db_user)
238241
session.commit()
239242

240-
@router.put("/pwd")
243+
@router.put("/pwd", summary=f"{PLACEHOLDER_PREFIX}update_pwd", description=f"{PLACEHOLDER_PREFIX}update_pwd")
241244
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id")
242245
async def pwdUpdate(session: SessionDep, current_user: CurrentUser, trans: Trans, editor: PwdEditor):
243246
new_pwd = editor.new_pwd
@@ -251,10 +254,10 @@ async def pwdUpdate(session: SessionDep, current_user: CurrentUser, trans: Trans
251254
session.commit()
252255

253256

254-
@router.patch("/status")
257+
@router.patch("/status", summary=f"{PLACEHOLDER_PREFIX}update_status", description=f"{PLACEHOLDER_PREFIX}update_status")
255258
@require_permissions(permission=SqlbotPermission(role=['admin']))
256259
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="statusDto.id")
257-
async def langChange(session: SessionDep, current_user: CurrentUser, trans: Trans, statusDto: UserStatus):
260+
async def statusChange(session: SessionDep, current_user: CurrentUser, trans: Trans, statusDto: UserStatus):
258261
if not current_user.isAdmin:
259262
raise Exception(trans('i18n_permission.no_permission', url = ", ", msg = trans('i18n_permission.only_admin')))
260263
status = statusDto.status

0 commit comments

Comments
 (0)