применил миграцию

This commit is contained in:
Андрей Дувакин 2025-02-06 20:17:59 +05:00
parent 3ec27706df
commit c7e6663b6a
12 changed files with 278 additions and 47 deletions

View File

@ -0,0 +1,27 @@
from fastapi import APIRouter, Depends, HTTPException
from fastapi.openapi.models import Response
from sqlalchemy.ext.asyncio import AsyncSession
from starlette import status
from app.database.session import get_db
from app.domain.entities.auth import AuthEntity
from app.infrastructure.auth_service import AuthService
router = APIRouter()
@router.post('/login/')
async def auth_user(response: Response, user_data: AuthEntity, db: AsyncSession = Depends(get_db)):
auth_service = AuthService(db)
check = await auth_service.authenticate_user(login=user_data.login, password=user_data.password)
if check is None:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail='Неверный логин или пароль',
)
access_token = auth_service.create_access_token({"sub": str(check.id)})
response.set_cookie(key="users_access_token", value=access_token, httponly=True)
return {'access_token': access_token, 'refresh_token': None}

View File

@ -1,10 +1,9 @@
from logging.config import fileConfig from logging.config import fileConfig
import sqlalchemy
from alembic import context from alembic import context
from sqlalchemy import pool from sqlalchemy import pool
from sqlalchemy.ext.asyncio import AsyncEngine from sqlalchemy.ext.asyncio import create_async_engine
from app.domain.models import Base from app.domain.models import Base
from app.settings import settings from app.settings import settings
@ -21,9 +20,8 @@ def get_url():
async def run_migrations_online(): async def run_migrations_online():
connectable = AsyncEngine( connectable = create_async_engine(get_url(), poolclass=pool.NullPool, future=True)
sqlalchemy.create_engine(get_url(), poolclass=pool.NullPool, future=True)
)
async with connectable.connect() as connection: async with connectable.connect() as connection:
await connection.run_sync(do_run_migrations) await connection.run_sync(do_run_migrations)

View File

