diff --git a/server/common/auth_casbin.py b/server/common/auth_casbin.py
index d6fcb69..d88114c 100644
--- a/server/common/auth_casbin.py
+++ b/server/common/auth_casbin.py
@@ -1,3 +1,4 @@
+from loguru import logger
from fastapi import Request, HTTPException
from ..settings import casbin_enforcer
@@ -12,5 +13,5 @@ def __call__(self, request: Request):
return True
model, act = self.policy.split(':')
if not casbin_enforcer.enforce(f'uid_{request.state.uid}', model, act):
- print('没有权限')
+ logger.warning(f'uid_{request.state.uid} {model} {act} 没有权限')
raise HTTPException(status_code=403, detail="没有权限")
diff --git a/server/common/log.py b/server/common/log.py
new file mode 100644
index 0000000..f308de5
--- /dev/null
+++ b/server/common/log.py
@@ -0,0 +1,37 @@
+import logging
+from loguru import logger
+
+
+# 参考自:https://gist.github.com/nkhitrov/a3e31cfcc1b19cba8e1b626276148c49
+
+
+class InterceptHandler(logging.Handler):
+ def emit(self, record):
+ # Get corresponding Loguru level if it exists
+ try:
+ level = logger.level(record.levelname).name
+ except ValueError:
+ level = record.levelno
+
+ # Find caller from where originated the logged message
+ frame, depth = logging.currentframe(), 2
+ while frame.f_code.co_filename == logging.__file__:
+ frame = frame.f_back
+ depth += 1
+
+ logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())
+
+
+def init_logging():
+ # 获取所有uvicorn的日志设定,并重置
+ print(logging.root.manager.loggerDict)
+ loggers = (
+ logging.getLogger(name)
+ for name in logging.root.manager.loggerDict
+ if name.startswith("uvicorn.")
+ )
+
+ for uvicorn_logger in loggers:
+ # 为了防止日志重复输出
+ uvicorn_logger.propagate = False
+ uvicorn_logger.handlers = [InterceptHandler()]
diff --git a/server/common/security.py b/server/common/security.py
index da41a28..6b3fd9c 100644
--- a/server/common/security.py
+++ b/server/common/security.py
@@ -1,3 +1,6 @@
+import logging
+
+from loguru import logger
from datetime import datetime, timedelta
from fastapi import Request, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
@@ -21,9 +24,10 @@ def auth_check(request: Request):
:param request:
:return:
"""
+ logger.info(f'request url:{request.url} method:{request.method}')
for url in settings.NO_VERIFY_URL:
if url == request.url.path.lower():
- print(f"{request.url.path} 在白名单中,不需要权限验证")
+ logger.debug(f"{request.url.path} 在白名单中,不需要权限验证")
return True
authorization: str = request.headers.get("Authorization")
schema, param = get_authorization_scheme_param(authorization)
diff --git a/server/common/utils.py b/server/common/utils.py
index b0733e5..5c2e890 100644
--- a/server/common/utils.py
+++ b/server/common/utils.py
@@ -1,5 +1,6 @@
import os
from typing import List, Generic, Type, TypeVar
+from loguru import logger
from sqlmodel import SQLModel
from ..models.internal.menu import MenusWithChild
@@ -61,5 +62,5 @@ def update_model(old_model, new_model):
def remove_tmp_file(file):
- print(f'删除临时文件{file}')
+ logger.debug(f'删除临时文件{file}')
os.remove(file)
diff --git a/server/crud/base.py b/server/crud/base.py
index 5efcdfa..5a2472e 100644
--- a/server/crud/base.py
+++ b/server/crud/base.py
@@ -1,5 +1,6 @@
# 参考自:tiangolo/full-stack-fastapi-postgresql项目,部分代码为直接摘抄
from copy import deepcopy
+from loguru import logger
from typing import TypeVar, Generic, List, Type, Any, Dict, Optional
from sqlmodel import Session, select, SQLModel, func, desc
from ..schemas.internal.pagination import Pagination
@@ -28,7 +29,7 @@ def insert(self, db: Session, obj_in):
def update(self, db: Session, db_obj: ModelType, new_obj: ModelType):
# SQLModel直接使用的pydantic的dict方法,没有轮询SQLModel封装的__sqlmodel_relationships__,对于外键的更新,只能手动指定
update_date = new_obj.dict()
- print(update_date)
+ logger.debug(update_date)
for field in update_date:
setattr(db_obj, field, update_date[field])
db.add(db_obj)
@@ -76,13 +77,14 @@ def _make_search(self, sql, search: Optional[Dict[str, Any]] = None, filter_type
return sql
def search(self, session: Session, search: Pagination, filter_type: Optional[Dict[str, str]] = None,
- columns: Optional[List] = None):
+ columns: Optional[List] = None, order_col: Optional[str] = 'id'):
"""
分页查询方法
:param session:
:param search: Pagination实例对象,包含各搜索参数
:param filter_type: 指定的各属性值判断形式
:param columns: 查询返回指定columns
+ :param order_col: order排序列名,默认id,此col需要为自增id
:return:
"""
if columns is None:
@@ -90,19 +92,20 @@ def search(self, session: Session, search: Pagination, filter_type: Optional[Dic
else:
sql = select(*columns)
sql = self._make_search(sql, search.search, filter_type)
- subquery = select(self.model.id)
+ subquery = select(getattr(self.model, order_col))
subquery = self._make_search(subquery, search.search, filter_type)
if search.model == 'desc':
- subquery = subquery.order_by(desc(self.model.id))
+ subquery = subquery.order_by(desc(getattr(self.model, order_col)))
else:
- subquery = subquery.order_by(self.model.id)
+ subquery = subquery.order_by(getattr(self.model, order_col))
subquery = subquery.offset(
(search.page - 1) * search.page_size).limit(1).subquery()
if search.model == 'desc':
- sql = sql.where(self.model.id <= subquery).order_by(desc(self.model.id)).limit(search.page_size)
+ sql = sql.where(getattr(self.model, order_col) <= subquery).order_by(desc(getattr(self.model, order_col))).limit(
+ search.page_size)
else:
- sql = sql.where(self.model.id >= subquery).limit(search.page_size)
- print(sql)
+ sql = sql.where(getattr(self.model, order_col) >= subquery).limit(search.page_size)
+ logger.debug(sql)
results = session.exec(sql).all()
return results
@@ -116,5 +119,5 @@ def search_total(self, session: Session, q: Dict[str, Any], filter_type: Optiona
"""
sql = select(func.count(self.model.id))
sql = self._make_search(sql, q, filter_type)
- print(str(sql))
+ logger.debug(str(sql))
return session.execute(sql).scalar()
diff --git a/server/crud/internal/dictonary.py b/server/crud/internal/dictonary.py
index 21b1e9c..24f741a 100644
--- a/server/crud/internal/dictonary.py
+++ b/server/crud/internal/dictonary.py
@@ -1,9 +1,9 @@
-from typing import Union
-from sqlmodel import select, Session
-from ...models.internal.dictonary import DataDict, DictItem
+from typing import Optional, List, Dict
+from loguru import logger
+from sqlmodel import select, Session, desc
+from ...models.internal.dictonary import DataDict, DictItem, DictItemSearch
from ..base import CRUDBase
-from ...schemas.internal.user import UserInfo, UserLogin
-from .roles import role
+from ...schemas.internal.pagination import Pagination
class CRUDDict(CRUDBase[DataDict]):
@@ -14,9 +14,24 @@ class CRUDItem(CRUDBase[DictItem]):
def get_items_by_code(self, db: Session, code: str):
dict_id = select(DataDict.id).where(DataDict.code == code).subquery()
sql = select(self.model).where(self.model.dict_id == dict_id).where(self.model.enable == 1).order_by(
- self.model.id)
+ self.model.sort)
return db.exec(sql).all()
+ def search(self, session: Session, search: Pagination[DictItemSearch], filter_type: Optional[Dict[str, str]] = None,
+ columns: Optional[List] = None, order_col: Optional[str] = 'id'):
+ """
+ 重写search函数,数据字典通过sort进行排序
+ """
+ sql = select(self.model).where(self.model.dict_id == search.search['dict_id'])
+ sql = self._make_search(sql, search.search, filter_type)
+ if search.model == 'desc':
+ sql = sql.order_by(desc(self.model.sort))
+ else:
+ sql = sql.order_by(self.model.sort)
+ sql = sql.limit(search.page_size).offset((search.page - 1) * search.page_size)
+ logger.debug(sql)
+ return session.exec(sql).all()
+
data_dict = CRUDDict(DataDict)
dict_item = CRUDItem(DictItem)
diff --git a/server/crud/internal/menu.py b/server/crud/internal/menu.py
index 10d1ddd..bd8c514 100644
--- a/server/crud/internal/menu.py
+++ b/server/crud/internal/menu.py
@@ -1,4 +1,5 @@
from typing import Optional, List
+from loguru import logger
from sqlmodel import Session, select
from ...models.internal.menu import Menu
from ..base import CRUDBase
@@ -19,7 +20,7 @@ def update(self, session: Session, db_obj, obj_in: Menu):
:param obj_in:
:return:
"""
- print(db_obj)
+ logger.debug(db_obj)
return super(CRUDMenu, self).update(session, db_obj, obj_in)
def delete(self, session: Session, id: int):
diff --git a/server/crud/internal/roles.py b/server/crud/internal/roles.py
index db0b49a..397ea95 100644
--- a/server/crud/internal/roles.py
+++ b/server/crud/internal/roles.py
@@ -1,4 +1,5 @@
from typing import List, Optional
+from loguru import logger
from sqlmodel import select, Session
from ...models.internal import Role, Menu, RoleMenu
from ..base import CRUDBase
@@ -43,15 +44,15 @@ def update_menus(self, session: Session, db_obj: Role, menus: List[int]):
:param menus:
:return:
"""
- print(db_obj.menus)
+ logger.debug(db_obj.menus)
db_menus = session.exec(select(Menu).where(Menu.id.in_(menus))).all()
db_obj.menus = db_menus
casbin_enforcer.delete_permissions_for_user(f'role_{db_obj.id}')
- print(db_menus)
+ logger.debug(db_menus)
for menu in db_menus:
- if menu.auth is not None:
+ if (menu.auth is not None) and menu.auth:
model, act = menu.auth.split(':')
- print(f'增加权限:role_{db_obj.id},{model},{act}')
+ logger.debug(f'增加权限:role_{db_obj.id},{model},{act}')
casbin_enforcer.add_permission_for_user(f'role_{db_obj.id}', model, act)
session.add(db_obj)
session.commit()
diff --git a/server/crud/internal/user.py b/server/crud/internal/user.py
index b16d154..102d7b0 100644
--- a/server/crud/internal/user.py
+++ b/server/crud/internal/user.py
@@ -1,4 +1,5 @@
from typing import Union
+from loguru import logger
from sqlmodel import select, Session
from ...models.internal.user import User
from ..base import CRUDBase
@@ -29,8 +30,8 @@ def update(self, session: Session, uid: int, user_info: UserInfo):
db_obj = super(CRUDUser, self).update(session, db_obj, updated_user)
user_roles = role.get_roles_by_id(session, user_info.roles)
db_obj.roles = user_roles
- print('update:')
- print(db_obj)
+ logger.debug('update:')
+ logger.debug(db_obj)
session.add(db_obj)
session.commit()
session.refresh(db_obj)
diff --git a/server/main.py b/server/main.py
index 7fca15c..6c46ca1 100644
--- a/server/main.py
+++ b/server/main.py
@@ -1,12 +1,13 @@
-from sqlmodel import Session
from fastapi import FastAPI, Depends
+from loguru import logger
+from .common.log import init_logging
from .routers.internal import login, user, menu, roles, dictonary
from .common.security import auth_check
-from .settings import engine
+
+init_logging()
app = FastAPI(dependencies=[Depends(auth_check)])
-# 不执行check_permission的,表示不需要权限验证
app.include_router(login.router, tags=['用户登录'])
app.include_router(user.router, tags=['用户管理'])
app.include_router(menu.router, tags=['菜单管理'])
@@ -15,15 +16,14 @@
@app.on_event("startup")
-def startup():
+async def startup():
"""
在此时添加openapi数据的获取,导入api表,判断有没有新接口信息需要添加进去
:return:
"""
- print('服务启动后执行服务')
- print('API接口更新')
+ logger.debug('服务启动后执行服务')
@app.on_event("shutdown")
def shutdown():
- print('关闭服务')
+ logger.debug('关闭服务')
diff --git a/server/routers/internal/login.py b/server/routers/internal/login.py
index e5c9df8..84dccd0 100644
--- a/server/routers/internal/login.py
+++ b/server/routers/internal/login.py
@@ -1,4 +1,5 @@
from typing import List
+from loguru import logger
from fastapi import APIRouter, Depends, Request, status
from ...common.database import get_session
from sqlmodel import Session, select
@@ -52,9 +53,9 @@ async def get_permission(request: Request, session: Session = Depends(get_sessio
:return:
"""
uid: int = request.state.uid
- print(f"uid is:{uid}")
+ logger.debug(f"uid is:{uid}")
user: User = crud.internal.user.get(session, uid)
- print(user.roles)
+ logger.debug(user.roles)
user_menus = []
# admin组用户获取所有菜单列表
if uid == 1 or crud.internal.role.check_admin(session, uid):
@@ -66,11 +67,9 @@ async def get_permission(request: Request, session: Session = Depends(get_sessio
menu_list = session.exec(
select(Menu).where(Menu.id.in_(set(user_menus))).where(Menu.type != 'btn').order_by(Menu.sort)).all()
btn_list = session.exec(select(Menu.auth).where(Menu.id.in_(set(user_menus))).where(Menu.type == 'btn')).all()
- print('menulist')
- print(menu_list)
user_menus = menu_convert(menu_list)
- print(user_menus)
+ logger.debug(f"user menus:{user_menus}")
return ApiResponse(
data={
'menus': user_menus,
diff --git a/server/routers/internal/roles.py b/server/routers/internal/roles.py
index 5b90e4c..71ffc7f 100644
--- a/server/routers/internal/roles.py
+++ b/server/routers/internal/roles.py
@@ -1,4 +1,5 @@
from typing import Optional, List
+from loguru import logger
from fastapi import APIRouter, Depends, status
from fastapi.exceptions import HTTPException
from sqlmodel import Session
@@ -38,7 +39,7 @@ async def get_role_menus(id: Optional[int] = None, session: Session = Depends(ge
summary="查询角色")
async def get_roles(search: Pagination[RoleBase], session: Session = Depends(get_session)):
total = crud.internal.role.search_total(session, search.search, {'name': 'like', 'enable': 'eq'})
- print(total)
+ logger.debug(total)
roles: List[Role] = crud.internal.role.search(session, search, {'name': 'like', 'enable': 'eq'})
role_with_menus: List[RoleWithMenus] = []
for role in roles:
@@ -55,7 +56,7 @@ async def get_roles(search: Pagination[RoleBase], session: Session = Depends(get
@router.post('/roles', summary="新建角色", response_model=ApiResponse[Role],
dependencies=[Depends(Authority('role:add'))])
async def add_roles(role_info: RoleInsert, session: Session = Depends(get_session)):
- print(role_info)
+ logger.debug(role_info)
enable_menus = role_info.menus
delattr(role_info, 'menus')
db_obj = crud.internal.role.insert(session, Role(**role_info.dict()))
@@ -68,7 +69,7 @@ async def add_roles(role_info: RoleInsert, session: Session = Depends(get_sessio
@router.put('/roles', summary="更新角色", response_model=ApiResponse[Role],
dependencies=[Depends(Authority('role:update'))])
async def update_roles(role_info: RoleUpdate, session: Session = Depends(get_session)):
- print(role_info)
+ logger.debug(role_info)
if role_info.name == 'admin':
ApiResponse(code=status.HTTP_400_BAD_REQUEST, message='admin权限组无法更新信息')
db_obj = crud.internal.role.get(session, role_info.id)
diff --git a/server/routers/internal/user.py b/server/routers/internal/user.py
index fed7061..eb54a1c 100644
--- a/server/routers/internal/user.py
+++ b/server/routers/internal/user.py
@@ -1,4 +1,5 @@
from typing import Optional, List
+from loguru import logger
from sqlmodel import Session, select
from sqlalchemy.exc import NoResultFound
from fastapi import APIRouter, Depends, status, HTTPException
@@ -66,10 +67,10 @@ async def get_all_user(search: Pagination[UserWithOutPasswd],
:return:
"""
total = crud.internal.user.search_total(session, search.search, {'name': 'like', 'enable': 'eq'})
- print(total)
+ logger.debug(total)
users = crud.internal.user.search(session, search, {'name': 'like', 'enable': 'eq'})
users_list = [user.dict(exclude={"password"}) for user in users]
- print(users_list)
+ logger.debug(users_list)
return ApiResponse(
data={
'total': total,
@@ -87,7 +88,7 @@ async def update_user(user_info: UserCreateWithRoles, session: Session = Depends
:param session:
:return:
"""
- print(user_info)
+ logger.debug(user_info)
user: User = crud.internal.user.insert(session, user_info)
new_roles = [role.id for role in user.roles]
for role in new_roles:
@@ -113,7 +114,7 @@ async def update_user(uid: int, user_info: UserUpdateWithRoles, session: Session
:param session:
:return:
"""
- print(user_info.dict(exclude_unset=True, exclude_none=True))
+ logger.debug(user_info.dict(exclude_unset=True, exclude_none=True))
user = crud.internal.user.update(session, uid, user_info)
new_roles = [role.id for role in user.roles]
casbin_enforcer.delete_roles_for_user(f'uid_{user.id}')
diff --git a/www/src/components/AutoDict.vue b/www/src/components/AutoDict.vue
index 5c2177c..a77a31c 100644
--- a/www/src/components/AutoDict.vue
+++ b/www/src/components/AutoDict.vue
@@ -12,29 +12,84 @@
+ 全选
- {{item.label}}
+
+
+ {{ item.label }}
+
+
+
diff --git a/www/src/views/system/roles/index.vue b/www/src/views/system/roles/index.vue
index 509a9f6..2991e79 100644
--- a/www/src/views/system/roles/index.vue
+++ b/www/src/views/system/roles/index.vue
@@ -126,7 +126,7 @@
id: null,
name: '',
description: '',
- enable: ''
+ enable: true
})
console.log(selectRole)
dialogVisible.value = true