Skip to content

Commit

Permalink
🎉 Source Zendesk Sunshine: support oauth (#7976)
Browse files Browse the repository at this point in the history
* add oauth support

* bump version

* add java part

* change date format

* change spec

* upd invalid_configs

* bump version and format
  • Loading branch information
annalvova05 authored Jan 4, 2022
1 parent ee26499 commit 7776dbe
Show file tree
Hide file tree
Showing 13 changed files with 492 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,7 @@
- name: Zendesk Sunshine
sourceDefinitionId: 325e0640-e7b3-4e24-b823-3361008f603f
dockerRepository: airbyte/source-zendesk-sunshine
dockerImageTag: 0.1.0
dockerImageTag: 0.1.1
documentationUrl: https://docs.airbyte.io/integrations/sources/zendesk-sunshine
icon: zendesk.svg
sourceType: api
Expand Down
127 changes: 112 additions & 15 deletions airbyte-config/init/src/main/resources/seed/source_specs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7553,40 +7553,137 @@
path_in_connector_config:
- "credentials"
- "client_secret"
- dockerImage: "airbyte/source-zendesk-sunshine:0.1.0"
- dockerImage: "airbyte/source-zendesk-sunshine:0.1.1"
spec:
documentationUrl: "https://docs.airbyte.io/integrations/sources/zendesk_sunshine"
connectionSpecification:
$schema: "http://json-schema.org/draft-07/schema#"
title: "Zendesk Sunshine Spec"
type: "object"
required:
- "api_token"
- "email"
- "start_date"
- "subdomain"
additionalProperties: false
additionalProperties: true
properties:
api_token:
type: "string"
airbyte_secret: true
description: "API Token. See the <a href=\"https://docs.airbyte.io/integrations/sources/zendesk_sunshine\"\
>docs</a> for information on how to generate this key."
email:
type: "string"
description: "The user email for your Zendesk account"
subdomain:
title: "Subdomain"
type: "string"
description: "The subdomain for your Zendesk Account"
description: "The subdomain for your Zendesk Account."
start_date:
title: "Start Date"
type: "string"
description: "The date from which you'd like to replicate the data"
description: "The date from which you'd like to replicate data for Zendesk\
\ Sunshine API, in the format YYYY-MM-DDT00:00:00Z."
pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
examples: "2021-01-01T00:00:00.000000Z"
examples:
- "2021-01-01T00:00:00Z"
credentials:
title: "Authorization Method"
type: "object"
oneOf:
- type: "object"
title: "OAuth2.0"
required:
- "auth_method"
- "client_id"
- "client_secret"
- "access_token"
properties:
auth_method:
type: "string"
const: "oauth2.0"
enum:
- "oauth2.0"
default: "oauth2.0"
order: 0
client_id:
type: "string"
title: "Client ID"
description: "The Client ID of your OAuth application."
airbyte_secret: true
client_secret:
type: "string"
title: "Client Secret"
description: "The Client Secret of your OAuth application."
airbyte_secret: true
access_token:
type: "string"
title: "Access Token"
description: "Long-term access Token for making authenticated requests."
airbyte_secret: true
- type: "object"
title: "API Token"
required:
- "auth_method"
- "api_token"
- "email"
properties:
auth_method:
type: "string"
const: "api_token"
enum:
- "api_token"
default: "api_token"
order: 1
api_token:
type: "string"
title: "API Token"
description: "API Token. See the <a href=\"https://docs.airbyte.io/integrations/sources/zendesk_sunshine\"\
>docs</a> for information on how to generate this key."
airbyte_secret: true
email:
type: "string"
title: "Email"
description: "The user email for your Zendesk account"
supportsNormalization: false
supportsDBT: false
supported_destination_sync_modes: []
advanced_auth:
auth_flow_type: "oauth2.0"
predicate_key:
- "credentials"
- "auth_method"
predicate_value: "oauth2.0"
oauth_config_specification:
oauth_user_input_from_connector_config_specification:
type: "object"
additionalProperties: false
properties:
subdomain:
type: "string"
path_in_connector_config:
- "subdomain"
complete_oauth_output_specification:
type: "object"
additionalProperties: false
properties:
access_token:
type: "string"
path_in_connector_config:
- "credentials"
- "access_token"
complete_oauth_server_input_specification:
type: "object"
additionalProperties: false
properties:
client_id:
type: "string"
client_secret:
type: "string"
complete_oauth_server_output_specification:
type: "object"
additionalProperties: false
properties:
client_id:
type: "string"
path_in_connector_config:
- "credentials"
- "client_id"
client_secret:
type: "string"
path_in_connector_config:
- "credentials"
- "client_secret"
- dockerImage: "airbyte/source-zendesk-support:0.1.11"
spec:
documentationUrl: "https://docs.airbyte.io/integrations/sources/zendesk-support"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ RUN pip install .
ENV AIRBYTE_ENTRYPOINT "python /airbyte/integration_code/main.py"
ENTRYPOINT ["python", "/airbyte/integration_code/main.py"]

LABEL io.airbyte.version=0.1.0
LABEL io.airbyte.version=0.1.1
LABEL io.airbyte.name=airbyte/source-zendesk-sunshine
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,25 @@ tests:
connection:
- config_path: "secrets/config.json"
status: "succeed"
- config_path: "secrets/config_oauth.json"
status: "succeed"
- config_path: "secrets/config_api_token.json"
status: "succeed"
- config_path: "integration_tests/invalid_config.json"
status: "failed"
- config_path: "integration_tests/invalid_config_api_token.json"
status: "failed"
- config_path: "integration_tests/invalid_config_oauth.json"
status: "failed"
discovery:
- config_path: "secrets/config.json"
basic_read:
- config_path: "secrets/config.json"
configured_catalog_path: "integration_tests/configured_catalog.json"
- config_path: "secrets/config_api_token.json"
configured_catalog_path: "integration_tests/configured_catalog.json"
- config_path: "secrets/config_oauth.json"
configured_catalog_path: "integration_tests/configured_catalog.json"
# incremental: # complex state ( {parent_id: {cur_field: value}} still not supported )
# - config_path: "secrets/config.json"
# configured_catalog_path: "integration_tests/configured_catalog.json"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"credentials": {
"auth_method": "api_token",
"email": "test@ayhghghte.io",
"api_token": "fgfgvf ghnbvg hnghbvnhbvnvbn"
},
"subdomain": "d3v-airbyte",
"start_date": "2020-01-01T00:00:00Z"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"credentials": {
"auth_method": "oauth2.0",
"client_id": "some_client_id",
"client_secret": "some_client_secret",
"access_token": "some_access_token"
},
"subdomain": "d3v-airbyte",
"start_date": "2020-01-01T00:00:00Z"
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