@ -1,30 +0,0 @@
"""initial migration
Revision ID: dde27a957087
Revises:
Create Date: 2025-02-04 13:46:46.958839
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision: str = 'dde27a957087'
down_revision: Union[str, None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
pass
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
pass
# ### end Alembic commands ###

View File

@ -0,0 +1,177 @@
"""Initial migrationA
Revision ID: f8f3f414b162
Revises:
Create Date: 2025-02-06 20:16:16.961555
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision: str = 'f8f3f414b162'
down_revision: Union[str, None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('appointment_types',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('title', sa.VARCHAR(length=150), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('title')
)
op.create_table('lenses_types',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('title', sa.VARCHAR(length=150), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('title')
)
op.create_table('mailing_delivery_methods',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('title', sa.VARCHAR(length=200), nullable=False),
sa.PrimaryKeyConstraint('id')
)
op.create_table('patients',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('first_name', sa.VARCHAR(length=200), nullable=False),
sa.Column('last_name', sa.VARCHAR(length=200), nullable=False),
sa.Column('patronymic', sa.VARCHAR(length=200), nullable=True),
sa.Column('birthday', sa.Date(), nullable=False),
sa.Column('address', sa.String(), nullable=True),
sa.Column('email', sa.VARCHAR(length=350), nullable=True),
sa.Column('phone', sa.VARCHAR(length=25), nullable=True),
sa.Column('diagnosis', sa.String(), nullable=True),
sa.Column('correction', sa.String(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_table('roles',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('title', sa.VARCHAR(length=150), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('title')
)
op.create_table('sets',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('title', sa.VARCHAR(length=150), nullable=False),
sa.Column('count', sa.Integer(), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('title')
)
op.create_table('lens',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('tor', sa.Float(), nullable=False),
sa.Column('trial', sa.Float(), nullable=False),
sa.Column('esa', sa.Float(), nullable=False),
sa.Column('fvc', sa.Float(), nullable=False),
sa.Column('preset_refraction', sa.Float(), nullable=False),
sa.Column('diameter', sa.Float(), nullable=False),
sa.Column('periphery_toricity', sa.Float(), nullable=False),
sa.Column('side', sa.Enum('LEFT', 'RIGHT', name='sideenum'), nullable=False),
sa.Column('type_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['type_id'], ['lenses_types.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('users',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('first_name', sa.VARCHAR(length=200), nullable=False),
sa.Column('last_name', sa.VARCHAR(length=200), nullable=False),
sa.Column('patronymic', sa.VARCHAR(length=200), nullable=True),
sa.Column('login', sa.String(), nullable=False),
sa.Column('password', sa.String(), nullable=False),
sa.Column('role_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['role_id'], ['roles.id'], ),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('login')
)
op.create_table('appointments',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('results', sa.String(), nullable=True),
sa.Column('days_until_the_next_appointment', sa.Integer(), nullable=True),
sa.Column('patient_id', sa.Integer(), nullable=False),
sa.Column('doctor_id', sa.Integer(), nullable=False),
sa.Column('type_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['doctor_id'], ['users.id'], ),
sa.ForeignKeyConstraint(['patient_id'], ['patients.id'], ),
sa.ForeignKeyConstraint(['type_id'], ['appointment_types.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('lens_issues',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('issue_date', sa.Date(), nullable=False),
sa.Column('patient_id', sa.Integer(), nullable=False),
sa.Column('doctor_id', sa.Integer(), nullable=False),
sa.Column('lens_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['doctor_id'], ['users.id'], ),
sa.ForeignKeyConstraint(['lens_id'], ['lens.id'], ),
sa.ForeignKeyConstraint(['patient_id'], ['patients.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('mailing',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('text', sa.String(), nullable=False),
sa.Column('title', sa.String(), nullable=False),
sa.Column('datetime', sa.DateTime(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('set_lens',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('set_id', sa.Integer(), nullable=False),
sa.Column('lens_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['lens_id'], ['lens.id'], ),
sa.ForeignKeyConstraint(['set_id'], ['sets.id'], ),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('lens_id')
)
op.create_table('appointment_files',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('file_path', sa.String(), nullable=False),
sa.Column('file_title', sa.String(), nullable=False),
sa.Column('appointment_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['appointment_id'], ['appointments.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('mailing_options',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('option_id', sa.Integer(), nullable=False),
sa.Column('mailing_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['mailing_id'], ['mailing.id'], ),
sa.ForeignKeyConstraint(['option_id'], ['patients.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('recipients',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('patient_id', sa.Integer(), nullable=False),
sa.Column('mailing_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['mailing_id'], ['mailing.id'], ),
sa.ForeignKeyConstraint(['patient_id'], ['mailing_delivery_methods.id'], ),
sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('recipients')
op.drop_table('mailing_options')
op.drop_table('appointment_files')
op.drop_table('set_lens')
op.drop_table('mailing')
op.drop_table('lens_issues')
op.drop_table('appointments')
op.drop_table('users')
op.drop_table('lens')
op.drop_table('sets')
op.drop_table('roles')
op.drop_table('patients')
op.drop_table('mailing_delivery_methods')
op.drop_table('lenses_types')
op.drop_table('appointment_types')
# ### end Alembic commands ###

View File

@ -0,0 +1,6 @@
from pydantic import BaseModel, Field
class AuthEntity(BaseModel):
login: str = Field(...)
password: str = Field(..., min_length=5)

View File

@ -1,3 +1,19 @@
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import declarative_base
Base = declarative_base() Base = declarative_base()
from app.domain.models.appointment_files import AppointmentFile
from app.domain.models.appointments import Appointment
from app.domain.models.appointment_types import AppointmentType
from app.domain.models.lenses_types import LensesType
from app.domain.models.lens_issues import LensIssue
from app.domain.models.lens import Lens
from app.domain.models.mailing_delivery_methods import MailingDeliveryMethod
from app.domain.models.mailing_options import MailingOption
from app.domain.models.mailing import Mailing
from app.domain.models.patients import Patient
from app.domain.models.recipients import Recipient
from app.domain.models.roles import Role
from app.domain.models.set_lens import SetLens
from app.domain.models.sets import Set
from app.domain.models.users import User

View File

@ -11,7 +11,7 @@ class LensIssue(Base):
issue_date = Column(Date, nullable=False) issue_date = Column(Date, nullable=False)
patient_id = Column(Integer, ForeignKey('patients.id'), nullable=False) patient_id = Column(Integer, ForeignKey('patients.id'), nullable=False)
doctor_id = Column(Integer, ForeignKey('user.id'), nullable=False) doctor_id = Column(Integer, ForeignKey('users.id'), nullable=False)
lens_id = Column(Integer, ForeignKey('lens.id'), nullable=False) lens_id = Column(Integer, ForeignKey('lens.id'), nullable=False)
patient = relationship('Patient', back_populates='lens_issues') patient = relationship('Patient', back_populates='lens_issues')

View File

@ -5,7 +5,7 @@ from app.domain.models import Base
class MailingDeliveryMethod(Base): class MailingDeliveryMethod(Base):
__tbalename__ = 'mailing_delivery_methods' __tablename__ = 'mailing_delivery_methods'
id = Column(Integer, primary_key=True, autoincrement=True) id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(VARCHAR(200), nullable=False) title = Column(VARCHAR(200), nullable=False)

View File

@ -5,7 +5,7 @@ from app.domain.models import Base
class Recipient(Base): class Recipient(Base):
__tbalename__ = 'recipients' __tablename__ = 'recipients'
id = Column(Integer, primary_key=True, autoincrement=True) id = Column(Integer, primary_key=True, autoincrement=True)

View File

@ -1,14 +1,33 @@
import datetime import datetime
from jose import jwt from jose import jwt
from sqlalchemy.ext.asyncio import AsyncSession
from app.application.users_repository import UsersRepository
from app.settings import get_auth_data from app.settings import get_auth_data
def create_access_token(data: dict) -> str: class AuthService:
to_encode = data.copy() def __init__(self, db: AsyncSession):
expire = datetime.now(datetime.timezone.utc) + datetime.timedelta(days=30) self.repository = UsersRepository(db)
to_encode.update({"exp": expire})
auth_data = get_auth_data() async def authenticate_user(self, login: str, password: str):
encode_jwt = jwt.encode(to_encode, auth_data['secret_key'], algorithm=auth_data['algorithm']) user = await self.repository.get_by_login(login)
return encode_jwt
if not user:
return None
if not user.check_password(password):
return None
return user
@staticmethod
def create_access_token(data: dict) -> str:
to_encode = data.copy()
expire = datetime.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

View File

@ -0,0 +1,4 @@
from app.run import start_app
if __name__ == '__main__':
start_app()

14
api/app/run.py Normal file
View File

@ -0,0 +1,14 @@
from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware
def start_app():
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=['*'],
allow_credentials=True,
allow_methods=['GET', 'POST', 'PUT', 'DELETE'],
allow_headers=['*'],
)