Files
SQLBot/backend/apps/system/middleware/auth.py
T

89 lines
3.8 KiB
Python

from typing import Optional
from fastapi import Request
from fastapi.responses import JSONResponse
import jwt
from sqlmodel import Session
from starlette.middleware.base import BaseHTTPMiddleware
from common.core.db import engine
from apps.system.crud.assistant import get_assistant_info, get_assistant_user
from apps.system.crud.user import get_user_info
from apps.system.schemas.system_schema import UserInfoDTO
from common.core import security
from common.core.config import settings
from common.core.schemas import TokenPayload
from common.utils.whitelist import whiteUtils
from fastapi.security.utils import get_authorization_scheme_param
class TokenMiddleware(BaseHTTPMiddleware):
def __init__(self, app):
super().__init__(app)
async def dispatch(self, request, call_next):
if self.is_options(request) or whiteUtils.is_whitelisted(request.url.path):
return await call_next(request)
assistantTokenKey = settings.ASSISTANT_TOKEN_KEY
assistantToken = request.headers.get(assistantTokenKey)
#if assistantToken and assistantToken.lower().startswith("assistant "):
if assistantToken:
validate_pass, data, assistant = await self.validateAssistant(assistantToken)
if validate_pass:
request.state.current_user = data
request.state.assistant = assistant
return await call_next(request)
return JSONResponse({"error": f"Unauthorized:[{data}]"}, status_code=401)
#validate pass
tokenkey = settings.TOKEN_KEY
token = request.headers.get(tokenkey)
validate_pass, data = await self.validateToken(token)
if validate_pass:
request.state.current_user = data
return await call_next(request)
return JSONResponse({"error": f"Unauthorized:[{data}]"}, status_code=401)
def is_options(self, request: Request):
return request.method == "OPTIONS"
async def validateToken(self, token: Optional[str]):
if not token:
return False, f"Miss Token[{settings.TOKEN_KEY}]!"
schema, param = get_authorization_scheme_param(token)
if schema.lower() != "bearer":
return False, f"Token schema error!"
payload = jwt.decode(
param, settings.SECRET_KEY, algorithms=[security.ALGORITHM]
)
token_data = TokenPayload(**payload)
try:
with Session(engine) as session:
session_user = await get_user_info(session = session, user_id = token_data.id)
session_user = UserInfoDTO.model_validate(session_user)
return True, session_user
except Exception as e:
return False, e
async def validateAssistant(self, assistantToken: Optional[str]):
if not assistantToken:
return False, f"Miss Token[{settings.TOKEN_KEY}]!"
schema, param = get_authorization_scheme_param(assistantToken)
if schema.lower() != "assistant":
return False, f"Token schema error!"
payload = jwt.decode(
param, settings.SECRET_KEY, algorithms=[security.ALGORITHM]
)
token_data = TokenPayload(**payload)
if not payload['assistant_id']:
return False, f"Miss assistant payload error!"
try:
with Session(engine) as session:
""" session_user = await get_user_info(session = session, user_id = token_data.id)
session_user = UserInfoDTO.model_validate(session_user) """
session_user = get_assistant_user(id = token_data.id)
assistant_info = get_assistant_info(session, payload['assistant_id'])
return True, session_user, assistant_info
except Exception as e:
return False, e