chat_back/app/chat/router.py

198 lines
7.1 KiB
Python

from cryptography.fernet import Fernet
from fastapi import APIRouter, Depends, status
from app.config import settings
from app.exceptions import UserDontHavePermissionException, MessageNotFoundException, UserCanNotReadThisChatException
from app.chat.shemas import SMessage, SLastMessages, SPinnedChat, SDeletedUser, SChat, SDeletedChat
from app.unit_of_work import UnitOfWork
from app.users.dependencies import check_verificated_user_with_exc
from app.users.auth import ADMIN_USER_ID, AuthService
from app.users.schemas import SCreateInvitationLink, SUserAddedToChat, SUser
router = APIRouter(prefix="/chat", tags=["Чат"])
@router.get(
"",
status_code=status.HTTP_200_OK,
response_model=list[SChat]
)
async def get_all_chats(user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)):
async with uow:
result = await uow.user.get_user_allowed_chats(user.id)
return result
@router.post(
"/create_chat",
status_code=status.HTTP_201_CREATED,
response_model=None,
)
async def create_chat(user_to_exclude: int, chat_name: str, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)):
async with uow:
if user.id == user_to_exclude:
raise UserCanNotReadThisChatException
chat_id = await uow.chat.create(user_id=user_to_exclude, chat_name=chat_name, created_by=user.id)
user_added_to_chat = await uow.chat.add_user_to_chat(user.id, chat_id)
await uow.chat.add_user_to_chat(ADMIN_USER_ID, chat_id)
return user_added_to_chat
@router.get(
"/get_last_message/{chat_id}",
status_code=status.HTTP_200_OK,
response_model=list[SMessage]
)
async def get_last_message(chat_id: int, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)):
await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
async with uow:
message = await uow.chat.get_some_messages(chat_id=chat_id, message_number_from=0, messages_to_get=1)
if message is None:
raise MessageNotFoundException
for mes in message:
mes["created_at"] = mes["created_at"].isoformat()
return message
@router.get(
"/get_some_messages/{chat_id}",
status_code=status.HTTP_200_OK,
response_model=list[SMessage]
)
async def get_some_messages(
chat_id: int, last_messages: SLastMessages = Depends(), user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)
):
await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
async with uow:
messages = await uow.chat.get_some_messages(
chat_id=chat_id,
message_number_from=last_messages.messages_loaded,
messages_to_get=last_messages.messages_to_get
)
if not messages:
raise MessageNotFoundException
for mes in messages:
mes["created_at"] = mes["created_at"].isoformat()
return messages
@router.get(
"/message/{chat_id}",
status_code=status.HTTP_200_OK,
response_model=SMessage
)
async def get_message_by_id(chat_id: int, message_id: int, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)):
await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
async with uow:
message = await uow.chat.get_message_by_id(message_id=message_id)
if not message:
raise MessageNotFoundException
message = dict(message)
message["created_at"] = message["created_at"].isoformat()
return message
@router.get(
"/create_invitation_link",
status_code=status.HTTP_201_CREATED,
response_model=SCreateInvitationLink,
)
async def create_invitation_link(chat_id: int, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)):
await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
cipher_suite = Fernet(settings.INVITATION_LINK_TOKEN_KEY)
invitation_token = cipher_suite.encrypt(str(chat_id).encode())
invitation_link = settings.INVITATION_LINK_HOST + "/api/chat/invite_to_chat/" + str(invitation_token).split("'")[1]
return {"invitation_link": invitation_link}
@router.get(
"/invite_to_chat/{invitation_token}",
status_code=status.HTTP_200_OK,
response_model=SUserAddedToChat,
)
async def invite_to_chat(invitation_token: str, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)):
async with uow:
invitation_token = invitation_token.encode()
cipher_suite = Fernet(settings.INVITATION_LINK_TOKEN_KEY)
chat_id = int(cipher_suite.decrypt(invitation_token))
chat = await uow.chat.find_one_or_none(id=chat_id)
if user.id == chat.chat_for:
raise UserCanNotReadThisChatException
return {"user_added_to_chat": await uow.chat.add_user_to_chat(chat_id=chat_id, user_id=user.id)}
@router.delete(
"/delete_chat/{chat_id}",
status_code=status.HTTP_200_OK,
response_model=SDeletedChat,
)
async def delete_chat(chat_id: int, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)):
async with uow:
chat = await uow.chat.find_one_or_none(id=chat_id)
if user.id == chat.created_by:
return {"deleted_chat": await uow.chat.delete_chat(chat_id)}
raise UserDontHavePermissionException
@router.delete(
"/delete_user_from_chat/{chat_id}",
status_code=status.HTTP_200_OK,
response_model=SDeletedUser
)
async def delete_user_from_chat(chat_id: int, user_id: int, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)):
async with uow:
chat = await uow.chat.find_one_or_none(id=chat_id)
if user.id == chat.created_by:
return {"deleted_user": await uow.chat.delete_user(chat_id=chat_id, user_id=user_id)}
raise UserDontHavePermissionException
@router.post(
"/pin_chat",
status_code=status.HTTP_200_OK,
response_model=SPinnedChat
)
async def pinn_chat(chat_id: int, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)):
await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
async with uow:
await uow.chat.pin_chat(chat_id=chat_id, user_id=user.id)
return {"chat_id": chat_id, "user_id": user.id}
@router.delete(
"/unpin_chat",
status_code=status.HTTP_200_OK,
response_model=SPinnedChat
)
async def unpinn_chat(chat_id: int, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)):
await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
async with uow:
await uow.chat.unpin_chat(chat_id=chat_id, user_id=user.id)
return {"chat_id": chat_id, "user_id": user.id}
@router.get(
"/get_pinned_chats",
status_code=status.HTTP_200_OK,
response_model=list[SChat]
)
async def get_pinned_chats(user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)):
async with uow:
return await uow.chat.get_pinned_chats(user_id=user.id)
@router.get(
"/pinned_messages/{chat_id}",
status_code=status.HTTP_200_OK,
response_model=list[SMessage] | None
)
async def pinned_messages(chat_id: int, user: SUser = Depends(check_verificated_user_with_exc), uow=Depends(UnitOfWork)):
await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
async with uow:
messages = await uow.chat.get_pinned_messages(chat_id=chat_id)
if messages:
for mes in messages:
mes["created_at"] = mes["created_at"].isoformat()
return messages