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:
Wu Clan
2024-03-22 18:16:15 +08:00
committed by GitHub
parent a98621b40d
commit 5e438c685d
190 changed files with 2408 additions and 1494 deletions
+2
View File
@@ -0,0 +1,2 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
+31
View File
@@ -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
+47
View File
@@ -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
+35
View File
@@ -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
+35
View File
@@ -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
+31
View File
@@ -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
+38
View File
@@ -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
+40
View File
@@ -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
+44
View File
@@ -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
+39
View File
@@ -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]
+31
View File
@@ -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
+97
View File
@@ -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
+21
View File
@@ -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