From e3299e5c09884218d486d4a488f343972674a417 Mon Sep 17 00:00:00 2001 From: Josue Ruiz <7465495+SwaySway@users.noreply.github.com> Date: Fri, 22 Oct 2021 12:49:33 -0700 Subject: [PATCH] fix: add schema directives for sync operation when conflict resolution is enabled (#8521) --- .../conflict-resolution.test.ts.snap | 52 ++++++++++++++ .../src/__tests__/amplify-admin-auth.test.ts | 2 +- .../src/__tests__/conflict-resolution.test.ts | 70 +++++++++++++++++++ .../src/__tests__/field-auth-argument.test.ts | 2 +- .../src/__tests__/group-auth.test.ts | 2 +- .../src/__tests__/multi-auth.test.ts | 2 +- .../src/__tests__/owner-auth.test.ts | 2 +- .../src/__tests__/searchable-auth.test.ts | 2 +- .../src/graphql-auth-transformer.ts | 5 +- 9 files changed, 131 insertions(+), 8 deletions(-) create mode 100644 packages/amplify-graphql-auth-transformer/src/__tests__/__snapshots__/conflict-resolution.test.ts.snap create mode 100644 packages/amplify-graphql-auth-transformer/src/__tests__/conflict-resolution.test.ts diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/__snapshots__/conflict-resolution.test.ts.snap b/packages/amplify-graphql-auth-transformer/src/__tests__/__snapshots__/conflict-resolution.test.ts.snap new file mode 100644 index 00000000000..a736cdea5da --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/__snapshots__/conflict-resolution.test.ts.snap @@ -0,0 +1,52 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test multi auth model with conflict resolution 1`] = ` +"## [Start] Authorization Steps. ** +$util.qr($ctx.stash.put(\\"hasAuth\\", true)) +#set( $isAuthorized = false ) +#set( $primaryFieldMap = {} ) +#if( $util.authType() == \\"IAM Authorization\\" ) + #if( !$isAuthorized ) + #if( $ctx.identity.userArn == $ctx.stash.authRole ) + #set( $isAuthorized = true ) + #end + #end +#end +#if( $util.authType() == \\"User Pool Authorization\\" ) + #if( !$isAuthorized ) + #set( $authFilter = [{ + \\"owner\\": { + \\"eq\\": $util.defaultIfNull($ctx.identity.claims.get(\\"username\\"), $util.defaultIfNull($ctx.identity.claims.get(\\"cognito:username\\"), \\"___xamznone____\\")) + } +}] ) + $util.qr($ctx.stash.put(\\"authFilter\\", { \\"or\\": $authFilter })) + #end +#end +#if( !$isAuthorized && $util.isNull($ctx.stash.authFilter) && $primaryFieldMap.isEmpty() ) +$util.unauthorized() +#end +$util.toJson({\\"version\\":\\"2018-05-29\\",\\"payload\\":{}}) +## [End] Authorization Steps. **" +`; + +exports[`test single auth model is enabled with conflict resolution 1`] = ` +"## [Start] Authorization Steps. ** +$util.qr($ctx.stash.put(\\"hasAuth\\", true)) +#set( $isAuthorized = false ) +#set( $primaryFieldMap = {} ) +#if( $util.authType() == \\"User Pool Authorization\\" ) + #if( !$isAuthorized ) + #set( $authFilter = [{ + \\"owner\\": { + \\"eq\\": $util.defaultIfNull($ctx.identity.claims.get(\\"username\\"), $util.defaultIfNull($ctx.identity.claims.get(\\"cognito:username\\"), \\"___xamznone____\\")) + } +}] ) + $util.qr($ctx.stash.put(\\"authFilter\\", { \\"or\\": $authFilter })) + #end +#end +#if( !$isAuthorized && $util.isNull($ctx.stash.authFilter) && $primaryFieldMap.isEmpty() ) +$util.unauthorized() +#end +$util.toJson({\\"version\\":\\"2018-05-29\\",\\"payload\\":{}}) +## [End] Authorization Steps. **" +`; diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/amplify-admin-auth.test.ts b/packages/amplify-graphql-auth-transformer/src/__tests__/amplify-admin-auth.test.ts index ce358a0143e..2ca7f2e4098 100644 --- a/packages/amplify-graphql-auth-transformer/src/__tests__/amplify-admin-auth.test.ts +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/amplify-admin-auth.test.ts @@ -1,4 +1,4 @@ -import { AuthTransformer } from '@aws-amplify/graphql-auth-transformer'; +import { AuthTransformer } from '../graphql-auth-transformer'; import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'; import { GraphQLTransform } from '@aws-amplify/graphql-transformer-core'; import _ from 'lodash'; diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/conflict-resolution.test.ts b/packages/amplify-graphql-auth-transformer/src/__tests__/conflict-resolution.test.ts new file mode 100644 index 00000000000..3ce36ff6494 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/conflict-resolution.test.ts @@ -0,0 +1,70 @@ +import { AuthTransformer } from '../graphql-auth-transformer'; +import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'; +import { GraphQLTransform, ConflictHandlerType } from '@aws-amplify/graphql-transformer-core'; +import _ from 'lodash'; + +test('test single auth model is enabled with conflict resolution', () => { + const validSchema = ` + type Post @model @auth(rules: [{ allow: owner}]) { + id: ID! + title: String! + createdAt: String + updatedAt: String + }`; + const transformer = new GraphQLTransform({ + authConfig: { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [], + }, + transformConfig: { + ResolverConfig: { + project: { + ConflictDetection: 'VERSION', + ConflictHandler: ConflictHandlerType.AUTOMERGE, + }, + }, + }, + transformers: [new ModelTransformer(), new AuthTransformer()], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + expect(out.schema).toContain( + `syncPosts(filter: ModelPostFilterInput, limit: Int, nextToken: String, lastSync: AWSTimestamp): ModelPostConnection`, + ); + expect(out.pipelineFunctions['Query.syncPosts.auth.1.req.vtl']).toMatchSnapshot(); +}); + +test('test multi auth model with conflict resolution', () => { + const validSchema = ` + type Post @model @auth(rules: [{ allow: owner }, { allow: private, provider: iam }]) { + id: ID! + title: String! + createdAt: String + updatedAt: String + }`; + const transformer = new GraphQLTransform({ + authConfig: { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [{ authenticationType: 'AWS_IAM' }], + }, + transformConfig: { + ResolverConfig: { + project: { + ConflictDetection: 'VERSION', + ConflictHandler: ConflictHandlerType.AUTOMERGE, + }, + }, + }, + transformers: [new ModelTransformer(), new AuthTransformer()], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + expect(out.schema).toContain( + `syncPosts(filter: ModelPostFilterInput, limit: Int, nextToken: String, lastSync: AWSTimestamp): ModelPostConnection @aws_iam @aws_cognito_user_pools`, + ); + expect(out.pipelineFunctions['Query.syncPosts.auth.1.req.vtl']).toMatchSnapshot(); +}); diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/field-auth-argument.test.ts b/packages/amplify-graphql-auth-transformer/src/__tests__/field-auth-argument.test.ts index 68ed3b95eae..d952d2acc32 100644 --- a/packages/amplify-graphql-auth-transformer/src/__tests__/field-auth-argument.test.ts +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/field-auth-argument.test.ts @@ -1,4 +1,4 @@ -import { AuthTransformer } from '@aws-amplify/graphql-auth-transformer'; +import { AuthTransformer } from '../graphql-auth-transformer'; import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'; import { GraphQLTransform } from '@aws-amplify/graphql-transformer-core'; import { ResourceConstants } from 'graphql-transformer-common'; diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/group-auth.test.ts b/packages/amplify-graphql-auth-transformer/src/__tests__/group-auth.test.ts index 6bf8f548ac8..350d843a75a 100644 --- a/packages/amplify-graphql-auth-transformer/src/__tests__/group-auth.test.ts +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/group-auth.test.ts @@ -1,4 +1,4 @@ -import { AuthTransformer } from '@aws-amplify/graphql-auth-transformer'; +import { AuthTransformer } from '../graphql-auth-transformer'; import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'; import { GraphQLTransform } from '@aws-amplify/graphql-transformer-core'; import { ResourceConstants } from 'graphql-transformer-common'; diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/multi-auth.test.ts b/packages/amplify-graphql-auth-transformer/src/__tests__/multi-auth.test.ts index 36e969dc115..3584c818a07 100644 --- a/packages/amplify-graphql-auth-transformer/src/__tests__/multi-auth.test.ts +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/multi-auth.test.ts @@ -1,4 +1,4 @@ -import { AuthTransformer } from '@aws-amplify/graphql-auth-transformer'; +import { AuthTransformer } from '../graphql-auth-transformer'; import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'; import { GraphQLTransform } from '@aws-amplify/graphql-transformer-core'; import { AppSyncAuthConfiguration, AppSyncAuthConfigurationOIDCEntry, AppSyncAuthMode } from '@aws-amplify/graphql-transformer-interfaces'; diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/owner-auth.test.ts b/packages/amplify-graphql-auth-transformer/src/__tests__/owner-auth.test.ts index db5c231707c..3cd649b0647 100644 --- a/packages/amplify-graphql-auth-transformer/src/__tests__/owner-auth.test.ts +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/owner-auth.test.ts @@ -1,5 +1,5 @@ import { parse } from 'graphql'; -import { AuthTransformer } from '@aws-amplify/graphql-auth-transformer'; +import { AuthTransformer } from '../graphql-auth-transformer'; import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'; import { GraphQLTransform } from '@aws-amplify/graphql-transformer-core'; import { ResourceConstants } from 'graphql-transformer-common'; diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/searchable-auth.test.ts b/packages/amplify-graphql-auth-transformer/src/__tests__/searchable-auth.test.ts index ee6677bcf10..e1bd1ee6dde 100644 --- a/packages/amplify-graphql-auth-transformer/src/__tests__/searchable-auth.test.ts +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/searchable-auth.test.ts @@ -1,4 +1,4 @@ -import { AuthTransformer } from '@aws-amplify/graphql-auth-transformer'; +import { AuthTransformer } from '../graphql-auth-transformer'; import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'; import { SearchableModelTransformer } from '@aws-amplify/graphql-searchable-transformer'; import { GraphQLTransform } from '@aws-amplify/graphql-transformer-core'; diff --git a/packages/amplify-graphql-auth-transformer/src/graphql-auth-transformer.ts b/packages/amplify-graphql-auth-transformer/src/graphql-auth-transformer.ts index 67f0c91c483..89da319484a 100644 --- a/packages/amplify-graphql-auth-transformer/src/graphql-auth-transformer.ts +++ b/packages/amplify-graphql-auth-transformer/src/graphql-auth-transformer.ts @@ -112,7 +112,7 @@ export class AuthTransformer extends TransformerAuthBase implements TransformerA private authPolicyResources = new Set(); private unauthPolicyResources = new Set(); - constructor(config: AuthTransformerConfig) { + constructor(config: AuthTransformerConfig = { addAwsIamAuthInOutputSchema: false }) { super('amplify-auth-transformer', authDirectiveDefinition); this.config = config; this.modelDirectiveConfig = new Map(); @@ -370,9 +370,10 @@ Static group authorization should perform as expected.`, this.addOperationToResourceReferences(typeName, operationName, acm.getRoles()); } }; - // default model operations TODO: protect sync queries once supported + // default model operations addServiceDirective(ctx.output.getQueryTypeName()!, 'read', modelConfig?.queries?.get); addServiceDirective(ctx.output.getQueryTypeName()!, 'read', modelConfig?.queries?.list); + addServiceDirective(ctx.output.getQueryTypeName()!, 'read', modelConfig?.queries?.sync); addServiceDirective(ctx.output.getMutationTypeName()!, 'create', modelConfig?.mutations?.create); addServiceDirective(ctx.output.getMutationTypeName()!, 'update', modelConfig?.mutations?.update); addServiceDirective(ctx.output.getMutationTypeName()!, 'delete', modelConfig?.mutations?.delete);