Skip to content

Commit 15fd454

Browse files
authored
Optimize schemas with model relationships (#552)
1 parent 7f6c4ad commit 15fd454

File tree

9 files changed

+43
-35
lines changed

9 files changed

+43
-35
lines changed

backend/app/admin/api/v1/sys/dict_data.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@
44

55
from fastapi import APIRouter, Depends, Path, Query
66

7-
from backend.app.admin.schema.dict_data import CreateDictDataParam, GetDictDataDetail, UpdateDictDataParam
7+
from backend.app.admin.schema.dict_data import (
8+
CreateDictDataParam,
9+
GetDictDataDetail,
10+
GetDictDataWithRelation,
11+
UpdateDictDataParam,
12+
)
813
from backend.app.admin.service.dict_data_service import dict_data_service
914
from backend.common.pagination import DependsPagination, PageData, paging_data
1015
from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base
@@ -17,7 +22,7 @@
1722

1823

1924
@router.get('/{pk}', summary='获取字典详情', dependencies=[DependsJwtAuth])
20-
async def get_dict_data(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetDictDataDetail]:
25+
async def get_dict_data(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetDictDataWithRelation]:
2126
data = await dict_data_service.get(pk=pk)
2227
return response_base.success(data=data)
2328

backend/app/admin/api/v1/sys/role.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from backend.app.admin.schema.role import (
88
CreateRoleParam,
99
GetRoleDetail,
10+
GetRoleWithRelationDetail,
1011
UpdateRoleMenuParam,
1112
UpdateRoleParam,
1213
UpdateRoleRuleParam,
@@ -49,7 +50,7 @@ async def get_role_all_rules(pk: Annotated[int, Path(...)]) -> ResponseSchemaMod
4950

5051

5152
@router.get('/{pk}', summary='获取角色详情', dependencies=[DependsJwtAuth])
52-
async def get_role(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetRoleDetail]:
53+
async def get_role(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetRoleWithRelationDetail]:
5354
data = await role_service.get(pk=pk)
5455
return response_base.success(data=data)
5556

backend/app/admin/api/v1/sys/user.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
from backend.app.admin.schema.user import (
88
AddUserParam,
99
AvatarParam,
10-
GetCurrentUserInfoDetail,
11-
GetUserInfoDetail,
10+
GetCurrentUserInfoWithRelationDetail,
11+
GetUserInfoWithRelationDetail,
1212
RegisterUserParam,
1313
ResetPasswordParam,
1414
UpdateUserParam,
@@ -32,7 +32,7 @@ async def register_user(obj: RegisterUserParam) -> ResponseModel:
3232

3333

3434
@router.post('/add', summary='添加用户', dependencies=[DependsRBAC])
35-
async def add_user(request: Request, obj: AddUserParam) -> ResponseSchemaModel[GetUserInfoDetail]:
35+
async def add_user(request: Request, obj: AddUserParam) -> ResponseSchemaModel[GetUserInfoWithRelationDetail]:
3636
await user_service.add(request=request, obj=obj)
3737
data = await user_service.get_userinfo(username=obj.username)
3838
return response_base.success(data=data)
@@ -47,13 +47,13 @@ async def password_reset(request: Request, obj: ResetPasswordParam) -> ResponseM
4747

4848

4949
@router.get('/me', summary='获取当前用户信息', dependencies=[DependsJwtAuth], response_model_exclude={'password'})
50-
async def get_current_user(request: Request) -> ResponseSchemaModel[GetCurrentUserInfoDetail]:
51-
data = GetCurrentUserInfoDetail(**request.user.model_dump())
50+
async def get_current_user(request: Request) -> ResponseSchemaModel[GetCurrentUserInfoWithRelationDetail]:
51+
data = request.user.model_dump()
5252
return response_base.success(data=data)
5353

5454

5555
@router.get('/{username}', summary='查看用户信息', dependencies=[DependsJwtAuth])
56-
async def get_user(username: Annotated[str, Path(...)]) -> ResponseSchemaModel[GetUserInfoDetail]:
56+
async def get_user(username: Annotated[str, Path(...)]) -> ResponseSchemaModel[GetUserInfoWithRelationDetail]:
5757
data = await user_service.get_userinfo(username=username)
5858
return response_base.success(data=data)
5959

@@ -103,7 +103,7 @@ async def get_pagination_users(
103103
username: Annotated[str | None, Query()] = None,
104104
phone: Annotated[str | None, Query()] = None,
105105
status: Annotated[int | None, Query()] = None,
106-
) -> ResponseSchemaModel[PageData[GetUserInfoDetail]]:
106+
) -> ResponseSchemaModel[PageData[GetUserInfoWithRelationDetail]]:
107107
user_select = await user_service.get_select(dept=dept, username=username, phone=phone, status=status)
108108
page_data = await paging_data(db, user_select)
109109
return response_base.success(data=page_data)

backend/app/admin/schema/dict_data.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ class GetDictDataDetail(DictDataSchemaBase):
3030
model_config = ConfigDict(from_attributes=True)
3131

3232
id: int
33-
type: GetDictTypeDetail | None = None
3433
created_time: datetime
3534
updated_time: datetime | None = None
35+
36+
37+
class GetDictDataWithRelation(DictDataSchemaBase):
38+
type: GetDictTypeDetail | None = None

backend/app/admin/schema/role.py

+3
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,8 @@ class GetRoleDetail(RoleSchemaBase):
3838
id: int
3939
created_time: datetime
4040
updated_time: datetime | None = None
41+
42+
43+
class GetRoleWithRelationDetail(GetRoleDetail):
4144
menus: list[GetMenuDetail | None] = []
4245
rules: list[GetDataRuleDetail | None] = []

backend/app/admin/schema/token.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
# -*- coding: utf-8 -*-
33
from datetime import datetime
44

5-
from backend.app.admin.schema.user import GetUserInfoNoRelationDetail
5+
from backend.app.admin.schema.user import GetUserInfoDetail
66
from backend.common.enums import StatusType
77
from backend.common.schema import SchemaBase
88

99

1010
class GetSwaggerToken(SchemaBase):
1111
access_token: str
1212
token_type: str = 'Bearer'
13-
user: GetUserInfoNoRelationDetail
13+
user: GetUserInfoDetail
1414

1515

1616
class AccessTokenBase(SchemaBase):
@@ -24,7 +24,7 @@ class GetNewToken(AccessTokenBase):
2424

2525

2626
class GetLoginToken(AccessTokenBase):
27-
user: GetUserInfoNoRelationDetail
27+
user: GetUserInfoDetail
2828

2929

3030
class KickOutToken(SchemaBase):

backend/app/admin/schema/user.py

+11-15
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from typing_extensions import Self
88

99
from backend.app.admin.schema.dept import GetDeptDetail
10-
from backend.app.admin.schema.role import GetRoleDetail
10+
from backend.app.admin.schema.role import GetRoleWithRelationDetail
1111
from backend.common.enums import StatusType
1212
from backend.common.schema import CustomPhoneNumber, SchemaBase
1313

@@ -33,6 +33,12 @@ class AddUserParam(AuthSchemaBase):
3333
email: EmailStr = Field(examples=['[email protected]'])
3434

3535

36+
class ResetPasswordParam(SchemaBase):
37+
old_password: str
38+
new_password: str
39+
confirm_password: str
40+
41+
3642
class UserInfoSchemaBase(SchemaBase):
3743
dept_id: int | None = None
3844
username: str
@@ -53,7 +59,7 @@ class AvatarParam(SchemaBase):
5359
url: HttpUrl = Field(description='头像 http 地址')
5460

5561

56-
class GetUserInfoNoRelationDetail(UserInfoSchemaBase):
62+
class GetUserInfoDetail(UserInfoSchemaBase):
5763
model_config = ConfigDict(from_attributes=True)
5864

5965
dept_id: int | None = None
@@ -68,14 +74,14 @@ class GetUserInfoNoRelationDetail(UserInfoSchemaBase):
6874
last_login_time: datetime | None = None
6975

7076

71-
class GetUserInfoDetail(GetUserInfoNoRelationDetail):
77+
class GetUserInfoWithRelationDetail(GetUserInfoDetail):
7278
model_config = ConfigDict(from_attributes=True)
7379

7480
dept: GetDeptDetail | None = None
75-
roles: list[GetRoleDetail]
81+
roles: list[GetRoleWithRelationDetail]
7682

7783

78-
class GetCurrentUserInfoDetail(GetUserInfoDetail):
84+
class GetCurrentUserInfoWithRelationDetail(GetUserInfoWithRelationDetail):
7985
model_config = ConfigDict(from_attributes=True)
8086

8187
dept: str | None = None
@@ -92,13 +98,3 @@ def handel(cls, data: Any) -> Self:
9298
if roles:
9399
data['roles'] = [role['name'] for role in roles]
94100
return data
95-
96-
97-
class CurrentUserIns(GetUserInfoDetail):
98-
model_config = ConfigDict(from_attributes=True)
99-
100-
101-
class ResetPasswordParam(SchemaBase):
102-
old_password: str
103-
new_password: str
104-
confirm_password: str

backend/common/security/jwt.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from sqlalchemy.ext.asyncio import AsyncSession
1616

1717
from backend.app.admin.model import User
18-
from backend.app.admin.schema.user import CurrentUserIns
18+
from backend.app.admin.schema.user import GetUserInfoWithRelationDetail
1919
from backend.common.dataclasses import AccessToken, NewToken, RefreshToken, TokenPayload
2020
from backend.common.exception.errors import AuthorizationError, TokenError
2121
from backend.core.conf import settings
@@ -211,7 +211,7 @@ def superuser_verify(request: Request) -> bool:
211211
return superuser
212212

213213

214-
async def jwt_authentication(token: str) -> CurrentUserIns:
214+
async def jwt_authentication(token: str) -> GetUserInfoWithRelationDetail:
215215
"""
216216
JWT authentication
217217
@@ -227,7 +227,7 @@ async def jwt_authentication(token: str) -> CurrentUserIns:
227227
if not cache_user:
228228
async with async_db_session() as db:
229229
current_user = await get_current_user(db, user_id)
230-
user = CurrentUserIns(**select_as_dict(current_user))
230+
user = GetUserInfoWithRelationDetail(**select_as_dict(current_user))
231231
await redis_client.setex(
232232
f'{settings.JWT_USER_REDIS_PREFIX}:{user_id}',
233233
settings.JWT_USER_REDIS_EXPIRE_SECONDS,
@@ -236,5 +236,5 @@ async def jwt_authentication(token: str) -> CurrentUserIns:
236236
else:
237237
# TODO: 在恰当的时机,应替换为使用 model_validate_json
238238
# https://docs.pydantic.dev/latest/concepts/json/#partial-json-parsing
239-
user = CurrentUserIns.model_validate(from_json(cache_user, allow_partial=True))
239+
user = GetUserInfoWithRelationDetail.model_validate(from_json(cache_user, allow_partial=True))
240240
return user

backend/middleware/jwt_auth_middleware.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from starlette.authentication import AuthCredentials, AuthenticationBackend, AuthenticationError
88
from starlette.requests import HTTPConnection
99

10-
from backend.app.admin.schema.user import CurrentUserIns
10+
from backend.app.admin.schema.user import GetUserInfoWithRelationDetail
1111
from backend.common.exception.errors import TokenError
1212
from backend.common.log import log
1313
from backend.common.security.jwt import jwt_authentication
@@ -32,7 +32,7 @@ def auth_exception_handler(conn: HTTPConnection, exc: _AuthenticationError) -> R
3232
"""覆盖内部认证错误处理"""
3333
return MsgSpecJSONResponse(content={'code': exc.code, 'msg': exc.msg, 'data': None}, status_code=exc.code)
3434

35-
async def authenticate(self, request: Request) -> tuple[AuthCredentials, CurrentUserIns] | None:
35+
async def authenticate(self, request: Request) -> tuple[AuthCredentials, GetUserInfoWithRelationDetail] | None:
3636
token = request.headers.get('Authorization')
3737
if not token:
3838
return

0 commit comments

Comments
 (0)