""" ©AngelaMos | 2025 Authentication service for user registration and login """ from __future__ import annotations from datetime import timedelta from sqlalchemy.orm import Session from fastapi import HTTPException, status from config import settings from core.security import ( create_access_token, hash_password, verify_password, ) from schemas.user_schemas import ( TokenResponse, UserCreate, UserLogin, UserResponse, ) from repositories.user_repository import UserRepository class AuthService: """ User registration, login, and token generation """ @staticmethod def register_user(db: Session, user_data: UserCreate) -> UserResponse: """ Register a new user Args: db: Database session user_data: User registration data Returns: UserResponse: Created user data """ existing_user = UserRepository.get_by_email(db, user_data.email) if existing_user: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Email already registered", ) hashed_password = hash_password(user_data.password) user = UserRepository.create_user( db=db, email=user_data.email, hashed_password=hashed_password, ) return UserResponse.model_validate(user) @staticmethod def login_user(db: Session, login_data: UserLogin) -> TokenResponse: """ Authenticate user and generate access token Args: db: Database session login_data: User login credentials Returns: TokenResponse: JWT access token """ user = UserRepository.get_by_email(db, login_data.email) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid email or password", ) if not verify_password(login_data.password, user.hashed_password): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid email or password", ) if not user.is_active: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Account is inactive", ) access_token = create_access_token( data={"sub": user.email}, expires_delta=timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES), ) return TokenResponse(access_token=access_token, token_type="bearer") @staticmethod def get_user_by_email(db: Session, email: str) -> UserResponse | None: """ Get user by email address Args: db: Database session email: User email Returns: UserResponse | None: User data or None if not found """ user = UserRepository.get_by_email(db, email) if user: return UserResponse.model_validate(user) return None