From 715600d8fee7fc054e89bd854a051359850cb442 Mon Sep 17 00:00:00 2001 From: Shopiley Date: Wed, 25 Jan 2023 21:35:39 +0100 Subject: [PATCH 01/11] feat: update threads endpoint --- backend/.pre-commit-config.yaml | 6 +- backend/endpoints/threads.py | 264 ++++++++++++++++++-------------- backend/utils/db.py | 22 ++- backend/utils/message_utils.py | 32 ++-- backend/utils/threads_utils.py | 72 +++++++-- 5 files changed, 247 insertions(+), 149 deletions(-) diff --git a/backend/.pre-commit-config.yaml b/backend/.pre-commit-config.yaml index 981ba454..0cb07d8d 100644 --- a/backend/.pre-commit-config.yaml +++ b/backend/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: pretty-format-json - repo: https://github.com/psf/black - rev: 21.9b0 + rev: 22.3.0 hooks: - id: black @@ -45,3 +45,7 @@ repos: - --disable=R0902 - --disable=R0903 - --disable=C0103 + - --disable=R0913 + - --disable=C0327 + - --disable=C0305 + - --disable=WO622 diff --git a/backend/endpoints/threads.py b/backend/endpoints/threads.py index c291bab0..b15d4757 100644 --- a/backend/endpoints/threads.py +++ b/backend/endpoints/threads.py @@ -1,14 +1,12 @@ - from fastapi import APIRouter, BackgroundTasks, HTTPException, status -from schema.message import Thread, MessageRequest, Message +from fastapi.responses import JSONResponse +from schema.message import MessageRequest from schema.response import ResponseModel from schema.thread_response import ThreadResponse -from fastapi.responses import JSONResponse from utils.centrifugo import Events, centrifugo_client -from utils.message_utils import get_message, get_room_messages, update_message_threads as edit_message_threads -from utils.room_utils import get_org_rooms -from utils.threads_utils import get_message_threads, add_message_to_thread_list -import json +from utils.message_utils import get_message +from utils.threads_utils import add_message_to_thread_list, get_message_threads +from utils.threads_utils import update_thread_message as edit_message_threads router = APIRouter() @@ -23,47 +21,44 @@ }, ) async def send_thread_message( - org_id: str, - room_id: str, - message_id: str, - request: MessageRequest + org_id: str, room_id: str, message_id: str, request: MessageRequest ): """Adds a thread to a parent message. - Edits an existing message document in the messages database collection while - publishing to all members of the room in the background. + Edits an existing message document in the messages database collection while + publishing to all members of the room in the background. - Args: - org_id: A unique identifier of the organization. - room_id: A unique identifier of the room. - message_id: A unique identifier of the message that is being edited. - request: A pydantic schema that defines the message request parameters. + Args: + org_id: A unique identifier of the organization. + room_id: A unique identifier of the room. + message_id: A unique identifier of the message that is being edited. + request: A pydantic schema that defines the message request parameters. - Returns: - A dict containing data about the message that was edited. + Returns: + A dict containing data about the message that was edited. + + { + "status": 201, + "event": "thread_message_create", + "thread_id": "bd830644-2205-11ec-9853-2ff0a732e3ef", + "room_id": "614e1606f31a74e068e4d2e2", + "message_id": "6155a0e6be7f31a9275a1eca", + "data": { + "sender_id": "61467e181ab13c00bcc15607", + "message": "Checking out the threads", + "created_at": "2021-09-30T15:41:45.685000Z" + } + } + + Raises: + HTTPException [401]: You are not authorized to edit this message. + HTTPException [404]: Message not found. + HTTPException [424]: Message not edited. + """ - { - "status": 201, - "event": "thread_message_create", - "thread_id": "bd830644-2205-11ec-9853-2ff0a732e3ef", - "room_id": "614e1606f31a74e068e4d2e2", - "message_id": "6155a0e6be7f31a9275a1eca", - "data": { - "sender_id": "61467e181ab13c00bcc15607", - "message": "Checking out the threads", - "created_at": "2021-09-30T15:41:45.685000Z" - } - } - - Raises: - HTTPException [401]: You are not authorized to edit this message. - HTTPException [404]: Message not found. - HTTPException [424]: Message not edited. - """ - response, thread_message = await add_message_to_thread_list( - org_id, room_id, message_id, request - ) + org_id, room_id, message_id, request + ) if response is None: raise HTTPException( @@ -72,12 +67,12 @@ async def send_thread_message( ) result = { - "status": 201, - "event": "thread_message_create", - "room_id": room_id, - "message_id": message_id, - "data": thread_message - } + "status": 201, + "event": "thread_message_create", + "room_id": room_id, + "message_id": message_id, + "data": thread_message, + } return JSONResponse( content=result, @@ -148,14 +143,13 @@ async def get_thread_messages(org_id: str, room_id: str, message_id: str): ) return JSONResponse( - content=ResponseModel.success( - data=response, message="Messages retrieved"), + content=ResponseModel.success(data=response, message="Messages retrieved"), status_code=status.HTTP_200_OK, ) @router.put( - "/org/{org_id}/rooms/{room_id}/messages/{message_id}/threads", + "/org/{org_id}/rooms/{room_id}/messages/{message_id}/threads/{thread_id}", response_model=ResponseModel, status_code=status.HTTP_200_OK, responses={ @@ -164,96 +158,144 @@ async def get_thread_messages(org_id: str, room_id: str, message_id: str): 424: {"description": "Message not edited"}, }, ) -async def update_threads_message( +async def update_thread_message( org_id: str, room_id: str, message_id: str, + thread_id: str, request: MessageRequest, background_tasks: BackgroundTasks, ): - payload = request.dict() - loadedMessage = await get_message(org_id, room_id, message_id) - loadedMessageThread = loadedMessage['threads'] - thread_to_add = {"threads": [payload, *loadedMessageThread]} + """(Still under development) Updates a thread message in a thread in a room. - if not loadedMessage: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, detail="Message not found" - ) + Edits an existing message document in the messages database collection while + publishing to all members of the room in the background. + + Args: + org_id: A unique identifier of the organization. + room_id: A unique identifier of the room. + message_id: A unique identifier of the message that is being edited. + thread_id: A unique identifier of the thread that is being edited. + request: A pydantic schema that defines the message request parameters. + background_tasks: A background task for publishing to all + members of the room. + + Returns: + A dict containing data about the thread that was edited. + + { + "_id": "61c3aa9478fb01b18fac1465", + "created_at": "2021-12-22 22:38:33.075643", + "edited": true, + "emojis": [ + { + "count": 1, + "emoji": "👹", + "name": "frown", + "reactedUsersId": [ + "619ba4671a5f54782939d385" + ] + } + ], + "files": [], + "org_id": "619ba4671a5f54782939d384", + "richUiData": { + "blocks": [ + { + "data": {}, + "depth": 0, + "entityRanges": [], + "inlineStyleRanges": [], + "key": "eljik", + "text": "HI, I'm mark.. new here", + "type": "unstyled" + } + ], + "entityMap": {} + }, + "room_id": "619e28c31a5f54782939d59a", + "saved_by": [], + "sender_id": "619ba4671a5f54782939d385", + "text": "string", + } + + Raises: + HTTPException [401]: You are not authorized to edit this message. + HTTPException [404]: Message not found. + HTTPException [424]: Message not edited. + """ - added_thread_message = await edit_message_threads(org_id, message_id, thread_to_add) + message = await get_message(org_id, room_id, message_id) + payload = request.dict(exclude_unset=True) - if not added_thread_message: + updated_thread_message = await edit_message_threads( + org_id, room_id, message_id, thread_id, payload + ) + + if not updated_thread_message: raise HTTPException( - status_code=status.HTTP_424_FAILED_DEPENDENCY, - detail={"thread not added": added_thread_message}, + status_code=status.HTTP_424_FAILED_DEPENDENCY, detail="thread not updated" ) - # payload["edited"] = True - loadedMessage.update(thread_to_add) - # Publish to centrifugo in the background. background_tasks.add_task( - centrifugo_client.publish, - room_id, - Events.MESSAGE_UPDATE, - loadedMessage + centrifugo_client.publish, room_id, Events.MESSAGE_UPDATE, message ) return JSONResponse( - content=ResponseModel.success( - data=loadedMessage, message="Thread Added"), + content=ResponseModel.success(data=message, message="Thread Updated"), status_code=status.HTTP_200_OK, ) -@router.get( - "/org/{org_id}/member/{member_id}/threads", - response_model=ResponseModel, - status_code=status.HTTP_200_OK, - responses={424: {"detail": "ZC Core failed"}}, -) -async def get_threads(org_id: str, member_id: str, page: int = 1, size: int = 15): - room_response = await get_org_rooms(org_id=org_id, member_id=member_id) +# @router.get( +# "/org/{org_id}/member/{member_id}/threads", +# response_model=ResponseModel, +# status_code=status.HTTP_200_OK, +# responses={424: {"detail": "ZC Core failed"}}, +# ) +# async def get_threads(org_id: str, member_id: str, page: int = 1, size: int = 15): - if room_response == []: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail="Member does not exist or Org not found" - ) +# room_response = await get_org_rooms(org_id=org_id, member_id=member_id) - if room_response is None: - raise HTTPException( - status_code=status.HTTP_424_FAILED_DEPENDENCY, - detail="Zc Core failed" - ) +# if room_response == []: +# raise HTTPException( +# status_code=status.HTTP_404_NOT_FOUND, +# detail="Member does not exist or Org not found" +# ) - room_ids = [] +# if room_response is None: +# raise HTTPException( +# status_code=status.HTTP_424_FAILED_DEPENDENCY, +# detail="Zc Core failed" +# ) - for room in room_response: - room_ids.append(room['_id']) +# room_ids = [] - for room_id in room_ids: - single_room_resp = await get_room_messages(org_id, room_id, page, size) - if single_room_resp == []: - # Room not found - pass +# for room in room_response: +# room_ids.append(room['_id']) - if single_room_resp is None: - # Zc Core failed - pass +# for room_id in room_ids: +# single_room_resp = await get_room_messages(org_id, room_id, page, size) +# if single_room_resp == []: +# # Room not found +# pass - # Gotten Single Room +# if single_room_resp is None: +# # Zc Core failed +# pass - messages_w_thread = [] +# # Gotten Single Room - for messages in single_room_resp: - if messages['threads'] != []: - messages_w_thread.append(messages) +# messages_w_thread = [] - return JSONResponse( - content=ResponseModel.success( - data=messages_w_thread, message="Rooms retrieved"), - status_code=status.HTTP_200_OK, - ) +# for messages in single_room_resp: +# if messages['threads'] != []: +# messages_w_thread.append(messages) + +# return JSONResponse( +# content=ResponseModel.success( +# data=messages_w_thread, message="Rooms retrieved"), +# status_code=status.HTTP_200_OK, +# ) diff --git a/backend/utils/db.py b/backend/utils/db.py index 54f11d88..d71aa8fe 100644 --- a/backend/utils/db.py +++ b/backend/utils/db.py @@ -45,8 +45,7 @@ def __init__(self, organization_id: str) -> None: self.organization_id = organization_id try: - response = requests.get( - url=f"{settings.BASE_URL}/marketplace/plugins") + response = requests.get(url=f"{settings.BASE_URL}/marketplace/plugins") response.raise_for_status() except requests.Timeout as timed_out_error: raise HTTPException( @@ -124,10 +123,16 @@ async def write(self, collection_name: str, data: dict[str, Any]) -> Any: return None if response.status_code == 201: return response.json() + return {"status_code": response.status_code, "message": response.json()} async def update( - self, collection_name: str, document_id: str, data: dict[str, Any] + self, + collection_name: str, + document_id: str, + data: Optional[dict[str, Any]] = None, + raw_query: Optional[dict[str, Any]] = None, + query: Optional[dict[str, Any]] = None, ) -> Any: """Updates data to zc_messaging collections. @@ -166,12 +171,18 @@ async def update( RequestException: Unable to connect to zc_core """ + # to ensure only either one of raw_query or data is sent + if data and raw_query: + raise Exception("Either one of data or raw_query is expected") + body = { "plugin_id": self.plugin_id, "organization_id": self.organization_id, "collection_name": collection_name, "object_id": document_id, "payload": data, + "raw_query": raw_query, + "filter": query, } try: @@ -180,6 +191,7 @@ async def update( return None if response.status_code == 200: return response.json() + print({"status_code": response.status_code, "message": response.json()}) return {"status_code": response.status_code, "message": response.json()} async def read( @@ -188,7 +200,7 @@ async def read( resource_id: Optional[str] = None, query: Optional[dict[str, Any]] = None, options: Optional[dict[str, Any]] = None, - raw_query: Optional [dict[str, Any]] = None + raw_query: Optional[dict[str, Any]] = None, ) -> Any: """Reads data from zc_messaging collections. @@ -238,7 +250,7 @@ async def read( "object_id": resource_id, "filter": query, "options": options, - "raw_query": raw_query + "raw_query": raw_query, } try: diff --git a/backend/utils/message_utils.py b/backend/utils/message_utils.py index e78aac0b..d00a0baf 100644 --- a/backend/utils/message_utils.py +++ b/backend/utils/message_utils.py @@ -1,5 +1,6 @@ from datetime import datetime from typing import Any, Optional + from config.settings import settings from schema.message import Message from utils.db import DataStorage @@ -7,7 +8,9 @@ async def get_org_messages( - org_id: str, page: int, size: int, + org_id: str, + page: int, + size: int, ) -> Optional[list[dict[str, Any]]]: """Gets all messages sent in an organization. @@ -81,11 +84,11 @@ async def get_room_messages( DB = DataStorage(org_id) skip = await off_set(page, size) - options = {"limit": size, "skip": skip, "sort": { "created_at": -1}} + options = {"limit": size, "skip": skip, "sort": {"created_at": -1}} raw_query = {} if created_at: date = datetime.datetime.now() - datetime.timedelta(days=created_at) - raw_query ={ "room_id": room_id, "created_at": { "$gte":str(date).split()[0]} } + raw_query = {"room_id": room_id, "created_at": {"$gte": str(date).split()[0]}} else: raw_query = {"room_id": room_id} response = await DB.read( @@ -176,21 +179,8 @@ async def update_message( db = DataStorage(org_id) message["edited"] = True - return await db.update(settings.MESSAGE_COLLECTION, message_id, message) - - -async def update_message_threads( - org_id: str, message_id: str, message: dict[str, Any] -) -> dict[str, Any]: - """Updates a message document in the database. - Args: - org_id (str): The organization id where the message is being updated. - message_id (str): The id of the message to be edited. - message (dict[str, Any]): The new data. - Returns: - dict[str, Any]: The response returned by DataStorage's update method. - """ - - db = DataStorage(org_id) - - return await db.update(settings.MESSAGE_COLLECTION, message_id, message) + return await db.update( + collection_name=settings.MESSAGE_COLLECTION, + document_id=message_id, + data=message, + ) diff --git a/backend/utils/threads_utils.py b/backend/utils/threads_utils.py index e622f689..30fdbbf9 100644 --- a/backend/utils/threads_utils.py +++ b/backend/utils/threads_utils.py @@ -1,16 +1,16 @@ import uuid -from fastapi import APIRouter, BackgroundTasks, HTTPException, status -import json -from typing import Any, Optional -from schema.message import Thread -from schema.message import Message, MessageRequest from datetime import datetime -from utils.db import DataStorage -from utils.message_utils import get_message ,update_message +from typing import Any + from config.settings import settings +from fastapi import HTTPException, status +from schema.message import Thread +from utils.db import DataStorage +from utils.message_utils import get_message, update_message # List all messages in a thread + async def get_message_threads(org_id, room_id, message_id): """Retrives all the messages in a thread. @@ -18,7 +18,7 @@ async def get_message_threads(org_id, room_id, message_id): org_id (str): The organization id where the message is being updated. room_id (str): The id of the room the message was sent in. message_id (str): The id of the message to be edited. - + Returns: [dict]: Returns an array of message objects. @@ -44,7 +44,7 @@ async def add_message_to_thread_list(org_id, room_id, message_id, request: Threa # add message to a parent thread message = await get_message(org_id, room_id, message_id) - + if not message: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Message not found" @@ -56,8 +56,58 @@ async def add_message_to_thread_list(org_id, room_id, message_id, request: Threa thread_message["created_at"] = str(datetime.utcnow()) message["threads"].insert(0, thread_message) - + response = await update_message(org_id, message_id, message) - + return response, thread_message + +async def update_thread_message( + org_id, room_id, message_id, thread_id, payload: Thread +) -> dict[str, Any]: + """Updates a message document in the database. + Args: + org_id (str): The organization id where the message is being updated. + message_id (str): The id of the parent message whose thread message is to be edited. + thread_id (str): The id of the thread message to be edited + payload (dict[str, Any]): the new thread mesage + Returns: + dict[str, Any]: The response returned by DataStorage's update method. + """ + message = await get_message(org_id, room_id, message_id) + + if not message: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail="Message not found" + ) + + if message["sender_id"] != payload["sender_id"]: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="You are not authorized to edit this message", + ) + + db = DataStorage(org_id) + payload["edited"] = True + + raw_query = { + "$set": {"threads.$": payload}, + # "arrayFilters": [ { "thread_id": thread_id } ] + } + + query = { + "_id": message_id, + "threads.thread_id": thread_id, + } + + response = await db.update( + collection_name=settings.MESSAGE_COLLECTION, + document_id=message_id, + raw_query=raw_query, + query=query, + ) + + if not response or "status_code" in response: + return None + + return response From 79c09c1d665c484cedd5fb1f77a4aa69345bf9a7 Mon Sep 17 00:00:00 2001 From: Shopiley Date: Mon, 30 Jan 2023 15:45:19 +0100 Subject: [PATCH 02/11] fixed update error --- backend/endpoints/threads.py | 4 ++++ backend/utils/db.py | 5 ++--- backend/utils/threads_utils.py | 8 +++++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/backend/endpoints/threads.py b/backend/endpoints/threads.py index b15d4757..39a8342b 100644 --- a/backend/endpoints/threads.py +++ b/backend/endpoints/threads.py @@ -233,11 +233,15 @@ async def update_thread_message( org_id, room_id, message_id, thread_id, payload ) + print(updated_thread_message) + if not updated_thread_message: raise HTTPException( status_code=status.HTTP_424_FAILED_DEPENDENCY, detail="thread not updated" ) + message.update(payload) + # Publish to centrifugo in the background. background_tasks.add_task( centrifugo_client.publish, room_id, Events.MESSAGE_UPDATE, message diff --git a/backend/utils/db.py b/backend/utils/db.py index d71aa8fe..bc4ebe66 100644 --- a/backend/utils/db.py +++ b/backend/utils/db.py @@ -129,7 +129,7 @@ async def write(self, collection_name: str, data: dict[str, Any]) -> Any: async def update( self, collection_name: str, - document_id: str, + document_id: Optional[str] = None, data: Optional[dict[str, Any]] = None, raw_query: Optional[dict[str, Any]] = None, query: Optional[dict[str, Any]] = None, @@ -174,7 +174,7 @@ async def update( # to ensure only either one of raw_query or data is sent if data and raw_query: raise Exception("Either one of data or raw_query is expected") - + print(document_id) body = { "plugin_id": self.plugin_id, "organization_id": self.organization_id, @@ -191,7 +191,6 @@ async def update( return None if response.status_code == 200: return response.json() - print({"status_code": response.status_code, "message": response.json()}) return {"status_code": response.status_code, "message": response.json()} async def read( diff --git a/backend/utils/threads_utils.py b/backend/utils/threads_utils.py index 30fdbbf9..1b984473 100644 --- a/backend/utils/threads_utils.py +++ b/backend/utils/threads_utils.py @@ -81,6 +81,8 @@ async def update_thread_message( status_code=status.HTTP_404_NOT_FOUND, detail="Message not found" ) + # we need to check if the threads exists first before updating + if message["sender_id"] != payload["sender_id"]: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, @@ -89,6 +91,7 @@ async def update_thread_message( db = DataStorage(org_id) payload["edited"] = True + payload["thread_id"] = thread_id raw_query = { "$set": {"threads.$": payload}, @@ -102,12 +105,11 @@ async def update_thread_message( response = await db.update( collection_name=settings.MESSAGE_COLLECTION, - document_id=message_id, raw_query=raw_query, query=query, ) - if not response or "status_code" in response: - return None + # if not response or "status_code" in response: + # return None return response From 65d532102445690e582ecd011a1249b05ca88a9c Mon Sep 17 00:00:00 2001 From: Shopiley Date: Mon, 30 Jan 2023 15:56:29 +0100 Subject: [PATCH 03/11] chore: refactored update_thread_message_function --- backend/utils/threads_utils.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/backend/utils/threads_utils.py b/backend/utils/threads_utils.py index 1b984473..6d032e47 100644 --- a/backend/utils/threads_utils.py +++ b/backend/utils/threads_utils.py @@ -103,13 +103,8 @@ async def update_thread_message( "threads.thread_id": thread_id, } - response = await db.update( + return await db.update( collection_name=settings.MESSAGE_COLLECTION, raw_query=raw_query, query=query, ) - - # if not response or "status_code" in response: - # return None - - return response From d9d2d25c1274c986e2a4a725cd0e628c236bab35 Mon Sep 17 00:00:00 2001 From: Shopiley Date: Tue, 31 Jan 2023 12:27:05 +0100 Subject: [PATCH 04/11] refactored response for update threads endpoint --- backend/endpoints/threads.py | 77 ++++++++++++++-------------------- backend/utils/db.py | 2 +- backend/utils/threads_utils.py | 10 ++--- 3 files changed, 36 insertions(+), 53 deletions(-) diff --git a/backend/endpoints/threads.py b/backend/endpoints/threads.py index 39a8342b..f5adc8ff 100644 --- a/backend/endpoints/threads.py +++ b/backend/endpoints/threads.py @@ -5,8 +5,8 @@ from schema.thread_response import ThreadResponse from utils.centrifugo import Events, centrifugo_client from utils.message_utils import get_message -from utils.threads_utils import add_message_to_thread_list, get_message_threads -from utils.threads_utils import update_thread_message as edit_message_threads +from utils.threads_utils import (add_message_to_thread_list, + get_message_threads, update_message_thread) router = APIRouter() @@ -167,10 +167,10 @@ async def update_thread_message( background_tasks: BackgroundTasks, ): - """(Still under development) Updates a thread message in a thread in a room. + """Updates a thread message in a thread in a room. - Edits an existing message document in the messages database collection while - publishing to all members of the room in the background. + Edits a thread in an existing message document in the messages database collection + while publishing to all members of the room in the background. Args: org_id: A unique identifier of the organization. @@ -185,70 +185,57 @@ async def update_thread_message( A dict containing data about the thread that was edited. { - "_id": "61c3aa9478fb01b18fac1465", - "created_at": "2021-12-22 22:38:33.075643", - "edited": true, - "emojis": [ - { - "count": 1, - "emoji": "👹", - "name": "frown", - "reactedUsersId": [ - "619ba4671a5f54782939d385" + "status": "success", + "message": "Thread Updated", + "data": { + "sender_id": "63cb53b42009ec8a16a5774b", + "emojis": [], + "richUiData": { + "blocks": [ + { + "data": {}, + "depth": 0, + "entityRanges": [], + "inlineStyleRanges": [], + "key": "eljik", + "text": "Steady green like what??", + "type": "unstyled" + } ] + }, + "files": [], + "saved_by": [], + "timestamp": 0, + "created_at": "2023-01-31 08:53:04.126997", + "edited": true, + "thread_id": "b39cfddc-a0a7-11ed-b15b-b8819887ed7a" } - ], - "files": [], - "org_id": "619ba4671a5f54782939d384", - "richUiData": { - "blocks": [ - { - "data": {}, - "depth": 0, - "entityRanges": [], - "inlineStyleRanges": [], - "key": "eljik", - "text": "HI, I'm mark.. new here", - "type": "unstyled" - } - ], - "entityMap": {} - }, - "room_id": "619e28c31a5f54782939d59a", - "saved_by": [], - "sender_id": "619ba4671a5f54782939d385", - "text": "string", } - Raises: - HTTPException [401]: You are not authorized to edit this message. + HTTPException [401]: You are not authorized to edit this thread message. HTTPException [404]: Message not found. - HTTPException [424]: Message not edited. + HTTPException [424]: thread not updated. """ message = await get_message(org_id, room_id, message_id) payload = request.dict(exclude_unset=True) - updated_thread_message = await edit_message_threads( + updated_thread_message = await update_message_thread( org_id, room_id, message_id, thread_id, payload ) - print(updated_thread_message) - if not updated_thread_message: raise HTTPException( status_code=status.HTTP_424_FAILED_DEPENDENCY, detail="thread not updated" ) - message.update(payload) - # Publish to centrifugo in the background. background_tasks.add_task( centrifugo_client.publish, room_id, Events.MESSAGE_UPDATE, message ) return JSONResponse( - content=ResponseModel.success(data=message, message="Thread Updated"), + content=ResponseModel.success(data=payload, message="Thread Updated"), status_code=status.HTTP_200_OK, ) diff --git a/backend/utils/db.py b/backend/utils/db.py index bc4ebe66..ea4cd2e5 100644 --- a/backend/utils/db.py +++ b/backend/utils/db.py @@ -174,7 +174,7 @@ async def update( # to ensure only either one of raw_query or data is sent if data and raw_query: raise Exception("Either one of data or raw_query is expected") - print(document_id) + body = { "plugin_id": self.plugin_id, "organization_id": self.organization_id, diff --git a/backend/utils/threads_utils.py b/backend/utils/threads_utils.py index 6d032e47..aaa839a0 100644 --- a/backend/utils/threads_utils.py +++ b/backend/utils/threads_utils.py @@ -62,7 +62,7 @@ async def add_message_to_thread_list(org_id, room_id, message_id, request: Threa return response, thread_message -async def update_thread_message( +async def update_message_thread( org_id, room_id, message_id, thread_id, payload: Thread ) -> dict[str, Any]: """Updates a message document in the database. @@ -81,21 +81,17 @@ async def update_thread_message( status_code=status.HTTP_404_NOT_FOUND, detail="Message not found" ) - # we need to check if the threads exists first before updating - if message["sender_id"] != payload["sender_id"]: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, - detail="You are not authorized to edit this message", + detail="You are not authorized to edit this thread message", ) - db = DataStorage(org_id) payload["edited"] = True payload["thread_id"] = thread_id raw_query = { "$set": {"threads.$": payload}, - # "arrayFilters": [ { "thread_id": thread_id } ] } query = { @@ -103,7 +99,7 @@ async def update_thread_message( "threads.thread_id": thread_id, } - return await db.update( + return await DataStorage(org_id).update( collection_name=settings.MESSAGE_COLLECTION, raw_query=raw_query, query=query, From c418cb96cf5fcb82cc113a336bbed95918ed80c3 Mon Sep 17 00:00:00 2001 From: Shopiley Date: Tue, 31 Jan 2023 12:58:00 +0100 Subject: [PATCH 05/11] cleaned up commented code --- backend/endpoints/threads.py | 52 ------------------------------------ 1 file changed, 52 deletions(-) diff --git a/backend/endpoints/threads.py b/backend/endpoints/threads.py index f5adc8ff..fbc174ac 100644 --- a/backend/endpoints/threads.py +++ b/backend/endpoints/threads.py @@ -238,55 +238,3 @@ async def update_thread_message( content=ResponseModel.success(data=payload, message="Thread Updated"), status_code=status.HTTP_200_OK, ) - - -# @router.get( -# "/org/{org_id}/member/{member_id}/threads", -# response_model=ResponseModel, -# status_code=status.HTTP_200_OK, -# responses={424: {"detail": "ZC Core failed"}}, -# ) -# async def get_threads(org_id: str, member_id: str, page: int = 1, size: int = 15): - -# room_response = await get_org_rooms(org_id=org_id, member_id=member_id) - -# if room_response == []: -# raise HTTPException( -# status_code=status.HTTP_404_NOT_FOUND, -# detail="Member does not exist or Org not found" -# ) - -# if room_response is None: -# raise HTTPException( -# status_code=status.HTTP_424_FAILED_DEPENDENCY, -# detail="Zc Core failed" -# ) - -# room_ids = [] - -# for room in room_response: -# room_ids.append(room['_id']) - -# for room_id in room_ids: -# single_room_resp = await get_room_messages(org_id, room_id, page, size) -# if single_room_resp == []: -# # Room not found -# pass - -# if single_room_resp is None: -# # Zc Core failed -# pass - -# # Gotten Single Room - -# messages_w_thread = [] - -# for messages in single_room_resp: -# if messages['threads'] != []: -# messages_w_thread.append(messages) - -# return JSONResponse( -# content=ResponseModel.success( -# data=messages_w_thread, message="Rooms retrieved"), -# status_code=status.HTTP_200_OK, -# ) From a9e0086052c5438a21b1cc18f7cbead8e35d2ada Mon Sep 17 00:00:00 2001 From: Shopiley Date: Thu, 2 Feb 2023 03:51:31 +0100 Subject: [PATCH 06/11] refactored update threads endpoint --- backend/endpoints/threads.py | 9 +++------ backend/utils/threads_utils.py | 4 +++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/backend/endpoints/threads.py b/backend/endpoints/threads.py index fbc174ac..58aec662 100644 --- a/backend/endpoints/threads.py +++ b/backend/endpoints/threads.py @@ -4,7 +4,6 @@ from schema.response import ResponseModel from schema.thread_response import ThreadResponse from utils.centrifugo import Events, centrifugo_client -from utils.message_utils import get_message from utils.threads_utils import (add_message_to_thread_list, get_message_threads, update_message_thread) @@ -198,7 +197,7 @@ async def update_thread_message( "entityRanges": [], "inlineStyleRanges": [], "key": "eljik", - "text": "Steady green like what??", + "text": "you're right about that", "type": "unstyled" } ] @@ -216,11 +215,9 @@ async def update_thread_message( HTTPException [404]: Message not found. HTTPException [424]: thread not updated. """ - - message = await get_message(org_id, room_id, message_id) payload = request.dict(exclude_unset=True) - updated_thread_message = await update_message_thread( + updated_thread_message, loaded_message = await update_message_thread( org_id, room_id, message_id, thread_id, payload ) @@ -231,7 +228,7 @@ async def update_thread_message( # Publish to centrifugo in the background. background_tasks.add_task( - centrifugo_client.publish, room_id, Events.MESSAGE_UPDATE, message + centrifugo_client.publish, room_id, Events.MESSAGE_UPDATE, loaded_message ) return JSONResponse( diff --git a/backend/utils/threads_utils.py b/backend/utils/threads_utils.py index aaa839a0..16111dcf 100644 --- a/backend/utils/threads_utils.py +++ b/backend/utils/threads_utils.py @@ -99,8 +99,10 @@ async def update_message_thread( "threads.thread_id": thread_id, } - return await DataStorage(org_id).update( + response = await DataStorage(org_id).update( collection_name=settings.MESSAGE_COLLECTION, raw_query=raw_query, query=query, ) + + return response, message From 4156c359d8b9ad6bf68eb3235954b2a6889a47e2 Mon Sep 17 00:00:00 2001 From: Shopiley Date: Thu, 2 Feb 2023 11:11:19 +0100 Subject: [PATCH 07/11] minor fixes --- backend/.pre-commit-config.yaml | 4 ---- backend/utils/db.py | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/backend/.pre-commit-config.yaml b/backend/.pre-commit-config.yaml index 0cb07d8d..407e3181 100644 --- a/backend/.pre-commit-config.yaml +++ b/backend/.pre-commit-config.yaml @@ -45,7 +45,3 @@ repos: - --disable=R0902 - --disable=R0903 - --disable=C0103 - - --disable=R0913 - - --disable=C0327 - - --disable=C0305 - - --disable=WO622 diff --git a/backend/utils/db.py b/backend/utils/db.py index ea4cd2e5..bf2fe851 100644 --- a/backend/utils/db.py +++ b/backend/utils/db.py @@ -171,8 +171,8 @@ async def update( RequestException: Unable to connect to zc_core """ - # to ensure only either one of raw_query or data is sent - if data and raw_query: + # to ensure either one of raw_query or data is sent + if len(list(filter(bool(data, raw_query)))) != 1: raise Exception("Either one of data or raw_query is expected") body = { From 029179803951f4166878933b6187a89aa0ff9104 Mon Sep 17 00:00:00 2001 From: Shopiley Date: Thu, 2 Feb 2023 11:38:33 +0100 Subject: [PATCH 08/11] diabled R0913 precommit hook --- backend/.pre-commit-config.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/.pre-commit-config.yaml b/backend/.pre-commit-config.yaml index 407e3181..1255b235 100644 --- a/backend/.pre-commit-config.yaml +++ b/backend/.pre-commit-config.yaml @@ -45,3 +45,5 @@ repos: - --disable=R0902 - --disable=R0903 - --disable=C0103 + - --disable=R0913 + From 792936c9637b082e398f2547c541c6bb8c04bae0 Mon Sep 17 00:00:00 2001 From: Shopiley Date: Tue, 28 Feb 2023 00:10:48 +0100 Subject: [PATCH 09/11] refactoring --- backend/endpoints/threads.py | 7 ------- backend/utils/threads_utils.py | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/backend/endpoints/threads.py b/backend/endpoints/threads.py index fbc174ac..e4aaa314 100644 --- a/backend/endpoints/threads.py +++ b/backend/endpoints/threads.py @@ -164,7 +164,6 @@ async def update_thread_message( message_id: str, thread_id: str, request: MessageRequest, - background_tasks: BackgroundTasks, ): """Updates a thread message in a thread in a room. @@ -217,7 +216,6 @@ async def update_thread_message( HTTPException [424]: thread not updated. """ - message = await get_message(org_id, room_id, message_id) payload = request.dict(exclude_unset=True) updated_thread_message = await update_message_thread( @@ -229,11 +227,6 @@ async def update_thread_message( status_code=status.HTTP_424_FAILED_DEPENDENCY, detail="thread not updated" ) - # Publish to centrifugo in the background. - background_tasks.add_task( - centrifugo_client.publish, room_id, Events.MESSAGE_UPDATE, message - ) - return JSONResponse( content=ResponseModel.success(data=payload, message="Thread Updated"), status_code=status.HTTP_200_OK, diff --git a/backend/utils/threads_utils.py b/backend/utils/threads_utils.py index aaa839a0..36db80a2 100644 --- a/backend/utils/threads_utils.py +++ b/backend/utils/threads_utils.py @@ -98,7 +98,7 @@ async def update_message_thread( "_id": message_id, "threads.thread_id": thread_id, } - + return await DataStorage(org_id).update( collection_name=settings.MESSAGE_COLLECTION, raw_query=raw_query, From e2668063124cc0395833ad83364fe2b47d76e10f Mon Sep 17 00:00:00 2001 From: Shopiley Date: Wed, 1 Mar 2023 18:34:34 +0100 Subject: [PATCH 10/11] feat/authorization for thread update --- backend/utils/db.py | 2 +- backend/utils/threads_utils.py | 42 +++++++++++++++++++++++++++++++--- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/backend/utils/db.py b/backend/utils/db.py index bf2fe851..45851c4e 100644 --- a/backend/utils/db.py +++ b/backend/utils/db.py @@ -172,7 +172,7 @@ async def update( """ # to ensure either one of raw_query or data is sent - if len(list(filter(bool(data, raw_query)))) != 1: + if len(list(filter(bool, (data, raw_query)))) != 1: raise Exception("Either one of data or raw_query is expected") body = { diff --git a/backend/utils/threads_utils.py b/backend/utils/threads_utils.py index 36db80a2..6abd3670 100644 --- a/backend/utils/threads_utils.py +++ b/backend/utils/threads_utils.py @@ -28,6 +28,39 @@ async def get_message_threads(org_id, room_id, message_id): message = await get_message(org_id, room_id, message_id) return message["threads"] +async def get_message_thread(org_id, room_id, message_id, thread_id): + """Retrives a single the messages in a thread. + + Args: + org_id (str): The organization id where the message is being updated. + room_id (str): The id of the room the message was sent in. + message_id (str): The id of the parent message whose thead message is to be edited. + thread_id (str): The id of the thread to be edited. + + + Returns: + [dict]: Returns an array of thread message objects. + """ + + query = { + "_id": message_id, + "threads.thread_id": thread_id + } + + options = { "projection": {"threads.$": 1} } + + response = await DataStorage(org_id).read( + collection_name=settings.MESSAGE_COLLECTION, + query=query, + options=options + ) + + if not response or "status_code" in response: + return [] + + return response["threads"] + + async def add_message_to_thread_list(org_id, room_id, message_id, request: Thread): """Adds a message to a thread. @@ -78,10 +111,13 @@ async def update_message_thread( if not message: raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, detail="Message not found" + status_code=status.HTTP_404_NOT_FOUND, detail="Parent message not found" ) - if message["sender_id"] != payload["sender_id"]: + loaded_message_thread = await get_message_thread(org_id, room_id, message_id, thread_id) + + + if loaded_message_thread[0]["sender_id"] != payload["sender_id"]: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="You are not authorized to edit this thread message", @@ -102,5 +138,5 @@ async def update_message_thread( return await DataStorage(org_id).update( collection_name=settings.MESSAGE_COLLECTION, raw_query=raw_query, - query=query, + query=query ) From 0db340ffe9670bf91736aa2598562a4ddb83b4bc Mon Sep 17 00:00:00 2001 From: Fadekemi Adebayo <82163647+Shopiley@users.noreply.github.com> Date: Fri, 3 Mar 2023 09:40:48 +0100 Subject: [PATCH 11/11] corrected typos in docstring --- backend/utils/threads_utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/utils/threads_utils.py b/backend/utils/threads_utils.py index 6abd3670..628c42a2 100644 --- a/backend/utils/threads_utils.py +++ b/backend/utils/threads_utils.py @@ -12,7 +12,7 @@ async def get_message_threads(org_id, room_id, message_id): - """Retrives all the messages in a thread. + """Retrieves all the messages in a thread. Args: org_id (str): The organization id where the message is being updated. @@ -29,7 +29,7 @@ async def get_message_threads(org_id, room_id, message_id): return message["threads"] async def get_message_thread(org_id, room_id, message_id, thread_id): - """Retrives a single the messages in a thread. + """Retrieves a single thread message. Args: org_id (str): The organization id where the message is being updated. @@ -39,7 +39,7 @@ async def get_message_thread(org_id, room_id, message_id, thread_id): Returns: - [dict]: Returns an array of thread message objects. + [dict]: Returns an array containing a single thread message. """ query = {