Рефакторинг

This commit is contained in:
urec56 2025-03-16 12:04:09 +03:00
parent fd03106c74
commit 259a83f337
26 changed files with 149 additions and 106 deletions

View file

@ -3,20 +3,20 @@ from uuid import UUID
from fastapi import APIRouter, Depends, status from fastapi import APIRouter, Depends, status
from app.chat.shemas import ( from app.chat.shemas import (
SMessage, Responses,
SLastMessages, SAllowedChats,
SAllowedChats, SChangeData,
SMessageList, SChatId,
SPinnedChats, SLastMessages,
SPinnedMessages, SMessage,
SChangeData, SMessageList,
SChatId, SPinnedChats,
Responses, SPinnedMessages,
) )
from app.services import chat_service, message_service, auth_service
from app.utils.unit_of_work import UnitOfWork
from app.dependencies import get_verificated_user from app.dependencies import get_verificated_user
from app.services import auth_service, chat_service, message_service
from app.users.schemas import SCreateInvitationLink, SUser from app.users.schemas import SCreateInvitationLink, SUser
from app.utils.unit_of_work import UnitOfWork
router = APIRouter(prefix="/chat", tags=["Чат"]) router = APIRouter(prefix="/chat", tags=["Чат"])

View file

@ -3,17 +3,33 @@ import logging
from collections import defaultdict from collections import defaultdict
import websockets import websockets
from fastapi import WebSocket, WebSocketDisconnect, Depends, HTTPException, status from fastapi import Depends, HTTPException, WebSocket, WebSocketDisconnect, status
from app.chat.exceptions import UseWSException, MessageNotFoundException, MessageAlreadyPinnedException from app.chat.exceptions import (
from app.exceptions import IncorrectDataException MessageAlreadyPinnedException,
from app.chat.exceptions import UserDontHavePermissionException MessageNotFoundException,
from app.services import message_service, auth_service UserDontHavePermissionException,
from app.utils.unit_of_work import UnitOfWork UseWSException,
)
from app.chat.router import router from app.chat.router import router
from app.chat.shemas import SSendMessage, SDeleteMessage, SEditMessage, SPinMessage, SUnpinMessage, Responses from app.chat.shemas import (
from app.dependencies import get_current_user_ws, get_token, get_subprotocol_ws, get_verificated_user Responses,
SDeleteMessage,
SEditMessage,
SPinMessage,
SSendMessage,
SUnpinMessage,
)
from app.dependencies import (
get_current_user_ws,
get_subprotocol_ws,
get_token,
get_verificated_user,
)
from app.exceptions import IncorrectDataException
from app.services import auth_service, message_service
from app.users.schemas import SUser from app.users.schemas import SUser
from app.utils.unit_of_work import UnitOfWork
class ConnectionManager: class ConnectionManager:

View file

