Skip to content

Commit

Permalink
feat(experimentalIdentityAndAuth): add codegen for `HttpAuthExtension…
Browse files Browse the repository at this point in the history
…Configuration` (#910)

Add code-generation for `HttpAuthExtensionConfiguration`, which allows
configuring:

- `httpAuthSchemes`
- `httpAuthSchemeProvider`
- Any `ConfigField` registered by `HttpAuthScheme`s

Also, add relative import dependencies for:

- `httpAuthSchemeProvider`
- `httpAuthExtensionConfiguration`
  • Loading branch information
Steven Yuan authored Sep 7, 2023
1 parent f2a78d5 commit b5ae5e4
Show file tree
Hide file tree
Showing 11 changed files with 513 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@
@SmithyUnstableApi
public final record ConfigField(
String name,
Type type,
Consumer<TypeScriptWriter> source,
Consumer<TypeScriptWriter> docs
) {}
) {
/**
* Defines the type of the config field.
*/
@SmithyUnstableApi
public enum Type {
/**
* Specifies the property is important, e.g. {@code apiKey} for {@code @httpApiKeyAuth}
*/
MAIN,
/**
* Specifies the property is auxiliary, e.g. {@code region} for {@code @aws.auth#sigv4}
*/
AUXILIARY
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

package software.amazon.smithy.typescript.codegen;

import java.nio.file.Paths;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
Expand All @@ -32,7 +31,6 @@
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.typescript.codegen.auth.AuthUtils;
import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthScheme;
import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthSchemeProviderGenerator;
import software.amazon.smithy.typescript.codegen.auth.http.SupportedHttpAuthSchemesIndex;
import software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration;
import software.amazon.smithy.utils.MapUtils;
Expand Down Expand Up @@ -212,9 +210,7 @@ private void generateHttpAuthSchemeConfig(
if (target.equals(LanguageTarget.SHARED)) {
configs.put("httpAuthSchemeProvider", w -> {
String providerName = "default" + service.toShapeId().getName() + "HttpAuthSchemeProvider";
w.addRelativeImport(providerName, null, Paths.get(".", CodegenUtils.SOURCE_FOLDER,
HttpAuthSchemeProviderGenerator.HTTP_AUTH_FOLDER,
HttpAuthSchemeProviderGenerator.HTTP_AUTH_SCHEME_RESOLVER_MODULE));
w.addImport(providerName, null, AuthUtils.AUTH_HTTP_PROVIDER_DEPENDENCY);
w.write(providerName);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import software.amazon.smithy.model.shapes.OperationShape;
import software.amazon.smithy.model.shapes.ServiceShape;
import software.amazon.smithy.rulesengine.traits.EndpointRuleSetTrait;
import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthSchemeProviderGenerator;
import software.amazon.smithy.typescript.codegen.auth.AuthUtils;
import software.amazon.smithy.typescript.codegen.auth.http.integration.HttpAuthTypeScriptIntegration;
import software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin;
import software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration;
Expand Down Expand Up @@ -313,10 +313,7 @@ private void generateClientDefaults() {
writer.write("httpAuthSchemes?: HttpAuthScheme[];\n");

String httpAuthSchemeProviderName = service.toShapeId().getName() + "HttpAuthSchemeProvider";
writer.addRelativeImport(httpAuthSchemeProviderName, null, Paths.get(".",
CodegenUtils.SOURCE_FOLDER,
HttpAuthSchemeProviderGenerator.HTTP_AUTH_FOLDER,
HttpAuthSchemeProviderGenerator.HTTP_AUTH_SCHEME_RESOLVER_MODULE));
writer.addImport(httpAuthSchemeProviderName, null, AuthUtils.AUTH_HTTP_PROVIDER_DEPENDENCY);
writer.writeDocs("""
experimentalIdentityAndAuth: Configuration of an HttpAuthSchemeProvider for a client which \
resolves which HttpAuthScheme to use.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@

package software.amazon.smithy.typescript.codegen.auth;

import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import software.amazon.smithy.codegen.core.SymbolDependency;
import software.amazon.smithy.model.knowledge.ServiceIndex;
import software.amazon.smithy.model.knowledge.ServiceIndex.AuthSchemeMode;
import software.amazon.smithy.model.shapes.ServiceShape;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.typescript.codegen.CodegenUtils;
import software.amazon.smithy.typescript.codegen.Dependency;
import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthScheme;
import software.amazon.smithy.typescript.codegen.auth.http.SupportedHttpAuthSchemesIndex;
import software.amazon.smithy.utils.SmithyInternalApi;
Expand All @@ -20,6 +26,54 @@
*/
@SmithyInternalApi
public final class AuthUtils {
public static final String HTTP_AUTH_FOLDER = "auth";

public static final String HTTP_AUTH_SCHEME_PROVIDER_MODULE = "httpAuthSchemeProvider";

public static final String HTTP_AUTH_SCHEME_PROVIDER_FILE =
HTTP_AUTH_SCHEME_PROVIDER_MODULE + ".ts";

public static final String HTTP_AUTH_SCHEME_PROVIDER_PATH =
Paths.get(".", CodegenUtils.SOURCE_FOLDER, HTTP_AUTH_FOLDER, HTTP_AUTH_SCHEME_PROVIDER_FILE).toString();

public static final Dependency AUTH_HTTP_PROVIDER_DEPENDENCY = new Dependency() {
@Override
public String getPackageName() {
return Paths.get(
".", CodegenUtils.SOURCE_FOLDER,
HTTP_AUTH_FOLDER, HTTP_AUTH_SCHEME_PROVIDER_MODULE
).toString();
}

@Override
public List<SymbolDependency> getDependencies() {
return Collections.emptyList();
}
};

public static final String HTTP_AUTH_SCHEME_EXTENSION_MODULE = "httpAuthExtensionConfiguration";

public static final String HTTP_AUTH_SCHEME_EXTENSION_FILE =
HTTP_AUTH_SCHEME_EXTENSION_MODULE + ".ts";

public static final String HTTP_AUTH_SCHEME_EXTENSION_PATH =
Paths.get(".", CodegenUtils.SOURCE_FOLDER, HTTP_AUTH_FOLDER, HTTP_AUTH_SCHEME_EXTENSION_FILE).toString();

public static final Dependency AUTH_HTTP_EXTENSION_DEPENDENCY = new Dependency() {
@Override
public String getPackageName() {
return Paths.get(
".", CodegenUtils.SOURCE_FOLDER,
HTTP_AUTH_FOLDER, HTTP_AUTH_SCHEME_EXTENSION_MODULE
).toString();
}

@Override
public List<SymbolDependency> getDependencies() {
return Collections.emptyList();
}
};

private AuthUtils() {}

public static Map<ShapeId, HttpAuthScheme> getAllEffectiveNoAuthAwareAuthSchemes(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,6 @@
*/
@SmithyInternalApi
public class HttpAuthSchemeProviderGenerator implements Runnable {
/**
* Directory segment for {@code auth/}.
*/
public static final String HTTP_AUTH_FOLDER = "auth";
/**
* File name segment for {@code httpAuthSchemeProvder}.
*/
public static final String HTTP_AUTH_SCHEME_RESOLVER_MODULE = "httpAuthSchemeProvider";

private static final String HTTP_AUTH_SCHEME_RESOLVER_FILE =
HTTP_AUTH_SCHEME_RESOLVER_MODULE + ".ts";
private static final String HTTP_AUTH_SCHEME_RESOLVER_PATH =
Paths.get(CodegenUtils.SOURCE_FOLDER, HTTP_AUTH_FOLDER, HTTP_AUTH_SCHEME_RESOLVER_FILE).toString();

private final TypeScriptDelegator delegator;
private final Model model;

Expand Down Expand Up @@ -104,7 +90,7 @@ export interface WeatherHttpAuthSchemeParameters {
}
*/
private void generateHttpAuthSchemeParametersInterface() {
delegator.useFileWriter(HTTP_AUTH_SCHEME_RESOLVER_PATH.toString(), w -> {
delegator.useFileWriter(AuthUtils.HTTP_AUTH_SCHEME_PROVIDER_PATH, w -> {
w.openBlock("""
/**
* @internal
Expand Down Expand Up @@ -138,7 +124,7 @@ export async function defaultWeatherHttpAuthSchemeParametersProvider(
};
*/
private void generateDefaultHttpAuthSchemeParametersProviderFunction() {
delegator.useFileWriter(HTTP_AUTH_SCHEME_RESOLVER_PATH.toString(), w -> {
delegator.useFileWriter(AuthUtils.HTTP_AUTH_SCHEME_PROVIDER_PATH, w -> {
w.addRelativeImport(serviceSymbol.getName() + "ResolvedConfig", null,
Paths.get(".", serviceSymbol.getNamespace()));
w.addImport("HandlerExecutionContext", null, TypeScriptDependency.SMITHY_TYPES);
Expand Down Expand Up @@ -190,7 +176,7 @@ function createSmithyApiHttpApiKeyAuthHttpAuthOption(authParameters: WeatherHttp
};
*/
private void generateHttpAuthOptionFunction(ShapeId shapeId, HttpAuthScheme authScheme) {
delegator.useFileWriter(HTTP_AUTH_SCHEME_RESOLVER_PATH.toString(), w -> {
delegator.useFileWriter(AuthUtils.HTTP_AUTH_SCHEME_PROVIDER_PATH, w -> {
String normalizedAuthSchemeName = normalizeAuthSchemeName(shapeId);
w.addDependency(TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
w.addImport("HttpAuthOption", null, TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
Expand Down Expand Up @@ -242,7 +228,7 @@ export interface WeatherHttpAuthSchemeProvider {
}
*/
private void generateHttpAuthSchemeProviderInterface() {
delegator.useFileWriter(HTTP_AUTH_SCHEME_RESOLVER_PATH.toString(), w -> {
delegator.useFileWriter(AuthUtils.HTTP_AUTH_SCHEME_PROVIDER_PATH, w -> {
w.write("""
/**
* @internal
Expand All @@ -267,7 +253,7 @@ export function defaultWeatherHttpAuthSchemeProvider(authParameters: WeatherHttp
};
*/
private void generateHttpAuthSchemeProviderDefaultFunction() {
delegator.useFileWriter(HTTP_AUTH_SCHEME_RESOLVER_PATH.toString(), w -> {
delegator.useFileWriter(AuthUtils.HTTP_AUTH_SCHEME_PROVIDER_PATH, w -> {
w.openBlock("""
/**
* @internal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import software.amazon.smithy.typescript.codegen.TypeScriptSettings;
import software.amazon.smithy.typescript.codegen.TypeScriptWriter;
import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthOptionProperty;
import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthOptionProperty.Type;
import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthScheme;
import software.amazon.smithy.utils.SmithyInternalApi;

Expand Down Expand Up @@ -47,20 +46,20 @@ public Optional<HttpAuthScheme> getHttpAuthScheme() {
return Optional.of(HttpAuthScheme.builder()
.schemeId(HttpApiKeyAuthTrait.ID)
.applicationProtocol(ApplicationProtocol.createDefaultHttpApplicationProtocol())
.addConfigField(new ConfigField("apiKey", w -> {
.addConfigField(new ConfigField("apiKey", ConfigField.Type.MAIN, w -> {
w.addImport("ApiKeyIdentity", null,
TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
w.addImport("ApiKeyIdentityProvider", null,
TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
w.write("ApiKeyIdentity | ApiKeyIdentityProvider");
}, w -> w.write("The API key to use when making requests.")))
.addHttpAuthOptionProperty(new HttpAuthOptionProperty(
"name", Type.SIGNING, t -> w -> {
"name", HttpAuthOptionProperty.Type.SIGNING, t -> w -> {
HttpApiKeyAuthTrait httpApiKeyAuthTrait = (HttpApiKeyAuthTrait) t;
w.write("$S", httpApiKeyAuthTrait.getName());
}))
.addHttpAuthOptionProperty(new HttpAuthOptionProperty(
"in", Type.SIGNING, t -> w -> {
"in", HttpAuthOptionProperty.Type.SIGNING, t -> w -> {
w.addImport("HttpApiKeyAuthLocation", null,
TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
HttpApiKeyAuthTrait httpApiKeyAuthTrait = (HttpApiKeyAuthTrait) t;
Expand All @@ -74,7 +73,7 @@ public Optional<HttpAuthScheme> getHttpAuthScheme() {
}
}))
.addHttpAuthOptionProperty(new HttpAuthOptionProperty(
"scheme", Type.SIGNING, t -> w -> {
"scheme", HttpAuthOptionProperty.Type.SIGNING, t -> w -> {
HttpApiKeyAuthTrait httpApiKeyAuthTrait = (HttpApiKeyAuthTrait) t;
httpApiKeyAuthTrait.getScheme().ifPresentOrElse(
s -> w.write(s),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import software.amazon.smithy.model.traits.HttpBearerAuthTrait;
import software.amazon.smithy.typescript.codegen.ApplicationProtocol;
import software.amazon.smithy.typescript.codegen.ConfigField;
import software.amazon.smithy.typescript.codegen.ConfigField.Type;
import software.amazon.smithy.typescript.codegen.LanguageTarget;
import software.amazon.smithy.typescript.codegen.TypeScriptDependency;
import software.amazon.smithy.typescript.codegen.TypeScriptSettings;
Expand Down Expand Up @@ -43,7 +44,7 @@ public Optional<HttpAuthScheme> getHttpAuthScheme() {
return Optional.of(HttpAuthScheme.builder()
.schemeId(HttpBearerAuthTrait.ID)
.applicationProtocol(ApplicationProtocol.createDefaultHttpApplicationProtocol())
.addConfigField(new ConfigField("token", w -> {
.addConfigField(new ConfigField("token", Type.MAIN, w -> {
w.addDependency(TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
w.addImport("TokenIdentity", null,
TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import software.amazon.smithy.typescript.codegen.TypeScriptSettings;
import software.amazon.smithy.typescript.codegen.TypeScriptWriter;
import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthOptionProperty;
import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthOptionProperty.Type;
import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthScheme;
import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthSchemeParameter;
import software.amazon.smithy.utils.SmithyInternalApi;
Expand Down Expand Up @@ -47,12 +46,12 @@ public Optional<HttpAuthScheme> getHttpAuthScheme() {
.schemeId(ShapeId.from("aws.auth#sigv4"))
.applicationProtocol(ApplicationProtocol.createDefaultHttpApplicationProtocol())
.putDefaultSigner(LanguageTarget.SHARED, AWS_SIGV4_AUTH_SIGNER)
.addConfigField(new ConfigField("region", w -> {
.addConfigField(new ConfigField("region", ConfigField.Type.AUXILIARY, w -> {
w.addDependency(TypeScriptDependency.SMITHY_TYPES);
w.addImport("Provider", "__Provider", TypeScriptDependency.SMITHY_TYPES);
w.write("string | __Provider<string>");
}, w -> w.write("The AWS region to which this client will send requests.")))
.addConfigField(new ConfigField("credentials", w -> {
.addConfigField(new ConfigField("credentials", ConfigField.Type.MAIN, w -> {
w.addDependency(TypeScriptDependency.SMITHY_TYPES);
w.addImport("AwsCredentialIdentity", null, TypeScriptDependency.SMITHY_TYPES);
w.addImport("AwsCredentialIdentityProvider", null, TypeScriptDependency.SMITHY_TYPES);
Expand All @@ -67,11 +66,11 @@ public Optional<HttpAuthScheme> getHttpAuthScheme() {
});
}))
.addHttpAuthOptionProperty(new HttpAuthOptionProperty(
"name", Type.SIGNING, t -> w -> {
"name", HttpAuthOptionProperty.Type.SIGNING, t -> w -> {
w.write("$S", t.toNode().expectObjectNode().getMember("name"));
}))
.addHttpAuthOptionProperty(new HttpAuthOptionProperty(
"region", Type.SIGNING, t -> w -> {
"region", HttpAuthOptionProperty.Type.SIGNING, t -> w -> {
w.write("authParameters.region");
}))
.build());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.typescript.codegen.auth.http.integration;

import software.amazon.smithy.typescript.codegen.Dependency;
import software.amazon.smithy.typescript.codegen.auth.AuthUtils;
import software.amazon.smithy.typescript.codegen.extensions.ExtensionConfigurationInterface;
import software.amazon.smithy.utils.Pair;
import software.amazon.smithy.utils.SmithyInternalApi;

/**
* Adds the corresponding interface and functions for {@code HttpAuthExtensionConfiguration}.
*
* This is experimental for `experimentalIdentityAndAuth`.
*/
@SmithyInternalApi
public class HttpAuthExtensionConfigurationInterface implements ExtensionConfigurationInterface {
@Override
public Pair<String, Dependency> name() {
return Pair.of("HttpAuthExtensionConfiguration", AuthUtils.AUTH_HTTP_EXTENSION_DEPENDENCY);
}

@Override
public Pair<String, Dependency> getExtensionConfigurationFn() {
return Pair.of("getHttpAuthExtensionConfiguration", AuthUtils.AUTH_HTTP_EXTENSION_DEPENDENCY);
}

@Override
public Pair<String, Dependency> resolveRuntimeConfigFn() {
return Pair.of("resolveHttpAuthRuntimeConfig", AuthUtils.AUTH_HTTP_EXTENSION_DEPENDENCY);
}
}
Loading

0 comments on commit b5ae5e4

Please sign in to comment.