Skip to content

Commit

Permalink
Revert "Revert "Bmoric/add fetch source schema in oauth"" (#19513)
Browse files Browse the repository at this point in the history
* Revert "Revert "Bmoric/add fetch source schema in oauth (#19392)" (#19512)"

This reverts commit f08b84f.

* Fix complete OAuth

* Use var
  • Loading branch information
benmoriceau committed Nov 17, 2022
1 parent e97ece5 commit 90350c1
Show file tree
Hide file tree
Showing 8 changed files with 339 additions and 51 deletions.
4 changes: 4 additions & 0 deletions airbyte-api/src/main/openapi/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4720,6 +4720,8 @@ components:
additionalProperties: true # Oauth parameters like code, state, etc.. will be different per API so we don't specify them in advance
oAuthInputConfiguration:
$ref: "#/components/schemas/OAuthInputConfiguration"
sourceId:
$ref: "#/components/schemas/SourceId"
CompleteDestinationOAuthRequest:
type: object
required:
Expand All @@ -4739,6 +4741,8 @@ components:
additionalProperties: true # Oauth parameters like code, state, etc.. will be different per API so we don't specify them in advance
oAuthInputConfiguration:
$ref: "#/components/schemas/OAuthInputConfiguration"
destinationId:
$ref: "#/components/schemas/DestinationId"
CompleteOAuthResponse:
type: object
additionalProperties: true # Oauth parameters like refresh/access token etc.. will be different per API so we don't specify them in advance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ public static void mergeMaps(final Map<String, Object> originalMap, final String
Entry::getValue)));
}

public static Map<String, String> deserializeToStringMap(JsonNode json) {
return OBJECT_MAPPER.convertValue(json, new TypeReference<>() {});
}

/**
* By the Jackson DefaultPrettyPrinter prints objects with an extra space as follows: {"name" :
* "airbyte"}. We prefer {"name": "airbyte"}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ public static ServerRunnable getServer(final ServerFactory apiFactory,

final HealthCheckHandler healthCheckHandler = new HealthCheckHandler(configRepository);

final OAuthHandler oAuthHandler = new OAuthHandler(configRepository, httpClient, trackingClient);
final OAuthHandler oAuthHandler = new OAuthHandler(configRepository, httpClient, trackingClient, secretsRepositoryReader);

final SourceHandler sourceHandler = new SourceHandler(
configRepository,
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2022 Airbyte, Inc., all rights reserved.
*/

package io.airbyte.server.handlers.helpers;