@ -1,16 +1,16 @@
from uuid import UUID from uuid import UUID
from pydantic import HttpUrl from pydantic import HttpUrl
from sqlalchemy import insert, select, update, delete, func from sqlalchemy import delete, func, insert, select, update
from sqlalchemy.exc import IntegrityError, NoResultFound from sqlalchemy.exc import IntegrityError, NoResultFound
from app.dao.base import BaseDAO
from app.chat.exceptions import ( from app.chat.exceptions import (
UserAlreadyPinnedChatException, ChatNotFoundException,
MessageAlreadyPinnedException, MessageAlreadyPinnedException,
ChatNotFoundException, UserAlreadyPinnedChatException,
) )
from app.chat.shemas import SPinnedChats, SChat from app.chat.shemas import SChat, SPinnedChats
from app.dao.base import BaseDAO
from app.models.chat import Chat from app.models.chat import Chat
from app.models.pinned_chat import PinnedChat from app.models.pinned_chat import PinnedChat
from app.models.pinned_message import PinnedMessage from app.models.pinned_message import PinnedMessage
@ -107,7 +107,6 @@ class ChatDAO(BaseDAO):
await self.session.execute(stmt) await self.session.execute(stmt)
async def get_pinned_chats(self, user_id: int) -> SPinnedChats: async def get_pinned_chats(self, user_id: int) -> SPinnedChats:
query = ( query = (
select( select(
func.json_build_object( func.json_build_object(

View file

@ -1,5 +1,5 @@
from datetime import datetime, UTC from datetime import UTC, datetime
from uuid import uuid4, UUID from uuid import UUID, uuid4
from app.chat.shemas import SMessageRaw, SMessageRawList from app.chat.shemas import SMessageRaw, SMessageRawList

View file

@ -1,15 +1,15 @@
from pydantic import EmailStr from pydantic import EmailStr
from sqlalchemy import update, select, insert, func, or_ from sqlalchemy import func, insert, or_, select, update
from sqlalchemy.exc import MultipleResultsFound, IntegrityError, NoResultFound from sqlalchemy.exc import IntegrityError, MultipleResultsFound, NoResultFound
from app.chat.shemas import SAllowedChats from app.chat.shemas import SAllowedChats
from app.dao.base import BaseDAO from app.dao.base import BaseDAO
from app.exceptions import IncorrectDataException from app.exceptions import IncorrectDataException
from app.users.exceptions import UserAlreadyExistsException, UserNotFoundException
from app.models.chat import Chat from app.models.chat import Chat
from app.models.user_avatar import UserAvatar from app.models.user_avatar import UserAvatar
from app.models.users import Users
from app.models.user_chat import UserChat from app.models.user_chat import UserChat
from app.models.users import Users
from app.users.exceptions import UserAlreadyExistsException, UserNotFoundException
from app.users.schemas import SUser, SUserAvatars, SUsers from app.users.schemas import SUser, SUserAvatars, SUsers

View file

@ -2,15 +2,18 @@ from typing import Annotated
from fastapi import Depends, Header from fastapi import Depends, Header
from fastapi.security import HTTPBearer from fastapi.security import HTTPBearer
from jose import JWTError, jwt, ExpiredSignatureError from jose import ExpiredSignatureError, JWTError, jwt
from app.config import settings from app.config import settings
from app.exceptions import IncorrectTokenFormatException, TokenMissingException, TokenExpiredException from app.exceptions import (
IncorrectTokenFormatException,
TokenExpiredException,
TokenMissingException,
)
from app.services import user_service from app.services import user_service
from app.utils.unit_of_work import UnitOfWork from app.users.exceptions import UserMustConfirmEmailException, UserNotFoundException
from app.users.schemas import SUser from app.users.schemas import SUser
from app.users.exceptions import UserNotFoundException, UserMustConfirmEmailException from app.utils.unit_of_work import UnitOfWork
auth_schema = HTTPBearer() auth_schema = HTTPBearer()

View file

@ -1,8 +1,8 @@
from fastapi import APIRouter, UploadFile, status, Depends from fastapi import APIRouter, Depends, UploadFile, status
from app.images.shemas import SImageUrl, Responses
from app.services import image_service
from app.dependencies import get_verificated_user from app.dependencies import get_verificated_user
from app.images.shemas import Responses, SImageUrl
from app.services import image_service
router = APIRouter(prefix="/images", tags=["Загрузка картинок"]) router = APIRouter(prefix="/images", tags=["Загрузка картинок"])

View file

@ -1,10 +1,9 @@
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from app.users.router import router as user_router
from app.chat.websocket import router as websocket_router from app.chat.websocket import router as websocket_router
from app.images.router import router as image_router from app.images.router import router as image_router
from app.users.router import router as user_router
# sentry_sdk.init( # sentry_sdk.init(
# dsn=settings.SENTRY_DSN, # dsn=settings.SENTRY_DSN,

View file

@ -1,16 +1,15 @@
from logging.config import fileConfig from logging.config import fileConfig
from sqlalchemy import engine_from_config, pool
from alembic import context from alembic import context
from sqlalchemy import engine_from_config, pool
from app.database import DATABASE_URL, Base from app.database import DATABASE_URL, Base
from app.models.users import Users # noqa
from app.models.chat import Chat # noqa from app.models.chat import Chat # noqa
from app.models.pinned_chat import PinnedChat # noqa from app.models.pinned_chat import PinnedChat # noqa
from app.models.pinned_message import PinnedMessage # noqa from app.models.pinned_message import PinnedMessage # noqa
from app.models.user_chat import UserChat # noqa
from app.models.user_avatar import UserAvatar # noqa from app.models.user_avatar import UserAvatar # noqa
from app.models.user_chat import UserChat # noqa
from app.models.users import Users # noqa
# this is the Alembic Config object, which provides # this is the Alembic Config object, which provides
# access to the values within the .ini file in use. # access to the values within the .ini file in use.

View file

@ -7,9 +7,8 @@ Create Date: 2024-08-20 12:30:52.435668
""" """
from typing import Sequence, Union from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision: str = '53fd6f2b93a4' revision: str = '53fd6f2b93a4'

View file

@ -1,5 +1,5 @@
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from sqlalchemy.orm import mapped_column, Mapped from sqlalchemy.orm import Mapped, mapped_column
from app.database import Base from app.database import Base

View file

@ -1,5 +1,5 @@
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from sqlalchemy.orm import mapped_column, Mapped from sqlalchemy.orm import Mapped, mapped_column
from app.database import Base from app.database import Base

View file

@ -1,7 +1,13 @@
from uuid import UUID from uuid import U[tool.isort]
profile = "black"
multi_line_output = 3
force_grid_wrap = 0
combine_as_imports = true
use_parentheses = trueUID
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from sqlalchemy.orm import mapped_column, Mapped from sqlalchemy.orm import Mapped, mapped_column
from app.database import Base from app.database import Base

View file

@ -1,7 +1,7 @@
from datetime import date from datetime import date
from sqlalchemy import func from sqlalchemy import func
from sqlalchemy.orm import mapped_column, Mapped from sqlalchemy.orm import Mapped, mapped_column
from app.database import Base from app.database import Base

View file

@ -1,19 +1,19 @@
from datetime import datetime, timedelta, UTC from datetime import UTC, datetime, timedelta
from cryptography.fernet import Fernet, InvalidToken from cryptography.fernet import Fernet, InvalidToken
from jose import jwt from jose import jwt
from passlib.context import CryptContext from passlib.context import CryptContext
from app.chat.exceptions import ChatNotFoundException, UserCanNotReadThisChatException
from app.config import settings from app.config import settings
from app.users.exceptions import ( from app.users.exceptions import (
IncorrectAuthDataException, IncorrectAuthDataException,
UserNotFoundException, UserMustConfirmEmailException,
UserMustConfirmEmailException, UserNotFoundException,
WrongCodeException, WrongCodeException,
) )
from app.chat.exceptions import ChatNotFoundException, UserCanNotReadThisChatException from app.users.schemas import SInvitationData, SUser
from app.utils.unit_of_work import UnitOfWork from app.utils.unit_of_work import UnitOfWork
from app.users.schemas import SUser, SInvitationData
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
# bcrypt не умеет больше 72 байт хешировать. Остальное обрезаем # bcrypt не умеет больше 72 байт хешировать. Остальное обрезаем

View file

@ -3,13 +3,16 @@ from urllib.parse import urljoin
from pydantic import ValidationError from pydantic import ValidationError
from app.chat.exceptions import UserDontHavePermissionException, UserCanNotReadThisChatException from app.chat.exceptions import (
from app.chat.shemas import SAllowedChats, SChangeData, SPinnedChats, SChat UserCanNotReadThisChatException,
UserDontHavePermissionException,
)
from app.chat.shemas import SAllowedChats, SChangeData, SChat, SPinnedChats
from app.config import settings from app.config import settings
from app.services import auth_service, user_service
from app.services.redis_service import RedisService from app.services.redis_service import RedisService
from app.services import user_service, auth_service
from app.utils.unit_of_work import UnitOfWork
from app.users.schemas import SInvitationData from app.users.schemas import SInvitationData
from app.utils.unit_of_work import UnitOfWork
async def find_chat(uow: UnitOfWork, chat_id: int, user_id: int) -> SChat: async def find_chat(uow: UnitOfWork, chat_id: int, user_id: int) -> SChat:

View file

@ -1,6 +1,6 @@
from urllib.parse import urljoin from urllib.parse import urljoin
from fastapi import UploadFile, HTTPException from fastapi import HTTPException, UploadFile
from httpx import AsyncClient, Response from httpx import AsyncClient, Response
from app.config import settings from app.config import settings

View file

@ -1,12 +1,18 @@
from datetime import datetime, UTC, timedelta from datetime import UTC, datetime, timedelta
from uuid import UUID from uuid import UUID
from app.chat.shemas import SMessage, SSendMessage, SPinnedMessages, SMessageList, SMessageRaw, SMessageRawList from app.chat.shemas import (
SMessage,
SMessageList,
SMessageRaw,
SMessageRawList,
SPinnedMessages,
SSendMessage,
)
from app.services import user_service from app.services import user_service
from app.users.schemas import SUser from app.users.schemas import SUser
from app.utils.unit_of_work import UnitOfWork from app.utils.unit_of_work import UnitOfWork
_users: dict[int, tuple[SUser, datetime]] = {} _users: dict[int, tuple[SUser, datetime]] = {}
async def _get_cached_user(uow: UnitOfWork, user_id: int) -> SUser: async def _get_cached_user(uow: UnitOfWork, user_id: int) -> SUser:

View file

@ -4,12 +4,19 @@ from pydantic import ValidationError
from app.config import settings from app.config import settings
from app.exceptions import BlackPhoenixException from app.exceptions import BlackPhoenixException
from app.tasks import tasks
from app.utils.unit_of_work import UnitOfWork
from app.users.exceptions import PasswordsMismatchException, WrongCodeException
from app.users.schemas import SUser, SUsers, SUserRegister, SConfirmationData, SUserAvatars, SUserChangeData
from app.services import auth_service from app.services import auth_service
from app.services.redis_service import RedisService from app.services.redis_service import RedisService
from app.tasks import tasks
from app.users.exceptions import PasswordsMismatchException, WrongCodeException
from app.users.schemas import (
SConfirmationData,
SUser,
SUserAvatars,
SUserChangeData,
SUserRegister,
SUsers,
)
from app.utils.unit_of_work import UnitOfWork
async def find_user(uow: UnitOfWork, **find_by) -> SUser: async def find_user(uow: UnitOfWork, **find_by) -> SUser:

View file

@ -2,7 +2,6 @@ from celery import Celery
from app.config import settings from app.config import settings
celery = Celery("tasks", broker=f"redis://{settings.REDIS_HOST}:{settings.REDIS_PORT}", include=["app.tasks.tasks"]) celery = Celery("tasks", broker=f"redis://{settings.REDIS_HOST}:{settings.REDIS_PORT}", include=["app.tasks.tasks"])
celery.conf.update(result_backend=f"redis://{settings.REDIS_HOST}:{settings.REDIS_PORT}") celery.conf.update(result_backend=f"redis://{settings.REDIS_HOST}:{settings.REDIS_PORT}")

View file

@ -1,22 +1,20 @@
import smtplib
import random import random
import smtplib
import string import string
from urllib.parse import urljoin from urllib.parse import urljoin
from pydantic import EmailStr from pydantic import EmailStr
from app.config import settings from app.config import settings
from app.services import auth_service
from app.tasks.celery import celery from app.tasks.celery import celery
from app.tasks.email_templates import ( from app.tasks.email_templates import (
create_registration_confirmation_template, create_data_change_confirmation_email,
create_data_change_confirmation_email, create_data_change_email,
create_data_change_email, create_registration_confirmation_template,
) )
from app.services import auth_service
from app.users.schemas import SConfirmationData from app.users.schemas import SConfirmationData
confirmation_mail_templates = { confirmation_mail_templates = {
"registration": create_registration_confirmation_template, "registration": create_registration_confirmation_template,
"data_change_confirmation": create_data_change_confirmation_email, "data_change_confirmation": create_data_change_confirmation_email,

View file

@ -2,26 +2,30 @@ from random import randrange
from fastapi import APIRouter, Depends, status from fastapi import APIRouter, Depends, status
from app.services import user_service, auth_service
from app.users.exceptions import UserAlreadyExistsException, PasswordAlreadyInUseException, UserNotFoundException
from app.utils.unit_of_work import UnitOfWork
from app.dependencies import get_current_user from app.dependencies import get_current_user
from app.users.schemas import ( from app.services import auth_service, user_service
SUserLogin, from app.users.exceptions import (
SUserRegister, PasswordAlreadyInUseException,
SUserResponse, UserAlreadyExistsException,
SUserAvatars, UserNotFoundException,
SUserFilter,
SUser,
SUserChangeData,
SUserSendConfirmationCode,
STokenLogin,
SUsers,
SUserPassword,
SGetUsersFilter,
SUserCode,
Responses,
) )
from app.users.schemas import (
Responses,
SGetUsersFilter,
STokenLogin,
SUser,
SUserAvatars,
SUserChangeData,
SUserCode,
SUserFilter,
SUserLogin,
SUserPassword,
SUserRegister,
SUserResponse,
SUsers,
SUserSendConfirmationCode,
)
from app.utils.unit_of_work import UnitOfWork
router = APIRouter(prefix="/users", tags=["Пользователи"]) router = APIRouter(prefix="/users", tags=["Пользователи"])

View file

@ -1,9 +1,9 @@
from datetime import date, timedelta, datetime, time from datetime import date, datetime, time, timedelta
from typing import Annotated from typing import Annotated
from pydantic_core import PydanticCustomError
from pydantic import BaseModel, EmailStr, field_validator, HttpUrl, StringConstraints
from fastapi import Query from fastapi import Query
from pydantic import BaseModel, EmailStr, HttpUrl, StringConstraints, field_validator
from pydantic_core import PydanticCustomError
class SUserLogin(BaseModel): class SUserLogin(BaseModel):

View file

@ -4,8 +4,8 @@ from sqlalchemy.exc import SQLAlchemyError
from app.dao.chat import ChatDAO from app.dao.chat import ChatDAO
from app.dao.message import MessageDAO from app.dao.message import MessageDAO
from app.database import async_session_maker, mongo_db
from app.dao.user import UserDAO from app.dao.user import UserDAO
from app.database import async_session_maker, mongo_db
from app.exceptions import BlackPhoenixException from app.exceptions import BlackPhoenixException

5
pyproject.toml Normal file
View file

@ -0,0 +1,5 @@
[tool.isort]
profile = "black"
multi_line_output = 3
force_grid_wrap = 0
use_parentheses = true

View file

@ -2,16 +2,16 @@ import json
from datetime import datetime from datetime import datetime
import pytest import pytest
from sqlalchemy import insert, update
from httpx import AsyncClient from httpx import AsyncClient
from sqlalchemy import insert, update
from app.config import settings from app.config import settings
from app.database import Base, async_session_maker, engine from app.database import Base, async_session_maker, engine
from app.models.users import Users from app.main import app as fastapi_app
from app.models.chat import Chat from app.models.chat import Chat
from app.models.message import Message from app.models.message import Message
from app.models.user_chat import UserChat from app.models.user_chat import UserChat
from app.main import app as fastapi_app from app.models.users import Users
@pytest.fixture(autouse=True, scope="module") @pytest.fixture(autouse=True, scope="module")