Files
2026-10-11 14:12:10 +03:00

80 lines
2.5 KiB
Python

from __future__ import annotations
from datetime import datetime
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from sqlalchemy.orm import Session
from app.database import get_db
from app.models import User
from app.schemas import LoginRequest, SetupPasswordRequest, StatusResponse, TokenResponse
from app.services.auth import (
create_access_token,
decode_token,
get_or_create_profile,
get_user,
has_password,
hash_password,
verify_password,
)
router = APIRouter(prefix="/api/auth", tags=["auth"])
security = HTTPBearer(auto_error=False)
def require_auth(
creds: Optional[HTTPAuthorizationCredentials] = Depends(security),
db: Session = Depends(get_db),
) -> User:
if not creds:
raise HTTPException(401, "Требуется авторизация")
sub = decode_token(creds.credentials)
if not sub:
raise HTTPException(401, "Недействительный токен")
user = get_user(db)
if not user:
raise HTTPException(401, "Пользователь не найден")
return user
@router.get("/status", response_model=StatusResponse)
def auth_status(db: Session = Depends(get_db)) -> StatusResponse:
profile = get_or_create_profile(db)
return StatusResponse(
has_password=has_password(db),
onboarded=profile.onboarded,
phase=profile.phase,
)
@router.post("/setup", response_model=TokenResponse)
def setup_password(body: SetupPasswordRequest, db: Session = Depends(get_db)) -> TokenResponse:
if has_password(db):
raise HTTPException(400, "Пароль уже задан")
user = User(password_hash=hash_password(body.password), created_at=datetime.utcnow())
db.add(user)
get_or_create_profile(db)
db.commit()
profile = get_or_create_profile(db)
return TokenResponse(
access_token=create_access_token(),
needs_setup=False,
onboarded=profile.onboarded,
)
@router.post("/login", response_model=TokenResponse)
def login(body: LoginRequest, db: Session = Depends(get_db)) -> TokenResponse:
user = get_user(db)
if not user:
raise HTTPException(400, "Сначала задайте пароль")
if not verify_password(body.password, user.password_hash):
raise HTTPException(401, "Неверный пароль")
profile = get_or_create_profile(db)
return TokenResponse(
access_token=create_access_token(),
onboarded=profile.onboarded,
)