Files
WonderQ-Admin/app/auth.py
duanshuwen 75f5a5a48b feat: add WonderQ admin backend
Add FastAPI admin/public API service, database setup, Docker deployment files, docs, and tests.
2026-06-30 13:56:45 +08:00

57 lines
1.9 KiB
Python

from datetime import datetime, timedelta, timezone
import bcrypt
import jwt
from fastapi import Depends, HTTPException, Request, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from sqlalchemy.orm import Session
from .config import get_settings
from .database import get_db
from .models import AdminUser
bearer = HTTPBearer(auto_error=False)
def verify_password(password: str, password_hash: str) -> bool:
return bcrypt.checkpw(password.encode("utf-8"), password_hash.encode("utf-8"))
def hash_password(password: str, rounds: int = 12) -> str:
return bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt(rounds)).decode("utf-8")
def create_token(user: AdminUser) -> str:
settings = get_settings()
now = datetime.now(timezone.utc)
payload = {
"sub": user.id,
"email": user.email,
"role": user.role,
"iat": now,
"exp": now + timedelta(hours=settings.jwt_expires_hours),
}
return jwt.encode(payload, settings.jwt_secret, algorithm="HS256")
def require_admin(
request: Request,
credentials: HTTPAuthorizationCredentials | None = Depends(bearer),
db: Session = Depends(get_db),
) -> AdminUser:
if credentials is None:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="请先登录后台")
try:
payload = jwt.decode(credentials.credentials, get_settings().jwt_secret, algorithms=["HS256"])
except jwt.PyJWTError as exc:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="请先登录后台") from exc
user_id = payload.get("sub")
user = db.get(AdminUser, user_id) if user_id else None
if not user or not user.isActive:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="请先登录后台")
request.state.actor_id = user.id
return user
def get_actor_id(request: Request) -> str | None:
return getattr(request.state, "actor_id", None)