mirror of
https://github.com/fastapi-practices/fastapi-best-architecture.git
synced 2026-09-21 21:15:13 +00:00
Refactor the backend architecture (#299)
* define the basic architecture * Update script and deployment file locations * Update the route registration * Fix CI download dependencies * Updated ruff to 0.3.3 * Update app subdirectory naming * Update the model import * fix pre-commit pdm lock * Update the service directory naming * Add CRUD method documents * Fix the issue of circular import * Update the README document * Update the SQL statement for create tables * Update docker scripts and documentation * Fix docker scripts * Update the backend README.md * Add the security folder and move the redis client * Update the configuration item * Fix environment configuration reads * Update the default configuration * Updated README description * Updated the user registration API * Fix test cases * Update the celery configuration * Update and fix celery configuration * Updated the celery structure * Update celery tasks and api * Add celery flower * Update the import style * Update contributors
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import ConfigDict, Field
|
||||
|
||||
from backend.common.enums import MethodType
|
||||
from backend.common.msd.schema import SchemaBase
|
||||
|
||||
|
||||
class ApiSchemaBase(SchemaBase):
|
||||
name: str
|
||||
method: MethodType = Field(default=MethodType.GET, description='请求方法')
|
||||
path: str = Field(..., description='api路径')
|
||||
remark: str | None = None
|
||||
|
||||
|
||||
class CreateApiParam(ApiSchemaBase):
|
||||
pass
|
||||
|
||||
|
||||
class UpdateApiParam(ApiSchemaBase):
|
||||
pass
|
||||
|
||||
|
||||
class GetApiListDetails(ApiSchemaBase):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
created_time: datetime
|
||||
updated_time: datetime | None = None
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
from pydantic import ConfigDict, Field
|
||||
|
||||
from backend.common.enums import MethodType
|
||||
from backend.common.msd.schema import SchemaBase
|
||||
|
||||
|
||||
class CreatePolicyParam(SchemaBase):
|
||||
sub: str = Field(..., description='用户uuid / 角色ID')
|
||||
path: str = Field(..., description='api 路径')
|
||||
method: MethodType = Field(default=MethodType.GET, description='请求方法')
|
||||
|
||||
|
||||
class UpdatePolicyParam(CreatePolicyParam):
|
||||
pass
|
||||
|
||||
|
||||
class DeletePolicyParam(CreatePolicyParam):
|
||||
pass
|
||||
|
||||
|
||||
class DeleteAllPoliciesParam(SchemaBase):
|
||||
uuid: str | None = None
|
||||
role: str
|
||||
|
||||
|
||||
class CreateUserRoleParam(SchemaBase):
|
||||
uuid: str = Field(..., description='用户 uuid')
|
||||
role: str = Field(..., description='角色')
|
||||
|
||||
|
||||
class DeleteUserRoleParam(CreateUserRoleParam):
|
||||
pass
|
||||
|
||||
|
||||
class GetPolicyListDetails(SchemaBase):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
ptype: str = Field(..., description='规则类型, p / g')
|
||||
v0: str = Field(..., description='用户 uuid / 角色')
|
||||
v1: str = Field(..., description='api 路径 / 角色')
|
||||
v2: str | None = None
|
||||
v3: str | None = None
|
||||
v4: str | None = None
|
||||
v5: str | None = None
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import ConfigDict, Field
|
||||
|
||||
from backend.common.enums import StatusType
|
||||
from backend.common.msd.schema import CustomEmailStr, CustomPhoneNumber, SchemaBase
|
||||
|
||||
|
||||
class DeptSchemaBase(SchemaBase):
|
||||
name: str
|
||||
parent_id: int | None = Field(default=None, description='部门父级ID')
|
||||
sort: int = Field(default=0, ge=0, description='排序')
|
||||
leader: str | None = None
|
||||
phone: CustomPhoneNumber | None = None
|
||||
email: CustomEmailStr | None = None
|
||||
status: StatusType = Field(default=StatusType.enable)
|
||||
|
||||
|
||||
class CreateDeptParam(DeptSchemaBase):
|
||||
pass
|
||||
|
||||
|
||||
class UpdateDeptParam(DeptSchemaBase):
|
||||
pass
|
||||
|
||||
|
||||
class GetDeptListDetails(DeptSchemaBase):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
del_flag: bool
|
||||
created_time: datetime
|
||||
updated_time: datetime | None = None
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import ConfigDict, Field
|
||||
|
||||
from backend.app.admin.schema.dict_type import GetDictTypeListDetails
|
||||
from backend.common.enums import StatusType
|
||||
from backend.common.msd.schema import SchemaBase
|
||||
|
||||
|
||||
class DictDataSchemaBase(SchemaBase):
|
||||
type_id: int
|
||||
label: str
|
||||
value: str
|
||||
sort: int
|
||||
status: StatusType = Field(default=StatusType.enable)
|
||||
remark: str | None = None
|
||||
|
||||
|
||||
class CreateDictDataParam(DictDataSchemaBase):
|
||||
pass
|
||||
|
||||
|
||||
class UpdateDictDataParam(DictDataSchemaBase):
|
||||
pass
|
||||
|
||||
|
||||
class GetDictDataListDetails(DictDataSchemaBase):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
type: GetDictTypeListDetails
|
||||
created_time: datetime
|
||||
updated_time: datetime | None = None
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import ConfigDict, Field
|
||||
|
||||
from backend.common.enums import StatusType
|
||||
from backend.common.msd.schema import SchemaBase
|
||||
|
||||
|
||||
class DictTypeSchemaBase(SchemaBase):
|
||||
name: str
|
||||
code: str
|
||||
status: StatusType = Field(default=StatusType.enable)
|
||||
remark: str | None = None
|
||||
|
||||
|
||||
class CreateDictTypeParam(DictTypeSchemaBase):
|
||||
pass
|
||||
|
||||
|
||||
class UpdateDictTypeParam(DictTypeSchemaBase):
|
||||
pass
|
||||
|
||||
|
||||
class GetDictTypeListDetails(DictTypeSchemaBase):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
created_time: datetime
|
||||
updated_time: datetime | None = None
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import ConfigDict
|
||||
|
||||
from backend.common.msd.schema import SchemaBase
|
||||
|
||||
|
||||
class LoginLogSchemaBase(SchemaBase):
|
||||
user_uuid: str
|
||||
username: str
|
||||
status: int
|
||||
ip: str
|
||||
country: str | None
|
||||
region: str | None
|
||||
city: str | None
|
||||
user_agent: str
|
||||
browser: str | None
|
||||
os: str | None
|
||||
device: str | None
|
||||
msg: str
|
||||
login_time: datetime
|
||||
|
||||
|
||||
class CreateLoginLogParam(LoginLogSchemaBase):
|
||||
pass
|
||||
|
||||
|
||||
class UpdateLoginLogParam(LoginLogSchemaBase):
|
||||
pass
|
||||
|
||||
|
||||
class GetLoginLogListDetails(LoginLogSchemaBase):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
created_time: datetime
|
||||
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import ConfigDict, Field
|
||||
|
||||
from backend.common.enums import MenuType, StatusType
|
||||
from backend.common.msd.schema import SchemaBase
|
||||
|
||||
|
||||
class MenuSchemaBase(SchemaBase):
|
||||
title: str
|
||||
name: str
|
||||
parent_id: int | None = Field(default=None, description='菜单父级ID')
|
||||
sort: int = Field(default=0, ge=0, description='排序')
|
||||
icon: str | None = None
|
||||
path: str | None = None
|
||||
menu_type: MenuType = Field(default=MenuType.directory, description='菜单类型(0目录 1菜单 2按钮)')
|
||||
component: str | None = None
|
||||
perms: str | None = None
|
||||
status: StatusType = Field(default=StatusType.enable)
|
||||
show: StatusType = Field(default=StatusType.enable)
|
||||
cache: StatusType = Field(default=StatusType.enable)
|
||||
remark: str | None = None
|
||||
|
||||
|
||||
class CreateMenuParam(MenuSchemaBase):
|
||||
pass
|
||||
|
||||
|
||||
class UpdateMenuParam(MenuSchemaBase):
|
||||
pass
|
||||
|
||||
|
||||
class GetMenuListDetails(MenuSchemaBase):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
created_time: datetime
|
||||
updated_time: datetime | None = None
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import ConfigDict, Field
|
||||
|
||||
from backend.common.enums import StatusType
|
||||
from backend.common.msd.schema import SchemaBase
|
||||
|
||||
|
||||
class OperaLogSchemaBase(SchemaBase):
|
||||
username: str | None = None
|
||||
method: str
|
||||
title: str
|
||||
path: str
|
||||
ip: str
|
||||
country: str | None = None
|
||||
region: str | None = None
|
||||
city: str | None = None
|
||||
user_agent: str
|
||||
os: str | None = None
|
||||
browser: str | None = None
|
||||
device: str | None = None
|
||||
args: dict | None = None
|
||||
status: StatusType = Field(default=StatusType.enable)
|
||||
code: str
|
||||
msg: str | None = None
|
||||
cost_time: float
|
||||
opera_time: datetime
|
||||
|
||||
|
||||
class CreateOperaLogParam(OperaLogSchemaBase):
|
||||
pass
|
||||
|
||||
|
||||
class UpdateOperaLogParam(OperaLogSchemaBase):
|
||||
pass
|
||||
|
||||
|
||||
class GetOperaLogListDetails(OperaLogSchemaBase):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
created_time: datetime
|
||||
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import ConfigDict, Field
|
||||
|
||||
from backend.app.admin.schema.menu import GetMenuListDetails
|
||||
from backend.common.enums import RoleDataScopeType, StatusType
|
||||
from backend.common.msd.schema import SchemaBase
|
||||
|
||||
|
||||
class RoleSchemaBase(SchemaBase):
|
||||
name: str
|
||||
data_scope: RoleDataScopeType = Field(
|
||||
default=RoleDataScopeType.custom, description='权限范围(1:全部数据权限 2:自定义数据权限)'
|
||||
)
|
||||
status: StatusType = Field(default=StatusType.enable)
|
||||
remark: str | None = None
|
||||
|
||||
|
||||
class CreateRoleParam(RoleSchemaBase):
|
||||
pass
|
||||
|
||||
|
||||
class UpdateRoleParam(RoleSchemaBase):
|
||||
pass
|
||||
|
||||
|
||||
class UpdateRoleMenuParam(SchemaBase):
|
||||
menus: list[int]
|
||||
|
||||
|
||||
class GetRoleListDetails(RoleSchemaBase):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
created_time: datetime
|
||||
updated_time: datetime | None = None
|
||||
menus: list[GetMenuListDetails]
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
from datetime import datetime
|
||||
|
||||
from backend.app.admin.schema.user import GetUserInfoNoRelationDetail
|
||||
from backend.common.msd.schema import SchemaBase
|
||||
|
||||
|
||||
class GetSwaggerToken(SchemaBase):
|
||||
access_token: str
|
||||
token_type: str = 'Bearer'
|
||||
user: GetUserInfoNoRelationDetail
|
||||
|
||||
|
||||
class AccessTokenBase(SchemaBase):
|
||||
access_token: str
|
||||
access_token_type: str = 'Bearer'
|
||||
access_token_expire_time: datetime
|
||||
|
||||
|
||||
class GetLoginToken(AccessTokenBase):
|
||||
refresh_token: str
|
||||
refresh_token_type: str = 'Bearer'
|
||||
refresh_token_expire_time: datetime
|
||||
user: GetUserInfoNoRelationDetail
|
||||
|
||||
|
||||
class GetNewToken(AccessTokenBase):
|
||||
refresh_token: str
|
||||
refresh_token_type: str = 'Bearer'
|
||||
refresh_token_expire_time: datetime
|
||||
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import ConfigDict, EmailStr, Field, HttpUrl, model_validator
|
||||
|
||||
from backend.app.admin.schema.dept import GetDeptListDetails
|
||||
from backend.app.admin.schema.role import GetRoleListDetails
|
||||
from backend.common.enums import StatusType
|
||||
from backend.common.msd.schema import CustomPhoneNumber, SchemaBase
|
||||
|
||||
|
||||
class AuthSchemaBase(SchemaBase):
|
||||
username: str
|
||||
password: str | None
|
||||
|
||||
|
||||
class AuthLoginParam(AuthSchemaBase):
|
||||
captcha: str
|
||||
|
||||
|
||||
class RegisterUserParam(AuthSchemaBase):
|
||||
nickname: str | None = None
|
||||
email: EmailStr = Field(..., example='user@example.com')
|
||||
|
||||
|
||||
class AddUserParam(AuthSchemaBase):
|
||||
dept_id: int
|
||||
roles: list[int]
|
||||
nickname: str | None = None
|
||||
email: EmailStr = Field(..., example='user@example.com')
|
||||
|
||||
|
||||
class UserInfoSchemaBase(SchemaBase):
|
||||
dept_id: int | None = None
|
||||
username: str
|
||||
nickname: str
|
||||
email: EmailStr = Field(..., example='user@example.com')
|
||||
phone: CustomPhoneNumber | None = None
|
||||
|
||||
|
||||
class UpdateUserParam(UserInfoSchemaBase):
|
||||
pass
|
||||
|
||||
|
||||
class UpdateUserRoleParam(SchemaBase):
|
||||
roles: list[int]
|
||||
|
||||
|
||||
class AvatarParam(SchemaBase):
|
||||
url: HttpUrl = Field(..., description='头像 http 地址')
|
||||
|
||||
|
||||
class GetUserInfoNoRelationDetail(UserInfoSchemaBase):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
dept_id: int | None = None
|
||||
id: int
|
||||
uuid: str
|
||||
avatar: str | None = None
|
||||
status: StatusType = Field(default=StatusType.enable)
|
||||
is_superuser: bool
|
||||
is_staff: bool
|
||||
is_multi_login: bool
|
||||
join_time: datetime = None
|
||||
last_login_time: datetime | None = None
|
||||
|
||||
|
||||
class GetUserInfoListDetails(GetUserInfoNoRelationDetail):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
dept: GetDeptListDetails | None = None
|
||||
roles: list[GetRoleListDetails]
|
||||
|
||||
|
||||
class GetCurrentUserInfoDetail(GetUserInfoListDetails):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
dept: GetDeptListDetails | str | None = None
|
||||
roles: list[GetRoleListDetails] | list[str] | None = None
|
||||
|
||||
@model_validator(mode='after')
|
||||
def handel(self, values):
|
||||
"""处理部门和角色"""
|
||||
dept = self.dept
|
||||
if dept:
|
||||
self.dept = dept.name # type: ignore
|
||||
roles = self.roles
|
||||
if roles:
|
||||
self.roles = [role.name for role in roles] # type: ignore
|
||||
return values
|
||||
|
||||
|
||||
class ResetPasswordParam(SchemaBase):
|
||||
old_password: str
|
||||
new_password: str
|
||||
confirm_password: str
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
from backend.common.enums import UserSocialType
|
||||
from backend.common.msd.schema import SchemaBase
|
||||
|
||||
|
||||
class UserSocialSchemaBase(SchemaBase):
|
||||
source: UserSocialType
|
||||
open_id: str | None = None
|
||||
uid: str | None = None
|
||||
union_id: str | None = None
|
||||
scope: str | None = None
|
||||
code: str | None = None
|
||||
|
||||
|
||||
class CreateUserSocialParam(UserSocialSchemaBase):
|
||||
user_id: int
|
||||
|
||||
|
||||
class UpdateUserSocialParam(SchemaBase):
|
||||
pass
|
||||
Reference in New Issue
Block a user