diff --git a/src/api/v1/auth.py b/src/api/v1/auth.py index 18a92ac..4aa181d 100644 --- a/src/api/v1/auth.py +++ b/src/api/v1/auth.py @@ -19,7 +19,10 @@ async def registration(session: sessionDep, credential: UserRequestADD): @router.post(path="/login") async def login( - session: sessionDep, - credential: Annotated[OAuth2PasswordRequestForm, Depends()], - ): - user = AuthService(session).login(credential.username, credential.password) + session: sessionDep, + credential: Annotated[OAuth2PasswordRequestForm, Depends()], +): + access_token = await AuthService(session).login( + credential.username, credential.password + ) + return access_token diff --git a/src/core/auth_manager.py b/src/core/auth_manager.py index 45fe5c2..310f184 100644 --- a/src/core/auth_manager.py +++ b/src/core/auth_manager.py @@ -6,7 +6,7 @@ from passlib.context import CryptContext from src.core.settings import settings -class AuthManger: +class AuthManager: pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") @classmethod diff --git a/src/repository/base.py b/src/repository/base.py index cd1d2cb..6ec7c9c 100644 --- a/src/repository/base.py +++ b/src/repository/base.py @@ -1,5 +1,5 @@ from pydantic import BaseModel -from sqlalchemy import insert +from sqlalchemy import insert, select from src.core.database import Base @@ -15,3 +15,9 @@ class BaseRepo: result = await self.session.execute(statement) obj = result.scalar_one() return obj + + async def get_one_or_none(self, **filter_by): + query = select(self.model).filter_by(**filter_by) + result = await self.session.execute(query) + model = result.scalars().one_or_none() + return model diff --git a/src/schemas/auth.py b/src/schemas/auth.py new file mode 100644 index 0000000..3fded6a --- /dev/null +++ b/src/schemas/auth.py @@ -0,0 +1,6 @@ +from pydantic import BaseModel + + +class Token(BaseModel): + access_token: str + token_type: str diff --git a/src/services/auth.py b/src/services/auth.py index 7a51697..c726333 100644 --- a/src/services/auth.py +++ b/src/services/auth.py @@ -1,11 +1,14 @@ -from src.schemas.users import UserRequestADD, User, UserAdd +from fastapi import HTTPException + +from src.schemas.auth import Token +from src.schemas.users import UserRequestADD, User, UserAdd, UserWithHashedPass from src.services.base import BaseService -from src.core.auth_manager import AuthManger +from src.core.auth_manager import AuthManager class AuthService(BaseService): async def registration(self, cred: UserRequestADD) -> User: - hashed_pass = AuthManger.get_password_hash(cred.password) + hashed_pass = AuthManager.get_password_hash(cred.password) user_to_insert = UserAdd( username=cred.username, email=cred.email, @@ -18,4 +21,20 @@ class AuthService(BaseService): return User.model_validate(result) async def login(self, username: str, password: str): - ... + result = await self.session.user.get_one_or_none(username=username) + if result is None: + raise HTTPException( + status_code=401, + detail="Incorrect username or password", + ) + user = UserWithHashedPass.model_validate(result) + verify = AuthManager.verify_password( + plain_password=password, hashed_password=user.hashed_password + ) + if not verify: + raise HTTPException( + status_code=401, + detail="Incorrect username or password", + ) + access_token = AuthManager.create_access_token(data={"sub": user.username}) + return Token(access_token=access_token, token_type="bearer")