From e3b18597716997cb10949fdff5080be3b4fa62ec Mon Sep 17 00:00:00 2001 From: Ella Rohm-Ensing Date: Fri, 13 Dec 2024 16:28:44 -0800 Subject: [PATCH] feat: allow end user to provide oauth app if server creds aren't available (#14775) --- .../server-api/src/main/openapi/config.yaml | 4 +- ...nnectorDefinitionSpecificationHandler.java | 4 +- .../commons/server/handlers/OAuthHandler.java | 72 ++++++++++++++----- ...torDefinitionSpecificationHandlerTest.java | 12 ++-- .../src/core/domain/connector/types.ts | 2 +- .../src/core/services/features/constants.ts | 2 + .../src/core/services/features/types.tsx | 2 +- .../ConnectorForm/ConnectorForm.test.tsx | 5 -- .../Sections/auth/useOauthFlowAdapter.tsx | 9 +-- .../views/Connector/ConnectorForm/utils.ts | 32 +++++++-- 10 files changed, 98 insertions(+), 46 deletions(-) diff --git a/airbyte-api/server-api/src/main/openapi/config.yaml b/airbyte-api/server-api/src/main/openapi/config.yaml index 392df6ef28..39f26104d3 100644 --- a/airbyte-api/server-api/src/main/openapi/config.yaml +++ b/airbyte-api/server-api/src/main/openapi/config.yaml @@ -9317,7 +9317,7 @@ components: $ref: "#/components/schemas/SourceDefinitionSpecification" advancedAuth: $ref: "#/components/schemas/AdvancedAuth" - advancedAuthCredentialsAvailable: + advancedAuthGlobalCredentialsAvailable: type: boolean jobInfo: $ref: "#/components/schemas/SynchronousJobRead" @@ -9762,7 +9762,7 @@ components: $ref: "#/components/schemas/DestinationDefinitionSpecification" advancedAuth: $ref: "#/components/schemas/AdvancedAuth" - advancedAuthCredentialsAvailable: + advancedAuthGlobalCredentialsAvailable: type: boolean jobInfo: $ref: "#/components/schemas/SynchronousJobRead" diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/ConnectorDefinitionSpecificationHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/ConnectorDefinitionSpecificationHandler.java index 27e68fb112..bb53b9c0d9 100644 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/ConnectorDefinitionSpecificationHandler.java +++ b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/ConnectorDefinitionSpecificationHandler.java @@ -166,7 +166,7 @@ SourceDefinitionSpecificationRead getSourceSpecificationRead(final StandardSourc if (advancedAuth.isPresent()) { final Optional sourceOAuthParameter = oAuthService.getSourceOAuthParameterOptional(workspaceId, sourceDefinition.getSourceDefinitionId()); - specRead.setAdvancedAuthCredentialsAvailable(sourceOAuthParameter.isPresent()); + specRead.setAdvancedAuthGlobalCredentialsAvailable(sourceOAuthParameter.isPresent()); } return specRead; @@ -190,7 +190,7 @@ DestinationDefinitionSpecificationRead getDestinationSpecificationRead(final Sta if (advancedAuth.isPresent()) { final Optional destinationOAuthParameter = oAuthService.getDestinationOAuthParameterOptional(workspaceId, destinationDefinition.getDestinationDefinitionId()); - specRead.setAdvancedAuthCredentialsAvailable(destinationOAuthParameter.isPresent()); + specRead.setAdvancedAuthGlobalCredentialsAvailable(destinationOAuthParameter.isPresent()); } return specRead; diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/OAuthHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/OAuthHandler.java index 8119124d59..3764e85bd6 100644 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/OAuthHandler.java +++ b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/OAuthHandler.java @@ -66,6 +66,7 @@ import io.airbyte.persistence.job.factory.OAuthConfigSupplier; import io.airbyte.persistence.job.tracker.TrackingMetadata; import io.airbyte.protocol.models.ConnectorSpecification; +import io.airbyte.protocol.models.OAuthConfigSpecification; import io.airbyte.validation.json.JsonValidationException; import jakarta.inject.Named; import jakarta.inject.Singleton; @@ -147,10 +148,16 @@ public OAuthConsentRead getSourceOAuthConsent(final SourceOauthConsentRequest so final Map metadata = TrackingMetadata.generateSourceDefinitionMetadata(sourceDefinition, sourceVersion); final OAuthConsentRead result; - final JsonNode sourceOAuthParamConfig = - getSourceOAuthParamConfig(sourceOauthConsentRequest.getWorkspaceId(), sourceDefinition.getSourceDefinitionId()); + final Optional paramOptional = oAuthService + .getSourceOAuthParameterWithSecretsOptional(sourceOauthConsentRequest.getWorkspaceId(), sourceOauthConsentRequest.getSourceDefinitionId()); + final JsonNode sourceOAuthParamConfig = paramOptional.isPresent() + ? MoreOAuthParameters.flattenOAuthConfig(paramOptional.get().getConfiguration()) + : Jsons.emptyObject(); if (OAuthConfigSupplier.hasOAuthConfigSpecification(spec)) { + final OAuthConfigSpecification oauthConfigSpecification = spec.getAdvancedAuth().getOauthConfigSpecification(); + OAuthHelper.updateOauthConfigToAcceptAdditionalUserInputProperties(oauthConfigSpecification); + final JsonNode oAuthInputConfigurationForConsent; if (sourceOauthConsentRequest.getSourceId() == null) { @@ -168,12 +175,14 @@ public OAuthConsentRead getSourceOAuthConsent(final SourceOauthConsentRequest so sourceOauthConsentRequest.getoAuthInputConfiguration()); } + final JsonNode oAuthInputConfigValues = Jsons.mergeNodes(sourceOAuthParamConfig, oAuthInputConfigurationForConsent); + result = new OAuthConsentRead().consentUrl(oAuthFlowImplementation.getSourceConsentUrl( sourceOauthConsentRequest.getWorkspaceId(), sourceOauthConsentRequest.getSourceDefinitionId(), sourceOauthConsentRequest.getRedirectUrl(), - oAuthInputConfigurationForConsent, - spec.getAdvancedAuth().getOauthConfigSpecification(), sourceOAuthParamConfig)); + oAuthInputConfigValues, + oauthConfigSpecification, oAuthInputConfigValues)); } else { result = new OAuthConsentRead().consentUrl(oAuthFlowImplementation.getSourceConsentUrl( sourceOauthConsentRequest.getWorkspaceId(), @@ -213,10 +222,16 @@ public OAuthConsentRead getDestinationOAuthConsent(final DestinationOauthConsent final Map metadata = TrackingMetadata.generateDestinationDefinitionMetadata(destinationDefinition, destinationVersion); final OAuthConsentRead result; - final JsonNode destinationOAuthParamConfig = getDestinationOAuthParamConfig( + final Optional paramOptional = oAuthService.getDestinationOAuthParameterWithSecretsOptional( destinationOauthConsentRequest.getWorkspaceId(), destinationOauthConsentRequest.getDestinationDefinitionId()); + final JsonNode destinationOAuthParamConfig = paramOptional.isPresent() + ? MoreOAuthParameters.flattenOAuthConfig(paramOptional.get().getConfiguration()) + : Jsons.emptyObject(); if (OAuthConfigSupplier.hasOAuthConfigSpecification(spec)) { + final OAuthConfigSpecification oauthConfigSpecification = spec.getAdvancedAuth().getOauthConfigSpecification(); + OAuthHelper.updateOauthConfigToAcceptAdditionalUserInputProperties(oauthConfigSpecification); + final JsonNode oAuthInputConfigurationForConsent; if (destinationOauthConsentRequest.getDestinationId() == null) { @@ -235,12 +250,14 @@ public OAuthConsentRead getDestinationOAuthConsent(final DestinationOauthConsent } + final JsonNode oAuthInputConfigValues = Jsons.mergeNodes(destinationOAuthParamConfig, oAuthInputConfigurationForConsent); + result = new OAuthConsentRead().consentUrl(oAuthFlowImplementation.getDestinationConsentUrl( destinationOauthConsentRequest.getWorkspaceId(), destinationOauthConsentRequest.getDestinationDefinitionId(), destinationOauthConsentRequest.getRedirectUrl(), - oAuthInputConfigurationForConsent, - spec.getAdvancedAuth().getOauthConfigSpecification(), destinationOAuthParamConfig)); + oAuthInputConfigValues, + spec.getAdvancedAuth().getOauthConfigSpecification(), oAuthInputConfigValues)); } else { result = new OAuthConsentRead().consentUrl(oAuthFlowImplementation.getDestinationConsentUrl( destinationOauthConsentRequest.getWorkspaceId(), @@ -283,9 +300,16 @@ public CompleteOAuthResponse completeSourceOAuth(final CompleteSourceOauthReques final Map metadata = TrackingMetadata.generateSourceDefinitionMetadata(sourceDefinition, sourceVersion); final Map result; - final JsonNode sourceOAuthParamConfig = - getSourceOAuthParamConfig(completeSourceOauthRequest.getWorkspaceId(), sourceDefinition.getSourceDefinitionId()); + final Optional paramOptional = oAuthService + .getSourceOAuthParameterWithSecretsOptional(completeSourceOauthRequest.getWorkspaceId(), completeSourceOauthRequest.getSourceDefinitionId()); + final JsonNode sourceOAuthParamConfig = paramOptional.isPresent() + ? MoreOAuthParameters.flattenOAuthConfig(paramOptional.get().getConfiguration()) + : Jsons.emptyObject(); + if (OAuthConfigSupplier.hasOAuthConfigSpecification(spec)) { + final OAuthConfigSpecification oauthConfigSpecification = spec.getAdvancedAuth().getOauthConfigSpecification(); + OAuthHelper.updateOauthConfigToAcceptAdditionalUserInputProperties(oauthConfigSpecification); + final JsonNode oAuthInputConfigurationForConsent; if (completeSourceOauthRequest.getSourceId() == null) { @@ -303,14 +327,16 @@ public CompleteOAuthResponse completeSourceOAuth(final CompleteSourceOauthReques completeSourceOauthRequest.getoAuthInputConfiguration()); } + final JsonNode oAuthInputConfigValues = Jsons.mergeNodes(sourceOAuthParamConfig, oAuthInputConfigurationForConsent); + result = oAuthFlowImplementation.completeSourceOAuth( completeSourceOauthRequest.getWorkspaceId(), completeSourceOauthRequest.getSourceDefinitionId(), completeSourceOauthRequest.getQueryParams(), completeSourceOauthRequest.getRedirectUrl(), - oAuthInputConfigurationForConsent, - spec.getAdvancedAuth().getOauthConfigSpecification(), - sourceOAuthParamConfig); + oAuthInputConfigValues, + oauthConfigSpecification, + oAuthInputConfigValues); } else { // deprecated but this path is kept for connectors that don't define OAuth Spec yet result = oAuthFlowImplementation.completeSourceOAuth( @@ -344,10 +370,16 @@ public CompleteOAuthResponse completeDestinationOAuth(final CompleteDestinationO final Map metadata = TrackingMetadata.generateDestinationDefinitionMetadata(destinationDefinition, destinationVersion); final Map result; - final JsonNode destinationOAuthParamConfig = getDestinationOAuthParamConfig( + final Optional paramOptional = oAuthService.getDestinationOAuthParameterWithSecretsOptional( completeDestinationOAuthRequest.getWorkspaceId(), completeDestinationOAuthRequest.getDestinationDefinitionId()); + final JsonNode destinationOAuthParamConfig = paramOptional.isPresent() + ? MoreOAuthParameters.flattenOAuthConfig(paramOptional.get().getConfiguration()) + : Jsons.emptyObject(); if (OAuthConfigSupplier.hasOAuthConfigSpecification(spec)) { + final OAuthConfigSpecification oauthConfigSpecification = spec.getAdvancedAuth().getOauthConfigSpecification(); + OAuthHelper.updateOauthConfigToAcceptAdditionalUserInputProperties(oauthConfigSpecification); + final JsonNode oAuthInputConfigurationForConsent; if (completeDestinationOAuthRequest.getDestinationId() == null) { @@ -366,13 +398,15 @@ public CompleteOAuthResponse completeDestinationOAuth(final CompleteDestinationO } + final JsonNode oAuthInputConfigValues = Jsons.mergeNodes(destinationOAuthParamConfig, oAuthInputConfigurationForConsent); + result = oAuthFlowImplementation.completeDestinationOAuth( completeDestinationOAuthRequest.getWorkspaceId(), completeDestinationOAuthRequest.getDestinationDefinitionId(), completeDestinationOAuthRequest.getQueryParams(), completeDestinationOAuthRequest.getRedirectUrl(), - oAuthInputConfigurationForConsent, - spec.getAdvancedAuth().getOauthConfigSpecification(), destinationOAuthParamConfig); + oAuthInputConfigValues, + oauthConfigSpecification, oAuthInputConfigValues); } else { // deprecated but this path is kept for connectors that don't define OAuth Spec yet result = oAuthFlowImplementation.completeDestinationOAuth( @@ -441,11 +475,15 @@ public void setDestinationInstancewideOauthParams(final SetInstancewideDestinati private JsonNode getOAuthInputConfigurationForConsent(final ConnectorSpecification spec, final JsonNode hydratedSourceConnectionConfiguration, final JsonNode oAuthInputConfiguration) { - final Map fieldsToGet = + final Map configOauthFields = buildJsonPathFromOAuthFlowInitParameters(OAuthHelper.extractOauthConfigurationPaths( spec.getAdvancedAuth().getOauthConfigSpecification().getOauthUserInputFromConnectorConfigSpecification())); + final Map serverOrConfigOauthFields = buildJsonPathFromOAuthFlowInitParameters(OAuthHelper.extractOauthConfigurationPaths( + spec.getAdvancedAuth().getOauthConfigSpecification().getCompleteOauthServerOutputSpecification())); + configOauthFields.putAll(serverOrConfigOauthFields); - final JsonNode oAuthInputConfigurationFromDB = getOAuthInputConfiguration(hydratedSourceConnectionConfiguration, fieldsToGet); + final JsonNode oAuthInputConfigurationFromDB = getOAuthInputConfiguration(hydratedSourceConnectionConfiguration, configOauthFields); + LOGGER.warn("oAuthInputConfigurationFromDB: {}", oAuthInputConfigurationFromDB); return getOauthFromDBIfNeeded(oAuthInputConfigurationFromDB, oAuthInputConfiguration); } diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/ConnectorDefinitionSpecificationHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/ConnectorDefinitionSpecificationHandlerTest.java index 02fb00ed72..bb5268aa8e 100644 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/ConnectorDefinitionSpecificationHandlerTest.java +++ b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/ConnectorDefinitionSpecificationHandlerTest.java @@ -303,11 +303,11 @@ void testDestinationSyncModeEnrichmentWithoutOverwrite(final boolean supportsRef @ValueSource(booleans = {true, false}) @ParameterizedTest - void getDestinationSpecificationReadAdvancedAuth(final boolean advancedAuthCredentialsAvailable) throws IOException { + void getDestinationSpecificationReadAdvancedAuth(final boolean advancedAuthGlobalCredentialsAvailable) throws IOException { final UUID workspaceId = UUID.randomUUID(); final UUID destinationDefinitionId = UUID.randomUUID(); when(oAuthService.getDestinationOAuthParameterOptional(workspaceId, destinationDefinitionId)) - .thenReturn(advancedAuthCredentialsAvailable ? Optional.of(new DestinationOAuthParameter()) : Optional.empty()); + .thenReturn(advancedAuthGlobalCredentialsAvailable ? Optional.of(new DestinationOAuthParameter()) : Optional.empty()); final DestinationDefinitionIdWithWorkspaceId destinationDefinitionIdWithWorkspaceId = new DestinationDefinitionIdWithWorkspaceId().destinationDefinitionId(destinationDefinitionId).workspaceId(workspaceId); @@ -325,16 +325,16 @@ void getDestinationSpecificationReadAdvancedAuth(final boolean advancedAuthCrede connectorDefinitionSpecificationHandler.getDestinationSpecificationRead(destinationDefinition, connectorSpecification, true, workspaceId); verify(oAuthService).getDestinationOAuthParameterOptional(workspaceId, destinationDefinitionId); - assertEquals(advancedAuthCredentialsAvailable, response.getAdvancedAuthCredentialsAvailable()); + assertEquals(advancedAuthGlobalCredentialsAvailable, response.getAdvancedAuthGlobalCredentialsAvailable()); } @ValueSource(booleans = {true, false}) @ParameterizedTest - void getSourceSpecificationReadAdvancedAuth(final boolean advancedAuthCredentialsAvailable) throws IOException { + void getSourceSpecificationReadAdvancedAuth(final boolean advancedAuthGlobalCredentialsAvailable) throws IOException { final UUID workspaceId = UUID.randomUUID(); final UUID sourceDefinitionId = UUID.randomUUID(); when(oAuthService.getSourceOAuthParameterOptional(workspaceId, sourceDefinitionId)) - .thenReturn(advancedAuthCredentialsAvailable ? Optional.of(new SourceOAuthParameter()) : Optional.empty()); + .thenReturn(advancedAuthGlobalCredentialsAvailable ? Optional.of(new SourceOAuthParameter()) : Optional.empty()); final SourceDefinitionIdWithWorkspaceId sourceDefinitionIdWithWorkspaceId = new SourceDefinitionIdWithWorkspaceId().sourceDefinitionId(sourceDefinitionId).workspaceId(workspaceId); @@ -352,7 +352,7 @@ void getSourceSpecificationReadAdvancedAuth(final boolean advancedAuthCredential connectorDefinitionSpecificationHandler.getSourceSpecificationRead(sourceDefinition, connectorSpecification, workspaceId); verify(oAuthService).getSourceOAuthParameterOptional(workspaceId, sourceDefinitionId); - assertEquals(advancedAuthCredentialsAvailable, response.getAdvancedAuthCredentialsAvailable()); + assertEquals(advancedAuthGlobalCredentialsAvailable, response.getAdvancedAuthGlobalCredentialsAvailable()); } } diff --git a/airbyte-webapp/src/core/domain/connector/types.ts b/airbyte-webapp/src/core/domain/connector/types.ts index a80e2050b0..f2a62a76b5 100644 --- a/airbyte-webapp/src/core/domain/connector/types.ts +++ b/airbyte-webapp/src/core/domain/connector/types.ts @@ -22,7 +22,7 @@ export type ConnectorDefinitionOrEnterpriseStub = ConnectorDefinition | Enterpri export type SourceDefinitionSpecificationDraft = Pick< SourceDefinitionSpecificationRead, - "documentationUrl" | "connectionSpecification" | "advancedAuth" + "documentationUrl" | "connectionSpecification" | "advancedAuth" | "advancedAuthGlobalCredentialsAvailable" >; export type ConnectorDefinitionSpecificationRead = diff --git a/airbyte-webapp/src/core/services/features/constants.ts b/airbyte-webapp/src/core/services/features/constants.ts index 551c172a3a..0898e4dc88 100644 --- a/airbyte-webapp/src/core/services/features/constants.ts +++ b/airbyte-webapp/src/core/services/features/constants.ts @@ -2,6 +2,7 @@ import { FeatureItem } from "./types"; export const defaultOssFeatures = [ FeatureItem.AllowAutoDetectSchema, + FeatureItem.AllowOAuthConnector, FeatureItem.AllowUpdateConnectors, FeatureItem.AllowUploadCustomImage, FeatureItem.EnterpriseUpsell, @@ -10,6 +11,7 @@ export const defaultOssFeatures = [ export const defaultEnterpriseFeatures = [ ...defaultOssFeatures, FeatureItem.AllowAllRBACRoles, + FeatureItem.AllowOAuthConnector, FeatureItem.ConnectionHistoryGraphs, FeatureItem.DiagnosticsExport, FeatureItem.DisplayOrganizationUsers, diff --git a/airbyte-webapp/src/core/services/features/types.tsx b/airbyte-webapp/src/core/services/features/types.tsx index 39bbadbc4c..67ff9f4284 100644 --- a/airbyte-webapp/src/core/services/features/types.tsx +++ b/airbyte-webapp/src/core/services/features/types.tsx @@ -9,7 +9,7 @@ export enum FeatureItem { AllowUploadCustomImage = "ALLOW_UPLOAD_CUSTOM_IMAGE", AllowDBTCloudIntegration = "ALLOW_DBT_CLOUD_INTEGRATION", AllowUpdateConnectors = "ALLOW_UPDATE_CONNECTORS", - AllowOAuthConnector = "ALLOW_OAUTH_CONNECTOR", + AllowOAuthConnector = "ALLOW_OAUTH_CONNECTOR", // TODO (ella) : remove this feature flag AllowChangeDataGeographies = "ALLOW_CHANGE_DATA_GEOGRAPHIES", CloudForTeamsBranding = "CLOUD_FOR_TEAMS_BRANDING", CloudForTeamsUpsell = "CLOUD_FOR_TEAMS_UPSELLING", diff --git a/airbyte-webapp/src/views/Connector/ConnectorForm/ConnectorForm.test.tsx b/airbyte-webapp/src/views/Connector/ConnectorForm/ConnectorForm.test.tsx index 9b6ab578e6..b51d8ca90f 100644 --- a/airbyte-webapp/src/views/Connector/ConnectorForm/ConnectorForm.test.tsx +++ b/airbyte-webapp/src/views/Connector/ConnectorForm/ConnectorForm.test.tsx @@ -1007,11 +1007,6 @@ describe("Connector form", () => { }, }); } - it("should render regular inputs for auth fields", async () => { - const container = await renderNewOAuthForm({ disableOAuth: true }); - expect(getInputByName(container, "connectionConfiguration.credentials.access_token")).toBeInTheDocument(); - expect(getOAuthButton(container)).not.toBeInTheDocument(); - }); it("should render the oauth button", async () => { const container = await renderNewOAuthForm(); diff --git a/airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/auth/useOauthFlowAdapter.tsx b/airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/auth/useOauthFlowAdapter.tsx index 6fb24d30b8..8b4cb78edd 100644 --- a/airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/auth/useOauthFlowAdapter.tsx +++ b/airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/auth/useOauthFlowAdapter.tsx @@ -14,7 +14,7 @@ import { useAuthentication } from "views/Connector/ConnectorForm/useAuthenticati import { useNotificationService } from "../../../../../../hooks/services/Notification"; import { useConnectorForm } from "../../../connectorFormContext"; import { ConnectorFormValues } from "../../../types"; -import { makeConnectionConfigurationPath, serverProvidedOauthPaths } from "../../../utils"; +import { makeConnectionConfigurationPath, serverProvidedOauthPaths, userProvidedOauthInputPaths } from "../../../utils"; interface Credentials { credentials: AdvancedAuth; @@ -74,12 +74,7 @@ function useFormOauthAdapter( done: done || hasAuthFieldValues, hasRun, run: async () => { - const oauthInputProperties = - ( - connector?.advancedAuth?.oauthConfigSpecification?.oauthUserInputFromConnectorConfigSpecification as { - properties: Array<{ path_in_connector_config: string[] }>; - } - )?.properties ?? {}; + const oauthInputProperties = userProvidedOauthInputPaths(connector); if (!isEmpty(oauthInputProperties)) { const oauthInputFields = diff --git a/airbyte-webapp/src/views/Connector/ConnectorForm/utils.ts b/airbyte-webapp/src/views/Connector/ConnectorForm/utils.ts index 90c0984c20..8ad4403809 100644 --- a/airbyte-webapp/src/views/Connector/ConnectorForm/utils.ts +++ b/airbyte-webapp/src/views/Connector/ConnectorForm/utils.ts @@ -1,6 +1,6 @@ import toLower from "lodash/toLower"; -import { AdvancedAuth } from "core/api/types/AirbyteClient"; +import { AdvancedAuth, OAuthConfigSpecification } from "core/api/types/AirbyteClient"; import { FormBlock } from "core/form/types"; import { naturalComparator } from "core/utils/objects"; @@ -25,17 +25,39 @@ export function authPredicateMatchesPath(path: string, spec?: { advancedAuth?: A type OAuthOutputSpec = { properties: Record } | undefined; +export function getOAuthPaths( + path: keyof OAuthConfigSpecification, + connector?: ConnectorDefinitionSpecificationRead +): Record { + return { + ...((connector?.advancedAuth?.oauthConfigSpecification?.[path] as OAuthOutputSpec)?.properties ?? {}), + }; +} + export function serverProvidedOauthPaths( connector?: ConnectorDefinitionSpecificationRead ): Record { + if (connector?.advancedAuthGlobalCredentialsAvailable === false) { + return getOAuthPaths("completeOAuthOutputSpecification", connector); + } return { - ...((connector?.advancedAuth?.oauthConfigSpecification?.completeOAuthOutputSpecification as OAuthOutputSpec) - ?.properties ?? {}), - ...((connector?.advancedAuth?.oauthConfigSpecification?.completeOAuthServerOutputSpecification as OAuthOutputSpec) - ?.properties ?? {}), + ...getOAuthPaths("completeOAuthServerOutputSpecification", connector), + ...getOAuthPaths("completeOAuthOutputSpecification", connector), }; } +export function userProvidedOauthInputPaths( + connector?: ConnectorDefinitionSpecificationRead +): Record { + if (connector?.advancedAuthGlobalCredentialsAvailable === false) { + return { + ...getOAuthPaths("completeOAuthServerOutputSpecification", connector), + ...getOAuthPaths("oauthUserInputFromConnectorConfigSpecification", connector), + }; + } + return getOAuthPaths("oauthUserInputFromConnectorConfigSpecification", connector); +} + export function OrderComparator(a: FormBlock, b: FormBlock): number { const aIsNumber = Number.isInteger(a.order); const bIsNumber = Number.isInteger(b.order);