Skip to content

Commit 8dcaf25

Browse files
authored
return auth spec in the API when getting definition specification (#6121)
1 parent 2b7c56e commit 8dcaf25

File tree

4 files changed

+137
-3
lines changed

4 files changed

+137
-3
lines changed

airbyte-api/src/main/openapi/config.yaml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1906,6 +1906,34 @@ components:
19061906
description: The specification for what values are required to configure the sourceDefinition.
19071907
type: object
19081908
example: { user: { type: string } }
1909+
SourceAuthSpecification:
1910+
$ref: "#/components/schemas/AuthSpecification"
1911+
AuthSpecification:
1912+
type: object
1913+
properties:
1914+
auth_type:
1915+
type: string
1916+
enum: ["oauth2.0"] # Future auth types should be added here
1917+
oauth2Specification:
1918+
"$ref": "#/components/schemas/OAuth2Specification"
1919+
OAuth2Specification:
1920+
description: An object containing any metadata needed to describe this connector's Oauth flow
1921+
type: object
1922+
properties:
1923+
oauthFlowInitParameters:
1924+
description:
1925+
"Pointers to the fields in the ConnectorSpecification which are needed to obtain the initial refresh/access tokens for the OAuth flow.
1926+
Each inner array represents the path in the ConnectorSpecification of the referenced field.
1927+
For example.
1928+
Assume the ConnectorSpecification contains params 'app_secret', 'app_id' which are needed to get the initial refresh token.
1929+
If they are not nested in the config, then the array would look like this [['app_secret'], ['app_id']]
1930+
If they are nested inside, say, an object called 'auth_params' then this array would be [['auth_params', 'app_secret'], ['auth_params', 'app_id']]"
1931+
type: array
1932+
items:
1933+
description: A list of strings which describes each parameter's path inside the ConnectionSpecification
1934+
type: array
1935+
items:
1936+
type: string
19091937
SourceDefinitionSpecificationRead:
19101938
type: object
19111939
required:
@@ -1918,6 +1946,8 @@ components:
19181946
type: string
19191947
connectionSpecification:
19201948
$ref: "#/components/schemas/SourceDefinitionSpecification"
1949+
authSpecification:
1950+
$ref: "#/components/schemas/SourceAuthSpecification"
19211951
jobInfo:
19221952
$ref: "#/components/schemas/SynchronousJobRead"
19231953
# SOURCE
@@ -2018,6 +2048,8 @@ components:
20182048
DestinationDefinitionId:
20192049
type: string
20202050
format: uuid
2051+
DestinationAuthSpecification:
2052+
$ref: "#/components/schemas/AuthSpecification"
20212053
DestinationDefinitionIdRequestBody:
20222054
type: object
20232055
required:
@@ -2101,6 +2133,8 @@ components:
21012133
type: string
21022134
connectionSpecification:
21032135
$ref: "#/components/schemas/DestinationDefinitionSpecification"
2136+
authSpecification:
2137+
$ref: "#/components/schemas/DestinationAuthSpecification"
21042138
jobInfo:
21052139
$ref: "#/components/schemas/SynchronousJobRead"
21062140
supportedDestinationSyncModes:
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* MIT License
3+
*
4+
* Copyright (c) 2020 Airbyte
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
package io.airbyte.server.converters;
26+
27+
import io.airbyte.api.model.AuthSpecification;
28+
import io.airbyte.api.model.OAuth2Specification;
29+
import io.airbyte.protocol.models.ConnectorSpecification;
30+
import java.util.Optional;
31+
32+
public class OauthModelConverter {
33+
34+
public static Optional<AuthSpecification> getAuthSpec(ConnectorSpecification spec) {
35+
if (spec.getAuthSpecification() == null) {
36+
return Optional.empty();
37+
}
38+
io.airbyte.protocol.models.AuthSpecification incomingAuthSpec = spec.getAuthSpecification();
39+
40+
AuthSpecification authSpecification = new AuthSpecification();
41+
if (incomingAuthSpec.getAuthType() == io.airbyte.protocol.models.AuthSpecification.AuthType.OAUTH_2_0) {
42+
authSpecification.authType(AuthSpecification.AuthTypeEnum.OAUTH2_0)
43+
.oauth2Specification(new OAuth2Specification()
44+
.oauthFlowInitParameters(incomingAuthSpec.getOauth2Specification().getOauthFlowInitParameters()));
45+
}
46+
47+
return Optional.ofNullable(authSpecification);
48+
}
49+
50+
}

airbyte-server/src/main/java/io/airbyte/server/handlers/SchedulerHandler.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import com.google.common.annotations.VisibleForTesting;
2828
import com.google.common.collect.Lists;
29+
import io.airbyte.api.model.AuthSpecification;
2930
import io.airbyte.api.model.CheckConnectionRead;
3031
import io.airbyte.api.model.CheckConnectionRead.StatusEnum;
3132
import io.airbyte.api.model.ConnectionIdRequestBody;
@@ -67,6 +68,7 @@
6768
import io.airbyte.server.converters.CatalogConverter;
6869
import io.airbyte.server.converters.ConfigurationUpdate;
6970
import io.airbyte.server.converters.JobConverter;
71+
import io.airbyte.server.converters.OauthModelConverter;
7072
import io.airbyte.server.converters.SpecFetcher;
7173
import io.airbyte.validation.json.JsonSchemaValidator;
7274
import io.airbyte.validation.json.JsonValidationException;
@@ -246,11 +248,18 @@ public SourceDefinitionSpecificationRead getSourceDefinitionSpecification(Source
246248
final String imageName = DockerUtils.getTaggedImageName(source.getDockerRepository(), source.getDockerImageTag());
247249
final SynchronousResponse<ConnectorSpecification> response = getConnectorSpecification(imageName);
248250
final ConnectorSpecification spec = response.getOutput();
249-
return new SourceDefinitionSpecificationRead()
251+
SourceDefinitionSpecificationRead specRead = new SourceDefinitionSpecificationRead()
250252
.jobInfo(JobConverter.getSynchronousJobRead(response))
251253
.connectionSpecification(spec.getConnectionSpecification())
252254
.documentationUrl(spec.getDocumentationUrl().toString())
253255
.sourceDefinitionId(sourceDefinitionId);
256+
257+
Optional<AuthSpecification> authSpec = OauthModelConverter.getAuthSpec(spec);
258+
if (authSpec.isPresent()) {
259+
specRead.setAuthSpecification(authSpec.get());
260+
}
261+
262+
return specRead;
254263
}
255264

256265
public DestinationDefinitionSpecificationRead getDestinationSpecification(DestinationDefinitionIdRequestBody destinationDefinitionIdRequestBody)
@@ -260,14 +269,22 @@ public DestinationDefinitionSpecificationRead getDestinationSpecification(Destin
260269
final String imageName = DockerUtils.getTaggedImageName(destination.getDockerRepository(), destination.getDockerImageTag());
261270
final SynchronousResponse<ConnectorSpecification> response = getConnectorSpecification(imageName);
262271
final ConnectorSpecification spec = response.getOutput();
263-
return new DestinationDefinitionSpecificationRead()
272+
273+
DestinationDefinitionSpecificationRead specRead = new DestinationDefinitionSpecificationRead()
264274
.jobInfo(JobConverter.getSynchronousJobRead(response))
265275
.supportedDestinationSyncModes(Enums.convertListTo(spec.getSupportedDestinationSyncModes(), DestinationSyncMode.class))
266276
.connectionSpecification(spec.getConnectionSpecification())
267277
.documentationUrl(spec.getDocumentationUrl().toString())
268278
.supportsNormalization(spec.getSupportsNormalization())
269279
.supportsDbt(spec.getSupportsDBT())
270280
.destinationDefinitionId(destinationDefinitionId);
281+
282+
Optional<AuthSpecification> authSpec = OauthModelConverter.getAuthSpec(spec);
283+
if (authSpec.isPresent()) {
284+
specRead.setAuthSpecification(authSpec.get());
285+
}
286+
287+
return specRead;
271288
}
272289

273290
public SynchronousResponse<ConnectorSpecification> getConnectorSpecification(String dockerImage) throws IOException {
@@ -352,7 +369,7 @@ public JobInfoRead cancelJob(JobIdRequestBody jobIdRequestBody) throws IOExcepti
352369

353370
private void cancelTemporalWorkflowIfPresent(long jobId) throws IOException {
354371
var latestAttemptId = jobPersistence.getJob(jobId).getAttempts().size() - 1; // attempts ids are monotonically increasing starting from 0 and
355-
// specific to a job id, allowing us to do this.
372+
// specific to a job id, allowing us to do this.
356373
var workflowId = jobPersistence.getAttemptTemporalWorkflowId(jobId, latestAttemptId);
357374

358375
if (workflowId.isPresent()) {

docs/reference/api/generated-api-html/index.html

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2296,6 +2296,12 @@ <h3 class="field-label">Example data</h3>
22962296
"supportedDestinationSyncModes" : [ null, null ],
22972297
"supportsDbt" : true,
22982298
"destinationDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91",
2299+
"authSpecification" : {
2300+
"auth_type" : "oauth2.0",
2301+
"oauth2Specification" : {
2302+
"oauthFlowInitParameters" : [ [ "oauthFlowInitParameters", "oauthFlowInitParameters" ], [ "oauthFlowInitParameters", "oauthFlowInitParameters" ] ]
2303+
}
2304+
},
22992305
"jobInfo" : {
23002306
"createdAt" : 0,
23012307
"configId" : "configId",
@@ -4641,6 +4647,12 @@ <h3 class="field-label">Example data</h3>
46414647
}
46424648
},
46434649
"sourceDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91",
4650+
"authSpecification" : {
4651+
"auth_type" : "oauth2.0",
4652+
"oauth2Specification" : {
4653+
"oauthFlowInitParameters" : [ [ "oauthFlowInitParameters", "oauthFlowInitParameters" ], [ "oauthFlowInitParameters", "oauthFlowInitParameters" ] ]
4654+
}
4655+
},
46444656
"jobInfo" : {
46454657
"createdAt" : 0,
46464658
"configId" : "configId",
@@ -6004,6 +6016,7 @@ <h3>Table of Contents</h3>
60046016
<li><a href="#AttemptInfoRead"><code>AttemptInfoRead</code> - </a></li>
60056017
<li><a href="#AttemptRead"><code>AttemptRead</code> - </a></li>
60066018
<li><a href="#AttemptStatus"><code>AttemptStatus</code> - </a></li>
6019+
<li><a href="#AuthSpecification"><code>AuthSpecification</code> - </a></li>
60076020
<li><a href="#CheckConnectionRead"><code>CheckConnectionRead</code> - </a></li>
60086021
<li><a href="#CheckOperationRead"><code>CheckOperationRead</code> - </a></li>
60096022
<li><a href="#CompleteDestinationOAuthRequest"><code>CompleteDestinationOAuthRequest</code> - </a></li>
@@ -6058,6 +6071,7 @@ <h3>Table of Contents</h3>
60586071
<li><a href="#Notification"><code>Notification</code> - </a></li>
60596072
<li><a href="#NotificationRead"><code>NotificationRead</code> - </a></li>
60606073
<li><a href="#NotificationType"><code>NotificationType</code> - </a></li>
6074+
<li><a href="#OAuth2Specification"><code>OAuth2Specification</code> - </a></li>
60616075
<li><a href="#OAuthConsentRead"><code>OAuthConsentRead</code> - </a></li>
60626076
<li><a href="#OperationCreate"><code>OperationCreate</code> - </a></li>
60636077
<li><a href="#OperationIdRequestBody"><code>OperationIdRequestBody</code> - </a></li>
@@ -6171,6 +6185,16 @@ <h3><a name="AttemptStatus"><code>AttemptStatus</code> - </a> <a class="up" href
61716185
<div class="field-items">
61726186
</div> <!-- field-items -->
61736187
</div>
6188+
<div class="model">
6189+
<h3><a name="AuthSpecification"><code>AuthSpecification</code> - </a> <a class="up" href="#__Models">Up</a></h3>
6190+
<div class='model-description'></div>
6191+
<div class="field-items">
6192+
<div class="param">auth_type (optional)</div><div class="param-desc"><span class="param-type"><a href="#string">String</a></span> </div>
6193+
<div class="param-enum-header">Enum:</div>
6194+
<div class="param-enum">oauth2.0</div>
6195+
<div class="param">oauth2Specification (optional)</div><div class="param-desc"><span class="param-type"><a href="#OAuth2Specification">OAuth2Specification</a></span> </div>
6196+
</div> <!-- field-items -->
6197+
</div>
61746198
<div class="model">
61756199
<h3><a name="CheckConnectionRead"><code>CheckConnectionRead</code> - </a> <a class="up" href="#__Models">Up</a></h3>
61766200
<div class='model-description'></div>
@@ -6410,6 +6434,7 @@ <h3><a name="DestinationDefinitionSpecificationRead"><code>DestinationDefinition
64106434
<div class="param">destinationDefinitionId </div><div class="param-desc"><span class="param-type"><a href="#UUID">UUID</a></span> format: uuid</div>
64116435
<div class="param">documentationUrl (optional)</div><div class="param-desc"><span class="param-type"><a href="#string">String</a></span> </div>
64126436
<div class="param">connectionSpecification (optional)</div><div class="param-desc"><span class="param-type"><a href="#DestinationDefinitionSpecification">DestinationDefinitionSpecification</a></span> </div>
6437+
<div class="param">authSpecification (optional)</div><div class="param-desc"><span class="param-type"><a href="#AuthSpecification">AuthSpecification</a></span> </div>
64136438
<div class="param">jobInfo </div><div class="param-desc"><span class="param-type"><a href="#SynchronousJobRead">SynchronousJobRead</a></span> </div>
64146439
<div class="param">supportedDestinationSyncModes (optional)</div><div class="param-desc"><span class="param-type"><a href="#DestinationSyncMode">array[DestinationSyncMode]</a></span> </div>
64156440
<div class="param">supportsDbt (optional)</div><div class="param-desc"><span class="param-type"><a href="#boolean">Boolean</a></span> </div>
@@ -6656,6 +6681,13 @@ <h3><a name="NotificationType"><code>NotificationType</code> - </a> <a class="up
66566681
<div class="field-items">
66576682
</div> <!-- field-items -->
66586683
</div>
6684+
<div class="model">
6685+
<h3><a name="OAuth2Specification"><code>OAuth2Specification</code> - </a> <a class="up" href="#__Models">Up</a></h3>
6686+
<div class='model-description'>An object containing any metadata needed to describe this connector's Oauth flow</div>
6687+
<div class="field-items">
6688+
<div class="param">oauthFlowInitParameters (optional)</div><div class="param-desc"><span class="param-type"><a href="#array">array[array[String]]</a></span> Pointers to the fields in the ConnectorSpecification which are needed to obtain the initial refresh/access tokens for the OAuth flow. Each inner array represents the path in the ConnectorSpecification of the referenced field. For example. Assume the ConnectorSpecification contains params 'app_secret', 'app_id' which are needed to get the initial refresh token. If they are not nested in the config, then the array would look like this [['app_secret'], ['app_id']] If they are nested inside, say, an object called 'auth_params' then this array would be [['auth_params', 'app_secret'], ['auth_params', 'app_id']] </div>
6689+
</div> <!-- field-items -->
6690+
</div>
66596691
<div class="model">
66606692
<h3><a name="OAuthConsentRead"><code>OAuthConsentRead</code> - </a> <a class="up" href="#__Models">Up</a></h3>
66616693
<div class='model-description'></div>
@@ -6849,6 +6881,7 @@ <h3><a name="SourceDefinitionSpecificationRead"><code>SourceDefinitionSpecificat
68496881
<div class="param">sourceDefinitionId </div><div class="param-desc"><span class="param-type"><a href="#UUID">UUID</a></span> format: uuid</div>
68506882
<div class="param">documentationUrl (optional)</div><div class="param-desc"><span class="param-type"><a href="#string">String</a></span> </div>
68516883
<div class="param">connectionSpecification (optional)</div><div class="param-desc"><span class="param-type"><a href="#SourceDefinitionSpecification">SourceDefinitionSpecification</a></span> </div>
6884+
<div class="param">authSpecification (optional)</div><div class="param-desc"><span class="param-type"><a href="#AuthSpecification">AuthSpecification</a></span> </div>
68526885
<div class="param">jobInfo </div><div class="param-desc"><span class="param-type"><a href="#SynchronousJobRead">SynchronousJobRead</a></span> </div>
68536886
</div> <!-- field-items -->
68546887
</div>

0 commit comments

Comments
 (0)