From 530ab77425c3a95b1acb4f9df8bbae73fcbbedec Mon Sep 17 00:00:00 2001 From: Mostafa Rashed <17770919+mrashed-dev@users.noreply.github.com> Date: Tue, 17 Oct 2023 17:21:45 -0400 Subject: [PATCH] Add Connector support (#292) This PR adds support for the connector endpoints. --- nylas/client.py | 11 ++ nylas/models/auth.py | 3 +- nylas/models/calendars.py | 10 +- nylas/models/connectors.py | 162 ++++++++++++++++++++++++++++++ nylas/models/events.py | 11 +- nylas/models/list_query_params.py | 17 ++++ nylas/resources/connectors.py | 104 +++++++++++++++++++ 7 files changed, 307 insertions(+), 11 deletions(-) create mode 100644 nylas/models/connectors.py create mode 100644 nylas/models/list_query_params.py 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/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/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/connectors.py b/nylas/models/connectors.py new file mode 100644 index 00000000..266f4a26 --- /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: 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: 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 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] diff --git a/nylas/resources/connectors.py b/nylas/resources/connectors.py new file mode 100644 index 00000000..ec171379 --- /dev/null +++ b/nylas/resources/connectors.py @@ -0,0 +1,104 @@ +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, + UpdateConnectorRequest, +) +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: UpdateConnectorRequest + ) -> 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, + )