diff --git a/.env_template b/.env_template index b8c1698..012887d 100644 --- a/.env_template +++ b/.env_template @@ -1,7 +1,7 @@ -DB_USER= -DB_PASS= DB_HOST= DB_PORT= +DB_USER= +DB_PASS= DB_NAME= SECRET_KEY= diff --git a/app/config.py b/app/config.py index 462520e..97cd937 100644 --- a/app/config.py +++ b/app/config.py @@ -1,4 +1,4 @@ -from pydantic import BaseSettings +from pydantic_settings import BaseSettings class Settings(BaseSettings): diff --git a/app/migrations/env.py b/app/migrations/env.py index 5ebf977..d4df8d2 100644 --- a/app/migrations/env.py +++ b/app/migrations/env.py @@ -7,7 +7,7 @@ from alembic import context from app.database import DATABASE_URL, Base from app.users.models import Users # noqa -from app.users.chat.models import Chats # noqa +from app.users.chat.models import Chats, Messages, UsersXChats # noqa # this is the Alembic Config object, which provides # access to the values within the .ini file in use. diff --git a/app/migrations/versions/050324c9bd94_изменение_models_py.py b/app/migrations/versions/050324c9bd94_изменение_models_py.py new file mode 100644 index 0000000..12deb5e --- /dev/null +++ b/app/migrations/versions/050324c9bd94_изменение_models_py.py @@ -0,0 +1,52 @@ +"""Изменение models.py + +Revision ID: 050324c9bd94 +Revises: 6b866e6065f2 +Create Date: 2024-01-31 16:51:52.969424 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision: str = '050324c9bd94' +down_revision: Union[str, None] = '6b866e6065f2' +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.alter_column('chats', 'chat', + existing_type=postgresql.JSON(astext_type=sa.Text()), + type_=postgresql.JSONB(astext_type=sa.Text()), + existing_nullable=True) + op.alter_column('chats', 'allowed_users', + existing_type=postgresql.JSON(astext_type=sa.Text()), + type_=postgresql.JSONB(astext_type=sa.Text()), + existing_nullable=True) + op.alter_column('chats', 'pinned_messages', + existing_type=postgresql.JSON(astext_type=sa.Text()), + type_=postgresql.JSONB(astext_type=sa.Text()), + existing_nullable=True) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('chats', 'pinned_messages', + existing_type=postgresql.JSONB(astext_type=sa.Text()), + type_=postgresql.JSON(astext_type=sa.Text()), + existing_nullable=True) + op.alter_column('chats', 'allowed_users', + existing_type=postgresql.JSONB(astext_type=sa.Text()), + type_=postgresql.JSON(astext_type=sa.Text()), + existing_nullable=True) + op.alter_column('chats', 'chat', + existing_type=postgresql.JSONB(astext_type=sa.Text()), + type_=postgresql.JSON(astext_type=sa.Text()), + existing_nullable=True) + # ### end Alembic commands ### diff --git a/app/migrations/versions/0cc334a2f727_изменение_models_py.py b/app/migrations/versions/0cc334a2f727_изменение_models_py.py new file mode 100644 index 0000000..917ab1a --- /dev/null +++ b/app/migrations/versions/0cc334a2f727_изменение_models_py.py @@ -0,0 +1,44 @@ +"""Изменение models.py + +Revision ID: 0cc334a2f727 +Revises: f34f22694e19 +Create Date: 2024-01-31 17:55:10.929751 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '0cc334a2f727' +down_revision: Union[str, None] = 'f34f22694e19' +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.alter_column('messages', 'chat_id', + existing_type=sa.INTEGER(), + nullable=True) + op.alter_column('messages', 'user_id', + existing_type=sa.INTEGER(), + nullable=True) + op.create_foreign_key(None, 'messages', 'chats', ['chat_id'], ['id']) + op.create_foreign_key(None, 'messages', 'users', ['user_id'], ['id']) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'messages', type_='foreignkey') + op.drop_constraint(None, 'messages', type_='foreignkey') + op.alter_column('messages', 'user_id', + existing_type=sa.INTEGER(), + nullable=False) + op.alter_column('messages', 'chat_id', + existing_type=sa.INTEGER(), + nullable=False) + # ### end Alembic commands ### diff --git a/app/migrations/versions/23d9de31839c_изменение_models_py.py b/app/migrations/versions/23d9de31839c_изменение_models_py.py new file mode 100644 index 0000000..cd8ebee --- /dev/null +++ b/app/migrations/versions/23d9de31839c_изменение_models_py.py @@ -0,0 +1,38 @@ +"""Изменение models.py + +Revision ID: 23d9de31839c +Revises: 3eb642de804e +Create Date: 2024-01-31 16:10:56.198957 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '23d9de31839c' +down_revision: Union[str, None] = '3eb642de804e' +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.add_column('chats', sa.Column('pinned_messages', sa.JSON(), nullable=True)) + op.alter_column('users', 'black_phoenix', + existing_type=sa.INTEGER(), + type_=sa.String(), + existing_nullable=False) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('users', 'black_phoenix', + existing_type=sa.String(), + type_=sa.INTEGER(), + existing_nullable=False) + op.drop_column('chats', 'pinned_messages') + # ### end Alembic commands ### diff --git a/app/migrations/versions/273e18fa9316_изменение_models_py.py b/app/migrations/versions/273e18fa9316_изменение_models_py.py new file mode 100644 index 0000000..304b0af --- /dev/null +++ b/app/migrations/versions/273e18fa9316_изменение_models_py.py @@ -0,0 +1,45 @@ +"""Изменение models.py + +Revision ID: 273e18fa9316 +Revises: 050324c9bd94 +Create Date: 2024-01-31 17:44:10.087705 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision: str = '273e18fa9316' +down_revision: Union[str, None] = '050324c9bd94' +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('messages', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('chat_id', sa.Integer(), nullable=False, foreign_key='chats.id'), + sa.Column('user_id', sa.Integer(), nullable=False, foreign_key='users.id'), + sa.Column('text', sa.String(), nullable=False), + sa.Column('image_url', sa.String(), nullable=True), + sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False), + sa.Column('visibility', sa.Boolean(), server_default='true', nullable=False), + sa.PrimaryKeyConstraint('id') + ) + op.drop_column('chats', 'pinned_messages') + op.drop_column('chats', 'allowed_users') + op.drop_column('chats', 'chat') + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('chats', sa.Column('chat', postgresql.JSONB(astext_type=sa.Text()), autoincrement=False, nullable=True)) + op.add_column('chats', sa.Column('allowed_users', postgresql.JSONB(astext_type=sa.Text()), autoincrement=False, nullable=True)) + op.add_column('chats', sa.Column('pinned_messages', postgresql.JSONB(astext_type=sa.Text()), autoincrement=False, nullable=True)) + op.drop_table('messages') + # ### end Alembic commands ### diff --git a/app/migrations/versions/3ed46f38168f_изменение_models_py.py b/app/migrations/versions/3ed46f38168f_изменение_models_py.py new file mode 100644 index 0000000..fe1a7e5 --- /dev/null +++ b/app/migrations/versions/3ed46f38168f_изменение_models_py.py @@ -0,0 +1,38 @@ +"""Изменение models.py + +Revision ID: 3ed46f38168f +Revises: 0cc334a2f727 +Create Date: 2024-01-31 17:59:24.302274 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision: str = '3ed46f38168f' +down_revision: Union[str, None] = '0cc334a2f727' +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.alter_column('messages', 'created_at', + existing_type=postgresql.TIMESTAMP(), + type_=sa.DateTime(timezone=True), + existing_nullable=False, + existing_server_default=sa.text('now()')) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('messages', 'created_at', + existing_type=sa.DateTime(timezone=True), + type_=postgresql.TIMESTAMP(), + existing_nullable=False, + existing_server_default=sa.text('now()')) + # ### end Alembic commands ### diff --git a/app/migrations/versions/6b866e6065f2_изменение_models_py.py b/app/migrations/versions/6b866e6065f2_изменение_models_py.py new file mode 100644 index 0000000..7c5a995 --- /dev/null +++ b/app/migrations/versions/6b866e6065f2_изменение_models_py.py @@ -0,0 +1,30 @@ +"""Изменение models.py + +Revision ID: 6b866e6065f2 +Revises: 8422962a574b +Create Date: 2024-01-31 16:50:40.170909 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '6b866e6065f2' +down_revision: Union[str, None] = '8422962a574b' +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 ### diff --git a/app/migrations/versions/8422962a574b_изменение_models_py.py b/app/migrations/versions/8422962a574b_изменение_models_py.py new file mode 100644 index 0000000..9144384 --- /dev/null +++ b/app/migrations/versions/8422962a574b_изменение_models_py.py @@ -0,0 +1,30 @@ +"""Изменение models.py + +Revision ID: 8422962a574b +Revises: 23d9de31839c +Create Date: 2024-01-31 16:31:00.680946 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '8422962a574b' +down_revision: Union[str, None] = '23d9de31839c' +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 ### diff --git a/app/migrations/versions/ad488d81e7b5_изменение_models_py.py b/app/migrations/versions/ad488d81e7b5_изменение_models_py.py new file mode 100644 index 0000000..b456b9a --- /dev/null +++ b/app/migrations/versions/ad488d81e7b5_изменение_models_py.py @@ -0,0 +1,37 @@ +"""Изменение models.py + +Revision ID: ad488d81e7b5 +Revises: 3ed46f38168f +Create Date: 2024-01-31 19:11:16.016911 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'ad488d81e7b5' +down_revision: Union[str, None] = '3ed46f38168f' +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('usersxchats', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('user_id', sa.Integer(), nullable=True), + sa.Column('chat_id', sa.Integer(), nullable=True), + sa.ForeignKeyConstraint(['chat_id'], ['chats.id'], ), + sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('usersxchats') + # ### end Alembic commands ### diff --git a/app/migrations/versions/f34f22694e19_изменение_models_py.py b/app/migrations/versions/f34f22694e19_изменение_models_py.py new file mode 100644 index 0000000..d2d7f23 --- /dev/null +++ b/app/migrations/versions/f34f22694e19_изменение_models_py.py @@ -0,0 +1,30 @@ +"""Изменение models.py + +Revision ID: f34f22694e19 +Revises: 273e18fa9316 +Create Date: 2024-01-31 17:53:48.531617 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'f34f22694e19' +down_revision: Union[str, None] = '273e18fa9316' +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 ### diff --git a/app/users/chat/models.py b/app/users/chat/models.py index eaf29ed..993342f 100644 --- a/app/users/chat/models.py +++ b/app/users/chat/models.py @@ -1,5 +1,8 @@ -from sqlalchemy import Column, Integer, JSON +from datetime import datetime +from typing import Optional +from sqlalchemy import func, ForeignKey, DateTime +from sqlalchemy.orm import mapped_column, Mapped, relationship from app.database import Base @@ -7,9 +10,42 @@ from app.database import Base class Chats(Base): __tablename__ = "chats" - id = Column(Integer, primary_key=True) - chat = Column(JSON) - allowed_users = Column(JSON) + id: Mapped[int] = mapped_column(primary_key=True) + + message = relationship("Messages", back_populates="chat") + usersxchats = relationship("UsersXChats", back_populates="chat") def __str__(self): - return f"Чат #{self.id} с {self.allowed_users}." + return f"Чат #{self.id}." + + +class Messages(Base): + __tablename__ = "messages" + + id: Mapped[int] = mapped_column(primary_key=True) + chat_id = mapped_column(ForeignKey("chats.id")) + user_id = mapped_column(ForeignKey("users.id")) + text: Mapped[str] + image_url: Mapped[Optional[str]] + created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) + visibility: Mapped[bool] = mapped_column(server_default='true') + + chat = relationship("Chats", back_populates="message") + user = relationship("Users", back_populates="message") + + def __str__(self): + return f"#{self.id} {self.text} от {self.user_id}. Написано {self.created_at}" + + +class UsersXChats(Base): + __tablename__ = "usersxchats" + + id: Mapped[int] = mapped_column(primary_key=True) + user_id = mapped_column(ForeignKey("users.id")) + chat_id = mapped_column(ForeignKey("chats.id")) + + chat = relationship("Chats", back_populates="usersxchats") + user = relationship("Users", back_populates="usersxchats") + + def __str__(self): + return f"Юзер #{self.user_id} допущен к чату {self.chat_id}" diff --git a/app/users/models.py b/app/users/models.py index 276b96f..3547613 100644 --- a/app/users/models.py +++ b/app/users/models.py @@ -1,4 +1,7 @@ -from sqlalchemy import Column, Integer, String, Date +from datetime import date +from typing import Optional + +from sqlalchemy.orm import mapped_column, Mapped, relationship from app.database import Base @@ -6,14 +9,17 @@ from app.database import Base class Users(Base): __tablename__ = "users" - id = Column(Integer, primary_key=True) - email = Column(String, nullable=False) - username = Column(String, nullable=False) - hashed_password = Column(String, nullable=False) - role = Column(Integer, nullable=False) - black_phoenix = Column(Integer, nullable=False) - avatar_image = Column(String) - date_of_birth = Column(Date, nullable=False) + id: Mapped[int] = mapped_column(primary_key=True) + email: Mapped[str] + username: Mapped[str] + hashed_password: Mapped[str] + role: Mapped[int] + black_phoenix: Mapped[str] + avatar_image: Mapped[Optional[str]] + date_of_birth: Mapped[date] + + message = relationship("Messages", back_populates="user") + usersxchats = relationship("UsersXChats", back_populates="user") def __str__(self): return f"Юзер {self.username}" diff --git a/app/users/schemas.py b/app/users/schemas.py index a129345..5a1c323 100644 --- a/app/users/schemas.py +++ b/app/users/schemas.py @@ -8,7 +8,7 @@ class SUserLogin(BaseModel): password: str class Config: - orm_mode = True + from_attributes = True class SUserRegister(BaseModel): @@ -18,5 +18,5 @@ class SUserRegister(BaseModel): date_of_birth: date class Config: - orm_mode = True + from_attributes = True diff --git a/requirements.txt b/requirements.txt index ed6d0e9..df1a71c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -60,8 +60,10 @@ prometheus-fastapi-instrumentator==6.1.0 prompt-toolkit==3.0.43 pyasn1==0.5.1 pycodestyle==2.11.1 -pydantic==1.10.14 -pydantic_core==2.14.6 +pydantic==2.6.0 +pydantic-extra-types==2.5.0 +pydantic-settings==2.1.0 +pydantic_core==2.16.1 pyflakes==3.2.0 pyright==1.1.347 pytest==7.4.4