|
29 | 29 | import software.amazon.smithy.model.shapes.ToShapeId;
|
30 | 30 | import software.amazon.smithy.model.traits.AuthDefinitionTrait;
|
31 | 31 | import software.amazon.smithy.model.traits.AuthTrait;
|
| 32 | +import software.amazon.smithy.model.traits.OptionalAuthTrait; |
32 | 33 | import software.amazon.smithy.model.traits.ProtocolDefinitionTrait;
|
33 | 34 | import software.amazon.smithy.model.traits.Trait;
|
| 35 | +import software.amazon.smithy.model.traits.synthetic.NoAuthTrait; |
| 36 | +import software.amazon.smithy.utils.MapUtils; |
34 | 37 |
|
35 | 38 | /**
|
36 | 39 | * An index that resolves service protocols and auth schemes.
|
@@ -63,6 +66,25 @@ public static ServiceIndex of(Model model) {
|
63 | 66 | return model.getKnowledge(ServiceIndex.class, ServiceIndex::new);
|
64 | 67 | }
|
65 | 68 |
|
| 69 | + /** |
| 70 | + * Defines the type of auth schemes returned by {@link #getEffectiveAuthSchemes}. |
| 71 | + */ |
| 72 | + public enum AuthSchemeMode { |
| 73 | + |
| 74 | + /** |
| 75 | + * Use only the modeled auth schemes. This is the default. |
| 76 | + */ |
| 77 | + MODELED, |
| 78 | + |
| 79 | + /** |
| 80 | + * Use the modeled auth schemes, as well as the synthetic {@link NoAuthTrait} where applicable. |
| 81 | + * |
| 82 | + * <p>The Smithy Reference Architecture recommends using the {@code smithy.api#noAuth} auth scheme to represent |
| 83 | + * no authentication which is available as the {@link NoAuthTrait}. |
| 84 | + */ |
| 85 | + NO_AUTH_AWARE; |
| 86 | + } |
| 87 | + |
66 | 88 | /**
|
67 | 89 | * Get all protocol traits attached to a service.
|
68 | 90 | *
|
@@ -154,6 +176,30 @@ public Map<ShapeId, Trait> getEffectiveAuthSchemes(ToShapeId service) {
|
154 | 176 | .orElse(Collections.emptyMap());
|
155 | 177 | }
|
156 | 178 |
|
| 179 | + /** |
| 180 | + * Gets a list of effective authentication schemes applied to a service, based on the AuthSchemeMode. |
| 181 | + * |
| 182 | + * <p>If AuthSchemeMode is {@code MODELED}, which is the default, the behavior is same as |
| 183 | + * {@link #getEffectiveAuthSchemes(ToShapeId)}. |
| 184 | + * |
| 185 | + * <p>If AuthSchemeMode is {@code NO_AUTH_AWARE}, the behavior is same, except that if the service has no effective |
| 186 | + * auth schemes, instead of an empty map, it returns the {@code smithy.api#noAuth} auth scheme. It avoids having to |
| 187 | + * special case handling an empty result. The returned map will always contain at least 1 entry. |
| 188 | + * |
| 189 | + * @param service Service to get the effective authentication schemes of. |
| 190 | + * @param authSchemeMode AuthSchemeMode to determine which authentication schemes to include. |
| 191 | + * @return Returns a map of the trait shape ID to the auth trait itself. |
| 192 | + */ |
| 193 | + public Map<ShapeId, Trait> getEffectiveAuthSchemes(ToShapeId service, AuthSchemeMode authSchemeMode) { |
| 194 | + Map<ShapeId, Trait> authSchemes = getEffectiveAuthSchemes(service); |
| 195 | + if (authSchemeMode == AuthSchemeMode.NO_AUTH_AWARE) { |
| 196 | + if (authSchemes.isEmpty()) { |
| 197 | + authSchemes = MapUtils.of(NoAuthTrait.ID, new NoAuthTrait()); |
| 198 | + } |
| 199 | + } |
| 200 | + return authSchemes; |
| 201 | + } |
| 202 | + |
157 | 203 | /**
|
158 | 204 | * Gets a list of effective authentication schemes applied to an operation
|
159 | 205 | * bound within a service.
|
@@ -198,7 +244,49 @@ public Map<ShapeId, Trait> getEffectiveAuthSchemes(ToShapeId service, ToShapeId
|
198 | 244 | .orElse(Collections.emptyMap());
|
199 | 245 | }
|
200 | 246 |
|
201 |
| - private Map<ShapeId, Trait> getAuthTraitValues(Shape service, Shape subject) { |
| 247 | + /** |
| 248 | + * Gets a list of effective authentication schemes applied to an operation |
| 249 | + * bound within a service, based on the AuthSchemeMode. |
| 250 | + * |
| 251 | + * <p>If AuthSchemeMode is {@code MODELED}, which is the default, the behavior is same as |
| 252 | + * {@link #getEffectiveAuthSchemes(ToShapeId, ToShapeId)}. |
| 253 | + * |
| 254 | + * <p>If AuthSchemeMode is {@code NO_AUTH_AWARE}, the behavior is same, with the following differences: |
| 255 | + * If the operation has no effective auth schemes, instead of an empty map, it returns the {@code smithy.api#noAuth} |
| 256 | + * auth scheme. |
| 257 | + * If the operation has the {@code smithy.api#optionalAuth} trait, it adds {@code smithy.api#noAuth} to the end. |
| 258 | + * |
| 259 | + * <p>Using {@code NO_AUTH_AWARE} accounts for {@code smithy.api#optionalAuth} and avoids having to special case |
| 260 | + * handling an empty result. The returned map will always contain at least 1 entry. |
| 261 | + * |
| 262 | + * <p>The {@code smithy.api#noAuth} scheme, if present, is always the last scheme. |
| 263 | + * |
| 264 | + * @param service Service the operation is within. |
| 265 | + * @param operation Operation to get the effective authentication schemes of. |
| 266 | + * @param authSchemeMode AuthSchemeMode to determine which authentication schemes to include. |
| 267 | + * @return Returns a map of the trait shape ID to the auth trait itself. |
| 268 | + */ |
| 269 | + public Map<ShapeId, Trait> getEffectiveAuthSchemes(ToShapeId service, |
| 270 | + ToShapeId operation, |
| 271 | + AuthSchemeMode authSchemeMode) { |
| 272 | + Map<ShapeId, Trait> authSchemes = getEffectiveAuthSchemes(service, operation); |
| 273 | + if (authSchemeMode == AuthSchemeMode.NO_AUTH_AWARE) { |
| 274 | + if (authSchemes.isEmpty() || hasOptionalAuth(operation)) { |
| 275 | + authSchemes = new LinkedHashMap<>(authSchemes); |
| 276 | + authSchemes.put(NoAuthTrait.ID, new NoAuthTrait()); |
| 277 | + } |
| 278 | + } |
| 279 | + return authSchemes; |
| 280 | + } |
| 281 | + |
| 282 | + private boolean hasOptionalAuth(ToShapeId operation) { |
| 283 | + return getModel() |
| 284 | + .getShape(operation.toShapeId()) |
| 285 | + .filter(shape -> shape.hasTrait(OptionalAuthTrait.class)) |
| 286 | + .isPresent(); |
| 287 | + } |
| 288 | + |
| 289 | + private static Map<ShapeId, Trait> getAuthTraitValues(Shape service, Shape subject) { |
202 | 290 | if (!subject.hasTrait(AuthTrait.class)) {
|
203 | 291 | return null;
|
204 | 292 | }
|
|
0 commit comments