diff --git a/api/app/application/users_repository.py b/api/app/application/users_repository.py index 9e89360..fb294b5 100644 --- a/api/app/application/users_repository.py +++ b/api/app/application/users_repository.py @@ -1,3 +1,5 @@ +from typing import Optional + from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.future import select from sqlalchemy.orm import joinedload @@ -14,12 +16,12 @@ class UsersRepository: result = await self.db.execute(stmt) return result.scalars().all() - async def get_by_id(self, user_id: int): + async def get_by_id(self, user_id: int) -> Optional[User]: stmt = select(User).filter(User.id == user_id) result = await self.db.execute(stmt) return result.scalars().first() - async def get_by_login(self, user_login: str): + async def get_by_login(self, user_login: str) -> Optional[User]: stmt = ( select(User) .filter(User.login == user_login) diff --git a/api/app/controllers/auth_routes.py b/api/app/controllers/auth_routes.py index be33d8b..19c7e98 100644 --- a/api/app/controllers/auth_routes.py +++ b/api/app/controllers/auth_routes.py @@ -1,8 +1,9 @@ -from fastapi import APIRouter, Depends, HTTPException, Response, status +from fastapi import APIRouter, Depends, HTTPException, Response from sqlalchemy.ext.asyncio import AsyncSession from app.database.session import get_db from app.domain.entities.auth import AuthEntity +from app.domain.entities.token_entity import TokenEntity from app.infrastructure.auth_service import AuthService router = APIRouter() @@ -10,7 +11,7 @@ router = APIRouter() @router.post( "/login/", - response_model=dict, + response_model=TokenEntity, responses={401: {"description": "Invalid username or password"}}, summary="User authentication", description="Logs in the user and outputs the `access_token` in the `cookie'", @@ -22,23 +23,19 @@ async def auth_user( ): auth_service = AuthService(db) - check = await auth_service.authenticate_user( - login=user_data.login, password=user_data.password - ) + token = await auth_service.authenticate_user(user_data.login, user_data.password) - if check is None: + if token is None: raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Invalid username or password", + status_code=401, + detail="Incorrect username or password" ) - access_token = auth_service.create_access_token({"sub": str(check.id)}) - response.set_cookie( key="users_access_token", - value=access_token, + value=token["access_token"], httponly=True, samesite="Lax", ) - return {"access_token": access_token, "refresh_token": None} + return token diff --git a/api/app/controllers/register_routes.py b/api/app/controllers/register_routes.py index 7fdb5d8..7d57b19 100644 --- a/api/app/controllers/register_routes.py +++ b/api/app/controllers/register_routes.py @@ -1,10 +1,9 @@ -from fastapi import APIRouter, Depends, HTTPException, Response, status +from fastapi import APIRouter, Depends from sqlalchemy.ext.asyncio import AsyncSession from app.database.session import get_db from app.domain.entities.register import RegisterEntity -from app.infrastructure.auth_service import AuthService -from app.infrastructure.user_service import UserService +from app.infrastructure.users_service import UsersService router = APIRouter() @@ -19,6 +18,6 @@ async def register_user( user_data: RegisterEntity, db: AsyncSession = Depends(get_db) ): - user_service = UserService(db) + user_service = UsersService(db) user = await user_service.register_user(user_data) return user.model_dump() diff --git a/api/app/domain/entities/token_entity.py b/api/app/domain/entities/token_entity.py new file mode 100644 index 0000000..cc190c0 --- /dev/null +++ b/api/app/domain/entities/token_entity.py @@ -0,0 +1,11 @@ +from typing import Optional + +from pydantic import BaseModel + + +class TokenEntity(BaseModel): + access_token: str + user_id: int + + class Config: + from_attributes = True diff --git a/api/app/infrastructure/auth_service.py b/api/app/infrastructure/auth_service.py index 3acd40a..bd48193 100644 --- a/api/app/infrastructure/auth_service.py +++ b/api/app/infrastructure/auth_service.py @@ -1,4 +1,5 @@ import datetime +from typing import Optional import jwt from sqlalchemy.ext.asyncio import AsyncSession @@ -9,18 +10,18 @@ from app.settings import get_auth_data class AuthService: def __init__(self, db: AsyncSession): - self.user_repository = UsersRepository(db) + self.users_repository = UsersRepository(db) - async def authenticate_user(self, login: str, password: str): - user = await self.user_repository.get_by_login(login) + async def authenticate_user(self, login: str, password: str) -> Optional[dict]: + user = await self.users_repository.get_by_login(login) + if user and user.check_password(password): + access_token = self.create_access_token({"user_id": user.id}) + return { + "access_token": access_token, + "user_id": user.id + } - if not user: - return None - - if not user.check_password(password): - return None - - return user + return None @staticmethod def create_access_token(data: dict) -> str: diff --git a/api/app/infrastructure/patient_service.py b/api/app/infrastructure/patients_service.py similarity index 99% rename from api/app/infrastructure/patient_service.py rename to api/app/infrastructure/patients_service.py index 886fa91..78bd84b 100644 --- a/api/app/infrastructure/patient_service.py +++ b/api/app/infrastructure/patients_service.py @@ -7,7 +7,7 @@ from app.domain.entities.patient import PatientEntity from app.domain.models import Patient -class PatientService: +class PatientsService: def __init__(self, db: AsyncSession): self.patient_repository = PatientsRepository(db) diff --git a/api/app/infrastructure/user_service.py b/api/app/infrastructure/users_service.py similarity index 99% rename from api/app/infrastructure/user_service.py rename to api/app/infrastructure/users_service.py index 8f991de..0bd1fda 100644 --- a/api/app/infrastructure/user_service.py +++ b/api/app/infrastructure/users_service.py @@ -10,7 +10,7 @@ from app.domain.entities.user import UserEntity from app.domain.models import User -class UserService: +class UsersService: def __init__(self, db: AsyncSession): self.user_repository = UsersRepository(db) self.role_repository = RolesRepository(db) diff --git a/api/app/main.py b/api/app/main.py index 3d8bd08..76b9283 100644 --- a/api/app/main.py +++ b/api/app/main.py @@ -17,8 +17,8 @@ def start_app(): allow_headers=['*'], ) - api_app.include_router(auth_router, prefix=settings.APP_PREFIX) - api_app.include_router(register_router, prefix=settings.APP_PREFIX) + api_app.include_router(auth_router, prefix=settings.APP_PREFIX, tags=['auth']) + api_app.include_router(register_router, prefix=settings.APP_PREFIX, tags=['register']) return api_app @@ -26,6 +26,6 @@ def start_app(): app = start_app() -@app.get("/") +@app.get("/", tags=['root']) async def root(): return {"message": "OK"}