From 3ec27706dfc01f6a3089666635b487a8e694e27c Mon Sep 17 00:00:00 2001 From: Andrei Duvakin Date: Wed, 5 Feb 2025 13:04:38 +0500 Subject: [PATCH] =?UTF-8?q?=D1=81=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20=D0=B3?= =?UTF-8?q?=D0=B5=D0=BD=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D1=8E=20jwt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/app/application/users_repository.py | 33 +++++++++++++++++++++++++ api/app/database/session.py | 2 ++ api/app/domain/models/users.py | 7 ++++++ api/app/infrastructure/auth_service.py | 14 +++++++++++ api/app/settings.py | 6 +++++ api/req.txt | 23 +++++++++++++++++ 6 files changed, 85 insertions(+) create mode 100644 api/app/application/users_repository.py create mode 100644 api/app/infrastructure/auth_service.py create mode 100644 api/req.txt diff --git a/api/app/application/users_repository.py b/api/app/application/users_repository.py new file mode 100644 index 0000000..2357e85 --- /dev/null +++ b/api/app/application/users_repository.py @@ -0,0 +1,33 @@ +from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy.orm import joinedload + +from app.domain.models.users import User + + +class UsersRepository: + def __init__(self, db: AsyncSession): + self.db = db + + def get_all(self): + return self.db.query(User).all() + + 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) + .options( + joinedload(User.role) + ) + .first() + ) + + def create(self, user: User): + self.db.add(user) + self.db.commit() + self.db.refresh(user) + + return user diff --git a/api/app/database/session.py b/api/app/database/session.py index e700b1f..7e0a76e 100644 --- a/api/app/database/session.py +++ b/api/app/database/session.py @@ -1,5 +1,6 @@ from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine from sqlalchemy.orm import sessionmaker + from app.settings import settings engine = create_async_engine(settings.DATABASE_URL, echo=True) @@ -8,6 +9,7 @@ async_session_maker = sessionmaker( bind=engine, class_=AsyncSession, expire_on_commit=False ) + async def get_db(): async with async_session_maker() as session: yield session diff --git a/api/app/domain/models/users.py b/api/app/domain/models/users.py index 050144f..3de7d14 100644 --- a/api/app/domain/models/users.py +++ b/api/app/domain/models/users.py @@ -1,5 +1,6 @@ from sqlalchemy import Column, Integer, VARCHAR, ForeignKey, String from sqlalchemy.orm import relationship +from werkzeug.security import check_password_hash, generate_password_hash from app.domain.models import Base @@ -21,3 +22,9 @@ class User(Base): lens_issues = relationship('LensIssue', back_populates='doctor') appointments = relationship('Appointment', back_populates='doctor') mailing = relationship('Mailing', back_populates='user') + + def check_password(self, password): + return check_password_hash(self.password, password) + + def set_password(self, password): + self.password = generate_password_hash(password) diff --git a/api/app/infrastructure/auth_service.py b/api/app/infrastructure/auth_service.py new file mode 100644 index 0000000..9ff5c60 --- /dev/null +++ b/api/app/infrastructure/auth_service.py @@ -0,0 +1,14 @@ +import datetime + +from jose import jwt + +from app.settings import get_auth_data + + +def create_access_token(data: dict) -> str: + to_encode = data.copy() + expire = datetime.now(datetime.timezone.utc) + datetime.timedelta(days=30) + to_encode.update({"exp": expire}) + auth_data = get_auth_data() + encode_jwt = jwt.encode(to_encode, auth_data['secret_key'], algorithm=auth_data['algorithm']) + return encode_jwt diff --git a/api/app/settings.py b/api/app/settings.py index 4850313..80a1638 100644 --- a/api/app/settings.py +++ b/api/app/settings.py @@ -5,6 +5,8 @@ class Settings(BaseSettings): DATABASE_URL: str LOG_LEVEL: str = "info" LOG_FILE: str = "logs/app.log" + SECRET_KEY: str + ALGORITHM: str class Config: env_file = ".env" @@ -12,3 +14,7 @@ class Settings(BaseSettings): settings = Settings() + + +def get_auth_data(): + return {"secret_key": settings.SECRET_KEY, "algorithm": settings.ALGORITHM} diff --git a/api/req.txt b/api/req.txt new file mode 100644 index 0000000..992aa49 --- /dev/null +++ b/api/req.txt @@ -0,0 +1,23 @@ +alembic==1.14.1 +annotated-types==0.7.0 +anyio==4.8.0 +asyncpg==0.30.0 +click==8.1.8 +fastapi==0.115.8 +greenlet==3.1.1 +h11==0.14.0 +idna==3.10 +Mako==1.3.8 +MarkupSafe==3.0.2 +psycopg==3.2.4 +psycopg-binary==3.2.4 +pydantic==2.10.6 +pydantic-settings==2.7.1 +pydantic_core==2.27.2 +python-dotenv==1.0.1 +sniffio==1.3.1 +SQLAlchemy==2.0.37 +starlette==0.45.3 +typing_extensions==4.12.2 +uvicorn==0.34.0 +Werkzeug==3.1.3