From cbfec3e04d5dfdd4e27d1b09774d4d1aca51d594 Mon Sep 17 00:00:00 2001 From: Christophe Duong Date: Thu, 2 Sep 2021 17:21:49 +0200 Subject: [PATCH] Start airbyte-oauth module --- airbyte-api/src/main/openapi/config.yaml | 2 +- airbyte-oauth/build.gradle | 7 +++ .../oauth/OAuthFlowImplementation.java | 36 +++++++++++++ .../oauth/OAuthImplementationFactory.java | 45 ++++++++++++++++ airbyte-server/build.gradle | 1 + .../airbyte/server/apis/ConfigurationApi.java | 2 +- .../airbyte/server/handlers/OAuthHandler.java | 51 ++++++++++++++----- .../api/generated-api-html/index.html | 2 +- settings.gradle | 1 + 9 files changed, 131 insertions(+), 16 deletions(-) create mode 100644 airbyte-oauth/build.gradle create mode 100644 airbyte-oauth/src/main/java/io/airbyte/oauth/OAuthFlowImplementation.java create mode 100644 airbyte-oauth/src/main/java/io/airbyte/oauth/OAuthImplementationFactory.java diff --git a/airbyte-api/src/main/openapi/config.yaml b/airbyte-api/src/main/openapi/config.yaml index 9e1f726455f8..8a9434307e23 100644 --- a/airbyte-api/src/main/openapi/config.yaml +++ b/airbyte-api/src/main/openapi/config.yaml @@ -2985,7 +2985,7 @@ components: required: - destinationDefinitionId properties: - sourceDefinitionId: + destinationDefinitionId: $ref: "#/components/schemas/DestinationDefinitionId" workspaceId: $ref: "#/components/schemas/WorkspaceId" diff --git a/airbyte-oauth/build.gradle b/airbyte-oauth/build.gradle new file mode 100644 index 000000000000..19ac6c1facd0 --- /dev/null +++ b/airbyte-oauth/build.gradle @@ -0,0 +1,7 @@ +plugins { + id "java-library" +} + +dependencies { + +} diff --git a/airbyte-oauth/src/main/java/io/airbyte/oauth/OAuthFlowImplementation.java b/airbyte-oauth/src/main/java/io/airbyte/oauth/OAuthFlowImplementation.java new file mode 100644 index 000000000000..1b114d563d3c --- /dev/null +++ b/airbyte-oauth/src/main/java/io/airbyte/oauth/OAuthFlowImplementation.java @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (c) 2020 Airbyte + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package io.airbyte.oauth; + +import java.util.Map; +import java.util.UUID; + +public interface OAuthFlowImplementation { + + String getConsentUrl(); + + Map completeOAuth(UUID workspaceId, Map queryParams); + +} diff --git a/airbyte-oauth/src/main/java/io/airbyte/oauth/OAuthImplementationFactory.java b/airbyte-oauth/src/main/java/io/airbyte/oauth/OAuthImplementationFactory.java new file mode 100644 index 000000000000..1354b201de3e --- /dev/null +++ b/airbyte-oauth/src/main/java/io/airbyte/oauth/OAuthImplementationFactory.java @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (c) 2020 Airbyte + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package io.airbyte.oauth; + +import com.google.common.collect.ImmutableMap; +import java.util.Map; + +public class OAuthImplementationFactory { + + static final Map OAUTH_FLOW_MAPPING = + ImmutableMap.builder() + .build(); + + public static OAuthFlowImplementation create(String imageName) { + if (OAUTH_FLOW_MAPPING.containsKey(imageName)) { + return OAUTH_FLOW_MAPPING.get(imageName); + } else { + throw new IllegalStateException( + String.format("Requested OAuth implementation for %s, but it is not included in the oauth mapping.", imageName)); + } + } + +} diff --git a/airbyte-server/build.gradle b/airbyte-server/build.gradle index 4bb80a5ddf33..13dfebf093ab 100644 --- a/airbyte-server/build.gradle +++ b/airbyte-server/build.gradle @@ -70,6 +70,7 @@ dependencies { implementation project(":airbyte-json-validation") implementation project(':airbyte-migration') implementation project(':airbyte-notification') + implementation project(':airbyte-oauth') implementation project(':airbyte-protocol:models') implementation project(':airbyte-scheduler:client') implementation project(':airbyte-scheduler:models') diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/ConfigurationApi.java b/airbyte-server/src/main/java/io/airbyte/server/apis/ConfigurationApi.java index f481fb112c00..10d21a6480f0 100644 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/ConfigurationApi.java +++ b/airbyte-server/src/main/java/io/airbyte/server/apis/ConfigurationApi.java @@ -196,12 +196,12 @@ public ConfigurationApi(final ConfigRepository configRepository, operationsHandler); webBackendSourceHandler = new WebBackendSourceHandler(sourceHandler, schedulerHandler, workspaceHelper); webBackendDestinationHandler = new WebBackendDestinationHandler(destinationHandler, schedulerHandler, workspaceHelper); + oAuthHandler = new OAuthHandler(configRepository); healthCheckHandler = new HealthCheckHandler(configRepository); archiveHandler = new ArchiveHandler(configs.getAirbyteVersion(), configRepository, jobPersistence, workspaceHelper, archiveTtlManager); logsHandler = new LogsHandler(); openApiConfigHandler = new OpenApiConfigHandler(); dbMigrationHandler = new DbMigrationHandler(configsDatabase, jobsDatabase); - oAuthHandler = new OAuthHandler(); this.configs = configs; } diff --git a/airbyte-server/src/main/java/io/airbyte/server/handlers/OAuthHandler.java b/airbyte-server/src/main/java/io/airbyte/server/handlers/OAuthHandler.java index 84fed43c8c09..27c543cb232a 100644 --- a/airbyte-server/src/main/java/io/airbyte/server/handlers/OAuthHandler.java +++ b/airbyte-server/src/main/java/io/airbyte/server/handlers/OAuthHandler.java @@ -29,29 +29,54 @@ import io.airbyte.api.model.DestinationOauthConsentRequest; import io.airbyte.api.model.OAuthConsentRead; import io.airbyte.api.model.SourceOauthConsentRequest; -import io.airbyte.server.errors.ApplicationErrorKnownException; +import io.airbyte.config.StandardDestinationDefinition; +import io.airbyte.config.StandardSourceDefinition; +import io.airbyte.config.persistence.ConfigNotFoundException; +import io.airbyte.config.persistence.ConfigRepository; +import io.airbyte.oauth.OAuthFlowImplementation; +import io.airbyte.oauth.OAuthImplementationFactory; +import io.airbyte.validation.json.JsonValidationException; +import java.io.IOException; import java.util.Map; public class OAuthHandler { - public OAuthConsentRead getSourceOAuthConsent(SourceOauthConsentRequest sourceDefinitionIdRequestBody) { - // TODO: Implement OAuth module to be called here https://github.com/airbytehq/airbyte/issues/5641 - throw new ApplicationErrorKnownException("Source connector does not supports OAuth yet."); + private final ConfigRepository configRepository; + + public OAuthHandler(ConfigRepository configRepository) { + this.configRepository = configRepository; + } + + public OAuthConsentRead getSourceOAuthConsent(SourceOauthConsentRequest sourceDefinitionIdRequestBody) + throws JsonValidationException, ConfigNotFoundException, IOException { + final StandardSourceDefinition standardSourceDefinition = configRepository + .getStandardSourceDefinition(sourceDefinitionIdRequestBody.getSourceDefinitionId()); + final OAuthFlowImplementation oAuthFlowImplementation = OAuthImplementationFactory.create(standardSourceDefinition.getDockerRepository()); + return new OAuthConsentRead().consentUrl(oAuthFlowImplementation.getConsentUrl()); } - public OAuthConsentRead getDestinationOAuthConsent(DestinationOauthConsentRequest destinationDefinitionIdRequestBody) { - // TODO: Implement OAuth module to be called here https://github.com/airbytehq/airbyte/issues/5641 - throw new ApplicationErrorKnownException("Destination connector does not supports OAuth yet."); + public OAuthConsentRead getDestinationOAuthConsent(DestinationOauthConsentRequest destinationDefinitionIdRequestBody) + throws JsonValidationException, ConfigNotFoundException, IOException { + final StandardDestinationDefinition standardDestinationDefinition = + configRepository.getStandardDestinationDefinition(destinationDefinitionIdRequestBody.getDestinationDefinitionId()); + final OAuthFlowImplementation oAuthFlowImplementation = OAuthImplementationFactory.create(standardDestinationDefinition.getDockerRepository()); + return new OAuthConsentRead().consentUrl(oAuthFlowImplementation.getConsentUrl()); } - public Map completeSourceOAuth(CompleteSourceOauthRequest oauthSourceRequestBody) { - // TODO: Implement OAuth module to be called here https://github.com/airbytehq/airbyte/issues/5641 - throw new ApplicationErrorKnownException("Source connector does not supports OAuth yet."); + public Map completeSourceOAuth(CompleteSourceOauthRequest oauthSourceRequestBody) + throws JsonValidationException, ConfigNotFoundException, IOException { + final StandardSourceDefinition standardSourceDefinition = + configRepository.getStandardSourceDefinition(oauthSourceRequestBody.getSourceDefinitionId()); + final OAuthFlowImplementation oAuthFlowImplementation = OAuthImplementationFactory.create(standardSourceDefinition.getDockerRepository()); + return oAuthFlowImplementation.completeOAuth(oauthSourceRequestBody.getWorkspaceId(), oauthSourceRequestBody.getQueryParams()); } - public Map completeDestinationOAuth(CompleteDestinationOAuthRequest oauthDestinationRequestBody) { - // TODO: Implement OAuth module to be called here https://github.com/airbytehq/airbyte/issues/5641 - throw new ApplicationErrorKnownException("Destination connector does not supports OAuth yet."); + public Map completeDestinationOAuth(CompleteDestinationOAuthRequest oauthDestinationRequestBody) + throws JsonValidationException, ConfigNotFoundException, IOException { + final StandardDestinationDefinition standardDestinationDefinition = + configRepository.getStandardDestinationDefinition(oauthDestinationRequestBody.getDestinationDefinitionId()); + final OAuthFlowImplementation oAuthFlowImplementation = OAuthImplementationFactory.create(standardDestinationDefinition.getDockerRepository()); + return oAuthFlowImplementation.completeOAuth(oauthDestinationRequestBody.getWorkspaceId(), oauthDestinationRequestBody.getQueryParams()); } } diff --git a/docs/reference/api/generated-api-html/index.html b/docs/reference/api/generated-api-html/index.html index 88e4a9bd63ef..c526bc29908f 100644 --- a/docs/reference/api/generated-api-html/index.html +++ b/docs/reference/api/generated-api-html/index.html @@ -6311,7 +6311,7 @@

DestinationIdRequestBody - <

DestinationOauthConsentRequest - Up

-
sourceDefinitionId (optional)
UUID format: uuid
+
destinationDefinitionId
UUID format: uuid
workspaceId (optional)
UUID format: uuid
diff --git a/settings.gradle b/settings.gradle index dea660c49074..57f764f59ef0 100644 --- a/settings.gradle +++ b/settings.gradle @@ -46,6 +46,7 @@ if(!System.getenv().containsKey("SUB_BUILD") || System.getenv().get("SUB_BUILD") include ':airbyte-e2e-testing' include ':airbyte-migration' include ':airbyte-notification' + include ':airbyte-oauth' include ':airbyte-scheduler:app' include ':airbyte-scheduler:client' include ':airbyte-scheduler:models'