diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/knowledge/ServiceIndex.java b/smithy-model/src/main/java/software/amazon/smithy/model/knowledge/ServiceIndex.java
index 0c32dc009dd..b458719ed0c 100644
--- a/smithy-model/src/main/java/software/amazon/smithy/model/knowledge/ServiceIndex.java
+++ b/smithy-model/src/main/java/software/amazon/smithy/model/knowledge/ServiceIndex.java
@@ -29,8 +29,11 @@
import software.amazon.smithy.model.shapes.ToShapeId;
import software.amazon.smithy.model.traits.AuthDefinitionTrait;
import software.amazon.smithy.model.traits.AuthTrait;
+import software.amazon.smithy.model.traits.OptionalAuthTrait;
import software.amazon.smithy.model.traits.ProtocolDefinitionTrait;
import software.amazon.smithy.model.traits.Trait;
+import software.amazon.smithy.model.traits.synthetic.NoAuthTrait;
+import software.amazon.smithy.utils.MapUtils;
/**
* An index that resolves service protocols and auth schemes.
@@ -63,6 +66,25 @@ public static ServiceIndex of(Model model) {
return model.getKnowledge(ServiceIndex.class, ServiceIndex::new);
}
+ /**
+ * Defines the type of auth schemes returned by {@link #getEffectiveAuthSchemes}.
+ */
+ public enum AuthSchemeMode {
+
+ /**
+ * Use only the modeled auth schemes. This is the default.
+ */
+ MODELED,
+
+ /**
+ * Use the modeled auth schemes, as well as the synthetic {@link NoAuthTrait} where applicable.
+ *
+ *
The Smithy Reference Architecture recommends using the {@code smithy.api#noAuth} auth scheme to represent
+ * no authentication which is available as the {@link NoAuthTrait}.
+ */
+ NO_AUTH_AWARE;
+ }
+
/**
* Get all protocol traits attached to a service.
*
@@ -154,6 +176,30 @@ public Map getEffectiveAuthSchemes(ToShapeId service) {
.orElse(Collections.emptyMap());
}
+ /**
+ * Gets a list of effective authentication schemes applied to a service, based on the AuthSchemeMode.
+ *
+ * If AuthSchemeMode is {@code MODELED}, which is the default, the behavior is same as
+ * {@link #getEffectiveAuthSchemes(ToShapeId)}.
+ *
+ *
If AuthSchemeMode is {@code NO_AUTH_AWARE}, the behavior is same, except that if the service has no effective
+ * auth schemes, instead of an empty map, it returns the {@code smithy.api#noAuth} auth scheme. It avoids having to
+ * special case handling an empty result. The returned map will always contain at least 1 entry.
+ *
+ * @param service Service to get the effective authentication schemes of.
+ * @param authSchemeMode AuthSchemeMode to determine which authentication schemes to include.
+ * @return Returns a map of the trait shape ID to the auth trait itself.
+ */
+ public Map getEffectiveAuthSchemes(ToShapeId service, AuthSchemeMode authSchemeMode) {
+ Map authSchemes = getEffectiveAuthSchemes(service);
+ if (authSchemeMode == AuthSchemeMode.NO_AUTH_AWARE) {
+ if (authSchemes.isEmpty()) {
+ authSchemes = MapUtils.of(NoAuthTrait.ID, new NoAuthTrait());
+ }
+ }
+ return authSchemes;
+ }
+
/**
* Gets a list of effective authentication schemes applied to an operation
* bound within a service.
@@ -198,7 +244,49 @@ public Map getEffectiveAuthSchemes(ToShapeId service, ToShapeId
.orElse(Collections.emptyMap());
}
- private Map getAuthTraitValues(Shape service, Shape subject) {
+ /**
+ * Gets a list of effective authentication schemes applied to an operation
+ * bound within a service, based on the AuthSchemeMode.
+ *
+ * If AuthSchemeMode is {@code MODELED}, which is the default, the behavior is same as
+ * {@link #getEffectiveAuthSchemes(ToShapeId, ToShapeId)}.
+ *
+ *
If AuthSchemeMode is {@code NO_AUTH_AWARE}, the behavior is same, with the following differences:
+ * If the operation has no effective auth schemes, instead of an empty map, it returns the {@code smithy.api#noAuth}
+ * auth scheme.
+ * If the operation has the {@code smithy.api#optionalAuth} trait, it adds {@code smithy.api#noAuth} to the end.
+ *
+ *
Using {@code NO_AUTH_AWARE} accounts for {@code smithy.api#optionalAuth} and avoids having to special case
+ * handling an empty result. The returned map will always contain at least 1 entry.
+ *
+ *
The {@code smithy.api#noAuth} scheme, if present, is always the last scheme.
+ *
+ * @param service Service the operation is within.
+ * @param operation Operation to get the effective authentication schemes of.
+ * @param authSchemeMode AuthSchemeMode to determine which authentication schemes to include.
+ * @return Returns a map of the trait shape ID to the auth trait itself.
+ */
+ public Map getEffectiveAuthSchemes(ToShapeId service,
+ ToShapeId operation,
+ AuthSchemeMode authSchemeMode) {
+ Map authSchemes = getEffectiveAuthSchemes(service, operation);
+ if (authSchemeMode == AuthSchemeMode.NO_AUTH_AWARE) {
+ if (authSchemes.isEmpty() || hasOptionalAuth(operation)) {
+ authSchemes = new LinkedHashMap<>(authSchemes);
+ authSchemes.put(NoAuthTrait.ID, new NoAuthTrait());
+ }
+ }
+ return authSchemes;
+ }
+
+ private boolean hasOptionalAuth(ToShapeId operation) {
+ return getModel()
+ .getShape(operation.toShapeId())
+ .filter(shape -> shape.hasTrait(OptionalAuthTrait.class))
+ .isPresent();
+ }
+
+ private static Map getAuthTraitValues(Shape service, Shape subject) {
if (!subject.hasTrait(AuthTrait.class)) {
return null;
}
diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/synthetic/NoAuthTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/synthetic/NoAuthTrait.java
new file mode 100644
index 00000000000..d49a472e4fa
--- /dev/null
+++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/synthetic/NoAuthTrait.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package software.amazon.smithy.model.traits.synthetic;
+
+import software.amazon.smithy.model.knowledge.ServiceIndex;
+import software.amazon.smithy.model.knowledge.ServiceIndex.AuthSchemeMode;
+import software.amazon.smithy.model.node.Node;
+import software.amazon.smithy.model.shapes.ShapeId;
+import software.amazon.smithy.model.traits.AnnotationTrait;
+
+/**
+ * An auth scheme trait for {@code smithy.api#noAuth} which indicates no authentication. This is not a real trait
+ * in the semantic model, but a valid auth scheme for use in {@link ServiceIndex#getEffectiveAuthSchemes} with
+ * {@link AuthSchemeMode#NO_AUTH_AWARE}.
+ */
+public final class NoAuthTrait extends AnnotationTrait {
+
+ public static final ShapeId ID = ShapeId.from("smithy.api#noAuth");
+
+ public NoAuthTrait() {
+ super(ID, Node.objectNode());
+ }
+
+ @Override
+ public boolean isSynthetic() {
+ return true;
+ }
+}
diff --git a/smithy-model/src/test/java/software/amazon/smithy/model/knowledge/ServiceIndexTest.java b/smithy-model/src/test/java/software/amazon/smithy/model/knowledge/ServiceIndexTest.java
index e7e899a6fdd..e58285e6923 100644
--- a/smithy-model/src/test/java/software/amazon/smithy/model/knowledge/ServiceIndexTest.java
+++ b/smithy-model/src/test/java/software/amazon/smithy/model/knowledge/ServiceIndexTest.java
@@ -16,12 +16,13 @@
package software.amazon.smithy.model.knowledge;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.equalTo;
+import static software.amazon.smithy.model.knowledge.ServiceIndex.AuthSchemeMode.NO_AUTH_AWARE;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.AfterAll;
@@ -33,9 +34,12 @@
import software.amazon.smithy.model.traits.HttpBearerAuthTrait;
import software.amazon.smithy.model.traits.HttpDigestAuthTrait;
import software.amazon.smithy.model.traits.Trait;
+import software.amazon.smithy.model.traits.synthetic.NoAuthTrait;
public class ServiceIndexTest {
+ private static final ShapeId CUSTOM_AUTH_ID = ShapeId.from("smithy.example#customAuth");
+
private static Model model;
@BeforeAll
@@ -52,7 +56,7 @@ public static void after() {
}
@Test
- public void returnsProtocolsOfService() {
+ public void protocolsOfService() {
Model model = Model.assembler()
.addImport(getClass().getResource("service-index-loads-protocols.smithy"))
.assemble()
@@ -66,88 +70,193 @@ public void returnsProtocolsOfService() {
}
@Test
- public void returnsAuthSchemesOfService() {
+ public void authSchemesOfService() {
ServiceIndex serviceIndex = ServiceIndex.of(model);
Map auth = serviceIndex.getAuthSchemes(
- ShapeId.from("smithy.example#ServiceWithNoAuthTrait"));
+ ShapeId.from("smithy.example#ServiceWithoutAuthTrait"));
+ assertAuthSchemes(auth, HttpBasicAuthTrait.ID, HttpBearerAuthTrait.ID, HttpDigestAuthTrait.ID, CUSTOM_AUTH_ID);
+ }
- List ids = new ArrayList<>(auth.keySet());
- assertThat(ids, hasSize(3));
- assertThat(ids.get(0), equalTo(HttpBasicAuthTrait.ID));
- assertThat(ids.get(1), equalTo(HttpBearerAuthTrait.ID));
- assertThat(ids.get(2), equalTo(HttpDigestAuthTrait.ID));
+ @Test
+ public void authSchemesOfServiceWithoutAuthTrait() {
+ ServiceIndex serviceIndex = ServiceIndex.of(model);
+ ShapeId service = ShapeId.from("smithy.example#ServiceWithoutAuthTrait");
+
+ Map auth = serviceIndex.getEffectiveAuthSchemes(service);
+ assertAuthSchemes(auth, HttpBasicAuthTrait.ID, HttpBearerAuthTrait.ID, HttpDigestAuthTrait.ID, CUSTOM_AUTH_ID);
+
+ auth = serviceIndex.getEffectiveAuthSchemes(service, NO_AUTH_AWARE);
+ assertAuthSchemes(auth, HttpBasicAuthTrait.ID, HttpBearerAuthTrait.ID, HttpDigestAuthTrait.ID, CUSTOM_AUTH_ID);
}
@Test
- public void getsAuthSchemesOfServiceWithNoAuthTrait() {
+ public void authSchemesOfServiceWithAuthTrait() {
ServiceIndex serviceIndex = ServiceIndex.of(model);
- Map auth = serviceIndex.getEffectiveAuthSchemes(
- ShapeId.from("smithy.example#ServiceWithNoAuthTrait"));
+ ShapeId service = ShapeId.from("smithy.example#ServiceWithAuthTrait");
- List ids = new ArrayList<>(auth.keySet());
- assertThat(ids, hasSize(3));
- assertThat(ids.get(0), equalTo(HttpBasicAuthTrait.ID));
- assertThat(ids.get(1), equalTo(HttpBearerAuthTrait.ID));
- assertThat(ids.get(2), equalTo(HttpDigestAuthTrait.ID));
+ Map auth = serviceIndex.getEffectiveAuthSchemes(service);
+ assertAuthSchemes(auth, HttpBasicAuthTrait.ID, HttpDigestAuthTrait.ID);
+
+ auth = serviceIndex.getEffectiveAuthSchemes(service, NO_AUTH_AWARE);
+ assertAuthSchemes(auth, HttpBasicAuthTrait.ID, HttpDigestAuthTrait.ID);
}
@Test
- public void getsAuthSchemesOfServiceWithAuthTrait() {
+ public void authSchemesOfServiceWithEmptyAuthTrait() {
ServiceIndex serviceIndex = ServiceIndex.of(model);
- Map auth = serviceIndex.getEffectiveAuthSchemes(
- ShapeId.from("smithy.example#ServiceWithAuthTrait"));
+ ShapeId service = ShapeId.from("smithy.example#ServiceWithEmptyAuthTrait");
- List ids = new ArrayList<>(auth.keySet());
- assertThat(auth.keySet(), hasSize(2));
- assertThat(ids.get(0), equalTo(HttpBasicAuthTrait.ID));
- assertThat(ids.get(1), equalTo(HttpDigestAuthTrait.ID));
+ Map auth = serviceIndex.getEffectiveAuthSchemes(service);
+ assertAuthSchemes(auth);
+
+ auth = serviceIndex.getEffectiveAuthSchemes(service, NO_AUTH_AWARE);
+ assertAuthSchemes(auth, NoAuthTrait.ID);
}
@Test
- public void getsAuthSchemesOfOperationWithNoAuthTraitAndServiceWithNoAuthTrait() {
+ public void authSchemesOfServiceWithoutAuthDefinitionTraits() {
ServiceIndex serviceIndex = ServiceIndex.of(model);
- Map auth = serviceIndex.getEffectiveAuthSchemes(
- ShapeId.from("smithy.example#ServiceWithNoAuthTrait"),
- ShapeId.from("smithy.example#OperationWithNoAuthTrait"));
+ ShapeId service = ShapeId.from("smithy.example#ServiceWithoutAuthDefinitionTraits");
- List ids = new ArrayList<>(auth.keySet());
- assertThat(ids, hasSize(3));
- assertThat(ids.get(0), equalTo(HttpBasicAuthTrait.ID));
- assertThat(ids.get(1), equalTo(HttpBearerAuthTrait.ID));
- assertThat(ids.get(2), equalTo(HttpDigestAuthTrait.ID));
+ Map auth = serviceIndex.getEffectiveAuthSchemes(service);
+ assertAuthSchemes(auth);
+
+ auth = serviceIndex.getEffectiveAuthSchemes(service, NO_AUTH_AWARE);
+ assertAuthSchemes(auth, NoAuthTrait.ID);
}
@Test
- public void getsAuthSchemesOfOperationWithNoAuthTraitAndServiceWithAuthTrait() {
+ public void authSchemesOfOperationWithoutAuthTraitAndServiceWithoutAuthTrait() {
ServiceIndex serviceIndex = ServiceIndex.of(model);
- Map auth = serviceIndex.getEffectiveAuthSchemes(
- ShapeId.from("smithy.example#ServiceWithAuthTrait"),
- ShapeId.from("smithy.example#OperationWithNoAuthTrait"));
+ ShapeId service = ShapeId.from("smithy.example#ServiceWithoutAuthTrait");
+ ShapeId operation = ShapeId.from("smithy.example#OperationWithoutAuthTrait");
- List ids = new ArrayList<>(auth.keySet());
- assertThat(ids, hasSize(2));
- assertThat(ids.get(0), equalTo(HttpBasicAuthTrait.ID));
- assertThat(ids.get(1), equalTo(HttpDigestAuthTrait.ID));
+ Map auth = serviceIndex.getEffectiveAuthSchemes(service, operation);
+ assertAuthSchemes(auth, HttpBasicAuthTrait.ID, HttpBearerAuthTrait.ID, HttpDigestAuthTrait.ID, CUSTOM_AUTH_ID);
+
+ auth = serviceIndex.getEffectiveAuthSchemes(service, operation, NO_AUTH_AWARE);
+ assertAuthSchemes(auth, HttpBasicAuthTrait.ID, HttpBearerAuthTrait.ID, HttpDigestAuthTrait.ID, CUSTOM_AUTH_ID);
}
@Test
- public void getsAuthSchemesOfOperationWithAuthTrait() {
+ public void authSchemesOfOperationWithoutAuthTraitAndServiceWithAuthTrait() {
+ ServiceIndex serviceIndex = ServiceIndex.of(model);
+ ShapeId service = ShapeId.from("smithy.example#ServiceWithAuthTrait");
+ ShapeId operation = ShapeId.from("smithy.example#OperationWithoutAuthTrait");
+
+ Map auth = serviceIndex.getEffectiveAuthSchemes(service, operation);
+ assertAuthSchemes(auth, HttpBasicAuthTrait.ID, HttpDigestAuthTrait.ID);
+
+ auth = serviceIndex.getEffectiveAuthSchemes(service, operation, NO_AUTH_AWARE);
+ assertAuthSchemes(auth, HttpBasicAuthTrait.ID, HttpDigestAuthTrait.ID);
+ }
+
+ @Test
+ public void authSchemesOfOperationWithoutAuthTraitAndServiceWithEmptyAuthTrait() {
+ ServiceIndex serviceIndex = ServiceIndex.of(model);
+ ShapeId service = ShapeId.from("smithy.example#ServiceWithEmptyAuthTrait");
+ ShapeId operation = ShapeId.from("smithy.example#OperationWithoutAuthTrait");
+
+ Map auth = serviceIndex.getEffectiveAuthSchemes(service, operation);
+ assertAuthSchemes(auth);
+
+ auth = serviceIndex.getEffectiveAuthSchemes(service, operation, NO_AUTH_AWARE);
+ assertAuthSchemes(auth, NoAuthTrait.ID);
+ }
+
+ @Test
+ public void authSchemesOfOperationWithAuthTrait() {
ServiceIndex serviceIndex = ServiceIndex.of(model);
Map auth = serviceIndex.getEffectiveAuthSchemes(
ShapeId.from("smithy.example#ServiceWithAuthTrait"),
ShapeId.from("smithy.example#OperationWithAuthTrait"));
+ assertAuthSchemes(auth, HttpDigestAuthTrait.ID);
+ }
- assertThat(auth.keySet(), hasSize(1));
- assertThat(auth, hasKey(HttpDigestAuthTrait.ID));
+ @Test
+ public void authSchemesOfOperationWithEmptyAuthTrait() {
+ ServiceIndex serviceIndex = ServiceIndex.of(model);
+ ShapeId service = ShapeId.from("smithy.example#ServiceWithAuthTrait");
+ ShapeId operation = ShapeId.from("smithy.example#OperationWithEmptyAuthTrait");
+
+ Map auth = serviceIndex.getEffectiveAuthSchemes(service, operation);
+ assertAuthSchemes(auth);
+
+ auth = serviceIndex.getEffectiveAuthSchemes(service, operation, NO_AUTH_AWARE);
+ assertAuthSchemes(auth, NoAuthTrait.ID);
}
@Test
- public void returnsAnEmptyCollectionWhenTheServiceDoesNotExist() {
+ public void authSchemesOfOperationWithOptionalAuthTrait() {
ServiceIndex serviceIndex = ServiceIndex.of(model);
- Map auth = serviceIndex.getEffectiveAuthSchemes(
- ShapeId.from("smithy.example#Invalid"),
- ShapeId.from("smithy.example#OperationWithAuthTrait"));
+ ShapeId service = ShapeId.from("smithy.example#ServiceWithAuthTrait");
+ ShapeId operation = ShapeId.from("smithy.example#OperationWithOptionalAuthTrait");
+
+ Map auth = serviceIndex.getEffectiveAuthSchemes(service, operation);
+ assertAuthSchemes(auth, HttpBasicAuthTrait.ID, HttpDigestAuthTrait.ID);
+
+ auth = serviceIndex.getEffectiveAuthSchemes(service, operation, NO_AUTH_AWARE);
+ assertAuthSchemes(auth, HttpBasicAuthTrait.ID, HttpDigestAuthTrait.ID, NoAuthTrait.ID);
+ }
+
+ // Test to assert that smithy.api#noAuth trait is not part of traits that are sorted alphabetically, but last.
+ // The authSchemesOfOperationWithOptionalAuthTrait() test above doesn't really assert that, because
+ // smithy.api#noAuth would have been last if included in sorting.
+ @Test
+ public void authSchemesOfOperationWithOptionalAuthTraitAndServiceWithoutAuthTrait() {
+ ServiceIndex serviceIndex = ServiceIndex.of(model);
+ ShapeId service = ShapeId.from("smithy.example#ServiceWithoutAuthTrait");
+ ShapeId operation = ShapeId.from("smithy.example#OperationWithOptionalAuthTrait");
+
+ Map auth = serviceIndex.getEffectiveAuthSchemes(service, operation);
+ assertAuthSchemes(auth, HttpBasicAuthTrait.ID, HttpBearerAuthTrait.ID, HttpDigestAuthTrait.ID, CUSTOM_AUTH_ID);
+
+ auth = serviceIndex.getEffectiveAuthSchemes(service, operation, NO_AUTH_AWARE);
+ assertAuthSchemes(auth, HttpBasicAuthTrait.ID, HttpBearerAuthTrait.ID, HttpDigestAuthTrait.ID, CUSTOM_AUTH_ID,
+ NoAuthTrait.ID);
+ }
+
+ @Test
+ public void authSchemesOfInvalidService() {
+ ServiceIndex serviceIndex = ServiceIndex.of(model);
+ ShapeId service = ShapeId.from("smithy.example#Invalid");
+
+ Map auth = serviceIndex.getEffectiveAuthSchemes(service);
+ assertAuthSchemes(auth);
- assertThat(auth.keySet(), empty());
+ auth = serviceIndex.getEffectiveAuthSchemes(service, NO_AUTH_AWARE);
+ assertAuthSchemes(auth, NoAuthTrait.ID);
+ }
+
+ @Test
+ public void authSchemesOfInvalidServiceWithInvalidOperation() {
+ ServiceIndex serviceIndex = ServiceIndex.of(model);
+ ShapeId service = ShapeId.from("smithy.example#Invalid");
+ ShapeId operation = ShapeId.from("smithy.example#OperationWithAuthTrait");
+
+ Map auth = serviceIndex.getEffectiveAuthSchemes(service, operation);
+ assertAuthSchemes(auth);
+
+ auth = serviceIndex.getEffectiveAuthSchemes(service, operation, NO_AUTH_AWARE);
+ assertAuthSchemes(auth, NoAuthTrait.ID);
+ }
+
+ @Test
+ public void authSchemesOfServiceWithInvalidOperation() {
+ ServiceIndex serviceIndex = ServiceIndex.of(model);
+ ShapeId service = ShapeId.from("smithy.example#ServiceWithoutAuthTrait");
+ ShapeId operation = ShapeId.from("smithy.example#InvalidOperation");
+
+ Map auth = serviceIndex.getEffectiveAuthSchemes(service, operation);
+ assertAuthSchemes(auth);
+
+ auth = serviceIndex.getEffectiveAuthSchemes(service, operation, NO_AUTH_AWARE);
+ assertAuthSchemes(auth, NoAuthTrait.ID);
+ }
+
+ private void assertAuthSchemes(Map auth, ShapeId... authSchemes) {
+ List ids = new ArrayList<>(auth.keySet());
+ assertThat(ids, hasSize(authSchemes.length));
+ assertThat(ids, equalTo(Arrays.asList(authSchemes)));
}
}
diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/service-index-finds-auth-schemes.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/service-index-finds-auth-schemes.smithy
index 95d5d6c8a5c..1a2ccb168b3 100644
--- a/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/service-index-finds-auth-schemes.smithy
+++ b/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/service-index-finds-auth-schemes.smithy
@@ -2,30 +2,77 @@ $version: "2"
namespace smithy.example
+@customAuth
@httpBasicAuth
@httpDigestAuth
@httpBearerAuth
-service ServiceWithNoAuthTrait {
- version: "2020-01-29",
+service ServiceWithoutAuthTrait {
+ version: "2020-01-29"
operations: [
- OperationWithNoAuthTrait,
+ OperationWithoutAuthTrait
OperationWithAuthTrait
+ OperationWithEmptyAuthTrait
+ OperationWithOptionalAuthTrait
]
}
+@customAuth
@httpBasicAuth
@httpDigestAuth
@httpBearerAuth
@auth([httpBasicAuth, httpDigestAuth])
service ServiceWithAuthTrait {
- version: "2020-01-29",
+ version: "2020-01-29"
operations: [
- OperationWithNoAuthTrait,
+ OperationWithoutAuthTrait
OperationWithAuthTrait
+ OperationWithEmptyAuthTrait
+ OperationWithOptionalAuthTrait
]
}
-operation OperationWithNoAuthTrait {}
+@customAuth
+@httpBasicAuth
+@httpDigestAuth
+@httpBearerAuth
+@auth([])
+service ServiceWithEmptyAuthTrait {
+ version: "2020-01-29"
+ operations: [
+ OperationWithoutAuthTrait
+ OperationWithAuthTrait
+ OperationWithEmptyAuthTrait
+ OperationWithOptionalAuthTrait
+ ]
+}
+
+service ServiceWithoutAuthDefinitionTraits {
+ version: "2020-01-29"
+ operations: [
+ OperationWithoutAuthTrait
+ OperationWithEmptyAuthTrait
+ OperationWithOptionalAuthTrait
+ ]
+}
+
+operation OperationWithoutAuthTrait {}
@auth([httpDigestAuth])
operation OperationWithAuthTrait {}
+
+@auth([])
+operation OperationWithEmptyAuthTrait {}
+
+@optionalAuth
+operation OperationWithOptionalAuthTrait {}
+
+// Defining a custom trait, to assert that alphabetical sorting of traits takes namespace into account, as well as
+// smithy.api#noAuth is added to the end, and not included in sorting.
+@trait(
+ selector: "service"
+ breakingChanges: [
+ {change: "remove"}
+ ]
+)
+@authDefinition
+structure customAuth {}