diff --git a/backend/app/api/api_v1/routers/auth.py b/backend/app/api/api_v1/routers/auth.py index efc1a4d..fcacd71 100644 --- a/backend/app/api/api_v1/routers/auth.py +++ b/backend/app/api/api_v1/routers/auth.py @@ -46,6 +46,9 @@ async def login(request: Request,db:Session= Depends(get_db) ,form_data: OAuth2P data={"sub": user.id,"roles":roles,"permissions": permissions,"tenant":user.tenantid,}, expires_delta=access_token_expires, ) + + request.state.user = user + return JSONResponse( status_code=200, content={"access_token": access_token, "token_type": "bearer","user_name":user.first_name + " " + user.last_name} diff --git a/backend/app/core/auth.py b/backend/app/core/auth.py index 23c6231..e9153a8 100644 --- a/backend/app/core/auth.py +++ b/backend/app/core/auth.py @@ -9,7 +9,7 @@ from app.core import security from app.db.cruddb import userService from app.core.dbmanager import get_db -async def get_current_user(security_scopes: SecurityScopes, +async def get_current_user(request: Request,security_scopes: SecurityScopes, db=Depends(get_db), token: str = Depends(security.oauth2_scheme) ): credentials_exception = HTTPException( @@ -42,6 +42,7 @@ async def get_current_user(security_scopes: SecurityScopes, user = userService.get_user(db, token_data.id) if user is None: raise credentials_exception + request.state.user = user return user async def get_current_active_user( diff --git a/backend/app/core/dbmanager.py b/backend/app/core/dbmanager.py index a4ccf98..d32a612 100644 --- a/backend/app/core/dbmanager.py +++ b/backend/app/core/dbmanager.py @@ -1,18 +1,21 @@ -from fastapi import Depends +from fastapi import Depends,Request from app.db.session import get_tenant_db,get_user_db from app.core import tenantCacheService from app.db.session import tenantdb -def get_db(tenant:str = "1",tenantdb = Depends(get_tenant_db)): +def get_db(request: Request,tenant:str = "1",tenantdb = Depends(get_tenant_db)): db_url = tenantCacheService.get_tenant_db(tenantdb,tenant) db = get_user_db(db_url) try: + request.state.tenant = tenant + request.state.db = db yield db finally: db.close() -def get_log_db(): +def get_log_db(request: Request): db = tenantdb.get_db() + request.state.db = db return db \ No newline at end of file diff --git a/backend/app/core/operation.py b/backend/app/core/operation.py index 7b5d457..05011d8 100644 --- a/backend/app/core/operation.py +++ b/backend/app/core/operation.py @@ -6,47 +6,57 @@ from app.db.models import OperationLog,User from functools import wraps from fastapi import Request +from contextvars import ContextVar +import json - - -def log_operation(func): - """自定义装饰器用于记录操作日志""" - @wraps(func) - async def wrapper(*args, **kwargs): - if 'request' in kwargs and isinstance(kwargs['request'], Request): - request: Request = kwargs['request'] - method = request.method - url = str(request.url) - client_ip = request.client.host - headers = dict(request.headers) - user_agent = headers.get("user-agent", "") - - if 'db' in kwargs and isinstance(kwargs['db'], Session): - db = kwargs['db'] - if 'user' in kwargs and isinstance(kwargs['user'], User): - user = kwargs['user'] - user_id = user.id - tenant_id = user.tenantid +class LoggingMiddleware(BaseHTTPMiddleware): + async def dispatch(self, request: Request, call_next): + if hasattr(request.state, "user") and hasattr(request.state, "tenant"): + if request.method in ("POST", "PUT", "PATCH","DELETE"): + try: + request.state.body = await request.json() + except json.JSONDecodeError: + request.state.body = await request.body() else: - user_id = None - tenant_id = None + request.state.body = None + + try: + response = await call_next(request) + state = request.state + except Exception as e: + await self.log_error(request, e) + raise - - try: - response = await func(*args, **kwargs) - if db: - db_operation = OperationLog(tenantid =tenant_id, - clientip =client_ip, - useragent =user_agent, - userid = user_id, - operation = method, - function = url, - response = f"status_code:{response.status_code }" ) - - db.add(db_operation) - db.commit() - except Exception as e: - raise e + await self.log_request(request, response,state) + else: + response = await call_next(request) + return response - return wrapper + async def log_request(self, request: Request, response,state): + try: + headers = dict(request.headers) + + db_operation = OperationLog(tenantid =request.state.tenant, + clientip = request.client.host if request.client else None, + useragent =headers.get("user-agent", ""), + userid = request.state.user.id, + operation = request.method, + function = request.url.path, + response = f"status_code:{response.status_code }" ) + + db = request.state.db + if db: + await self.write_log_to_db(db_operation,db) + except Exception as e: + print(f"Logging failed: {str(e)}") + + + async def log_error(self, request: Request, exc: Exception): + # 错误处理逻辑 + pass + + async def write_log_to_db(self, db_operation,db): + db.add(db_operation) + db.commit() + \ No newline at end of file diff --git a/backend/app/main.py b/backend/app/main.py index b718962..479c4f7 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -20,7 +20,7 @@ from app.db.crud import create_log from fastapi.responses import JSONResponse import asyncio from contextlib import asynccontextmanager - +from app.core.operation import LoggingMiddleware #Base.metadata.create_all(bind=engine) @@ -45,6 +45,8 @@ app.add_middleware( allow_headers=["*"], ) +app.add_middleware(LoggingMiddleware) + add_pagination(app) # @app.middleware("http")