import com.fasterxml.jackson.databind.JsonNode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class OAuthPathExtractor {

private static final String PROPERTIES = "properties";
private static final String PATH_IN_CONNECTOR_CONFIG = "path_in_connector_config";

public static Map<String, List<String>> extractOauthConfigurationPaths(final JsonNode configuration) {

if (configuration.has(PROPERTIES) && configuration.get(PROPERTIES).isObject()) {
final Map<String, List<String>> result = new HashMap<>();

configuration.get(PROPERTIES).fields().forEachRemaining(entry -> {
final JsonNode value = entry.getValue();
if (value.isObject() && value.has(PATH_IN_CONNECTOR_CONFIG) && value.get(PATH_IN_CONNECTOR_CONFIG).isArray()) {
final List<String> path = new ArrayList<>();
for (final JsonNode pathPart : value.get(PATH_IN_CONNECTOR_CONFIG)) {
path.add(pathPart.textValue());
}
result.put(entry.getKey(), path);
}
});

return result;
} else {
return new HashMap<>();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.fasterxml.jackson.databind.JsonNode;
import io.airbyte.analytics.TrackingClient;
import io.airbyte.api.model.generated.SetInstancewideDestinationOauthParamsRequestBody;
import io.airbyte.api.model.generated.SetInstancewideSourceOauthParamsRequestBody;
import io.airbyte.commons.json.Jsons;
import io.airbyte.config.DestinationOAuthParameter;
import io.airbyte.config.SourceOAuthParameter;
import io.airbyte.config.persistence.ConfigRepository;
import io.airbyte.config.persistence.SecretsRepositoryReader;
import io.airbyte.validation.json.JsonValidationException;
import java.io.IOException;
import java.net.http.HttpClient;
Expand All @@ -34,6 +36,7 @@ class OAuthHandlerTest {
private OAuthHandler handler;
private TrackingClient trackingClient;
private HttpClient httpClient;
private SecretsRepositoryReader secretsRepositoryReader;
private static final String CLIENT_ID = "123";
private static final String CLIENT_ID_KEY = "client_id";
private static final String CLIENT_SECRET_KEY = "client_secret";
Expand All @@ -44,7 +47,8 @@ public void init() {
configRepository = Mockito.mock(ConfigRepository.class);
trackingClient = mock(TrackingClient.class);
httpClient = Mockito.mock(HttpClient.class);
handler = new OAuthHandler(configRepository, httpClient, trackingClient);
secretsRepositoryReader = mock(SecretsRepositoryReader.class);
handler = new OAuthHandler(configRepository, httpClient, trackingClient, secretsRepositoryReader);
}

@Test
Expand Down Expand Up @@ -151,4 +155,77 @@ void resetDestinationInstancewideOauthParams() throws JsonValidationException, I
assertEquals(oauthParameterId, capturedValues.get(1).getOauthParameterId());
}

@Test
void testBuildJsonPathFromOAuthFlowInitParameters() {
final Map<String, List<String>> input = Map.ofEntries(
Map.entry("field1", List.of("1")),
Map.entry("field2", List.of("2", "3")));

final Map<String, String> expected = Map.ofEntries(
Map.entry("field1", "$.1"),
Map.entry("field2", "$.2.3"));

assertEquals(expected, handler.buildJsonPathFromOAuthFlowInitParameters(input));
}

@Test
void testGetOAuthInputConfiguration() {
final JsonNode hydratedConfig = Jsons.deserialize(
"""
{
"field1": "1",
"field2": "2",
"field3": {
"field3_1": "3_1",
"field3_2": "3_2"
}
}
""");

final Map<String, String> pathsToGet = Map.ofEntries(
Map.entry("field1", "$.field1"),
Map.entry("field3_1", "$.field3.field3_1"),
Map.entry("field3_2", "$.field3.field3_2"));

final JsonNode expected = Jsons.deserialize(
"""
{
"field1": "1",
"field3_1": "3_1",
"field3_2": "3_2"
}
""");

assertEquals(expected, handler.getOAuthInputConfiguration(hydratedConfig, pathsToGet));
}

@Test
void testGetOauthFromDBIfNeeded() {
final JsonNode fromInput = Jsons.deserialize(
"""
{
"testMask": "**********",
"testNotMask": "this"
}
""");

final JsonNode fromDb = Jsons.deserialize(
"""
{
"testMask": "mask",
"testNotMask": "notThis"
}
""");

final JsonNode expected = Jsons.deserialize(
"""
{
"testMask": "mask",
"testNotMask": "this"
}
""");

assertEquals(expected, handler.getOauthFromDBIfNeeded(fromDb, fromInput));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2022 Airbyte, Inc., all rights reserved.
*/

package io.airbyte.server.handlers.helper;

import com.fasterxml.jackson.databind.JsonNode;
import io.airbyte.commons.json.Jsons;
import io.airbyte.server.handlers.helpers.OAuthPathExtractor;
import java.util.List;
import java.util.Map;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

class OAuthPathExtractorTest {

@Test
void testExtract() {
final JsonNode input = Jsons.deserialize("""
{
"type": "object",
"additionalProperties": false,
"properties": {
"tenant_id": {
"type": "string",
"path_in_connector_config": ["tenant_id"]
},
"another_property": {
"type": "string",
"path_in_connector_config": ["another", "property"]
}
}
}
""");

final Map<String, List<String>> expected = Map.ofEntries(
Map.entry("tenant_id", List.of("tenant_id")),
Map.entry("another_property", List.of("another", "property")));

Assertions.assertThat(OAuthPathExtractor.extractOauthConfigurationPaths(input))
.containsExactlyInAnyOrderEntriesOf(expected);
}

}
2 changes: 2 additions & 0 deletions docs/reference/api/generated-api-html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10792,6 +10792,7 @@ <h3><a name="CompleteDestinationOAuthRequest"><code>CompleteDestinationOAuthRequ
<div class="param">redirectUrl (optional)</div><div class="param-desc"><span class="param-type"><a href="#string">String</a></span> When completing OAuth flow to gain an access token, some API sometimes requires to verify that the app re-send the redirectUrl that was used when consent was given. </div>
<div class="param">queryParams (optional)</div><div class="param-desc"><span class="param-type"><a href="#AnyType">map[String, oas_any_type_not_mapped]</a></span> The query parameters present in the redirect URL after a user granted consent e.g auth code </div>
<div class="param">oAuthInputConfiguration (optional)</div><div class="param-desc"><span class="param-type"><a href="#OAuthConfiguration">OAuthConfiguration</a></span> </div>
<div class="param">destinationId (optional)</div><div class="param-desc"><span class="param-type"><a href="#UUID">UUID</a></span> format: uuid</div>
</div> <!-- field-items -->
</div>
<div class="model">
Expand All @@ -10803,6 +10804,7 @@ <h3><a name="CompleteSourceOauthRequest"><code>CompleteSourceOauthRequest</code>
<div class="param">redirectUrl (optional)</div><div class="param-desc"><span class="param-type"><a href="#string">String</a></span> When completing OAuth flow to gain an access token, some API sometimes requires to verify that the app re-send the redirectUrl that was used when consent was given. </div>
<div class="param">queryParams (optional)</div><div class="param-desc"><span class="param-type"><a href="#AnyType">map[String, oas_any_type_not_mapped]</a></span> The query parameters present in the redirect URL after a user granted consent e.g auth code </div>
<div class="param">oAuthInputConfiguration (optional)</div><div class="param-desc"><span class="param-type"><a href="#OAuthConfiguration">OAuthConfiguration</a></span> </div>
<div class="param">sourceId (optional)</div><div class="param-desc"><span class="param-type"><a href="#UUID">UUID</a></span> format: uuid</div>
</div> <!-- field-items -->
</div>
<div class="model">
Expand Down

0 comments on commit 90350c1

Please sign in to comment.