From 87f69be5481a8c35c02e13e0df0b9b614b4d093e Mon Sep 17 00:00:00 2001 From: andrei Date: Fri, 4 Oct 2024 19:26:11 +0500 Subject: [PATCH] ._. --- app/core/usecases/auth_service.py | 50 +++++++++++++++++++ .../database/repository/user_repository.py | 3 ++ app/infrastructure/fastapi/user_routes.py | 21 +++++++- 3 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 app/core/usecases/auth_service.py diff --git a/app/core/usecases/auth_service.py b/app/core/usecases/auth_service.py new file mode 100644 index 0000000..765376c --- /dev/null +++ b/app/core/usecases/auth_service.py @@ -0,0 +1,50 @@ +from datetime import datetime, timedelta, timezone +from typing import Optional +from fastapi import Depends, HTTPException +from fastapi.security import OAuth2PasswordBearer +import jwt +from sqlalchemy.orm import Session +from dotenv import load_dotenv +import os + +from app.infrastructure.database.dependencies import get_db +from app.infrastructure.database.repository.user_repository import UsersRepository + +load_dotenv() + +SECRET_KEY = os.getenv("SECRET_KEY") +ALGORITHM = "HS256" +ACCESS_TOKEN_EXPIRE_MINUTES = 30 + +oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") + +def create_access_token(data: dict, expires_delta: Optional[timedelta] = None): + to_encode = data.copy() + if expires_delta: + expire = datetime.now(timezone.utc) + expires_delta + else: + expire = datetime.now(timezone.utc) + timedelta(minutes=15) + to_encode.update({"exp": expire}) + return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) + +def verify_token(token: str, db: Session = Depends(get_db)): + credentials_exception = HTTPException( + status_code=401, + detail="Could not validate credentials", + headers={"WWW-Authenticate": "Bearer"}, + ) + try: + payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) + user_id: str = payload.get("sub") + if user_id is None: + raise credentials_exception + + user_repo = UsersRepository(db) + user = user_repo.get_by_id( + int(user_id) + ) + if user is None: + raise credentials_exception + return user + except jwt.PyJWTError: # Обрабатываем исключения от PyJWT + raise credentials_exception diff --git a/app/infrastructure/database/repository/user_repository.py b/app/infrastructure/database/repository/user_repository.py index f35c134..72ef013 100644 --- a/app/infrastructure/database/repository/user_repository.py +++ b/app/infrastructure/database/repository/user_repository.py @@ -12,6 +12,9 @@ class UsersRepository: def get_by_id(self, user_id: int): return self.db.query(User).filter(User.id == user_id).first() + def get_by_login(self, user_login: str): + return self.db.query(User).filter(User.login == user_login).first() + def create(self, user: User): self.db.add(user) self.db.commit() diff --git a/app/infrastructure/fastapi/user_routes.py b/app/infrastructure/fastapi/user_routes.py index ca42ece..20f4b05 100644 --- a/app/infrastructure/fastapi/user_routes.py +++ b/app/infrastructure/fastapi/user_routes.py @@ -1,11 +1,15 @@ from typing import List -from fastapi import APIRouter, HTTPException, Depends +from fastapi import APIRouter, Depends +from fastapi import HTTPException +from fastapi.security import OAuth2PasswordRequestForm from sqlalchemy.orm import Session -from app.infrastructure.database.dependencies import get_db from app.core.entities.user import UserEntity +from app.core.usecases.auth_service import create_access_token from app.core.usecases.user_service import UsersService +from app.infrastructure.database.dependencies import get_db +from app.infrastructure.database.repository.user_repository import UsersRepository router = APIRouter() @@ -47,3 +51,16 @@ def delete_user(user_id: int, db: Session = Depends(get_db)): if not success: raise HTTPException(status_code=404, detail="User not found") return success + + +@router.post("/token") +def login(form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)): + user_repo = UsersRepository(db) + user = user_repo.get_by_login( + form_data.username + ) + + if not user or user.password != form_data.password: + raise HTTPException(status_code=400, detail="Incorrect username or password") + access_token = create_access_token(data={"sub": user.id}) + return {"access_token": access_token, "token_type": "bearer"}