From 8ec86398485bf6afd08f266110d3844014156222 Mon Sep 17 00:00:00 2001 From: IluaAir Date: Sun, 20 Jul 2025 12:34:18 +0300 Subject: [PATCH] create cur user --- src/api/dependacies/user_dep.py | 30 ++++++++++++++++++++++++++++++ src/api/v1/users.py | 6 ++++++ src/core/auth_manager.py | 8 ++++++++ src/core/settings.py | 8 ++++++++ src/schemas/auth.py | 5 +++++ src/services/auth.py | 4 +++- 6 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/api/dependacies/user_dep.py diff --git a/src/api/dependacies/user_dep.py b/src/api/dependacies/user_dep.py new file mode 100644 index 0000000..90735ac --- /dev/null +++ b/src/api/dependacies/user_dep.py @@ -0,0 +1,30 @@ +from typing import Annotated + +from fastapi import HTTPException, Depends +from fastapi.security import OAuth2PasswordBearer +from jwt import InvalidTokenError + +from src.core.auth_manager import AuthManager +from src.core.settings import settings +from src.schemas.auth import TokenData + +oauth2_scheme = OAuth2PasswordBearer(tokenUrl=f"{settings.api.v1_login_url}/login") + + +async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]): + credentials_exception = HTTPException( + status_code=401, + detail="Could not validate credentials", + headers={"WWW-Authenticate": "Bearer"}, + ) + try: + payload = AuthManager.decode_access_token(token=token) + if payload is None: + raise credentials_exception + user = TokenData(**payload) + except InvalidTokenError: + raise credentials_exception + return user + + +CurUsr = Annotated[TokenData, Depends(get_current_user)] diff --git a/src/api/v1/users.py b/src/api/v1/users.py index e354377..737e561 100644 --- a/src/api/v1/users.py +++ b/src/api/v1/users.py @@ -1,5 +1,11 @@ from fastapi import APIRouter +from src.api.dependacies.user_dep import CurUsr from src.core.settings import settings router = APIRouter(prefix=settings.api.v1.users, tags=["Users"]) + + +@router.get("/me") +async def get_me(user: CurUsr): + return {"user"} diff --git a/src/core/auth_manager.py b/src/core/auth_manager.py index 310f184..408b532 100644 --- a/src/core/auth_manager.py +++ b/src/core/auth_manager.py @@ -33,3 +33,11 @@ class AuthManager: algorithm=settings.access_token.algorithm, ) return encoded_jwt + + @classmethod + def decode_access_token(cls, token: str) -> dict: + return jwt.decode( + token, + settings.access_token.secret_key, + algorithms=[settings.access_token.algorithm], + ) diff --git a/src/core/settings.py b/src/core/settings.py index 9944291..c27c294 100644 --- a/src/core/settings.py +++ b/src/core/settings.py @@ -12,11 +12,19 @@ class ApiV1Prefix(BaseModel): auth: str = "/auth" users: str = "/users" + @property + def login_url(self) -> str: + return f"{self.prefix}{self.auth}" + class ApiPrefix(BaseModel): prefix: str = "/api" v1: ApiV1Prefix = ApiV1Prefix() + @property + def v1_login_url(self) -> str: + return f"{self.prefix}{self.v1.login_url}" + class DbSettings(BaseModel): url: str = f"sqlite+aiosqlite:///{DB_PATH}" diff --git a/src/schemas/auth.py b/src/schemas/auth.py index 3fded6a..eab7a8b 100644 --- a/src/schemas/auth.py +++ b/src/schemas/auth.py @@ -4,3 +4,8 @@ from pydantic import BaseModel class Token(BaseModel): access_token: str token_type: str + + +class TokenData(BaseModel): + sub: str | None = None + is_active: bool diff --git a/src/services/auth.py b/src/services/auth.py index 6c0b719..0a09ccc 100644 --- a/src/services/auth.py +++ b/src/services/auth.py @@ -34,5 +34,7 @@ class AuthService(BaseService): status_code=401, detail="Incorrect username or password", ) - access_token = AuthManager.create_access_token(data={"sub": user.username}) + access_token = AuthManager.create_access_token( + data={"sub": user.username, "is_active": user.is_active} + ) return Token(access_token=access_token, token_type="bearer")