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, )