import base64
from typing import Any, List, Mapping, Tuple
from typing import Any, List, Mapping, Tuple, Union

import pendulum
from airbyte_cdk.logger import AirbyteLogger
Expand All @@ -23,11 +23,24 @@ def __init__(self, auth: Tuple[str, str], auth_method: str = "Basic", **kwargs):
super().__init__(token=b64_encoded, auth_method=auth_method, **kwargs)


class ZendeskSunshineAuthenticator:
"""Provides the authentication capabilities for both old and new methods."""

@staticmethod
def get_auth(config: Mapping[str, Any]) -> Union[Base64HttpAuthenticator, TokenAuthenticator]:
credentials = config.get("credentials", {})
token = config.get("api_token") or credentials.get("api_token")
email = config.get("email") or credentials.get("email")
if email and token:
return Base64HttpAuthenticator(auth=(f"{email}/token", token))
return TokenAuthenticator(token=credentials["access_token"])


class SourceZendeskSunshine(AbstractSource):
def check_connection(self, logger: AirbyteLogger, config: Mapping[str, Any]) -> Tuple[bool, Any]:
try:
pendulum.parse(config["start_date"], strict=True)
authenticator = Base64HttpAuthenticator(auth=(f'{config["email"]}/token', config["api_token"]))
authenticator = ZendeskSunshineAuthenticator.get_auth(config)
stream = Limits(authenticator=authenticator, subdomain=config["subdomain"], start_date=pendulum.parse(config["start_date"]))
records = stream.read_records(sync_mode=SyncMode.full_refresh)
next(records)
Expand All @@ -47,7 +60,7 @@ def streams(self, config: Mapping[str, Any]) -> List[Stream]:
After this time is passed we have no data. It will require permanent population, to pass
the test criteria `stream should contain at least 1 record)
"""
authenticator = Base64HttpAuthenticator(auth=(f'{config["email"]}/token', config["api_token"]))
authenticator = ZendeskSunshineAuthenticator.get_auth(config)
args = {"authenticator": authenticator, "subdomain": config["subdomain"], "start_date": config["start_date"]}
return [
ObjectTypes(**args),
Expand Down
Loading

0 comments on commit 7776dbe

Please sign in to comment.