| from datetime import datetime, timezone
|
|
|
| from app.core.exceptions import ForbiddenError, UnauthorizedError
|
| from app.core.security import create_access_token, verify_password
|
| from app.models.user import User
|
| from app.repositories.user import UserRepository
|
| from app.schemas.user import TokenResponse, UserResponse
|
|
|
|
|
| class AuthService:
|
| def __init__(self, repo: UserRepository):
|
| self.repo = repo
|
|
|
| async def login(self, username: str, password: str) -> TokenResponse:
|
| user = await self.repo.get_by_username(username)
|
|
|
| if not user or not verify_password(password, user.password_hash):
|
| raise UnauthorizedError("Incorrect username or password")
|
|
|
| if not user.is_active:
|
| raise ForbiddenError("Account is disabled")
|
|
|
|
|
| await self.repo.update(user, last_login_at=datetime.now(timezone.utc))
|
|
|
| token = create_access_token({"sub": str(user.id), "role": user.role})
|
| return TokenResponse(
|
| access_token=token,
|
| user=UserResponse.model_validate(user),
|
| )
|
|
|
| async def get_user_by_id(self, user_id: int) -> User:
|
| user = await self.repo.get(user_id)
|
| if not user or not user.is_active:
|
| raise UnauthorizedError("User not found or inactive")
|
| return user |