Files
info-user/server/routes/auth_routes.py
T

90 lines
3.0 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, status, Response
from fastapi.security import OAuth2PasswordRequestForm
from sqlalchemy.orm import Session
from datetime import datetime, timezone
from typing import Optional
from database import get_db
from auth import (
verify_password,
get_password_hash,
create_access_token,
create_refresh_token,
verify_token,
get_current_user,
create_default_admin,
)
from models import User
from schemas import UserCreate, UserOut, LoginPayload, Token, TokenRefresh
router = APIRouter(prefix="/api/auth", tags=["auth"])
@router.post("/register", response_model=UserOut, status_code=status.HTTP_201_CREATED)
def register(payload: UserCreate, db: Session = Depends(get_db)):
existing = db.query(User).filter(User.username == payload.username).first()
if existing:
raise HTTPException(status_code=400, detail="Username already exists")
user = User(
username=payload.username,
password_hash=get_password_hash(payload.password),
role="viewer",
)
db.add(user)
db.commit()
db.refresh(user)
return user
@router.post("/login", response_model=Token)
def login(
response: Response,
form_data: OAuth2PasswordRequestForm = Depends(),
db: Session = Depends(get_db),
):
create_default_admin(db)
user = db.query(User).filter(User.username == form_data.username).first()
if not user or not verify_password(form_data.password, user.password_hash):
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials")
access = create_access_token({"sub": user.username, "role": user.role})
refresh = create_refresh_token({"sub": user.username, "role": user.role})
response.set_cookie(
key="access_token",
value=access,
httponly=True,
max_age=1800,
samesite="lax",
)
return {"access_token": access, "refresh_token": refresh}
@router.post("/refresh", response_model=Token)
def refresh(payload: TokenRefresh, response: Response, db: Session = Depends(get_db)):
data = verify_token(payload.refresh_token, "refresh")
if not data or "sub" not in data:
raise HTTPException(status_code=401, detail="Invalid refresh token")
user = db.query(User).filter(User.username == data["sub"]).first()
if not user:
raise HTTPException(status_code=401, detail="User not found")
access = create_access_token({"sub": user.username, "role": user.role})
refresh = create_refresh_token({"sub": user.username, "role": user.role})
response.set_cookie(
key="access_token",
value=access,
httponly=True,
max_age=1800,
samesite="lax",
)
return {"access_token": access, "refresh_token": refresh}
@router.get("/me", response_model=UserOut)
def me(user: User = Depends(get_current_user)):
return user
@router.post("/logout")
def logout(response: Response):
response.delete_cookie("access_token")
return {"ok": True}