From d98f3e4c2d5658592de574e2ccd59641a59d5ed5 Mon Sep 17 00:00:00 2001 From: Andrey Date: Thu, 27 Apr 2023 17:21:48 +0300 Subject: [PATCH 01/10] Extend get query endpoint. --- backend/moonstreamapi/data.py | 11 +++++++++ backend/moonstreamapi/routes/queries.py | 32 +++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/backend/moonstreamapi/data.py b/backend/moonstreamapi/data.py index 76b6aec1..2d1dfbb6 100644 --- a/backend/moonstreamapi/data.py +++ b/backend/moonstreamapi/data.py @@ -284,3 +284,14 @@ class PreapprovedQuery(BaseModel): class QueryPresignUrl(BaseModel): url: str + + +class QueryInfoResponse(BaseModel): + query: str + query_id: str + public: bool = False + preapproved: bool = False + approved: bool = False + parameters: List[str] = Field(default_factory=list) + created_at: datetime + updated_at: datetime diff --git a/backend/moonstreamapi/routes/queries.py b/backend/moonstreamapi/routes/queries.py index a0b5f6bd..9d3b2a11 100644 --- a/backend/moonstreamapi/routes/queries.py +++ b/backend/moonstreamapi/routes/queries.py @@ -10,6 +10,7 @@ from bugout.data import BugoutResources, BugoutJournalEntryContent, BugoutJourna from bugout.exceptions import BugoutResponseException from fastapi import APIRouter, Body, Request import requests # type: ignore +from sqlalchemy import text from .. import data @@ -154,7 +155,9 @@ async def create_query_handler( @router.get("/{query_name}/query", tags=["queries"]) -async def get_query_handler(request: Request, query_name: str) -> BugoutJournalEntry: +async def get_query_handler( + request: Request, query_name: str +) -> data.QueryInfoResponse: token = request.state.token try: @@ -180,7 +183,32 @@ async def get_query_handler(request: Request, query_name: str) -> BugoutJournalE except Exception as e: raise MoonstreamHTTPException(status_code=500, internal_error=e) - return entry + try: + query = text(entry.content) + except Exception as e: + raise MoonstreamHTTPException( + status_code=500, internal_error=e, detail="Error in query parsing" + ) + + query_parameters = query._bindparams.keys() + + preaprove = False + if "preapprove" in entry.tags: + preaprove = True + + approved = False + if "approved" in entry.tags: + approved = True + + return data.QueryInfoResponse( + query=query, + query_id=entry.id, + preapprove=preaprove, + approved=approved, + parameters=query_parameters, + created_at=entry.created_at, + updated_at=entry.updated_at, + ) @router.put("/{query_name}", tags=["queries"]) From 9f2051688a103ed29a8841b207a3c1d490e9b985 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 2 May 2023 15:04:46 +0300 Subject: [PATCH 02/10] Add limit and offset. --- backend/moonstreamapi/routes/subscriptions.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/moonstreamapi/routes/subscriptions.py b/backend/moonstreamapi/routes/subscriptions.py index 3fc020cf..8ea74049 100644 --- a/backend/moonstreamapi/routes/subscriptions.py +++ b/backend/moonstreamapi/routes/subscriptions.py @@ -238,7 +238,11 @@ async def delete_subscription_handler(request: Request, subscription_id: str): @router.get("/", tags=["subscriptions"], response_model=data.SubscriptionsListResponse) -async def get_subscriptions_handler(request: Request) -> data.SubscriptionsListResponse: +async def get_subscriptions_handler( + request: Request, + limit: Optional[int] = 10, + offset: Optional[int] = 0, +) -> data.SubscriptionsListResponse: """ Get user's subscriptions. """ @@ -255,7 +259,8 @@ async def get_subscriptions_handler(request: Request) -> data.SubscriptionsListR token=token, collection_id=collection_id, required_field=[f"type:subscription"], - limit=1000, + limit=limit, + offset=offset, ) # resources: BugoutResources = bc.list_resources(token=token, params=params) From d794a887ce8731c967009d58ee6c9dda115f34e0 Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 3 May 2023 16:48:40 +0300 Subject: [PATCH 03/10] Add fixes. --- backend/moonstreamapi/routes/queries.py | 6 +++--- backend/moonstreamapi/routes/subscriptions.py | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/backend/moonstreamapi/routes/queries.py b/backend/moonstreamapi/routes/queries.py index 9d3b2a11..25a18c97 100644 --- a/backend/moonstreamapi/routes/queries.py +++ b/backend/moonstreamapi/routes/queries.py @@ -190,7 +190,7 @@ async def get_query_handler( status_code=500, internal_error=e, detail="Error in query parsing" ) - query_parameters = query._bindparams.keys() + query_parameters = list(query._bindparams.keys()) preaprove = False if "preapprove" in entry.tags: @@ -201,8 +201,8 @@ async def get_query_handler( approved = True return data.QueryInfoResponse( - query=query, - query_id=entry.id, + query=entry.content, + query_id=str(entry.id), preapprove=preaprove, approved=approved, parameters=query_parameters, diff --git a/backend/moonstreamapi/routes/subscriptions.py b/backend/moonstreamapi/routes/subscriptions.py index 8ea74049..8146145d 100644 --- a/backend/moonstreamapi/routes/subscriptions.py +++ b/backend/moonstreamapi/routes/subscriptions.py @@ -263,7 +263,6 @@ async def get_subscriptions_handler( offset=offset, ) - # resources: BugoutResources = bc.list_resources(token=token, params=params) except EntityCollectionNotFoundException as e: raise MoonstreamHTTPException( status_code=404, From 789ed431c14d6b9337c7e467488a2d6619f9e4e3 Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 3 May 2023 17:00:20 +0300 Subject: [PATCH 04/10] Add changes. --- backend/moonstreamapi/data.py | 2 +- backend/moonstreamapi/routes/queries.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/moonstreamapi/data.py b/backend/moonstreamapi/data.py index 2c215b27..72fb7305 100644 --- a/backend/moonstreamapi/data.py +++ b/backend/moonstreamapi/data.py @@ -291,7 +291,7 @@ class QueryInfoResponse(BaseModel): query: str query_id: str public: bool = False - preapproved: bool = False + preapprove: bool = False approved: bool = False parameters: List[str] = Field(default_factory=list) created_at: datetime diff --git a/backend/moonstreamapi/routes/queries.py b/backend/moonstreamapi/routes/queries.py index 25a18c97..43ed2d9a 100644 --- a/backend/moonstreamapi/routes/queries.py +++ b/backend/moonstreamapi/routes/queries.py @@ -184,6 +184,10 @@ async def get_query_handler( raise MoonstreamHTTPException(status_code=500, internal_error=e) try: + if entry.content is None: + raise MoonstreamHTTPException( + status_code=403, detail=f"Query is empty. Please update it." + ) query = text(entry.content) except Exception as e: raise MoonstreamHTTPException( From d2f29f583115b8e18b874057eb1412ab289855a5 Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 3 May 2023 17:21:48 +0300 Subject: [PATCH 05/10] Fix data type. --- backend/moonstreamapi/data.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/moonstreamapi/data.py b/backend/moonstreamapi/data.py index 72fb7305..6a6c018d 100644 --- a/backend/moonstreamapi/data.py +++ b/backend/moonstreamapi/data.py @@ -294,5 +294,5 @@ class QueryInfoResponse(BaseModel): preapprove: bool = False approved: bool = False parameters: List[str] = Field(default_factory=list) - created_at: datetime - updated_at: datetime + created_at: Optional[datetime] + updated_at: Optional[datetime] From 50c4720349d5dfb0db88493ae49aa6028c44c2b7 Mon Sep 17 00:00:00 2001 From: Andrey Date: Thu, 4 May 2023 16:28:37 +0300 Subject: [PATCH 06/10] Add type support. --- backend/moonstreamapi/data.py | 2 +- backend/moonstreamapi/routes/queries.py | 23 ++++++++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/backend/moonstreamapi/data.py b/backend/moonstreamapi/data.py index 6a6c018d..ac67968e 100644 --- a/backend/moonstreamapi/data.py +++ b/backend/moonstreamapi/data.py @@ -293,6 +293,6 @@ class QueryInfoResponse(BaseModel): public: bool = False preapprove: bool = False approved: bool = False - parameters: List[str] = Field(default_factory=list) + parameters: Dict[str, Any] = Field(default_factory=dict) created_at: Optional[datetime] updated_at: Optional[datetime] diff --git a/backend/moonstreamapi/routes/queries.py b/backend/moonstreamapi/routes/queries.py index 43ed2d9a..97c71de7 100644 --- a/backend/moonstreamapi/routes/queries.py +++ b/backend/moonstreamapi/routes/queries.py @@ -194,21 +194,26 @@ async def get_query_handler( status_code=500, internal_error=e, detail="Error in query parsing" ) - query_parameters = list(query._bindparams.keys()) + query_parameters_names = list(query._bindparams.keys()) - preaprove = False - if "preapprove" in entry.tags: - preaprove = True + tags_dict = { + tag.split(":")[0]: (tag.split(":")[1] if ":" in tag else True) + for tag in entry.tags + } - approved = False - if "approved" in entry.tags: - approved = True + query_parameters: Dict[str, Any] = {} + + for param in query_parameters_names: + if param in tags_dict: + query_parameters[param] = tags_dict[param] + else: + query_parameters[param] = None return data.QueryInfoResponse( query=entry.content, query_id=str(entry.id), - preapprove=preaprove, - approved=approved, + preapprove="preapprove" in tags_dict, + approved="approved" in tags_dict, parameters=query_parameters, created_at=entry.created_at, updated_at=entry.updated_at, From 4535e7b3c0707ce5720c243c65fe26a5f846400d Mon Sep 17 00:00:00 2001 From: Andrey Date: Thu, 4 May 2023 17:20:55 +0300 Subject: [PATCH 07/10] bump version. --- backend/moonstreamapi/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/moonstreamapi/version.py b/backend/moonstreamapi/version.py index edd28105..286247fc 100644 --- a/backend/moonstreamapi/version.py +++ b/backend/moonstreamapi/version.py @@ -2,4 +2,4 @@ Moonstream library and API version. """ -MOONSTREAMAPI_VERSION = "0.2.4" +MOONSTREAMAPI_VERSION = "0.2.5" From ba1992c26dd22b507c602bcfd3c79f4100f04e81 Mon Sep 17 00:00:00 2001 From: Andrey Date: Thu, 4 May 2023 18:30:25 +0300 Subject: [PATCH 08/10] Add fix of subscriptions. --- backend/moonstreamapi/routes/subscriptions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/moonstreamapi/routes/subscriptions.py b/backend/moonstreamapi/routes/subscriptions.py index 8146145d..836c03e2 100644 --- a/backend/moonstreamapi/routes/subscriptions.py +++ b/backend/moonstreamapi/routes/subscriptions.py @@ -253,6 +253,7 @@ async def get_subscriptions_handler( resource_type=BUGOUT_RESOURCE_TYPE_ENTITY_SUBSCRIPTION, token=MOONSTREAM_ADMIN_ACCESS_TOKEN, user_id=user.id, + create_if_not_exist=True, ) subscriprions_list = ec.search_entities( From d20c0bf43c5cc6bbf7a6d78a9cd1852cb8c0f407 Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 8 May 2023 16:04:32 +0300 Subject: [PATCH 09/10] Add fixes. --- backend/moonstreamapi/actions.py | 113 +++++++++++++++++--------- backend/moonstreamapi/routes/users.py | 3 +- 2 files changed, 76 insertions(+), 40 deletions(-) diff --git a/backend/moonstreamapi/actions.py b/backend/moonstreamapi/actions.py index 70e84e9b..5f47bb2a 100644 --- a/backend/moonstreamapi/actions.py +++ b/backend/moonstreamapi/actions.py @@ -636,51 +636,86 @@ def get_entity_subscription_collection_id( raise EntityCollectionNotFoundException( "Subscription collection not found." ) - try: - # try get collection + generate_collection_for_user(resource_type, token, user_id) - collections: EntityCollectionsResponse = ec.list_collections(token=token) - - available_collections: Dict[str, str] = { - collection.name: collection.collection_id - for collection in collections.collections - } - - if f"subscriptions_{user_id}" not in available_collections: - collection: EntityCollectionResponse = ec.add_collection( - token=token, name=f"subscriptions_{user_id}" - ) - collection_id = collection.collection_id - else: - collection_id = available_collections[f"subscriptions_{user_id}"] - except EntityUnexpectedResponse as e: - logger.error(f"Error create collection, error: {str(e)}") - raise MoonstreamHTTPException( - status_code=500, detail="Can't create collection for subscriptions" - ) - - resource_data = { - "type": resource_type, - "user_id": str(user_id), - "collection_id": str(collection_id), - } - - try: - resource: BugoutResource = bc.create_resource( - token=token, - application_id=MOONSTREAM_APPLICATION_ID, - resource_data=resource_data, - ) - except BugoutResponseException as e: - raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail) - except Exception as e: - logger.error(f"Error creating subscription resource: {str(e)}") - raise MoonstreamHTTPException(status_code=500, internal_error=e) else: resource = resources.resources[0] return resource.resource_data["collection_id"] +def generate_collection_for_user( + resource_type: str, + token: Union[uuid.UUID, str], + user_id: uuid.UUID, +) -> str: + try: + # try get collection + + collections: EntityCollectionsResponse = ec.list_collections(token=token) + + available_collections: Dict[str, str] = { + collection.name: collection.collection_id + for collection in collections.collections + } + + if f"subscriptions_{user_id}" not in available_collections: + collection: EntityCollectionResponse = ec.add_collection( + token=token, name=f"subscriptions_{user_id}" + ) + collection_id = collection.collection_id + else: + collection_id = available_collections[f"subscriptions_{user_id}"] + except EntityUnexpectedResponse as e: + logger.error(f"Error create collection, error: {str(e)}") + raise MoonstreamHTTPException( + status_code=500, detail="Can't create collection for subscriptions" + ) + + resource_data = { + "type": resource_type, + "user_id": str(user_id), + "collection_id": str(collection_id), + } + + try: + bc.create_resource( + token=token, + application_id=MOONSTREAM_APPLICATION_ID, + resource_data=resource_data, + ) + except BugoutResponseException as e: + raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail) + except Exception as e: + logger.error(f"Error creating subscription resource: {str(e)}") + logger.error( + f"Required create resource data: {resource_data}, and grand access to journal: {collection_id}, for user: {user_id}" + ) + raise MoonstreamHTTPException(status_code=500, internal_error=e) + + try: + bc.update_journal_scopes( + token=MOONSTREAM_ADMIN_ACCESS_TOKEN, + journal_id=collection_id, + holder_type="user", + holder_id=user_id, + permission_list=[ + "journals.read", + "journals.entries.read", + "journals.entries.create", + "journals.entries.update", + "journals.entries.delete", + ], + ) + except Exception as e: + logger.error(f"Error updating journal scopes: {str(e)}") + logger.error( + f"Required grand access to journal: {collection_id}, for user: {user_id}" + ) + raise MoonstreamHTTPException(status_code=500, internal_error=e) + + return collection_id + + def generate_s3_access_links( method_name: str, bucket: str, diff --git a/backend/moonstreamapi/routes/users.py b/backend/moonstreamapi/routes/users.py index 28ba7894..d4cfa747 100644 --- a/backend/moonstreamapi/routes/users.py +++ b/backend/moonstreamapi/routes/users.py @@ -10,7 +10,7 @@ from bugout.exceptions import BugoutResponseException from fastapi import APIRouter, Body, Form, Request from .. import data -from ..actions import create_onboarding_resource +from ..actions import create_onboarding_resource, generate_collection_for_user from ..middleware import MoonstreamHTTPException from ..settings import BUGOUT_REQUEST_TIMEOUT_SECONDS, MOONSTREAM_APPLICATION_ID from ..settings import bugout_client as bc @@ -35,6 +35,7 @@ async def create_user_handler( raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail) except Exception as e: raise MoonstreamHTTPException(status_code=500, internal_error=e) + return user From 4b135720408314f94ebf68c8eb90c44f206a7b53 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 9 May 2023 13:11:34 +0300 Subject: [PATCH 10/10] Add changes. --- backend/moonstreamapi/actions.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/backend/moonstreamapi/actions.py b/backend/moonstreamapi/actions.py index 5f47bb2a..a00c716f 100644 --- a/backend/moonstreamapi/actions.py +++ b/backend/moonstreamapi/actions.py @@ -636,7 +636,9 @@ def get_entity_subscription_collection_id( raise EntityCollectionNotFoundException( "Subscription collection not found." ) - generate_collection_for_user(resource_type, token, user_id) + collection_id = generate_collection_for_user(resource_type, token, user_id) + + return collection_id else: resource = resources.resources[0] @@ -658,13 +660,15 @@ def generate_collection_for_user( for collection in collections.collections } - if f"subscriptions_{user_id}" not in available_collections: + subscription_collection_name = f"subscriptions_{user_id}" + + if subscription_collection_name not in available_collections: collection: EntityCollectionResponse = ec.add_collection( - token=token, name=f"subscriptions_{user_id}" + token=token, name=subscription_collection_name ) collection_id = collection.collection_id else: - collection_id = available_collections[f"subscriptions_{user_id}"] + collection_id = available_collections[subscription_collection_name] except EntityUnexpectedResponse as e: logger.error(f"Error create collection, error: {str(e)}") raise MoonstreamHTTPException( @@ -706,6 +710,9 @@ def generate_collection_for_user( "journals.entries.delete", ], ) + logger.info( + f"Grand access to journal: {collection_id}, for user: {user_id} successfully" + ) except Exception as e: logger.error(f"Error updating journal scopes: {str(e)}") logger.error(