From 6606ac35e0a6fc9209fe532880e2b69148207ce7 Mon Sep 17 00:00:00 2001 From: Mostafa Rashed <17770919+mrashed-dev@users.noreply.github.com> Date: Tue, 17 Oct 2023 13:08:19 -0400 Subject: [PATCH 1/5] add base class for query params --- nylas/models/calendars.py | 10 +++++----- nylas/models/events.py | 11 ++++++----- nylas/models/list_query_params.py | 17 +++++++++++++++++ 3 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 nylas/models/list_query_params.py diff --git a/nylas/models/calendars.py b/nylas/models/calendars.py index 6e2054c0..82c0f258 100644 --- a/nylas/models/calendars.py +++ b/nylas/models/calendars.py @@ -4,6 +4,8 @@ from dataclasses_json import dataclass_json from typing_extensions import TypedDict, NotRequired +from nylas.models.list_query_params import ListQueryParams + @dataclass_json @dataclass @@ -44,20 +46,18 @@ class Calendar: metadata: Optional[Dict[str, Any]] = None -class ListCalendersQueryParams(TypedDict): +class ListCalendersQueryParams(ListQueryParams): """ Interface of the query parameters for listing calendars. Attributes: - limit: The maximum number of objects to return. + limit (NotRequired[int]): The maximum number of objects to return. This field defaults to 50. The maximum allowed value is 200. - page_token: An identifier that specifies which page of data to return. + page_token (NotRequired[str]): An identifier that specifies which page of data to return. This value should be taken from a ListResponse object's next_cursor parameter. metadata_pair: Pass in your metadata key-value pair to search for metadata. """ - limit: NotRequired[int] - page_token: NotRequired[str] metadata_pair: NotRequired[Dict[str, str]] diff --git a/nylas/models/events.py b/nylas/models/events.py index 736ac625..e7660003 100644 --- a/nylas/models/events.py +++ b/nylas/models/events.py @@ -4,6 +4,8 @@ from dataclasses_json import dataclass_json, config from typing_extensions import TypedDict, NotRequired +from nylas.models.list_query_params import ListQueryParams + Status = Literal["confirmed", "tentative", "cancelled"] """ Literal representing the status of an Event. """ @@ -660,7 +662,7 @@ class UpdateEventRequest(TypedDict): hide_participants: NotRequired[bool] -class ListEventQueryParams(TypedDict): +class ListEventQueryParams(ListQueryParams): """ Interface representing the query parameters for listing events. @@ -684,9 +686,10 @@ class ListEventQueryParams(TypedDict): busy: Returns events with a busy status of true. order_by: Order results by the specified field. Currently only start is supported. - limit: The maximum number of objects to return. + limit (NotRequired[int]): The maximum number of objects to return. This field defaults to 50. The maximum allowed value is 200. - page_token: An identifier that specifies which page of data to return. + page_token (NotRequired[str]): An identifier that specifies which page of data to return. + This value should be taken from a ListResponse object's next_cursor parameter. """ calendar_id: str @@ -700,8 +703,6 @@ class ListEventQueryParams(TypedDict): expand_recurring: NotRequired[bool] busy: NotRequired[bool] order_by: NotRequired[str] - limit: NotRequired[int] - page_token: NotRequired[str] class CreateEventQueryParams(TypedDict): diff --git a/nylas/models/list_query_params.py b/nylas/models/list_query_params.py new file mode 100644 index 00000000..8c9432b9 --- /dev/null +++ b/nylas/models/list_query_params.py @@ -0,0 +1,17 @@ +from typing import Dict +from typing_extensions import TypedDict, NotRequired + + +class ListQueryParams(TypedDict): + """ + Interface of the query parameters for listing resources. + + Attributes: + limit: The maximum number of objects to return. + This field defaults to 50. The maximum allowed value is 200. + page_token: An identifier that specifies which page of data to return. + This value should be taken from a ListResponse object's next_cursor parameter. + """ + + limit: NotRequired[int] + page_token: NotRequired[str] From 36f07932f064b22c365ffbbff337b3218fd63c96 Mon Sep 17 00:00:00 2001 From: Mostafa Rashed <17770919+mrashed-dev@users.noreply.github.com> Date: Tue, 17 Oct 2023 13:08:26 -0400 Subject: [PATCH 2/5] add connector models --- nylas/models/auth.py | 3 +- nylas/models/connectors.py | 162 +++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 nylas/models/connectors.py diff --git a/nylas/models/auth.py b/nylas/models/auth.py index dca5dba5..377a034d 100644 --- a/nylas/models/auth.py +++ b/nylas/models/auth.py @@ -7,7 +7,7 @@ AccessType = Literal["online", "offline"] """ Literal for the access type of the authentication URL. """ -Provider = Literal["google", "imap", "microsoft"] +Provider = Literal["google", "imap", "microsoft", "virtual-calendar"] """ Literal for the different authentication providers. """ @@ -129,6 +129,7 @@ class TokenInfoResponse: sub: The token's subject. email: The email address of the Grant belonging to the user's token. """ + iss: str aud: str iat: int diff --git a/nylas/models/connectors.py b/nylas/models/connectors.py new file mode 100644 index 00000000..dcfc6af3 --- /dev/null +++ b/nylas/models/connectors.py @@ -0,0 +1,162 @@ +from dataclasses import dataclass +from typing import Dict, Any, List, Optional, Union +from typing_extensions import TypedDict, NotRequired + +from dataclasses_json import dataclass_json + +from nylas.models.auth import Provider +from nylas.models.list_query_params import ListQueryParams + + +@dataclass_json +@dataclass +class Connector: + """ + Interface representing the Nylas connector response. + + Attributes: + name: Custom name of the connector + provider: The provider type + settings: Optional settings from provider + scope: Default scopes for the connector + """ + + name: str + provider: Provider + settings: Optional[Dict[str, Any]] = None + scope: Optional[List[str]] = None + + +class BaseCreateConnectorRequest(TypedDict): + """ + Interface representing the base Nylas connector creation request. + + Attributes: + name: Custom name of the connector + provider: The provider type + """ + + name: str + provider: Provider + + +class GoogleCreateConnectorSettings(TypedDict): + """ + Interface representing a Google connector creation request. + + Attributes: + client_id: The Google Client ID + client_secret: The Google Client Secret + topic_name: The Google Pub/Sub topic name + """ + + client_id: str + client_secret: str + topic_name: NotRequired[str] + + +class MicrosoftCreateConnectorSettings(TypedDict): + """ + Interface representing a Microsoft connector creation request. + + Attributes: + client_id: The Google Client ID + client_secret: The Google Client Secret + tenant: The Microsoft tenant ID + """ + + client_id: str + client_secret: str + tenant: NotRequired[str] + + +class GoogleCreateConnectorRequest(BaseCreateConnectorRequest): + """ + Interface representing the base Nylas connector creation request. + + Attributes: + name (str): Custom name of the connector + provider (Provider): The provider type, should be Google + settings: The Google OAuth provider credentials and settings + scope: The Google OAuth scopes + """ + + settings: NotRequired[GoogleCreateConnectorSettings] + scope: NotRequired[List[str]] + + +class MicrosoftCreateConnectorRequest(BaseCreateConnectorRequest): + """ + Interface representing the base Nylas connector creation request. + + Attributes: + name (str): Custom name of the connector + provider (Provider): The provider type, should be Google + settings: The Microsoft OAuth provider credentials and settings + scope: The Microsoft OAuth scopes + """ + + settings: NotRequired[MicrosoftCreateConnectorSettings] + scope: NotRequired[List[str]] + + +class ImapCreateConnectorRequest(BaseCreateConnectorRequest): + """ + Interface representing the base Nylas connector creation request. + + Attributes: + name (str): Custom name of the connector + provider (Provider): The provider type, should be IMAP + """ + + pass + + +class VirtualCalendarsCreateConnectorRequest(BaseCreateConnectorRequest): + """ + Interface representing the base Nylas connector creation request. + + Attributes: + name (str): Custom name of the connector + provider (Provider): The provider type + """ + + pass + + +CreateConnectorRequest = Union[ + GoogleCreateConnectorRequest, + MicrosoftCreateConnectorRequest, + ImapCreateConnectorRequest, + VirtualCalendarsCreateConnectorRequest, +] +""" The type of the Nylas connector creation request. """ + + +class UpdateConnectorRequest(TypedDict): + """ + Interface representing the base Nylas connector creation request. + + Attributes: + name: Custom name of the connector + settings: The OAuth provider credentials and settings + scope: The OAuth scopes + """ + + name: NotRequired[str] + settings: NotRequired[Dict[str, Any]] + scope: NotRequired[List[str]] + + +class ListConnectorQueryParams(ListQueryParams): + """ + Interface of the query parameters for listing connectors. + + Attributes: + limit (NotRequired[int]): The maximum number of objects to return. + This field defaults to 50. The maximum allowed value is 200. + page_token (NotRequired[str]): An identifier that specifies which page of data to return. + This value should be taken from a ListResponse object's next_cursor parameter. + """ + + pass From 0125db510f2039258f470fd0159a025083c42cd9 Mon Sep 17 00:00:00 2001 From: Mostafa Rashed <17770919+mrashed-dev@users.noreply.github.com> Date: Tue, 17 Oct 2023 13:09:32 -0400 Subject: [PATCH 3/5] Add connector endpoints --- nylas/client.py | 11 ++++ nylas/resources/connectors.py | 103 ++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 nylas/resources/connectors.py diff --git a/nylas/client.py b/nylas/client.py index 0b42e1c5..176ad346 100644 --- a/nylas/client.py +++ b/nylas/client.py @@ -3,6 +3,7 @@ from nylas.resources.applications import Applications from nylas.resources.auth import Auth from nylas.resources.calendars import Calendars +from nylas.resources.connectors import Connectors from nylas.resources.events import Events from nylas.resources.webhooks import Webhooks @@ -52,6 +53,16 @@ def applications(self) -> Applications: """ return Applications(self.http_client) + @property + def connectors(self) -> Connectors: + """ + Access the Connectors API. + + Returns: + The Connectors API. + """ + return Connectors(self.http_client) + @property def calendars(self) -> Calendars: """ diff --git a/nylas/resources/connectors.py b/nylas/resources/connectors.py new file mode 100644 index 00000000..799f8abb --- /dev/null +++ b/nylas/resources/connectors.py @@ -0,0 +1,103 @@ +from nylas.handler.api_resources import ( + ListableApiResource, + FindableApiResource, + CreatableApiResource, + UpdatableApiResource, + DestroyableApiResource, +) +from nylas.models.auth import Provider +from nylas.models.connectors import ( + ListConnectorQueryParams, + Connector, + CreateConnectorRequest, +) +from nylas.models.response import ListResponse, Response, DeleteResponse + + +class Connectors( + ListableApiResource, + FindableApiResource, + CreatableApiResource, + UpdatableApiResource, + DestroyableApiResource, +): + def list(self, query_params: ListConnectorQueryParams) -> ListResponse[Connector]: + """ + Return all Connectors. + + Args: + query_params: The query parameters to include in the request. + + Returns: + The list of Connectors. + """ + + return super(Connectors, self).list( + path="/v3/connectors", response_type=Connector, query_params=query_params + ) + + def find(self, provider: Provider) -> Response[Connector]: + """ + Return a connector associated with the provider. + + Args: + provider: The provider associated to the connector to retrieve. + + Returns: + The Connector. + """ + return super(Connectors, self).find( + path=f"/v3/connectors/{provider}", + response_type=Connector, + ) + + def create(self, request_body: CreateConnectorRequest) -> Response[Connector]: + """ + Create a connector. + + Args: + request_body: The values to create the connector with. + + Returns: + The created connector. + """ + return super(Connectors, self).create( + path=f"/v3/connectors", + request_body=request_body, + response_type=Connector, + ) + + def update( + self, provider: Provider, request_body: CreateConnectorRequest + ) -> Response[Connector]: + """ + Create a connector. + + Args: + provider: The provider associated to the connector to update. + request_body: The values to update the connector with. + + Returns: + The created connector. + """ + return super(Connectors, self).update( + path=f"/v3/connectors/{provider}", + request_body=request_body, + response_type=Connector, + method="PATCH", + ) + + def destroy(self, provider: Provider) -> DeleteResponse: + """ + Delete a connector. + + Args: + provider: The provider associated to the connector to delete. + + Returns: + The deleted connector. + """ + return super(Connectors, self).destroy( + path=f"/v3/connectors/{provider}", + response_type=Connector, + ) From 047d1c2707fae6f770cb8c36b08bd19e76c61c58 Mon Sep 17 00:00:00 2001 From: Mostafa Rashed <17770919+mrashed-dev@users.noreply.github.com> Date: Tue, 17 Oct 2023 15:41:11 -0400 Subject: [PATCH 4/5] require settings for google and mircosoft --- nylas/models/connectors.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nylas/models/connectors.py b/nylas/models/connectors.py index dcfc6af3..266f4a26 100644 --- a/nylas/models/connectors.py +++ b/nylas/models/connectors.py @@ -81,7 +81,7 @@ class GoogleCreateConnectorRequest(BaseCreateConnectorRequest): scope: The Google OAuth scopes """ - settings: NotRequired[GoogleCreateConnectorSettings] + settings: GoogleCreateConnectorSettings scope: NotRequired[List[str]] @@ -96,7 +96,7 @@ class MicrosoftCreateConnectorRequest(BaseCreateConnectorRequest): scope: The Microsoft OAuth scopes """ - settings: NotRequired[MicrosoftCreateConnectorSettings] + settings: MicrosoftCreateConnectorSettings scope: NotRequired[List[str]] From de61b67e9e0a393e09991aa2fcd9b50028c0a4e5 Mon Sep 17 00:00:00 2001 From: Mostafa Rashed <17770919+mrashed-dev@users.noreply.github.com> Date: Tue, 17 Oct 2023 17:05:19 -0400 Subject: [PATCH 5/5] fix update type mismatch --- nylas/resources/connectors.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nylas/resources/connectors.py b/nylas/resources/connectors.py index 799f8abb..ec171379 100644 --- a/nylas/resources/connectors.py +++ b/nylas/resources/connectors.py @@ -10,6 +10,7 @@ ListConnectorQueryParams, Connector, CreateConnectorRequest, + UpdateConnectorRequest, ) from nylas.models.response import ListResponse, Response, DeleteResponse @@ -68,7 +69,7 @@ def create(self, request_body: CreateConnectorRequest) -> Response[Connector]: ) def update( - self, provider: Provider, request_body: CreateConnectorRequest + self, provider: Provider, request_body: UpdateConnectorRequest ) -> Response[Connector]: """ Create a connector.