Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions backend/apps/swagger/i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
46 changes: 46 additions & 0 deletions backend/apps/swagger/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
48 changes: 47 additions & 1 deletion backend/apps/swagger/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": "删除权限",
Expand All @@ -33,4 +79,4 @@
"tr_api": "表关联关系",
"tr_save": "保存关联关系",
"tr_get": "查询关联关系"
}
}
61 changes: 32 additions & 29 deletions backend/apps/system/api/user.py
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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())
Expand All @@ -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):
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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
Expand All @@ -226,18 +229,18 @@ 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)
db_user.password = default_md5_pwd()
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
Expand All @@ -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
Expand Down
Loading