From 63cbc8d9863715015b6ba081a4edd6831eb11580 Mon Sep 17 00:00:00 2001 From: Steven Yuan Date: Fri, 18 Aug 2023 10:43:00 -0700 Subject: [PATCH 1/2] feat(experimentalIdentityAndAuth): simplify `AddHttpApiKeyAuthPlugin` control branch --- .../integration/AddHttpApiKeyAuthPlugin.java | 53 ++++++++++--------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddHttpApiKeyAuthPlugin.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddHttpApiKeyAuthPlugin.java index c1691e1583a..4e6b5bbd6bd 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddHttpApiKeyAuthPlugin.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddHttpApiKeyAuthPlugin.java @@ -18,15 +18,14 @@ import java.nio.file.Paths; import java.util.HashMap; import java.util.List; -import java.util.Set; import java.util.function.BiConsumer; import java.util.function.Consumer; import software.amazon.smithy.codegen.core.Symbol; import software.amazon.smithy.model.Model; import software.amazon.smithy.model.knowledge.ServiceIndex; -import software.amazon.smithy.model.knowledge.TopDownIndex; import software.amazon.smithy.model.shapes.OperationShape; import software.amazon.smithy.model.shapes.ServiceShape; +import software.amazon.smithy.model.shapes.ShapeId; import software.amazon.smithy.model.traits.HttpApiKeyAuthTrait; import software.amazon.smithy.model.traits.OptionalAuthTrait; import software.amazon.smithy.typescript.codegen.CodegenUtils; @@ -93,10 +92,7 @@ public List getClientPlugins() { s.expectTrait(HttpApiKeyAuthTrait.class).getScheme().ifPresent(scheme -> put("scheme", scheme)); }}) - .operationPredicate((m, s, o) -> ServiceIndex.of(m).getEffectiveAuthSchemes(s, o) - .keySet() - .contains(HttpApiKeyAuthTrait.ID) - && !o.hasTrait(OptionalAuthTrait.class)) + .operationPredicate((m, s, o) -> hasEffectiveHttpApiKeyAuthTrait(m, s, o)) .settingsPredicate((m, s, settings) -> !settings.getExperimentalIdentityAndAuth()) .build() ); @@ -170,28 +166,33 @@ private void writeAdditionalExports( } } - // The service has the effective trait if it's in the "effective auth schemes" response - // AND if not all of the operations have the optional auth trait. - private static boolean hasEffectiveHttpApiKeyAuthTrait(Model model, ServiceShape service) { - return ServiceIndex.of(model).getEffectiveAuthSchemes(service) - .keySet() - .contains(HttpApiKeyAuthTrait.ID) - && !areAllOptionalAuthOperations(model, service); + // If no operations use it, then the service doesn't use it + private static boolean hasEffectiveHttpApiKeyAuthTrait( + Model model, + ServiceShape service + ) { + ServiceIndex serviceIndex = ServiceIndex.of(model); + for (ShapeId id : service.getAllOperations()) { + OperationShape operation = model.expectShape(id, OperationShape.class); + if (operation.hasTrait(OptionalAuthTrait.ID)) { + continue; + } + if (serviceIndex.getEffectiveAuthSchemes(service, operation).containsKey(HttpApiKeyAuthTrait.ID)) { + return true; + } + } + return false; } - - // This is derived from https://github.com/aws/aws-sdk-js-v3/blob/main/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddAwsAuthPlugin.java. - private static boolean areAllOptionalAuthOperations(Model model, ServiceShape service) { - TopDownIndex topDownIndex = TopDownIndex.of(model); - Set operations = topDownIndex.getContainedOperations(service); - ServiceIndex index = ServiceIndex.of(model); - - for (OperationShape operation : operations) { - if (index.getEffectiveAuthSchemes(service, operation).isEmpty() - || !operation.hasTrait(OptionalAuthTrait.class)) { - return false; - } + private static boolean hasEffectiveHttpApiKeyAuthTrait( + Model model, + ServiceShape service, + OperationShape operation + ) { + if (operation.hasTrait(OptionalAuthTrait.class)) { + return false; } - return true; + return ServiceIndex.of(model) + .getEffectiveAuthSchemes(service, operation).containsKey(HttpApiKeyAuthTrait.ID); } } From dfa8befbe9919df07dc56453a4ccaf438096960f Mon Sep 17 00:00:00 2001 From: Steven Yuan Date: Fri, 18 Aug 2023 10:43:33 -0700 Subject: [PATCH 2/2] feat(experimentalIdentityAndAuth): add more auth traits to generic client tests Note that the `smithy-aws-traits` dependency is added for including `@aws.auth#sigv4`, which will have generic client support. This should not affect packaging of `smithy-typescript-codegen` since these tests are in `smithy-typescript-codegen-test`. --- .../build.gradle.kts | 1 + .../model/main.smithy | 41 ++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/smithy-typescript-codegen-test/build.gradle.kts b/smithy-typescript-codegen-test/build.gradle.kts index 62fc2cfc501..821d7c5e455 100644 --- a/smithy-typescript-codegen-test/build.gradle.kts +++ b/smithy-typescript-codegen-test/build.gradle.kts @@ -47,4 +47,5 @@ dependencies { implementation(project(":smithy-typescript-ssdk-codegen-test-utils")) implementation("software.amazon.smithy:smithy-waiters:$smithyVersion") implementation("software.amazon.smithy:smithy-protocol-test-traits:$smithyVersion") + implementation("software.amazon.smithy:smithy-aws-traits:$smithyVersion") } diff --git a/smithy-typescript-codegen-test/model/main.smithy b/smithy-typescript-codegen-test/model/main.smithy index c86ba31f387..138d46fc730 100644 --- a/smithy-typescript-codegen-test/model/main.smithy +++ b/smithy-typescript-codegen-test/model/main.smithy @@ -2,6 +2,7 @@ $version: "2.0" namespace example.weather +use aws.auth#sigv4 use smithy.test#httpRequestTests use smithy.test#httpResponseTests use smithy.waiters#waitable @@ -9,13 +10,51 @@ use smithy.waiters#waitable /// Provides weather forecasts. @fakeProtocol @httpApiKeyAuth(name: "X-Api-Key", in: "header") +@httpBearerAuth +@sigv4(name: "weather") +@auth([sigv4]) @paginated(inputToken: "nextToken", outputToken: "nextToken", pageSize: "pageSize") service Weather { version: "2006-03-01" resources: [City] - operations: [GetCurrentTime, Invoke] + operations: [ + GetCurrentTime + // util-stream.integ.spec.ts + Invoke + // experimentalIdentityAndAuth + OnlyHttpApiKeyAuth + OnlyHttpBearerAuth + OnlyHttpApiKeyAndBearerAuth + OnlyHttpApiKeyAndBearerAuthReversed + OnlyHttpApiKeyAuthOptional + SameAsService + ] } +@http(method: "GET", uri: "/OnlyHttpApiKeyAuth") +@auth([httpApiKeyAuth]) +operation OnlyHttpApiKeyAuth {} + +@http(method: "GET", uri: "/OnlyHttpBearerAuth") +@auth([httpBearerAuth]) +operation OnlyHttpBearerAuth {} + +@http(method: "GET", uri: "/OnlyHttpApiKeyAndBearerAuth") +@auth([httpApiKeyAuth, httpBearerAuth]) +operation OnlyHttpApiKeyAndBearerAuth {} + +@http(method: "GET", uri: "/OnlyHttpApiKeyAndBearerAuthReversed") +@auth([httpBearerAuth, httpApiKeyAuth]) +operation OnlyHttpApiKeyAndBearerAuthReversed {} + +@http(method: "GET", uri: "/OnlyHttpApiKeyAuthOptional") +@auth([httpApiKeyAuth]) +@optionalAuth +operation OnlyHttpApiKeyAuthOptional {} + +@http(method: "GET", uri: "/SameAsService") +operation SameAsService {} + resource City { identifiers: {cityId: CityId} create: CreateCity