You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

58 lines
1.9 KiB

from typing import Annotated
from fastapi import Depends, Request, HTTPException
from fastapi.templating import Jinja2Templates
from passlib.context import CryptContext
from database import get_db
from models import User, UserRole
from sqlalchemy.orm import Session
pwd_context = CryptContext(schemes=["argon2"], deprecated="auto")
templates = Jinja2Templates(directory="templates")
templates.env.filters['average'] = lambda lst: sum(lst) / len(lst) if lst else 0
def verify_password(plain_password, hashed_password):
return pwd_context.verify(plain_password, hashed_password)
def get_password_hash(password):
try:
password_bytes = password.encode('utf-8')
if len(password_bytes) > 72:
password_bytes = password_bytes[:72]
password = password_bytes.decode('utf-8', errors='ignore')
return pwd_context.hash(password)
except Exception as e:
print(f"Error hashing password: {e}")
print(f"Password length: {len(password)}, Bytes: {len(password.encode('utf-8'))}")
raise
def get_current_user(request: Request, db: Session = Depends(get_db)):
user_id = request.session.get("user_id")
if not user_id:
return None
user = db.query(User).filter(User.id == user_id).first()
return user
def require_auth(request: Request, db: Session = Depends(get_db)):
user = get_current_user(request, db)
if not user:
raise HTTPException(status_code=303, headers={"Location": "/login"})
return user
def require_role(role: UserRole):
def dependency(request: Request, db: Session = Depends(get_db)):
user = get_current_user(request, db)
if not user:
raise HTTPException(status_code=303, headers={"Location": "/login"})
if user.role != role:
raise HTTPException(status_code=403, detail="权限不足")
return user
return dependency