Skip to content

Commit 2d08997

Browse files
authored
fix: add missing aws_iam directive on custom types (#3270)
* fix: add missing aws_iam directive on custom types * chore: update api extract * chore: remove todos * test: add iam auth test specifically for EventInvocationResponse type --------- Co-authored-by: Jon Wire <wirej@amazon.com>
1 parent 34ffc45 commit 2d08997

3 files changed

Lines changed: 67 additions & 4 deletions

File tree

packages/amplify-graphql-auth-transformer/API.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ export class AuthTransformer extends TransformerAuthBase implements TransformerA
117117
// (undocumented)
118118
addFieldsToObject: (ctx: TransformerTransformSchemaStepContextProvider, modelName: string, ownerFields: Array<string>) => void;
119119
// (undocumented)
120+
addIamAuthToCustomTypes: (ctx: TransformerTransformSchemaStepContextProvider) => void;
121+
// (undocumented)
120122
after: (context: TransformerContextProvider) => void;
121123
// (undocumented)
122124
before: (context: TransformerBeforeStepContextProvider) => void;

packages/amplify-graphql-auth-transformer/src/__tests__/iam-custom-operations.test.ts

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { FunctionTransformer } from '@aws-amplify/graphql-function-transformer';
12
import { ModelTransformer } from '@aws-amplify/graphql-model-transformer';
23
import { mockSqlDataSourceStrategy, testTransform } from '@aws-amplify/graphql-transformer-test-utils';
34
import { PrimaryKeyTransformer } from '@aws-amplify/graphql-index-transformer';
@@ -40,6 +41,7 @@ const makeTransformers = (): TransformerPluginProvider[] => [
4041
new AuthTransformer(),
4142
new PrimaryKeyTransformer(),
4243
new SqlTransformer(),
44+
new FunctionTransformer(),
4345
];
4446

4547
const makeSqlDirectiveDataSourceStrategies = (schema: string, strategy: ModelDataSourceStrategy): SqlDirectiveDataSourceStrategy[] =>
@@ -367,8 +369,7 @@ describe('Custom operations have @aws_iam directives when enableIamAuthorization
367369
expect(out.schema).not.toMatch(/onUpdateFooCustom: String.*@aws_iam/);
368370
});
369371

370-
// TODO: Enable this test once we fix https://github.com/aws-amplify/amplify-category-api/issues/2929
371-
test.skip('Adds @aws_iam to non-model custom types when there is no model', () => {
372+
test('Adds @aws_iam to non-model custom types when there is no model', () => {
372373
const strategy = makeStrategy(strategyType);
373374
const schema = /* GraphQL */ `
374375
type Foo {
@@ -403,8 +404,7 @@ describe('Custom operations have @aws_iam directives when enableIamAuthorization
403404
expect(out.schema).toMatch(/type Foo.*@aws_iam/);
404405
});
405406

406-
// TODO: Enable this test once we fix https://github.com/aws-amplify/amplify-category-api/issues/2929
407-
test.skip('Adds @aws_iam to non-model custom types when there is a model', () => {
407+
test('Adds @aws_iam to non-model custom types when there is a model', () => {
408408
const strategy = makeStrategy(strategyType);
409409
const schema = /* GraphQL */ `
410410
type Todo @model {
@@ -478,6 +478,42 @@ describe('Custom operations have @aws_iam directives when enableIamAuthorization
478478
expect(out.schema).toMatch(/description: String.*@aws_iam/);
479479
});
480480

481+
test('Adds @aws_iam to async function EventInvocationResponse type', () => {
482+
const strategy = makeStrategy(strategyType);
483+
const schema = /* GraphQL */ `
484+
type Foo {
485+
description: String
486+
}
487+
type EventInvocationResponse @aws_api_key {
488+
success: Boolean!
489+
}
490+
type Query {
491+
getFooCustom: Foo
492+
}
493+
type Mutation {
494+
updateFooCustom: Foo
495+
doSomethingAsync(body: String!): EventInvocationResponse
496+
@function(name: "FnDoSomethingAsync", invocationType: Event)
497+
@auth(rules: [{ allow: public, provider: apiKey }])
498+
}
499+
type Subscription {
500+
onUpdateFooCustom: Foo @aws_subscribe(mutations: ["updateFooCustom"])
501+
}
502+
`;
503+
504+
const out = testTransform({
505+
schema,
506+
dataSourceStrategies: constructDataSourceStrategies(schema, strategy),
507+
authConfig: makeAuthConfig(),
508+
synthParameters: makeSynthParameters(),
509+
transformers: makeTransformers(),
510+
sqlDirectiveDataSourceStrategies: makeSqlDirectiveDataSourceStrategies(schema, strategy),
511+
});
512+
513+
// Also expect the custom type referenced by the custom operation to be authorized
514+
expect(out.schema).toMatch(/type EventInvocationResponse.*@aws_iam/);
515+
});
516+
481517
test('Does not add duplicate @aws_iam directive to custom type if already present', () => {
482518
const strategy = makeStrategy(strategyType);
483519
const schema = /* GraphQL */ `

packages/amplify-graphql-auth-transformer/src/graphql-auth-transformer.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
isBuiltInGraphqlNode,
1111
isDynamoDbModel,
1212
isModelType,
13+
isObjectTypeDefinitionNode,
1314
isSqlModel,
1415
MappingTemplate,
1516
TransformerAuthBase,
@@ -377,8 +378,32 @@ export class AuthTransformer extends TransformerAuthBase implements TransformerA
377378
});
378379
};
379380

381+
/**
382+
* Adds the `aws_iam` directive to all custom/non-model types when IAM access is enabled.
383+
*/
384+
addIamAuthToCustomTypes = (ctx: TransformerTransformSchemaStepContextProvider): void => {
385+
if (!ctx.transformParameters.sandboxModeEnabled && !ctx.synthParameters.enableIamAccess) {
386+
return;
387+
}
388+
389+
const needsAwsIamDirective = (type: TypeDefinitionNode): boolean => {
390+
return !type.directives?.some((dir) => dir.name.value === 'aws_iam');
391+
};
392+
393+
const isNonModelType = (type: TypeDefinitionNode): boolean => {
394+
return !type.directives?.some((dir) => dir.name.value === 'model');
395+
};
396+
397+
ctx.inputDocument.definitions
398+
.filter(isObjectTypeDefinitionNode)
399+
.filter(isNonModelType)
400+
.filter(needsAwsIamDirective)
401+
.forEach((def) => extendTypeWithDirectives(ctx, def.name.value, [makeDirective('aws_iam', [])]));
402+
};
403+
380404
transformSchema = (context: TransformerTransformSchemaStepContextProvider): void => {
381405
this.addCustomOperationFieldsToAuthNonModelConfig(context);
406+
this.addIamAuthToCustomTypes(context);
382407

383408
const searchableAggregateServiceDirectives = new Set<AuthProvider>();
384409

0 commit comments

Comments
 (0)