Переделка бд
This commit is contained in:
parent
51f32c0750
commit
56afc2649b
13 changed files with 133 additions and 157 deletions
33
app/chat/exceptions.py
Normal file
33
app/chat/exceptions.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
from fastapi import status
|
||||
|
||||
from app.exceptions import BlackPhoenixException
|
||||
|
||||
|
||||
class UseWSException(BlackPhoenixException):
|
||||
status_code = status.HTTP_403_FORBIDDEN
|
||||
detail = "Це для теста, не трожь сцука!!!"
|
||||
|
||||
|
||||
class UserDontHavePermissionException(BlackPhoenixException):
|
||||
status_code = status.HTTP_409_CONFLICT
|
||||
detail = "У вас нет прав для этого действия"
|
||||
|
||||
|
||||
class MessageNotFoundException(BlackPhoenixException):
|
||||
status_code = status.HTTP_404_NOT_FOUND
|
||||
detail = "Сообщение не найдено"
|
||||
|
||||
|
||||
class UserCanNotReadThisChatException(BlackPhoenixException):
|
||||
status_code = status.HTTP_409_CONFLICT
|
||||
detail = "Юзер не может читать этот чат"
|
||||
|
||||
|
||||
class UserAlreadyInChatException(BlackPhoenixException):
|
||||
status_code = status.HTTP_409_CONFLICT
|
||||
detail = "Юзер уже добавлен в чат"
|
||||
|
||||
|
||||
class UserAlreadyPinnedChatException(BlackPhoenixException):
|
||||
status_code = status.HTTP_409_CONFLICT
|
||||
detail = "Юзер уже закрепил чат"
|
|
@ -1,7 +1,11 @@
|
|||
from fastapi import APIRouter, Depends, status
|
||||
|
||||
from app.config import settings
|
||||
from app.exceptions import UserDontHavePermissionException, MessageNotFoundException, UserCanNotReadThisChatException
|
||||
from app.chat.exceptions import (
|
||||
UserDontHavePermissionException,
|
||||
MessageNotFoundException,
|
||||
UserCanNotReadThisChatException,
|
||||
)
|
||||
from app.chat.shemas import (
|
||||
SMessage,
|
||||
SLastMessages,
|
||||
|
@ -11,7 +15,7 @@ from app.chat.shemas import (
|
|||
SAllowedChats,
|
||||
SMessageList,
|
||||
SPinnedChats,
|
||||
SPinnedMessages
|
||||
SPinnedMessages,
|
||||
)
|
||||
from app.unit_of_work import UnitOfWork
|
||||
from app.users.dependencies import check_verificated_user_with_exc
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import logging
|
||||
|
||||
import websockets
|
||||
from fastapi import WebSocket, WebSocketDisconnect, Depends
|
||||
|
||||
from app.exceptions import IncorrectDataException, UserDontHavePermissionException
|
||||
from app.chat.exceptions import UseWSException
|
||||
from app.exceptions import IncorrectDataException
|
||||
from app.chat.exceptions import UserDontHavePermissionException
|
||||
from app.services.message_service import MessageService
|
||||
from app.unit_of_work import UnitOfWork
|
||||
from app.utils.auth import AuthService
|
||||
|
@ -97,10 +97,8 @@ class ConnectionManager:
|
|||
@staticmethod
|
||||
async def add_message_to_database(uow: UnitOfWork, user_id: int, chat_id: int, message: SSendMessage) -> SMessage:
|
||||
new_message = await MessageService.send_message(
|
||||
uow=uow, user_id=user_id, chat_id=chat_id, message=message.message, image_url=message.image_url
|
||||
uow=uow, user_id=user_id, chat_id=chat_id, message=message, image_url=message.image_url
|
||||
)
|
||||
if message.answer:
|
||||
new_message = await MessageService.add_answer(uow=uow, self_id=new_message.id, answer_id=message.answer)
|
||||
return new_message
|
||||
|
||||
@staticmethod
|
||||
|
@ -152,13 +150,13 @@ async def websocket_endpoint(
|
|||
|
||||
|
||||
@router.post(
|
||||
"/ws/{chat_id}"
|
||||
"/ws/{chat_id}",
|
||||
)
|
||||
async def websocket_endpoint(
|
||||
async def chat_ws(
|
||||
chat_id: int,
|
||||
token: str = Depends(get_token),
|
||||
):
|
||||
logging.critical("Это сообщение уровня INFO")
|
||||
raise UseWSException # noqa
|
||||
url = f"ws://localhost:8000/api/chat/ws/{chat_id}"
|
||||
async with websockets.connect(url, extra_headers={"Authorization": f"Bearer {token}"}) as websocket:
|
||||
print(await websocket.recv())
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
from sqlalchemy import insert, select, update, delete
|
||||
import logging
|
||||
|
||||
from sqlalchemy import insert, select, update, delete, func
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
from app.dao.base import BaseDAO
|
||||
from app.database import engine # noqa
|
||||
from app.exceptions import UserAlreadyInChatException, UserAlreadyPinnedChatException
|
||||
from app.chat.exceptions import UserAlreadyInChatException, UserAlreadyPinnedChatException
|
||||
from app.chat.shemas import SMessage
|
||||
from app.models.users import Users
|
||||
from app.models.message_answer import MessageAnswer
|
||||
|
@ -37,38 +39,15 @@ class ChatDAO(BaseDAO):
|
|||
except IntegrityError:
|
||||
raise UserAlreadyInChatException
|
||||
|
||||
async def send_message(self, user_id: int, chat_id: int, message: str, image_url: str | None = None) -> SMessage:
|
||||
inserted_image = (
|
||||
async def send_message(self, user_id: int, chat_id: int, message: str, image_url: str | None = None) -> int:
|
||||
stmt = (
|
||||
insert(Message)
|
||||
.values(chat_id=chat_id, user_id=user_id, message=message, image_url=image_url)
|
||||
.returning(
|
||||
Message.id, Message.message, Message.image_url, Message.chat_id, Message.user_id, Message.created_at
|
||||
)
|
||||
.cte("inserted_image")
|
||||
.returning(Message.id)
|
||||
)
|
||||
|
||||
query = (
|
||||
select(
|
||||
inserted_image.c.id,
|
||||
inserted_image.c.message,
|
||||
inserted_image.c.image_url,
|
||||
inserted_image.c.chat_id,
|
||||
inserted_image.c.user_id,
|
||||
inserted_image.c.created_at,
|
||||
Users.avatar_image,
|
||||
Users.username,
|
||||
MessageAnswer.self_id,
|
||||
MessageAnswer.answer_id,
|
||||
)
|
||||
.select_from(inserted_image)
|
||||
.join(Users, Users.id == inserted_image.c.user_id)
|
||||
.join(MessageAnswer, MessageAnswer.self_id == inserted_image.c.id, isouter=True)
|
||||
)
|
||||
|
||||
result = await self.session.execute(query)
|
||||
await self.session.commit()
|
||||
result = result.mappings().one()
|
||||
return SMessage.model_validate(result, from_attributes=True)
|
||||
result = await self.session.execute(stmt)
|
||||
return result.scalar()
|
||||
|
||||
async def get_message_by_id(self, message_id: int):
|
||||
query = (
|
||||
|
@ -152,36 +131,37 @@ class ChatDAO(BaseDAO):
|
|||
await self.session.commit()
|
||||
return True
|
||||
|
||||
async def add_answer(self, self_id: int, answer_id: int) -> SMessage:
|
||||
answer = (
|
||||
insert(MessageAnswer)
|
||||
.values(self_id=self_id, answer_id=answer_id)
|
||||
.returning(MessageAnswer.self_id, MessageAnswer.answer_id)
|
||||
.cte("answer")
|
||||
)
|
||||
async def add_answer(self, self_id: int, answer_id: int | None) -> SMessage:
|
||||
if answer_id:
|
||||
stmt = (
|
||||
insert(MessageAnswer)
|
||||
.values(self_id=self_id, answer_id=answer_id)
|
||||
)
|
||||
await self.session.execute(stmt)
|
||||
|
||||
query = (
|
||||
select(
|
||||
Message.id,
|
||||
Message.message,
|
||||
Message.image_url,
|
||||
Message.chat_id,
|
||||
Message.user_id,
|
||||
Message.created_at,
|
||||
Users.avatar_image,
|
||||
Users.username,
|
||||
answer.c.self_id,
|
||||
answer.c.answer_id,
|
||||
func.json_build_object(
|
||||
"id", Message.id,
|
||||
"message", Message.message,
|
||||
"image_url", Message.image_url,
|
||||
"chat_id", Message.chat_id,
|
||||
"user_id", Message.user_id,
|
||||
"created_at", Message.created_at,
|
||||
"avatar_image", Users.avatar_image,
|
||||
"username", Users.username,
|
||||
"answer_id", MessageAnswer.answer_id,
|
||||
)
|
||||
.select_from(Message)
|
||||
.join(Users, Users.id == Message.user_id)
|
||||
.join(MessageAnswer, MessageAnswer.self_id == Message.id, isouter=True)
|
||||
.where(Message.id == self_id)
|
||||
)
|
||||
.select_from(Message)
|
||||
.join(Users, Users.id == Message.user_id)
|
||||
.join(answer, answer.c.self_id == Message.id, isouter=True)
|
||||
.where(Message.id == self_id)
|
||||
)
|
||||
|
||||
result = await self.session.execute(query)
|
||||
await self.session.commit()
|
||||
result = result.mappings().one()
|
||||
result = result.scalar_one()
|
||||
logging.critical(result)
|
||||
return SMessage.model_validate(result)
|
||||
|
||||
async def delete_chat(self, chat_id: int) -> bool:
|
||||
|
|
|
@ -4,7 +4,8 @@ from sqlalchemy.exc import MultipleResultsFound, IntegrityError
|
|||
|
||||
from app.dao.base import BaseDAO
|
||||
from app.database import engine # noqa
|
||||
from app.exceptions import IncorrectDataException, UserAlreadyExistsException
|
||||
from app.exceptions import IncorrectDataException
|
||||
from app.users.exceptions import UserAlreadyExistsException
|
||||
from app.models.chat import Chats
|
||||
from app.models.user_avatar import UserAvatar
|
||||
from app.models.users import Users
|
||||
|
|
|
@ -9,16 +9,6 @@ class BlackPhoenixException(HTTPException):
|
|||
super().__init__(status_code=self.status_code, detail=self.detail)
|
||||
|
||||
|
||||
class UserAlreadyExistsException(BlackPhoenixException):
|
||||
status_code = status.HTTP_409_CONFLICT
|
||||
detail = "Пользователь с таким ником или почтой уже существует"
|
||||
|
||||
|
||||
class IncorrectAuthDataException(BlackPhoenixException):
|
||||
status_code = status.HTTP_401_UNAUTHORIZED
|
||||
detail = "Введены не верные данные"
|
||||
|
||||
|
||||
class IncorrectTokenFormatException(BlackPhoenixException):
|
||||
status_code = status.HTTP_401_UNAUTHORIZED
|
||||
detail = "Некорректный формат токена"
|
||||
|
@ -34,50 +24,11 @@ class TokenExpiredException(BlackPhoenixException):
|
|||
detail = "Токен истёк"
|
||||
|
||||
|
||||
class UserIsNotPresentException(BlackPhoenixException):
|
||||
status_code = status.HTTP_401_UNAUTHORIZED
|
||||
|
||||
|
||||
class UserDontHavePermissionException(BlackPhoenixException):
|
||||
status_code = status.HTTP_409_CONFLICT
|
||||
detail = "У вас нет прав для этого действия"
|
||||
|
||||
|
||||
class MessageNotFoundException(BlackPhoenixException):
|
||||
status_code = status.HTTP_404_NOT_FOUND
|
||||
detail = "Сообщение не найдено"
|
||||
|
||||
|
||||
class PasswordsMismatchException(BlackPhoenixException):
|
||||
status_code = status.HTTP_409_CONFLICT
|
||||
detail = "Пароли не совпадают"
|
||||
|
||||
|
||||
class UserCanNotReadThisChatException(BlackPhoenixException):
|
||||
status_code = status.HTTP_409_CONFLICT
|
||||
detail = "Юзер не может читать этот чат"
|
||||
|
||||
|
||||
class WrongCodeException(BlackPhoenixException):
|
||||
status_code = status.HTTP_409_CONFLICT
|
||||
detail = "Введён не верный код подтверждения"
|
||||
|
||||
|
||||
class UserNotFoundException(BlackPhoenixException):
|
||||
status_code = status.HTTP_404_NOT_FOUND
|
||||
detail = "Юзер не найден"
|
||||
|
||||
|
||||
class UserAlreadyInChatException(BlackPhoenixException):
|
||||
status_code = status.HTTP_409_CONFLICT
|
||||
detail = "Юзер уже добавлен в чат"
|
||||
|
||||
|
||||
class UserAlreadyPinnedChatException(BlackPhoenixException):
|
||||
status_code = status.HTTP_409_CONFLICT
|
||||
detail = "Юзер уже закрепил чат"
|
||||
|
||||
|
||||
class UserMustConfirmEmailException(BlackPhoenixException):
|
||||
status_code = status.HTTP_409_CONFLICT
|
||||
detail = "Сначала подтвердите почту"
|
||||
|
|
21
app/main.py
21
app/main.py
|
@ -1,9 +1,6 @@
|
|||
import logging
|
||||
|
||||
from fastapi import FastAPI, Request
|
||||
from fastapi import FastAPI
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
|
||||
from app.users.router import router as user_router
|
||||
from app.chat.websocket import router as websocket_router
|
||||
|
@ -29,8 +26,6 @@ headers = [
|
|||
"Access-Control-Allow-Headers",
|
||||
"Authorization",
|
||||
"Accept",
|
||||
"Access-Control-Allow-Origin",
|
||||
"Sec-WebSocket-Protocol",
|
||||
]
|
||||
|
||||
app.add_middleware(
|
||||
|
@ -43,17 +38,3 @@ app.add_middleware(
|
|||
|
||||
app.mount("/static", StaticFiles(directory="app/static"), name="static")
|
||||
|
||||
|
||||
class AddHeaderMiddleware(BaseHTTPMiddleware):
|
||||
async def dispatch(self, request: Request, call_next):
|
||||
logging.critical(f"Запрос \n{request.headers.get("Sec-Websocket-Protocol", "НИХУЯ")}")
|
||||
logging.critical(f"Запрос {request.headers}")
|
||||
logging.critical("Sec-Websocket-Protocol".lower() in request.headers)
|
||||
response = await call_next(request)
|
||||
response.headers["Sec-Websocket-Protocol"] = ""
|
||||
logging.critical(f"Ответ \n {response.headers}")
|
||||
return response
|
||||
|
||||
|
||||
# app.add_middleware(AddHeaderMiddleware)
|
||||
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
from app.chat.shemas import SMessage
|
||||
from app.chat.shemas import SMessage, SSendMessage
|
||||
from app.unit_of_work import UnitOfWork
|
||||
|
||||
|
||||
class MessageService:
|
||||
@staticmethod
|
||||
async def send_message(
|
||||
uow: UnitOfWork, user_id: int, chat_id: int, message: str, image_url: str | None = None
|
||||
uow: UnitOfWork, user_id: int, chat_id: int, message: SSendMessage, image_url: str | None = None
|
||||
) -> SMessage:
|
||||
async with uow:
|
||||
new_message = await uow.chat.send_message(user_id=user_id, chat_id=chat_id, message=message, image_url=image_url)
|
||||
return new_message
|
||||
message_id = await uow.chat.send_message(
|
||||
user_id=user_id, chat_id=chat_id, message=message.message, image_url=image_url
|
||||
)
|
||||
new_message = await uow.chat.add_answer(self_id=message_id, answer_id=message.id)
|
||||
await uow.commit()
|
||||
|
||||
@staticmethod
|
||||
async def add_answer(uow: UnitOfWork, self_id: int, answer_id: int) -> SMessage:
|
||||
async with uow:
|
||||
new_message = await uow.chat.add_answer(self_id=self_id, answer_id=answer_id)
|
||||
return new_message
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import logging
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Depends, Header
|
||||
|
@ -10,7 +9,7 @@ from app.exceptions import (
|
|||
IncorrectTokenFormatException,
|
||||
TokenAbsentException,
|
||||
TokenExpiredException,
|
||||
UserIsNotPresentException,
|
||||
UserNotFoundException,
|
||||
UserMustConfirmEmailException,
|
||||
)
|
||||
from app.services.user_service import UserService
|
||||
|
@ -36,11 +35,11 @@ async def get_current_user(token: str = Depends(get_token), uow=Depends(UnitOfWo
|
|||
|
||||
user_id: str = payload.get("sub")
|
||||
if not user_id:
|
||||
raise UserIsNotPresentException
|
||||
raise UserNotFoundException
|
||||
|
||||
user = await UserService.find_one_or_none(uow=uow, user_id=int(user_id))
|
||||
if not user:
|
||||
raise UserIsNotPresentException
|
||||
raise UserNotFoundException
|
||||
|
||||
return user
|
||||
|
||||
|
@ -67,11 +66,11 @@ async def get_current_user_ws(token: str = Depends(get_token_ws), uow=Depends(Un
|
|||
|
||||
user_id: str = payload.get("sub")
|
||||
if not user_id:
|
||||
raise UserIsNotPresentException
|
||||
raise UserNotFoundException
|
||||
|
||||
user = await UserService.find_one_or_none(uow=uow, user_id=int(user_id))
|
||||
if not user:
|
||||
raise UserIsNotPresentException
|
||||
raise UserNotFoundException
|
||||
|
||||
return user
|
||||
|
||||
|
|
25
app/users/exceptions.py
Normal file
25
app/users/exceptions.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
from fastapi import status
|
||||
|
||||
from app.exceptions import BlackPhoenixException
|
||||
|
||||
|
||||
class UserAlreadyExistsException(BlackPhoenixException):
|
||||
status_code = status.HTTP_409_CONFLICT
|
||||
detail = "Пользователь с таким ником или почтой уже существует"
|
||||
|
||||
|
||||
class IncorrectAuthDataException(BlackPhoenixException):
|
||||
status_code = status.HTTP_401_UNAUTHORIZED
|
||||
detail = "Введены не верные данные"
|
||||
|
||||
|
||||
class PasswordsMismatchException(BlackPhoenixException):
|
||||
status_code = status.HTTP_409_CONFLICT
|
||||
detail = "Пароли не совпадают"
|
||||
|
||||
|
||||
class WrongCodeException(BlackPhoenixException):
|
||||
status_code = status.HTTP_409_CONFLICT
|
||||
detail = "Введён не верный код подтверждения"
|
||||
|
||||
|
|
@ -1,15 +1,21 @@
|
|||
from fastapi import APIRouter, Depends, status
|
||||
|
||||
from app.config import settings
|
||||
from app.exceptions import (
|
||||
PasswordsMismatchException,
|
||||
WrongCodeException,
|
||||
from app.users.exceptions import (
|
||||
UserAlreadyExistsException,
|
||||
IncorrectAuthDataException,
|
||||
PasswordsMismatchException,
|
||||
WrongCodeException,
|
||||
)
|
||||
from app.services.redis_service import RedisService, get_redis_session
|
||||
from app.unit_of_work import UnitOfWork
|
||||
from app.utils.auth import get_password_hash, create_access_token, AuthService, verify_password, decode_confirmation_token
|
||||
from app.utils.auth import (
|
||||
get_password_hash,
|
||||
create_access_token,
|
||||
AuthService,
|
||||
verify_password,
|
||||
decode_confirmation_token
|
||||
)
|
||||
from app.users.dependencies import get_current_user
|
||||
from app.users.schemas import (
|
||||
SUserLogin,
|
||||
|
@ -27,7 +33,8 @@ from app.users.schemas import (
|
|||
)
|
||||
from app.tasks.tasks import (
|
||||
send_registration_confirmation_email,
|
||||
send_data_change_confirmation_email, generate_confirmation_code
|
||||
send_data_change_confirmation_email,
|
||||
generate_confirmation_code
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/users", tags=["Пользователи"])
|
||||
|
|
|
@ -7,11 +7,11 @@ from pydantic import EmailStr
|
|||
|
||||
from app.config import settings
|
||||
from app.exceptions import (
|
||||
UserDontHavePermissionException,
|
||||
IncorrectAuthDataException,
|
||||
UserNotFoundException,
|
||||
UserMustConfirmEmailException,
|
||||
)
|
||||
from app.users.exceptions import IncorrectAuthDataException
|
||||
from app.chat.exceptions import UserDontHavePermissionException
|
||||
from app.unit_of_work import UnitOfWork
|
||||
from app.users.schemas import SUser, SConfirmationData, SInvitationData
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ async def prepare_database():
|
|||
return json.load(file)
|
||||
|
||||
users = open_mock_json("users")
|
||||
users_verification_codes = open_mock_json("verification_codes")
|
||||
chats = open_mock_json("chats")
|
||||
users_x_chats = open_mock_json("x_chats")
|
||||
messages = open_mock_json("messages")
|
||||
|
@ -46,7 +45,6 @@ async def prepare_database():
|
|||
set_verified_user = update(Users).values(role=1).where(Users.id == 3)
|
||||
|
||||
await session.execute(add_users)
|
||||
await session.execute(add_users_verification_codes)
|
||||
await session.execute(add_chats)
|
||||
await session.execute(add_users_x_chats)
|
||||
await session.execute(add_messages)
|
||||
|
|
Loading…
Add table
Reference in a new issue