Рефакторинг, убрал лишнее ооп
This commit is contained in:
parent
f21cedbb81
commit
fd03106c74
12 changed files with 452 additions and 496 deletions
|
@ -13,11 +13,9 @@ from app.chat.shemas import (
|
||||||
SChatId,
|
SChatId,
|
||||||
Responses,
|
Responses,
|
||||||
)
|
)
|
||||||
from app.services.chat_service import ChatService
|
from app.services import chat_service, message_service, auth_service
|
||||||
from app.services.message_service import MessageService
|
|
||||||
from app.utils.unit_of_work import UnitOfWork
|
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.auth_service import AuthService
|
|
||||||
from app.users.schemas import SCreateInvitationLink, SUser
|
from app.users.schemas import SCreateInvitationLink, SUser
|
||||||
|
|
||||||
router = APIRouter(prefix="/chat", tags=["Чат"])
|
router = APIRouter(prefix="/chat", tags=["Чат"])
|
||||||
|
@ -51,7 +49,7 @@ router = APIRouter(prefix="/chat", tags=["Чат"])
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def get_all_chats(user: SUser = Depends(get_verificated_user), uow=Depends(UnitOfWork)):
|
async def get_all_chats(user: SUser = Depends(get_verificated_user), uow=Depends(UnitOfWork)):
|
||||||
allowed_chats = await ChatService.get_all_chats(uow=uow, user_id=user.id)
|
allowed_chats = await chat_service.get_all_chats(uow=uow, user_id=user.id)
|
||||||
return allowed_chats
|
return allowed_chats
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,7 +86,7 @@ async def create_chat(
|
||||||
user: SUser = Depends(get_verificated_user),
|
user: SUser = Depends(get_verificated_user),
|
||||||
uow=Depends(UnitOfWork),
|
uow=Depends(UnitOfWork),
|
||||||
):
|
):
|
||||||
chat_id = await ChatService.create_chat(
|
chat_id = await chat_service.create_chat(
|
||||||
uow=uow,
|
uow=uow,
|
||||||
user_id=user.id,
|
user_id=user.id,
|
||||||
user_to_exclude_id=user_to_exclude,
|
user_to_exclude_id=user_to_exclude,
|
||||||
|
@ -129,8 +127,8 @@ async def change_chat_data(
|
||||||
user: SUser = Depends(get_verificated_user),
|
user: SUser = Depends(get_verificated_user),
|
||||||
uow=Depends(UnitOfWork),
|
uow=Depends(UnitOfWork),
|
||||||
):
|
):
|
||||||
await AuthService.validate_user_access_to_chat(uow=uow, chat_id=user_data.chat_id, user_id=user.id)
|
await auth_service.validate_user_access_to_chat(uow=uow, chat_id=user_data.chat_id, user_id=user.id)
|
||||||
await ChatService.change_chat_data(uow=uow, user_id=user.id, user_data=user_data)
|
await chat_service.change_chat_data(uow=uow, user_id=user.id, user_data=user_data)
|
||||||
|
|
||||||
|
|
||||||
@router.get(
|
@router.get(
|
||||||
|
@ -161,8 +159,8 @@ async def change_chat_data(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def get_last_message(chat_id: int, user: SUser = Depends(get_verificated_user), uow=Depends(UnitOfWork)):
|
async def get_last_message(chat_id: int, user: SUser = Depends(get_verificated_user), uow=Depends(UnitOfWork)):
|
||||||
await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
|
await auth_service.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
|
||||||
message = await MessageService.get_some_messages(uow=uow, chat_id=chat_id, message_number_from=0, messages_to_get=1)
|
message = await message_service.get_some_messages(uow=uow, chat_id=chat_id, message_number_from=0, messages_to_get=1)
|
||||||
return message
|
return message
|
||||||
|
|
||||||
|
|
||||||
|
@ -199,8 +197,8 @@ async def get_some_messages(
|
||||||
user: SUser = Depends(get_verificated_user),
|
user: SUser = Depends(get_verificated_user),
|
||||||
uow=Depends(UnitOfWork),
|
uow=Depends(UnitOfWork),
|
||||||
):
|
):
|
||||||
await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
|
await auth_service.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
|
||||||
messages = await MessageService.get_some_messages(
|
messages = await message_service.get_some_messages(
|
||||||
uow=uow,
|
uow=uow,
|
||||||
chat_id=chat_id,
|
chat_id=chat_id,
|
||||||
message_number_from=last_messages.messages_loaded,
|
message_number_from=last_messages.messages_loaded,
|
||||||
|
@ -242,8 +240,8 @@ async def get_message_by_id(
|
||||||
user: SUser = Depends(get_verificated_user),
|
user: SUser = Depends(get_verificated_user),
|
||||||
uow=Depends(UnitOfWork),
|
uow=Depends(UnitOfWork),
|
||||||
):
|
):
|
||||||
await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
|
await auth_service.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
|
||||||
message = await MessageService.get_message_by_id(uow=uow, message_id=message_id)
|
message = await message_service.get_message_by_id(uow=uow, message_id=message_id)
|
||||||
return message
|
return message
|
||||||
|
|
||||||
|
|
||||||
|
@ -279,8 +277,8 @@ async def create_invitation_link(
|
||||||
user: SUser = Depends(get_verificated_user),
|
user: SUser = Depends(get_verificated_user),
|
||||||
uow=Depends(UnitOfWork),
|
uow=Depends(UnitOfWork),
|
||||||
):
|
):
|
||||||
await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
|
await auth_service.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
|
||||||
invitation_link = ChatService.create_invitation_link(chat_id=chat_id)
|
invitation_link = chat_service.create_invitation_link(chat_id=chat_id)
|
||||||
return {"invitation_link": invitation_link}
|
return {"invitation_link": invitation_link}
|
||||||
|
|
||||||
|
|
||||||
|
@ -316,7 +314,7 @@ async def invite_to_chat(
|
||||||
user: SUser = Depends(get_verificated_user),
|
user: SUser = Depends(get_verificated_user),
|
||||||
uow=Depends(UnitOfWork),
|
uow=Depends(UnitOfWork),
|
||||||
):
|
):
|
||||||
await ChatService.invite_to_chat(uow=uow, user_id=user.id, invitation_token=invitation_token)
|
await chat_service.invite_to_chat(uow=uow, user_id=user.id, invitation_token=invitation_token)
|
||||||
|
|
||||||
|
|
||||||
@router.delete(
|
@router.delete(
|
||||||
|
@ -347,7 +345,7 @@ async def invite_to_chat(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def delete_chat(chat_id: int, user: SUser = Depends(get_verificated_user), uow=Depends(UnitOfWork)):
|
async def delete_chat(chat_id: int, user: SUser = Depends(get_verificated_user), uow=Depends(UnitOfWork)):
|
||||||
await ChatService.delete_chat(uow=uow, user_id=user.id, chat_id=chat_id)
|
await chat_service.delete_chat(uow=uow, user_id=user.id, chat_id=chat_id)
|
||||||
|
|
||||||
|
|
||||||
@router.delete(
|
@router.delete(
|
||||||
|
@ -383,7 +381,7 @@ async def delete_user_from_chat(
|
||||||
user: SUser = Depends(get_verificated_user),
|
user: SUser = Depends(get_verificated_user),
|
||||||
uow=Depends(UnitOfWork),
|
uow=Depends(UnitOfWork),
|
||||||
):
|
):
|
||||||
await ChatService.delete_user_from_chat(uow=uow, user_id=user.id, chat_id=chat_id, user_id_for_delete=user_id)
|
await chat_service.delete_user_from_chat(uow=uow, user_id=user.id, chat_id=chat_id, user_id_for_delete=user_id)
|
||||||
|
|
||||||
|
|
||||||
@router.post(
|
@router.post(
|
||||||
|
@ -414,8 +412,8 @@ async def delete_user_from_chat(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def pin_chat(chat_id: int, user: SUser = Depends(get_verificated_user), uow=Depends(UnitOfWork)):
|
async def pin_chat(chat_id: int, user: SUser = Depends(get_verificated_user), uow=Depends(UnitOfWork)):
|
||||||
await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
|
await auth_service.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
|
||||||
await ChatService.pin_chat(uow=uow, user_id=user.id, chat_id=chat_id)
|
await chat_service.pin_chat(uow=uow, user_id=user.id, chat_id=chat_id)
|
||||||
|
|
||||||
|
|
||||||
@router.delete(
|
@router.delete(
|
||||||
|
@ -445,9 +443,9 @@ async def pin_chat(chat_id: int, user: SUser = Depends(get_verificated_user), uo
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def unpinn_chat(chat_id: int, user: SUser = Depends(get_verificated_user), uow=Depends(UnitOfWork)):
|
async def unpin_chat(chat_id: int, user: SUser = Depends(get_verificated_user), uow=Depends(UnitOfWork)):
|
||||||
await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
|
await auth_service.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
|
||||||
await ChatService.unpin_chat(uow=uow, user_id=user.id, chat_id=chat_id)
|
await chat_service.unpin_chat(uow=uow, user_id=user.id, chat_id=chat_id)
|
||||||
|
|
||||||
|
|
||||||
@router.get(
|
@router.get(
|
||||||
|
@ -478,7 +476,7 @@ async def unpinn_chat(chat_id: int, user: SUser = Depends(get_verificated_user),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def get_pinned_chats(user: SUser = Depends(get_verificated_user), uow=Depends(UnitOfWork)):
|
async def get_pinned_chats(user: SUser = Depends(get_verificated_user), uow=Depends(UnitOfWork)):
|
||||||
pinned_chats = await ChatService.get_pinned_chats(uow=uow, user_id=user.id)
|
pinned_chats = await chat_service.get_pinned_chats(uow=uow, user_id=user.id)
|
||||||
return pinned_chats
|
return pinned_chats
|
||||||
|
|
||||||
|
|
||||||
|
@ -510,6 +508,6 @@ async def get_pinned_chats(user: SUser = Depends(get_verificated_user), uow=Depe
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def get_pinned_messages(chat_id: int, user: SUser = Depends(get_verificated_user), uow=Depends(UnitOfWork)):
|
async def get_pinned_messages(chat_id: int, user: SUser = Depends(get_verificated_user), uow=Depends(UnitOfWork)):
|
||||||
await AuthService.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
|
await auth_service.validate_user_access_to_chat(uow=uow, chat_id=chat_id, user_id=user.id)
|
||||||
pinned_messages = await MessageService.get_pinned_messages(uow=uow, chat_id=chat_id)
|
pinned_messages = await message_service.get_pinned_messages(uow=uow, chat_id=chat_id)
|
||||||
return pinned_messages
|
return pinned_messages
|
||||||
|
|
|
@ -8,9 +8,8 @@ from fastapi import WebSocket, WebSocketDisconnect, Depends, HTTPException, stat
|
||||||
from app.chat.exceptions import UseWSException, MessageNotFoundException, MessageAlreadyPinnedException
|
from app.chat.exceptions import UseWSException, MessageNotFoundException, MessageAlreadyPinnedException
|
||||||
from app.exceptions import IncorrectDataException
|
from app.exceptions import IncorrectDataException
|
||||||
from app.chat.exceptions import UserDontHavePermissionException
|
from app.chat.exceptions import UserDontHavePermissionException
|
||||||
from app.services.message_service import MessageService
|
from app.services import message_service, auth_service
|
||||||
from app.utils.unit_of_work import UnitOfWork
|
from app.utils.unit_of_work import UnitOfWork
|
||||||
from app.services.auth_service import AuthService
|
|
||||||
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 SSendMessage, SDeleteMessage, SEditMessage, SPinMessage, SUnpinMessage, Responses
|
||||||
from app.dependencies import get_current_user_ws, get_token, get_subprotocol_ws, get_verificated_user
|
from app.dependencies import get_current_user_ws, get_token, get_subprotocol_ws, get_verificated_user
|
||||||
|
@ -33,7 +32,10 @@ class ConnectionManager:
|
||||||
self.active_connections[chat_id].append(websocket)
|
self.active_connections[chat_id].append(websocket)
|
||||||
|
|
||||||
async def disconnect(
|
async def disconnect(
|
||||||
self, chat_id: int, websocket: WebSocket, code_and_reason: tuple[int, str] | None = None
|
self,
|
||||||
|
chat_id: int,
|
||||||
|
websocket: WebSocket,
|
||||||
|
code_and_reason: tuple[int, str] | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.active_connections[chat_id].remove(websocket)
|
self.active_connections[chat_id].remove(websocket)
|
||||||
if code_and_reason:
|
if code_and_reason:
|
||||||
|
@ -54,7 +56,7 @@ class ConnectionManager:
|
||||||
async def _send(uow: UnitOfWork, user_id: int, chat_id: int, message: dict) -> dict:
|
async def _send(uow: UnitOfWork, user_id: int, chat_id: int, message: dict) -> dict:
|
||||||
message = SSendMessage.model_validate(message)
|
message = SSendMessage.model_validate(message)
|
||||||
|
|
||||||
new_message = await MessageService.send_message(
|
new_message = await message_service.send_message(
|
||||||
uow=uow,
|
uow=uow,
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
chat_id=chat_id,
|
chat_id=chat_id,
|
||||||
|
@ -74,7 +76,7 @@ class ConnectionManager:
|
||||||
if message.user_id != user_id:
|
if message.user_id != user_id:
|
||||||
raise UserDontHavePermissionException
|
raise UserDontHavePermissionException
|
||||||
|
|
||||||
await MessageService.delete_message(uow=uow, message_id=message.id)
|
await message_service.delete_message(uow=uow, message_id=message.id)
|
||||||
new_message = {"id": str(message.id), "flag": "delete"}
|
new_message = {"id": str(message.id), "flag": "delete"}
|
||||||
return new_message
|
return new_message
|
||||||
|
|
||||||
|
@ -85,7 +87,7 @@ class ConnectionManager:
|
||||||
if message.user_id != user_id:
|
if message.user_id != user_id:
|
||||||
raise UserDontHavePermissionException
|
raise UserDontHavePermissionException
|
||||||
|
|
||||||
await MessageService.edit_message(
|
await message_service.edit_message(
|
||||||
uow=uow,
|
uow=uow,
|
||||||
message_id=message.id,
|
message_id=message.id,
|
||||||
new_message=message.new_message,
|
new_message=message.new_message,
|
||||||
|
@ -102,7 +104,7 @@ class ConnectionManager:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def _pin(uow: UnitOfWork, _: int, chat_id: int, message: dict) -> dict:
|
async def _pin(uow: UnitOfWork, _: int, chat_id: int, message: dict) -> dict:
|
||||||
message = SPinMessage.model_validate(message)
|
message = SPinMessage.model_validate(message)
|
||||||
pinned_message = await MessageService.pin_message(
|
pinned_message = await message_service.pin_message(
|
||||||
uow=uow,
|
uow=uow,
|
||||||
chat_id=chat_id,
|
chat_id=chat_id,
|
||||||
user_id=message.user_id,
|
user_id=message.user_id,
|
||||||
|
@ -118,7 +120,7 @@ class ConnectionManager:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def _unpin(uow: UnitOfWork, _: int, chat_id: int, message: dict) -> dict:
|
async def _unpin(uow: UnitOfWork, _: int, chat_id: int, message: dict) -> dict:
|
||||||
message = SUnpinMessage.model_validate(message)
|
message = SUnpinMessage.model_validate(message)
|
||||||
await MessageService.unpin_message(uow=uow, chat_id=chat_id, message_id=message.id)
|
await message_service.unpin_message(uow=uow, chat_id=chat_id, message_id=message.id)
|
||||||
new_message = {"flag": "unpin", "id": str(message.id)}
|
new_message = {"flag": "unpin", "id": str(message.id)}
|
||||||
return new_message
|
return new_message
|
||||||
|
|
||||||
|
@ -137,8 +139,8 @@ async def websocket_endpoint(
|
||||||
uow=Depends(UnitOfWork),
|
uow=Depends(UnitOfWork),
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
await AuthService.check_verificated_user(uow=uow, user_id=user.id)
|
await auth_service.check_verificated_user(uow=uow, user_id=user.id)
|
||||||
await AuthService.validate_user_access_to_chat(uow=uow, user_id=user.id, chat_id=chat_id)
|
await auth_service.validate_user_access_to_chat(uow=uow, user_id=user.id, chat_id=chat_id)
|
||||||
await manager.connect(chat_id, websocket, subprotocol)
|
await manager.connect(chat_id, websocket, subprotocol)
|
||||||
while True:
|
while True:
|
||||||
data = await websocket.receive_json()
|
data = await websocket.receive_json()
|
||||||
|
@ -266,7 +268,7 @@ polling_manager = PollingManager()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def poll(chat_id: int, user: SUser = Depends(get_verificated_user), uow=Depends(UnitOfWork)):
|
async def poll(chat_id: int, user: SUser = Depends(get_verificated_user), uow=Depends(UnitOfWork)):
|
||||||
await AuthService.validate_user_access_to_chat(uow=uow, user_id=user.id, chat_id=chat_id)
|
await auth_service.validate_user_access_to_chat(uow=uow, user_id=user.id, chat_id=chat_id)
|
||||||
return await polling_manager.poll(chat_id)
|
return await polling_manager.poll(chat_id)
|
||||||
|
|
||||||
|
|
||||||
|
@ -303,5 +305,5 @@ async def send(
|
||||||
user: SUser = Depends(get_verificated_user),
|
user: SUser = Depends(get_verificated_user),
|
||||||
uow=Depends(UnitOfWork),
|
uow=Depends(UnitOfWork),
|
||||||
):
|
):
|
||||||
await AuthService.validate_user_access_to_chat(uow=uow, user_id=user.id, chat_id=chat_id)
|
await auth_service.validate_user_access_to_chat(uow=uow, user_id=user.id, chat_id=chat_id)
|
||||||
await polling_manager.prepare(uow=uow, user_id=user.id, chat_id=chat_id, message=message)
|
await polling_manager.prepare(uow=uow, user_id=user.id, chat_id=chat_id, message=message)
|
||||||
|
|
|
@ -7,7 +7,7 @@ from jose import JWTError, jwt, ExpiredSignatureError
|
||||||
from app.config import settings
|
from app.config import settings
|
||||||
from app.exceptions import IncorrectTokenFormatException, TokenMissingException, TokenExpiredException
|
from app.exceptions import IncorrectTokenFormatException, TokenMissingException, TokenExpiredException
|
||||||
|
|
||||||
from app.services.user_service import UserService
|
from app.services import user_service
|
||||||
from app.utils.unit_of_work import UnitOfWork
|
from app.utils.unit_of_work import UnitOfWork
|
||||||
from app.users.schemas import SUser
|
from app.users.schemas import SUser
|
||||||
from app.users.exceptions import UserNotFoundException, UserMustConfirmEmailException
|
from app.users.exceptions import UserNotFoundException, UserMustConfirmEmailException
|
||||||
|
@ -33,7 +33,7 @@ async def get_current_user(token: str = Depends(get_token), uow=Depends(UnitOfWo
|
||||||
if not user_id:
|
if not user_id:
|
||||||
raise UserNotFoundException
|
raise UserNotFoundException
|
||||||
|
|
||||||
user = await UserService.find_user(uow=uow, id=int(user_id))
|
user = await user_service.find_user(uow=uow, id=int(user_id))
|
||||||
|
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ async def get_current_user_ws(token: str = Depends(get_token_ws), uow=Depends(Un
|
||||||
if not user_id:
|
if not user_id:
|
||||||
raise UserNotFoundException
|
raise UserNotFoundException
|
||||||
|
|
||||||
user = await UserService.find_user(uow=uow, id=int(user_id))
|
user = await user_service.find_user(uow=uow, id=int(user_id))
|
||||||
|
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from fastapi import APIRouter, UploadFile, status, Depends
|
from fastapi import APIRouter, UploadFile, status, Depends
|
||||||
|
|
||||||
from app.images.shemas import SImageUrl, Responses
|
from app.images.shemas import SImageUrl, Responses
|
||||||
from app.services.image_service import ImageService
|
from app.services import image_service
|
||||||
from app.dependencies import get_verificated_user
|
from app.dependencies import get_verificated_user
|
||||||
|
|
||||||
router = APIRouter(prefix="/images", tags=["Загрузка картинок"])
|
router = APIRouter(prefix="/images", tags=["Загрузка картинок"])
|
||||||
|
@ -35,7 +35,7 @@ router = APIRouter(prefix="/images", tags=["Загрузка картинок"])
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def upload_avatar(file: UploadFile, _=Depends(get_verificated_user)):
|
async def upload_avatar(file: UploadFile, _=Depends(get_verificated_user)):
|
||||||
image_url = await ImageService.upload_file_returning_str(file, "upload_avatar")
|
image_url = await image_service.upload_file_returning_str(file, "upload_avatar")
|
||||||
return {"image_url": image_url}
|
return {"image_url": image_url}
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,5 +67,5 @@ async def upload_avatar(file: UploadFile, _=Depends(get_verificated_user)):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def upload_image(file: UploadFile, _=Depends(get_verificated_user)):
|
async def upload_image(file: UploadFile, _=Depends(get_verificated_user)):
|
||||||
image_url = await ImageService.upload_file_returning_str(file, "upload_image")
|
image_url = await image_service.upload_file_returning_str(file, "upload_image")
|
||||||
return {"image_url": image_url}
|
return {"image_url": image_url}
|
||||||
|
|
|
@ -15,34 +15,29 @@ from app.chat.exceptions import ChatNotFoundException, UserCanNotReadThisChatExc
|
||||||
from app.utils.unit_of_work import UnitOfWork
|
from app.utils.unit_of_work import UnitOfWork
|
||||||
from app.users.schemas import SUser, SInvitationData
|
from app.users.schemas import SUser, SInvitationData
|
||||||
|
|
||||||
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") # bcrypt не умеет больше 72 байт хешировать. Остальное обрезаем
|
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||||
|
# bcrypt не умеет больше 72 байт хешировать. Остальное обрезаем
|
||||||
|
|
||||||
cipher_suite = Fernet(settings.INVITATION_LINK_TOKEN_KEY)
|
cipher_suite = Fernet(settings.INVITATION_LINK_TOKEN_KEY)
|
||||||
|
|
||||||
class AuthService:
|
def get_password_hash(password: str) -> str:
|
||||||
@staticmethod
|
|
||||||
def get_password_hash(password: str) -> str:
|
|
||||||
return pwd_context.hash(password.encode("utf-8")[:72])
|
return pwd_context.hash(password.encode("utf-8")[:72])
|
||||||
|
|
||||||
@staticmethod
|
def verify_password(plain_password: str, hashed_password: str) -> bool:
|
||||||
def verify_password(plain_password: str, hashed_password: str) -> bool:
|
|
||||||
return pwd_context.verify(plain_password.encode("utf-8")[:72], hashed_password)
|
return pwd_context.verify(plain_password.encode("utf-8")[:72], hashed_password)
|
||||||
|
|
||||||
@staticmethod
|
def create_access_token(data: dict[str, str | datetime]) -> str:
|
||||||
def create_access_token(data: dict[str, str | datetime]) -> str:
|
|
||||||
to_encode = data.copy()
|
to_encode = data.copy()
|
||||||
expire = datetime.now(UTC) + timedelta(days=30)
|
expire = datetime.now(UTC) + timedelta(days=30)
|
||||||
to_encode.update({"exp": expire})
|
to_encode.update({"exp": expire})
|
||||||
encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, settings.ALGORITHM)
|
encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, settings.ALGORITHM)
|
||||||
return encoded_jwt
|
return encoded_jwt
|
||||||
|
|
||||||
@staticmethod
|
def encode_invitation_token(user_data: SInvitationData) -> str:
|
||||||
def encode_invitation_token(user_data: SInvitationData) -> str:
|
|
||||||
invitation_token = cipher_suite.encrypt(user_data.model_dump_json().encode())
|
invitation_token = cipher_suite.encrypt(user_data.model_dump_json().encode())
|
||||||
return invitation_token.decode()
|
return invitation_token.decode()
|
||||||
|
|
||||||
@staticmethod
|
def decode_invitation_token(invitation_token: str) -> SInvitationData:
|
||||||
def decode_invitation_token(invitation_token: str) -> SInvitationData:
|
|
||||||
try:
|
try:
|
||||||
user_code = invitation_token.encode()
|
user_code = invitation_token.encode()
|
||||||
user_data = cipher_suite.decrypt(user_code)
|
user_data = cipher_suite.decrypt(user_code)
|
||||||
|
@ -50,13 +45,11 @@ class AuthService:
|
||||||
except InvalidToken:
|
except InvalidToken:
|
||||||
raise WrongCodeException
|
raise WrongCodeException
|
||||||
|
|
||||||
@staticmethod
|
def encode_confirmation_token(confirmation_code: str) -> str:
|
||||||
def encode_confirmation_token(confirmation_code: str) -> str:
|
|
||||||
invitation_token = cipher_suite.encrypt(confirmation_code.encode())
|
invitation_token = cipher_suite.encrypt(confirmation_code.encode())
|
||||||
return invitation_token.decode()
|
return invitation_token.decode()
|
||||||
|
|
||||||
@staticmethod
|
def decode_confirmation_token(invitation_token: str) -> str:
|
||||||
def decode_confirmation_token(invitation_token: str) -> str:
|
|
||||||
try:
|
try:
|
||||||
user_code = invitation_token.encode()
|
user_code = invitation_token.encode()
|
||||||
confirmation_code = cipher_suite.decrypt(user_code).decode()
|
confirmation_code = cipher_suite.decrypt(user_code).decode()
|
||||||
|
@ -64,30 +57,26 @@ class AuthService:
|
||||||
except InvalidToken:
|
except InvalidToken:
|
||||||
raise WrongCodeException
|
raise WrongCodeException
|
||||||
|
|
||||||
@classmethod
|
def get_confirmation_code(user_code: str) -> str:
|
||||||
def get_confirmation_code(cls, user_code: str) -> str:
|
return user_code if len(user_code) == 6 else decode_confirmation_token(user_code)
|
||||||
return user_code if len(user_code) == 6 else cls.decode_confirmation_token(user_code)
|
|
||||||
|
|
||||||
@classmethod
|
async def authenticate_user(uow: UnitOfWork, email_or_username: str, password: str) -> SUser:
|
||||||
async def authenticate_user(cls, uow: UnitOfWork, email_or_username: str, password: str) -> SUser:
|
|
||||||
try:
|
try:
|
||||||
async with uow:
|
async with uow:
|
||||||
user = await uow.user.find_one_by_username_or_email(username=email_or_username, email=email_or_username)
|
user = await uow.user.find_one_by_username_or_email(username=email_or_username, email=email_or_username)
|
||||||
if not cls.verify_password(password, user.hashed_password):
|
if not verify_password(password, user.hashed_password):
|
||||||
raise IncorrectAuthDataException
|
raise IncorrectAuthDataException
|
||||||
return user
|
return user
|
||||||
except UserNotFoundException:
|
except UserNotFoundException:
|
||||||
raise IncorrectAuthDataException
|
raise IncorrectAuthDataException
|
||||||
|
|
||||||
@classmethod
|
async def check_verificated_user(uow: UnitOfWork, user_id: int) -> None:
|
||||||
async def check_verificated_user(cls, uow: UnitOfWork, user_id: int) -> None:
|
|
||||||
async with uow:
|
async with uow:
|
||||||
user = await uow.user.find_one(id=user_id)
|
user = await uow.user.find_one(id=user_id)
|
||||||
if user.role < settings.VERIFICATED_USER:
|
if user.role < settings.VERIFICATED_USER:
|
||||||
raise UserMustConfirmEmailException
|
raise UserMustConfirmEmailException
|
||||||
|
|
||||||
@classmethod
|
async def validate_user_access_to_chat(uow: UnitOfWork, user_id: int, chat_id: int) -> None:
|
||||||
async def validate_user_access_to_chat(cls, uow: UnitOfWork, user_id: int, chat_id: int) -> None:
|
|
||||||
try:
|
try:
|
||||||
async with uow:
|
async with uow:
|
||||||
await uow.chat.find_chat(chat_id=chat_id, user_id=user_id)
|
await uow.chat.find_chat(chat_id=chat_id, user_id=user_id)
|
||||||
|
|
|
@ -7,27 +7,22 @@ from app.chat.exceptions import UserDontHavePermissionException, UserCanNotReadT
|
||||||
from app.chat.shemas import SAllowedChats, SChangeData, SPinnedChats, SChat
|
from app.chat.shemas import SAllowedChats, SChangeData, SPinnedChats, SChat
|
||||||
from app.config import settings
|
from app.config import settings
|
||||||
from app.services.redis_service import RedisService
|
from app.services.redis_service import RedisService
|
||||||
from app.services.user_service import UserService
|
from app.services import user_service, auth_service
|
||||||
from app.utils.unit_of_work import UnitOfWork
|
from app.utils.unit_of_work import UnitOfWork
|
||||||
from app.users.schemas import SInvitationData
|
from app.users.schemas import SInvitationData
|
||||||
from app.services.auth_service import AuthService
|
|
||||||
|
|
||||||
|
|
||||||
class ChatService:
|
async def find_chat(uow: UnitOfWork, chat_id: int, user_id: int) -> SChat:
|
||||||
@staticmethod
|
|
||||||
async def find_chat(uow: UnitOfWork, chat_id: int, user_id: int) -> SChat:
|
|
||||||
async with uow:
|
async with uow:
|
||||||
chat = await uow.chat.find_chat(chat_id=chat_id, user_id=user_id)
|
chat = await uow.chat.find_chat(chat_id=chat_id, user_id=user_id)
|
||||||
return chat
|
return chat
|
||||||
|
|
||||||
@staticmethod
|
async def find_one(uow: UnitOfWork, chat_id: int) -> SChat:
|
||||||
async def find_one(uow: UnitOfWork, chat_id: int) -> SChat:
|
|
||||||
async with uow:
|
async with uow:
|
||||||
chat = await uow.chat.find_one(chat_id=chat_id)
|
chat = await uow.chat.find_one(chat_id=chat_id)
|
||||||
return chat
|
return chat
|
||||||
|
|
||||||
@staticmethod
|
async def get_all_chats(uow: UnitOfWork, user_id: int) -> SAllowedChats:
|
||||||
async def get_all_chats(uow: UnitOfWork, user_id: int) -> SAllowedChats:
|
|
||||||
try:
|
try:
|
||||||
async with RedisService() as redis:
|
async with RedisService() as redis:
|
||||||
allowed_chats = await redis.get_value(key=f"user_allowed_chats: {user_id}", model=SAllowedChats)
|
allowed_chats = await redis.get_value(key=f"user_allowed_chats: {user_id}", model=SAllowedChats)
|
||||||
|
@ -43,11 +38,10 @@ class ChatService:
|
||||||
)
|
)
|
||||||
return allowed_chats
|
return allowed_chats
|
||||||
|
|
||||||
@staticmethod
|
async def create_chat(uow: UnitOfWork, user_id: int, user_to_exclude_id: int, chat_name: str) -> int:
|
||||||
async def create_chat(uow: UnitOfWork, user_id: int, user_to_exclude_id: int, chat_name: str) -> int:
|
|
||||||
if user_id == user_to_exclude_id:
|
if user_id == user_to_exclude_id:
|
||||||
raise UserCanNotReadThisChatException
|
raise UserCanNotReadThisChatException
|
||||||
user_chat_for = await UserService.find_user(uow=uow, id=user_to_exclude_id)
|
user_chat_for = await user_service.find_user(uow=uow, id=user_to_exclude_id)
|
||||||
async with uow:
|
async with uow:
|
||||||
chat_id = await uow.chat.create_chat(
|
chat_id = await uow.chat.create_chat(
|
||||||
user_id=user_to_exclude_id,
|
user_id=user_to_exclude_id,
|
||||||
|
@ -63,9 +57,8 @@ class ChatService:
|
||||||
await uow.commit()
|
await uow.commit()
|
||||||
return chat_id
|
return chat_id
|
||||||
|
|
||||||
@classmethod
|
async def change_chat_data(uow: UnitOfWork, user_id: int, user_data: SChangeData) -> None:
|
||||||
async def change_chat_data(cls, uow: UnitOfWork, user_id: int, user_data: SChangeData) -> None:
|
chat = await find_chat(uow=uow, chat_id=user_data.chat_id, user_id=user_id)
|
||||||
chat = await cls.find_chat(uow=uow, chat_id=user_data.chat_id, user_id=user_id)
|
|
||||||
if chat.created_by != user_id:
|
if chat.created_by != user_id:
|
||||||
raise UserDontHavePermissionException
|
raise UserDontHavePermissionException
|
||||||
async with uow:
|
async with uow:
|
||||||
|
@ -78,17 +71,15 @@ class ChatService:
|
||||||
await redis.delete_key(key=f"user_allowed_chats: {user_id}")
|
await redis.delete_key(key=f"user_allowed_chats: {user_id}")
|
||||||
await uow.commit()
|
await uow.commit()
|
||||||
|
|
||||||
@staticmethod
|
def create_invitation_link(chat_id: int) -> str:
|
||||||
def create_invitation_link(chat_id: int) -> str:
|
|
||||||
invitation_data = SInvitationData.model_validate({"chat_id": chat_id})
|
invitation_data = SInvitationData.model_validate({"chat_id": chat_id})
|
||||||
invitation_token = AuthService.encode_invitation_token(invitation_data)
|
invitation_token = auth_service.encode_invitation_token(invitation_data)
|
||||||
invitation_link = urljoin(settings.INVITATION_LINK_HOST, f"/submitNewChat#code={invitation_token}")
|
invitation_link = urljoin(settings.INVITATION_LINK_HOST, f"/submitNewChat#code={invitation_token}")
|
||||||
return invitation_link
|
return invitation_link
|
||||||
|
|
||||||
@classmethod
|
async def invite_to_chat(uow: UnitOfWork, user_id: int, invitation_token: str) -> None:
|
||||||
async def invite_to_chat(cls, uow: UnitOfWork, user_id: int, invitation_token: str) -> None:
|
invitation_data = auth_service.decode_invitation_token(invitation_token)
|
||||||
invitation_data = AuthService.decode_invitation_token(invitation_token)
|
chat = await find_one(uow=uow, chat_id=invitation_data.chat_id)
|
||||||
chat = await cls.find_one(uow=uow, chat_id=invitation_data.chat_id)
|
|
||||||
if user_id == chat.chat_for:
|
if user_id == chat.chat_for:
|
||||||
raise UserCanNotReadThisChatException
|
raise UserCanNotReadThisChatException
|
||||||
async with uow:
|
async with uow:
|
||||||
|
@ -97,9 +88,8 @@ class ChatService:
|
||||||
await redis.delete_key(key=f"user_allowed_chats: {user_id}")
|
await redis.delete_key(key=f"user_allowed_chats: {user_id}")
|
||||||
await uow.commit()
|
await uow.commit()
|
||||||
|
|
||||||
@classmethod
|
async def delete_chat(uow: UnitOfWork, user_id: int, chat_id: int) -> None:
|
||||||
async def delete_chat(cls, uow: UnitOfWork, user_id: int, chat_id: int) -> None:
|
chat = await find_chat(uow=uow, chat_id=chat_id, user_id=user_id)
|
||||||
chat = await cls.find_chat(uow=uow, chat_id=chat_id, user_id=user_id)
|
|
||||||
if not user_id == chat.created_by:
|
if not user_id == chat.created_by:
|
||||||
raise UserDontHavePermissionException
|
raise UserDontHavePermissionException
|
||||||
async with uow:
|
async with uow:
|
||||||
|
@ -108,9 +98,8 @@ class ChatService:
|
||||||
await redis.delete_key(key=f"user_allowed_chats: {user_id}")
|
await redis.delete_key(key=f"user_allowed_chats: {user_id}")
|
||||||
await uow.commit()
|
await uow.commit()
|
||||||
|
|
||||||
@classmethod
|
async def delete_user_from_chat(uow: UnitOfWork, user_id: int, chat_id: int, user_id_for_delete: int) -> None:
|
||||||
async def delete_user_from_chat(cls, uow: UnitOfWork, user_id: int, chat_id: int, user_id_for_delete: int) -> None:
|
chat = await find_chat(uow=uow, chat_id=chat_id, user_id=user_id)
|
||||||
chat = await cls.find_chat(uow=uow, chat_id=chat_id, user_id=user_id)
|
|
||||||
if not user_id == chat.created_by:
|
if not user_id == chat.created_by:
|
||||||
raise UserDontHavePermissionException
|
raise UserDontHavePermissionException
|
||||||
async with uow:
|
async with uow:
|
||||||
|
@ -119,20 +108,17 @@ class ChatService:
|
||||||
await redis.delete_key(key=f"user_allowed_chats: {user_id_for_delete}")
|
await redis.delete_key(key=f"user_allowed_chats: {user_id_for_delete}")
|
||||||
await uow.commit()
|
await uow.commit()
|
||||||
|
|
||||||
@staticmethod
|
async def pin_chat(uow: UnitOfWork, user_id: int, chat_id: int) -> None:
|
||||||
async def pin_chat(uow: UnitOfWork, user_id: int, chat_id: int) -> None:
|
|
||||||
async with uow:
|
async with uow:
|
||||||
await uow.chat.pin_chat(chat_id=chat_id, user_id=user_id)
|
await uow.chat.pin_chat(chat_id=chat_id, user_id=user_id)
|
||||||
await uow.commit()
|
await uow.commit()
|
||||||
|
|
||||||
@staticmethod
|
async def unpin_chat(uow: UnitOfWork, user_id: int, chat_id: int) -> None:
|
||||||
async def unpin_chat(uow: UnitOfWork, user_id: int, chat_id: int) -> None:
|
|
||||||
async with uow:
|
async with uow:
|
||||||
await uow.chat.unpin_chat(chat_id=chat_id, user_id=user_id)
|
await uow.chat.unpin_chat(chat_id=chat_id, user_id=user_id)
|
||||||
await uow.commit()
|
await uow.commit()
|
||||||
|
|
||||||
@staticmethod
|
async def get_pinned_chats(uow: UnitOfWork, user_id: int) -> SPinnedChats:
|
||||||
async def get_pinned_chats(uow: UnitOfWork, user_id: int) -> SPinnedChats:
|
|
||||||
async with uow:
|
async with uow:
|
||||||
pinned_chats = await uow.chat.get_pinned_chats(user_id=user_id)
|
pinned_chats = await uow.chat.get_pinned_chats(user_id=user_id)
|
||||||
return pinned_chats
|
return pinned_chats
|
||||||
|
|
|
@ -6,9 +6,7 @@ from httpx import AsyncClient, Response
|
||||||
from app.config import settings
|
from app.config import settings
|
||||||
|
|
||||||
|
|
||||||
class ImageService:
|
async def upload_file(file: UploadFile, remote_server_url: str) -> Response:
|
||||||
@staticmethod
|
|
||||||
async def upload_file(file: UploadFile, remote_server_url: str) -> Response:
|
|
||||||
try:
|
try:
|
||||||
file_content = await file.read()
|
file_content = await file.read()
|
||||||
async with AsyncClient() as ac:
|
async with AsyncClient() as ac:
|
||||||
|
@ -23,10 +21,9 @@ class ImageService:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
@classmethod
|
async def upload_file_returning_str(file: UploadFile, sub_str: str) -> str:
|
||||||
async def upload_file_returning_str(cls, file: UploadFile, sub_str: str) -> str:
|
|
||||||
remote_server_url = urljoin(settings.IMAGE_UPLOAD_SERVER, sub_str)
|
remote_server_url = urljoin(settings.IMAGE_UPLOAD_SERVER, sub_str)
|
||||||
response = await cls.upload_file(file, remote_server_url)
|
response = await upload_file(file, remote_server_url)
|
||||||
image_url = response.json()["image_url"]
|
image_url = response.json()["image_url"]
|
||||||
image_url = urljoin(settings.IMAGE_UPLOAD_SERVER, image_url)
|
image_url = urljoin(settings.IMAGE_UPLOAD_SERVER, image_url)
|
||||||
return image_url
|
return image_url
|
||||||
|
|
|
@ -2,54 +2,49 @@ from datetime import datetime, UTC, 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, SSendMessage, SPinnedMessages, SMessageList, SMessageRaw, SMessageRawList
|
||||||
from app.services.user_service import UserService
|
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
|
||||||
|
|
||||||
|
|
||||||
class MessageService:
|
_users: dict[int, tuple[SUser, datetime]] = {}
|
||||||
users: dict[int, tuple[SUser, datetime]] = {}
|
|
||||||
|
|
||||||
@classmethod
|
async def _get_cached_user(uow: UnitOfWork, user_id: int) -> SUser:
|
||||||
async def _get_cached_user(cls, uow: UnitOfWork, user_id: int) -> SUser:
|
if user_id in _users and _users[user_id][1] > datetime.now(UTC):
|
||||||
if user_id in cls.users and cls.users[user_id][1] > datetime.now(UTC):
|
return _users[user_id][0]
|
||||||
return cls.users[user_id][0]
|
|
||||||
|
|
||||||
user = await UserService.find_user(uow=uow, id=user_id)
|
user = await user_service.find_user(uow=uow, id=user_id)
|
||||||
cls.users[user_id] = user, datetime.now(UTC) + timedelta(minutes=5)
|
_users[user_id] = user, datetime.now(UTC) + timedelta(minutes=5)
|
||||||
return user
|
return user
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def _add_avatar_image_and_username_to_message(cls, uow: UnitOfWork, message: SMessageRaw) -> SMessage:
|
async def _add_avatar_image_and_username_to_message(uow: UnitOfWork, message: SMessageRaw) -> SMessage:
|
||||||
user = await cls._get_cached_user(uow=uow, user_id=message.user_id)
|
user = await _get_cached_user(uow=uow, user_id=message.user_id)
|
||||||
message = message.model_dump()
|
message = message.model_dump()
|
||||||
message["avatar_image"] = str(user.avatar_image)
|
message["avatar_image"] = str(user.avatar_image)
|
||||||
message["username"] = user.username
|
message["username"] = user.username
|
||||||
return SMessage.model_validate(message)
|
return SMessage.model_validate(message)
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def _add_avatar_image_and_username_to_message_list(
|
async def _add_avatar_image_and_username_to_message_list(
|
||||||
cls,
|
|
||||||
uow: UnitOfWork,
|
uow: UnitOfWork,
|
||||||
messages: SMessageRawList,
|
messages: SMessageRawList,
|
||||||
) -> SMessageList:
|
) -> SMessageList:
|
||||||
return SMessageList.model_validate(
|
return SMessageList.model_validate(
|
||||||
{
|
{
|
||||||
"messages": [
|
"messages": [
|
||||||
await cls._add_avatar_image_and_username_to_message(uow=uow, message=message)
|
await _add_avatar_image_and_username_to_message(uow=uow, message=message)
|
||||||
for message in messages.message_raw_list
|
for message in messages.message_raw_list
|
||||||
] if messages.message_raw_list else None
|
] if messages.message_raw_list else None
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
async def send_message(
|
||||||
async def send_message(
|
|
||||||
cls,
|
|
||||||
uow: UnitOfWork,
|
uow: UnitOfWork,
|
||||||
user_id: int,
|
user_id: int,
|
||||||
chat_id: int,
|
chat_id: int,
|
||||||
message: SSendMessage,
|
message: SSendMessage,
|
||||||
) -> SMessage:
|
) -> SMessage:
|
||||||
async with uow:
|
async with uow:
|
||||||
if message.answer:
|
if message.answer:
|
||||||
answer_message = await uow.message.get_message_by_id(message_id=message.answer)
|
answer_message = await uow.message.get_message_by_id(message_id=message.answer)
|
||||||
|
@ -69,18 +64,16 @@ class MessageService:
|
||||||
message=message.message,
|
message=message.message,
|
||||||
image_url=message.image_url,
|
image_url=message.image_url,
|
||||||
)
|
)
|
||||||
raw_message = await uow.message.get_message_by_id(message_id=message_id)
|
|
||||||
new_message = await cls._add_avatar_image_and_username_to_message(uow=uow, message=raw_message)
|
new_message = await get_message_by_id(uow=uow, message_id=message_id)
|
||||||
|
|
||||||
return new_message
|
return new_message
|
||||||
|
|
||||||
@staticmethod
|
async def delete_message(uow: UnitOfWork, message_id: UUID) -> None:
|
||||||
async def delete_message(uow: UnitOfWork, message_id: UUID) -> None:
|
|
||||||
async with uow:
|
async with uow:
|
||||||
await uow.message.delete_message(message_id=message_id)
|
await uow.message.delete_message(message_id=message_id)
|
||||||
|
|
||||||
@staticmethod
|
async def edit_message(uow: UnitOfWork, message_id: UUID, new_message: str, new_image_url: str) -> None:
|
||||||
async def edit_message(uow: UnitOfWork, message_id: UUID, new_message: str, new_image_url: str) -> None:
|
|
||||||
async with uow:
|
async with uow:
|
||||||
await uow.message.edit_message(
|
await uow.message.edit_message(
|
||||||
message_id=message_id,
|
message_id=message_id,
|
||||||
|
@ -88,51 +81,51 @@ class MessageService:
|
||||||
new_image_url=new_image_url,
|
new_image_url=new_image_url,
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def pin_message(cls, uow: UnitOfWork, chat_id: int, user_id: int, message_id: UUID) -> SMessage:
|
async def pin_message(uow: UnitOfWork, chat_id: int, user_id: int, message_id: UUID) -> SMessage:
|
||||||
async with uow:
|
async with uow:
|
||||||
await uow.chat.pin_message(chat_id=chat_id, message_id=message_id, user_id=user_id)
|
await uow.chat.pin_message(chat_id=chat_id, message_id=message_id, user_id=user_id)
|
||||||
await uow.commit()
|
await uow.commit()
|
||||||
|
|
||||||
raw_message = await uow.message.get_message_by_id(message_id=message_id)
|
pinned_message = await get_message_by_id(uow=uow, message_id=message_id)
|
||||||
pinned_message = await cls._add_avatar_image_and_username_to_message(uow=uow, message=raw_message)
|
|
||||||
|
|
||||||
return pinned_message
|
return pinned_message
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
async def unpin_message(uow: UnitOfWork, chat_id: int, message_id: UUID) -> None:
|
async def unpin_message(uow: UnitOfWork, chat_id: int, message_id: UUID) -> None:
|
||||||
async with uow:
|
async with uow:
|
||||||
await uow.chat.unpin_message(chat_id=chat_id, message_id=message_id)
|
await uow.chat.unpin_message(chat_id=chat_id, message_id=message_id)
|
||||||
await uow.commit()
|
await uow.commit()
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def get_message_by_id(cls, uow: UnitOfWork, message_id: UUID) -> SMessage:
|
async def get_message_by_id(uow: UnitOfWork, message_id: UUID) -> SMessage:
|
||||||
async with uow:
|
async with uow:
|
||||||
raw_message = await uow.message.get_message_by_id(message_id=message_id)
|
raw_message = await uow.message.get_message_by_id(message_id=message_id)
|
||||||
message = await cls._add_avatar_image_and_username_to_message(uow=uow, message=raw_message)
|
message = await _add_avatar_image_and_username_to_message(uow=uow, message=raw_message)
|
||||||
return message
|
return message
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def get_pinned_messages(cls, uow: UnitOfWork, chat_id: int) -> SPinnedMessages:
|
async def get_pinned_messages(uow: UnitOfWork, chat_id: int) -> SPinnedMessages:
|
||||||
async with uow:
|
async with uow:
|
||||||
pinned_messages_ids = await uow.chat.get_pinned_messages_ids(chat_id=chat_id)
|
pinned_messages_ids = await uow.chat.get_pinned_messages_ids(chat_id=chat_id)
|
||||||
raw_messages = await uow.message.get_messages_by_ids(messages_ids=pinned_messages_ids)
|
raw_messages = await uow.message.get_messages_by_ids(messages_ids=pinned_messages_ids)
|
||||||
pinned_messages = await cls._add_avatar_image_and_username_to_message_list(uow=uow, messages=raw_messages)
|
|
||||||
|
pinned_messages = await _add_avatar_image_and_username_to_message_list(uow=uow, messages=raw_messages)
|
||||||
return SPinnedMessages.model_validate({"pinned_messages": pinned_messages.messages})
|
return SPinnedMessages.model_validate({"pinned_messages": pinned_messages.messages})
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def get_some_messages(
|
async def get_some_messages(
|
||||||
cls,
|
|
||||||
uow: UnitOfWork,
|
uow: UnitOfWork,
|
||||||
chat_id: int,
|
chat_id: int,
|
||||||
message_number_from: int,
|
message_number_from: int,
|
||||||
messages_to_get: int,
|
messages_to_get: int,
|
||||||
) -> SMessageList:
|
) -> SMessageList:
|
||||||
async with uow:
|
async with uow:
|
||||||
messages = await uow.message.get_some_messages(
|
messages = await uow.message.get_some_messages(
|
||||||
chat_id=chat_id,
|
chat_id=chat_id,
|
||||||
message_number_from=message_number_from,
|
message_number_from=message_number_from,
|
||||||
messages_to_get=messages_to_get,
|
messages_to_get=messages_to_get,
|
||||||
)
|
)
|
||||||
messages = await cls._add_avatar_image_and_username_to_message_list(uow=uow, messages=messages)
|
|
||||||
|
messages = await _add_avatar_image_and_username_to_message_list(uow=uow, messages=messages)
|
||||||
return messages
|
return messages
|
||||||
|
|
|
@ -4,17 +4,15 @@ 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.services.redis_service import RedisService
|
from app.tasks import tasks
|
||||||
from app.tasks.tasks import generate_confirmation_code, send_confirmation_email, send_data_change_email
|
|
||||||
from app.utils.unit_of_work import UnitOfWork
|
from app.utils.unit_of_work import UnitOfWork
|
||||||
from app.users.exceptions import PasswordsMismatchException, WrongCodeException
|
from app.users.exceptions import PasswordsMismatchException, WrongCodeException
|
||||||
from app.users.schemas import SUser, SUsers, SUserRegister, SConfirmationData, SUserAvatars, SUserChangeData
|
from app.users.schemas import SUser, SUsers, SUserRegister, SConfirmationData, SUserAvatars, SUserChangeData
|
||||||
from app.services.auth_service import AuthService
|
from app.services import auth_service
|
||||||
|
from app.services.redis_service import RedisService
|
||||||
|
|
||||||
|
|
||||||
class UserService:
|
async def find_user(uow: UnitOfWork, **find_by) -> SUser:
|
||||||
@staticmethod
|
|
||||||
async def find_user(uow: UnitOfWork, **find_by) -> SUser:
|
|
||||||
try:
|
try:
|
||||||
async with RedisService(is_raise=True) as redis:
|
async with RedisService(is_raise=True) as redis:
|
||||||
user = await redis.get_value(key=f"user: {find_by}", model=SUser)
|
user = await redis.get_value(key=f"user: {find_by}", model=SUser)
|
||||||
|
@ -30,18 +28,16 @@ class UserService:
|
||||||
)
|
)
|
||||||
return user
|
return user
|
||||||
|
|
||||||
@staticmethod
|
async def find_all(uow: UnitOfWork, username: str) -> SUsers:
|
||||||
async def find_all(uow: UnitOfWork, username: str) -> SUsers:
|
|
||||||
async with uow:
|
async with uow:
|
||||||
users = await uow.user.find_all(username=username)
|
users = await uow.user.find_all(username=username)
|
||||||
return users
|
return users
|
||||||
|
|
||||||
@staticmethod
|
async def add_user(uow: UnitOfWork, user_data: SUserRegister) -> SUser:
|
||||||
async def add_user(uow: UnitOfWork, user_data: SUserRegister) -> SUser:
|
|
||||||
if user_data.password != user_data.password2:
|
if user_data.password != user_data.password2:
|
||||||
raise PasswordsMismatchException
|
raise PasswordsMismatchException
|
||||||
|
|
||||||
hashed_password = AuthService.get_password_hash(user_data.password)
|
hashed_password = auth_service.get_password_hash(user_data.password)
|
||||||
async with uow:
|
async with uow:
|
||||||
user = await uow.user.add(
|
user = await uow.user.add(
|
||||||
email=user_data.email,
|
email=user_data.email,
|
||||||
|
@ -53,9 +49,8 @@ class UserService:
|
||||||
await uow.commit()
|
await uow.commit()
|
||||||
return user
|
return user
|
||||||
|
|
||||||
@staticmethod
|
async def send_confirmation_email(user: SUser, mail_type: str, email: str | None = None) -> None:
|
||||||
async def send_confirmation_email(user: SUser, mail_type: str, email: str | None = None) -> None:
|
user_code = tasks.generate_confirmation_code()
|
||||||
user_code = generate_confirmation_code()
|
|
||||||
async with RedisService(is_raise=True) as redis:
|
async with RedisService(is_raise=True) as redis:
|
||||||
await redis.delete_key(key=f"user_verification_code: {user.id}")
|
await redis.delete_key(key=f"user_verification_code: {user.id}")
|
||||||
await redis.set_key(key=f"user_verification_code: {user.id}", expire_time=timedelta(minutes=5), value=user_code)
|
await redis.set_key(key=f"user_verification_code: {user.id}", expire_time=timedelta(minutes=5), value=user_code)
|
||||||
|
@ -69,10 +64,9 @@ class UserService:
|
||||||
"type": mail_type,
|
"type": mail_type,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
send_confirmation_email.delay(user_mail_data.model_dump())
|
tasks.send_confirmation_email.delay(user_mail_data.model_dump())
|
||||||
|
|
||||||
@staticmethod
|
async def verificate_user(uow: UnitOfWork, user: SUser, confirmation_code: str) -> None:
|
||||||
async def verificate_user(uow: UnitOfWork, user: SUser, confirmation_code: str) -> None:
|
|
||||||
try:
|
try:
|
||||||
async with RedisService(is_raise=True) as redis:
|
async with RedisService(is_raise=True) as redis:
|
||||||
verification_code = await redis.get_value(key=f"user_verification_code: {user.id}")
|
verification_code = await redis.get_value(key=f"user_verification_code: {user.id}")
|
||||||
|
@ -86,14 +80,12 @@ class UserService:
|
||||||
await redis.delete_key(key=f"user: {dict(id=user.id)}")
|
await redis.delete_key(key=f"user: {dict(id=user.id)}")
|
||||||
await uow.commit()
|
await uow.commit()
|
||||||
|
|
||||||
@staticmethod
|
async def get_user_avatars_history(uow: UnitOfWork, user_id: int) -> SUserAvatars:
|
||||||
async def get_user_avatars_history(uow: UnitOfWork, user_id: int) -> SUserAvatars:
|
|
||||||
async with uow:
|
async with uow:
|
||||||
user_avatars = await uow.user.get_user_avatars(user_id=user_id)
|
user_avatars = await uow.user.get_user_avatars(user_id=user_id)
|
||||||
return user_avatars
|
return user_avatars
|
||||||
|
|
||||||
@staticmethod
|
async def change_data(uow: UnitOfWork, user: SUser, user_data: SUserChangeData) -> None:
|
||||||
async def change_data(uow: UnitOfWork, user: SUser, user_data: SUserChangeData) -> None:
|
|
||||||
try:
|
try:
|
||||||
async with RedisService(is_raise=True) as redis:
|
async with RedisService(is_raise=True) as redis:
|
||||||
verification_code = await redis.get_value(key=f"user_verification_code: {user.id}")
|
verification_code = await redis.get_value(key=f"user_verification_code: {user.id}")
|
||||||
|
@ -102,7 +94,7 @@ class UserService:
|
||||||
if verification_code != user_data.verification_code:
|
if verification_code != user_data.verification_code:
|
||||||
raise WrongCodeException
|
raise WrongCodeException
|
||||||
hashed_password = (
|
hashed_password = (
|
||||||
AuthService.get_password_hash(user_data.new_password) if user_data.new_password else user.hashed_password
|
auth_service.get_password_hash(user_data.new_password) if user_data.new_password else user.hashed_password
|
||||||
)
|
)
|
||||||
async with uow:
|
async with uow:
|
||||||
await uow.user.change_data(
|
await uow.user.change_data(
|
||||||
|
@ -118,4 +110,4 @@ class UserService:
|
||||||
async with RedisService() as redis:
|
async with RedisService() as redis:
|
||||||
await redis.delete_key(key=f"user: {dict(id=user.id)}")
|
await redis.delete_key(key=f"user: {dict(id=user.id)}")
|
||||||
|
|
||||||
send_data_change_email.delay(user_data.username, user_data.email)
|
tasks.send_data_change_email.delay(user_data.username, user_data.email)
|
||||||
|
|
|
@ -13,7 +13,7 @@ from app.tasks.email_templates import (
|
||||||
create_data_change_confirmation_email,
|
create_data_change_confirmation_email,
|
||||||
create_data_change_email,
|
create_data_change_email,
|
||||||
)
|
)
|
||||||
from app.services.auth_service import AuthService
|
from app.services import auth_service
|
||||||
from app.users.schemas import SConfirmationData
|
from app.users.schemas import SConfirmationData
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ def generate_confirmation_code(length=6) -> str:
|
||||||
@celery.task
|
@celery.task
|
||||||
def send_confirmation_email(user_data: dict) -> None:
|
def send_confirmation_email(user_data: dict) -> None:
|
||||||
user_data = SConfirmationData.model_validate(user_data)
|
user_data = SConfirmationData.model_validate(user_data)
|
||||||
invitation_token = AuthService.encode_confirmation_token(user_data.confirmation_code)
|
invitation_token = auth_service.encode_confirmation_token(user_data.confirmation_code)
|
||||||
|
|
||||||
confirmation_link = urljoin(settings.INVITATION_LINK_HOST, f"/submitEmail#code={invitation_token}")
|
confirmation_link = urljoin(settings.INVITATION_LINK_HOST, f"/submitEmail#code={invitation_token}")
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,9 @@ from random import randrange
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, status
|
from fastapi import APIRouter, Depends, status
|
||||||
|
|
||||||
from app.services.user_service import UserService
|
from app.services import user_service, auth_service
|
||||||
from app.users.exceptions import UserAlreadyExistsException, PasswordAlreadyInUseException, UserNotFoundException
|
from app.users.exceptions import UserAlreadyExistsException, PasswordAlreadyInUseException, UserNotFoundException
|
||||||
from app.utils.unit_of_work import UnitOfWork
|
from app.utils.unit_of_work import UnitOfWork
|
||||||
from app.services.auth_service import AuthService
|
|
||||||
from app.dependencies import get_current_user
|
from app.dependencies import get_current_user
|
||||||
from app.users.schemas import (
|
from app.users.schemas import (
|
||||||
SUserLogin,
|
SUserLogin,
|
||||||
|
@ -39,7 +38,7 @@ router = APIRouter(prefix="/users", tags=["Пользователи"])
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def get_all_users(filter_by=Depends(SGetUsersFilter), uow=Depends(UnitOfWork)):
|
async def get_all_users(filter_by=Depends(SGetUsersFilter), uow=Depends(UnitOfWork)):
|
||||||
users = await UserService.find_all(uow=uow, username=filter_by.username)
|
users = await user_service.find_all(uow=uow, username=filter_by.username)
|
||||||
return users
|
return users
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,7 +59,7 @@ async def get_all_users(filter_by=Depends(SGetUsersFilter), uow=Depends(UnitOfWo
|
||||||
)
|
)
|
||||||
async def check_existing_user(user_filter: SUserFilter, uow=Depends(UnitOfWork)):
|
async def check_existing_user(user_filter: SUserFilter, uow=Depends(UnitOfWork)):
|
||||||
try:
|
try:
|
||||||
await UserService.find_user(uow=uow, **user_filter.model_dump(exclude_none=True))
|
await user_service.find_user(uow=uow, **user_filter.model_dump(exclude_none=True))
|
||||||
raise UserAlreadyExistsException
|
raise UserAlreadyExistsException
|
||||||
except UserNotFoundException:
|
except UserNotFoundException:
|
||||||
pass
|
pass
|
||||||
|
@ -103,10 +102,10 @@ async def check_existing_password(_: SUserPassword):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def register_user(user_data: SUserRegister, uow=Depends(UnitOfWork)):
|
async def register_user(user_data: SUserRegister, uow=Depends(UnitOfWork)):
|
||||||
user = await UserService.add_user(uow=uow, user_data=user_data)
|
user = await user_service.add_user(uow=uow, user_data=user_data)
|
||||||
await UserService.send_confirmation_email(user=user, mail_type="registration")
|
await user_service.send_confirmation_email(user=user, mail_type="registration")
|
||||||
|
|
||||||
access_token = AuthService.create_access_token({"sub": str(user.id)})
|
access_token = auth_service.create_access_token({"sub": str(user.id)})
|
||||||
return {"authorization": f"Bearer {access_token}"}
|
return {"authorization": f"Bearer {access_token}"}
|
||||||
|
|
||||||
|
|
||||||
|
@ -138,7 +137,7 @@ async def register_user(user_data: SUserRegister, uow=Depends(UnitOfWork)):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def resend_email_verification(user: SUser = Depends(get_current_user)):
|
async def resend_email_verification(user: SUser = Depends(get_current_user)):
|
||||||
await UserService.send_confirmation_email(user=user, mail_type="registration")
|
await user_service.send_confirmation_email(user=user, mail_type="registration")
|
||||||
|
|
||||||
|
|
||||||
@router.post(
|
@router.post(
|
||||||
|
@ -169,8 +168,8 @@ async def resend_email_verification(user: SUser = Depends(get_current_user)):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def email_verification(user_code: SUserCode, user: SUser = Depends(get_current_user), uow=Depends(UnitOfWork)):
|
async def email_verification(user_code: SUserCode, user: SUser = Depends(get_current_user), uow=Depends(UnitOfWork)):
|
||||||
confirmation_code = AuthService.get_confirmation_code(user_code.user_code)
|
confirmation_code = auth_service.get_confirmation_code(user_code.user_code)
|
||||||
await UserService.verificate_user(uow=uow, user=user, confirmation_code=confirmation_code)
|
await user_service.verificate_user(uow=uow, user=user, confirmation_code=confirmation_code)
|
||||||
|
|
||||||
|
|
||||||
@router.post(
|
@router.post(
|
||||||
|
@ -193,12 +192,12 @@ async def email_verification(user_code: SUserCode, user: SUser = Depends(get_cur
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def login_user(user_data: SUserLogin, uow=Depends(UnitOfWork)):
|
async def login_user(user_data: SUserLogin, uow=Depends(UnitOfWork)):
|
||||||
user = await AuthService.authenticate_user(
|
user = await auth_service.authenticate_user(
|
||||||
uow=uow,
|
uow=uow,
|
||||||
email_or_username=user_data.email_or_username,
|
email_or_username=user_data.email_or_username,
|
||||||
password=user_data.password,
|
password=user_data.password,
|
||||||
)
|
)
|
||||||
access_token = AuthService.create_access_token({"sub": str(user.id)})
|
access_token = auth_service.create_access_token({"sub": str(user.id)})
|
||||||
return {"authorization": f"Bearer {access_token}"}
|
return {"authorization": f"Bearer {access_token}"}
|
||||||
|
|
||||||
|
|
||||||
|
@ -253,7 +252,7 @@ async def get_user(user: SUser = Depends(get_current_user)):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def get_user_avatars_history(user=Depends(get_current_user), uow=Depends(UnitOfWork)):
|
async def get_user_avatars_history(user=Depends(get_current_user), uow=Depends(UnitOfWork)):
|
||||||
user_avatars = await UserService.get_user_avatars_history(uow=uow, user_id=user.id)
|
user_avatars = await user_service.get_user_avatars_history(uow=uow, user_id=user.id)
|
||||||
return user_avatars
|
return user_avatars
|
||||||
|
|
||||||
|
|
||||||
|
@ -281,7 +280,7 @@ async def get_user_avatars_history(user=Depends(get_current_user), uow=Depends(U
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def send_confirmation_code(user_data: SUserSendConfirmationCode, user: SUser = Depends(get_current_user)):
|
async def send_confirmation_code(user_data: SUserSendConfirmationCode, user: SUser = Depends(get_current_user)):
|
||||||
await UserService.send_confirmation_email(user=user, mail_type="data_change_confirmation", email=user_data.email)
|
await user_service.send_confirmation_email(user=user, mail_type="data_change_confirmation", email=user_data.email)
|
||||||
|
|
||||||
|
|
||||||
@router.post(
|
@router.post(
|
||||||
|
@ -316,4 +315,4 @@ async def change_user_data(
|
||||||
user: SUser = Depends(get_current_user),
|
user: SUser = Depends(get_current_user),
|
||||||
uow=Depends(UnitOfWork),
|
uow=Depends(UnitOfWork),
|
||||||
):
|
):
|
||||||
await UserService.change_data(uow=uow, user=user, user_data=user_data)
|
await user_service.change_data(uow=uow, user=user, user_data=user_data)
|
||||||
|
|
|
@ -42,7 +42,7 @@ target-version = "py312"
|
||||||
[lint]
|
[lint]
|
||||||
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
|
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
|
||||||
select = ["F", "E", "W", "C"]
|
select = ["F", "E", "W", "C"]
|
||||||
ignore = ["W191", "W391", "C901"]
|
ignore = ["W191", "W391", "C901", "C408"]
|
||||||
|
|
||||||
# Allow fix for all enabled rules (when `--fix`) is provided.
|
# Allow fix for all enabled rules (when `--fix`) is provided.
|
||||||
fixable = ["ALL"]
|
fixable = ["ALL"]
|
||||||
|
|
Loading…
Add table
Reference in a new issue