chore: update backend lib version and update Dockerfile
This commit is contained in:
parent
a033eceb3a
commit
9da334adaa
@ -1,5 +1,15 @@
|
|||||||
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9
|
# 第一阶段:构建镜像
|
||||||
COPY . /app
|
FROM python:3.9-slim-buster AS build
|
||||||
|
WORKDIR /app
|
||||||
|
COPY requirements.txt .
|
||||||
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
|
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
|
||||||
echo 'Asia/Shanghai' >/etc/timezone && \
|
echo 'Asia/Shanghai' >/etc/timezone && \
|
||||||
pip install --no-cache-dir --upgrade -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/
|
pip install --no-cache-dir --user -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/
|
||||||
|
COPY . .
|
||||||
|
# 第二阶段:运行镜像
|
||||||
|
FROM python:3.9-slim-buster
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=build /root/.local /root/.local
|
||||||
|
COPY --from=build /app .
|
||||||
|
ENV PATH=/root/.local/bin:$PATH
|
||||||
|
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
|
||||||
|
@ -4,7 +4,6 @@ from starlette.responses import JSONResponse
|
|||||||
|
|
||||||
|
|
||||||
class TokenAuthFailure(HTTPException):
|
class TokenAuthFailure(HTTPException):
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -1 +1,8 @@
|
|||||||
from loguru import logger
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
handler = logging.StreamHandler()
|
||||||
|
formatter = logging.Formatter("[%(asctime)s] %(levelname)s %(message)s")
|
||||||
|
handler.setFormatter(formatter)
|
||||||
|
logger.addHandler(handler)
|
||||||
|
@ -2,7 +2,6 @@ from core.dbhelper import DbHelper
|
|||||||
|
|
||||||
|
|
||||||
class Service:
|
class Service:
|
||||||
|
|
||||||
filter_del = {"status__not": 9}
|
filter_del = {"status__not": 9}
|
||||||
|
|
||||||
def __init__(self, dao: DbHelper):
|
def __init__(self, dao: DbHelper):
|
||||||
|
@ -20,7 +20,6 @@ def list_to_tree(
|
|||||||
menu_map = {menu["id"]: menu for menu in menus}
|
menu_map = {menu["id"]: menu for menu in menus}
|
||||||
arr = []
|
arr = []
|
||||||
for menu in menus:
|
for menu in menus:
|
||||||
|
|
||||||
# 有父级
|
# 有父级
|
||||||
if mid := menu.get(parent_flag):
|
if mid := menu.get(parent_flag):
|
||||||
# 有 子项的情况
|
# 有 子项的情况
|
||||||
@ -79,7 +78,7 @@ def load_routers(
|
|||||||
kwargs = dict(router=router_obj, dependencies=depends)
|
kwargs = dict(router=router_obj, dependencies=depends)
|
||||||
app.include_router(**kwargs)
|
app.include_router(**kwargs)
|
||||||
|
|
||||||
logger.info("开始扫描路由。")
|
logger.info("♻️开始扫描路由。")
|
||||||
if depends is None:
|
if depends is None:
|
||||||
depends = []
|
depends = []
|
||||||
if is_init:
|
if is_init:
|
||||||
@ -99,9 +98,9 @@ def load_routers(
|
|||||||
|
|
||||||
for route in app.routes:
|
for route in app.routes:
|
||||||
try:
|
try:
|
||||||
logger.debug(
|
logger.info(
|
||||||
f"{route.path}, {route.methods}, {route.__dict__.get('summary')}"
|
f"🦌{route.path}, {route.methods}, {route.__dict__.get('summary')}"
|
||||||
)
|
)
|
||||||
except AttributeError as e:
|
except AttributeError as e:
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
logger.info("👌路由注册完成✅。")
|
logger.info("®️路由注册完成✅。")
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
bcrypt==4.0.0
|
bcrypt==4.0.1
|
||||||
fastapi==0.85.0
|
fastapi==0.94.0
|
||||||
|
gunicorn==20.1.0
|
||||||
passlib==1.7.4
|
passlib==1.7.4
|
||||||
pytest==7.1.3
|
pytest==7.2.2
|
||||||
python-jose==3.3.0
|
python-jose==3.3.0
|
||||||
requests==2.28.1
|
requests==2.28.2
|
||||||
tortoise-orm==0.19.2
|
tortoise-orm==0.19.3
|
||||||
uvicorn==0.18.3
|
uvicorn==0.21.0
|
||||||
websockets==10.3
|
websockets==10.4
|
||||||
loguru==0.6.0
|
|
||||||
|
@ -9,8 +9,8 @@ router = APIRouter(tags=["公共"])
|
|||||||
LoginResult = BaseSchema.Response[BaseSchema.LoginResult]
|
LoginResult = BaseSchema.Response[BaseSchema.LoginResult]
|
||||||
|
|
||||||
|
|
||||||
@router.post("/login", summary="登录", response_model=LoginResult)
|
@router.post("/login", summary="登录")
|
||||||
async def login(data: BaseSchema.LoginForm):
|
async def login(data: BaseSchema.LoginForm) -> LoginResult:
|
||||||
return await AuthService.user_login(data)
|
return await AuthService.user_login(data)
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,22 +9,22 @@ router = APIRouter(prefix="/menu", tags=["菜单管理"])
|
|||||||
Response = BaseSchema.Response
|
Response = BaseSchema.Response
|
||||||
|
|
||||||
|
|
||||||
@router.post("", summary="菜单新增", response_model=Response[MenuSchema.MenuRead])
|
@router.post("", summary="菜单新增")
|
||||||
async def menu_add(data: MenuSchema.MenuIn):
|
async def menu_add(data: MenuSchema.MenuIn) -> Response[MenuSchema.MenuRead]:
|
||||||
return await MenuService.create_item(data)
|
return await MenuService.create_item(data)
|
||||||
|
|
||||||
|
|
||||||
@router.get("", summary="菜单列表", response_model=Response)
|
@router.get("", summary="菜单列表")
|
||||||
async def menu_arr():
|
async def menu_arr() -> Response:
|
||||||
return await MenuService.get_items()
|
return await MenuService.get_items()
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/{pk}", summary="菜单删除", response_model=Response)
|
@router.delete("/{pk}", summary="菜单删除")
|
||||||
async def menu_del(pk: int):
|
async def menu_del(pk: int) -> Response:
|
||||||
return await MenuService.delete_item(pk)
|
return await MenuService.delete_item(pk)
|
||||||
|
|
||||||
|
|
||||||
@router.put("/{pk}", summary="菜单更新", response_model=Response)
|
@router.put("/{pk}", summary="菜单更新")
|
||||||
async def menu_put(pk: int, data: MenuSchema.MenuIn):
|
async def menu_put(pk: int, data: MenuSchema.MenuIn) -> Response:
|
||||||
"""更新菜单"""
|
"""更新菜单"""
|
||||||
return await MenuService.update_item(pk, data)
|
return await MenuService.update_item(pk, data)
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
from fastapi import APIRouter, Query
|
from fastapi import APIRouter, Depends
|
||||||
|
|
||||||
from schemas import common as BaseSchema
|
from schemas import common as BaseSchema
|
||||||
from schemas import role as RoleSchema
|
from schemas import role as RoleSchema
|
||||||
|
from schemas.common import QueryData
|
||||||
from service.role import service as RoleService
|
from service.role import service as RoleService
|
||||||
|
|
||||||
router = APIRouter(prefix="/role", tags=["角色管理"])
|
router = APIRouter(prefix="/role", tags=["角色管理"])
|
||||||
@ -12,35 +13,32 @@ ListAll = BaseSchema.ListAll
|
|||||||
role_list_schema = ListAll[list[RoleSchema.RoleRead]]
|
role_list_schema = ListAll[list[RoleSchema.RoleRead]]
|
||||||
|
|
||||||
|
|
||||||
@router.get("", summary="角色列表", response_model=Response[role_list_schema])
|
@router.get("", summary="角色列表")
|
||||||
async def role_list(
|
async def role_list(query: QueryData = Depends()) -> Response[role_list_schema]:
|
||||||
offset: int = Query(default=1, description="偏移量-页码"),
|
return await RoleService.get_items(query.offset, query.limit)
|
||||||
limit: int = Query(default=10, description="数据量"),
|
|
||||||
):
|
|
||||||
return await RoleService.get_items(offset, limit)
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("/query", summary="角色查询", response_model=Response[role_list_schema])
|
@router.post("/query", summary="角色查询")
|
||||||
async def role_query(query: RoleSchema.RoleQuery):
|
async def role_query(query: RoleSchema.RoleQuery) -> Response[role_list_schema]:
|
||||||
return await RoleService.query_items(query)
|
return await RoleService.query_items(query)
|
||||||
|
|
||||||
|
|
||||||
@router.post("", summary="角色新增", response_model=Response[RoleSchema.RoleInfo])
|
@router.post("", summary="角色新增")
|
||||||
async def role_create(data: RoleSchema.RoleIn):
|
async def role_create(data: RoleSchema.RoleIn) -> Response[RoleSchema.RoleInfo]:
|
||||||
return await RoleService.create_item(data)
|
return await RoleService.create_item(data)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{rid}/menu", summary="查询角色拥有权限", response_model=Response)
|
@router.get("/{rid}/menu", summary="查询角色拥有权限")
|
||||||
async def role_has_menu(rid: int):
|
async def role_has_menu(rid: int) -> Response:
|
||||||
return await RoleService.has_tree_menus(rid)
|
return await RoleService.has_tree_menus(rid)
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/{pk}", summary="角色删除", response_model=Response)
|
@router.delete("/{pk}", summary="角色删除")
|
||||||
async def role_del(pk: int):
|
async def role_del(pk: int) -> Response:
|
||||||
return await RoleService.delete_item(pk)
|
return await RoleService.delete_item(pk)
|
||||||
|
|
||||||
|
|
||||||
@router.put("/{pk}", summary="角色更新", response_model=Response)
|
@router.put("/{pk}", summary="角色更新")
|
||||||
async def role_put(pk: int, data: RoleSchema.RoleIn):
|
async def role_put(pk: int, data: RoleSchema.RoleIn) -> Response:
|
||||||
"""更新角色"""
|
"""更新角色"""
|
||||||
return await RoleService.update_item(pk, data)
|
return await RoleService.update_item(pk, data)
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
from fastapi import APIRouter, Depends, Query
|
from fastapi import APIRouter, Depends
|
||||||
|
|
||||||
from core.security import check_permissions
|
from core.security import check_permissions
|
||||||
from schemas import common as BaseSchema
|
from schemas import common as BaseSchema
|
||||||
from schemas import user as UserSchema
|
from schemas import user as UserSchema
|
||||||
|
from schemas.common import QueryData
|
||||||
from service.user import service as UserService
|
from service.user import service as UserService
|
||||||
|
|
||||||
router = APIRouter(prefix="/user", tags=["用户管理"])
|
router = APIRouter(prefix="/user", tags=["用户管理"])
|
||||||
@ -13,41 +14,38 @@ ListAll = BaseSchema.ListAll
|
|||||||
user_list_schema = ListAll[list[UserSchema.UserRead]]
|
user_list_schema = ListAll[list[UserSchema.UserRead]]
|
||||||
|
|
||||||
|
|
||||||
@router.get("", summary="用户列表", response_model=Response[user_list_schema])
|
@router.get("", summary="用户列表")
|
||||||
async def user_list(
|
async def user_list(query: QueryData = Depends()) -> Response[user_list_schema]:
|
||||||
offset: int = Query(default=1, description="偏移量-页码"),
|
return await UserService.get_items(query.offset, query.limit)
|
||||||
limit: int = Query(default=10, description="数据量"),
|
|
||||||
):
|
|
||||||
return await UserService.get_items(offset, limit)
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("/query", summary="用户查询", response_model=Response[user_list_schema])
|
@router.post("/query", summary="用户查询")
|
||||||
async def user_query(query: UserSchema.UserQuery):
|
async def user_query(query: UserSchema.UserQuery) -> Response[user_list_schema]:
|
||||||
return await UserService.query_items(query)
|
return await UserService.query_items(query)
|
||||||
|
|
||||||
|
|
||||||
@router.post("", summary="用户新增", response_model=Response[UserSchema.UserRead])
|
@router.post("", summary="用户新增")
|
||||||
async def user_create(data: UserSchema.UserAdd):
|
async def user_create(data: UserSchema.UserAdd) -> Response[UserSchema.UserRead]:
|
||||||
return await UserService.create_item(data)
|
return await UserService.create_item(data)
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/{pk}", summary="用户删除", response_model=Response)
|
@router.delete("/{pk}", summary="用户删除")
|
||||||
async def user_delete(pk: int):
|
async def user_delete(pk: int) -> Response:
|
||||||
return await UserService.delete_item(pk)
|
return await UserService.delete_item(pk)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{pk}", summary="用户信息", response_model=Response[UserSchema.UserInfo])
|
@router.get("/{pk}", summary="用户信息")
|
||||||
async def user_info(pk: int):
|
async def user_info(pk: int) -> Response[UserSchema.UserInfo]:
|
||||||
return await UserService.get_item(pk)
|
return await UserService.get_item(pk)
|
||||||
|
|
||||||
|
|
||||||
@router.put("/{pk}", summary="用户更新", response_model=Response)
|
@router.put("/{pk}", summary="用户更新")
|
||||||
async def user_update(pk: int, data: UserSchema.UserPut):
|
async def user_update(pk: int, data: UserSchema.UserPut) -> Response:
|
||||||
return await UserService.update_item(pk, data)
|
return await UserService.update_item(pk, data)
|
||||||
|
|
||||||
|
|
||||||
@router.put("/role/{rid}", summary="用户切换角色", response_model=Response)
|
@router.put("/role/{rid}", summary="用户切换角色")
|
||||||
async def user_change_role(
|
async def user_change_role(
|
||||||
rid: int, user: UserSchema.UserRead = Depends(check_permissions)
|
rid: int, user: UserSchema.UserRead = Depends(check_permissions)
|
||||||
):
|
) -> Response:
|
||||||
return await UserService.change_current_role(user.id, rid)
|
return await UserService.change_current_role(user.id, rid)
|
||||||
|
@ -26,8 +26,8 @@ class ReadBase(BaseModel):
|
|||||||
class LoginForm(BaseModel):
|
class LoginForm(BaseModel):
|
||||||
"""用户登录参数"""
|
"""用户登录参数"""
|
||||||
|
|
||||||
username: str = Field(..., description="账号", max_length=12, min_length=3)
|
username: str = Field("admin", description="账号", max_length=12, min_length=3)
|
||||||
password: str = Field(..., description="密码", min_length=6, max_length=16)
|
password: str = Field("123456", description="密码", min_length=6, max_length=16)
|
||||||
|
|
||||||
|
|
||||||
class LoginResult(BaseModel):
|
class LoginResult(BaseModel):
|
||||||
@ -41,8 +41,8 @@ class LoginResult(BaseModel):
|
|||||||
class QueryData(BaseModel):
|
class QueryData(BaseModel):
|
||||||
"""分页查询基础数据"""
|
"""分页查询基础数据"""
|
||||||
|
|
||||||
offset: int = 1
|
offset: int = Field(default=1, description="页码", ge=1)
|
||||||
limit: int = 10
|
limit: int = Field(default=10, description="数量", ge=1)
|
||||||
|
|
||||||
|
|
||||||
class ListAll(GenericModel, Generic[T]):
|
class ListAll(GenericModel, Generic[T]):
|
||||||
|
Loading…
Reference in New Issue
Block a user