diff --git a/.circleci/config.yml b/.circleci/config.yml index d16f84b3740..8065817e72b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9518,6 +9518,36 @@ jobs: environment: TEST_SUITE: src/__tests__/schema-iterative-update-4.test.ts CLI_REGION: us-east-2 + AuthV2Transformer-e2e-graphql_e2e_tests: + working_directory: ~/repo + parameters: + os: + type: executor + default: linux + executor: << parameters.os >> + steps: + - attach_workspace: + at: ./ + - restore_cache: + key: >- + amplify-cli-yarn-deps-{{ .Branch }}-{{ checksum "yarn.lock" }}-{{ + arch }} + - run: + name: Run GraphQL end-to-end tests + command: | + source .circleci/local_publish_helpers.sh + cd packages/graphql-transformers-e2e-tests/ + retry yarn e2e --maxWorkers=3 $TEST_SUITE + environment: + AMPLIFY_CLI_DISABLE_LOGGING: 'true' + no_output_timeout: 90m + - store_test_results: + path: packages/graphql-transformers-e2e-tests/ + environment: + AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin + AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify + TEST_SUITE: src/__tests__/AuthV2Transformer.e2e.test.ts + CLI_REGION: us-east-2 ConnectionsWithAuthTests-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -9547,7 +9577,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/ConnectionsWithAuthTests.e2e.test.ts - CLI_REGION: us-east-2 + CLI_REGION: us-west-2 CustomRoots-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -9577,7 +9607,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/CustomRoots.e2e.test.ts - CLI_REGION: us-west-2 + CLI_REGION: eu-west-2 DefaultValueTransformer-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -9607,7 +9637,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/DefaultValueTransformer.e2e.test.ts - CLI_REGION: eu-west-2 + CLI_REGION: eu-central-1 DynamoDBModelTransformer-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -9637,7 +9667,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/DynamoDBModelTransformer.e2e.test.ts - CLI_REGION: eu-central-1 + CLI_REGION: ap-northeast-1 FunctionTransformerTests-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -9667,7 +9697,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/FunctionTransformerTests.e2e.test.ts - CLI_REGION: ap-northeast-1 + CLI_REGION: ap-southeast-1 HttpTransformer-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -9697,7 +9727,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/HttpTransformer.e2e.test.ts - CLI_REGION: ap-southeast-1 + CLI_REGION: ap-southeast-2 IndexTransformer-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -9727,7 +9757,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/IndexTransformer.e2e.test.ts - CLI_REGION: ap-southeast-2 + CLI_REGION: us-east-2 KeyTransformer-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -9757,7 +9787,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/KeyTransformer.e2e.test.ts - CLI_REGION: us-east-2 + CLI_REGION: us-west-2 KeyTransformerLocal-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -9787,7 +9817,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/KeyTransformerLocal.e2e.test.ts - CLI_REGION: us-west-2 + CLI_REGION: eu-west-2 KeyWithAuth-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -9817,7 +9847,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/KeyWithAuth.e2e.test.ts - CLI_REGION: eu-west-2 + CLI_REGION: eu-central-1 ModelAuthTransformer-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -9847,7 +9877,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/ModelAuthTransformer.e2e.test.ts - CLI_REGION: eu-central-1 + CLI_REGION: ap-northeast-1 ModelConnectionTransformer-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -9877,7 +9907,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/ModelConnectionTransformer.e2e.test.ts - CLI_REGION: ap-northeast-1 + CLI_REGION: ap-southeast-1 ModelConnectionWithKeyTransformer-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -9907,7 +9937,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/ModelConnectionWithKeyTransformer.e2e.test.ts - CLI_REGION: ap-southeast-1 + CLI_REGION: ap-southeast-2 ModelTransformer-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -9937,7 +9967,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/ModelTransformer.e2e.test.ts - CLI_REGION: ap-southeast-2 + CLI_REGION: us-east-2 MultiAuthModelAuthTransformer-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -9967,7 +9997,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/MultiAuthModelAuthTransformer.e2e.test.ts - CLI_REGION: us-east-2 + CLI_REGION: us-west-2 MutationCondition-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -9997,7 +10027,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/MutationCondition.e2e.test.ts - CLI_REGION: us-west-2 + CLI_REGION: eu-west-2 NestedStacksTest-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -10027,7 +10057,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/NestedStacksTest.e2e.test.ts - CLI_REGION: eu-west-2 + CLI_REGION: eu-central-1 NewConnectionTransformer-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -10057,7 +10087,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/NewConnectionTransformer.e2e.test.ts - CLI_REGION: eu-central-1 + CLI_REGION: ap-northeast-1 NewConnectionWithAuth-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -10087,7 +10117,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/NewConnectionWithAuth.e2e.test.ts - CLI_REGION: ap-northeast-1 + CLI_REGION: ap-southeast-1 NoneEnvFunctionTransformer-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -10117,7 +10147,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/NoneEnvFunctionTransformer.e2e.test.ts - CLI_REGION: ap-southeast-1 + CLI_REGION: ap-southeast-2 NonModelAuthFunction-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -10147,7 +10177,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/NonModelAuthFunction.e2e.test.ts - CLI_REGION: ap-southeast-2 + CLI_REGION: us-east-2 PerFieldAuthTests-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -10177,7 +10207,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/PerFieldAuthTests.e2e.test.ts - CLI_REGION: us-east-2 + CLI_REGION: us-west-2 PredictionsTransformerTests-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -10207,7 +10237,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/PredictionsTransformerTests.e2e.test.ts - CLI_REGION: us-west-2 + CLI_REGION: eu-west-2 RelationalTransformers-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -10237,7 +10267,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/RelationalTransformers.e2e.test.ts - CLI_REGION: eu-west-2 + CLI_REGION: eu-central-1 SearchableModelTransformer-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -10267,7 +10297,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/SearchableModelTransformer.e2e.test.ts - CLI_REGION: eu-central-1 + CLI_REGION: ap-northeast-1 SearchableModelTransformerV2-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -10297,7 +10327,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/SearchableModelTransformerV2.e2e.test.ts - CLI_REGION: ap-northeast-1 + CLI_REGION: ap-southeast-1 SearchableWithAuthTests-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -10327,7 +10357,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/SearchableWithAuthTests.e2e.test.ts - CLI_REGION: ap-southeast-1 + CLI_REGION: ap-southeast-2 SubscriptionsWithAuthTest-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -10357,7 +10387,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/SubscriptionsWithAuthTest.e2e.test.ts - CLI_REGION: ap-southeast-2 + CLI_REGION: us-east-2 TestComplexStackMappingsLocal-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -10387,7 +10417,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/TestComplexStackMappingsLocal.e2e.test.ts - CLI_REGION: us-east-2 + CLI_REGION: us-west-2 VersionedModelTransformer-e2e-graphql_e2e_tests: working_directory: ~/repo parameters: @@ -10417,7 +10447,7 @@ jobs: AMPLIFY_DIR: /home/circleci/repo/packages/amplify-cli/bin AMPLIFY_PATH: /home/circleci/repo/packages/amplify-cli/bin/amplify TEST_SUITE: src/__tests__/VersionedModelTransformer.e2e.test.ts - CLI_REGION: us-west-2 + CLI_REGION: eu-west-2 migration_tests-auth-deployment-migration-auth-deployment-secrets-amplify_migration_tests_v4: working_directory: ~/repo parameters: @@ -11792,6 +11822,11 @@ workflows: - schema-auth-11-amplify_e2e_tests_pkg - schema-connection-amplify_e2e_tests_pkg - api_5-amplify_e2e_tests_pkg + - AuthV2Transformer-e2e-graphql_e2e_tests + - IndexTransformer-e2e-graphql_e2e_tests + - ModelTransformer-e2e-graphql_e2e_tests + - NonModelAuthFunction-e2e-graphql_e2e_tests + - SubscriptionsWithAuthTest-e2e-graphql_e2e_tests - ConnectionsWithAuthTests-e2e-graphql_e2e_tests - KeyTransformer-e2e-graphql_e2e_tests - MultiAuthModelAuthTransformer-e2e-graphql_e2e_tests @@ -11818,10 +11853,6 @@ workflows: - ModelConnectionWithKeyTransformer-e2e-graphql_e2e_tests - NoneEnvFunctionTransformer-e2e-graphql_e2e_tests - SearchableWithAuthTests-e2e-graphql_e2e_tests - - IndexTransformer-e2e-graphql_e2e_tests - - ModelTransformer-e2e-graphql_e2e_tests - - NonModelAuthFunction-e2e-graphql_e2e_tests - - SubscriptionsWithAuthTest-e2e-graphql_e2e_tests - >- migration_tests-auth-deployment-migration-auth-deployment-secrets-amplify_migration_tests_v4 - update_tests-function_migration_update-amplify_migration_tests_v4 @@ -15437,7 +15468,7 @@ workflows: parameters: os: - linux - - ConnectionsWithAuthTests-e2e-graphql_e2e_tests: + - AuthV2Transformer-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15453,7 +15484,7 @@ workflows: parameters: os: - linux - - KeyTransformer-e2e-graphql_e2e_tests: + - IndexTransformer-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15469,7 +15500,7 @@ workflows: parameters: os: - linux - - MultiAuthModelAuthTransformer-e2e-graphql_e2e_tests: + - ModelTransformer-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15485,7 +15516,7 @@ workflows: parameters: os: - linux - - PerFieldAuthTests-e2e-graphql_e2e_tests: + - NonModelAuthFunction-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15501,7 +15532,7 @@ workflows: parameters: os: - linux - - TestComplexStackMappingsLocal-e2e-graphql_e2e_tests: + - SubscriptionsWithAuthTest-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15517,7 +15548,7 @@ workflows: parameters: os: - linux - - CustomRoots-e2e-graphql_e2e_tests: + - ConnectionsWithAuthTests-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15533,7 +15564,7 @@ workflows: parameters: os: - linux - - KeyTransformerLocal-e2e-graphql_e2e_tests: + - KeyTransformer-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15549,7 +15580,7 @@ workflows: parameters: os: - linux - - MutationCondition-e2e-graphql_e2e_tests: + - MultiAuthModelAuthTransformer-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15565,7 +15596,7 @@ workflows: parameters: os: - linux - - PredictionsTransformerTests-e2e-graphql_e2e_tests: + - PerFieldAuthTests-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15581,7 +15612,7 @@ workflows: parameters: os: - linux - - VersionedModelTransformer-e2e-graphql_e2e_tests: + - TestComplexStackMappingsLocal-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15597,7 +15628,7 @@ workflows: parameters: os: - linux - - DefaultValueTransformer-e2e-graphql_e2e_tests: + - CustomRoots-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15613,7 +15644,7 @@ workflows: parameters: os: - linux - - KeyWithAuth-e2e-graphql_e2e_tests: + - KeyTransformerLocal-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15629,7 +15660,7 @@ workflows: parameters: os: - linux - - NestedStacksTest-e2e-graphql_e2e_tests: + - MutationCondition-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15645,7 +15676,7 @@ workflows: parameters: os: - linux - - RelationalTransformers-e2e-graphql_e2e_tests: + - PredictionsTransformerTests-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15661,7 +15692,7 @@ workflows: parameters: os: - linux - - DynamoDBModelTransformer-e2e-graphql_e2e_tests: + - VersionedModelTransformer-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15677,7 +15708,7 @@ workflows: parameters: os: - linux - - ModelAuthTransformer-e2e-graphql_e2e_tests: + - DefaultValueTransformer-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15693,7 +15724,7 @@ workflows: parameters: os: - linux - - NewConnectionTransformer-e2e-graphql_e2e_tests: + - KeyWithAuth-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15709,7 +15740,7 @@ workflows: parameters: os: - linux - - SearchableModelTransformer-e2e-graphql_e2e_tests: + - NestedStacksTest-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15725,7 +15756,7 @@ workflows: parameters: os: - linux - - FunctionTransformerTests-e2e-graphql_e2e_tests: + - RelationalTransformers-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15741,7 +15772,7 @@ workflows: parameters: os: - linux - - ModelConnectionTransformer-e2e-graphql_e2e_tests: + - DynamoDBModelTransformer-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15757,7 +15788,7 @@ workflows: parameters: os: - linux - - NewConnectionWithAuth-e2e-graphql_e2e_tests: + - ModelAuthTransformer-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15773,7 +15804,7 @@ workflows: parameters: os: - linux - - SearchableModelTransformerV2-e2e-graphql_e2e_tests: + - NewConnectionTransformer-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15789,7 +15820,7 @@ workflows: parameters: os: - linux - - HttpTransformer-e2e-graphql_e2e_tests: + - SearchableModelTransformer-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15805,7 +15836,7 @@ workflows: parameters: os: - linux - - ModelConnectionWithKeyTransformer-e2e-graphql_e2e_tests: + - FunctionTransformerTests-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15821,7 +15852,7 @@ workflows: parameters: os: - linux - - NoneEnvFunctionTransformer-e2e-graphql_e2e_tests: + - ModelConnectionTransformer-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15837,7 +15868,7 @@ workflows: parameters: os: - linux - - SearchableWithAuthTests-e2e-graphql_e2e_tests: + - NewConnectionWithAuth-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15853,7 +15884,7 @@ workflows: parameters: os: - linux - - IndexTransformer-e2e-graphql_e2e_tests: + - SearchableModelTransformerV2-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15869,7 +15900,7 @@ workflows: parameters: os: - linux - - ModelTransformer-e2e-graphql_e2e_tests: + - HttpTransformer-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15885,7 +15916,7 @@ workflows: parameters: os: - linux - - NonModelAuthFunction-e2e-graphql_e2e_tests: + - ModelConnectionWithKeyTransformer-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context @@ -15901,7 +15932,23 @@ workflows: parameters: os: - linux - - SubscriptionsWithAuthTest-e2e-graphql_e2e_tests: + - NoneEnvFunctionTransformer-e2e-graphql_e2e_tests: + context: + - amplify-ecr-image-pull + - e2e-test-context + filters: + branches: + only: + - master + - /tagged-release\/.*/ + - /run-e2e\/.*/ + requires: + - build + matrix: + parameters: + os: + - linux + - SearchableWithAuthTests-e2e-graphql_e2e_tests: context: - amplify-ecr-image-pull - e2e-test-context diff --git a/packages/amplify-category-api/package.json b/packages/amplify-category-api/package.json index e5fe23c82de..fa76cb59454 100644 --- a/packages/amplify-category-api/package.json +++ b/packages/amplify-category-api/package.json @@ -65,6 +65,8 @@ "@octokit/rest": "^18.0.9", "amplify-cli-core": "1.31.1", "amplify-headless-interface": "1.10.0", + "amplify-prompts": "1.2.0", + "amplify-provider-awscloudformation": "4.61.1", "amplify-util-headless-input": "1.5.4", "chalk": "^4.1.1", "constructs": "^3.3.125", diff --git a/packages/amplify-category-api/resources/awscloudformation/graphql-schemas/blank-schema.graphql b/packages/amplify-category-api/resources/awscloudformation/graphql-schemas/blank-schema.graphql new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/amplify-category-api/resources/awscloudformation/graphql-schemas/many-relationship-schema-v2.graphql b/packages/amplify-category-api/resources/awscloudformation/graphql-schemas/many-relationship-schema-v2.graphql new file mode 100644 index 00000000000..2619b187297 --- /dev/null +++ b/packages/amplify-category-api/resources/awscloudformation/graphql-schemas/many-relationship-schema-v2.graphql @@ -0,0 +1,18 @@ +type Blog @model { + id: ID! + name: String! + posts: [Post] @hasMany +} + +type Post @model { + id: ID! + title: String! + blog: Blog @belongsTo + comments: [Comment] @hasMany +} + +type Comment @model { + id: ID! + post: Post @belongsTo + content: String! +} diff --git a/packages/amplify-category-api/resources/awscloudformation/graphql-schemas/single-object-auth-schema-v2.graphql b/packages/amplify-category-api/resources/awscloudformation/graphql-schemas/single-object-auth-schema-v2.graphql new file mode 100644 index 00000000000..0faf0997d4a --- /dev/null +++ b/packages/amplify-category-api/resources/awscloudformation/graphql-schemas/single-object-auth-schema-v2.graphql @@ -0,0 +1,15 @@ +type Task + @model + @auth(rules: [ + { allow: groups, groups: ["Managers"], operations: [create, update, read, delete] } + { allow: groups, groups: ["Employees"], operations: [read] } ]) { + id: ID! + title: String! + description: String + status: String +} + +type PrivateNote @model @auth(rules: [{ allow: owner }]) { + id: ID! + content: String! +} diff --git a/packages/amplify-category-api/resources/awscloudformation/graphql-schemas/single-object-schema-v2.graphql b/packages/amplify-category-api/resources/awscloudformation/graphql-schemas/single-object-schema-v2.graphql new file mode 100644 index 00000000000..74b097ceae9 --- /dev/null +++ b/packages/amplify-category-api/resources/awscloudformation/graphql-schemas/single-object-schema-v2.graphql @@ -0,0 +1,5 @@ +type Todo @model { + id: ID! + name: String! + description: String +} diff --git a/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/__snapshots__/cfn-api-artifact-handler.test.ts.snap b/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/__snapshots__/cfn-api-artifact-handler.test.ts.snap index 36f39965a9b..3b9aa6928f1 100644 --- a/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/__snapshots__/cfn-api-artifact-handler.test.ts.snap +++ b/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/__snapshots__/cfn-api-artifact-handler.test.ts.snap @@ -18,6 +18,7 @@ Object { }, Object { "apiKeyConfig": Object { + "apiKeyExpirationDate": undefined, "apiKeyExpirationDays": undefined, "description": undefined, }, diff --git a/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/cfn-api-artifact-handler.test.ts b/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/cfn-api-artifact-handler.test.ts index 28e2aec71d3..e8dfa51770a 100644 --- a/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/cfn-api-artifact-handler.test.ts +++ b/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/cfn-api-artifact-handler.test.ts @@ -30,7 +30,7 @@ jest.mock('../../../provider-utils/awscloudformation/utils/amplify-meta-utils', jest.mock('amplify-cli-core'); -const fs_mock = (fs as unknown) as jest.Mocked; +const fs_mock = fs as unknown as jest.Mocked; const writeTransformerConfiguration_mock = writeTransformerConfiguration as jest.MockedFunction; const getAppSyncResourceName_mock = getAppSyncResourceName as jest.MockedFunction; const getAppSyncAuthConfig_mock = getAppSyncAuthConfig as jest.MockedFunction; diff --git a/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/prompt-to-add-api-key.test.ts b/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/prompt-to-add-api-key.test.ts new file mode 100644 index 00000000000..871b8c8f1ea --- /dev/null +++ b/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/prompt-to-add-api-key.test.ts @@ -0,0 +1,44 @@ +import { $TSContext } from 'amplify-cli-core'; +import * as prompts from 'amplify-prompts'; +import { promptToAddApiKey } from '../../../provider-utils/awscloudformation/prompt-to-add-api-key'; +import * as walkthrough from '../../../provider-utils/awscloudformation/service-walkthroughs/appSync-walkthrough'; +import * as cfnApiArtifactHandler from '../../../provider-utils/awscloudformation/cfn-api-artifact-handler'; + +jest.mock('../../../provider-utils/awscloudformation/service-walkthroughs/appSync-walkthrough', () => ({ + askApiKeyQuestions: jest.fn(), +})); + +jest.mock('../../../provider-utils/awscloudformation/cfn-api-artifact-handler', () => ({ + getCfnApiArtifactHandler: jest.fn(() => { + return { updateArtifacts: jest.fn() }; + }), +})); + +jest.mock('amplify-prompts', () => ({ + prompter: { + confirmContinue: jest.fn().mockImplementation(() => true), + }, +})); + +describe('prompt to add Api Key', () => { + it('runs through expected user flow: print info, update files', async () => { + const envName = 'envone'; + const ctx = { + amplify: { + getEnvInfo() { + return { envName }; + }, + }, + } as unknown as $TSContext; + + jest.spyOn(prompts.prompter, 'confirmContinue'); + jest.spyOn(walkthrough, 'askApiKeyQuestions'); + jest.spyOn(cfnApiArtifactHandler, 'getCfnApiArtifactHandler'); + + await promptToAddApiKey(ctx); + + expect(prompts.prompter.confirmContinue).toHaveBeenCalledWith('Would you like to create an API Key?'); + expect(walkthrough.askApiKeyQuestions).toHaveBeenCalledTimes(1); + expect(cfnApiArtifactHandler.getCfnApiArtifactHandler).toHaveBeenCalledTimes(1); + }); +}); diff --git a/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/service-walkthroughs/appSync-walkthrough.test.ts b/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/service-walkthroughs/appSync-walkthrough.test.ts index a664b0b4698..1d7ed55cdfd 100644 --- a/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/service-walkthroughs/appSync-walkthrough.test.ts +++ b/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/service-walkthroughs/appSync-walkthrough.test.ts @@ -3,7 +3,7 @@ import { askAdditionalAuthQuestions, } from '../../../../provider-utils/awscloudformation/service-walkthroughs/appSync-walkthrough'; import { authConfigHasApiKey, getAppSyncAuthConfig } from '../../../../provider-utils/awscloudformation/utils/amplify-meta-utils'; -import { FeatureFlags, CLIEnvironmentProvider, FeatureFlagRegistration } from 'amplify-cli-core'; +import { FeatureFlags } from 'amplify-cli-core'; jest.mock('../../../../provider-utils/awscloudformation/utils/amplify-meta-utils', () => ({ getAppSyncAuthConfig: jest.fn(), authConfigHasApiKey: jest.fn(), diff --git a/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/utils/__snapshots__/auth-config-to-app-sync-auth-type-bi-di-mapper.test.ts.snap b/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/utils/__snapshots__/auth-config-to-app-sync-auth-type-bi-di-mapper.test.ts.snap index 73049e4ca95..3c18c0fa241 100644 --- a/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/utils/__snapshots__/auth-config-to-app-sync-auth-type-bi-di-mapper.test.ts.snap +++ b/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/utils/__snapshots__/auth-config-to-app-sync-auth-type-bi-di-mapper.test.ts.snap @@ -12,6 +12,7 @@ Object { exports[`AppSyncAuthType to authConfig maps API_KEY correctly 1`] = ` Object { "apiKeyConfig": Object { + "apiKeyExpirationDate": undefined, "apiKeyExpirationDays": 120, "description": undefined, }, @@ -47,6 +48,7 @@ Object { exports[`authConfig to AppSyncAuthType maps API_KEY auth correctly 1`] = ` Object { + "apiKeyExpirationDate": undefined, "expirationTime": 120, "keyDescription": "api key description", "mode": "API_KEY", diff --git a/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/utils/global-sandbox-mode.test.ts b/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/utils/global-sandbox-mode.test.ts new file mode 100644 index 00000000000..a895da7f667 --- /dev/null +++ b/packages/amplify-category-api/src/__tests__/provider-utils/awscloudformation/utils/global-sandbox-mode.test.ts @@ -0,0 +1,21 @@ +import { defineGlobalSandboxMode } from '../../../../provider-utils/awscloudformation/utils/global-sandbox-mode'; +import { $TSContext } from 'amplify-cli-core'; + +describe('global sandbox mode GraphQL directive', () => { + it('returns AMPLIFY_DIRECTIVE type with code comment, directive, and env name', () => { + const envName = 'envone'; + const ctx = <$TSContext>{ + amplify: { + getEnvInfo() { + return { envName }; + }, + }, + }; + + expect(defineGlobalSandboxMode(ctx)) + .toBe(`# This allows public create, read, update, and delete access for a limited time to all models via API Key. +# To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql-transformer/auth +type AMPLIFY_GLOBAL @allow_public_data_access_with_api_key(in: \"${envName}\") # FOR TESTING ONLY!\n +`); + }); +}); diff --git a/packages/amplify-category-api/src/index.ts b/packages/amplify-category-api/src/index.ts index af7f1625011..3593ba6b977 100644 --- a/packages/amplify-category-api/src/index.ts +++ b/packages/amplify-category-api/src/index.ts @@ -3,6 +3,9 @@ import fs from 'fs-extra'; import path from 'path'; import { run } from './commands/api/console'; import { getCfnApiArtifactHandler } from './provider-utils/awscloudformation/cfn-api-artifact-handler'; +import { askAuthQuestions } from './provider-utils/awscloudformation/service-walkthroughs/appSync-walkthrough'; +import { getAppSyncResourceName, getAppSyncAuthConfig } from './provider-utils/awscloudformation//utils/amplify-meta-utils'; +import { authConfigToAppSyncAuthType } from './provider-utils/awscloudformation/utils/auth-config-to-app-sync-auth-type-bi-di-mapper'; export { NETWORK_STACK_LOGICAL_ID } from './category-constants'; export { DEPLOYMENT_MECHANISM } from './provider-utils/awscloudformation/base-api-stack'; @@ -15,6 +18,7 @@ export { processDockerConfig, } from './provider-utils/awscloudformation/utils/containers-artifacts'; export { getContainers } from './provider-utils/awscloudformation/docker-compose'; +export { promptToAddApiKey } from './provider-utils/awscloudformation/prompt-to-add-api-key'; const category = 'api'; @@ -217,3 +221,32 @@ export async function handleAmplifyEvent(context, args) { context.print.info(`${category} handleAmplifyEvent to be implemented`); context.print.info(`Received event args ${args}`); } + +export async function addGraphQLAuthorizationMode(context, args) { + const { authType, printLeadText, authSettings } = args; + const apiName = getAppSyncResourceName(context.amplify.getProjectMeta()); + if (!apiName) { + return; + } + + const authConfig = getAppSyncAuthConfig(context.amplify.getProjectMeta()); + const addAuthConfig = await askAuthQuestions(authType, context, printLeadText, authSettings); + authConfig.additionalAuthenticationProviders.push(addAuthConfig); + await context.amplify.updateamplifyMetaAfterResourceUpdate(category, apiName, 'output', { authConfig }); + await context.amplify.updateBackendConfigAfterResourceUpdate(category, apiName, 'output', { authConfig }); + + await getCfnApiArtifactHandler(context).updateArtifacts( + { + version: 1, + serviceModification: { + serviceName: 'AppSync', + additionalAuthTypes: authConfig.additionalAuthenticationProviders.map(authConfigToAppSyncAuthType), + }, + }, + { + skipCompile: false, + }, + ); + + return addAuthConfig; +} \ No newline at end of file diff --git a/packages/amplify-category-api/src/provider-utils/api-artifact-handler.ts b/packages/amplify-category-api/src/provider-utils/api-artifact-handler.ts index a3b7de27c51..7dbab41d779 100644 --- a/packages/amplify-category-api/src/provider-utils/api-artifact-handler.ts +++ b/packages/amplify-category-api/src/provider-utils/api-artifact-handler.ts @@ -1,6 +1,10 @@ import { AddApiRequest, UpdateApiRequest } from 'amplify-headless-interface'; +export interface ApiArtifactHandlerOptions { + skipCompile?: boolean; +} + export interface ApiArtifactHandler { createArtifacts(request: AddApiRequest): Promise; - updateArtifacts(request: UpdateApiRequest): Promise; + updateArtifacts(request: UpdateApiRequest, opts?: ApiArtifactHandlerOptions): Promise; } diff --git a/packages/amplify-category-api/src/provider-utils/awscloudformation/cfn-api-artifact-handler.ts b/packages/amplify-category-api/src/provider-utils/awscloudformation/cfn-api-artifact-handler.ts index cc421715b5d..f06fc279414 100644 --- a/packages/amplify-category-api/src/provider-utils/awscloudformation/cfn-api-artifact-handler.ts +++ b/packages/amplify-category-api/src/provider-utils/awscloudformation/cfn-api-artifact-handler.ts @@ -12,7 +12,7 @@ import _ from 'lodash'; import * as path from 'path'; import uuid from 'uuid'; import { category } from '../../category-constants'; -import { ApiArtifactHandler } from '../api-artifact-handler'; +import { ApiArtifactHandler, ApiArtifactHandlerOptions } from '../api-artifact-handler'; import { cfnParametersFilename, gqlSchemaFilename, provider, rootAssetDir } from './aws-constants'; import { authConfigHasApiKey, checkIfAuthExists, getAppSyncAuthConfig, getAppSyncResourceName } from './utils/amplify-meta-utils'; import { appSyncAuthTypeToAuthConfig } from './utils/auth-config-to-app-sync-auth-type-bi-di-mapper'; @@ -96,7 +96,7 @@ class CfnApiArtifactHandler implements ApiArtifactHandler { // TODO once the AddApiRequest contains multiple services this class should depend on an ApiArtifactHandler // for each service and delegate to the correct one - updateArtifacts = async (request: UpdateApiRequest): Promise => { + updateArtifacts = async (request: UpdateApiRequest, opts?: ApiArtifactHandlerOptions): Promise => { const updates = request.serviceModification; const apiName = getAppSyncResourceName(this.context.amplify.getProjectMeta()); if (!apiName) { @@ -118,11 +118,14 @@ class CfnApiArtifactHandler implements ApiArtifactHandler { if (updates.additionalAuthTypes) { authConfig.additionalAuthenticationProviders = updates.additionalAuthTypes.map(appSyncAuthTypeToAuthConfig); } - await this.context.amplify.executeProviderUtils(this.context, 'awscloudformation', 'compileSchema', { - resourceDir, - parameters: this.getCfnParameters(apiName, authConfig, resourceDir), - authConfig, - }); + + if (!opts?.skipCompile) { + await this.context.amplify.executeProviderUtils(this.context, 'awscloudformation', 'compileSchema', { + resourceDir, + parameters: this.getCfnParameters(apiName, authConfig, resourceDir), + authConfig, + }); + } this.context.amplify.updateamplifyMetaAfterResourceUpdate(category, apiName, 'output', { authConfig }); this.context.amplify.updateBackendConfigAfterResourceUpdate(category, apiName, 'output', { authConfig }); diff --git a/packages/amplify-category-api/src/provider-utils/awscloudformation/prompt-to-add-api-key.ts b/packages/amplify-category-api/src/provider-utils/awscloudformation/prompt-to-add-api-key.ts new file mode 100644 index 00000000000..4e3a92b5ea4 --- /dev/null +++ b/packages/amplify-category-api/src/provider-utils/awscloudformation/prompt-to-add-api-key.ts @@ -0,0 +1,27 @@ +import { $TSContext } from 'amplify-cli-core'; +import { askApiKeyQuestions } from './service-walkthroughs/appSync-walkthrough'; +import { authConfigToAppSyncAuthType } from './utils/auth-config-to-app-sync-auth-type-bi-di-mapper'; +import { getCfnApiArtifactHandler } from './cfn-api-artifact-handler'; +import { prompter } from 'amplify-prompts'; + +export async function promptToAddApiKey(context: $TSContext): Promise { + if (await prompter.confirmContinue('Would you like to create an API Key?')) { + const apiKeyConfig = await askApiKeyQuestions(); + const authConfig = [apiKeyConfig]; + + await getCfnApiArtifactHandler(context).updateArtifacts( + { + version: 1, + serviceModification: { + serviceName: 'AppSync', + additionalAuthTypes: authConfig.map(authConfigToAppSyncAuthType), + }, + }, + { + skipCompile: true, + }, + ); + + return apiKeyConfig; + } +} diff --git a/packages/amplify-category-api/src/provider-utils/awscloudformation/service-walkthroughs/appSync-walkthrough.ts b/packages/amplify-category-api/src/provider-utils/awscloudformation/service-walkthroughs/appSync-walkthrough.ts index f2878dbb503..c8561d30e01 100644 --- a/packages/amplify-category-api/src/provider-utils/awscloudformation/service-walkthroughs/appSync-walkthrough.ts +++ b/packages/amplify-category-api/src/provider-utils/awscloudformation/service-walkthroughs/appSync-walkthrough.ts @@ -4,12 +4,13 @@ import inquirer from 'inquirer'; import fs from 'fs-extra'; import path from 'path'; import { rootAssetDir } from '../aws-constants'; -import { collectDirectivesByTypeNames, readProjectConfiguration, ConflictHandlerType } from 'graphql-transformer-core'; +import { collectDirectivesByTypeNames, readProjectConfiguration } from 'graphql-transformer-core'; import { category } from '../../../category-constants'; import { UpdateApiRequest } from '../../../../../amplify-headless-interface/lib/interface/api/update'; import { authConfigToAppSyncAuthType } from '../utils/auth-config-to-app-sync-auth-type-bi-di-mapper'; import { resolverConfigToConflictResolution } from '../utils/resolver-config-to-conflict-resolution-bi-di-mapper'; import _ from 'lodash'; +import chalk from 'chalk'; import { getAppSyncAuthConfig, checkIfAuthExists, authConfigHasApiKey } from '../utils/amplify-meta-utils'; import { ResourceAlreadyExistsError, @@ -21,6 +22,8 @@ import { $TSContext, open, } from 'amplify-cli-core'; +import { Duration, Expiration } from '@aws-cdk/core'; +import { defineGlobalSandboxMode } from '../utils/global-sandbox-mode'; const serviceName = 'AppSync'; const elasticContainerServiceName = 'ElasticContainer'; @@ -46,6 +49,63 @@ const authProviderChoices = [ }, ]; +const conflictResolutionHanlderChoices = [ + { + name: 'Auto Merge', + value: 'AUTOMERGE', + }, + { + name: 'Optimistic Concurrency', + value: 'OPTIMISTIC_CONCURRENCY', + }, + { + name: 'Custom Lambda', + value: 'LAMBDA', + }, + { + name: 'Learn More', + value: 'Learn More', + }, +]; + +const schemaTemplatesV1 = [ + { + name: 'Single object with fields (e.g., “Todo” with ID, name, description)', + value: 'single-object-schema.graphql', + }, + { + name: 'One-to-many relationship (e.g., “Blogs” with “Posts” and “Comments”)', + value: 'many-relationship-schema.graphql', + }, + { + name: 'Objects with fine-grained access control (e.g., a project management app with owner-based authorization)', + value: 'single-object-auth-schema.graphql', + }, + { + name: 'Blank Schema', + value: 'blank-schema.graphql', + }, +]; + +const schemaTemplatesV2 = [ + { + name: 'Single object with fields (e.g., “Todo” with ID, name, description)', + value: 'single-object-schema-v2.graphql', + }, + { + name: 'One-to-many relationship (e.g., “Blogs” with “Posts” and “Comments”)', + value: 'many-relationship-schema-v2.graphql', + }, + { + name: 'Objects with fine-grained access control (e.g., a project management app with owner-based authorization)', + value: 'single-object-auth-schema-v2.graphql', + }, + { + name: 'Blank Schema', + value: 'blank-schema.graphql', + }, +]; + export const openConsole = async (context: $TSContext) => { const amplifyMeta = stateManager.getMeta(); const categoryAmplifyMeta = amplifyMeta[category]; @@ -136,90 +196,129 @@ export const openConsole = async (context: $TSContext) => { } }; -export const serviceWalkthrough = async (context: $TSContext, defaultValuesFilename, serviceMetadata) => { - const resourceName = resourceAlreadyExists(context); +const serviceApiInputWalkthrough = async (context: $TSContext, defaultValuesFilename, serviceMetadata) => { + let continuePrompt = false; let authConfig; let defaultAuthType; let resolverConfig; - - if (resourceName) { - const errMessage = - 'You already have an AppSync API in your project. Use the "amplify update api" command to update your existing AppSync API.'; - context.print.warning(errMessage); - await context.usageData.emitError(new ResourceAlreadyExistsError(errMessage)); - exitOnNextTick(0); - } - const { amplify } = context; const { inputs } = serviceMetadata; const defaultValuesSrc = `${__dirname}/../default-values/${defaultValuesFilename}`; const { getAllDefaults } = require(defaultValuesSrc); const allDefaultValues = getAllDefaults(amplify.getProjectDetails()); - const resourceQuestions = [ - { - type: inputs[1].type, - name: inputs[1].key, - message: inputs[1].question, - validate: amplify.inputValidation(inputs[1]), - default: () => { - const defaultValue = allDefaultValues[inputs[1].key]; - return defaultValue; + let resourceAnswers = {}; + resourceAnswers[inputs[1].key] = allDefaultValues[inputs[1].key]; + resourceAnswers[inputs[0].key] = resourceAnswers[inputs[1].key]; + + // + // Default authConfig - API Key (expires in 7 days) + // + authConfig = { + defaultAuthentication: { + apiKeyConfig: { + apiKeyExpirationDays: 7, }, + authenticationType: 'API_KEY', }, - ]; + additionalAuthenticationProviders: [], + }; - // API name question + // + // Repeat prompt until user selects Continue + // + while (!continuePrompt) { + const getAuthModeChoice = async () => { + if (authConfig.defaultAuthentication.authenticationType === 'API_KEY') { + return `${ + authProviderChoices.find(choice => choice.value === authConfig.defaultAuthentication.authenticationType).name + } (default, expiration time: ${authConfig.defaultAuthentication.apiKeyConfig.apiKeyExpirationDays} days from now)`; + } + return `${authProviderChoices.find(choice => choice.value === authConfig.defaultAuthentication.authenticationType).name} (default)`; + }; - const resourceAnswers = await inquirer.prompt(resourceQuestions); - resourceAnswers[inputs[0].key] = resourceAnswers[inputs[1].key]; + const getAdditionalAuthModeChoices = async () => { + let additionalAuthModesText = ''; + authConfig.additionalAuthenticationProviders.map(async authMode => { + additionalAuthModesText += `, ${authProviderChoices.find(choice => choice.value === authMode.authenticationType).name}`; + }); + return additionalAuthModesText; + }; + + const basicInfoQuestionChoices = []; - // Ask additonal questions + basicInfoQuestionChoices.push({ + name: chalk`{bold Name:} ${resourceAnswers[inputs[1].key]}`, + value: 'API_NAME', + }); - ({ authConfig, defaultAuthType } = await askDefaultAuthQuestion(context)); - ({ authConfig, resolverConfig } = await askAdditionalQuestions(context, authConfig, defaultAuthType)); + basicInfoQuestionChoices.push({ + name: chalk`{bold Authorization modes:} ${await getAuthModeChoice()}${await getAdditionalAuthModeChoices()}`, + value: 'API_AUTH_MODE', + }); - // Ask schema file question + basicInfoQuestionChoices.push({ + name: chalk`{bold Conflict detection (required for DataStore):} ${resolverConfig?.project ? 'Enabled' : 'Disabled'}`, + value: 'CONFLICT_DETECTION', + }); - const schemaFileQuestion = { - type: inputs[2].type, - name: inputs[2].key, - message: inputs[2].question, - validate: amplify.inputValidation(inputs[2]), - default: () => { - const defaultValue = allDefaultValues[inputs[2].key]; - return defaultValue; - }, - }; + if (resolverConfig?.project) { + basicInfoQuestionChoices.push({ + name: chalk`{bold Conflict resolution strategy:} ${ + conflictResolutionHanlderChoices.find(x => x.value === resolverConfig.project.ConflictHandler).name + }`, + value: 'CONFLICT_STRATEGY', + }); + } - const schemaFileAnswer = await inquirer.prompt(schemaFileQuestion); + basicInfoQuestionChoices.push({ + name: 'Continue', + value: 'CONTINUE', + }); - let schemaContent = ''; - let askToEdit = true; - if (schemaFileAnswer[inputs[2].key]) { - // User has an annotated schema file - const filePathQuestion = { - type: inputs[3].type, - name: inputs[3].key, - message: inputs[3].question, - validate: amplify.inputValidation(inputs[3]), - }; - const { schemaFilePath } = await inquirer.prompt(filePathQuestion); - schemaContent = fs.readFileSync(schemaFilePath, 'utf8'); - askToEdit = false; - } else { - // Schema template selection - const templateSelectionQuestion = { - type: inputs[4].type, - name: inputs[4].key, - message: inputs[4].question, - choices: inputs[4].options.filter(templateSchemaFilter(authConfig)), - validate: amplify.inputValidation(inputs[4]), + const basicInfoQuestion = { + type: 'list', + name: 'basicApiSettings', + message: 'Here is the GraphQL API that we will create. Select a setting to edit or continue', + default: 'CONTINUE', + choices: basicInfoQuestionChoices, }; - const { templateSelection } = await inquirer.prompt(templateSelectionQuestion); - const schemaFilePath = path.join(graphqlSchemaDir, templateSelection); - schemaContent = fs.readFileSync(schemaFilePath, 'utf8'); + let { basicApiSettings } = await inquirer.prompt([basicInfoQuestion]); + + switch (basicApiSettings) { + case 'API_NAME': + const resourceQuestions = [ + { + type: inputs[1].type, + name: inputs[1].key, + message: inputs[1].question, + validate: amplify.inputValidation(inputs[1]), + default: () => { + const defaultValue = allDefaultValues[inputs[1].key]; + return defaultValue; + }, + }, + ]; + // API name question + resourceAnswers = await inquirer.prompt(resourceQuestions); + resourceAnswers[inputs[0].key] = resourceAnswers[inputs[1].key]; + break; + case 'API_AUTH_MODE': + // Ask additonal questions + ({ authConfig, defaultAuthType } = await askDefaultAuthQuestion(context)); + ({ authConfig } = await askAdditionalQuestions(context, authConfig, defaultAuthType)); + break; + case 'CONFLICT_DETECTION': + resolverConfig = await askResolverConflictQuestion(context, resolverConfig); + break; + case 'CONFLICT_STRATEGY': + resolverConfig = await askResolverConflictHandlerQuestion(context); + break; + case 'CONTINUE': + continuePrompt = true; + break; + } } return { @@ -227,8 +326,99 @@ export const serviceWalkthrough = async (context: $TSContext, defaultValuesFilen output: { authConfig, }, - noCfnFile: true, resolverConfig, + }; +}; + +const updateApiInputWalkthrough = async (context, project, resolverConfig, modelTypes) => { + let authConfig; + let defaultAuthType; + const updateChoices = [ + { + name: 'Authorization modes', + value: 'AUTH_MODE', + }, + ]; + // check if DataStore is enabled for the entire API + if (project.config && !_.isEmpty(project.config.ResolverConfig)) { + updateChoices.push({ + name: 'Conflict resolution strategy', + value: 'CONFLICT_STRATEGY', + }); + updateChoices.push({ + name: 'Disable conflict detection', + value: 'DISABLE_CONFLICT', + }); + } else { + updateChoices.push({ + name: 'Enable conflict detection (required for DataStore)', + value: 'ENABLE_CONFLICT', + }); + } + + const updateOptionQuestion = { + type: 'list', + name: 'updateOption', + message: 'Select a setting to edit', + choices: updateChoices, + }; + + const { updateOption } = await inquirer.prompt([updateOptionQuestion]); + + if (updateOption === 'ENABLE_CONFLICT') { + resolverConfig = await askResolverConflictHandlerQuestion(context, modelTypes); + } else if (updateOption === 'DISABLE_CONFLICT') { + resolverConfig = {}; + } else if (updateOption === 'AUTH_MODE') { + ({ authConfig, defaultAuthType } = await askDefaultAuthQuestion(context)); + authConfig = await askAdditionalAuthQuestions(context, authConfig, defaultAuthType); + } else if (updateOption === 'CONFLICT_STRATEGY') { + resolverConfig = await askResolverConflictHandlerQuestion(context, modelTypes); + } + + return { + authConfig, + resolverConfig, + }; +}; + +export const serviceWalkthrough = async (context: $TSContext, defaultValuesFilename, serviceMetadata) => { + const resourceName = resourceAlreadyExists(context); + const useExperimentalPipelineTransformer = FeatureFlags.getBoolean('graphQLTransformer.useExperimentalPipelinedTransformer'); + + if (resourceName) { + const errMessage = + 'You already have an AppSync API in your project. Use the "amplify update api" command to update your existing AppSync API.'; + context.print.warning(errMessage); + await context.usageData.emitError(new ResourceAlreadyExistsError(errMessage)); + exitOnNextTick(0); + } + + const { amplify } = context; + const { inputs } = serviceMetadata; + + const basicInfoAnswers = await serviceApiInputWalkthrough(context, defaultValuesFilename, serviceMetadata); + let schemaContent = ''; + let askToEdit = true; + + // Schema template selection + const schemaTemplateOptions = useExperimentalPipelineTransformer ? schemaTemplatesV2 : schemaTemplatesV1; + const templateSelectionQuestion = { + type: inputs[4].type, + name: inputs[4].key, + message: inputs[4].question, + choices: schemaTemplateOptions.filter(templateSchemaFilter(basicInfoAnswers.output.authConfig)), + validate: amplify.inputValidation(inputs[4]), + }; + + const { templateSelection } = await inquirer.prompt(templateSelectionQuestion); + const schemaFilePath = path.join(graphqlSchemaDir, templateSelection); + schemaContent += useExperimentalPipelineTransformer ? defineGlobalSandboxMode(context) : ''; + schemaContent += fs.readFileSync(schemaFilePath, 'utf8'); + + return { + ...basicInfoAnswers, + noCfnFile: true, schemaContent, askToEdit, }; @@ -238,13 +428,13 @@ export const updateWalkthrough = async (context): Promise => { const { allResources } = await context.amplify.getResourceStatus(); let resourceDir; let resourceName; + let resource; let authConfig; - let defaultAuthType; const resources = allResources.filter(resource => resource.service === 'AppSync'); // There can only be one appsync resource if (resources.length > 0) { - const resource = resources[0]; + resource = resources[0]; if (resource.providerPlugin !== providerName) { // TODO: Move message string to seperate file throw new Error( @@ -265,6 +455,8 @@ export const updateWalkthrough = async (context): Promise => { const project = await readProjectConfiguration(resourceDir); let resolverConfig = project.config.ResolverConfig; + await displayApiInformation(context, resource, project); + // Check for common errors const directiveMap = collectDirectivesByTypeNames(project.schema); let modelTypes = []; @@ -276,45 +468,8 @@ export const updateWalkthrough = async (context): Promise => { } }); } - const updateChoices = [ - { - name: 'Walkthrough all configurations', - value: 'all', - }, - { - name: 'Update auth settings', - value: 'authUpdate', - }, - ]; - // check if DataStore is enabled for the entire API - if (project.config && !_.isEmpty(project.config.ResolverConfig)) { - updateChoices.push({ name: 'Disable DataStore for entire API', value: 'disableDatastore' }); - } else { - updateChoices.push({ name: 'Enable DataStore for entire API', value: 'enableDatastore' }); - } - - const updateOptionQuestion = { - type: 'list', - name: 'updateOption', - message: 'Select from the options below', - choices: updateChoices, - }; - const { updateOption } = await inquirer.prompt([updateOptionQuestion]); - - if (updateOption === 'enableDatastore') { - resolverConfig = { - project: { ConflictHandler: ConflictHandlerType.AUTOMERGE, ConflictDetection: 'VERSION' }, - }; - } else if (updateOption === 'disableDatastore') { - resolverConfig = {}; - } else if (updateOption === 'authUpdate') { - ({ authConfig, defaultAuthType } = await askDefaultAuthQuestion(context)); - authConfig = await askAdditionalAuthQuestions(context, authConfig, defaultAuthType); - } else if (updateOption === 'all') { - ({ authConfig, defaultAuthType } = await askDefaultAuthQuestion(context)); - ({ authConfig, resolverConfig } = await askAdditionalQuestions(context, authConfig, defaultAuthType, modelTypes)); - } + ({ authConfig, resolverConfig } = await updateApiInputWalkthrough(context, project, resolverConfig, modelTypes)); return { version: 1, @@ -330,111 +485,130 @@ export const updateWalkthrough = async (context): Promise => { }; }; -async function askAdditionalQuestions(context, authConfig, defaultAuthType, modelTypes?) { - let resolverConfig; +async function displayApiInformation(context, resource, project) { + let authModes: string[] = []; + authModes.push( + `- Default: ${await displayAuthMode(context, resource, resource.output.authConfig.defaultAuthentication.authenticationType)}`, + ); + await resource.output.authConfig.additionalAuthenticationProviders.map(async authMode => { + authModes.push(`- ${await displayAuthMode(context, resource, authMode.authenticationType)}`); + }); - const advancedSettingsQuestion = { - type: 'list', - name: 'advancedSettings', - message: 'Do you want to configure advanced settings for the GraphQL API', - choices: [ - { - name: 'No, I am done.', - value: false, - }, - { - name: 'Yes, I want to make some additional changes.', - value: true, - }, - ], - }; + context.print.info(''); - const advancedSettingsAnswer = await inquirer.prompt([advancedSettingsQuestion]); + context.print.success('General information'); + context.print.info('- Name: '.concat(resource.resourceName)); + if (resource?.output?.GraphQLAPIEndpointOutput) { + context.print.info(`- API endpoint: ${resource?.output?.GraphQLAPIEndpointOutput}`); + } + context.print.info(''); - if (advancedSettingsAnswer.advancedSettings) { - authConfig = await askAdditionalAuthQuestions(context, authConfig, defaultAuthType); - resolverConfig = await askResolverConflictQuestion(context, modelTypes); + context.print.success('Authorization modes'); + authModes.forEach(authMode => context.print.info(authMode)); + context.print.info(''); + + context.print.success('Conflict detection (required for DataStore)'); + if (project.config && !_.isEmpty(project.config.ResolverConfig)) { + context.print.info( + `- Conflict resolution strategy: ${ + conflictResolutionHanlderChoices.find(choice => choice.value === project.config.ResolverConfig.project.ConflictHandler).name + }`, + ); + } else { + context.print.info('- Disabled'); } - return { authConfig, resolverConfig }; + context.print.info(''); } -async function askResolverConflictQuestion(context, modelTypes?) { - let resolverConfig: any = {}; +async function displayAuthMode(context, resource, authMode) { + if (authMode == 'API_KEY' && resource.output.GraphQLAPIKeyOutput) { + let { apiKeys } = await context.amplify.executeProviderUtils(context, 'awscloudformation', 'getAppSyncApiKeys', { + apiId: resource.output.GraphQLAPIIdOutput, + }); + let apiKeyExpires = apiKeys.find(key => key.id == resource.output.GraphQLAPIKeyOutput)?.expires; + if (!apiKeyExpires) { + return authProviderChoices.find(choice => choice.value === authMode).name; + } + let apiKeyExpiresDate = new Date(apiKeyExpires * 1000); + return `${authProviderChoices.find(choice => choice.value === authMode).name} expiring ${apiKeyExpiresDate}: ${ + resource.output.GraphQLAPIKeyOutput + }`; + } + return authProviderChoices.find(choice => choice.value === authMode).name; +} - if (await context.prompt.confirm('Enable conflict detection?')) { - const askConflictResolutionStrategy = async msg => { - let conflictResolutionStrategy; - - do { - const conflictResolutionQuestion: ListQuestion = { - type: 'list', - name: 'conflictResolutionStrategy', - message: msg, - default: 'AUTOMERGE', - choices: [ - { - name: 'Auto Merge', - value: 'AUTOMERGE', - }, - { - name: 'Optimistic Concurrency', - value: 'OPTIMISTIC_CONCURRENCY', - }, - { - name: 'Custom Lambda', - value: 'LAMBDA', - }, - { - name: 'Learn More', - value: 'Learn More', - }, - ], - }; - if (conflictResolutionStrategy === 'Learn More') { - conflictResolutionQuestion.prefix = dataStoreLearnMore; - } - ({ conflictResolutionStrategy } = await inquirer.prompt([conflictResolutionQuestion])); - } while (conflictResolutionStrategy === 'Learn More'); +async function askAdditionalQuestions(context, authConfig, defaultAuthType, modelTypes?) { + authConfig = await askAdditionalAuthQuestions(context, authConfig, defaultAuthType); + return { authConfig }; +} - let syncConfig: any = { - ConflictHandler: conflictResolutionStrategy, - ConflictDetection: 'VERSION', - }; +async function askResolverConflictQuestion(context, resolverConfig, modelTypes?) { + let resolverConfigResponse: any = {}; + + if (await context.prompt.confirm('Enable conflict detection?', !resolverConfig?.project)) { + resolverConfigResponse = await askResolverConflictHandlerQuestion(context, modelTypes); + } + + return resolverConfigResponse; +} - if (conflictResolutionStrategy === 'LAMBDA') { - const { newFunction, lambdaFunctionName } = await askSyncFunctionQuestion(context); - syncConfig.LambdaConflictHandler = { - name: lambdaFunctionName, - new: newFunction, - }; +async function askResolverConflictHandlerQuestion(context, modelTypes?) { + let resolverConfig: any = {}; + const askConflictResolutionStrategy = async msg => { + let conflictResolutionStrategy; + + do { + const conflictResolutionQuestion: ListQuestion = { + type: 'list', + name: 'conflictResolutionStrategy', + message: msg, + default: 'AUTOMERGE', + choices: conflictResolutionHanlderChoices, + }; + if (conflictResolutionStrategy === 'Learn More') { + conflictResolutionQuestion.prefix = dataStoreLearnMore; } + ({ conflictResolutionStrategy } = await inquirer.prompt([conflictResolutionQuestion])); + } while (conflictResolutionStrategy === 'Learn More'); - return syncConfig; + let syncConfig: any = { + ConflictHandler: conflictResolutionStrategy, + ConflictDetection: 'VERSION', }; - resolverConfig.project = await askConflictResolutionStrategy('Select the default resolution strategy'); + if (conflictResolutionStrategy === 'LAMBDA') { + const { newFunction, lambdaFunctionName } = await askSyncFunctionQuestion(context); + syncConfig.LambdaConflictHandler = { + name: lambdaFunctionName, + new: newFunction, + }; + } - // Ask for per-model resolver override setting + return syncConfig; + }; + + resolverConfig.project = await askConflictResolutionStrategy('Select the default resolution strategy'); + + // Ask for per-model resolver override setting - if (modelTypes && modelTypes.length > 0) { - if (await context.prompt.confirm('Do you want to override default per model settings?', false)) { - const modelTypeQuestion = { - type: 'checkbox', - name: 'selectedModelTypes', - message: 'Select the models from below:', - choices: modelTypes, - }; + if (modelTypes && modelTypes.length > 0) { + if (await context.prompt.confirm('Do you want to override default per model settings?', false)) { + const modelTypeQuestion = { + type: 'checkbox', + name: 'selectedModelTypes', + message: 'Select the models from below:', + choices: modelTypes, + }; - const { selectedModelTypes } = await inquirer.prompt([modelTypeQuestion]); + const { selectedModelTypes } = await inquirer.prompt([modelTypeQuestion]); - if (selectedModelTypes.length > 0) { - resolverConfig.models = {}; - for (let i = 0; i < selectedModelTypes.length; i += 1) { - resolverConfig.models[selectedModelTypes[i]] = await askConflictResolutionStrategy( - `Select the resolution strategy for ${selectedModelTypes[i]} model`, - ); - } + if (selectedModelTypes.length > 0) { + resolverConfig.models = {}; + for (let i = 0; i < selectedModelTypes.length; i += 1) { + resolverConfig.models[selectedModelTypes[i]] = await askConflictResolutionStrategy( + `Select the resolution strategy for ${selectedModelTypes[i]} model`, + ); } } } @@ -492,7 +666,7 @@ async function askDefaultAuthQuestion(context) { const { defaultAuthType } = await inquirer.prompt([defaultAuthTypeQuestion]); // Get default auth configured - const defaultAuth = await askAuthQuestions(defaultAuthType, context); + const defaultAuth = await askAuthQuestions(defaultAuthType, context, false, currentAuthConfig?.defaultAuthentication); return { authConfig: { @@ -508,9 +682,11 @@ export async function askAdditionalAuthQuestions(context, authConfig, defaultAut if (await context.prompt.confirm('Configure additional auth types?')) { // Get additional auth configured const remainingAuthProviderChoices = authProviderChoices.filter(p => p.value !== defaultAuthType); - const currentAdditionalAuth = ((currentAuthConfig && currentAuthConfig.additionalAuthenticationProviders - ? currentAuthConfig.additionalAuthenticationProviders - : []) as any[]).map(authProvider => authProvider.authenticationType); + const currentAdditionalAuth = ( + (currentAuthConfig && currentAuthConfig.additionalAuthenticationProviders + ? currentAuthConfig.additionalAuthenticationProviders + : []) as any[] + ).map(authProvider => authProvider.authenticationType); const additionalProvidersQuestion: CheckboxQuestion = { type: 'checkbox', @@ -525,7 +701,12 @@ export async function askAdditionalAuthQuestions(context, authConfig, defaultAut for (let i = 0; i < additionalProvidersAnswer.authType.length; i += 1) { const authProvider = additionalProvidersAnswer.authType[i]; - const config = await askAuthQuestions(authProvider, context, true); + const config = await askAuthQuestions( + authProvider, + context, + true, + currentAuthConfig?.additionalAuthenticationProviders?.find(authSetting => authSetting.authenticationType == authProvider), + ); authConfig.additionalAuthenticationProviders.push(config); } @@ -537,7 +718,7 @@ export async function askAdditionalAuthQuestions(context, authConfig, defaultAut return authConfig; } -async function askAuthQuestions(authType, context, printLeadText = false) { +export async function askAuthQuestions(authType, context, printLeadText = false, authSettings) { if (authType === 'AMAZON_COGNITO_USER_POOLS') { if (printLeadText) { context.print.info('Cognito UserPool configuration'); @@ -553,7 +734,7 @@ async function askAuthQuestions(authType, context, printLeadText = false) { context.print.info('API key configuration'); } - const apiKeyConfig = await askApiKeyQuestions(); + const apiKeyConfig = await askApiKeyQuestions(authSettings); return apiKeyConfig; } @@ -569,7 +750,7 @@ async function askAuthQuestions(authType, context, printLeadText = false) { context.print.info('OpenID Connect configuration'); } - const openIDConnectConfig = await askOpenIDConnectQuestions(); + const openIDConnectConfig = await askOpenIDConnectQuestions(authSettings); return openIDConnectConfig; } @@ -582,9 +763,8 @@ async function askAuthQuestions(authType, context, printLeadText = false) { async function askUserPoolQuestions(context) { let authResourceName = checkIfAuthExists(context); - if (!authResourceName) { - authResourceName = await context.amplify.invokePluginMethod(context, 'auth', undefined, 'add', [context]); + authResourceName = await context.amplify.invokePluginMethod(context, 'auth', undefined, 'add', [context, true]); } else { context.print.info('Use a Cognito user pool configured as a part of this project.'); } @@ -600,18 +780,25 @@ async function askUserPoolQuestions(context) { }; } -async function askApiKeyQuestions() { +export async function askApiKeyQuestions(authSettings = undefined) { + let defaultValues = { + apiKeyExpirationDays: 7, + description: undefined, + }; + Object.assign(defaultValues, authSettings?.apiKeyConfig); + const apiKeyQuestions = [ { type: 'input', name: 'description', message: 'Enter a description for the API key:', + default: defaultValues.description, }, { type: 'input', name: 'apiKeyExpirationDays', message: 'After how many days from now the API key should expire (1-365):', - default: 7, + default: defaultValues.apiKeyExpirationDays, validate: validateDays, // adding filter to ensure parsing input as int -> https://github.com/SBoudrias/Inquirer.js/issues/866 filter: value => (isNaN(parseInt(value, 10)) ? value : parseInt(value, 10)), @@ -619,6 +806,8 @@ async function askApiKeyQuestions() { ]; const apiKeyConfig = await inquirer.prompt(apiKeyQuestions); + const apiKeyExpirationDaysNum = Number(apiKeyConfig.apiKeyExpirationDays); + apiKeyConfig.apiKeyExpirationDate = Expiration.after(Duration.days(apiKeyExpirationDaysNum)).date; return { authenticationType: 'API_KEY', @@ -626,35 +815,49 @@ async function askApiKeyQuestions() { }; } -async function askOpenIDConnectQuestions() { +async function askOpenIDConnectQuestions(authSettings) { + let defaultValues = { + authTTL: undefined, + clientId: undefined, + iatTTL: undefined, + issuerUrl: undefined, + name: undefined, + }; + Object.assign(defaultValues, authSettings?.openIDConnectConfig); + const openIDConnectQuestions = [ { type: 'input', name: 'name', message: 'Enter a name for the OpenID Connect provider:', + default: defaultValues.name, }, { type: 'input', name: 'issuerUrl', message: 'Enter the OpenID Connect provider domain (Issuer URL):', validate: validateIssuerUrl, + default: defaultValues.issuerUrl, }, { type: 'input', name: 'clientId', message: 'Enter the Client Id from your OpenID Client Connect application (optional):', + default: defaultValues.clientId, }, { type: 'input', name: 'iatTTL', message: 'Enter the number of milliseconds a token is valid after being issued to a user:', validate: validateTTL, + default: defaultValues.iatTTL, }, { type: 'input', name: 'authTTL', message: 'Enter the number of milliseconds a token is valid after being authenticated:', validate: validateTTL, + default: defaultValues.authTTL, }, ]; @@ -677,9 +880,10 @@ function validateDays(input) { } function validateIssuerUrl(input) { - const isValid = /^(((?!http:\/\/(?!localhost))([a-zA-Z0-9.]{1,}):\/\/([a-zA-Z0-9-._~:?#@!$&'()*+,;=/]{1,})\/)|(?!http)(?!https)([a-zA-Z0-9.]{1,}):\/\/)$/.test( - input, - ); + const isValid = + /^(((?!http:\/\/(?!localhost))([a-zA-Z0-9.]{1,}):\/\/([a-zA-Z0-9-._~:?#@!$&'()*+,;=/]{1,})\/)|(?!http)(?!https)([a-zA-Z0-9.]{1,}):\/\/)$/.test( + input, + ); if (!isValid) { return 'The value must be a valid URI with a trailing forward slash. HTTPS must be used instead of HTTP unless you are using localhost.'; @@ -779,8 +983,8 @@ const buildPolicyResource = (resourceName: string, path: string | null) => { { Ref: `${category}${resourceName}GraphQLAPIIdOutput`, }, - ...(path ? [path] : []) - ] + ...(path ? [path] : []), + ], ], }; }; @@ -788,7 +992,8 @@ const buildPolicyResource = (resourceName: string, path: string | null) => { const templateSchemaFilter = authConfig => { const authIncludesCognito = getAuthTypes(authConfig).includes('AMAZON_COGNITO_USER_POOLS'); return (templateOption: ListChoiceOptions): boolean => - authIncludesCognito || templateOption.value !== 'single-object-auth-schema.graphql'; + authIncludesCognito || + templateOption.name !== 'Objects with fine-grained access control (e.g., a project management app with owner-based authorization)'; }; const getAuthTypes = authConfig => { diff --git a/packages/amplify-category-api/src/provider-utils/awscloudformation/utils/auth-config-to-app-sync-auth-type-bi-di-mapper.ts b/packages/amplify-category-api/src/provider-utils/awscloudformation/utils/auth-config-to-app-sync-auth-type-bi-di-mapper.ts index d52094eae50..c1a8dde916a 100644 --- a/packages/amplify-category-api/src/provider-utils/awscloudformation/utils/auth-config-to-app-sync-auth-type-bi-di-mapper.ts +++ b/packages/amplify-category-api/src/provider-utils/awscloudformation/utils/auth-config-to-app-sync-auth-type-bi-di-mapper.ts @@ -30,6 +30,7 @@ const authConfigToAppSyncAuthTypeMap: Record AppSyn API_KEY: authConfig => ({ mode: 'API_KEY', expirationTime: authConfig.apiKeyConfig.apiKeyExpirationDays, + apiKeyExpirationDate: authConfig.apiKeyConfig?.apiKeyExpirationDate, keyDescription: authConfig.apiKeyConfig.description, }), AWS_IAM: () => ({ @@ -54,6 +55,7 @@ const appSyncAuthTypeToAuthConfigMap: Record { type: 'confirm', name: 'editNow', message: 'Do you want to edit the schema now?', - default: false, + default: true, }; if (!(await inquirer.prompt(prompt)).editNow) return; diff --git a/packages/amplify-category-api/src/provider-utils/awscloudformation/utils/global-sandbox-mode.ts b/packages/amplify-category-api/src/provider-utils/awscloudformation/utils/global-sandbox-mode.ts new file mode 100644 index 00000000000..27fc26f1f30 --- /dev/null +++ b/packages/amplify-category-api/src/provider-utils/awscloudformation/utils/global-sandbox-mode.ts @@ -0,0 +1,10 @@ +import { $TSContext } from 'amplify-cli-core'; + +export function defineGlobalSandboxMode(context: $TSContext): string { + const envName = context.amplify.getEnvInfo().envName; + + return `# This allows public create, read, update, and delete access for a limited time to all models via API Key. +# To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql-transformer/auth +type AMPLIFY_GLOBAL @allow_public_data_access_with_api_key(in: \"${envName}\") # FOR TESTING ONLY!\n +`; +} diff --git a/packages/amplify-category-api/src/provider-utils/supported-services.ts b/packages/amplify-category-api/src/provider-utils/supported-services.ts index 9bf9cbba01e..d5fe5482aa2 100644 --- a/packages/amplify-category-api/src/provider-utils/supported-services.ts +++ b/packages/amplify-category-api/src/provider-utils/supported-services.ts @@ -52,6 +52,10 @@ export const supportedServices = { name: 'Objects with fine-grained access control (e.g., a project management app with owner-based authorization)', value: 'single-object-auth-schema.graphql', }, + { + name: 'Blank Schema', + value: 'blank-schema.graphql', + }, ], required: true, }, diff --git a/packages/amplify-category-auth/src/index.js b/packages/amplify-category-auth/src/index.js index 60d30618107..7912c91db6b 100644 --- a/packages/amplify-category-auth/src/index.js +++ b/packages/amplify-category-auth/src/index.js @@ -34,7 +34,7 @@ const { } = require('./provider-utils/awscloudformation/utils/auth-sms-workflow-helper'); // this function is being kept for temporary compatability. -async function add(context) { +async function add(context, skipNextSteps = false) { const { amplify } = context; const servicesMetadata = getSupportedServices(); const existingAuth = amplify.getProjectDetails().amplifyMeta.auth || {}; @@ -54,7 +54,7 @@ async function add(context) { context.print.error('Provider not configured for this category'); return; } - return providerController.addResource(context, result.service); + return providerController.addResource(context, result.service, skipNextSteps); }) .catch(err => { context.print.info(err.stack); diff --git a/packages/amplify-category-auth/src/provider-utils/awscloudformation/handlers/resource-handlers.ts b/packages/amplify-category-auth/src/provider-utils/awscloudformation/handlers/resource-handlers.ts index 8986123be4b..f40a03833c0 100644 --- a/packages/amplify-category-auth/src/provider-utils/awscloudformation/handlers/resource-handlers.ts +++ b/packages/amplify-category-auth/src/provider-utils/awscloudformation/handlers/resource-handlers.ts @@ -11,7 +11,7 @@ import { doesConfigurationIncludeSMS } from '../utils/auth-sms-workflow-helper'; * The consumer returns the resourceName of the generated resource. * @param context The amplify context */ -export const getAddAuthHandler = (context: any) => async (request: ServiceQuestionsResult) => { +export const getAddAuthHandler = (context: any, skipNextSteps: boolean = false) => async (request: ServiceQuestionsResult) => { const serviceMetadata = getSupportedServices()[request.serviceName]; const { cfnFilename, defaultValuesFilename, provider } = serviceMetadata; @@ -26,7 +26,7 @@ export const getAddAuthHandler = (context: any) => async (request: ServiceQuesti await getPostAddAuthMetaUpdater(context, { service: requestWithDefaults.serviceName, providerName: provider })( requestWithDefaults.resourceName!, ); - await getPostAddAuthMessagePrinter(context.print)(requestWithDefaults.resourceName!); + await getPostAddAuthMessagePrinter(context.print)(requestWithDefaults.resourceName!, skipNextSteps); if (doesConfigurationIncludeSMS(request)) { await printSMSSandboxWarning(context.print); diff --git a/packages/amplify-category-auth/src/provider-utils/awscloudformation/index.js b/packages/amplify-category-auth/src/provider-utils/awscloudformation/index.js index 6f1e6260f2c..3a8a5691e93 100644 --- a/packages/amplify-category-auth/src/provider-utils/awscloudformation/index.js +++ b/packages/amplify-category-auth/src/provider-utils/awscloudformation/index.js @@ -14,10 +14,10 @@ function serviceQuestions(context, defaultValuesFilename, stringMapsFilename, se return serviceWalkthrough(context, defaultValuesFilename, stringMapsFilename, serviceMetadata); } -async function addResource(context, service) { +async function addResource(context, service, skipNextSteps = false) { const serviceMetadata = getSupportedServices()[service]; const { defaultValuesFilename, stringMapsFilename, serviceWalkthroughFilename } = serviceMetadata; - return getAddAuthHandler(context)( + return getAddAuthHandler(context, skipNextSteps)( await serviceQuestions(context, defaultValuesFilename, stringMapsFilename, serviceWalkthroughFilename, serviceMetadata), ); } diff --git a/packages/amplify-category-auth/src/provider-utils/awscloudformation/utils/message-printer.ts b/packages/amplify-category-auth/src/provider-utils/awscloudformation/utils/message-printer.ts index b5c0c0148a8..9b3f9a71bae 100644 --- a/packages/amplify-category-auth/src/provider-utils/awscloudformation/utils/message-printer.ts +++ b/packages/amplify-category-auth/src/provider-utils/awscloudformation/utils/message-printer.ts @@ -5,9 +5,12 @@ import { BannerMessage } from 'amplify-cli-core'; * A factory function that returns a function that prints the "success message" after adding auth * @param print The amplify print object */ -export const getPostAddAuthMessagePrinter = (print: any) => (resourceName: string) => { +export const getPostAddAuthMessagePrinter = (print: any) => (resourceName: string, skipNextSteps: boolean = false) => { print.success(`Successfully added auth resource ${resourceName} locally`); - printCommonText(print); + + if (!skipNextSteps) { + printCommonText(print); + } }; /** diff --git a/packages/amplify-cli/src/__tests__/commands/status.test.ts b/packages/amplify-cli/src/__tests__/commands/status.test.ts index d22a798a354..30f9dc59605 100644 --- a/packages/amplify-cli/src/__tests__/commands/status.test.ts +++ b/packages/amplify-cli/src/__tests__/commands/status.test.ts @@ -1,5 +1,3 @@ -import { UnknownArgumentError } from 'amplify-cli-core'; - describe('amplify status: ', () => { const { run } = require('../../commands/status'); const runStatusCmd = run; @@ -11,17 +9,10 @@ describe('amplify status: ', () => { }); it('status run method should call context.amplify.showStatusTable', async () => { - const cliInput = { - command: 'status', - subCommands: [], - options: { - verbose: true, - }, - }; - const mockContextNoCLArgs = { amplify: { showStatusTable: jest.fn(), + showGlobalSandboxModeWarning: jest.fn(), showHelpfulProviderLinks: jest.fn(), getCategoryPluginInfo: jest.fn().mockReturnValue({ packageLocation: mockPath }), }, @@ -43,6 +34,7 @@ describe('amplify status: ', () => { const mockContextWithVerboseOptionAndCLArgs = { amplify: { showStatusTable: jest.fn(), + showGlobalSandboxModeWarning: jest.fn(), showHelpfulProviderLinks: jest.fn(), getCategoryPluginInfo: jest.fn().mockReturnValue({ packageLocation: statusPluginInfo }), }, @@ -61,6 +53,7 @@ describe('amplify status: ', () => { const mockContextWithVerboseOptionWithCategoriesAndCLArgs = { amplify: { showStatusTable: jest.fn(), + showGlobalSandboxModeWarning: jest.fn(), showHelpfulProviderLinks: jest.fn(), getCategoryPluginInfo: jest.fn().mockReturnValue({ packageLocation: statusPluginInfo }), }, @@ -82,6 +75,7 @@ describe('amplify status: ', () => { const mockContextWithHelpSubcommandAndCLArgs = { amplify: { showStatusTable: jest.fn(), + showGlobalSandboxModeWarning: jest.fn(), showHelpfulProviderLinks: jest.fn(), getCategoryPluginInfo: jest.fn().mockReturnValue({ packageLocation: statusPluginInfo }), }, @@ -94,5 +88,4 @@ describe('amplify status: ', () => { //TBD: to move ViewResourceTableParams into a separate file for mocking instance functions. expect(mockContextWithHelpSubcommandAndCLArgs.amplify.showStatusTable.mock.calls.length).toBe(0); }); - }); diff --git a/packages/amplify-cli/src/__tests__/extensions/amplify-helpers/testData/mockLocalCloud/amplify-meta-2.json b/packages/amplify-cli/src/__tests__/extensions/amplify-helpers/testData/mockLocalCloud/amplify-meta-2.json new file mode 100644 index 00000000000..9bd3f8293be --- /dev/null +++ b/packages/amplify-cli/src/__tests__/extensions/amplify-helpers/testData/mockLocalCloud/amplify-meta-2.json @@ -0,0 +1,25 @@ +{ + "api": { + "ampapp": { + "service": "AppSync", + "providerPlugin": "awscloudformation", + "output": { + "authConfig": { + "defaultAuthentication": { + "authenticationType": "AWS_IAM" + }, + "additionalAuthenticationProviders": [ + { + "authenticationType": "API_KEY", + "apiKeyConfig": { + "apiKeyExpirationDays": 2, + "apiKeyExpirationDate": "2021-08-20T20:38:07.585Z", + "description": "" + } + } + ] + } + } + } + } +} diff --git a/packages/amplify-cli/src/__tests__/extensions/amplify-helpers/testData/mockLocalCloud/amplify-meta-3.json b/packages/amplify-cli/src/__tests__/extensions/amplify-helpers/testData/mockLocalCloud/amplify-meta-3.json new file mode 100644 index 00000000000..7aa92695860 --- /dev/null +++ b/packages/amplify-cli/src/__tests__/extensions/amplify-helpers/testData/mockLocalCloud/amplify-meta-3.json @@ -0,0 +1,16 @@ +{ + "api": { + "ampapp": { + "service": "AppSync", + "providerPlugin": "awscloudformation", + "output": { + "authConfig": { + "defaultAuthentication": { + "authenticationType": "AWS_IAM" + }, + "additionalAuthenticationProviders": [] + } + } + } + } +} diff --git a/packages/amplify-cli/src/__tests__/extensions/amplify-helpers/testData/mockLocalCloud/amplify-meta.json b/packages/amplify-cli/src/__tests__/extensions/amplify-helpers/testData/mockLocalCloud/amplify-meta.json new file mode 100644 index 00000000000..cb9a35d4025 --- /dev/null +++ b/packages/amplify-cli/src/__tests__/extensions/amplify-helpers/testData/mockLocalCloud/amplify-meta.json @@ -0,0 +1,28 @@ +{ + "api": { + "ampapp": { + "service": "AppSync", + "providerPlugin": "awscloudformation", + "output": { + "authConfig": { + "defaultAuthentication": { + "authenticationType": "AWS_IAM" + }, + "additionalAuthenticationProviders": [ + { + "authenticationType": "API_KEY", + "apiKeyConfig": { + "apiKeyExpirationDays": 2, + "apiKeyExpirationDate": "2021-08-20T20:38:07.585Z", + "description": "" + } + } + ] + }, + "globalSandboxModeConfig": { + "env": "dev" + } + } + } + } +} diff --git a/packages/amplify-cli/src/commands/status.ts b/packages/amplify-cli/src/commands/status.ts index 3e11576346a..b9dad7bf397 100644 --- a/packages/amplify-cli/src/commands/status.ts +++ b/packages/amplify-cli/src/commands/status.ts @@ -1,26 +1,27 @@ -import { ViewResourceTableParams, CLIParams, $TSContext } from "amplify-cli-core"; +import { ViewResourceTableParams, CLIParams, $TSContext } from 'amplify-cli-core'; +export const run = async (context: $TSContext) => { + const cliParams: CLIParams = { + cliCommand: context?.input?.command, + cliSubcommands: context?.input?.subCommands, + cliOptions: context?.input?.options, + }; -export const run = async (context : $TSContext) => { - const cliParams:CLIParams = { cliCommand : context?.input?.command, - cliSubcommands: context?.input?.subCommands, - cliOptions : context?.input?.options } - - const view = new ViewResourceTableParams( cliParams ); - if ( context?.input?.subCommands?.includes("help")){ - context.print.info( view.getStyledHelp() ); + const view = new ViewResourceTableParams(cliParams); + if (context?.input?.subCommands?.includes('help')) { + context.print.info(view.getStyledHelp()); } else { try { - await context.amplify.showStatusTable( view ); + await context.amplify.showStatusTable(view); await context.amplify.showHelpfulProviderLinks(context); await showAmplifyConsoleHostingStatus(context); - } catch ( e ){ + } catch (e) { view.logErrorException(e, context); } } }; -async function showAmplifyConsoleHostingStatus( context) { +async function showAmplifyConsoleHostingStatus(context) { const pluginInfo = context.amplify.getCategoryPluginInfo(context, 'hosting', 'amplifyhosting'); if (pluginInfo && pluginInfo.packageLocation) { const { status } = await import(pluginInfo.packageLocation); diff --git a/packages/amplify-cli/src/domain/amplify-toolkit.ts b/packages/amplify-cli/src/domain/amplify-toolkit.ts index 55f1b41b753..046f9fbbb3f 100644 --- a/packages/amplify-cli/src/domain/amplify-toolkit.ts +++ b/packages/amplify-cli/src/domain/amplify-toolkit.ts @@ -261,8 +261,7 @@ export class AmplifyToolkit { } get showStatusTable(): any { - this._showStatusTable = - this._showStatusTable || require(path.join(this._amplifyHelpersDirPath, 'resource-status')).showStatusTable; + this._showStatusTable = this._showStatusTable || require(path.join(this._amplifyHelpersDirPath, 'resource-status')).showStatusTable; return this._showStatusTable; } diff --git a/packages/amplify-cli/src/extensions/amplify-helpers/push-resources.ts b/packages/amplify-cli/src/extensions/amplify-helpers/push-resources.ts index 3e3c5efa8b0..dc38a8b44ba 100644 --- a/packages/amplify-cli/src/extensions/amplify-helpers/push-resources.ts +++ b/packages/amplify-cli/src/extensions/amplify-helpers/push-resources.ts @@ -68,20 +68,27 @@ export async function pushResources( continueToPush = await context.amplify.confirmPrompt('Are you sure you want to continue?'); } + let retryPush; if (continueToPush) { - try { - // Get current-cloud-backend's amplify-meta - const currentAmplifyMeta = stateManager.getCurrentMeta(); - - await providersPush(context, category, resourceName, filteredResources); - await onCategoryOutputsChange(context, currentAmplifyMeta); - } catch (err) { - // Handle the errors and print them nicely for the user. - if (!(err instanceof CustomPoliciesFormatError)) { - printer.error(`\n${err.message}`); + do { + retryPush = false; + try { + // Get current-cloud-backend's amplify-meta + const currentAmplifyMeta = stateManager.getCurrentMeta(); + + await providersPush(context, category, resourceName, filteredResources); + await onCategoryOutputsChange(context, currentAmplifyMeta); + } catch (err) { + if (await isValidGraphQLAuthError(err.message)) { + retryPush = await handleValidGraphQLAuthError(context, err.message); + } + if(!retryPush) { + // Handle the errors and print them nicely for the user. + context.print.error(`\n${err.message}`); + throw err; + } } - throw err; - } + } while (retryPush); } else { // there's currently no other mechanism to stop the execution of the postPush workflow in this case, so exiting here exitOnNextTick(1); @@ -90,6 +97,49 @@ export async function pushResources( return continueToPush; } +async function isValidGraphQLAuthError(message: string) { + if (message === `@auth directive with 'iam' provider found, but the project has no IAM authentication provider configured.` + || message === `@auth directive with 'userPools' provider found, but the project has no Cognito User Pools authentication provider configured.` + || message === `@auth directive with 'oidc' provider found, but the project has no OPENID_CONNECT authentication provider configured.` + || message === `@auth directive with 'apiKey' provider found, but the project has no API Key authentication provider configured.` + || message === `@auth directive with 'function' provider found, but the project has no Lambda authentication provider configured.`) { + return true; + } +} + +async function handleValidGraphQLAuthError(context: $TSContext, message: string) { + if (message === `@auth directive with 'iam' provider found, but the project has no IAM authentication provider configured.`) { + await addGraphQLAuthRequirement(context, 'AWS_IAM'); + return true; + } else if (!context?.parameters?.options?.yes) { + if (message === `@auth directive with 'userPools' provider found, but the project has no Cognito User Pools authentication provider configured.`) { + await addGraphQLAuthRequirement(context, 'AMAZON_COGNITO_USER_POOLS'); + return true; + } else if (message === `@auth directive with 'oidc' provider found, but the project has no OPENID_CONNECT authentication provider configured.`) { + await addGraphQLAuthRequirement(context, 'OPENID_CONNECT') + return true; + } else if (message === `@auth directive with 'apiKey' provider found, but the project has no API Key authentication provider configured.`) { + await addGraphQLAuthRequirement(context, 'AWS_KEY'); + return true; + } else if (message === `@auth directive with 'function' provider found, but the project has no Lambda authentication provider configured.`) { + await addGraphQLAuthRequirement(context, 'AWS_LAMBDA'); + return true; + } + } + return false; +} + +async function addGraphQLAuthRequirement(context, authType) { + return await context.amplify.invokePluginMethod(context, 'api', undefined, 'addGraphQLAuthorizationMode', [ + context, + { + authType: authType, + printLeadText: true, + authSettings: undefined, + }, + ]); +} + async function providersPush(context: $TSContext, category, resourceName, filteredResources) { const { providers } = getProjectConfig(); const providerPlugins = getProviderPlugins(context); diff --git a/packages/amplify-e2e-core/src/categories/api.ts b/packages/amplify-e2e-core/src/categories/api.ts index 141d7e07da8..66c03980297 100644 --- a/packages/amplify-e2e-core/src/categories/api.ts +++ b/packages/amplify-e2e-core/src/categories/api.ts @@ -27,30 +27,27 @@ export function apiGqlCompile(cwd: string, testingWithLatestCodebase: boolean = interface AddApiOptions { apiName: string; + testingWithLatestCodebase: boolean; } const defaultOptions: AddApiOptions = { - apiName: EOL, + apiName: '\r', + testingWithLatestCodebase: true, }; -export function addApiWithoutSchema(cwd: string, opts: Partial = {}) { +export function addApiWithoutSchema(cwd: string, opts: Partial = {}) { const options = _.assign(defaultOptions, opts); return new Promise((resolve, reject) => { - spawn(getCLIPath(), ['add', 'api'], { cwd, stripColors: true }) + spawn(getCLIPath(options.testingWithLatestCodebase), ['add', 'api'], { cwd, stripColors: true }) .wait('Please select from one of the below mentioned services:') .sendCarriageReturn() + .wait(/.*Here is the GraphQL API that we will create. Select a setting to edit or continue.*/) + .sendKeyUp(3) + .sendCarriageReturn() .wait('Provide API name:') .sendLine(options.apiName) - .wait(/.*Choose the default authorization type for the API.*/) - .sendCarriageReturn() - .wait(/.*Enter a description for the API key.*/) - .sendCarriageReturn() - .wait(/.*After how many days from now the API key should expire.*/) - .sendCarriageReturn() - .wait(/.*Do you want to configure advanced settings for the GraphQL API.*/) + .wait(/.*Here is the GraphQL API that we will create. Select a setting to edit or continue.*/) .sendCarriageReturn() - .wait('Do you have an annotated GraphQL schema?') - .sendConfirmNo() .wait('Choose a schema template:') .sendCarriageReturn() .wait('Do you want to edit the schema now?') @@ -68,30 +65,28 @@ export function addApiWithoutSchema(cwd: string, opts: Partial = }); } -export function addApiWithSchema(cwd: string, schemaFile: string, opts: Partial = {}) { +export function addApiWithBlankSchema(cwd: string, opts: Partial = {}) { const options = _.assign(defaultOptions, opts); - const schemaPath = getSchemaPath(schemaFile); return new Promise((resolve, reject) => { - spawn(getCLIPath(), ['add', 'api'], { cwd, stripColors: true }) + spawn(getCLIPath(options.testingWithLatestCodebase), ['add', 'api'], { cwd, stripColors: true }) .wait('Please select from one of the below mentioned services:') .sendCarriageReturn() + .wait(/.*Here is the GraphQL API that we will create. Select a setting to edit or continue.*/) + .sendKeyUp(3) + .sendCarriageReturn() .wait('Provide API name:') .sendLine(options.apiName) - .wait(/.*Choose the default authorization type for the API.*/) + .wait(/.*Here is the GraphQL API that we will create. Select a setting to edit or continue.*/) .sendCarriageReturn() - .wait(/.*Enter a description for the API key.*/) - .sendCarriageReturn() - .wait(/.*After how many days from now the API key should expire.*/) - .sendLine(opts.apiKeyExpirationDays ? opts.apiKeyExpirationDays.toString() : '1') - .wait(/.*Do you want to configure advanced settings for the GraphQL API.*/) + .wait('Choose a schema template:') + .sendKeyDown(2) .sendCarriageReturn() - .wait('Do you have an annotated GraphQL schema?') - .sendConfirmYes() - .wait('Provide your schema file path:') - .sendLine(schemaPath) + .wait('Do you want to edit the schema now?') + .sendLine('n') .wait( '"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud', ) + .sendEof() .run((err: Error) => { if (!err) { resolve(); @@ -99,35 +94,29 @@ export function addApiWithSchema(cwd: string, schemaFile: string, opts: Partial< reject(err); } }); + }); } -export function addApiWithSchemaAndConflictDetection(cwd: string, schemaFile: string) { - const schemaPath = getSchemaPath(schemaFile); +export function addApiWithBlankSchemaAndConflictDetection(cwd: string) { return new Promise((resolve, reject) => { - spawn(getCLIPath(), ['add', 'api'], { cwd, stripColors: true }) + spawn(getCLIPath(defaultOptions.testingWithLatestCodebase), ['add', 'api'], { cwd, stripColors: true }) .wait('Please select from one of the below mentioned services:') .sendCarriageReturn() - .wait('Provide API name:') - .sendCarriageReturn() - .wait(/.*Choose the default authorization type for the API.*/) - .sendCarriageReturn() - .wait(/.*Enter a description for the API key.*/) - .sendCarriageReturn() - .wait(/.*After how many days from now the API key should expire.*/) + .wait(/.*Here is the GraphQL API that we will create. Select a setting to edit or continue.*/) + .sendKeyUp() .sendCarriageReturn() - .wait(/.*Do you want to configure advanced settings for the GraphQL API.*/) - .sendLine(KEY_DOWN_ARROW) // Down - .wait(/.*Configure additional auth types.*/) - .sendConfirmNo() .wait(/.*Enable conflict detection.*/) .sendConfirmYes() .wait(/.*Select the default resolution strategy.*/) .sendCarriageReturn() - .wait(/.*Do you have an annotated GraphQL schema.*/) - .sendConfirmYes() - .wait('Provide your schema file path:') - .sendLine(schemaPath) + .wait(/.*Here is the GraphQL API that we will create. Select a setting to edit or continue.*/) + .sendCarriageReturn() + .wait('Choose a schema template:') + .sendKeyDown(2) + .sendCarriageReturn() + .wait('Do you want to edit the schema now?') + .sendLine('n') .wait( '"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud', ) @@ -155,7 +144,7 @@ export function updateApiWithMultiAuth(cwd: string, settings: any) { spawn(getCLIPath(settings.testingWithLatestCodebase), ['update', 'api'], { cwd, stripColors: true }) .wait('Please select from one of the below mentioned services:') .sendCarriageReturn() - .wait('Select from the options below') + .wait(/.*Select a setting to edit.*/) .sendCarriageReturn() .wait(/.*Choose the default authorization type for the API.*/) .sendCarriageReturn() @@ -163,8 +152,6 @@ export function updateApiWithMultiAuth(cwd: string, settings: any) { .sendLine('description') .wait(/.*After how many days from now the API key should expire.*/) .sendLine('300') - .wait(/.*Do you want to configure advanced settings for the GraphQL API.*/) - .sendLine(KEY_DOWN_ARROW) // Down .wait(/.*Configure additional auth types.*/) .sendConfirmYes() .wait(/.*Choose the additional authorization types you want to configure for the API.*/) @@ -187,7 +174,29 @@ export function updateApiWithMultiAuth(cwd: string, settings: any) { .sendLine('1000') .wait(/.*Enter the number of milliseconds a token is valid after being authenticated.*/) .sendLine('2000') - .wait('Enable conflict detection?') + .wait(/.*Successfully updated resource.*/) + .sendEof() + .run((err: Error) => { + if (!err) { + resolve(); + } else { + reject(err); + } + }); + }); +} + +export function apiEnableDataStore(cwd: string, settings: any) { + return new Promise((resolve, reject) => { + spawn(getCLIPath(settings.testingWithLatestCodebase), ['update', 'api'], { cwd, stripColors: true }) + .wait('Please select from one of the below mentioned services:') + .sendCarriageReturn() + .wait(/.*Select a setting to edit.*/) + .sendKeyDown() + .sendCarriageReturn() + .wait(/.*Select the default resolution strategy.*/) + .sendCarriageReturn() + .wait(/.*Do you want to override default per model settings?.*/) .sendConfirmNo() .wait(/.*Successfully updated resource.*/) .sendEof() @@ -201,14 +210,14 @@ export function updateApiWithMultiAuth(cwd: string, settings: any) { }); } -export function apiUpdateToggleDataStore(cwd: string, settings: any) { +export function apiDisableDataStore(cwd: string, settings: any) { return new Promise((resolve, reject) => { spawn(getCLIPath(settings.testingWithLatestCodebase), ['update', 'api'], { cwd, stripColors: true }) .wait('Please select from one of the below mentioned services:') .sendCarriageReturn() - .wait('Select from the options below') - .send(KEY_DOWN_ARROW) - .sendLine(KEY_DOWN_ARROW) // select enable datastore for the api + .wait(/.*Select a setting to edit.*/) + .sendKeyDown(2) // Disable conflict detection + .sendCarriageReturn() .wait(/.*Successfully updated resource.*/) .sendEof() .run((err: Error) => { @@ -221,28 +230,41 @@ export function apiUpdateToggleDataStore(cwd: string, settings: any) { }); } -export function updateAPIWithResolutionStrategy(cwd: string, settings: any) { +export function updateAPIWithResolutionStrategyWithoutModels(cwd: string, settings: any) { return new Promise((resolve, reject) => { spawn(getCLIPath(settings.testingWithLatestCodebase), ['update', 'api'], { cwd, stripColors: true }) .wait('Please select from one of the below mentioned services:') .sendCarriageReturn() - .wait('Select from the options below') + .wait(/.*Select a setting to edit.*/) + .sendKeyDown() .sendCarriageReturn() - .wait(/.*Choose the default authorization type for the API.*/) + .wait(/.*Select the default resolution strategy.*/) + .sendKeyDown() .sendCarriageReturn() - .wait(/.*Enter a description for the API key.*/) + .wait(/.*Successfully updated resource.*/) + .sendEof() + .run((err: Error) => { + if (!err) { + resolve(); + } else { + reject(err); + } + }); + }); +} + +export function updateAPIWithResolutionStrategyWithModels(cwd: string, settings: any) { + return new Promise((resolve, reject) => { + spawn(getCLIPath(settings.testingWithLatestCodebase), ['update', 'api'], { cwd, stripColors: true }) + .wait('Please select from one of the below mentioned services:') .sendCarriageReturn() - .wait(/.*After how many days from now the API key should expire.*/) + .wait(/.*Select a setting to edit.*/) + .sendKeyDown() .sendCarriageReturn() - .wait(/.*Do you want to configure advanced settings for the GraphQL API.*/) - .sendLine(KEY_DOWN_ARROW) // Down - .wait(/.*Configure additional auth types.*/) - .sendConfirmNo() - .wait(/.*Enable conflict detection.*/) - .sendConfirmYes() .wait(/.*Select the default resolution strategy.*/) - .sendLine(KEY_DOWN_ARROW) // Down - .wait(/.*Do you want to override default per model settings.*/) + .sendKeyDown() + .sendCarriageReturn() + .wait(/.*Do you want to override default per model settings?.*/) .sendConfirmNo() .wait(/.*Successfully updated resource.*/) .sendEof() @@ -385,16 +407,19 @@ const allAuthTypes = ['API key', 'Amazon Cognito User Pool', 'IAM', 'OpenID Conn export function addApi(projectDir: string, settings?: any) { let authTypesToSelectFrom = allAuthTypes.slice(); return new Promise((resolve, reject) => { - let chain = spawn(getCLIPath(), ['add', 'api'], { cwd: projectDir, stripColors: true }) + let chain = spawn(getCLIPath(defaultOptions.testingWithLatestCodebase), ['add', 'api'], { cwd: projectDir, stripColors: true }) .wait('Please select from one of the below mentioned services:') .sendCarriageReturn() - .wait('Provide API name:') - .sendCarriageReturn(); if (settings && Object.keys(settings).length > 0) { const authTypesToAdd = Object.keys(settings); const defaultType = authTypesToAdd[0]; + chain + .wait(/.*Here is the GraphQL API that we will create. Select a setting to edit or continue.*/) + .sendKeyUp(2) + .sendCarriageReturn(); + singleSelect(chain.wait('Choose the default authorization type for the API'), defaultType, authTypesToSelectFrom); setupAuthType(defaultType, chain, settings); @@ -402,9 +427,6 @@ export function addApi(projectDir: string, settings?: any) { authTypesToAdd.shift(); chain - .wait('Do you want to configure advanced settings for the GraphQL API') - .send(KEY_DOWN_ARROW) //yes - .sendCarriageReturn() .wait('Configure additional auth types?') .sendConfirmYes(); @@ -419,21 +441,16 @@ export function addApi(projectDir: string, settings?: any) { authTypesToAdd.forEach(authType => { setupAuthType(authType, chain, settings); }); - - chain.wait('Enable conflict detection?').sendCarriageReturn(); //No } else { - chain.wait('Do you want to configure advanced settings for the GraphQL API').sendCarriageReturn(); //No + chain + .wait('Configure additional auth types?') + .sendLine('n'); } - } else { - chain.wait('Choose the default authorization type for the API').sendCarriageReturn(); - setupAPIKey(chain); - - chain.wait('Do you want to configure advanced settings for the GraphQL API').sendCarriageReturn(); //No } chain - .wait('Do you have an annotated GraphQL schema?') - .sendConfirmNo() + .wait(/.*Here is the GraphQL API that we will create. Select a setting to edit or continue.*/) + .sendCarriageReturn() .wait('Choose a schema template:') .sendCarriageReturn() .wait('Do you want to edit the schema now?') @@ -512,18 +529,19 @@ function setupOIDC(chain: any, settings?: any) { export function addApiWithCognitoUserPoolAuthTypeWhenAuthExists(projectDir: string) { return new Promise((resolve, reject) => { - spawn(getCLIPath(), ['add', 'api'], { cwd: projectDir, stripColors: true }) + spawn(getCLIPath(defaultOptions.testingWithLatestCodebase), ['add', 'api'], { cwd: projectDir, stripColors: true }) .wait('Please select from one of the below mentioned services:') .sendCarriageReturn() - .wait('Provide API name:') + .wait(/.*Here is the GraphQL API that we will create. Select a setting to edit or continue.*/) + .sendKeyUp(2) .sendCarriageReturn() - .wait('Choose the default authorization type for the API') - .send(KEY_DOWN_ARROW) + .wait(/.*Choose the default authorization type for the API.*/) + .sendKeyDown(1) .sendCarriageReturn() - .wait('Do you want to configure advanced settings for the GraphQL AP') + .wait(/.*Configure additional auth types.*/) + .sendLine('n') + .wait(/.*Here is the GraphQL API that we will create. Select a setting to edit or continue.*/) .sendCarriageReturn() - .wait('Do you have an annotated GraphQL schema?') - .sendConfirmNo() .wait('Choose a schema template:') .sendCarriageReturn() .wait('Do you want to edit the schema now?') diff --git a/packages/amplify-e2e-core/src/categories/auth.ts b/packages/amplify-e2e-core/src/categories/auth.ts index fa71b669b0b..d358b656d76 100644 --- a/packages/amplify-e2e-core/src/categories/auth.ts +++ b/packages/amplify-e2e-core/src/categories/auth.ts @@ -119,12 +119,23 @@ export function addAuthWithGroupTrigger(cwd: string, settings: any): Promise { return new Promise((resolve, reject) => { - spawn(getCLIPath(), ['add', 'api'], { cwd, stripColors: true }) + spawn(getCLIPath(defaultOptions.testingWithLatestCodebase), ['add', 'api'], { cwd, stripColors: true }) .wait('Please select from one of the below mentioned services:') .sendCarriageReturn() - .wait('Provide API name') + .wait(/.*Here is the GraphQL API that we will create. Select a setting to edit or continue.*/) + .sendKeyUp(2) .sendCarriageReturn() .wait('Choose the default authorization type for the API') .send(KEY_DOWN_ARROW) @@ -148,10 +159,9 @@ export function addAuthViaAPIWithTrigger(cwd: string, settings: any): Promise { return new Promise((resolve, reject) => { - spawn(getCLIPath(), ['add', 'api'], { cwd, stripColors: true }) + spawn(getCLIPath(defaultOptions.testingWithLatestCodebase), ['add', 'api'], { cwd, stripColors: true }) .wait('Please select from one of the below mentioned services:') .sendCarriageReturn() - .wait('Provide API name') + .wait(/.*Here is the GraphQL API that we will create. Select a setting to edit or continue.*/) + .sendKeyUp(2) .sendCarriageReturn() .wait('Choose the default authorization type for the API') .send(KEY_DOWN_ARROW) @@ -235,10 +246,9 @@ export function addAuthwithUserPoolGroupsViaAPIWithTrigger(cwd: string, settings .sendCarriageReturn() .wait('Do you want to edit your add-to-group function now?') .sendConfirmNo() - .wait(/.*Do you want to configure advanced settings for the GraphQL API.*/) - .sendCarriageReturn() - .wait('Do you have an annotated GraphQL schema?') + .wait(/.*Configure additional auth types.*/) .sendConfirmNo() + .wait(/.*Here is the GraphQL API that we will create. Select a setting to edit or continue.*/) .sendCarriageReturn() .wait('Choose a schema template:') .sendCarriageReturn() diff --git a/packages/amplify-e2e-core/src/init/initProjectHelper.ts b/packages/amplify-e2e-core/src/init/initProjectHelper.ts index 0a942b3e89e..fac3d5b5908 100644 --- a/packages/amplify-e2e-core/src/init/initProjectHelper.ts +++ b/packages/amplify-e2e-core/src/init/initProjectHelper.ts @@ -2,6 +2,7 @@ import { nspawn as spawn, getCLIPath, singleSelect, addCircleCITags } from '..'; import { KEY_DOWN_ARROW } from '../utils'; import { amplifyRegions } from '../configure'; import { EOL } from 'os'; +import { v4 as uuid } from 'uuid'; const defaultSettings = { name: EOL, @@ -45,6 +46,8 @@ export function initJSProjectWithProfile(cwd: string, settings?: Partial 20) console.warn('Project names should not be longer than 20 characters. This may cause tests to break.'); + return new Promise((resolve, reject) => { const chain = spawn(getCLIPath(), cliArgs, { cwd, stripColors: true, env, disableCIDetection: s.disableCIDetection }) .wait('Enter a name for the project') @@ -130,6 +133,12 @@ export function initAndroidProjectWithProfile(cwd: string, settings: Object): Pr }); } +export function createRandomName() { + const length = 20; + const regExp = new RegExp('-', 'g'); + return uuid().replace(regExp, '').substring(0, length); +} + export function initIosProjectWithProfile(cwd: string, settings: Object): Promise { const s = { ...defaultSettings, ...settings }; diff --git a/packages/amplify-e2e-tests/schemas/model_with_sandbox_mode.graphql b/packages/amplify-e2e-tests/schemas/model_with_sandbox_mode.graphql new file mode 100644 index 00000000000..22c833e9c67 --- /dev/null +++ b/packages/amplify-e2e-tests/schemas/model_with_sandbox_mode.graphql @@ -0,0 +1,6 @@ +type AMPLIFY_GLOBAL @allow_public_data_access_with_api_key(in: "dev") + +type Todo @model { + id: ID! + content: String +} diff --git a/packages/amplify-e2e-tests/src/__tests__/api_1.test.ts b/packages/amplify-e2e-tests/src/__tests__/api_1.test.ts index e20b226cab2..206dfea857a 100644 --- a/packages/amplify-e2e-tests/src/__tests__/api_1.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/api_1.test.ts @@ -4,7 +4,7 @@ import { deleteProject, initFlutterProjectWithProfile, initJSProjectWithProfile, - addApiWithSchema, + addApiWithoutSchema, updateApiSchema, updateApiWithMultiAuth, createNewProjectDir, @@ -22,6 +22,7 @@ import { getBackendAmplifyMeta, amplifyPushUpdateForDependentModel, amplifyPushForce, + createRandomName, } from 'amplify-e2e-core'; import path from 'path'; import { existsSync } from 'fs'; @@ -30,8 +31,10 @@ import _ from 'lodash'; describe('amplify add api (GraphQL)', () => { let projRoot: string; + let projFolderName: string; beforeEach(async () => { - projRoot = await createNewProjectDir('graphql-api'); + projFolderName = 'graphqlapi'; + projRoot = await createNewProjectDir(projFolderName); }); afterEach(async () => { @@ -44,8 +47,10 @@ describe('amplify add api (GraphQL)', () => { it('init a project and add the simple_model api', async () => { const envName = 'devtest'; - await initJSProjectWithProfile(projRoot, { name: 'simplemodel', envName }); - await addApiWithSchema(projRoot, 'simple_model.graphql'); + const projName = 'simplemodel'; + await initJSProjectWithProfile(projRoot, { name: projName, envName }); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projName, 'simple_model.graphql'); await amplifyPush(projRoot); const meta = getProjectMeta(projRoot); @@ -74,8 +79,10 @@ describe('amplify add api (GraphQL)', () => { it('init a project then add and remove api', async () => { const envName = 'devtest'; - await initIosProjectWithProfile(projRoot, { name: 'simplemodel', envName }); - await addApiWithSchema(projRoot, 'simple_model.graphql'); + const projName = 'simplemodel'; + await initIosProjectWithProfile(projRoot, { name: projName, envName }); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projName, 'simple_model.graphql'); await amplifyPush(projRoot); let meta = getProjectMeta(projRoot); @@ -98,8 +105,10 @@ describe('amplify add api (GraphQL)', () => { it('init a Flutter project and add the simple_model api', async () => { const envName = 'devtest'; - await initFlutterProjectWithProfile(projRoot, { name: 'simplemodel', envName }); - await addApiWithSchema(projRoot, 'simple_model.graphql'); + const projName = 'simplemodel'; + await initFlutterProjectWithProfile(projRoot, { name: projName, envName }); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projName, 'simple_model.graphql'); await amplifyPushWithoutCodegen(projRoot); const meta = getProjectMeta(projRoot); @@ -132,7 +141,8 @@ describe('amplify add api (GraphQL)', () => { const initialSchema = 'initial_key_blog.graphql'; const nextSchema = 'next_key_blog.graphql'; await initJSProjectWithProfile(projRoot, { name: projectName }); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); updateApiSchema(projRoot, projectName, nextSchema); await amplifyPushUpdate(projRoot); @@ -145,13 +155,15 @@ describe('amplify add api (GraphQL)', () => { }); it('init a project and add the simple_model api with multiple authorization providers', async () => { - await initJSProjectWithProfile(projRoot, { name: 'simplemodelmultiauth' }); - await addApiWithSchema(projRoot, 'simple_model.graphql'); + const appName = createRandomName(); + await initJSProjectWithProfile(projRoot, { name: appName }); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, appName, 'simple_model.graphql'); await updateApiWithMultiAuth(projRoot, {}); await amplifyPush(projRoot); const meta = getProjectMeta(projRoot); - const { output } = meta.api.simplemodelmultiauth; + const { output } = meta.api[appName]; const { GraphQLAPIIdOutput, GraphQLAPIEndpointOutput, GraphQLAPIKeyOutput } = output; const { graphqlApi } = await getAppSyncApi(GraphQLAPIIdOutput, meta.providers.awscloudformation.Region); @@ -189,7 +201,8 @@ describe('amplify add api (GraphQL)', () => { it('init a project and add the simple_model api, match transformer version to current version', async () => { const name = `simplemodelv${TRANSFORM_CURRENT_VERSION}`; await initJSProjectWithProfile(projRoot, { name }); - await addApiWithSchema(projRoot, 'simple_model.graphql'); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, name, 'simple_model.graphql'); await amplifyPush(projRoot); const meta = getProjectMeta(projRoot); @@ -217,7 +230,8 @@ describe('amplify add api (GraphQL)', () => { const initialSchema = 'two-model-schema.graphql'; const fnName = `integtestfn${random}`; await initJSProjectWithProfile(projRoot, { name: projectName }); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await addFunction( projRoot, { @@ -264,7 +278,8 @@ describe('amplify add api (GraphQL)', () => { it('api force push with no changes', async () => { const projectName = `apinochange`; await initJSProjectWithProfile(projRoot, { name: projectName }); - await addApiWithSchema(projRoot, 'two-model-schema.graphql'); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, 'two-model-schema.graphql'); await amplifyPush(projRoot); let meta = getBackendAmplifyMeta(projRoot); const { lastPushDirHash: beforeDirHash } = meta.api[projectName]; diff --git a/packages/amplify-e2e-tests/src/__tests__/api_2.test.ts b/packages/amplify-e2e-tests/src/__tests__/api_2.test.ts index 968bff75d5e..0462834fe81 100644 --- a/packages/amplify-e2e-tests/src/__tests__/api_2.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/api_2.test.ts @@ -1,37 +1,37 @@ import { + addApiWithBlankSchemaAndConflictDetection, + addApiWithoutSchema, + addFunction, + addRestApi, + addSimpleDDB, amplifyPush, - amplifyPushUpdate, - deleteProject, + amplifyPushUpdate, + apiDisableDataStore, + apiEnableDataStore, + checkIfBucketExists, + createNewProjectDir, + deleteProject, + deleteProjectDir, + enableAdminUI, + getAppSyncApi, + getLocalEnvInfo, + getProjectMeta, + getTransformConfig, initJSProjectWithProfile, listAttachedRolePolicies, listRolePolicies, + updateApiSchema, + updateAPIWithResolutionStrategyWithModels, updateAuthAddAdminQueries, } from 'amplify-e2e-core'; -import * as path from 'path'; -import { existsSync, readFileSync, readdirSync, writeFileSync } from 'fs'; import AWSAppSyncClient, { AUTH_TYPE } from 'aws-appsync'; +import { existsSync, readdirSync, readFileSync, writeFileSync } from 'fs'; import gql from 'graphql-tag'; -const providerName = 'awscloudformation'; - -import { - addApiWithSchema, - addApiWithSchemaAndConflictDetection, - addRestApi, - updateAPIWithResolutionStrategy, - apiUpdateToggleDataStore, - addFunction, - addSimpleDDB, - checkIfBucketExists, - createNewProjectDir, - deleteProjectDir, - getAppSyncApi, - getProjectMeta, - getLocalEnvInfo, - getTransformConfig, - enableAdminUI, -} from 'amplify-e2e-core'; import { TRANSFORM_CURRENT_VERSION } from 'graphql-transformer-core'; import _ from 'lodash'; +import * as path from 'path'; +const providerName = 'awscloudformation'; + // to deal with bug in cognito-identity-js (global as any).fetch = require('node-fetch'); @@ -55,7 +55,8 @@ describe('amplify add api (GraphQL)', () => { it('init a project with conflict detection enabled and a schema with @key, test update mutation', async () => { const name = `keyconflictdetection`; await initJSProjectWithProfile(projRoot, { name }); - await addApiWithSchemaAndConflictDetection(projRoot, 'key-conflict-detection.graphql'); + await addApiWithBlankSchemaAndConflictDetection(projRoot); + await updateApiSchema(projRoot, name, 'key-conflict-detection.graphql'); await amplifyPush(projRoot); const meta = getProjectMeta(projRoot); @@ -139,7 +140,8 @@ describe('amplify add api (GraphQL)', () => { it('init a project with conflict detection enabled and toggle disable', async () => { const name = `conflictdetection`; await initJSProjectWithProfile(projRoot, { name }); - await addApiWithSchemaAndConflictDetection(projRoot, 'simple_model.graphql'); + await addApiWithBlankSchemaAndConflictDetection(projRoot); + await updateApiSchema(projRoot, name, 'simple_model.graphql'); await amplifyPush(projRoot); @@ -165,7 +167,7 @@ describe('amplify add api (GraphQL)', () => { expect(transformConfig.ResolverConfig.project.ConflictHandler).toEqual('AUTOMERGE'); // remove datastore feature - await apiUpdateToggleDataStore(projRoot, {}); + await apiDisableDataStore(projRoot, {}); await amplifyPushUpdate(projRoot); const disableDSConfig = getTransformConfig(projRoot, name); expect(disableDSConfig).toBeDefined(); @@ -188,7 +190,8 @@ describe('amplify add api (GraphQL)', () => { // setupAdminUI await enableAdminUI(appId, envName, region); - await addApiWithSchemaAndConflictDetection(projRoot, 'simple_model.graphql'); + await addApiWithBlankSchemaAndConflictDetection(projRoot); + await updateApiSchema(projRoot, name, 'simple_model.graphql'); await amplifyPush(projRoot); meta = getProjectMeta(projRoot); @@ -209,7 +212,8 @@ describe('amplify add api (GraphQL)', () => { it('init a sync enabled project and update conflict resolution strategy', async () => { const name = `syncenabled`; await initJSProjectWithProfile(projRoot, { name }); - await addApiWithSchemaAndConflictDetection(projRoot, 'simple_model.graphql'); + await addApiWithBlankSchemaAndConflictDetection(projRoot); + await updateApiSchema(projRoot, name, 'simple_model.graphql'); let transformConfig = getTransformConfig(projRoot, name); expect(transformConfig).toBeDefined(); @@ -218,7 +222,7 @@ describe('amplify add api (GraphQL)', () => { expect(transformConfig.ResolverConfig.project.ConflictDetection).toEqual('VERSION'); expect(transformConfig.ResolverConfig.project.ConflictHandler).toEqual('AUTOMERGE'); - await updateAPIWithResolutionStrategy(projRoot, {}); + await updateAPIWithResolutionStrategyWithModels(projRoot, {}); transformConfig = getTransformConfig(projRoot, name); expect(transformConfig).toBeDefined(); @@ -246,7 +250,8 @@ describe('amplify add api (GraphQL)', () => { it('init a datastore enabled project and then remove datastore config in update', async () => { const name = 'withoutdatastore'; await initJSProjectWithProfile(projRoot, { name }); - await addApiWithSchema(projRoot, 'simple_model.graphql'); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, name, 'simple_model.graphql'); await amplifyPush(projRoot); const meta = getProjectMeta(projRoot); @@ -267,7 +272,7 @@ describe('amplify add api (GraphQL)', () => { expect(_.isEmpty(withoutDSConfig.ResolverConfig)).toBe(true); // amplify update api to enable datastore - await apiUpdateToggleDataStore(projRoot, {}); + await apiEnableDataStore(projRoot, {}); let transformConfigWithDS = getTransformConfig(projRoot, name); expect(transformConfigWithDS).toBeDefined(); expect(transformConfigWithDS.ResolverConfig).toBeDefined(); diff --git a/packages/amplify-e2e-tests/src/__tests__/api_3.test.ts b/packages/amplify-e2e-tests/src/__tests__/api_3.test.ts index 266fafd3423..6a426c246a7 100644 --- a/packages/amplify-e2e-tests/src/__tests__/api_3.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/api_3.test.ts @@ -8,7 +8,8 @@ import { updateHeadlessApi, getProjectSchema, removeHeadlessApi, - addApiWithSchema, + addApiWithoutSchema, + updateApiSchema, createNewProjectDir, deleteProjectDir, getAppSyncApi, @@ -39,8 +40,8 @@ describe('amplify add api (GraphQL)', () => { it('init a project and add the simple_model api, change transformer version to base version and push', async () => { const name = `simplemodelv${TRANSFORM_BASE_VERSION}`; await initJSProjectWithProfile(projRoot, { name }); - await addApiWithSchema(projRoot, 'simple_model.graphql'); - + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, name, 'simple_model.graphql'); const transformConfig = getTransformConfig(projRoot, name); expect(transformConfig).toBeDefined(); expect(transformConfig.Version).toBeDefined(); diff --git a/packages/amplify-e2e-tests/src/__tests__/api_4.test.ts b/packages/amplify-e2e-tests/src/__tests__/api_4.test.ts index 177f658d14e..338fac8d53a 100644 --- a/packages/amplify-e2e-tests/src/__tests__/api_4.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/api_4.test.ts @@ -1,5 +1,6 @@ import { - addApiWithSchema, + addApiWithoutSchema, + updateApiSchema, amplifyPush, createNewProjectDir, deleteProject, @@ -31,7 +32,8 @@ describe('multi-key GSI behavior', () => { beforeEach(async () => { projRoot = await createNewProjectDir(projName); await initJSProjectWithProfile(projRoot, { name: projName }); - await addApiWithSchema(projRoot, 'multi-gsi.graphql'); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projName, 'multi-gsi.graphql'); await amplifyPush(projRoot); appSyncClient = getAppSyncClientFromProj(projRoot); diff --git a/packages/amplify-e2e-tests/src/__tests__/api_5.test.ts b/packages/amplify-e2e-tests/src/__tests__/api_5.test.ts index e17e45de418..7d80c569814 100644 --- a/packages/amplify-e2e-tests/src/__tests__/api_5.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/api_5.test.ts @@ -14,11 +14,7 @@ import gql from 'graphql-tag'; const providerName = 'awscloudformation'; import { - addApiWithSchema, - addApiWithSchemaAndConflictDetection, addRestApi, - updateAPIWithResolutionStrategy, - apiUpdateToggleDataStore, addFunction, addSimpleDDB, checkIfBucketExists, diff --git a/packages/amplify-e2e-tests/src/__tests__/feature-flags.test.ts b/packages/amplify-e2e-tests/src/__tests__/feature-flags.test.ts index 14cf60fab36..9f68cbe9a58 100644 --- a/packages/amplify-e2e-tests/src/__tests__/feature-flags.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/feature-flags.test.ts @@ -1,5 +1,5 @@ import * as fs from 'fs-extra'; -import { initJSProjectWithProfile, deleteProject, addApiWithSchema, amplifyPush, amplifyPull, getAppId } from 'amplify-e2e-core'; +import { initJSProjectWithProfile, deleteProject, addApiWithoutSchema, updateApiSchema, amplifyPush, amplifyPull, getAppId } from 'amplify-e2e-core'; import { createNewProjectDir, deleteProjectDir } from 'amplify-e2e-core'; import { pathManager } from 'amplify-cli-core'; import { addEnvironment } from '../environment/env'; @@ -24,9 +24,11 @@ describe('feature flags', () => { it('push and pull with multiple config files for environments', async () => { await initJSProjectWithProfile(projRoot, { + name: 'apifeatureflag', disableAmplifyAppCreation: false, }); - await addApiWithSchema(projRoot, 'simple_model.graphql'); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, 'apifeatureflag', 'simple_model.graphql'); const envName = 'test'; const cliJSONPath = pathManager.getCLIJSONFilePath(projRoot); diff --git a/packages/amplify-e2e-tests/src/__tests__/function_1.test.ts b/packages/amplify-e2e-tests/src/__tests__/function_1.test.ts index 793eebb1f93..391a9ddb32b 100644 --- a/packages/amplify-e2e-tests/src/__tests__/function_1.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/function_1.test.ts @@ -3,7 +3,7 @@ import { addFunction, functionBuild, addLambdaTrigger } from 'amplify-e2e-core'; import { addSimpleDDB } from 'amplify-e2e-core'; import { addKinesis } from 'amplify-e2e-core'; import { createNewProjectDir, deleteProjectDir, getProjectMeta, getFunction } from 'amplify-e2e-core'; -import { addApiWithSchema } from 'amplify-e2e-core'; +import { addApiWithoutSchema, updateApiSchema } from 'amplify-e2e-core'; import { appsyncGraphQLRequest } from 'amplify-e2e-core'; import { getCloudWatchLogs, putKinesisRecords, invokeFunction, getEventSourceMappings } from 'amplify-e2e-core'; @@ -60,8 +60,11 @@ describe('nodejs', () => { }); it('graphql mutation should result in trigger called in minimal AppSync + trigger infra', async () => { - await initJSProjectWithProfile(projRoot, {}); - await addApiWithSchema(projRoot, 'simple_model.graphql'); + await initJSProjectWithProfile(projRoot, { + name: 'graphqltriggerinfra', + }); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, 'graphqltriggerinfra', 'simple_model.graphql'); await addFunction(projRoot, { functionTemplate: 'Lambda trigger', triggerType: 'DynamoDB' }, 'nodejs', addLambdaTrigger); await functionBuild(projRoot, {}); diff --git a/packages/amplify-e2e-tests/src/__tests__/function_2.test.ts b/packages/amplify-e2e-tests/src/__tests__/function_2.test.ts index 1eb2c43e7a6..d92fb6842f7 100644 --- a/packages/amplify-e2e-tests/src/__tests__/function_2.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/function_2.test.ts @@ -1,5 +1,6 @@ import { - addApiWithSchema, + addApiWithoutSchema, + updateApiSchema, addApi, addAuthWithDefault, addDDBWithTrigger, @@ -28,9 +29,8 @@ import { addAuthWithGroupsAndAdminAPI, getFunction, loadFunctionTestFile, + createRandomName, } from 'amplify-e2e-core'; -import fs from 'fs-extra'; -import path from 'path'; import _ from 'lodash'; describe('nodejs', () => { @@ -120,14 +120,17 @@ describe('nodejs', () => { }); it('lambda with dynamoDB permissions should be able to scan ddb', async () => { - await initJSProjectWithProfile(projRoot, {}); + await initJSProjectWithProfile(projRoot, { + name: 'dynamodbscan', + }); const random = Math.floor(Math.random() * 10000); const fnName = `integtestfn${random}`; const ddbName = `integtestddb${random}`; // test ability to scan both appsync @model-backed and regular ddb tables - await addApiWithSchema(projRoot, 'simple_model.graphql'); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, 'dynamodbscan', 'simple_model.graphql'); await addSimpleDDB(projRoot, { name: ddbName }); await addFunction( @@ -185,7 +188,10 @@ describe('nodejs', () => { }); it('existing lambda updated with additional permissions should be able to scan ddb', async () => { - await initJSProjectWithProfile(projRoot, {}); + const appName = createRandomName(); + await initJSProjectWithProfile(projRoot, { + name: appName, + }); const random = Math.floor(Math.random() * 10000); const fnName = `integtestfn${random}`; @@ -209,7 +215,8 @@ describe('nodejs', () => { expect(functionName).toBeDefined(); expect(region).toBeDefined(); - await addApiWithSchema(projRoot, 'simple_model.graphql'); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, appName, 'simple_model.graphql'); await updateFunction( projRoot, { @@ -241,8 +248,11 @@ describe('nodejs', () => { }); it('@model-backed lambda function should generate envvars TODOTABLE_NAME, TODOTABLE_ARN, GRAPHQLAPIIDOUTPUT', async () => { - await initJSProjectWithProfile(projRoot, {}); - await addApiWithSchema(projRoot, 'simple_model.graphql'); + await initJSProjectWithProfile(projRoot, { + name: 'modelbackedlambda', + }); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, 'modelbackedlambda', 'simple_model.graphql'); const random = Math.floor(Math.random() * 10000); const fnName = `integtestfn${random}`; diff --git a/packages/amplify-e2e-tests/src/__tests__/function_5.test.ts b/packages/amplify-e2e-tests/src/__tests__/function_5.test.ts index a12eeb99fa0..9bb8ebdd115 100644 --- a/packages/amplify-e2e-tests/src/__tests__/function_5.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/function_5.test.ts @@ -1,6 +1,6 @@ import { addFunction, - addApiWithSchema, + addApiWithoutSchema, amplifyPull, amplifyPushAuth, amplifyPush, @@ -83,9 +83,13 @@ describe('test dependency in root stack', () => { }); it('init a project with api and function and update the @model and add function access to @model ', async () => { - await initJSProjectWithProfile(projRoot, {}); const projectName = 'mytestapi'; - await addApiWithSchema(projRoot, 'simple_model.graphql', { apiName: projectName }); + await initJSProjectWithProfile(projRoot, { + name: projectName, + }); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, 'simple_model.graphql'); + const random = Math.floor(Math.random() * 10000); const fnName = `integtestfn${random}`; await addFunction( diff --git a/packages/amplify-e2e-tests/src/__tests__/function_9.test.ts b/packages/amplify-e2e-tests/src/__tests__/function_9.test.ts index 30e89832eac..cd7df53717e 100644 --- a/packages/amplify-e2e-tests/src/__tests__/function_9.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/function_9.test.ts @@ -1,5 +1,5 @@ import { - addApiWithSchema, + addApiWithoutSchema, addApi, addAuthWithDefault, addDDBWithTrigger, @@ -28,6 +28,8 @@ import { addAuthWithGroupsAndAdminAPI, getFunction, loadFunctionTestFile, + updateApiSchema, + createRandomName, } from 'amplify-e2e-core'; import fs from 'fs-extra'; import path from 'path'; @@ -80,8 +82,12 @@ describe('nodejs', () => { }); it('adding api and storage permissions should not add duplicates to CFN', async () => { - await initJSProjectWithProfile(projRoot, {}); - await addApiWithSchema(projRoot, 'two-model-schema.graphql'); + const appName = createRandomName(); + await initJSProjectWithProfile(projRoot, { + name: appName, + }); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, appName, 'two-model-schema.graphql'); const random = Math.floor(Math.random() * 10000); const fnName = `integtestfn${random}`; @@ -143,8 +149,12 @@ describe('nodejs', () => { }); it('function dependencies should be preserved when not editing permissions during `amplify update function`', async () => { - await initJSProjectWithProfile(projRoot, {}); - await addApiWithSchema(projRoot, 'two-model-schema.graphql'); + const appName = createRandomName(); + await initJSProjectWithProfile(projRoot, { + name: appName, + }); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, appName, 'two-model-schema.graphql'); const random = Math.floor(Math.random() * 10000); const fnName = `integtestfn${random}`; diff --git a/packages/amplify-e2e-tests/src/__tests__/migration/api.connection.migration.test.ts b/packages/amplify-e2e-tests/src/__tests__/migration/api.connection.migration.test.ts index bcbf7ded7de..809aea44e16 100644 --- a/packages/amplify-e2e-tests/src/__tests__/migration/api.connection.migration.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/migration/api.connection.migration.test.ts @@ -1,5 +1,5 @@ import { initJSProjectWithProfile, deleteProject, amplifyPush, amplifyPushUpdate, addFeatureFlag } from 'amplify-e2e-core'; -import { addApiWithSchema, updateApiSchema } from 'amplify-e2e-core'; +import { addApiWithoutSchema, updateApiSchema } from 'amplify-e2e-core'; import { createNewProjectDir, deleteProjectDir } from 'amplify-e2e-core'; describe('amplify add api', () => { @@ -21,7 +21,8 @@ describe('amplify add api', () => { await initJSProjectWithProfile(projRoot, { name: projectName }); addFeatureFlag(projRoot, 'graphqltransformer', 'enableiterativegsiupdates', false); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); updateApiSchema(projRoot, projectName, nextSchema1); await expect( @@ -40,7 +41,8 @@ describe('amplify add api', () => { await initJSProjectWithProfile(projRoot, { name: projectName }); addFeatureFlag(projRoot, 'graphqltransformer', 'enableiterativegsiupdates', false); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); updateApiSchema(projRoot, projectName, nextSchema1); await expect( diff --git a/packages/amplify-e2e-tests/src/__tests__/migration/api.connection.migration2.test.ts b/packages/amplify-e2e-tests/src/__tests__/migration/api.connection.migration2.test.ts index e23854dc03d..4573978141b 100644 --- a/packages/amplify-e2e-tests/src/__tests__/migration/api.connection.migration2.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/migration/api.connection.migration2.test.ts @@ -1,5 +1,5 @@ import { initJSProjectWithProfile, deleteProject, amplifyPush, amplifyPushUpdate, addFeatureFlag } from 'amplify-e2e-core'; -import { addApiWithSchema, updateApiSchema } from 'amplify-e2e-core'; +import { addApiWithoutSchema, updateApiSchema } from 'amplify-e2e-core'; import { createNewProjectDir, deleteProjectDir } from 'amplify-e2e-core'; describe('amplify add api', () => { @@ -21,7 +21,8 @@ describe('amplify add api', () => { await initJSProjectWithProfile(projRoot, { name: projectName }); addFeatureFlag(projRoot, 'graphqltransformer', 'enableiterativegsiupdates', false); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); updateApiSchema(projRoot, projectName, nextSchema1); await expect( @@ -41,7 +42,8 @@ describe('amplify add api', () => { await initJSProjectWithProfile(projRoot, { name: projectName }); addFeatureFlag(projRoot, 'graphqltransformer', 'enableiterativegsiupdates', false); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); updateApiSchema(projRoot, projectName, nextSchema1); await amplifyPushUpdate(projRoot, /GraphQL endpoint:.*/); diff --git a/packages/amplify-e2e-tests/src/__tests__/migration/api.key.migration1.test.ts b/packages/amplify-e2e-tests/src/__tests__/migration/api.key.migration1.test.ts index d323a06dac6..2664f430aa7 100644 --- a/packages/amplify-e2e-tests/src/__tests__/migration/api.key.migration1.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/migration/api.key.migration1.test.ts @@ -1,5 +1,5 @@ import { initJSProjectWithProfile, deleteProject, amplifyPush, amplifyPushUpdate, addFeatureFlag } from 'amplify-e2e-core'; -import { addApiWithSchema, updateApiSchema } from 'amplify-e2e-core'; +import { addApiWithoutSchema, updateApiSchema } from 'amplify-e2e-core'; import { createNewProjectDir, deleteProjectDir } from 'amplify-e2e-core'; describe('amplify add api', () => { @@ -23,7 +23,8 @@ describe('amplify add api', () => { // testing this with old behavior with named lsi key addFeatureFlag(projRoot, 'graphqltransformer', 'secondarykeyasgsi', false); - await addApiWithSchema(projRoot, initialSchema, { apiKeyExpirationDays: 2 }); + await addApiWithoutSchema(projRoot, { apiKeyExpirationDays: 2 }); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); updateApiSchema(projRoot, projectName, nextSchema1); @@ -43,7 +44,8 @@ describe('amplify add api', () => { await initJSProjectWithProfile(projRoot, { name: projectName }); addFeatureFlag(projRoot, 'graphqltransformer', 'enableiterativegsiupdates', false); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); updateApiSchema(projRoot, projectName, nextSchema1); @@ -60,7 +62,8 @@ describe('amplify add api', () => { await initJSProjectWithProfile(projRoot, { name: projectName }); addFeatureFlag(projRoot, 'graphqltransformer', 'enableiterativegsiupdates', false); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); updateApiSchema(projRoot, projectName, nextSchema1); @@ -77,7 +80,8 @@ describe('amplify add api', () => { await initJSProjectWithProfile(projRoot, { name: projectName }); addFeatureFlag(projRoot, 'graphqltransformer', 'enableiterativegsiupdates', false); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); updateApiSchema(projRoot, projectName, nextSchema1); diff --git a/packages/amplify-e2e-tests/src/__tests__/migration/api.key.migration2.test.ts b/packages/amplify-e2e-tests/src/__tests__/migration/api.key.migration2.test.ts index eb7f82e437b..724026221f8 100644 --- a/packages/amplify-e2e-tests/src/__tests__/migration/api.key.migration2.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/migration/api.key.migration2.test.ts @@ -1,5 +1,5 @@ import { initJSProjectWithProfile, deleteProject, amplifyPush, amplifyPushUpdate, addFeatureFlag } from 'amplify-e2e-core'; -import { addApiWithSchema, updateApiSchema, getProjectMeta } from 'amplify-e2e-core'; +import { addApiWithoutSchema, updateApiSchema, getProjectMeta } from 'amplify-e2e-core'; import { createNewProjectDir, deleteProjectDir } from 'amplify-e2e-core'; import { addEnvironment } from '../../environment/env'; @@ -19,7 +19,8 @@ describe('amplify add api', () => { const initial_schema = 'migrations_key/three_gsi_model_schema.graphql'; const nextSchema = 'migrations_key/four_gsi_model_schema.graphql'; await initJSProjectWithProfile(projRoot, { name: projectName }); - await addApiWithSchema(projRoot, initial_schema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initial_schema); await amplifyPush(projRoot); updateApiSchema(projRoot, projectName, nextSchema); @@ -32,7 +33,8 @@ describe('amplify add api', () => { const nextSchema1 = 'migrations_key/cant_change_key_schema.graphql'; await initJSProjectWithProfile(projRoot, { name: projectName }); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); await addEnvironment(projRoot, { envName: 'test' }); updateApiSchema(projRoot, projectName, nextSchema1); @@ -53,7 +55,8 @@ describe('amplify add api', () => { await initJSProjectWithProfile(projRoot, { name: projectName }); addFeatureFlag(projRoot, 'graphqltransformer', 'enableiterativegsiupdates', false); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); updateApiSchema(projRoot, projectName, nextSchema1); @@ -73,7 +76,8 @@ describe('amplify add api', () => { await initJSProjectWithProfile(projRoot, { name: projectName }); addFeatureFlag(projRoot, 'graphqltransformer', 'enableiterativegsiupdates', false); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); updateApiSchema(projRoot, projectName, nextSchema1); @@ -93,7 +97,8 @@ describe('amplify add api', () => { await initJSProjectWithProfile(projRoot, { name: projectName }); addFeatureFlag(projRoot, 'graphqltransformer', 'enableiterativegsiupdates', false); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); updateApiSchema(projRoot, projectName, nextSchema1); await expect( @@ -113,7 +118,8 @@ describe('amplify add api', () => { await initJSProjectWithProfile(projRoot, { name: projectName }); addFeatureFlag(projRoot, 'graphqltransformer', 'enableiterativegsiupdates', false); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); updateApiSchema(projRoot, projectName, nextSchema); @@ -133,7 +139,8 @@ describe('amplify add api', () => { await initJSProjectWithProfile(projRoot, { name: projectName }); addFeatureFlag(projRoot, 'graphqltransformer', 'enableiterativegsiupdates', false); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); updateApiSchema(projRoot, projectName, nextSchema); @@ -148,7 +155,8 @@ describe('amplify add api', () => { await initJSProjectWithProfile(projRoot, { name: projectName }); addFeatureFlag(projRoot, 'graphqltransformer', 'enableiterativegsiupdates', false); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); updateApiSchema(projRoot, projectName, nextSchema1); diff --git a/packages/amplify-e2e-tests/src/__tests__/pull.test.ts b/packages/amplify-e2e-tests/src/__tests__/pull.test.ts index eaba219a335..155ad825f7d 100644 --- a/packages/amplify-e2e-tests/src/__tests__/pull.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/pull.test.ts @@ -1,6 +1,7 @@ import { getAppId, - addApiWithSchema, + addApiWithoutSchema, + updateApiSchema, amplifyPull, amplifyPush, createNewProjectDir, @@ -24,8 +25,12 @@ describe('amplify pull', () => { }); it('pulling twice with noUpdateBackend does not re-prompt', async () => { - await initJSProjectWithProfile(projRoot, { disableAmplifyAppCreation: false }); - await addApiWithSchema(projRoot, 'simple_model.graphql'); + await initJSProjectWithProfile(projRoot, { + disableAmplifyAppCreation: false, + name: 'testapi', + }); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, 'testapi', 'simple_model.graphql'); await amplifyPush(projRoot); const appId = getAppId(projRoot); await amplifyPull(projRoot2, { appId, emptyDir: true, noUpdateBackend: true }); diff --git a/packages/amplify-e2e-tests/src/__tests__/schema-iterative-rollback-1.test.ts b/packages/amplify-e2e-tests/src/__tests__/schema-iterative-rollback-1.test.ts index dd64161cb29..ecaec785943 100644 --- a/packages/amplify-e2e-tests/src/__tests__/schema-iterative-rollback-1.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/schema-iterative-rollback-1.test.ts @@ -7,22 +7,27 @@ import { amplifyPushIterativeRollback, getDDBTable, getBackendAmplifyMeta, - addApiWithSchema, + addApiWithoutSchema, addFeatureFlag, amplifyPush, updateApiSchema, getTableResourceId, getNestedStackID, cancelIterativeAmplifyPush, + createRandomName, } from 'amplify-e2e-core'; // 30-45min describe('Iterative Rollback - add 2 @keys ', () => { let projectDir: string; + let appName: string; beforeAll(async () => { + appName = createRandomName(); projectDir = await createNewProjectDir('iterativeRollback'); - await initJSProjectWithProfile(projectDir, {}); + await initJSProjectWithProfile(projectDir, { + name: appName, + }); addFeatureFlag(projectDir, 'graphqltransformer', 'enableiterativegsiupdates', true); }); afterAll(async () => { @@ -30,15 +35,15 @@ describe('Iterative Rollback - add 2 @keys ', () => { deleteProjectDir(projectDir); }); it('should support rolling back from the 2nd deployment on adding gsis', async () => { - const apiName = 'renamekey'; const initialSchema = path.join('iterative-push', 'two-key-add', 'initial-schema.graphql'); - await addApiWithSchema(projectDir, initialSchema, { apiName, apiKeyExpirationDays: 7 }); + await addApiWithoutSchema(projectDir, { apiKeyExpirationDays: 7 }); + await updateApiSchema(projectDir, appName, initialSchema); await amplifyPush(projectDir); // get info on table const meta = getBackendAmplifyMeta(projectDir); const { StackId: stackId, Region: region } = meta.providers.awscloudformation; - const { logicalId } = meta.api[apiName].providerMetadata; + const { logicalId } = meta.api[appName].providerMetadata; const apiID = await getNestedStackID(stackId, region, logicalId); const tableName = await getTableResourceId(region, 'Record', apiID); let table = await getDDBTable(tableName, region); @@ -46,7 +51,7 @@ describe('Iterative Rollback - add 2 @keys ', () => { expect(table.Table.GlobalSecondaryIndexes).toBeUndefined(); const finalSchema = path.join('iterative-push', 'two-key-add', 'final-schema.graphql'); - updateApiSchema(projectDir, apiName, finalSchema); + updateApiSchema(projectDir, appName, finalSchema); // cancel iterative push on 2nd deployment await cancelIterativeAmplifyPush(projectDir, { current: 2, max: 3 }); diff --git a/packages/amplify-e2e-tests/src/__tests__/schema-iterative-rollback-2.test.ts b/packages/amplify-e2e-tests/src/__tests__/schema-iterative-rollback-2.test.ts index fda5124dc18..3175875a28f 100644 --- a/packages/amplify-e2e-tests/src/__tests__/schema-iterative-rollback-2.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/schema-iterative-rollback-2.test.ts @@ -7,21 +7,26 @@ import { amplifyPushIterativeRollback, getDDBTable, getBackendAmplifyMeta, - addApiWithSchema, + addApiWithoutSchema, addFeatureFlag, amplifyPush, updateApiSchema, getTableResourceId, getNestedStackID, cancelIterativeAmplifyPush, + createRandomName, } from 'amplify-e2e-core'; describe('Iterative Rollback - removing two @keys', () => { let projectDir: string; + let appName: string; beforeAll(async () => { + appName = createRandomName(); projectDir = await createNewProjectDir('iterativeRollback'); - await initJSProjectWithProfile(projectDir, {}); + await initJSProjectWithProfile(projectDir, { + name: appName, + }); addFeatureFlag(projectDir, 'graphqltransformer', 'enableiterativegsiupdates', true); }); afterAll(async () => { @@ -29,15 +34,15 @@ describe('Iterative Rollback - removing two @keys', () => { deleteProjectDir(projectDir); }); it('should support rolling back from the 2nd deployment on adding gsis', async () => { - const apiName = 'renamekey'; const initialSchema = path.join('iterative-push', 'multiple-key-delete', 'initial-schema.graphql'); - await addApiWithSchema(projectDir, initialSchema, { apiName, apiKeyExpirationDays: 7 }); + await addApiWithoutSchema(projectDir, { apiKeyExpirationDays: 7 }); + await updateApiSchema(projectDir, appName, initialSchema); await amplifyPush(projectDir); // get info on table const meta = getBackendAmplifyMeta(projectDir); const { StackId: stackId, Region: region } = meta.providers.awscloudformation; - const { logicalId } = meta.api[apiName].providerMetadata; + const { logicalId } = meta.api[appName].providerMetadata; const apiID = await getNestedStackID(stackId, region, logicalId); const tableName = await getTableResourceId(region, 'Something', apiID); let table = await getDDBTable(tableName, region); @@ -46,7 +51,7 @@ describe('Iterative Rollback - removing two @keys', () => { expect(table.Table.GlobalSecondaryIndexes.length).toEqual(2); const finalSchema = path.join('iterative-push', 'multiple-key-delete', 'final-schema.graphql'); - updateApiSchema(projectDir, apiName, finalSchema); + updateApiSchema(projectDir, appName, finalSchema); // cancel iterative push on 2nd deployment await cancelIterativeAmplifyPush(projectDir, { current: 2, max: 3 }); diff --git a/packages/amplify-e2e-tests/src/__tests__/schema-iterative-update-1.test.ts b/packages/amplify-e2e-tests/src/__tests__/schema-iterative-update-1.test.ts index 2c4109c2b8b..ad7679da174 100644 --- a/packages/amplify-e2e-tests/src/__tests__/schema-iterative-update-1.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/schema-iterative-update-1.test.ts @@ -4,19 +4,24 @@ import { initJSProjectWithProfile, deleteProject, deleteProjectDir, - addApiWithSchema, + addApiWithoutSchema, addFeatureFlag, amplifyPush, updateApiSchema, amplifyPushUpdate, + createRandomName, } from 'amplify-e2e-core'; describe('Schema iterative update - rename @key', () => { let projectDir: string; + let appName: string; beforeAll(async () => { + appName = createRandomName(); projectDir = await createNewProjectDir('schemaIterative'); - await initJSProjectWithProfile(projectDir, {}); + await initJSProjectWithProfile(projectDir, { + name: appName, + }); addFeatureFlag(projectDir, 'graphqltransformer', 'enableiterativegsiupdates', true); }); @@ -25,14 +30,13 @@ describe('Schema iterative update - rename @key', () => { deleteProjectDir(projectDir); }); it('should support changing gsi name', async () => { - const apiName = 'renamekey'; - const initialSchema = path.join('iterative-push', 'change-model-name', 'initial-schema.graphql'); - await addApiWithSchema(projectDir, initialSchema, { apiName, apiKeyExpirationDays: 7 }); + await addApiWithoutSchema(projectDir, { apiKeyExpirationDays: 7 }); + await updateApiSchema(projectDir, appName, initialSchema); await amplifyPush(projectDir); const finalSchema = path.join('iterative-push', 'change-model-name', 'final-schema.graphql'); - await updateApiSchema(projectDir, apiName, finalSchema); + await updateApiSchema(projectDir, appName, finalSchema); await amplifyPushUpdate(projectDir); }); }); diff --git a/packages/amplify-e2e-tests/src/__tests__/schema-iterative-update-3.test.ts b/packages/amplify-e2e-tests/src/__tests__/schema-iterative-update-3.test.ts index 31fd211f241..1878135d8ef 100644 --- a/packages/amplify-e2e-tests/src/__tests__/schema-iterative-update-3.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/schema-iterative-update-3.test.ts @@ -4,7 +4,7 @@ import { initJSProjectWithProfile, deleteProject, deleteProjectDir, - addApiWithSchema, + addApiWithoutSchema, addFeatureFlag, amplifyPush, updateApiSchema, @@ -16,7 +16,9 @@ describe('Schema iterative update - delete', () => { beforeAll(async () => { projectDir = await createNewProjectDir('schemaIterative'); - await initJSProjectWithProfile(projectDir, {}); + await initJSProjectWithProfile(projectDir, { + name: 'deletekeys', + }); addFeatureFlag(projectDir, 'graphqltransformer', 'enableiterativegsiupdates', true); }); @@ -28,7 +30,8 @@ describe('Schema iterative update - delete', () => { const apiName = 'deletekeys'; const initialSchema = path.join('iterative-push', 'multiple-key-delete', 'initial-schema.graphql'); - await addApiWithSchema(projectDir, initialSchema, { apiName, apiKeyExpirationDays: 7 }); + await addApiWithoutSchema(projectDir, { apiKeyExpirationDays: 7 }); + await updateApiSchema(projectDir, apiName, initialSchema); await amplifyPush(projectDir); const finalSchema = path.join('iterative-push', 'multiple-key-delete', 'final-schema.graphql'); diff --git a/packages/amplify-e2e-tests/src/__tests__/schema-iterative-update-4.test.ts b/packages/amplify-e2e-tests/src/__tests__/schema-iterative-update-4.test.ts index a83805997a0..6f1a0bb1180 100644 --- a/packages/amplify-e2e-tests/src/__tests__/schema-iterative-update-4.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/schema-iterative-update-4.test.ts @@ -4,7 +4,7 @@ import { initJSProjectWithProfile, deleteProject, deleteProjectDir, - addApiWithSchema, + addApiWithoutSchema, addFeatureFlag, amplifyPush, updateApiSchema, @@ -16,7 +16,9 @@ describe('Schema iterative update - create update and delete', () => { beforeAll(async () => { projectDir = await createNewProjectDir('schemaIterative'); - await initJSProjectWithProfile(projectDir, {}); + await initJSProjectWithProfile(projectDir, { + name: 'iterativetest1', + }); addFeatureFlag(projectDir, 'graphqltransformer', 'enableiterativegsiupdates', true); }); @@ -28,7 +30,8 @@ describe('Schema iterative update - create update and delete', () => { const apiName = 'iterativetest1'; const initialSchema = path.join('iterative-push', 'add-remove-and-update-key', 'initial-schema.graphql'); - await addApiWithSchema(projectDir, initialSchema, { apiName, apiKeyExpirationDays: 7 }); + await addApiWithoutSchema(projectDir, { apiKeyExpirationDays: 7 }); + await updateApiSchema(projectDir, apiName, initialSchema); await amplifyPush(projectDir); const finalSchema = path.join('iterative-push', 'add-remove-and-update-key', 'final-schema.graphql'); diff --git a/packages/amplify-e2e-tests/src/__tests__/schema-iterative-update-locking.test.ts b/packages/amplify-e2e-tests/src/__tests__/schema-iterative-update-locking.test.ts index 1fe5aefa131..d0ea8a4818b 100644 --- a/packages/amplify-e2e-tests/src/__tests__/schema-iterative-update-locking.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/schema-iterative-update-locking.test.ts @@ -4,7 +4,7 @@ import { initJSProjectWithProfile, deleteProject, deleteProjectDir, - addApiWithSchema, + addApiWithoutSchema, addFeatureFlag, amplifyPush, updateApiSchema, @@ -24,6 +24,7 @@ describe('Schema iterative update - locking', () => { projectRoot = await createNewProjectDir('schemaIterativeLock'); await initJSProjectWithProfile(projectRoot, { + name: 'iterlock', disableAmplifyAppCreation: false, }); @@ -40,7 +41,8 @@ describe('Schema iterative update - locking', () => { // Create and push project with API const initialSchema = path.join('iterative-push', 'change-model-name', 'initial-schema.graphql'); - await addApiWithSchema(projectRoot, initialSchema, { apiName, apiKeyExpirationDays: 7 }); + await addApiWithoutSchema(projectRoot, { apiKeyExpirationDays: 7 }); + await updateApiSchema(projectRoot, apiName, initialSchema); await amplifyPush(projectRoot); // Apply updates to first project diff --git a/packages/amplify-e2e-tests/src/__tests__/schema-key.test.ts b/packages/amplify-e2e-tests/src/__tests__/schema-key.test.ts index f58c885e7e0..4b95ddd3114 100644 --- a/packages/amplify-e2e-tests/src/__tests__/schema-key.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/schema-key.test.ts @@ -1,12 +1,14 @@ -import { initJSProjectWithProfile, deleteProject, createNewProjectDir, deleteProjectDir } from 'amplify-e2e-core'; +import { initJSProjectWithProfile, deleteProject, createNewProjectDir, deleteProjectDir, createRandomName } from 'amplify-e2e-core'; import { testSchema } from '../schema-api-directives'; describe('api directives @key', () => { let projectDir: string; + let appName: string; beforeEach(async () => { + appName = createRandomName(); projectDir = await createNewProjectDir('key'); - await initJSProjectWithProfile(projectDir, {}); + await initJSProjectWithProfile(projectDir, { name: appName }); }); afterEach(async () => { @@ -30,7 +32,7 @@ describe('api directives @key', () => { }); it('key SelectiveSync with key directive', async () => { - const testresult = await testSchema(projectDir, 'key', 'howTo4'); + const testresult = await testSchema(projectDir, 'key', 'howTo4', appName); expect(testresult).toBeTruthy(); }); }); diff --git a/packages/amplify-e2e-tests/src/schema-api-directives/index.ts b/packages/amplify-e2e-tests/src/schema-api-directives/index.ts index db52c93a9b4..d54d6b03b70 100644 --- a/packages/amplify-e2e-tests/src/schema-api-directives/index.ts +++ b/packages/amplify-e2e-tests/src/schema-api-directives/index.ts @@ -13,7 +13,7 @@ import { runFunctionTest } from './functionTester'; // to deal with subscriptions in node env (global as any).WebSocket = require('ws'); -export async function testSchema(projectDir: string, directive: string, section: string): Promise { +export async function testSchema(projectDir: string, directive: string, section: string, appName?: string): Promise { let testModule; const testFilePath = path.join(__dirname, 'tests', `${directive}-${section}.ts`); @@ -29,7 +29,7 @@ export async function testSchema(projectDir: string, directive: string, section: try { if (testModule.runTest) { - await testModule.runTest(projectDir, testModule); + await testModule.runTest(projectDir, testModule, appName); } else { switch (directive) { case 'auth': diff --git a/packages/amplify-e2e-tests/src/schema-api-directives/tests/key-howTo4.ts b/packages/amplify-e2e-tests/src/schema-api-directives/tests/key-howTo4.ts index 9c5398c0c14..266432014a1 100644 --- a/packages/amplify-e2e-tests/src/schema-api-directives/tests/key-howTo4.ts +++ b/packages/amplify-e2e-tests/src/schema-api-directives/tests/key-howTo4.ts @@ -1,5 +1,5 @@ import _ from 'lodash'; -import { addApiWithSchemaAndConflictDetection, amplifyPush } from 'amplify-e2e-core'; +import { addApiWithBlankSchemaAndConflictDetection, amplifyPush, updateApiSchema } from 'amplify-e2e-core'; import { getApiKey, configureAmplify, getConfiguredAppsyncClientAPIKeyAuth } from '../authHelper'; import { testQueries, testMutations } from '../common'; @@ -269,8 +269,9 @@ export const expected_result_query5 = { }, }; -export async function runTest(projectDir: string, testModule: any) { - await addApiWithSchemaAndConflictDetection(projectDir, testModule.schemaName); +export async function runTest(projectDir: string, testModule: any, appName: string) { + await addApiWithBlankSchemaAndConflictDetection(projectDir); + await updateApiSchema(projectDir, appName, testModule.schemaName); await amplifyPush(projectDir); const awsconfig = configureAmplify(projectDir); diff --git a/packages/amplify-graphql-auth-transformer/.npmignore b/packages/amplify-graphql-auth-transformer/.npmignore new file mode 100644 index 00000000000..3ee5d55b0b8 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/.npmignore @@ -0,0 +1,5 @@ +**/__mocks__/** +**/__tests__/** +src +tsconfig.json +tsconfig.tsbuildinfo diff --git a/packages/amplify-graphql-auth-transformer/CHANGELOG.md b/packages/amplify-graphql-auth-transformer/CHANGELOG.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/amplify-graphql-auth-transformer/package.json b/packages/amplify-graphql-auth-transformer/package.json new file mode 100644 index 00000000000..a298804f5c1 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/package.json @@ -0,0 +1,67 @@ +{ + "name": "@aws-amplify/graphql-auth-transformer", + "version": "0.1.0", + "description": "Amplify GraphQL @auth Transformer", + "repository": { + "type": "git", + "url": "https://github.com/aws-amplify/amplify-cli.git", + "directory": "packages/amplify-graphql-auth-transformer" + }, + "author": "Amazon Web Services", + "license": "Apache-2.0", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "keywords": [ + "graphql", + "cloudformation", + "aws", + "amplify" + ], + "publishConfig": { + "access": "public" + }, + "scripts": { + "test": "jest", + "build": "tsc", + "clean": "rimraf ./lib", + "watch": "tsc -w" + }, + "dependencies": { + "@aws-amplify/graphql-transformer-core": "0.9.2", + "@aws-amplify/graphql-transformer-interfaces": "1.10.0", + "@aws-amplify/graphql-model-transformer": "0.6.4", + "@aws-cdk/aws-appsync": "~1.124.0", + "@aws-cdk/aws-dynamodb": "~1.124.0", + "@aws-cdk/core": "~1.124.0", + "@aws-cdk/aws-iam": "~1.124.0", + "constructs": "^3.3.125", + "graphql": "^14.5.8", + "graphql-mapping-template": "4.18.3", + "graphql-transformer-common": "4.19.10", + "lodash": "^4.17.21" + }, + "devDependencies": { + "@aws-amplify/graphql-index-transformer": "0.4.0", + "@aws-amplify/graphql-relational-transformer": "0.3.1", + "@aws-amplify/graphql-searchable-transformer": "0.6.3", + "@types/fs-extra": "^8.0.1", + "@aws-cdk/assert": "~1.124.0", + "@types/node": "^12.12.6" + }, + "jest": { + "testURL": "http://localhost", + "transform": { + "^.+\\.tsx?$": "ts-jest" + }, + "testRegex": "(src/__tests__/.*.test.ts)$", + "moduleFileExtensions": [ + "ts", + "tsx", + "js", + "jsx", + "json", + "node" + ], + "collectCoverage": true + } +} diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/__snapshots__/field-auth-argument.test.ts.snap b/packages/amplify-graphql-auth-transformer/src/__tests__/__snapshots__/field-auth-argument.test.ts.snap new file mode 100644 index 00000000000..0a0706bd49e --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/__snapshots__/field-auth-argument.test.ts.snap @@ -0,0 +1,40 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`per-field @auth without @model 1`] = ` +Object { + "Properties": Object { + "Description": "", + "Path": "/", + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "appsync:GraphQL", + "Effect": "Allow", + "Resource": Object { + "Fn::Sub": Array [ + "arn:aws:appsync:\${AWS::Region}:\${AWS::AccountId}:apis/\${apiId}/types/\${typeName}/fields/\${fieldName}", + Object { + "apiId": Object { + "Fn::GetAtt": Array [ + "GraphQLAPI", + "ApiId", + ], + }, + "fieldName": "listContext", + "typeName": "Query", + }, + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "Roles": Array [ + Object { + "Ref": "authRoleName", + }, + ], + }, + "Type": "AWS::IAM::ManagedPolicy", +} +`; diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/accesscontrol.test.ts b/packages/amplify-graphql-auth-transformer/src/__tests__/accesscontrol.test.ts new file mode 100644 index 00000000000..6aa2d0e9ecf --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/accesscontrol.test.ts @@ -0,0 +1,112 @@ +import { AccessControlMatrix } from '../accesscontrol'; +import { MODEL_OPERATIONS } from '../utils'; + +test('test access control on object and field', () => { + /* + given the following schema + type Student + @model + @auth(rules: [ + { allow: groups, groups: ["admin"] } + { allow: groups, groups: ["student"], operations: [read] } + ]) { + studentID: ID + name: String + #acm protect email only studentID can update their own email + email: AWSEmail @auth(rules: [ + { allow: owner, ownerField: "studentID", operations: [update] } + { allow: groups, groups: ["admin"] } + ]) + # only allowed to student and admin + ssn: String @auth(rules: [ + { allow: owner, ownerField: "studentID", operations: [read] } + { allow: groups, groups: ["admin"] } + ]) + } + */ + // create an acm for the student type + const adminRole = 'userPools:staticGroup:admin'; + const studentGroupRole = 'userPools:staticGroup:student'; + const studentOwnerRole = 'userPools:owner:studentID'; + const studentTypeFields = ['studentID', 'name', 'email', 'ssn']; + const acm = new AccessControlMatrix({ + resources: studentTypeFields, + operations: MODEL_OPERATIONS, + }); + // add OBJECT rules first + // add admin role which has full access on all CRUD operations for all fields + acm.setRole({ + role: adminRole, + operations: MODEL_OPERATIONS, + }); + // add the student static group rule which only has read access + acm.setRole({ + role: studentGroupRole, + operations: ['read'], + }); + + studentTypeFields.forEach(field => { + // check that admin has CRUD access on all fields + expect(acm.isAllowed(adminRole, field, 'create')).toBe(true); + expect(acm.isAllowed(adminRole, field, 'read')).toBe(true); + expect(acm.isAllowed(adminRole, field, 'update')).toBe(true); + expect(acm.isAllowed(adminRole, field, 'delete')).toBe(true); + // check that studentGroupRole has access to read only + expect(acm.isAllowed(studentGroupRole, field, 'read')).toBe(true); + expect(acm.isAllowed(studentGroupRole, field, 'create')).toBe(false); + expect(acm.isAllowed(studentGroupRole, field, 'update')).toBe(false); + expect(acm.isAllowed(studentGroupRole, field, 'delete')).toBe(false); + }); + // when adding a field rule on email we need to overwrite it + acm.resetAccessForResource('email'); + + expect(acm.isAllowed(studentGroupRole, 'email', 'read')).toBe(false); + acm.setRole({ + role: studentOwnerRole, + operations: ['update'], + resource: 'email', + }); + expect(acm.isAllowed(adminRole, 'email', 'update')).toBe(false); + expect(acm.isAllowed(studentOwnerRole, 'email', 'update')).toBe(true); +}); + +test('test access control only on field', () => { + /* + given the following schema + type Student + @model { + studentID: ID + name: String + # only allows read access on email and ssn for studentID ownerfield can also only update email + email: AWSEmail @auth(rules: [ + { allow: owner, ownerField: "studentID", operations: [read, update] } + ]) + ssn: String @auth(rules: [ + { allow: owner, ownerField: "studentID", operations: [read] } + ]) + } + */ + // create an acm for the student type + const studentOwnerRole = 'userPools:owner:studentID'; + const studentTypeFields = ['studentID', 'name', 'email', 'ssn']; + const acm = new AccessControlMatrix({ + resources: studentTypeFields, + operations: MODEL_OPERATIONS, + }); + // set role for email field + acm.setRole({ role: studentOwnerRole, operations: ['read', 'update'], resource: 'email' }); + // set role for ssn field + acm.setRole({ role: studentOwnerRole, operations: ['read'], resource: 'ssn' }); + + // expect the correct permissions are assigned for email field + expect(acm.isAllowed(studentOwnerRole, 'email', 'update')).toBe(true); + expect(acm.isAllowed(studentOwnerRole, 'email', 'read')).toBe(true); + expect(acm.isAllowed(studentOwnerRole, 'email', 'delete')).toBe(false); + expect(acm.isAllowed(studentOwnerRole, 'email', 'create')).toBe(false); + + // expect the correct permissions are assigned for ssn field + expect(acm.isAllowed(studentOwnerRole, 'ssn', 'create')).toBe(false); + expect(acm.isAllowed(studentOwnerRole, 'ssn', 'read')).toBe(true); + expect(acm.isAllowed(studentOwnerRole, 'ssn', 'update')).toBe(false); + expect(acm.isAllowed(studentOwnerRole, 'ssn', 'delete')).toBe(false); +}); 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 new file mode 100644 index 00000000000..ce358a0143e --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/amplify-admin-auth.test.ts @@ -0,0 +1,337 @@ +import { AuthTransformer } from '@aws-amplify/graphql-auth-transformer'; +import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'; +import { GraphQLTransform } from '@aws-amplify/graphql-transformer-core'; +import _ from 'lodash'; + +test('test simple model with public auth rule and amplify admin app is present', () => { + const validSchema = ` + type Post @model @auth(rules: [{allow: public}]) { + id: ID! + title: String! + createdAt: String + updatedAt: String + }`; + const transformer = new GraphQLTransform({ + authConfig: { + defaultAuthentication: { + authenticationType: 'API_KEY', + }, + additionalAuthenticationProviders: [ + { + authenticationType: 'AWS_IAM', + }, + ], + }, + transformers: [ + new ModelTransformer(), + new AuthTransformer({ + addAwsIamAuthInOutputSchema: true, + adminUserPoolID: 'us-fake-1_uuid', + }), + ], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + expect(out.schema).toContain('Post @aws_api_key @aws_iam'); +}); + +test('Test simple model with public auth rule and amplify admin app is not enabled', () => { + const validSchema = ` + type Post @model @auth(rules: [{allow: public}]) { + id: ID! + title: String! + createdAt: String + updatedAt: String + } + `; + const transformer = new GraphQLTransform({ + authConfig: { + defaultAuthentication: { + authenticationType: 'API_KEY', + }, + additionalAuthenticationProviders: [], + }, + transformers: [ + new ModelTransformer(), + new AuthTransformer({ + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + expect(out.schema).not.toContain('Post @aws_api_key @aws_iam'); +}); + +test('Test model with public auth rule without all operations and amplify admin app is present', () => { + const validSchema = ` + type Post @model @auth(rules: [{allow: public, operations: [read, update]}]) { + id: ID! + title: String! + createdAt: String + updatedAt: String + } + `; + const transformer = new GraphQLTransform({ + authConfig: { + defaultAuthentication: { + authenticationType: 'API_KEY', + }, + additionalAuthenticationProviders: [ + { + authenticationType: 'AWS_IAM', + }, + ], + }, + transformers: [ + new ModelTransformer(), + new AuthTransformer({ + addAwsIamAuthInOutputSchema: true, + adminUserPoolID: 'us-fake-1_uuid', + }), + ], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + + expect(out.schema).toContain('type Post @aws_iam @aws_api_key'); + expect(out.schema).toContain('createPost(input: CreatePostInput!, condition: ModelPostConditionInput): Post @aws_api_key @aws_iam'); + expect(out.schema).toContain('updatePost(input: UpdatePostInput!, condition: ModelPostConditionInput): Post @aws_api_key @aws_iam'); + expect(out.schema).toContain('deletePost(input: DeletePostInput!, condition: ModelPostConditionInput): Post @aws_api_key @aws_iam'); + + // No Resource extending Auth and UnAuth role + const policyResources = Object.values(out.rootStack.Resources!).filter(r => r.Type === 'AWS::IAM::ManagedPolicy'); + expect(policyResources).toHaveLength(0); +}); + +test('Test simple model with private auth rule and amplify admin app is present', () => { + const validSchema = ` + type Post @model @auth(rules: [{allow: groups, groups: ["Admin", "Dev"]}]) { + id: ID! + title: String! + createdAt: String + updatedAt: String + } + `; + const transformer = new GraphQLTransform({ + authConfig: { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [ + { + authenticationType: 'AWS_IAM', + }, + ], + }, + transformers: [ + new ModelTransformer(), + new AuthTransformer({ + addAwsIamAuthInOutputSchema: true, + adminUserPoolID: 'us-fake-1_uuid', + }), + ], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + expect(out.schema).toContain('type Post @aws_iam @aws_cognito_user_pools'); +}); + +test('Test simple model with private auth rule and amplify admin app not enabled', () => { + const validSchema = ` + type Post @model @auth(rules: [{allow: groups, groups: ["Admin", "Dev"]}]) { + id: ID! + title: String! + createdAt: String + updatedAt: String + } + `; + const transformer = new GraphQLTransform({ + authConfig: { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [ + { + authenticationType: 'AWS_IAM', + }, + ], + }, + transformers: [ + new ModelTransformer(), + new AuthTransformer({ + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + expect(out.schema).not.toContain('type Post @aws_iam @aws_cognito_user_pools'); +}); + +test('Test simple model with private auth rule, few operations, and amplify admin app enabled', () => { + const validSchema = ` + type Post @model @auth(rules: [{allow: groups, groups: ["Admin", "Dev"], operations: [read]}]) { + id: ID! + title: String! + createdAt: String + updatedAt: String + } + `; + const transformer = new GraphQLTransform({ + authConfig: { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [ + { + authenticationType: 'AWS_IAM', + }, + ], + }, + transformers: [ + new ModelTransformer(), + new AuthTransformer({ + authConfig: { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [ + { + authenticationType: 'AWS_IAM', + }, + ], + }, + addAwsIamAuthInOutputSchema: true, + adminUserPoolID: 'us-fake-1_uuid', + }), + ], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + expect(out.schema).toContain('type Post @aws_iam @aws_cognito_user_pools'); + expect(out.schema).toContain( + 'createPost(input: CreatePostInput!, condition: ModelPostConditionInput): Post @aws_iam @aws_cognito_user_pools', + ); + expect(out.schema).toContain( + 'updatePost(input: UpdatePostInput!, condition: ModelPostConditionInput): Post @aws_iam @aws_cognito_user_pools', + ); + expect(out.schema).toContain( + 'deletePost(input: DeletePostInput!, condition: ModelPostConditionInput): Post @aws_iam @aws_cognito_user_pools', + ); + + // No Resource extending Auth and UnAuth role + const policyResources = Object.values(out.rootStack.Resources!).filter(r => r.Type === 'AWS::IAM::ManagedPolicy'); + expect(policyResources).toHaveLength(0); +}); + +test('Test simple model with private IAM auth rule, few operations, and amplify admin app is not enabled', () => { + const validSchema = ` + type Post @model @auth(rules: [{allow: private, provider: iam, operations: [read]}]) { + id: ID! + title: String! + createdAt: String + updatedAt: String + } + `; + const transformer = new GraphQLTransform({ + authConfig: { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [ + { + authenticationType: 'AWS_IAM', + }, + ], + }, + transformers: [ + new ModelTransformer(), + new AuthTransformer({ + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + expect(out.schema).toContain('Post @aws_iam'); + expect(out.schema).not.toContain( + 'createPost(input: CreatePostInput!, condition: ModelPostConditionInput): Post @aws_iam @aws_cognito_user_pools', + ); + expect(out.schema).not.toContain('deletePost(input: DeletePostInput!): Post @aws_iam'); + expect(out.schema).not.toContain('updatePost(input: UpdatePostInput!): Post @aws_iam'); + + expect(out.schema).toContain('getPost(id: ID!): Post @aws_iam'); + expect(out.schema).toContain('listPosts(filter: ModelPostFilterInput, limit: Int, nextToken: String): ModelPostConnection @aws_iam'); +}); + +test('Test simple model with AdminUI enabled should add IAM policy only for fields that have explicit IAM auth', () => { + const validSchema = ` + type Post @model @auth(rules: [{allow: private, provider: iam, operations: [read]}]) { + id: ID! + title: String! + createdAt: String + updatedAt: String + } + `; + const transformer = new GraphQLTransform({ + authConfig: { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [ + { + authenticationType: 'AWS_IAM', + }, + ], + }, + transformers: [ + new ModelTransformer(), + new AuthTransformer({ + addAwsIamAuthInOutputSchema: true, + adminUserPoolID: 'us-fake-1_uuid', + }), + ], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + expect(out.schema).toContain('Post @aws_iam @aws_cognito_user_pool'); + expect(out.schema).toContain( + 'createPost(input: CreatePostInput!, condition: ModelPostConditionInput): Post @aws_iam @aws_cognito_user_pools', + ); + expect(out.schema).toContain( + 'updatePost(input: UpdatePostInput!, condition: ModelPostConditionInput): Post @aws_iam @aws_cognito_user_pools', + ); + expect(out.schema).toContain( + 'deletePost(input: DeletePostInput!, condition: ModelPostConditionInput): Post @aws_iam @aws_cognito_user_pools', + ); + + expect(out.schema).toContain('getPost(id: ID!): Post @aws_iam'); + expect(out.schema).toContain('listPosts(filter: ModelPostFilterInput, limit: Int, nextToken: String): ModelPostConnection @aws_iam'); + const policyResources = _.filter(out.rootStack.Resources, r => r.Type === 'AWS::IAM::ManagedPolicy'); + expect(policyResources).toHaveLength(1); + const resources = _.get(policyResources, '[0].Properties.PolicyDocument.Statement[0].Resource'); + const typeFieldList = _.map(resources, r => _.get(r, 'Fn::Sub[1]')).map(r => `${_.get(r, 'typeName')}.${_.get(r, 'fieldName', '*')}`); + expect(typeFieldList).toEqual([ + 'Post.*', + 'Query.getPost', + 'Query.listPosts', + 'Mutation.createPost', + 'Mutation.updatePost', + 'Mutation.deletePost', + 'Subscription.onCreatePost', + 'Subscription.onUpdatePost', + 'Subscription.onDeletePost', + ]); + // should throw unauthorized if it's not signed by the admin ui iam role + ['Mutation.createPost.auth.1.req.vtl', 'Mutation.updatePost.auth.1.res.vtl', 'Mutation.deletePost.auth.1.res.vtl'].forEach(r => { + expect(out.pipelineFunctions[r]).toContain( + '#if( $util.authType() == "IAM Authorization" )\n' + + ' #if( $ctx.identity.userArn.contains("us-fake-1_uuid_Full-access/CognitoIdentityCredentials") || $ctx.identity.userArn.contains("us-fake-1_uuid_Manage-only/CognitoIdentityCredentials") )\n' + + ' #return($util.toJson({})\n' + + ' #end\n' + + '$util.unauthorized()\n' + + '#end', + ); + }); +}); 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 new file mode 100644 index 00000000000..5a30bfda709 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/field-auth-argument.test.ts @@ -0,0 +1,118 @@ +import { AuthTransformer } from '@aws-amplify/graphql-auth-transformer'; +import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'; +import { HasManyTransformer } from '@aws-amplify/graphql-relational-transformer'; +import { GraphQLTransform } from '@aws-amplify/graphql-transformer-core'; +import { ResourceConstants } from 'graphql-transformer-common'; +import { AppSyncAuthConfiguration } from '@aws-amplify/graphql-transformer-interfaces'; + +test('subscriptions are only generated if the respective mutation operation exists', () => { + const validSchema = ` + type Salary + @model + @auth(rules: [ + {allow: owner}, + {allow: groups, groups: ["Moderator"]} + ]) { + id: ID! + wage: Int + owner: String + secret: String @auth(rules: [{allow: owner}]) + }`; + const authConfig: AppSyncAuthConfiguration = { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [], + }; + const transformer = new GraphQLTransform({ + authConfig, + transformers: [ + new ModelTransformer(), + new HasManyTransformer(), + new AuthTransformer({ + authConfig, + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + const out = transformer.transform(validSchema); + // expect to generate subscription resolvers for create and update only + expect(out).toBeDefined(); + expect(out.rootStack.Resources[ResourceConstants.RESOURCES.GraphQLAPILogicalID].Properties.AuthenticationType).toEqual( + 'AMAZON_COGNITO_USER_POOLS', + ); + expect(out.pipelineFunctions['Salary.secret.res.vtl']).toContain('#if( $operation == "Mutation" )'); + + expect(out.pipelineFunctions['Mutation.createSalary.res.vtl']).toContain('$util.qr($ctx.result.put("__operation", "Mutation"))'); + expect(out.pipelineFunctions['Mutation.updateSalary.res.vtl']).toContain('$util.qr($ctx.result.put("__operation", "Mutation"))'); + expect(out.pipelineFunctions['Mutation.deleteSalary.res.vtl']).toContain('$util.qr($ctx.result.put("__operation", "Mutation"))'); +}); + +test('per-field auth on relational field', () => { + const validSchema = ` + type Post @model @auth(rules: [ { allow: groups, groups: ["admin"] }, { allow: groups, groups: ["viewer"], operations: [read] } ]){ + id: ID! + title: String! + comments: [Comment] @hasMany @auth(rules: [ { allow: groups, groups: ["admin"] } ]) + } + + type Comment @model { + id: ID! + content: String + }`; + const authConfig: AppSyncAuthConfiguration = { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [{ authenticationType: 'AWS_IAM' }], + }; + const transformer = new GraphQLTransform({ + authConfig, + transformers: [ + new ModelTransformer(), + new HasManyTransformer(), + new AuthTransformer({ + authConfig, + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + + expect(out.pipelineFunctions['Post.comments.auth.1.req.vtl']).toContain( + '#set( $staticGroupRoles = [{"claim":"cognito:groups","entity":"admin"}] )', + ); +}); + +test('per-field @auth without @model', () => { + const validSchema = ` + type Query { + listContext: String @auth(rules: [{ allow: groups, groups: ["Allowed"] }, { allow: private, provider: iam }]) + }`; + const authConfig: AppSyncAuthConfiguration = { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [{ authenticationType: 'AWS_IAM' }], + }; + const transformer = new GraphQLTransform({ + authConfig, + transformers: [ + new ModelTransformer(), + new AuthTransformer({ + authConfig, + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + + const resources = out.rootStack.Resources; + const authPolicyIdx = Object.keys(out.rootStack.Resources).find(r => r.includes('AuthRolePolicy')); + expect(resources[authPolicyIdx]).toMatchSnapshot(); + expect(out.pipelineFunctions['Query.listContext.req.vtl']).toContain( + '#set( $staticGroupRoles = [{"claim":"cognito:groups","entity":"Allowed"}] )', + ); +}); 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 new file mode 100644 index 00000000000..6bf8f548ac8 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/group-auth.test.ts @@ -0,0 +1,97 @@ +import { AuthTransformer } from '@aws-amplify/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'; +import { AppSyncAuthConfiguration } from '@aws-amplify/graphql-transformer-interfaces'; + +test('happy case with static groups', () => { + const authConfig: AppSyncAuthConfiguration = { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [], + }; + const validSchema = ` + type Post @model @auth(rules: [{allow: groups, groups: ["Admin", "Dev"]}]) { + id: ID! + title: String! + createdAt: String + updatedAt: String + }`; + const transformer = new GraphQLTransform({ + authConfig, + transformers: [ + new ModelTransformer(), + new AuthTransformer({ + authConfig, + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + expect(out.rootStack!.Resources![ResourceConstants.RESOURCES.GraphQLAPILogicalID].Properties.AuthenticationType).toEqual( + 'AMAZON_COGNITO_USER_POOLS', + ); +}); + +test('happy case with dynamic groups', () => { + const authConfig: AppSyncAuthConfiguration = { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [], + }; + const validSchema = ` + type Post @model @auth(rules: [{allow: groups, groupsField: "groups"}]) { + id: ID! + title: String! + groups: [String] + createdAt: String + updatedAt: String + } + `; + const transformer = new GraphQLTransform({ + authConfig, + transformers: [ + new ModelTransformer(), + new AuthTransformer({ + authConfig, + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + expect(out.rootStack!.Resources![ResourceConstants.RESOURCES.GraphQLAPILogicalID].Properties.AuthenticationType).toEqual( + 'AMAZON_COGNITO_USER_POOLS', + ); +}); + +test('validation on @auth on a non-@model type', () => { + const authConfig: AppSyncAuthConfiguration = { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [], + }; + const invalidSchema = ` + type Post @auth(rules: [{allow: groups, groupsField: "groups"}]) { + id: ID! + title: String! + group: String + createdAt: String + updatedAt: String + }`; + const transformer = new GraphQLTransform({ + authConfig, + transformers: [ + new ModelTransformer(), + new AuthTransformer({ + authConfig, + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + expect(() => transformer.transform(invalidSchema)).toThrowError('Types annotated with @auth must also be annotated with @model.'); +}); 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 new file mode 100644 index 00000000000..620824ea105 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/multi-auth.test.ts @@ -0,0 +1,683 @@ +import { AuthTransformer } from '@aws-amplify/graphql-auth-transformer'; +import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'; +import { IndexTransformer } from '@aws-amplify/graphql-index-transformer'; +import { HasManyTransformer, HasOneTransformer, BelongsToTransformer } from '@aws-amplify/graphql-relational-transformer'; +import { GraphQLTransform } from '@aws-amplify/graphql-transformer-core'; +import { AppSyncAuthConfiguration, AppSyncAuthConfigurationOIDCEntry, AppSyncAuthMode } from '@aws-amplify/graphql-transformer-interfaces'; +import { DocumentNode, ObjectTypeDefinitionNode, Kind, FieldDefinitionNode, parse, InputValueDefinitionNode } from 'graphql'; + +const userPoolsDefaultConfig: AppSyncAuthConfiguration = { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [], +}; + +const apiKeyDefaultConfig: AppSyncAuthConfiguration = { + defaultAuthentication: { + authenticationType: 'API_KEY', + }, + additionalAuthenticationProviders: [], +}; + +const iamDefaultConfig: AppSyncAuthConfiguration = { + defaultAuthentication: { + authenticationType: 'AWS_IAM', + }, + additionalAuthenticationProviders: [], +}; + +const withAuthModes = (authConfig: AppSyncAuthConfiguration, authModes: AppSyncAuthMode[]): AppSyncAuthConfiguration => { + const newAuthConfig = { + defaultAuthentication: { + authenticationType: authConfig.defaultAuthentication.authenticationType, + }, + additionalAuthenticationProviders: [], + }; + + for (const authMode of authModes) { + newAuthConfig.additionalAuthenticationProviders.push({ + authenticationType: authMode, + }); + } + + return newAuthConfig; +}; + +const apiKeyDirectiveName = 'aws_api_key'; +const userPoolsDirectiveName = 'aws_cognito_user_pools'; +const iamDirectiveName = 'aws_iam'; +const openIdDirectiveName = 'aws_oidc'; + +const multiAuthDirective = + '@auth(rules: [{allow: private}, {allow: public}, {allow: private, provider: iam }, {allow: owner, provider: oidc }])'; +const ownerAuthDirective = '@auth(rules: [{allow: owner}])'; +const ownerWithIAMAuthDirective = '@auth(rules: [{allow: owner, provider: iam }])'; +const ownerRestrictedPublicAuthDirective = '@auth(rules: [{allow: owner},{allow: public, operations: [read]}])'; +const ownerRestrictedIAMPrivateAuthDirective = '@auth(rules: [{allow: owner},{allow: private, operations: [read], provider: iam }])'; +const groupsAuthDirective = '@auth(rules: [{allow: groups, groups: ["admin"] }])'; +const groupsWithApiKeyAuthDirective = '@auth(rules: [{allow: groups, groups: ["admin"]}, {allow: public, operations: [read]}])'; +const groupsWithProviderAuthDirective = '@auth(rules: [{allow: groups,groups: ["admin"], provider: iam }])'; +const ownerOpenIdAuthDirective = '@auth(rules: [{allow: owner, provider: oidc }])'; +const privateAuthDirective = '@auth(rules: [{allow: private}])'; +const publicIAMAuthDirective = '@auth(rules: [{allow: public, provider: iam }])'; +const privateWithApiKeyAuthDirective = '@auth(rules: [{allow: private, provider: apiKey }])'; +const publicAuthDirective = '@auth(rules: [{allow: public}])'; +const publicUserPoolsAuthDirective = '@auth(rules: [{allow: public, provider: userPools}])'; +const privateAndPublicDirective = '@auth(rules: [{allow: private}, {allow: public}])'; +const privateIAMDirective = '@auth(rules: [{allow: private, provider: iam}])'; +// const privateAndPrivateIAMDirective = '@auth(rules: [{allow: private}, {allow: private, provider: iam}])'; + +const getSchema = (authDirective: string) => { + return ` + type Post @model ${authDirective} { + id: ID! + title: String! + createdAt: String + updatedAt: String + }`; +}; + +const getSchemaWithFieldAuth = (authDirective: string) => { + return ` + type Post @model { + id: ID + title: String + createdAt: String + updatedAt: String + protected: String ${authDirective} + }`; +}; + +const getSchemaWithTypeAndFieldAuth = (typeAuthDirective: string, fieldAuthDirective: string) => { + return ` + type Post @model ${typeAuthDirective} { + id: ID + title: String + createdAt: String + updatedAt: String + protected: String ${fieldAuthDirective} + }`; +}; + +const getSchemaWithNonModelField = (authDirective: string) => { + return ` + type Post @model ${authDirective} { + id: ID! + title: String! + location: Location + status: Status + createdAt: String + updatedAt: String + } + + type Location { + name: String + address: Address + } + + type Address { + street: String + city: String + state: String + zip: String + } + + enum Status { + PUBLISHED, + DRAFT + }`; +}; + +const getSchemaWithRecursiveNonModelField = (authDirective: string) => { + return ` + type Post @model ${authDirective} { + id: ID! + title: String! + tags: [Tag] + } + + type Tag { + id: ID + tags: [Tag] + } + `; +}; + +const getRecursiveSchemaWithDiffModesOnParentType = (authDir1: string, authDir2: string) => { + return ` + type Post @model ${authDir1} { + id: ID! + title: String! + tags: [Tag] + } + + type Comment @model ${authDir2} { + id: ID! + content: String + tags: [Tag] + } + + type Tag { + id: ID + tags: [Tag] + } + `; +}; + +const getTransformer = (authConfig: AppSyncAuthConfiguration) => + new GraphQLTransform({ + authConfig, + transformers: [ + new ModelTransformer(), + new IndexTransformer(), + new HasManyTransformer(), + new HasOneTransformer(), + new BelongsToTransformer(), + new AuthTransformer({ + authConfig, + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + +const getObjectType = (doc: DocumentNode, type: string): ObjectTypeDefinitionNode | undefined => { + return doc.definitions.find(def => def.kind === Kind.OBJECT_TYPE_DEFINITION && def.name.value === type) as + | ObjectTypeDefinitionNode + | undefined; +}; + +const expectNone = fieldOrType => { + expect(fieldOrType.directives.length === 0); +}; + +const expectOne = (fieldOrType, directiveName) => { + expect(fieldOrType.directives.length).toBe(1); + expect(fieldOrType.directives.find(d => d.name.value === directiveName)).toBeDefined(); +}; + +const expectTwo = (fieldOrType, directiveNames) => { + expect(directiveNames).toBeDefined(); + expect(directiveNames).toHaveLength(2); + expect(fieldOrType.directives.length === 2); + expect(fieldOrType.directives.find(d => d.name.value === directiveNames[0])).toBeDefined(); + expect(fieldOrType.directives.find(d => d.name.value === directiveNames[1])).toBeDefined(); +}; + +const expectMultiple = (fieldOrType: ObjectTypeDefinitionNode | FieldDefinitionNode, directiveNames: string[]) => { + expect(directiveNames).toBeDefined(); + expect(directiveNames).toHaveLength(directiveNames.length); + expect(fieldOrType.directives.length).toEqual(directiveNames.length); + directiveNames.forEach(directiveName => { + expect(fieldOrType.directives).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + name: expect.objectContaining({ value: directiveName }), + }), + ]), + ); + }); +}; + +const getField = (type, name) => type.fields.find(f => f.name.value === name); + +describe('validation tests', () => { + const validationTest = (authDirective, authConfig, expectedError) => { + const schema = getSchema(authDirective); + const transformer = getTransformer(authConfig); + + const t = () => { + const out = transformer.transform(schema); + }; + + expect(t).toThrowError(expectedError); + }; + + test('AMAZON_COGNITO_USER_POOLS not configured for project', () => { + validationTest( + privateAuthDirective, + apiKeyDefaultConfig, + `@auth directive with 'userPools' provider found, but the project has no Cognito User \ +Pools authentication provider configured.`, + ); + }); + + test('API_KEY not configured for project', () => { + validationTest( + publicAuthDirective, + userPoolsDefaultConfig, + `@auth directive with 'apiKey' provider found, but the project has no API Key \ +authentication provider configured.`, + ); + }); + + test('AWS_IAM not configured for project', () => { + validationTest( + publicIAMAuthDirective, + userPoolsDefaultConfig, + `@auth directive with 'iam' provider found, but the project has no IAM \ +authentication provider configured.`, + ); + }); + + test('OPENID_CONNECT not configured for project', () => { + validationTest( + ownerOpenIdAuthDirective, + userPoolsDefaultConfig, + `@auth directive with 'oidc' provider found, but the project has no OPENID_CONNECT \ +authentication provider configured.`, + ); + }); + + test(`'group' cannot have provider`, () => { + validationTest( + groupsWithProviderAuthDirective, + userPoolsDefaultConfig, + `@auth directive with 'groups' strategy only supports 'userPools' and 'oidc' providers, but found \ +'iam' assigned`, + ); + }); + + test(`'owner' has invalid IAM provider`, () => { + validationTest( + ownerWithIAMAuthDirective, + userPoolsDefaultConfig, + `@auth directive with 'owner' strategy only supports 'userPools' (default) and \ +'oidc' providers, but found 'iam' assigned.`, + ); + }); + + test(`'public' has invalid 'userPools' provider`, () => { + validationTest( + publicUserPoolsAuthDirective, + userPoolsDefaultConfig, + `@auth directive with 'public' strategy only supports 'apiKey' (default) and 'iam' providers, but \ +found 'userPools' assigned.`, + ); + }); + + test(`'private' has invalid 'apiKey' provider`, () => { + validationTest( + privateWithApiKeyAuthDirective, + userPoolsDefaultConfig, + `@auth directive with 'private' strategy only supports 'userPools' (default) and 'iam' providers, but \ +found 'apiKey' assigned.`, + ); + }); +}); + +describe('schema generation directive tests', () => { + const transformTest = (authDirective, authConfig, expectedDirectiveNames?: string[] | undefined) => { + const schema = getSchema(authDirective); + const transformer = getTransformer(authConfig); + + const out = transformer.transform(schema); + + const schemaDoc = parse(out.schema); + + const postType = getObjectType(schemaDoc, 'Post'); + + if (expectedDirectiveNames && expectedDirectiveNames.length > 0) { + let expectedDireciveNameCount = 0; + + for (const expectedDirectiveName of expectedDirectiveNames) { + expect(postType.directives.find(d => d.name.value === expectedDirectiveName)).toBeDefined(); + expectedDireciveNameCount++; + } + + expect(expectedDireciveNameCount).toEqual(postType.directives.length); + } + }; + + test(`When provider is the same as default, then no directive added`, () => { + transformTest(ownerAuthDirective, userPoolsDefaultConfig); + }); + + test(`When all providers are configured all of them are added`, () => { + const authConfig = withAuthModes(apiKeyDefaultConfig, ['AMAZON_COGNITO_USER_POOLS', 'AWS_IAM', 'OPENID_CONNECT']); + + (authConfig.additionalAuthenticationProviders[2] as AppSyncAuthConfigurationOIDCEntry).openIDConnectConfig = { + name: 'Test Provider', + issuerUrl: 'https://abc.def/', + }; + + transformTest(multiAuthDirective, authConfig, [userPoolsDirectiveName, iamDirectiveName, openIdDirectiveName, apiKeyDirectiveName]); + }); + + test(`Operation fields are getting the directive added, when type has the @auth for all operations`, () => { + const schema = getSchema(ownerAuthDirective); + const transformer = getTransformer(withAuthModes(apiKeyDefaultConfig, ['AMAZON_COGNITO_USER_POOLS'])); + + const out = transformer.transform(schema); + const schemaDoc = parse(out.schema); + const queryType = getObjectType(schemaDoc, 'Query'); + const mutationType = getObjectType(schemaDoc, 'Mutation'); + const subscriptionType = getObjectType(schemaDoc, 'Subscription'); + + const fields = [...queryType.fields, ...mutationType.fields]; + + for (const field of fields) { + expect(field.directives.length === 1); + expect(field.directives.find(d => d.name.value === userPoolsDirectiveName)).toBeDefined(); + } + + // Check that owner is required when only using owner auth rules + for (const field of subscriptionType.fields) { + expect(field.arguments).toHaveLength(1); + let arg: InputValueDefinitionNode = field.arguments[0]; + expect(arg.name.value).toEqual('owner'); + expect(arg.type.kind).toEqual(Kind.NAMED_TYPE); + } + + // Check that resolvers containing the authMode check block + const authStepSnippet = '## [Start] Authorization Steps. **'; + + expect(out.pipelineFunctions['Query.getPost.auth.1.req.vtl']).toContain(authStepSnippet); + expect(out.pipelineFunctions['Query.listPosts.auth.1.req.vtl']).toContain(authStepSnippet); + expect(out.pipelineFunctions['Mutation.createPost.auth.1.req.vtl']).toContain(authStepSnippet); + expect(out.pipelineFunctions['Mutation.createPost.auth.1.req.vtl']).toContain(authStepSnippet); + expect(out.pipelineFunctions['Mutation.updatePost.auth.1.res.vtl']).toContain(authStepSnippet); + expect(out.pipelineFunctions['Mutation.deletePost.auth.1.res.vtl']).toContain(authStepSnippet); + }); + + test(`Operation fields are getting the directive added, when type has the @auth only for allowed operations`, () => { + const schema = getSchema(ownerRestrictedPublicAuthDirective); + const transformer = getTransformer(withAuthModes(apiKeyDefaultConfig, ['AMAZON_COGNITO_USER_POOLS'])); + + const out = transformer.transform(schema); + const schemaDoc = parse(out.schema); + const queryType = getObjectType(schemaDoc, 'Query'); + const mutationType = getObjectType(schemaDoc, 'Mutation'); + const subscriptionType = getObjectType(schemaDoc, 'Subscription'); + + expectTwo(getField(queryType, 'getPost'), ['aws_cognito_user_pools', 'aws_api_key']); + expectTwo(getField(queryType, 'listPosts'), ['aws_cognito_user_pools', 'aws_api_key']); + + expectOne(getField(mutationType, 'createPost'), 'aws_cognito_user_pools'); + expectOne(getField(mutationType, 'updatePost'), 'aws_cognito_user_pools'); + expectOne(getField(mutationType, 'deletePost'), 'aws_cognito_user_pools'); + + const onCreate = getField(subscriptionType, 'onCreatePost'); + expectMultiple(onCreate, ['aws_subscribe', 'aws_api_key', 'aws_cognito_user_pools']); + expectMultiple(getField(subscriptionType, 'onUpdatePost'), ['aws_subscribe', 'aws_api_key', 'aws_cognito_user_pools']); + expectMultiple(getField(subscriptionType, 'onDeletePost'), ['aws_subscribe', 'aws_api_key', 'aws_cognito_user_pools']); + expect(onCreate.arguments).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + name: expect.objectContaining({ value: 'owner' }), + type: expect.objectContaining({ kind: 'NamedType' }), + }), + ]), + ); + }); + + test(`Field level @auth is propagated to type and the type related operations`, () => { + const schema = getSchemaWithFieldAuth(ownerRestrictedPublicAuthDirective); + const transformer = getTransformer(withAuthModes(apiKeyDefaultConfig, ['AMAZON_COGNITO_USER_POOLS'])); + + const out = transformer.transform(schema); + const schemaDoc = parse(out.schema); + const queryType = getObjectType(schemaDoc, 'Query'); + const mutationType = getObjectType(schemaDoc, 'Mutation'); + + expectTwo(getField(queryType, 'getPost'), ['aws_cognito_user_pools', 'aws_api_key']); + expectTwo(getField(queryType, 'listPosts'), ['aws_cognito_user_pools', 'aws_api_key']); + + expectOne(getField(mutationType, 'createPost'), 'aws_cognito_user_pools'); + expectOne(getField(mutationType, 'updatePost'), 'aws_cognito_user_pools'); + // since there is only one field allowed on delete it does not have access to delete + expectNone(getField(mutationType, 'deletePost')); + + // Check that resolvers containing the authMode check block + const authModeCheckSnippet = '## [Start] Field Authorization Steps. **'; + // resolvers to check is all other resolvers other than protected + expect(out.pipelineFunctions['Post.id.req.vtl']).toContain(authModeCheckSnippet); + expect(out.pipelineFunctions['Post.title.req.vtl']).toContain(authModeCheckSnippet); + expect(out.pipelineFunctions['Post.createdAt.req.vtl']).toContain(authModeCheckSnippet); + expect(out.pipelineFunctions['Post.updatedAt.req.vtl']).toContain(authModeCheckSnippet); + }); + + test(`'groups' @auth at field level is propagated to type and the type related operations`, () => { + const schema = getSchemaWithFieldAuth(groupsAuthDirective); + const transformer = getTransformer(withAuthModes(apiKeyDefaultConfig, ['AMAZON_COGNITO_USER_POOLS'])); + + const out = transformer.transform(schema); + const schemaDoc = parse(out.schema); + const queryType = getObjectType(schemaDoc, 'Query'); + const mutationType = getObjectType(schemaDoc, 'Mutation'); + + expectOne(getField(queryType, 'getPost'), 'aws_cognito_user_pools'); + expectOne(getField(queryType, 'listPosts'), 'aws_cognito_user_pools'); + + expectOne(getField(mutationType, 'createPost'), 'aws_cognito_user_pools'); + expectOne(getField(mutationType, 'updatePost'), 'aws_cognito_user_pools'); + // since there is only one field allowed on delete it does not have access to delete + expectNone(getField(mutationType, 'deletePost')); + + // Check that resolvers containing the authMode check block + const authModeCheckSnippet = '## [Start] Field Authorization Steps. **'; + + // resolvers to check is all other resolvers other than protected + expect(out.pipelineFunctions['Post.id.req.vtl']).toContain(authModeCheckSnippet); + expect(out.pipelineFunctions['Post.title.req.vtl']).toContain(authModeCheckSnippet); + expect(out.pipelineFunctions['Post.createdAt.req.vtl']).toContain(authModeCheckSnippet); + expect(out.pipelineFunctions['Post.updatedAt.req.vtl']).toContain(authModeCheckSnippet); + }); + + test(`'groups' @auth at field level is propagated to type and the type related operations, also default provider for read`, () => { + const schema = getSchemaWithTypeAndFieldAuth(groupsAuthDirective, groupsWithApiKeyAuthDirective); + const transformer = getTransformer(withAuthModes(apiKeyDefaultConfig, ['AMAZON_COGNITO_USER_POOLS'])); + + const out = transformer.transform(schema); + const schemaDoc = parse(out.schema); + const queryType = getObjectType(schemaDoc, 'Query'); + const mutationType = getObjectType(schemaDoc, 'Mutation'); + + expectTwo(getField(queryType, 'getPost'), ['aws_cognito_user_pools', 'aws_api_key']); + expectTwo(getField(queryType, 'listPosts'), ['aws_cognito_user_pools', 'aws_api_key']); + + expectOne(getField(mutationType, 'createPost'), 'aws_cognito_user_pools'); + expectOne(getField(mutationType, 'updatePost'), 'aws_cognito_user_pools'); + expectOne(getField(mutationType, 'deletePost'), 'aws_cognito_user_pools'); + + // Check that resolvers containing the authMode group check + const groupCheckSnippet = '#set( $staticGroupRoles = [{"claim":"cognito:groups","entity":"admin"}] )'; + + // resolvers to check is all other resolvers other than protected by the group rule + expect(out.pipelineFunctions['Post.id.req.vtl']).toContain(groupCheckSnippet); + expect(out.pipelineFunctions['Post.title.req.vtl']).toContain(groupCheckSnippet); + expect(out.pipelineFunctions['Post.createdAt.req.vtl']).toContain(groupCheckSnippet); + expect(out.pipelineFunctions['Post.updatedAt.req.vtl']).toContain(groupCheckSnippet); + }); + + test(`Nested types without @model not getting directives applied for iam, and no policy is generated`, () => { + const schema = getSchemaWithNonModelField(''); + const transformer = getTransformer(withAuthModes(iamDefaultConfig, ['AMAZON_COGNITO_USER_POOLS'])); + + const out = transformer.transform(schema); + const schemaDoc = parse(out.schema); + + const locationType = getObjectType(schemaDoc, 'Location'); + const addressType = getObjectType(schemaDoc, 'Address'); + + expect(locationType.directives.length).toBe(0); + expect(addressType.directives.length).toBe(0); + + const authPolicyIdx = Object.keys(out.rootStack.Resources).find(r => r.includes('AuthRolePolicy')); + + expect(out.rootStack.Resources[authPolicyIdx]).toBeUndefined(); + }); + + test(`Nested types without @model not getting directives applied for iam, but policy is generated`, () => { + const schema = getSchemaWithNonModelField(privateIAMDirective); + const transformer = getTransformer(withAuthModes(iamDefaultConfig, ['AMAZON_COGNITO_USER_POOLS'])); + + const out = transformer.transform(schema); + const schemaDoc = parse(out.schema); + + const locationType = getObjectType(schemaDoc, 'Location'); + const addressType = getObjectType(schemaDoc, 'Address'); + + expect(locationType.directives.length).toBe(0); + expect(addressType.directives.length).toBe(0); + + // find the key to account for the hash + const authPolicyIdx = Object.keys(out.rootStack.Resources).find(r => r.includes('AuthRolePolicy01')); + expect(out.rootStack.Resources[authPolicyIdx]).toBeDefined; + const authRolePolicy = out.rootStack.Resources[authPolicyIdx]; + + const locationPolicy = authRolePolicy.Properties.PolicyDocument.Statement[0].Resource.filter( + r => + r['Fn::Sub'] && + r['Fn::Sub'].length && + r['Fn::Sub'].length === 2 && + r['Fn::Sub'][1].typeName && + r['Fn::Sub'][1].typeName === 'Location', + ); + expect(locationPolicy).toHaveLength(1); + + const addressPolicy = authRolePolicy.Properties.PolicyDocument.Statement[0].Resource.filter( + r => + r['Fn::Sub'] && + r['Fn::Sub'].length && + r['Fn::Sub'].length === 2 && + r['Fn::Sub'][1].typeName && + r['Fn::Sub'][1].typeName === 'Address', + ); + expect(addressPolicy).toHaveLength(1); + }); + + test(`Recursive types with diff auth modes on parent @model types`, () => { + const schema = getRecursiveSchemaWithDiffModesOnParentType(ownerAuthDirective, privateIAMDirective); + const transformer = getTransformer(withAuthModes(userPoolsDefaultConfig, ['AWS_IAM'])); + + const out = transformer.transform(schema); + const schemaDoc = parse(out.schema); + + const tagType = getObjectType(schemaDoc, 'Tag'); + const expectedDirectiveNames = [userPoolsDirectiveName, iamDirectiveName]; + + expectMultiple(tagType, expectedDirectiveNames); + }); + + test(`Recursive types without @model`, () => { + const schema = getSchemaWithRecursiveNonModelField(ownerRestrictedIAMPrivateAuthDirective); + const transformer = getTransformer(withAuthModes(userPoolsDefaultConfig, ['AWS_IAM'])); + + const out = transformer.transform(schema); + const schemaDoc = parse(out.schema); + + const tagType = getObjectType(schemaDoc, 'Tag'); + const expectedDirectiveNames = [userPoolsDirectiveName, iamDirectiveName]; + + expectMultiple(tagType, expectedDirectiveNames); + }); + + test(`Nested types without @model getting directives applied (cognito default, api key additional)`, () => { + const schema = getSchemaWithNonModelField(privateAndPublicDirective); + const transformer = getTransformer(withAuthModes(userPoolsDefaultConfig, ['API_KEY'])); + + const out = transformer.transform(schema); + const schemaDoc = parse(out.schema); + + const locationType = getObjectType(schemaDoc, 'Location'); + const addressType = getObjectType(schemaDoc, 'Address'); + const expectedDirectiveNames = [userPoolsDirectiveName, apiKeyDirectiveName]; + + if (expectedDirectiveNames && expectedDirectiveNames.length > 0) { + let expectedDireciveNameCount = 0; + + for (const expectedDirectiveName of expectedDirectiveNames) { + expect(locationType.directives.find(d => d.name.value === expectedDirectiveName)).toBeDefined(); + expectedDireciveNameCount++; + } + + expect(expectedDireciveNameCount).toEqual(locationType.directives.length); + + expectedDireciveNameCount = 0; + + for (const expectedDirectiveName of expectedDirectiveNames) { + expect(addressType.directives.find(d => d.name.value === expectedDirectiveName)).toBeDefined(); + expectedDireciveNameCount++; + } + + expect(expectedDireciveNameCount).toEqual(addressType.directives.length); + } + }); + + test(`ModelXConnection type is getting the directives added, when a field has @hasMany but one fo the types has no queries defined`, () => { + const validSchema = ` + type User @model + @auth(rules: [ + { allow: private, provider: iam, operations: [read] } + { allow: groups, groups: ["group"], operations: [read, update, delete] }, + ]) { + id: ID! + posts: [Post!] @hasMany(indexName: "byUser", fields: ["id"]) + } + type Post @model(queries: null) + @auth(rules: [ + { allow: private, provider: iam, operations: [read] }, + { allow: groups, groups: ["group"], operations: [read, update, delete] } + ]) { + id: ID! + postUserId: ID! @index(name: "byUser") + message: String + }`; + const transformer = getTransformer(withAuthModes(iamDefaultConfig, ['AMAZON_COGNITO_USER_POOLS'])); + const out = transformer.transform(validSchema); + const schemaDoc = parse(out.schema); + const queryType = getObjectType(schemaDoc, 'Query'); + const mutationType = getObjectType(schemaDoc, 'Mutation'); + + expectTwo(getField(queryType, 'getUser'), ['aws_iam', 'aws_cognito_user_pools']); + expectTwo(getField(queryType, 'listUsers'), ['aws_iam', 'aws_cognito_user_pools']); + + expectNone(getField(mutationType, 'createUser')); + expectOne(getField(mutationType, 'updateUser'), 'aws_cognito_user_pools'); + expectOne(getField(mutationType, 'deleteUser'), 'aws_cognito_user_pools'); + + const userType = getObjectType(schemaDoc, 'User'); + expectTwo(userType, ['aws_iam', 'aws_cognito_user_pools']); + expectNone(getField(userType, 'posts')); + + const modelPostConnectionType = getObjectType(schemaDoc, 'ModelPostConnection'); + expect(modelPostConnectionType).toBeDefined(); + expectTwo(modelPostConnectionType, ['aws_iam', 'aws_cognito_user_pools']); + }); + + test(`ModelXConnection type is getting the directives added, when a field has @connection but one of the types has no queries defined. Many to Many`, () => { + const schema = ` + type Post @model @auth(rules: [{ allow: owner }]) { + id: ID! + title: String! + editors: [PostEditor] @hasMany(indexName: "byPost", fields: ["id"]) + } + # Create a join model and disable queries as you don't need them + # and can query through Post.editors and User.posts + type PostEditor + @model(queries: null) + @auth(rules: [{ allow: owner }]) { + id: ID! + postID: ID! @index(name: "byPost", sortKeyFields: ["editorID"]) + editorID: ID! @index(name: "byEditor", sortKeyFields: ["postID"]) + post: Post! @belongsTo(fields: ["postID"]) + editor: User! @belongsTo(fields: ["editorID"]) + } + type User @model @auth(rules: [{ allow: owner }]) { + id: ID! + username: String! + posts: [PostEditor] @hasMany(indexName: "byEditor", fields: ["id"]) + }`; + + const transformer = getTransformer(withAuthModes(apiKeyDefaultConfig, ['AMAZON_COGNITO_USER_POOLS'])); + const out = transformer.transform(schema); + const schemaDoc = parse(out.schema); + + const modelPostEditorConnectionType = getObjectType(schemaDoc, 'ModelPostEditorConnection'); + expect(modelPostEditorConnectionType).toBeDefined(); + // since we have resolver level auth to deny providers the default is added here to ensure the access is granted if the default type is not applied on the parent + // therefore we just need to make sure that the access is at least granted on the schema level + expect(modelPostEditorConnectionType.directives.some(dir => dir.name.value === 'aws_cognito_user_pools')).toBe(true); + }); +}); 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 new file mode 100644 index 00000000000..db5c231707c --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/owner-auth.test.ts @@ -0,0 +1,230 @@ +import { parse } from 'graphql'; +import { AuthTransformer } from '@aws-amplify/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'; +import { getField, getObjectType } from './test-helpers'; +import { AppSyncAuthConfiguration } from '@aws-amplify/graphql-transformer-interfaces'; + +test('auth transformer validation happy case', () => { + const authConfig: AppSyncAuthConfiguration = { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [], + }; + const validSchema = ` + type Post @model @auth(rules: [{allow: owner}]) { + id: ID! + title: String! + createdAt: String + updatedAt: String + }`; + const transformer = new GraphQLTransform({ + authConfig, + transformers: [ + new ModelTransformer(), + new AuthTransformer({ + authConfig, + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + expect(out.rootStack.Resources[ResourceConstants.RESOURCES.GraphQLAPILogicalID].Properties.AuthenticationType).toEqual( + 'AMAZON_COGNITO_USER_POOLS', + ); +}); + +test('ownerfield with subscriptions', () => { + const authConfig: AppSyncAuthConfiguration = { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [], + }; + const validSchema = ` + type Post @model @auth(rules: [ + {allow: owner, ownerField: "postOwner"} + ]){ + id: ID! + title: String + postOwner: String + }`; + const transformer = new GraphQLTransform({ + authConfig, + transformers: [ + new ModelTransformer(), + new AuthTransformer({ + authConfig, + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + + // expect 'postOwner' as an argument for subscription operations + expect(out.schema).toContain('onCreatePost(postOwner: String)'); + expect(out.schema).toContain('onUpdatePost(postOwner: String)'); + expect(out.schema).toContain('onDeletePost(postOwner: String)'); + + // expect logic in the resolvers to check for postOwner args as an allowed owner + expect(out.pipelineFunctions['Subscription.onCreatePost.auth.1.req.vtl']).toContain( + '#set( $ownerEntity0 = $util.defaultIfNull($ctx.args.postOwner, null) )', + ); + expect(out.pipelineFunctions['Subscription.onUpdatePost.auth.1.req.vtl']).toContain( + '#set( $ownerEntity0 = $util.defaultIfNull($ctx.args.postOwner, null) )', + ); + expect(out.pipelineFunctions['Subscription.onDeletePost.auth.1.req.vtl']).toContain( + '#set( $ownerEntity0 = $util.defaultIfNull($ctx.args.postOwner, null) )', + ); +}); + +test('multiple owner rules with subscriptions', () => { + const validSchema = ` + type Post @model + @auth(rules: [ + { allow: owner }, + { allow: owner, ownerField: "editor", operations: [read, update] } + ]) + { + id: ID! + title: String + owner: String + editor: String + }`; + + const authConfig: AppSyncAuthConfiguration = { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [], + }; + const transformer = new GraphQLTransform({ + authConfig, + transformers: [ + new ModelTransformer(), + new AuthTransformer({ + authConfig, + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + + // expect 'owner' and 'editors' as arguments for subscription operations + expect(out.schema).toContain('onCreatePost(owner: String, editor: String)'); + expect(out.schema).toContain('onUpdatePost(owner: String, editor: String)'); + expect(out.schema).toContain('onDeletePost(owner: String, editor: String)'); + + // expect logic in the resolvers to check for owner args as an allowedOwner + expect(out.pipelineFunctions['Subscription.onCreatePost.auth.1.req.vtl']).toContain( + '#set( $ownerEntity0 = $util.defaultIfNull($ctx.args.owner, null) )', + ); + expect(out.pipelineFunctions['Subscription.onUpdatePost.auth.1.req.vtl']).toContain( + '#set( $ownerEntity0 = $util.defaultIfNull($ctx.args.owner, null) )', + ); + expect(out.pipelineFunctions['Subscription.onDeletePost.auth.1.req.vtl']).toContain( + '#set( $ownerEntity0 = $util.defaultIfNull($ctx.args.owner, null) )', + ); + + // expect logic in the resolvers to check for editor args as an allowedOwner + expect(out.pipelineFunctions['Subscription.onCreatePost.auth.1.req.vtl']).toContain( + '#set( $ownerEntity1 = $util.defaultIfNull($ctx.args.editor, null) )', + ); + expect(out.pipelineFunctions['Subscription.onUpdatePost.auth.1.req.vtl']).toContain( + '#set( $ownerEntity1 = $util.defaultIfNull($ctx.args.editor, null) )', + ); + expect(out.pipelineFunctions['Subscription.onDeletePost.auth.1.req.vtl']).toContain( + '#set( $ownerEntity1 = $util.defaultIfNull($ctx.args.editor, null) )', + ); +}); + +test('implicit owner fields get added to the type', () => { + const authConfig: AppSyncAuthConfiguration = { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [], + }; + const transformer = new GraphQLTransform({ + authConfig, + transformers: [ + new ModelTransformer(), + new AuthTransformer({ + authConfig, + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + const validSchema = ` + type Post @model + @auth(rules: [ + {allow: owner, ownerField: "postOwner"} + { allow: owner, ownerField: "customOwner", identityClaim: "sub"} + ]) + { + id: ID! + title: String + } + `; + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + + const schema = parse(out.schema); + const postType = getObjectType(schema, 'Post'); + expect(postType).toBeDefined(); + + const postOwnerField = getField(postType, 'postOwner'); + expect(postOwnerField).toBeDefined(); + expect((postOwnerField as any).type.name.value).toEqual('String'); + + const customOwner = getField(postType, 'customOwner'); + expect(customOwner).toBeDefined(); + expect((customOwner as any).type.name.value).toEqual('String'); +}); + +test('implicit owner fields from field level auth get added to the type', () => { + const validSchema = ` + type Post @model + { + id: ID + title: String + protectedField: String @auth(rules: [ + {allow: owner, ownerField: "postOwner"} + { allow: owner, ownerField: "customOwner", identityClaim: "sub"} + ]) + }`; + const authConfig: AppSyncAuthConfiguration = { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [], + }; + const transformer = new GraphQLTransform({ + authConfig, + transformers: [ + new ModelTransformer(), + new AuthTransformer({ + authConfig, + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + const schema = parse(out.schema); + const postType = getObjectType(schema, 'Post'); + expect(postType).toBeDefined(); + + const postOwnerField = getField(postType, 'postOwner'); + expect(postOwnerField).toBeDefined(); + expect((postOwnerField as any).type.name.value).toEqual('String'); + + const customOwner = getField(postType, 'customOwner'); + expect(customOwner).toBeDefined(); + expect((customOwner as any).type.name.value).toEqual('String'); +}); 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 new file mode 100644 index 00000000000..ee6677bcf10 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/searchable-auth.test.ts @@ -0,0 +1,93 @@ +import { AuthTransformer } from '@aws-amplify/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'; +import { AppSyncAuthConfiguration } from '@aws-amplify/graphql-transformer-interfaces'; + +test('auth logic is enabled on owner/static rules in es request', () => { + const validSchema = ` + type Comment @model + @searchable + @auth(rules: [ + { allow: owner } + { allow: groups, groups: ["writer"]} + ]) + { + id: ID! + content: String + } + `; + const authConfig: AppSyncAuthConfiguration = { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [], + }; + const transformer = new GraphQLTransform({ + authConfig, + transformers: [ + new ModelTransformer(), + new SearchableModelTransformer(), + new AuthTransformer({ + authConfig, + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + const out = transformer.transform(validSchema); + // expect response resolver to contain auth logic for owner rule + expect(out).toBeDefined(); + expect(out.pipelineFunctions['Query.searchComments.auth.1.req.vtl']).toContain( + '"terms": [$util.defaultIfNull($ctx.identity.claims.get("username"), $util.defaultIfNull($ctx.identity.claims.get("cognito:username"), "___xamznone____"))],', + ); + // expect response resolver to contain auth logic for group rule + expect(out.pipelineFunctions['Query.searchComments.auth.1.req.vtl']).toContain( + '#set( $staticGroupRoles = [{"claim":"cognito:groups","entity":"writer"}] )', + ); +}); + +test('auth logic is enabled for iam/apiKey auth rules', () => { + const validSchema = ` + type Post @model + @searchable + @auth(rules: [ + { allow: public, provider: apiKey } # api key is allowed + { allow: private, provider: iam } # auth roles are allowed + ]) { + id: ID! + content: String + secret: String @auth(rules: [{ allow: private, provider: iam }]) # only auth role can do crud on this + } + `; + const authConfig: AppSyncAuthConfiguration = { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [ + { + authenticationType: 'API_KEY', + apiKeyConfig: { + description: 'E2E Test API Key', + apiKeyExpirationDays: 300, + }, + }, + { + authenticationType: 'AWS_IAM', + }, + ], + }; + const transformer = new GraphQLTransform({ + authConfig, + transformers: [ + new ModelTransformer(), + new SearchableModelTransformer(), + new AuthTransformer({ + authConfig, + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + const out = transformer.transform(validSchema); + expect(out).toBeDefined(); + expect(out.schema).toContain('SearchablePostConnection @aws_api_key @aws_iam'); +}); diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/test-helpers.ts b/packages/amplify-graphql-auth-transformer/src/__tests__/test-helpers.ts new file mode 100644 index 00000000000..7b92473311a --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/test-helpers.ts @@ -0,0 +1,10 @@ +import { ObjectTypeDefinitionNode, FieldDefinitionNode, DocumentNode, Kind } from 'graphql'; + +export const getObjectType = (doc: DocumentNode, type: string): ObjectTypeDefinitionNode | undefined => { + return doc.definitions.find(def => def.kind === Kind.OBJECT_TYPE_DEFINITION && def.name.value === type) as + | ObjectTypeDefinitionNode + | undefined; +}; +export const getField = (obj: ObjectTypeDefinitionNode, fieldName: string): FieldDefinitionNode | void => { + return obj.fields?.find(f => f.name.value === fieldName); +}; diff --git a/packages/amplify-graphql-auth-transformer/src/accesscontrol/acm.ts b/packages/amplify-graphql-auth-transformer/src/accesscontrol/acm.ts new file mode 100644 index 00000000000..77166997285 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/accesscontrol/acm.ts @@ -0,0 +1,193 @@ +import assert from 'assert'; + +type ACMConfig = { + resources: string[]; + operations: string[]; +}; + +type SetRoleInput = { + role: string; + operations: Array; + resource?: string; +}; + +type ValidateInput = { + role?: string; + resource?: string; + operations?: Array; +}; + +type ResourceOperationInput = { + operations: Array; + role?: string; + resource?: string; +}; + +/** + * Creates an access control matrix + * The following vectors are used + * - Roles + * - Resources + * - Operations + */ +export class AccessControlMatrix { + private roles: Array; + private operations: Array; + private resources: Array; + private matrix: Array>>; + + constructor(config: ACMConfig) { + this.operations = config.operations; + this.resources = config.resources; + this.matrix = new Array(); + this.roles = new Array(); + } + + public setRole(input: SetRoleInput): void { + const { role, resource, operations } = input; + this.validate({ resource, operations }); + let allowedVector: Array>; + if (!this.roles.includes(role)) { + allowedVector = this.getResourceOperationMatrix({ operations, resource }); + this.roles.push(input.role); + this.matrix.push(allowedVector); + assert(this.roles.length === this.matrix.length, 'Roles are not aligned with Roles added in Matrix'); + } else { + allowedVector = this.getResourceOperationMatrix({ operations, resource, role }); + const roleIndex = this.roles.indexOf(role); + this.matrix[roleIndex] = allowedVector; + } + } + + public hasRole(role: string): boolean { + return this.roles.includes(role); + } + + public getRoles(): Array { + return this.roles; + } + + public getResources(): Readonly> { + return this.resources; + } + + public isAllowed(role: string, resource: string, operation: string): boolean { + this.validate({ role, resource, operations: [operation] }); + const roleIndex = this.roles.indexOf(role); + const resourceIndex = this.resources.indexOf(resource); + const operationIndex = this.operations.indexOf(operation); + return this.matrix[roleIndex][resourceIndex][operationIndex]; + } + + public resetAccessForResource(resource: string): void { + this.validate({ resource }); + const resourceIndex = this.resources.indexOf(resource); + for (let i = 0; i < this.roles.length; i++) { + this.matrix[i][resourceIndex] = new Array(this.operations.length).fill(false); + } + } + + /** + * Given an operation returns the roles which have access to at least one resource + * If fullAccess is true then it returns roles which have operation access on all resources + * @param operation string + * @param fullAccess boolean + * @returns array of roles + */ + public getRolesPerOperation(operation: string, fullAccess: boolean = false): Array { + this.validate({ operations: [operation] }); + const operationIndex = this.operations.indexOf(operation); + const roles = new Array(); + for (let x = 0; x < this.roles.length; x++) { + let hasOperation: boolean = false; + if (fullAccess) { + hasOperation = this.resources.every((resource, idx) => { + return this.matrix[x][idx][operationIndex]; + }); + } else { + hasOperation = this.resources.some((resource, idx) => { + return this.matrix[x][idx][operationIndex]; + }); + } + if (hasOperation) roles.push(this.roles[x]); + } + return roles; + } + + /** + * @returns a map of role and their access + * this object can then be used in console.table() + */ + public getAcmPerRole(): Map { + const acmPerRole: Map = new Map(); + for (let i = 0; i < this.matrix.length; i++) { + let tableObj: any = {}; + for (let y = 0; y < this.matrix[i].length; y++) { + tableObj[this.resources[y]] = this.matrix[i][y].reduce((prev: any, resource: boolean, index: number) => { + prev[this.operations[index]] = resource; + return prev; + }, {}); + } + acmPerRole.set(this.roles[i], tableObj); + } + return acmPerRole; + } + + /** + * helpers + */ + private validate(input: ValidateInput) { + if (input.resource && !this.resources.includes(input.resource)) { + throw Error(`Resource: ${input.resource} is not configued in the ACM`); + } + if (input.role && !this.roles.includes(input.role)) { + throw Error(`Role: ${input.role} does not exist in ACM.`); + } + if (input.operations) { + input.operations.forEach(operation => { + if (this.operations.indexOf(operation) === -1) throw Error(`Operation: ${operation} does not exist in the ACM.`); + }); + } + } + + /** + * + * if singular resource is specified the operations are only applied on the resource + * a denied array for every other resource is returned in the matrix + * @param operations + * @param resource + * @returns a 2d matrix containg the access for each resource + */ + private getResourceOperationMatrix(input: ResourceOperationInput): Array> { + const { operations, resource, role } = input; + let fieldAllowVector: boolean[][] = []; + let operationList: boolean[] = this.getOperationList(operations); + if (role && resource) { + const roleIndex = this.roles.indexOf(role); + const resourceIndex = this.resources.indexOf(resource); + fieldAllowVector = this.matrix[roleIndex]; + fieldAllowVector[resourceIndex] = operationList; + return fieldAllowVector; + } + for (let i = 0; i < this.resources.length; i++) { + if (resource) { + if (this.resources.indexOf(resource) === i) { + fieldAllowVector.push(operationList); + } else { + fieldAllowVector.push(new Array(this.operations.length).fill(false)); + } + } else { + fieldAllowVector.push(operationList); + } + } + return fieldAllowVector; + } + + private getOperationList(operations: Array): Array { + let operationList: Array = new Array(); + for (let operation of this.operations) { + operationList.push(operations.includes(operation)); + } + return operationList; + } +} diff --git a/packages/amplify-graphql-auth-transformer/src/accesscontrol/index.ts b/packages/amplify-graphql-auth-transformer/src/accesscontrol/index.ts new file mode 100644 index 00000000000..e07fbd95541 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/accesscontrol/index.ts @@ -0,0 +1 @@ +export { AccessControlMatrix } from './acm'; diff --git a/packages/amplify-graphql-auth-transformer/src/graphql-auth-transformer.ts b/packages/amplify-graphql-auth-transformer/src/graphql-auth-transformer.ts new file mode 100644 index 00000000000..bd49ca098cd --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/graphql-auth-transformer.ts @@ -0,0 +1,948 @@ +import { + DirectiveWrapper, + TransformerContractError, + TransformerAuthBase, + InvalidDirectiveError, + MappingTemplate, + IAM_AUTH_ROLE_PARAMETER, + IAM_UNAUTH_ROLE_PARAMETER, + TransformerResolver, +} from '@aws-amplify/graphql-transformer-core'; +import { + DataSourceProvider, + MutationFieldType, + QueryFieldType, + TransformerTransformSchemaStepContextProvider, + TransformerContextProvider, + TransformerResolverProvider, + TransformerSchemaVisitStepContextProvider, + TransformerAuthProvider, + TransformerBeforeStepContextProvider, +} from '@aws-amplify/graphql-transformer-interfaces'; +import { + AuthRule, + authDirectiveDefinition, + ConfiguredAuthProviders, + getConfiguredAuthProviders, + AuthTransformerConfig, + collectFieldNames, + DEFAULT_GROUP_CLAIM, + MODEL_OPERATIONS, + ModelOperation, + ensureAuthRuleDefaults, + DEFAULT_IDENTITY_CLAIM, + DEFAULT_GROUPS_FIELD, + DEFAULT_OWNER_FIELD, + getModelConfig, + validateFieldRules, + validateRules, + AuthProvider, + AUTH_PROVIDER_DIRECTIVE_MAP, + extendTypeWithDirectives, + RoleDefinition, + addDirectivesToOperation, + createPolicyDocumentForManagedPolicy, + getQueryFieldNames, + getMutationFieldNames, + addSubscriptionArguments, + fieldIsList, + getSubscriptionFieldNames, + addDirectivesToField, + getSearchableConfig, + getStackForField, + NONE_DS, +} from './utils'; +import { + DirectiveNode, + FieldDefinitionNode, + ObjectTypeDefinitionNode, + InterfaceTypeDefinitionNode, + Kind, + TypeDefinitionNode, +} from 'graphql'; +import { SubscriptionLevel, ModelDirectiveConfiguration } from '@aws-amplify/graphql-model-transformer'; +import { AccessControlMatrix } from './accesscontrol'; +import { getBaseType, makeDirective, makeField, makeNamedType, ResourceConstants } from 'graphql-transformer-common'; +import * as iam from '@aws-cdk/aws-iam'; +import * as cdk from '@aws-cdk/core'; +import { + generateAuthExpressionForCreate, + generateAuthExpressionForUpdate, + generateAuthRequestExpression, + geneateAuthExpressionForDelete, + generateAuthExpressionForField, + generateFieldAuthResponse, + generateAuthExpressionForQueries, + generateAuthExpressionForSubscriptions, +} from './resolvers'; +import { toUpper } from 'graphql-transformer-common'; + +// @ auth +// changing the schema +// - transformSchema +// adding resolver +// - generateResolver +// editing IAM policy +// - generateResolver (cdk) +// resolver mapping + +// resolver.ts for auth pipeline slots + +export class AuthTransformer extends TransformerAuthBase implements TransformerAuthProvider { + private config: AuthTransformerConfig; + private configuredAuthProviders: ConfiguredAuthProviders; + // access control + private roleMap: Map; + private authModelConfig: Map; + private authNonModelConfig: Map; + // model config + private modelDirectiveConfig: Map; + // schema generation + private seenNonModelTypes: Map>; + // iam policy generation + private generateIAMPolicyforUnauthRole: boolean; + private generateIAMPolicyforAuthRole: boolean; + private authPolicyResources = new Set(); + private unauthPolicyResources = new Set(); + + constructor(config: AuthTransformerConfig) { + super('amplify-auth-transformer', authDirectiveDefinition); + this.config = config; + this.modelDirectiveConfig = new Map(); + this.seenNonModelTypes = new Map(); + this.authModelConfig = new Map(); + this.roleMap = new Map(); + this.generateIAMPolicyforUnauthRole = false; + this.generateIAMPolicyforAuthRole = false; + this.authNonModelConfig = new Map(); + } + + before = (context: TransformerBeforeStepContextProvider): void => { + // if there was no auth config in the props we add the authConfig from the context + this.config.authConfig = this.config.authConfig || context.authConfig; + this.configuredAuthProviders = getConfiguredAuthProviders(this.config); + }; + + object = (def: ObjectTypeDefinitionNode, directive: DirectiveNode, context: TransformerSchemaVisitStepContextProvider): void => { + const modelDirective = def.directives?.find(dir => dir.name.value === 'model'); + if (!modelDirective) { + throw new TransformerContractError('Types annotated with @auth must also be annotated with @model.'); + } + const typeName = def.name.value; + const authDir = new DirectiveWrapper(directive); + const rules: AuthRule[] = authDir.getArguments<{ rules: Array }>({ rules: [] }).rules; + ensureAuthRuleDefaults(rules); + // validate rules + validateRules(rules, this.configuredAuthProviders); + // create access control for object + const acm = new AccessControlMatrix({ + operations: MODEL_OPERATIONS, + resources: collectFieldNames(def), + }); + // Check the rules to see if we should generate Auth/Unauth Policies + this.setAuthPolicyFlag(rules); + this.setUnauthPolicyFlag(rules); + // add object into policy + this.addTypeToResourceReferences(def.name.value, rules); + // turn rules into roles and add into acm and roleMap + this.convertRulesToRoles(acm, rules); + this.modelDirectiveConfig.set(typeName, getModelConfig(modelDirective, typeName, context.isProjectUsingDataStore())); + this.authModelConfig.set(typeName, acm); + }; + + field = ( + parent: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode, + field: FieldDefinitionNode, + directive: DirectiveNode, + context: TransformerSchemaVisitStepContextProvider, + ): void => { + if (parent.kind === Kind.INTERFACE_TYPE_DEFINITION) { + throw new InvalidDirectiveError( + `The @auth directive cannot be placed on an interface's field. See ${parent.name.value}${field.name.value}`, + ); + } + const isParentTypeBuiltinType = + parent.name.value === context.output.getQueryTypeName() || + parent.name.value === context.output.getMutationTypeName() || + parent.name.value === context.output.getSubscriptionTypeName(); + + if (isParentTypeBuiltinType) { + console.warn( + `Be careful when using @auth directives on a field in a root type. @auth directives on field definitions use the source \ +object to perform authorization logic and the source will be an empty object for fields on root types. \ +Static group authorization should perform as expected.`, + ); + } + // context.api.host.resolver + // context.resolver -> resolver manager -> dynamodb, relation directives, searchable + // creates field resolver + + const modelDirective = parent.directives?.find(dir => dir.name.value === 'model'); + const typeName = parent.name.value; + const fieldName = field.name.value; + const authDir = new DirectiveWrapper(directive); + const rules: AuthRule[] = authDir.getArguments<{ rules: Array }>({ rules: [] }).rules; + ensureAuthRuleDefaults(rules); + validateFieldRules(rules, isParentTypeBuiltinType, modelDirective !== undefined, this.configuredAuthProviders); + + // regardless if a model directive is used we generate the policy for iam auth + this.setAuthPolicyFlag(rules); + this.setUnauthPolicyFlag(rules); + this.addFieldToResourceReferences(parent.name.value, field.name.value, rules); + + if (modelDirective) { + // auth on models + let acm: AccessControlMatrix; + // check if the parent is already in the model config if not add it + if (!this.modelDirectiveConfig.has(typeName)) { + this.modelDirectiveConfig.set(typeName, getModelConfig(modelDirective, typeName, context.isProjectUsingDataStore())); + acm = new AccessControlMatrix({ + operations: MODEL_OPERATIONS, + resources: collectFieldNames(parent), + }); + } else { + acm = this.authModelConfig.get(typeName) as AccessControlMatrix; + acm.resetAccessForResource(fieldName); + } + this.convertRulesToRoles(acm, rules, fieldName); + this.authModelConfig.set(typeName, acm); + } else { + // if @auth is used without @model only generate static group rules in the resolver + // since we only protect the field for non models we store the typeName + fieldName + // in the authNonModelTypes map + const staticRules = rules.filter((rule: AuthRule) => rule.allow !== 'owner' && !rule.groupsField); + const typeFieldName = `${typeName}:${fieldName}`; + const acm = new AccessControlMatrix({ + operations: ['read'], + resources: [typeFieldName], + }); + this.convertRulesToRoles(acm, staticRules, typeFieldName, ['read']); + this.authNonModelConfig.set(typeFieldName, acm); + } + }; + + transformSchema = (context: TransformerTransformSchemaStepContextProvider): void => { + const getOwnerFields = (acm: AccessControlMatrix) => { + return acm.getRoles().reduce((prev: string[], role: string) => { + if (this.roleMap.get(role)!.strategy === 'owner') prev.push(this.roleMap.get(role)!.entity!); + return prev; + }, []); + }; + for (let [modelName, acm] of this.authModelConfig) { + const def = context.output.getObject(modelName)!; + // collect ownerFields and them in the model + this.addFieldsToObject(context, modelName, getOwnerFields(acm)); + // Get the directives we need to add to the GraphQL nodes + const providers = this.getAuthProviders(acm.getRoles()); + const directives = this.getServiceDirectives(providers, providers.length === 0 ? this.shouldAddDefaultServiceDirective() : false); + if (directives.length > 0) { + extendTypeWithDirectives(context, modelName, directives); + } + this.protectSchemaOperations(context, def, acm); + this.propagateAuthDirectivesToNestedTypes(context, context.output.getObject(modelName)!, providers); + } + for (let [typeFieldName, acm] of this.authNonModelConfig) { + // protect the non model field + const [typeName, fieldName] = typeFieldName.split(':'); + const providers = this.getAuthProviders(acm.getRoles()); + const directives = this.getServiceDirectives(providers, false); + if (directives.length > 0) { + addDirectivesToField(context, typeName, fieldName, directives); + } + } + }; + + generateResolvers = (context: TransformerContextProvider): void => { + // generate iam policies + this.generateIAMPolicies(context); + // generate auth resolver code + for (let [modelName, acm] of this.authModelConfig) { + const indexKeyName = `${modelName}:indicies`; + const def = context.output.getObject(modelName)!; + const searchableDirective = def.directives.find(dir => dir.name.value === 'searchable'); + // queries + const queryFields = getQueryFieldNames(this.modelDirectiveConfig.get(modelName)!); + for (let query of queryFields.values()) { + switch (query.type) { + case QueryFieldType.GET: + this.protectGetResolver(context, def, query.typeName, query.fieldName, acm); + break; + case QueryFieldType.LIST: + this.protectListResolver(context, def, query.typeName, query.fieldName, acm); + break; + case QueryFieldType.SYNC: + this.protectSyncResolver(context, def, query.typeName, query.fieldName, acm); + break; + default: + throw new TransformerContractError('Unkown query field type'); + } + } + // protect additional query fields if they exist + if (context.metadata.has(indexKeyName)) { + for (let index of context.metadata.get>(indexKeyName)!.values()) { + this.protectListResolver(context, def, def.name.value, index, acm); + } + } + // check if searchable if included in the typeName + if (searchableDirective) { + // protect search query + const config = getSearchableConfig(searchableDirective, modelName); + this.protectSearchResolver(context, def, context.output.getQueryTypeName()!, config.queries.search, acm); + } + // get fields specified in the schema + // if there is a role that does not have read access on the field then we create a field resolver + const readRoles = acm.getRolesPerOperation('read'); + const modelFields = def.fields?.filter(f => acm.getResources().includes(f.name.value)) ?? []; + for (let field of modelFields) { + const allowedRoles = readRoles.filter(r => acm.isAllowed(r, field.name.value, 'read')); + if (allowedRoles.length < readRoles.length) { + if (field.type.kind === Kind.NON_NULL_TYPE) { + throw new InvalidDirectiveError(`\nPer-field auth on the required field ${field.name.value} is not supported with subscriptions. + Either make the field optional, set auth on the object and not the field, or disable subscriptions for the object (setting level to off or public)\n`); + } + this.protectFieldResolver(context, def, modelName, field.name.value, allowedRoles); + } + } + const mutationFields = getMutationFieldNames(this.modelDirectiveConfig.get(modelName)!); + for (let mutation of mutationFields.values()) { + switch (mutation.type) { + case MutationFieldType.CREATE: + this.protectCreateResolver(context, def, mutation.typeName, mutation.fieldName, acm); + break; + case MutationFieldType.UPDATE: + this.protectUpdateResolver(context, def, mutation.typeName, mutation.fieldName, acm); + break; + case MutationFieldType.DELETE: + this.protectDeleteResolver(context, def, mutation.typeName, mutation.fieldName, acm); + break; + default: + throw new TransformerContractError('Unkown Mutation field type'); + } + } + + const subscriptionFieldNames = getSubscriptionFieldNames(this.modelDirectiveConfig.get(modelName)!); + const subscriptionRoles = acm + .getRolesPerOperation('read') + .map(role => this.roleMap.get(role)!) + // for subscriptions we only use static rules or owner rule where the field is not a list + .filter(roleDef => (roleDef.strategy === 'owner' && !fieldIsList(def.fields ?? [], roleDef.entity!)) || roleDef.static); + for (let subscription of subscriptionFieldNames) { + this.protectSubscriptionResolver(context, subscription.typeName, subscription.fieldName, subscriptionRoles); + } + } + + for (let [typeFieldName, acm] of this.authNonModelConfig) { + // field resolvers + const [typeName, fieldName] = typeFieldName.split(':'); + const def = context.output.getObject(typeName); + this.protectFieldResolver(context, def, typeName, fieldName, acm.getRoles()); + } + }; + + protectSchemaOperations = ( + ctx: TransformerTransformSchemaStepContextProvider, + def: ObjectTypeDefinitionNode, + acm: AccessControlMatrix, + ): void => { + const modelConfig = this.modelDirectiveConfig.get(def.name.value)!; + const indexKeyName = `${def.name.value}:indicies`; + const searchableDirective = def.directives.find(dir => dir.name.value === 'searchable'); + const addServiceDirective = (typeName: string, operation: ModelOperation, operationName: string | null = null) => { + if (operationName) { + const includeDefault = this.doesTypeHaveRulesForOperation(acm, operation); + const providers = this.getAuthProviders(acm.getRolesPerOperation(operation, operation === 'delete')); + const operationDirectives = this.getServiceDirectives(providers, includeDefault); + if (operationDirectives.length > 0) { + addDirectivesToOperation(ctx, typeName, operationName, operationDirectives); + } + this.addOperationToResourceReferences(typeName, operationName, acm.getRoles()); + } + }; + // default model operations TODO: protect sync queries once supported + addServiceDirective(ctx.output.getQueryTypeName()!, 'read', modelConfig?.queries?.get); + addServiceDirective(ctx.output.getQueryTypeName()!, 'read', modelConfig?.queries?.list); + addServiceDirective(ctx.output.getMutationTypeName()!, 'create', modelConfig?.mutations?.create); + addServiceDirective(ctx.output.getMutationTypeName()!, 'update', modelConfig?.mutations?.update); + addServiceDirective(ctx.output.getMutationTypeName()!, 'delete', modelConfig?.mutations?.delete); + // @index queries + if (ctx.metadata.has(indexKeyName)) { + for (let index of ctx.metadata.get>(indexKeyName)!.values()) { + addServiceDirective(ctx.output.getQueryTypeName(), 'read', index); + } + } + // @searchable + if (searchableDirective) { + const config = getSearchableConfig(searchableDirective, def.name.value); + addServiceDirective(ctx.output.getQueryTypeName(), 'read', config.queries.search); + } + + const subscriptions = modelConfig?.subscriptions; + if (subscriptions.level === SubscriptionLevel.on) { + const subscriptionArguments = acm + .getRolesPerOperation('read') + .map(role => this.roleMap.get(role)!) + .filter(roleDef => roleDef.strategy === 'owner' && !fieldIsList(def.fields ?? [], roleDef.entity!)); + if (subscriptions.onCreate && modelConfig?.mutations?.create) { + for (let onCreateSub of subscriptions.onCreate) { + addServiceDirective(ctx.output.getSubscriptionTypeName()!, 'read', onCreateSub); + addSubscriptionArguments(ctx, onCreateSub, subscriptionArguments); + } + } + if (subscriptions.onUpdate && modelConfig?.mutations?.update) { + for (let onUpdateSub of subscriptions.onUpdate) { + addServiceDirective(ctx.output.getSubscriptionTypeName()!, 'read', onUpdateSub); + addSubscriptionArguments(ctx, onUpdateSub, subscriptionArguments); + } + } + if (subscriptions.onDelete && modelConfig?.mutations?.delete) { + for (let onDeleteSub of subscriptions.onDelete) { + addServiceDirective(ctx.output.getSubscriptionTypeName()!, 'read', onDeleteSub); + addSubscriptionArguments(ctx, onDeleteSub, subscriptionArguments); + } + } + } + }; + + protectGetResolver = ( + ctx: TransformerContextProvider, + def: ObjectTypeDefinitionNode, + typeName: string, + fieldName: string, + acm: AccessControlMatrix, + ): void => { + const resolver = ctx.resolvers.getResolver(typeName, fieldName) as TransformerResolverProvider; + const roleDefinitions = acm.getRolesPerOperation('read').map(r => this.roleMap.get(r)!); + const authExpression = generateAuthExpressionForQueries(this.configuredAuthProviders, roleDefinitions, def.fields ?? []); + resolver.addToSlot( + 'auth', + MappingTemplate.s3MappingTemplateFromString(authExpression, `${typeName}.${fieldName}.{slotName}.{slotIndex}.req.vtl`), + ); + }; + protectListResolver = ( + ctx: TransformerContextProvider, + def: ObjectTypeDefinitionNode, + typeName: string, + fieldName: string, + acm: AccessControlMatrix, + ): void => { + const resolver = ctx.resolvers.getResolver(typeName, fieldName) as TransformerResolverProvider; + const roleDefinitions = acm.getRolesPerOperation('read').map(r => this.roleMap.get(r)!); + const authExpression = generateAuthExpressionForQueries(this.configuredAuthProviders, roleDefinitions, def.fields ?? []); + resolver.addToSlot( + 'auth', + MappingTemplate.s3MappingTemplateFromString(authExpression, `${typeName}.${fieldName}.{slotName}.{slotIndex}.req.vtl`), + ); + }; + protectSyncResolver = ( + ctx: TransformerContextProvider, + def: ObjectTypeDefinitionNode, + typeName: string, + fieldName: string, + acm: AccessControlMatrix, + ): void => { + if (ctx.isProjectUsingDataStore()) { + const resolver = ctx.resolvers.getResolver(typeName, fieldName) as TransformerResolverProvider; + const roleDefinitions = acm.getRolesPerOperation('read').map(r => this.roleMap.get(r)!); + const authExpression = generateAuthExpressionForQueries(this.configuredAuthProviders, roleDefinitions, def.fields ?? []); + resolver.addToSlot( + 'auth', + MappingTemplate.s3MappingTemplateFromString(authExpression, `${typeName}.${fieldName}.{slotName}.{slotIndex}.req.vtl`), + ); + } + }; + protectSearchResolver = ( + ctx: TransformerContextProvider, + def: ObjectTypeDefinitionNode, + typeName: string, + fieldName: string, + acm: AccessControlMatrix, + ): void => { + const resolver = ctx.resolvers.getResolver(typeName, fieldName) as TransformerResolverProvider; + const roleDefinitions = acm.getRolesPerOperation('read').map(r => this.roleMap.get(r)!); + const authExpression = generateAuthExpressionForQueries(this.configuredAuthProviders, roleDefinitions, def.fields ?? [], 'opensearch'); + resolver.addToSlot( + 'auth', + MappingTemplate.s3MappingTemplateFromString(authExpression, `${typeName}.${fieldName}.{slotName}.{slotIndex}.req.vtl`), + ); + }; + /* + Field Resovler can protect the following + - model fields + - relational fields (hasOne, hasMany, belongsTo) + - fields on an operation (query/mutation) + - protection on predictions/function/no directive + Order of precendence + - resolver in api host (ex. @function, @predictions) + - resolver in resolver manager (ex. @hasOne, @hasMany @belongsTo) + - no resolver creates a blank non-pipeline resolver will return the source field + */ + protectFieldResolver = ( + ctx: TransformerContextProvider, + def: ObjectTypeDefinitionNode, + typeName: string, + fieldName: string, + roles: Array, + ): void => { + const roleDefinitions = roles.map(r => this.roleMap.get(r)!); + const hasModelDirective = def.directives.some(dir => dir.name.value === 'model'); + const stack = getStackForField(ctx, def, fieldName, hasModelDirective); + if (ctx.api.host.hasResolver(typeName, fieldName)) { + // TODO: move pipeline resolvers created in the api host to the resolver manager + const fieldResolver = ctx.api.host.getResolver(typeName, fieldName) as any; + const fieldAuthExpression = generateAuthExpressionForField(this.configuredAuthProviders, roleDefinitions, []); + if (!ctx.api.host.hasDataSource(NONE_DS)) { + ctx.api.host.addNoneDataSource(NONE_DS); + } + const authFunction = ctx.api.host.addAppSyncFunction( + `${toUpper(typeName)}${toUpper(fieldName)}AuthFN`, + MappingTemplate.s3MappingTemplateFromString(fieldAuthExpression, `${typeName}.${fieldName}.auth.req.vtl`), + MappingTemplate.inlineTemplateFromString('$util.toJson({})'), + NONE_DS, + stack, + ); + (fieldResolver.pipelineConfig.functions as string[]).unshift(authFunction.functionId); + } else if (ctx.resolvers.hasResolver(typeName, fieldName)) { + // if there a resolver in the resolver manager we can append to the auth slot + const fieldResolver = ctx.resolvers.getResolver(typeName, fieldName) as TransformerResolverProvider; + const authExpression = generateAuthExpressionForQueries(this.configuredAuthProviders, roleDefinitions, def.fields ?? []); + fieldResolver.addToSlot( + 'auth', + MappingTemplate.s3MappingTemplateFromString(authExpression, `${typeName}.${fieldName}.{slotName}.{slotIndex}.req.vtl`), + ); + } else { + const fieldAuthExpression = generateAuthExpressionForField(this.configuredAuthProviders, roleDefinitions, def.fields ?? []); + const subsEnabled = hasModelDirective ? this.modelDirectiveConfig.get(typeName)!.subscriptions.level === 'on' : false; + const fieldResponse = generateFieldAuthResponse('Mutation', fieldName, subsEnabled); + const resolver = ctx.resolvers.addResolver( + typeName, + fieldName, + new TransformerResolver( + typeName, + fieldName, + MappingTemplate.s3MappingTemplateFromString(fieldAuthExpression, `${typeName}.${fieldName}.req.vtl`), + MappingTemplate.s3MappingTemplateFromString(fieldResponse, `${typeName}.${fieldName}.res.vtl`), + ['init'], + ['finish'], + ), + ); + resolver.mapToStack(stack); + } + }; + protectCreateResolver = ( + ctx: TransformerContextProvider, + def: ObjectTypeDefinitionNode, + typeName: string, + fieldName: string, + acm: AccessControlMatrix, + ): void => { + const resolver = ctx.resolvers.getResolver(typeName, fieldName) as TransformerResolverProvider; + const fields = acm.getResources(); + const createRoles = acm.getRolesPerOperation('create').map(role => { + const allowedFields = fields.filter(resource => acm.isAllowed(role, resource, 'create')); + const roleDefinition = this.roleMap.get(role)!; + roleDefinition.allowedFields = allowedFields.length === fields.length ? [] : allowedFields; + return roleDefinition; + }); + const authExpression = generateAuthExpressionForCreate(this.configuredAuthProviders, createRoles, def.fields ?? []); + resolver.addToSlot( + 'auth', + MappingTemplate.s3MappingTemplateFromString(authExpression, `${typeName}.${fieldName}.{slotName}.{slotIndex}.req.vtl`), + ); + }; + protectUpdateResolver = ( + ctx: TransformerContextProvider, + def: ObjectTypeDefinitionNode, + typeName: string, + fieldName: string, + acm: AccessControlMatrix, + ): void => { + const resolver = ctx.resolvers.getResolver(typeName, fieldName) as TransformerResolverProvider; + const fields = acm.getResources(); + const updateDeleteRoles = [...new Set([...acm.getRolesPerOperation('update'), ...acm.getRolesPerOperation('delete')])]; + // protect fields to be updated and fields that can't be set to null (partial delete on fields) + const totalRoles = updateDeleteRoles.map(role => { + const allowedFields = fields.filter(resource => acm.isAllowed(role, resource, 'update')); + const nullAllowedFileds = fields.filter(resource => acm.isAllowed(role, resource, 'delete')); + const roleDefinition = this.roleMap.get(role)!; + roleDefinition.allowedFields = allowedFields.length === fields.length ? [] : allowedFields; + roleDefinition.nullAllowedFields = nullAllowedFileds.length === fields.length ? [] : nullAllowedFileds; + return roleDefinition; + }); + const datasource = ctx.api.host.getDataSource(`${def.name.value}Table`) as DataSourceProvider; + const requestExpression = generateAuthRequestExpression(); + const authExpression = generateAuthExpressionForUpdate(this.configuredAuthProviders, totalRoles, def.fields ?? []); + resolver.addToSlot( + 'auth', + MappingTemplate.s3MappingTemplateFromString(requestExpression, `${typeName}.${fieldName}.{slotName}.{slotIndex}.req.vtl`), + MappingTemplate.s3MappingTemplateFromString(authExpression, `${typeName}.${fieldName}.{slotName}.{slotIndex}.res.vtl`), + datasource, + ); + }; + + protectDeleteResolver = ( + ctx: TransformerContextProvider, + def: ObjectTypeDefinitionNode, + typeName: string, + fieldName: string, + acm: AccessControlMatrix, + ): void => { + const resolver = ctx.resolvers.getResolver(typeName, fieldName) as TransformerResolverProvider; + // only roles with full delete on every field can delete + const deleteRoles = acm.getRolesPerOperation('delete', true).map(role => this.roleMap.get(role)!); + const datasource = ctx.api.host.getDataSource(`${def.name.value}Table`) as DataSourceProvider; + const requestExpression = generateAuthRequestExpression(); + const authExpression = geneateAuthExpressionForDelete(this.configuredAuthProviders, deleteRoles, def.fields ?? []); + resolver.addToSlot( + 'auth', + MappingTemplate.s3MappingTemplateFromString(requestExpression, `${typeName}.${fieldName}.{slotName}.{slotIndex}.req.vtl`), + MappingTemplate.s3MappingTemplateFromString(authExpression, `${typeName}.${fieldName}.{slotName}.{slotIndex}.res.vtl`), + datasource, + ); + }; + + protectSubscriptionResolver = ( + ctx: TransformerContextProvider, + typeName: string, + fieldName: string, + subscriptionRoles: Array, + ): void => { + const resolver = ctx.resolvers.getResolver(typeName, fieldName) as TransformerResolverProvider; + const authExpression = generateAuthExpressionForSubscriptions(this.configuredAuthProviders, subscriptionRoles); + resolver.addToSlot( + 'auth', + MappingTemplate.s3MappingTemplateFromString(authExpression, `${typeName}.${fieldName}.{slotName}.{slotIndex}.req.vtl`), + ); + }; + + /* + Role Helpers + */ + private convertRulesToRoles(acm: AccessControlMatrix, authRules: AuthRule[], field?: string, overideOperations?: ModelOperation[]) { + for (let rule of authRules) { + let operations: ModelOperation[] = overideOperations ? overideOperations : rule.operations || MODEL_OPERATIONS; + if (rule.groups && !rule.groupsField) { + rule.groups.forEach(group => { + const groupClaim = rule.groupClaim || DEFAULT_GROUP_CLAIM; + const roleName = `${rule.provider}:staticGroup:${group}:${groupClaim}`; + if (!(roleName in this.roleMap)) { + this.roleMap.set(roleName, { + provider: rule.provider!, + strategy: rule.allow, + static: true, + claim: groupClaim, + entity: group, + }); + } + acm.setRole({ role: roleName, resource: field, operations }); + }); + } else { + let roleName: string; + let roleDefinition: RoleDefinition; + switch (rule.provider) { + case 'apiKey': + roleName = 'apiKey:public'; + roleDefinition = { provider: rule.provider, strategy: rule.allow, static: true }; + break; + case 'iam': + roleName = `iam:${rule.allow}`; + roleDefinition = { + provider: rule.provider, + strategy: rule.allow, + static: true, + claim: rule.allow === 'private' ? 'authRole' : 'unauthRole', + }; + break; + case 'oidc': + case 'userPools': + if (rule.allow === 'groups') { + const groupClaim = rule.groupClaim || DEFAULT_GROUP_CLAIM; + const groupsField = rule.groupsField || DEFAULT_GROUPS_FIELD; + roleName = `${rule.provider}:dynamicGroup:${groupsField}:${groupClaim}`; + roleDefinition = { + provider: rule.provider, + strategy: rule.allow, + static: false, + claim: groupClaim, + entity: groupsField, + }; + } else if (rule.allow === 'owner') { + const ownerField = rule.ownerField || DEFAULT_OWNER_FIELD; + const ownerClaim = rule.identityClaim || DEFAULT_IDENTITY_CLAIM; + roleName = `${rule.provider}:owner:${ownerField}:${ownerClaim}`; + roleDefinition = { + provider: rule.provider, + strategy: rule.allow, + static: false, + claim: ownerClaim, + entity: ownerField, + }; + } else if (rule.allow === 'private') { + roleName = `${rule.provider}:${rule.allow}`; + roleDefinition = { + provider: rule.provider, + strategy: rule.allow, + static: true, + }; + } else { + throw new TransformerContractError(`Could not create a role from ${JSON.stringify(rule)}`); + } + break; + default: + throw new TransformerContractError(`Could not create a role from ${JSON.stringify(rule)}`); + } + if (!(roleName in this.roleMap)) { + this.roleMap.set(roleName, roleDefinition); + } + acm.setRole({ role: roleName, resource: field, operations }); + } + } + } + + private doesTypeHaveRulesForOperation(acm: AccessControlMatrix, operation: ModelOperation) { + const rolesHasDefaultProvider = (roles: Array) => { + return roles.some(r => this.roleMap.get(r)!.provider! === this.configuredAuthProviders.default); + }; + const roles = acm.getRolesPerOperation(operation, operation === 'delete'); + return rolesHasDefaultProvider(roles) || (roles.length === 0 && this.shouldAddDefaultServiceDirective()); + } + private getAuthProviders(roles: Array): Array { + const providers: Set = new Set(); + // get the roles created for type + for (let role of roles) { + providers.add(this.roleMap.get(role)!.provider); + } + if (this.configuredAuthProviders.hasAdminUIEnabled) { + providers.add('iam'); + } + return Array.from(providers); + } + + /* + Schema Generation Helpers + */ + private addFieldsToObject(ctx: TransformerTransformSchemaStepContextProvider, modelName: string, ownerFields: Array) { + const modelObject = ctx.output.getObject(modelName)!; + const existingFields = collectFieldNames(modelObject); + const ownerFieldsToAdd = ownerFields.filter(field => !existingFields.includes(field)); + for (let ownerField of ownerFieldsToAdd) { + (modelObject as any).fields.push(makeField(ownerField, [], makeNamedType('String'))); + } + ctx.output.putType(modelObject); + } + private propagateAuthDirectivesToNestedTypes( + ctx: TransformerTransformSchemaStepContextProvider, + def: ObjectTypeDefinitionNode, + providers: Array, + ) { + const nonModelTypePredicate = (fieldType: TypeDefinitionNode): TypeDefinitionNode | undefined => { + if (fieldType) { + if (fieldType.kind !== 'ObjectTypeDefinition') { + return undefined; + } + const typeModel = fieldType.directives!.find(dir => dir.name.value === 'model'); + return typeModel !== undefined ? undefined : fieldType; + } + return fieldType; + }; + const nonModelFieldTypes = def + .fields!.map(f => ctx.output.getType(getBaseType(f.type)) as TypeDefinitionNode) + .filter(nonModelTypePredicate); + for (const nonModelFieldType of nonModelFieldTypes) { + const nonModelName = nonModelFieldType.name.value; + const hasSeenType = this.seenNonModelTypes.has(nonModelFieldType.name.value); + let directives = this.getServiceDirectives(providers, hasSeenType); + if (!hasSeenType) { + this.seenNonModelTypes.set(nonModelName, new Set([...directives.map(dir => dir.name.value)])); + // since we haven't seen this type before we add it to the iam policy resource sets + const hasIAM = directives.some(dir => dir.name.value === 'aws_iam') || this.configuredAuthProviders.default === 'iam'; + if (hasIAM) { + this.unauthPolicyResources.add(`${nonModelFieldType.name.value}/null`); + this.authPolicyResources.add(`${nonModelFieldType.name.value}/null`); + } + } else { + const currentDirectives = this.seenNonModelTypes.get(nonModelName)!; + directives = directives.filter(dir => !currentDirectives.has(dir.name.value)); + this.seenNonModelTypes.set(nonModelName, new Set([...directives.map(dir => dir.name.value), ...currentDirectives])); + } + // we continue to check the nested types if we find that directives list is not empty or if haven't seen the type before + if (directives.length > 0 || !hasSeenType) { + extendTypeWithDirectives(ctx, nonModelFieldType.name.value, directives); + this.propagateAuthDirectivesToNestedTypes(ctx, nonModelFieldType, providers); + } + } + } + + private getServiceDirectives(providers: Readonly>, addDefaultIfNeeded: boolean = true): Array { + if (providers.length === 0) { + return []; + } + const directives: Array = new Array(); + /* + We only add a service directive if it's not the default or + it's the default but there are other rules under different providers. + For fields we don't we don't add the default since it would open up access. + */ + const addDirectiveIfNeeded = (provider: AuthProvider, directiveName: string): void => { + if ( + (this.configuredAuthProviders.default !== provider && providers.some(p => p === provider)) || + (this.configuredAuthProviders.default === provider && providers.some(p => p !== provider && addDefaultIfNeeded === true)) + ) { + directives.push(makeDirective(directiveName, [])); + } + }; + + for (let [authProvider, directiveName] of AUTH_PROVIDER_DIRECTIVE_MAP) { + addDirectiveIfNeeded(authProvider, directiveName); + } + /* + If we have any rules for the default provider AND those with other providers, + we add the default provider directive, regardless of the addDefaultDirective value + + For example if we have this rule and the default is API_KEY + @auth(rules: [{ allow: owner }, { allow: public, operations: [read] }]) + + Then we need to add @aws_api_key on the queries along with @aws_cognito_user_pools, but we + cannot add @aws_api_key to other operations since their is no rule granted access to it + */ + if ( + providers.some(p => p === this.configuredAuthProviders.default) && + providers.some(p => p !== this.configuredAuthProviders.default) && + !directives.some(d => d.name.value === AUTH_PROVIDER_DIRECTIVE_MAP.get(this.configuredAuthProviders.default)) + ) { + directives.push(makeDirective(AUTH_PROVIDER_DIRECTIVE_MAP.get(this.configuredAuthProviders.default) as string, [])); + } + return directives; + } + /** + * When AdminUI is enabled, all the types and operations get IAM auth. If the default auth mode is + * not IAM all the fields will need to have the default auth mode directive to ensure both IAM and deault + * auth modes are allowed to access + * default auth provider needs to be added if AdminUI is enabled and default auth type is not IAM + * @returns boolean + */ + private shouldAddDefaultServiceDirective(): boolean { + return this.configuredAuthProviders.hasAdminUIEnabled && this.config.authConfig.defaultAuthentication.authenticationType !== 'AWS_IAM'; + } + /* + IAM Helpers + */ + private generateIAMPolicies(ctx: TransformerContextProvider) { + // iam + if (this.generateIAMPolicyforAuthRole) { + // Sanity check to make sure we're not generating invalid policies, where no resources are defined. + if (this.authPolicyResources.size === 0) { + // When AdminUI is enabled, IAM auth is added but it does not need any policies to be generated + if (!this.configuredAuthProviders.hasAdminUIEnabled) { + throw new TransformerContractError('AuthRole policies should be generated, but no resources were added.'); + } + } else { + const authRoleParameter = (ctx.stackManager.getParameter(IAM_AUTH_ROLE_PARAMETER) as cdk.CfnParameter).valueAsString; + const authPolicyDocuments = createPolicyDocumentForManagedPolicy(this.authPolicyResources); + const rootStack = ctx.stackManager.rootStack; + for (let i = 0; i < authPolicyDocuments.length; i++) { + const paddedIndex = `${i + 1}`.padStart(2, '0'); + const resourceName = `${ResourceConstants.RESOURCES.AuthRolePolicy}${paddedIndex}`; + new iam.ManagedPolicy(rootStack, resourceName, { + document: iam.PolicyDocument.fromJson(authPolicyDocuments[i]), + // we need to add the arn path as this is something cdk is looking for when using imported roles in policies + roles: [ + iam.Role.fromRoleArn( + rootStack, + 'auth-role-name', + `arn:aws:iam::${cdk.Stack.of(rootStack).account}:role/${authRoleParameter}`, + ), + ], + }); + } + } + } + if (this.generateIAMPolicyforUnauthRole) { + // Sanity check to make sure we're not generating invalid policies, where no resources are defined. + if (this.unauthPolicyResources.size === 0) { + throw new TransformerContractError('UnauthRole policies should be generated, but no resources were added'); + } + const unauthRoleParameter = (ctx.stackManager.getParameter(IAM_UNAUTH_ROLE_PARAMETER) as cdk.CfnParameter).valueAsString; + const unauthPolicyDocuments = createPolicyDocumentForManagedPolicy(this.unauthPolicyResources); + const rootStack = ctx.stackManager.rootStack; + for (let i = 0; i < unauthPolicyDocuments.length; i++) { + const paddedIndex = `${i + 1}`.padStart(2, '0'); + const resourceName = `${ResourceConstants.RESOURCES.UnauthRolePolicy}${paddedIndex}`; + new iam.ManagedPolicy(ctx.stackManager.rootStack, resourceName, { + document: iam.PolicyDocument.fromJson(unauthPolicyDocuments[i]), + roles: [ + iam.Role.fromRoleArn( + rootStack, + 'unauth-role-name', + `arn:aws:iam::${cdk.Stack.of(rootStack).account}:role/${unauthRoleParameter}`, + ), + ], + }); + } + } + } + private setAuthPolicyFlag(rules: AuthRule[]): void { + if (rules.length === 0 || this.generateIAMPolicyforAuthRole === true) { + return; + } + for (const rule of rules) { + if ((rule.allow === 'private' || rule.allow === 'public') && rule.provider === 'iam') { + this.generateIAMPolicyforAuthRole = true; + return; + } + } + } + + private setUnauthPolicyFlag(rules: AuthRule[]): void { + if (rules.length === 0 || this.generateIAMPolicyforUnauthRole === true) { + return; + } + for (const rule of rules) { + if (rule.allow === 'public' && rule.provider === 'iam') { + this.generateIAMPolicyforUnauthRole = true; + return; + } + } + } + + private addOperationToResourceReferences(operationName: string, fieldName: string, roles: Array) { + const iamPublicRolesExist = roles.some(r => this.roleMap.get(r)!.provider === 'iam' && this.roleMap.get(r)!.strategy === 'public'); + const iamPrivateRolesExist = roles.some(r => this.roleMap.get(r)!.provider === 'iam' && this.roleMap.get(r)!.strategy === 'private'); + + if (iamPublicRolesExist) { + this.unauthPolicyResources.add(`${operationName}/${fieldName}`); + this.authPolicyResources.add(`${operationName}/${fieldName}`); + } + if (iamPrivateRolesExist) { + this.authPolicyResources.add(`${operationName}/${fieldName}`); + } + } + + /** + * TODO: Change Resource Ref Object/Field Functions to work with roles + */ + private addTypeToResourceReferences(typeName: string, rules: AuthRule[]): void { + const iamPublicRulesExist = rules.some(r => r.allow === 'public' && r.provider === 'iam' && r.generateIAMPolicy); + const iamPrivateRulesExist = rules.some(r => r.allow === 'private' && r.provider === 'iam' && r.generateIAMPolicy); + + if (iamPublicRulesExist) { + this.unauthPolicyResources.add(`${typeName}/null`); + this.authPolicyResources.add(`${typeName}/null`); + } + if (iamPrivateRulesExist) { + this.authPolicyResources.add(`${typeName}/null`); + } + } + + private addFieldToResourceReferences(typeName: string, fieldName: string, rules: AuthRule[]): void { + const iamPublicRulesExist = rules.some(r => r.allow === 'public' && r.provider === 'iam' && r.generateIAMPolicy); + const iamPrivateRulesExist = rules.some(r => r.allow === 'private' && r.provider === 'iam' && r.generateIAMPolicy); + + if (iamPublicRulesExist) { + this.unauthPolicyResources.add(`${typeName}/${fieldName}`); + this.authPolicyResources.add(`${typeName}/${fieldName}`); + } + if (iamPrivateRulesExist) { + this.authPolicyResources.add(`${typeName}/${fieldName}`); + } + } +} diff --git a/packages/amplify-graphql-auth-transformer/src/index.ts b/packages/amplify-graphql-auth-transformer/src/index.ts new file mode 100644 index 00000000000..5382eacf29f --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/index.ts @@ -0,0 +1,4 @@ +export * from './graphql-auth-transformer'; +export * from './utils/constants'; +export * from './utils/definitions'; +export { AccessControlMatrix } from './accesscontrol'; diff --git a/packages/amplify-graphql-auth-transformer/src/resolvers/field.ts b/packages/amplify-graphql-auth-transformer/src/resolvers/field.ts new file mode 100644 index 00000000000..e5ec9ffe460 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/resolvers/field.ts @@ -0,0 +1,136 @@ +import { OPERATION_KEY } from '@aws-amplify/graphql-model-transformer'; +import { FieldDefinitionNode } from 'graphql'; +import { + Expression, + iff, + not, + ref, + equals, + str, + compoundExpression, + printBlock, + toJson, + set, + methodCall, + nul, + ifElse, + bool, + raw, + forEach, +} from 'graphql-mapping-template'; +import { + RoleDefinition, + splitRoles, + COGNITO_AUTH_TYPE, + OIDC_AUTH_TYPE, + ConfiguredAuthProviders, + fieldIsList, + IS_AUTHORIZED_FLAG, +} from '../utils'; +import { getOwnerClaim, generateStaticRoleExpression, apiKeyExpression, iamExpression, emptyPayload } from './helpers'; + +// Field Read VTL Functions +const generateDynamicAuthReadExpression = (roles: Array, fields: ReadonlyArray) => { + const ownerExpressions = new Array(); + const dynamicGroupExpressions = new Array(); + roles.forEach((role, idx) => { + const entityIsList = fieldIsList(fields, role.entity!); + if (role.strategy === 'owner') { + ownerExpressions.push( + iff( + not(ref(IS_AUTHORIZED_FLAG)), + compoundExpression([ + set(ref(`ownerEntity${idx}`), methodCall(ref('util.defaultIfNull'), ref(`ctx.source.${role.entity!}`), nul())), + set(ref(`ownerClaim${idx}`), getOwnerClaim(role.claim!)), + ...(entityIsList + ? [ + forEach(ref('allowedOwner'), ref(`ownerEntity${idx}`), [ + iff( + equals(ref('allowedOwner'), ref(`ownerClaim${idx}`)), + compoundExpression([set(ref(IS_AUTHORIZED_FLAG), bool(true)), raw('#break')]), + ), + ]), + ] + : [iff(equals(ref(`ownerEntity${idx}`), ref(`ownerClaim${idx}`)), set(ref(IS_AUTHORIZED_FLAG), bool(true)))]), + ]), + ), + ); + } + if (role.strategy === 'groups') { + dynamicGroupExpressions.push( + iff( + not(ref(IS_AUTHORIZED_FLAG)), + compoundExpression([ + set(ref(`groupEntity${idx}`), methodCall(ref('util.defaultIfNull'), ref(`ctx.source.${role.entity!}`), nul())), + set(ref(`groupClaim${idx}`), getOwnerClaim(role.claim!)), + forEach(ref('userGroup'), ref('dynamicGroupClaim'), [ + iff( + entityIsList + ? methodCall(ref(`groupEntity${idx}.contains`), ref('userGroup')) + : equals(ref(`groupEntity${idx}`), ref('userGroup')), + compoundExpression([set(ref(IS_AUTHORIZED_FLAG), bool(true)), raw('#break')]), + ), + ]), + ]), + ), + ); + } + }); + return [...(ownerExpressions.length > 0 || dynamicGroupExpressions.length > 0 ? [...ownerExpressions, ...dynamicGroupExpressions] : [])]; +}; + +export const generateAuthExpressionForField = ( + provider: ConfiguredAuthProviders, + roles: Array, + fields: ReadonlyArray, +): string => { + const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, iamRoles, apiKeyRoles } = splitRoles(roles); + const totalAuthExpressions: Array = [set(ref(IS_AUTHORIZED_FLAG), bool(false))]; + if (provider.hasApiKey) { + totalAuthExpressions.push(apiKeyExpression(apiKeyRoles)); + } + if (provider.hasIAM) { + totalAuthExpressions.push(iamExpression(iamRoles, provider.hasAdminUIEnabled, provider.adminUserPoolID)); + } + if (provider.hasUserPools) { + totalAuthExpressions.push( + iff( + equals(ref('util.authType()'), str(COGNITO_AUTH_TYPE)), + compoundExpression([ + ...generateStaticRoleExpression(cogntoStaticRoles), + ...generateDynamicAuthReadExpression(cognitoDynamicRoles, fields), + ]), + ), + ); + } + if (provider.hasOIDC) { + totalAuthExpressions.push( + iff( + equals(ref('util.authType()'), str(OIDC_AUTH_TYPE)), + compoundExpression([ + ...generateStaticRoleExpression(oidcStaticRoles), + ...generateDynamicAuthReadExpression(oidcDynamicRoles, fields), + ]), + ), + ); + } + totalAuthExpressions.push(iff(not(ref(IS_AUTHORIZED_FLAG)), ref('util.unauthorized()'))); + return printBlock('Field Authorization Steps')(compoundExpression([...totalAuthExpressions, emptyPayload])); +}; + +/** + * This is the response resolver for fields to protect subscriptions + * @param subscriptionsEnabled + * @returns + */ +export const generateFieldAuthResponse = (operation: string, fieldName: string, subscriptionsEnabled: boolean): string => { + if (subscriptionsEnabled) { + return printBlock('Checking for allowed operations which can return this field')( + compoundExpression([ + set(ref('operation'), methodCall(ref('util.defaultIfNull'), methodCall(ref('ctx.source.get'), str(OPERATION_KEY)), nul())), + ifElse(equals(ref('operation'), str(operation)), toJson(nul()), toJson(ref(`context.source.${fieldName}`))), + ]), + ); + } + return printBlock('Return Source Field')(toJson(ref(`context.source.${fieldName}`))); +}; diff --git a/packages/amplify-graphql-auth-transformer/src/resolvers/helpers.ts b/packages/amplify-graphql-auth-transformer/src/resolvers/helpers.ts new file mode 100644 index 00000000000..5ac4e417b94 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/resolvers/helpers.ts @@ -0,0 +1,152 @@ +import { + qref, + Expression, + ifElse, + iff, + methodCall, + not, + ref, + set, + str, + raw, + obj, + bool, + compoundExpression, + printBlock, + toJson, + forEach, + list, + equals, + or, +} from 'graphql-mapping-template'; +import { NONE_VALUE } from 'graphql-transformer-common'; +import { + DEFAULT_COGNITO_IDENTITY_CLAIM, + RoleDefinition, + IS_AUTHORIZED_FLAG, + ALLOWED_FIELDS, + API_KEY_AUTH_TYPE, + ADMIN_ROLE, + IAM_AUTH_TYPE, + MANAGE_ROLE, +} from '../utils'; + +// note in the resolver that operation is protected by auth +export const setHasAuthExpression: Expression = qref(methodCall(ref('ctx.stash.put'), str('hasAuth'), bool(true))); + +// since the keySet returns a set we can convert it to a list by converting to json and parsing back as a list +export const getInputFields = (): Expression => { + return set(ref('inputFields'), methodCall(ref('util.parseJson'), methodCall(ref('util.toJson'), ref('ctx.args.input.keySet()')))); +}; + +export const getIdentityClaimExp = (value: Expression, defaultValueExp: Expression): Expression => { + return methodCall(ref('util.defaultIfNull'), methodCall(ref('ctx.identity.claims.get'), value), defaultValueExp); +}; + +// for create mutations and subscriptions +export const addAllowedFieldsIfElse = (fieldKey: string, breakLoop: boolean = false): Expression => { + return ifElse( + not(ref(`${fieldKey}.isEmpty()`)), + qref(methodCall(ref(`${ALLOWED_FIELDS}.addAll`), ref(fieldKey))), + compoundExpression([set(ref(IS_AUTHORIZED_FLAG), bool(true)), ...(breakLoop ? [raw('#break')] : [])]), + ); +}; + +// iam check +export const iamCheck = (claim: string, exp: Expression) => iff(equals(ref('ctx.identity.userArn'), ref(`ctx.stash.${claim}`)), exp); + +/** + * Behavior of auth v1 + * Order of how the owner value is retrieved from the jwt + * if claim is username + * 1. username + * 2. cognito:username + * 3. none value + * + * if claim is custom + * 1. custom + * 2. none value + */ +export const getOwnerClaim = (ownerClaim: string): Expression => { + if (ownerClaim === 'username') { + return getIdentityClaimExp(str(ownerClaim), getIdentityClaimExp(str(DEFAULT_COGNITO_IDENTITY_CLAIM), str(NONE_VALUE))); + } + return getIdentityClaimExp(str(ownerClaim), str(NONE_VALUE)); +}; + +export const responseCheckForErrors = () => + iff(ref('ctx.error'), methodCall(ref('util.error'), ref('ctx.error.message'), ref('ctx.error.type'))); + +// Common Expressions + +export const generateStaticRoleExpression = (roles: Array): Array => { + const staticRoleExpression: Array = new Array(); + const privateRoleIdx = roles.findIndex(r => r.strategy === 'private'); + if (privateRoleIdx > -1) { + staticRoleExpression.push(set(ref(IS_AUTHORIZED_FLAG), bool(true))); + roles.splice(privateRoleIdx, 1); + } + if (roles.length > 0) { + staticRoleExpression.push( + iff( + not(ref(IS_AUTHORIZED_FLAG)), + compoundExpression([ + set(ref('staticGroupRoles'), raw(JSON.stringify(roles.map(r => ({ claim: r.claim, entity: r.entity }))))), + forEach(ref('groupRole'), ref('staticGroupRoles'), [ + set(ref('groupsInToken'), getIdentityClaimExp(ref('groupRole.claim'), list([]))), + iff( + methodCall(ref('groupsInToken.contains'), ref('groupRole.entity')), + compoundExpression([set(ref(IS_AUTHORIZED_FLAG), bool(true)), raw(`#break`)]), + ), + ]), + ]), + ), + ); + } + return staticRoleExpression; +}; + +export const apiKeyExpression = (roles: Array) => + iff( + equals(ref('util.authType()'), str(API_KEY_AUTH_TYPE)), + compoundExpression([...(roles.length > 0 ? [set(ref(IS_AUTHORIZED_FLAG), bool(true))] : [])]), + ); + +export const iamExpression = (roles: Array, adminuiEnabled: boolean = false, adminUserPoolID?: string) => { + const expression = new Array(); + // allow if using admin ui + if (adminuiEnabled) { + expression.push( + iff( + or([ + methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID}${ADMIN_ROLE}`)), + methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID}${MANAGE_ROLE}`)), + ]), + raw('#return($util.toJson({})'), + ), + ); + } + if (roles.length > 0) { + for (let role of roles) { + expression.push(iff(not(ref(IS_AUTHORIZED_FLAG)), iamCheck(role.claim!, set(ref(IS_AUTHORIZED_FLAG), bool(true))))); + } + } + return iff(equals(ref('util.authType()'), str(IAM_AUTH_TYPE)), compoundExpression(expression)); +}; + +// Get Request for Update and Delete +export const generateAuthRequestExpression = () => { + const statements = [ + set(ref('GetRequest'), obj({ version: str('2018-05-29'), operation: str('GetItem') })), + ifElse( + ref('ctx.stash.metadata.modelObjectKey'), + set(ref('key'), ref('ctx.stash.metadata.modelObjectKey')), + compoundExpression([set(ref('key'), obj({ id: methodCall(ref('util.dynamodb.toDynamoDB'), ref('ctx.args.input.id')) }))]), + ), + qref(methodCall(ref('GetRequest.put'), str('key'), ref('key'))), + toJson(ref('GetRequest')), + ]; + return printBlock('Get Request template')(compoundExpression(statements)); +}; + +export const emptyPayload = toJson(raw(JSON.stringify({ version: '2018-05-29', payload: {} }))); diff --git a/packages/amplify-graphql-auth-transformer/src/resolvers/index.ts b/packages/amplify-graphql-auth-transformer/src/resolvers/index.ts new file mode 100644 index 00000000000..5f9e8476d39 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/resolvers/index.ts @@ -0,0 +1,7 @@ +export { generateAuthExpressionForQueries } from './query'; +export { generateAuthExpressionForCreate } from './mutation.create'; +export { generateAuthExpressionForUpdate } from './mutation.update'; +export { geneateAuthExpressionForDelete } from './mutation.delete'; +export { generateAuthExpressionForField, generateFieldAuthResponse } from './field'; +export { generateAuthExpressionForSubscriptions } from './subscriptions'; +export { generateAuthRequestExpression } from './helpers'; diff --git a/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.create.ts b/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.create.ts new file mode 100644 index 00000000000..22dd6a95d22 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.create.ts @@ -0,0 +1,274 @@ +import { FieldDefinitionNode } from 'graphql'; +import { + Expression, + compoundExpression, + set, + ref, + bool, + raw, + iff, + and, + isNullOrEmpty, + not, + methodCall, + qref, + list, + nul, + forEach, + equals, + str, + or, + printBlock, +} from 'graphql-mapping-template'; +import { + getOwnerClaim, + getIdentityClaimExp, + getInputFields, + addAllowedFieldsIfElse, + emptyPayload, + setHasAuthExpression, + iamCheck, +} from './helpers'; +import { + ADMIN_ROLE, + API_KEY_AUTH_TYPE, + COGNITO_AUTH_TYPE, + ConfiguredAuthProviders, + IAM_AUTH_TYPE, + MANAGE_ROLE, + OIDC_AUTH_TYPE, + RoleDefinition, + splitRoles, + fieldIsList, + IS_AUTHORIZED_FLAG, + ALLOWED_FIELDS, + DENIED_FIELDS, +} from '../utils'; + +/** + * There is only one role for ApiKey we can use the first index + * @param roles + * @returns Expression | null + */ +const apiKeyExpression = (roles: Array) => { + const expression = new Array(); + if (roles.length === 0) { + return iff(equals(ref('util.authType()'), str(API_KEY_AUTH_TYPE)), ref('util.unauthorized()')); + } + if (roles[0].allowedFields!.length > 0) { + expression.push(set(ref(`${ALLOWED_FIELDS}`), raw(JSON.stringify(roles[0].allowedFields)))); + } else { + expression.push(set(ref(IS_AUTHORIZED_FLAG), bool(true))); + } + return iff(equals(ref('util.authType()'), str(API_KEY_AUTH_TYPE)), compoundExpression(expression)); +}; + +/** + * No need to combine allowed fields as the request can only be signed by one iam role + * @param roles + * @returns + */ +const iamExpression = (roles: Array, hasAdminUIEnabled: boolean = false, adminUserPoolID?: string) => { + const expression = new Array(); + // allow if using admin ui + if (hasAdminUIEnabled) { + expression.push( + iff( + or([ + methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID!}${ADMIN_ROLE}`)), + methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID!}${MANAGE_ROLE}`)), + ]), + raw('#return($util.toJson({})'), + ), + ); + } + if (roles.length > 0) { + for (let role of roles) { + if (role.allowedFields!.length > 0) { + expression.push( + iamCheck(role.claim!, compoundExpression([set(ref(`${ALLOWED_FIELDS}`), raw(JSON.stringify(role.allowedFields)))])), + ); + } else { + expression.push(iamCheck(role.claim!, set(ref(IS_AUTHORIZED_FLAG), bool(true)))); + } + } + } else { + expression.push(ref('util.unauthorized()')); + } + return iff(equals(ref('util.authType()'), str(IAM_AUTH_TYPE)), compoundExpression(expression)); +}; + +const generateStaticRoleExpression = (roles: Array): Array => { + const staticRoleExpression: Array = new Array(); + const privateRoleIdx = roles.findIndex(r => r.strategy === 'private'); + if (privateRoleIdx > -1) { + const privateRole = roles[privateRoleIdx]; + if (privateRole.allowedFields!.length > 0) { + staticRoleExpression.push(qref(methodCall(ref(`${ALLOWED_FIELDS}.addAll`), raw(JSON.stringify(privateRole.allowedFields))))); + } else { + staticRoleExpression.push(set(ref(IS_AUTHORIZED_FLAG), bool(true))); + } + roles.splice(privateRoleIdx, 1); + } + if (roles.length > 0) { + staticRoleExpression.push( + iff( + not(ref(IS_AUTHORIZED_FLAG)), + compoundExpression([ + set( + ref('staticGroupRoles'), + raw(JSON.stringify(roles.map(r => ({ claim: r.claim, entity: r.entity, allowedFields: r.allowedFields ?? [] })))), + ), + forEach(/** for */ ref('groupRole'), /** in */ ref('staticGroupRoles'), [ + set(ref('groupsInToken'), getIdentityClaimExp(ref('groupRole.claim'), list([]))), + iff( + methodCall(ref('groupsInToken.contains'), ref('groupRole.entity')), + addAllowedFieldsIfElse('groupRole.allowedFields', true), + ), + ]), + ]), + ), + ); + } + return staticRoleExpression; +}; + +const dynamicGroupRoleExpression = (roles: Array, fields: ReadonlyArray): Array => { + const ownerExpression = new Array(); + const dynamicGroupExpression = new Array(); + roles.forEach((role, idx) => { + const entityIsList = fieldIsList(fields, role.entity!); + if (role.strategy === 'owner') { + ownerExpression.push( + iff( + not(ref(IS_AUTHORIZED_FLAG)), + compoundExpression([ + set( + ref(`ownerEntity${idx}`), + methodCall(ref('util.defaultIfNull'), ref(`ctx.args.input.${role.entity!}`), entityIsList ? list([]) : nul()), + ), + set(ref(`ownerClaim${idx}`), getOwnerClaim(role.claim!)), + set(ref(`ownerAllowedFields${idx}`), raw(JSON.stringify(role.allowedFields))), + ...(entityIsList + ? [ + forEach(ref('allowedOwner'), ref(`ownerEntity${idx}`), [ + iff(equals(ref('allowedOwner'), ref(`ownerClaim${idx}`)), addAllowedFieldsIfElse(`ownerAllowedFields${idx}`, true)), + ]), + ] + : [iff(equals(ref(`ownerClaim${idx}`), ref(`ownerEntity${idx}`)), addAllowedFieldsIfElse(`ownerAllowedFields${idx}`))]), + iff( + and([isNullOrEmpty(ref(`ownerEntity${idx}`)), not(methodCall(ref('ctx.args.input.containsKey'), str(role.entity!)))]), + compoundExpression([ + qref( + methodCall( + ref('ctx.args.input.put'), + str(role.entity!), + entityIsList ? list([ref(`ownerClaim${idx}`)]) : ref(`ownerClaim${idx}`), + ), + ), + addAllowedFieldsIfElse(`ownerAllowedFields${idx}`), + ]), + ), + ]), + ), + ); + } + if (role.strategy === 'groups') { + dynamicGroupExpression.push( + iff( + not(ref(IS_AUTHORIZED_FLAG)), + compoundExpression([ + set( + ref(`groupEntity${idx}`), + methodCall(ref('util.defaultIfNull'), ref(`ctx.args.input.${role.entity!}`), entityIsList ? list([]) : nul()), + ), + set(ref(`groupClaim${idx}`), getIdentityClaimExp(str(role.claim!), list([]))), + set(ref(`groupAllowedFields${idx}`), raw(JSON.stringify(role.allowedFields))), + forEach(ref('userGroup'), ref(`groupClaim${idx}`), [ + iff( + entityIsList + ? methodCall(ref(`groupEntity${idx}.contains`), ref('userGroup')) + : equals(ref(`groupEntity${idx}`), ref('userGroup')), + addAllowedFieldsIfElse(`groupAllowedFields${idx}`, true), + ), + ]), + ]), + ), + ); + } + }); + + return [...(ownerExpression.length > 0 ? ownerExpression : []), ...(dynamicGroupExpression.length > 0 ? dynamicGroupExpression : [])]; +}; + +/** + * Unauthorized if + * - auth conditions could not be met + * - there are fields conditions that could not be met + * @param providers + * @param roles + * @param fields + * @returns + */ +export const generateAuthExpressionForCreate = ( + providers: ConfiguredAuthProviders, + roles: Array, + fields: ReadonlyArray, +): string => { + const { + cogntoStaticRoles: cognitoStaticGroupRoles, + cognitoDynamicRoles, + oidcStaticRoles: oidcStaticGroupRoles, + oidcDynamicRoles, + apiKeyRoles, + iamRoles, + } = splitRoles(roles); + const totalAuthExpressions: Array = [ + setHasAuthExpression, + getInputFields(), + set(ref(IS_AUTHORIZED_FLAG), bool(false)), + set(ref(ALLOWED_FIELDS), list([])), + ]; + if (providers.hasApiKey) { + totalAuthExpressions.push(apiKeyExpression(apiKeyRoles)); + } + if (providers.hasIAM) { + totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminUIEnabled, providers.adminUserPoolID)); + } + if (providers.hasUserPools) { + totalAuthExpressions.push( + iff( + equals(ref('util.authType()'), str(COGNITO_AUTH_TYPE)), + compoundExpression([ + ...generateStaticRoleExpression(cognitoStaticGroupRoles), + ...dynamicGroupRoleExpression(cognitoDynamicRoles, fields), + ]), + ), + ); + } + if (providers.hasOIDC) { + totalAuthExpressions.push( + iff( + equals(ref('util.authType()'), str(OIDC_AUTH_TYPE)), + compoundExpression([ + ...generateStaticRoleExpression(oidcStaticGroupRoles), + ...dynamicGroupRoleExpression(oidcDynamicRoles, fields), + ]), + ), + ); + } + totalAuthExpressions.push( + iff(and([not(ref(IS_AUTHORIZED_FLAG)), ref(`${ALLOWED_FIELDS}.isEmpty()`)]), ref('util.unauthorized()')), + iff( + not(ref(IS_AUTHORIZED_FLAG)), + compoundExpression([ + set(ref(DENIED_FIELDS), methodCall(ref('util.list.copyAndRemoveAll'), ref('inputFields'), ref(ALLOWED_FIELDS))), + iff( + ref(`${DENIED_FIELDS}.size() > 0`), + methodCall(ref('util.error'), str(`Unauthorized on \${${DENIED_FIELDS}}`), str('Unauthorized')), + ), + ]), + ), + ); + return printBlock('Authorization Steps')(compoundExpression([...totalAuthExpressions, emptyPayload])); +}; diff --git a/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.delete.ts b/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.delete.ts new file mode 100644 index 00000000000..c5656f061dc --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.delete.ts @@ -0,0 +1,189 @@ +import { FieldDefinitionNode } from 'graphql'; +import { + Expression, + printBlock, + compoundExpression, + bool, + equals, + iff, + raw, + ref, + set, + str, + methodCall, + or, + forEach, + list, + not, + nul, +} from 'graphql-mapping-template'; +import { emptyPayload, getIdentityClaimExp, getOwnerClaim, iamCheck, setHasAuthExpression } from './helpers'; +import { + ADMIN_ROLE, + API_KEY_AUTH_TYPE, + COGNITO_AUTH_TYPE, + ConfiguredAuthProviders, + fieldIsList, + IAM_AUTH_TYPE, + IS_AUTHORIZED_FLAG, + MANAGE_ROLE, + OIDC_AUTH_TYPE, + RoleDefinition, + splitRoles, +} from '../utils'; + +/** + * There is only one role for ApiKey we can use the first index + * @param roles + * @returns Expression | null + */ +const apiKeyExpression = (roles: Array) => { + const expression = new Array(); + if (roles.length === 0) { + return iff(equals(ref('util.authType()'), str(API_KEY_AUTH_TYPE)), ref('util.unauthorized()')); + } + if (roles.length > 0) { + expression.push(set(ref(IS_AUTHORIZED_FLAG), bool(true))); + } + return iff(equals(ref('util.authType()'), str(API_KEY_AUTH_TYPE)), compoundExpression(expression)); +}; +/** + * No need to combine allowed fields as the request can only be signed by one iam role + * @param roles + * @returns + */ +const iamExpression = (roles: Array, hasAdminUIEnabled: boolean = false, adminUserPoolID?: string) => { + const expression = new Array(); + // allow if using admin ui + if (hasAdminUIEnabled) { + expression.push( + iff( + or([ + methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID}${ADMIN_ROLE}`)), + methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID}${MANAGE_ROLE}`)), + ]), + raw('#return($util.toJson({})'), + ), + ); + } + if (roles.length > 0) { + for (let role of roles) { + iamCheck(role.claim!, set(ref(IS_AUTHORIZED_FLAG), bool(true))); + } + } else { + expression.push(ref('util.unauthorized()')); + } + return iff(equals(ref('util.authType()'), str(IAM_AUTH_TYPE)), compoundExpression(expression)); +}; + +const generateStaticRoleExpression = (roles: Array): Array => { + const staticRoleExpression: Array = new Array(); + const privateRoleIdx = roles.findIndex(r => r.strategy === 'private'); + if (privateRoleIdx > -1) { + staticRoleExpression.push(set(ref(IS_AUTHORIZED_FLAG), bool(true))); + roles.splice(privateRoleIdx, -1); + } + if (roles.length > 0) { + staticRoleExpression.push( + iff( + not(ref(IS_AUTHORIZED_FLAG)), + compoundExpression([ + set(ref('staticGroupRoles'), raw(JSON.stringify(roles.map(r => ({ claim: r.claim, entity: r.entity }))))), + forEach(/** for */ ref('groupRole'), /** in */ ref('staticGroupRoles'), [ + set(ref('groupsInToken'), getIdentityClaimExp(ref('groupRole.claim'), list([]))), + iff( + methodCall(ref('groupsInToken.contains'), ref('groupRole.entity')), + compoundExpression([set(ref(IS_AUTHORIZED_FLAG), bool(true)), raw('#break')]), + ), + ]), + ]), + ), + ); + } + return staticRoleExpression; +}; + +const dynamicGroupRoleExpression = (roles: Array, fields: ReadonlyArray) => { + const ownerExpression = new Array(); + const dynamicGroupExpression = new Array(); + roles.forEach((role, idx) => { + const entityIsList = fieldIsList(fields, role.entity!); + if (role.strategy === 'owner') { + ownerExpression.push( + iff( + not(ref(IS_AUTHORIZED_FLAG)), + compoundExpression([ + set(ref(`ownerEntity${idx}`), methodCall(ref('util.defaultIfNull'), ref(`ctx.result.${role.entity!}`), nul())), + set(ref(`ownerClaim${idx}`), getOwnerClaim(role.claim!)), + ...(entityIsList + ? [ + forEach(ref('allowedOwner'), ref(`ownerEntity${idx}`), [ + iff(equals(ref('allowedOwner'), ref(`ownerClaim${idx}`)), set(ref(IS_AUTHORIZED_FLAG), bool(true))), + ]), + ] + : [iff(equals(ref(`ownerEntity${idx}`), ref(`ownerClaim${idx}`)), set(ref(IS_AUTHORIZED_FLAG), bool(true)))]), + ]), + ), + ); + } + if (role.strategy === 'groups') { + dynamicGroupExpression.push( + iff( + not(ref(IS_AUTHORIZED_FLAG)), + compoundExpression([ + set( + ref(`groupEntity${idx}`), + methodCall(ref('util.defaultIfNull'), ref(`ctx.result.${role.entity}`), entityIsList ? list([]) : nul()), + ), + set(ref(`groupClaim${idx}`), getIdentityClaimExp(str(role.claim!), list([]))), + forEach(ref('userGroup'), ref(`groupClaim${idx}`), [ + iff( + entityIsList + ? methodCall(ref(`groupEntity${idx}.contains`), ref('userGroup')) + : equals(ref(`groupEntity${idx}`), ref('userGroup')), + set(ref(IS_AUTHORIZED_FLAG), bool(true)), + ), + ]), + ]), + ), + ); + } + }); + return [...(ownerExpression.length > 0 ? ownerExpression : []), ...(dynamicGroupExpression.length > 0 ? dynamicGroupExpression : [])]; +}; + +export const geneateAuthExpressionForDelete = ( + providers: ConfiguredAuthProviders, + roles: Array, + fields: ReadonlyArray, +) => { + const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, apiKeyRoles, iamRoles } = splitRoles(roles); + const totalAuthExpressions: Array = [setHasAuthExpression, set(ref(IS_AUTHORIZED_FLAG), bool(false))]; + if (providers.hasApiKey) { + totalAuthExpressions.push(apiKeyExpression(apiKeyRoles)); + } + if (providers.hasIAM) { + totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminUIEnabled, providers.adminUserPoolID)); + } + if (providers.hasUserPools) { + totalAuthExpressions.push( + iff( + equals(ref('util.authType()'), str(COGNITO_AUTH_TYPE)), + compoundExpression([ + ...generateStaticRoleExpression(cogntoStaticRoles), + ...dynamicGroupRoleExpression(cognitoDynamicRoles, fields), + ]), + ), + ); + } + if (providers.hasOIDC) { + totalAuthExpressions.push( + iff( + equals(ref('util.authType()'), str(OIDC_AUTH_TYPE)), + compoundExpression([...generateStaticRoleExpression(oidcStaticRoles), ...dynamicGroupRoleExpression(oidcDynamicRoles, fields)]), + ), + ); + } + totalAuthExpressions.push(iff(not(ref(IS_AUTHORIZED_FLAG)), ref('util.unauthorized()'))); + return printBlock('Authorization Steps')(compoundExpression([...totalAuthExpressions, emptyPayload])); +}; diff --git a/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.update.ts b/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.update.ts new file mode 100644 index 00000000000..a58101a3ce3 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.update.ts @@ -0,0 +1,318 @@ +import { FieldDefinitionNode } from 'graphql'; +import { + compoundExpression, + iff, + raw, + set, + ref, + forEach, + bool, + Expression, + not, + obj, + list, + qref, + equals, + str, + and, + methodCall, + toJson, + printBlock, + ifElse, + nul, + or, +} from 'graphql-mapping-template'; +import { + ADMIN_ROLE, + API_KEY_AUTH_TYPE, + COGNITO_AUTH_TYPE, + ConfiguredAuthProviders, + IAM_AUTH_TYPE, + MANAGE_ROLE, + OIDC_AUTH_TYPE, + RoleDefinition, + splitRoles, + fieldIsList, + IS_AUTHORIZED_FLAG, + ALLOWED_FIELDS, + NULL_ALLOWED_FIELDS, + DENIED_FIELDS, +} from '../utils'; +import { getIdentityClaimExp, responseCheckForErrors, getOwnerClaim, getInputFields, setHasAuthExpression, iamCheck } from './helpers'; + +/** + * There is only one role for ApiKey we can use the first index + * @param roles + * @returns Expression | null + */ +const apiKeyExpression = (roles: Array) => { + const expression = new Array(); + if (roles.length === 0) { + return iff(equals(ref('util.authType()'), str(API_KEY_AUTH_TYPE)), ref('util.unauthorized()')); + } + if (roles[0].allowedFields!.length > 0 || roles[0].nullAllowedFields!.length > 0) { + expression.push( + set(ref(`${ALLOWED_FIELDS}`), raw(JSON.stringify(roles[0].allowedFields))), + set(ref(`${NULL_ALLOWED_FIELDS}`), raw(JSON.stringify(roles[0].nullAllowedFields))), + ); + } else { + expression.push(set(ref(IS_AUTHORIZED_FLAG), bool(true))); + } + return iff(equals(ref('util.authType()'), str(API_KEY_AUTH_TYPE)), compoundExpression(expression)); +}; + +const iamExpression = (roles: Array, hasAdminUIEnabled: boolean = false, adminUserPoolID?: string) => { + const expression = new Array(); + // allow if using admin ui + if (hasAdminUIEnabled) { + expression.push( + iff( + or([ + methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID}${ADMIN_ROLE}`)), + methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID}${MANAGE_ROLE}`)), + ]), + raw('#return($util.toJson({})'), + ), + ); + } + if (roles.length > 0) { + for (let role of roles) { + if (role.allowedFields!.length > 0 || role.nullAllowedFields!.length > 0) { + expression.push( + iamCheck( + role.claim!, + compoundExpression([ + set(ref(`${ALLOWED_FIELDS}`), raw(JSON.stringify(role.allowedFields))), + set(ref(`${NULL_ALLOWED_FIELDS}`), raw(JSON.stringify(role.nullAllowedFields))), + ]), + ), + ); + } else { + iamCheck(role.claim!, set(ref(IS_AUTHORIZED_FLAG), bool(true))); + } + } + } else { + expression.push(ref('util.unauthorized()')); + } + return iff(equals(ref('util.authType()'), str(IAM_AUTH_TYPE)), compoundExpression(expression)); +}; + +const generateStaticRoleExpression = (roles: Array) => { + const staticRoleExpression: Array = new Array(); + const privateRoleIdx = roles.findIndex(r => r.strategy === 'private'); + if (privateRoleIdx > -1) { + const privateRole = roles[privateRoleIdx]; + if (privateRole.allowedFields!.length > 0 || privateRole.nullAllowedFields!.length > 0) { + staticRoleExpression.push( + qref(methodCall(ref(`${ALLOWED_FIELDS}.addAll`), raw(JSON.stringify(privateRole.allowedFields)))), + qref(methodCall(ref(`${NULL_ALLOWED_FIELDS}.addAll`), raw(JSON.stringify(privateRole.nullAllowedFields)))), + ); + } else { + staticRoleExpression.push(set(ref(IS_AUTHORIZED_FLAG), bool(true))); + } + roles.splice(privateRoleIdx, 1); + } + if (roles.length > 0) { + staticRoleExpression.push( + iff( + not(ref(IS_AUTHORIZED_FLAG)), + compoundExpression([ + set( + ref('staticGroupRoles'), + raw( + JSON.stringify( + roles.map(r => ({ + claim: r.claim, + entity: r.entity, + allowedFields: r.allowedFields, + nullAllowedFields: r.nullAllowedFields, + })), + ), + ), + ), + forEach(/** for */ ref('groupRole'), /** in */ ref('staticGroupRoles'), [ + set(ref('groupsInToken'), getIdentityClaimExp(ref('groupRole.claim'), list([]))), + iff( + methodCall(ref('groupsInToken.contains'), ref('groupRole.entity')), + compoundExpression([ + // if we find that it's not fully allowed on update (update/delete) we add the field conditions + // otherwise we set to true and break + ifElse( + or([not(ref(`groupRole.allowedFields.isEmpty()`)), not(ref('groupRole.nullAllowedFields.isEmpty()'))]), + compoundExpression([ + qref(methodCall(ref(`${ALLOWED_FIELDS}.addAll`), ref('groupRole.allowedFields'))), + qref(methodCall(ref(`${NULL_ALLOWED_FIELDS}.addAll`), ref('groupRole.nullAllowedFields'))), + ]), + compoundExpression([set(ref(IS_AUTHORIZED_FLAG), bool(true)), raw('#break')]), + ), + ]), + ), + ]), + ]), + ), + ); + } + return staticRoleExpression; +}; +const dynamicGroupRoleExpression = (roles: Array, fields: ReadonlyArray): Array => { + const ownerExpression = new Array(); + const dynamicGroupExpression = new Array(); + roles.forEach((role, idx) => { + const entityIsList = fieldIsList(fields, role.entity!); + if (role.strategy === 'owner') { + ownerExpression.push( + iff( + not(ref(IS_AUTHORIZED_FLAG)), + compoundExpression([ + set( + ref(`ownerEntity${idx}`), + methodCall(ref('util.defaultIfNull'), ref(`ctx.result.${role.entity!}`), entityIsList ? list([]) : nul()), + ), + set(ref(`ownerClaim${idx}`), getOwnerClaim(role.claim!)), + set(ref(`ownerAllowedFields${idx}`), raw(JSON.stringify(role.allowedFields))), + set(ref(`ownerNullAllowedFields${idx}`), raw(JSON.stringify(role.nullAllowedFields))), + ...(entityIsList + ? [ + forEach(ref('allowedOwner'), ref(`ownerEntity${idx}`), [ + iff( + equals(ref('allowedOwner'), ref(`ownerClaim${idx}`)), + ifElse( + or([not(ref(`ownerAllowedFields${idx}.isEmpty()`)), not(ref(`ownerNullAllowedFields${idx}.isEmpty()`))]), + compoundExpression([ + qref(methodCall(ref(`${ALLOWED_FIELDS}.addAll`), ref(`ownerAllowedFields${idx}`))), + qref(methodCall(ref(`${NULL_ALLOWED_FIELDS}.addAll`), ref(`ownerNullAllowedFields${idx}`))), + ]), + compoundExpression([set(ref(IS_AUTHORIZED_FLAG), bool(true)), raw('#break')]), + ), + ), + ]), + ] + : [ + iff( + equals(ref(`ownerEntity${idx}`), ref(`ownerClaim${idx}`)), + ifElse( + or([not(ref(`ownerAllowedFields${idx}.isEmpty()`)), not(ref(`ownerNullAllowedFields${idx}.isEmpty()`))]), + compoundExpression([ + qref(methodCall(ref(`${ALLOWED_FIELDS}.addAll`), ref(`ownerAllowedFields${idx}`))), + qref(methodCall(ref(`${NULL_ALLOWED_FIELDS}.addAll`), ref(`ownerNullAllowedFields${idx}`))), + ]), + compoundExpression([set(ref(IS_AUTHORIZED_FLAG), bool(true))]), + ), + ), + ]), + ]), + ), + ); + } + if (role.strategy === 'groups') { + dynamicGroupExpression.push( + iff( + not(ref(IS_AUTHORIZED_FLAG)), + compoundExpression([ + set( + ref(`groupEntity${idx}`), + methodCall(ref('util.defaultIfNull'), ref(`ctx.result.${role.entity}`), entityIsList ? list([]) : nul()), + ), + set(ref(`groupClaim${idx}`), getIdentityClaimExp(str(role.claim!), list([]))), + set(ref(`groupAllowedFields${idx}`), raw(JSON.stringify(role.allowedFields))), + set(ref(`groupNullAllowedFields${idx}`), raw(JSON.stringify(role.nullAllowedFields))), + forEach(ref('userGroup'), ref(`groupClaim${idx}`), [ + iff( + entityIsList + ? methodCall(ref(`groupEntity${idx}.contains`), ref('userGroup')) + : equals(ref(`groupEntity${idx}`), ref('userGroup')), + ifElse( + or([not(ref(`groupAllowedFields${idx}.isEmpty()`)), not(ref(`groupNullAllowedFields${idx}.isEmpty()`))]), + compoundExpression([ + qref(methodCall(ref(`${ALLOWED_FIELDS}.addAll`), ref('groupRole.allowedFields'))), + qref(methodCall(ref(`${NULL_ALLOWED_FIELDS}.addAll`), ref('groupRole.nullAllowedFields'))), + ]), + compoundExpression([set(ref(IS_AUTHORIZED_FLAG), bool(true)), raw('#break')]), + ), + ), + ]), + ]), + ), + ); + } + }); + return [...(ownerExpression.length > 0 ? ownerExpression : []), ...(dynamicGroupExpression.length > 0 ? dynamicGroupExpression : [])]; +}; + +/** + * For update we need to check for allowed fields and null allowed fields + * unauthorized if + * - none of the roles have been met and there are no field conditions + * - role is partially allowed but the field conditions have not been met + * @param providers + * @param roles + * @param fields + * @returns + */ +export const generateAuthExpressionForUpdate = ( + providers: ConfiguredAuthProviders, + roles: Array, + fields: ReadonlyArray, +) => { + const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, apiKeyRoles, iamRoles } = splitRoles(roles); + const totalAuthExpressions: Array = [ + setHasAuthExpression, + responseCheckForErrors(), + getInputFields(), + set(ref(IS_AUTHORIZED_FLAG), bool(false)), + set(ref(`${ALLOWED_FIELDS}`), list([])), + set(ref(`${NULL_ALLOWED_FIELDS}`), list([])), + set(ref(`${DENIED_FIELDS}`), obj({})), + ]; + if (providers.hasApiKey) { + totalAuthExpressions.push(apiKeyExpression(apiKeyRoles)); + } + if (providers.hasIAM) { + totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminUIEnabled, providers.adminUserPoolID)); + } + if (providers.hasUserPools) { + totalAuthExpressions.push( + iff( + equals(ref('util.authType()'), str(COGNITO_AUTH_TYPE)), + compoundExpression([ + ...generateStaticRoleExpression(cogntoStaticRoles), + ...dynamicGroupRoleExpression(cognitoDynamicRoles, fields), + ]), + ), + ); + } + if (providers.hasOIDC) { + totalAuthExpressions.push( + iff( + equals(ref('util.authType()'), str(OIDC_AUTH_TYPE)), + compoundExpression([...generateStaticRoleExpression(oidcStaticRoles), ...dynamicGroupRoleExpression(oidcDynamicRoles, fields)]), + ), + ); + } + totalAuthExpressions.push( + iff( + and([not(ref(IS_AUTHORIZED_FLAG)), ref(`${ALLOWED_FIELDS}.isEmpty()`), ref(`${NULL_ALLOWED_FIELDS}.isEmpty()`)]), + ref('util.unauthorized()'), + ), + // if not authorized we check the field conditions + iff( + not(ref(IS_AUTHORIZED_FLAG)), + compoundExpression([ + forEach(ref('entry'), ref('util.map.copyAndRetainAllKeys($ctx.args.input, $inputFields).entrySet()'), [ + iff( + and([methodCall(ref('util.isNull'), ref('entry.value')), not(ref(`${NULL_ALLOWED_FIELDS}.contains($entry.value)`))]), + qref(methodCall(ref(`${DENIED_FIELDS}.put`), ref('entry.key'), str(''))), + ), + ]), + forEach(ref('deniedField'), ref(`util.list.copyAndRemoveAll($inputFields, \$${ALLOWED_FIELDS})`), [ + qref(methodCall(ref(`${DENIED_FIELDS}.put`), ref('deniedField'), str(''))), + ]), + ]), + ), + iff( + ref(`${DENIED_FIELDS}.keySet().size() > 0`), + methodCall(ref('util.error'), str(`Unauthorized on \${${DENIED_FIELDS}.keySet()}`), str('Unauthorized')), + ), + ); + return printBlock('Authorization Steps')(compoundExpression([...totalAuthExpressions, toJson(obj({}))])); +}; diff --git a/packages/amplify-graphql-auth-transformer/src/resolvers/query.ts b/packages/amplify-graphql-auth-transformer/src/resolvers/query.ts new file mode 100644 index 00000000000..fc244d65912 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/resolvers/query.ts @@ -0,0 +1,204 @@ +import { FieldDefinitionNode } from 'graphql'; +import { + compoundExpression, + Expression, + obj, + printBlock, + and, + equals, + iff, + methodCall, + not, + ref, + str, + bool, + forEach, + list, + qref, + raw, + set, +} from 'graphql-mapping-template'; +import { getIdentityClaimExp, getOwnerClaim, apiKeyExpression, iamExpression, emptyPayload, setHasAuthExpression } from './helpers'; +import { + COGNITO_AUTH_TYPE, + OIDC_AUTH_TYPE, + RoleDefinition, + splitRoles, + ConfiguredAuthProviders, + IS_AUTHORIZED_FLAG, + fieldIsList, + QuerySource, +} from '../utils'; +import { InvalidDirectiveError } from '@aws-amplify/graphql-transformer-core'; +import { NONE_VALUE } from 'graphql-transformer-common'; + +const generateStaticRoleExpression = (roles: Array): Array => { + const staticRoleExpression: Array = []; + let privateRoleIdx = roles.findIndex(r => r.strategy === 'private'); + if (privateRoleIdx > -1) { + staticRoleExpression.push(set(ref(IS_AUTHORIZED_FLAG), bool(true))); + roles.splice(privateRoleIdx, 1); + } + if (roles.length > 0) { + staticRoleExpression.push( + iff( + not(ref(IS_AUTHORIZED_FLAG)), + compoundExpression([ + set(ref('staticGroupRoles'), raw(JSON.stringify(roles.map(r => ({ claim: r.claim, entity: r.entity }))))), + forEach(ref('groupRole'), ref('staticGroupRoles'), [ + set(ref('groupsInToken'), getIdentityClaimExp(ref('groupRole.claim'), list([]))), + iff( + methodCall(ref('groupsInToken.contains'), ref('groupRole.entity')), + compoundExpression([set(ref(IS_AUTHORIZED_FLAG), bool(true)), raw(`#break`)]), + ), + ]), + ]), + ), + ); + } + return staticRoleExpression; +}; + +const generateAuthFilter = ( + roles: Array, + fields: ReadonlyArray, + querySource: QuerySource, +): Array => { + const authFilter = new Array(); + const groupMap = new Map>(); + const groupContainsExpression = new Array(); + if (!(roles.length > 0)) return []; + /** + * if ownerField is string + * ownerField: { eq: "cognito:owner" } + * if ownerField is a List + * ownerField: { contains: "cognito:owner"} + * + * if groupsField is a string + * groupsField: { in: "cognito:groups" } + * if groupsField is a list + * groupsField: { contains: "cognito:groups" } + * */ + if (querySource === 'dynamodb') { + for (let role of roles) { + const entityIsList = fieldIsList(fields, role.entity!); + if (role.strategy === 'owner') { + const ownerCondition = entityIsList ? 'contains' : 'eq'; + authFilter.push(obj({ [role.entity!]: obj({ [ownerCondition]: getOwnerClaim(role.claim!) }) })); + } + if (role.strategy === 'groups') { + // for fields where the group is a list and the token is a list we must add every group in the claim + if (entityIsList) { + if (groupMap.has(role.claim!)) { + groupMap.get(role.claim).push(role.entity); + } else { + groupMap.set(role.claim!, [role.entity]); + } + } else { + authFilter.push(obj({ [role.entity!]: obj({ in: getIdentityClaimExp(str(role.claim!), list([str(NONE_VALUE)])) }) })); + } + } + } + for (let [groupClaim, fieldList] of groupMap) { + groupContainsExpression.push( + forEach( + ref('group'), + ref(`util.defaultIfNull($ctx.identity.claims.get("${groupClaim}"), ["${NONE_VALUE}"])`), + fieldList.map(field => qref(methodCall(ref('authFilter.add'), raw(`{"${field}": { "contains": $group }}`)))), + ), + ); + } + return [ + iff( + not(ref(IS_AUTHORIZED_FLAG)), + compoundExpression([ + set(ref('authFilter'), list(authFilter)), + ...(groupContainsExpression.length > 0 ? groupContainsExpression : []), + qref(methodCall(ref('ctx.stash.put'), str('authFilter'), raw('{ "or": $authFilter }'))), + ]), + ), + ]; + } + if (querySource === 'opensearch') { + for (let role of roles) { + let claimValue: Expression; + if (role.strategy === 'owner') { + claimValue = getOwnerClaim(role.claim!); + authFilter.push( + obj({ + terms_set: obj({ + [role.entity!]: obj({ + terms: list([claimValue]), + minimum_should_match_script: obj({ source: str('1') }), + }), + }), + }), + ); + } else if (role.strategy === 'groups') { + claimValue = getIdentityClaimExp(str(role.claim!), list([str(NONE_VALUE)])); + authFilter.push( + obj({ + terms_set: obj({ + [role.entity!]: obj({ + terms: claimValue, + minimum_should_match_script: obj({ source: str('1') }), + }), + }), + }), + ); + } + } + return [ + iff( + not(ref(IS_AUTHORIZED_FLAG)), + qref(methodCall(ref('ctx.stash.put'), str('authFilter'), obj({ bool: obj({ should: list(authFilter) }) }))), + ), + ]; + } + throw new InvalidDirectiveError(`Could not generate an auth filter for a ${querySource} datasource.`); +}; + +export const generateAuthExpressionForQueries = ( + providers: ConfiguredAuthProviders, + roles: Array, + fields: ReadonlyArray, + querySource: QuerySource = 'dynamodb', +): string => { + const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, apiKeyRoles, iamRoles } = splitRoles(roles); + const totalAuthExpressions: Array = [setHasAuthExpression, set(ref(IS_AUTHORIZED_FLAG), bool(false))]; + if (providers.hasApiKey) { + totalAuthExpressions.push(apiKeyExpression(apiKeyRoles)); + } + if (providers.hasIAM) { + totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminUIEnabled, providers.adminUserPoolID)); + } + if (providers.hasUserPools) { + totalAuthExpressions.push( + iff( + equals(ref('util.authType()'), str(COGNITO_AUTH_TYPE)), + compoundExpression([ + ...generateStaticRoleExpression(cogntoStaticRoles), + ...generateAuthFilter(cognitoDynamicRoles, fields, querySource), + ]), + ), + ); + } + if (providers.hasOIDC) { + totalAuthExpressions.push( + iff( + equals(ref('util.authType()'), str(OIDC_AUTH_TYPE)), + compoundExpression([ + ...generateAuthFilter(oidcDynamicRoles, fields, querySource), + ...generateStaticRoleExpression(oidcStaticRoles), + ]), + ), + ); + } + totalAuthExpressions.push( + iff( + and([not(ref(IS_AUTHORIZED_FLAG)), methodCall(ref('util.isNullOrEmpty'), methodCall(ref('ctx.stash.get'), str('authFilter')))]), + ref('util.unauthorized()'), + ), + ); + return printBlock('Authorization Steps')(compoundExpression([...totalAuthExpressions, emptyPayload])); +}; diff --git a/packages/amplify-graphql-auth-transformer/src/resolvers/subscriptions.ts b/packages/amplify-graphql-auth-transformer/src/resolvers/subscriptions.ts new file mode 100644 index 00000000000..9f5add04279 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/resolvers/subscriptions.ts @@ -0,0 +1,65 @@ +import { + bool, + compoundExpression, + equals, + Expression, + iff, + methodCall, + not, + ref, + set, + str, + list, + nul, + printBlock, +} from 'graphql-mapping-template'; +import { COGNITO_AUTH_TYPE, ConfiguredAuthProviders, IS_AUTHORIZED_FLAG, OIDC_AUTH_TYPE, RoleDefinition, splitRoles } from '../utils'; +import { generateStaticRoleExpression, getOwnerClaim, apiKeyExpression, iamExpression, emptyPayload } from './helpers'; + +const dynamicRoleExpression = (roles: Array): Array => { + const ownerExpression = new Array(); + // we only check against owner rules which are not list fields + roles.forEach((role, idx) => { + if (role.strategy === 'owner') { + ownerExpression.push( + iff( + not(ref(IS_AUTHORIZED_FLAG)), + compoundExpression([ + set(ref(`ownerEntity${idx}`), methodCall(ref('util.defaultIfNull'), ref(`ctx.args.${role.entity!}`), nul())), + set(ref(`ownerClaim${idx}`), getOwnerClaim(role.claim!)), + iff(equals(ref(`ownerEntity${idx}`), ref(`ownerClaim${idx}`)), set(ref(IS_AUTHORIZED_FLAG), bool(true))), + ]), + ), + ); + } + }); + + return [...(ownerExpression.length > 0 ? ownerExpression : [])]; +}; + +export const generateAuthExpressionForSubscriptions = (providers: ConfiguredAuthProviders, roles: Array): string => { + const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, iamRoles, apiKeyRoles } = splitRoles(roles); + const totalAuthExpressions: Array = [set(ref(IS_AUTHORIZED_FLAG), bool(false)), set(ref('allowedFields'), list([]))]; + if (providers.hasApiKey) { + totalAuthExpressions.push(apiKeyExpression(apiKeyRoles)); + } + if (providers.hasIAM) { + totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminUIEnabled, providers.adminUserPoolID)); + } + if (providers.hasUserPools) + totalAuthExpressions.push( + iff( + equals(ref('util.authType()'), str(COGNITO_AUTH_TYPE)), + compoundExpression([...generateStaticRoleExpression(cogntoStaticRoles), ...dynamicRoleExpression(cognitoDynamicRoles)]), + ), + ); + if (providers.hasOIDC) + totalAuthExpressions.push( + iff( + equals(ref('util.authType()'), str(OIDC_AUTH_TYPE)), + compoundExpression([...generateStaticRoleExpression(oidcStaticRoles), ...dynamicRoleExpression(oidcDynamicRoles)]), + ), + ); + totalAuthExpressions.push(iff(not(ref(IS_AUTHORIZED_FLAG)), ref('util.unauthorized()'))); + return printBlock('Authorization Steps')(compoundExpression([...totalAuthExpressions, emptyPayload])); +}; diff --git a/packages/amplify-graphql-auth-transformer/src/utils/constants.ts b/packages/amplify-graphql-auth-transformer/src/utils/constants.ts new file mode 100644 index 00000000000..7b9d3cb428d --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/utils/constants.ts @@ -0,0 +1,32 @@ +import { AuthProvider, ModelOperation } from './definitions'; +export const DEFAULT_OWNER_FIELD = 'owner'; +export const DEFAULT_GROUPS_FIELD = 'groups'; +export const DEFAULT_IDENTITY_CLAIM = 'username'; +export const DEFAULT_COGNITO_IDENTITY_CLAIM = 'cognito:username'; +export const DEFAULT_GROUP_CLAIM = 'cognito:groups'; +export const ON_CREATE_FIELD = 'onCreate'; +export const ON_UPDATE_FIELD = 'onUpdate'; +export const ON_DELETE_FIELD = 'onDelete'; +export const AUTH_NON_MODEL_TYPES = 'authNonModelTypes'; +export const MODEL_OPERATIONS: ModelOperation[] = ['create', 'read', 'update', 'delete']; +export const AUTH_PROVIDER_DIRECTIVE_MAP = new Map([ + ['apiKey', 'aws_api_key'], + ['iam', 'aws_iam'], + ['oidc', 'aws_oidc'], + ['userPools', 'aws_cognito_user_pools'], +]); +// values for $util.authType() https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference.html +export const COGNITO_AUTH_TYPE = 'User Pool Authorization'; +export const OIDC_AUTH_TYPE = 'Open ID Connect Authorization'; +export const IAM_AUTH_TYPE = 'IAM Authorization'; +export const API_KEY_AUTH_TYPE = 'API Key Authorization'; +// resolver refs +export const IS_AUTHORIZED_FLAG = 'isAuthorized'; +export const ALLOWED_FIELDS = 'allowedFields'; +export const NULL_ALLOWED_FIELDS = 'nullAllowedFields'; +export const DENIED_FIELDS = 'deniedFields'; +// Admin Roles +export const ADMIN_ROLE = '_Full-access/CognitoIdentityCredentials'; +export const MANAGE_ROLE = '_Manage-only/CognitoIdentityCredentials'; +// resolver +export const NONE_DS = 'NONE_DS'; diff --git a/packages/amplify-graphql-auth-transformer/src/utils/definitions.ts b/packages/amplify-graphql-auth-transformer/src/utils/definitions.ts new file mode 100644 index 00000000000..786879c3b0e --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/utils/definitions.ts @@ -0,0 +1,99 @@ +import { AppSyncAuthConfiguration } from '@aws-amplify/graphql-transformer-interfaces'; +export type AuthStrategy = 'owner' | 'groups' | 'public' | 'private'; +export type AuthProvider = 'apiKey' | 'iam' | 'oidc' | 'userPools'; +export type ModelQuery = 'get' | 'list'; +export type ModelMutation = 'create' | 'update' | 'delete'; +export type ModelOperation = 'create' | 'update' | 'delete' | 'read'; + +export type QuerySource = 'dynamodb' | 'opensearch'; +export interface SearchableConfig { + queries: { + search: string; + }; +} + +export interface RolesByProvider { + cogntoStaticRoles: Array; + cognitoDynamicRoles: Array; + oidcStaticRoles: Array; + oidcDynamicRoles: Array; + iamRoles: Array; + apiKeyRoles: Array; +} + +export interface AuthRule { + allow: AuthStrategy; + provider?: AuthProvider; + ownerField?: string; + identityClaim?: string; + groupsField?: string; + groupClaim?: string; + groups?: string[]; + operations?: ModelOperation[]; + // Used only for IAM provider to decide if an IAM policy needs to be generated. IAM auth with AdminUI does not need IAM policies + generateIAMPolicy?: boolean; +} + +export interface RoleDefinition { + provider: AuthProvider; + strategy: AuthStrategy; + static: boolean; + claim?: string; + entity?: string; + // specific to mutations + allowedFields?: Array; + nullAllowedFields?: Array; +} + +export interface AuthDirective { + rules: AuthRule[]; +} + +export interface ConfiguredAuthProviders { + default: AuthProvider; + onlyDefaultAuthProviderConfigured: boolean; + hasApiKey: boolean; + hasUserPools: boolean; + hasOIDC: boolean; + hasIAM: boolean; + hasAdminUIEnabled: boolean; + adminUserPoolID?: string; +} + +export interface AuthTransformerConfig { + addAwsIamAuthInOutputSchema: boolean; + authConfig?: AppSyncAuthConfiguration; + adminUserPoolID?: string; +} + +export const authDirectiveDefinition = ` + directive @auth(rules: [AuthRule!]!) on OBJECT | FIELD_DEFINITION + input AuthRule { + allow: AuthStrategy! + provider: AuthProvider + identityClaim: String + groupClaim: String + ownerField: String + groupsField: String + groups: [String] + operations: [ModelOperation] + } + enum AuthStrategy { + owner + groups + private + public + } + enum AuthProvider { + apiKey + iam + oidc + userPools + } + enum ModelOperation { + create + update + delete + read + } +`; diff --git a/packages/amplify-graphql-auth-transformer/src/utils/iam.ts b/packages/amplify-graphql-auth-transformer/src/utils/iam.ts new file mode 100644 index 00000000000..596f976ceb6 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/utils/iam.ts @@ -0,0 +1,70 @@ +import * as cdk from '@aws-cdk/core'; +interface PolicyDocument { + [key: string]: any; +} + +export const createPolicyDocumentForManagedPolicy = (resources: Set) => { + const policyDocuments = new Array(); + let policyDocumentResources = new Array(); + let resourceSize = 0; + + // 6144 bytes is the maximum policy payload size, but there is structural overhead, hence the 6000 bytes + const MAX_BUILT_SIZE_BYTES = 6000; + // The overhead is the amount of static policy arn contents like region, accountid, etc. + // arn:aws:appsync:${AWS::Region}:${AWS::AccountId}:apis/${apiId}/types/${typeName}/fields/${fieldName} + // 16 15 13 5 27 6 X+1 7 Y + // 89 + 11 extra = 100 + const RESOURCE_OVERHEAD = 100; + + const createPolicyDocument = (newPolicyDocumentResources: Array): PolicyDocument => { + return { + Version: '2012-10-17', + Statement: [ + { + Effect: 'Allow', + Action: ['appsync:GraphQL'], + Resource: newPolicyDocumentResources, + }, + ], + }; + }; + + for (const resource of resources) { + // We always have 2 parts, no need to check + const [typeName, fieldName] = resource.split('/'); + + if (fieldName !== 'null') { + policyDocumentResources.push( + cdk.Fn.sub('arn:aws:appsync:${AWS::Region}:${AWS::AccountId}:apis/${apiId}/types/${typeName}/fields/${fieldName}', { + apiId: cdk.Fn.getAtt('GraphQLAPI', 'ApiId').toString(), + typeName, + fieldName, + }).toString(), + ); + resourceSize += RESOURCE_OVERHEAD + typeName.length + fieldName.length; + } else { + policyDocumentResources.push( + cdk.Fn.sub('arn:aws:appsync:${AWS::Region}:${AWS::AccountId}:apis/${apiId}/types/${typeName}/*', { + apiId: cdk.Fn.getAtt('GraphQLAPI', 'ApiId').toString(), + typeName, + }).toString(), + ); + resourceSize = RESOURCE_OVERHEAD + typeName.length; + } + // + // Check size of resource and if needed create a new one and clear the resources and + // reset accumulated size + // + if (resourceSize > MAX_BUILT_SIZE_BYTES) { + const policyDocument = createPolicyDocument(policyDocumentResources.slice(0, policyDocumentResources.length - 1)); + policyDocuments.push(policyDocument); + // Remove all but the last item + policyDocumentResources = policyDocumentResources.slice(-1); + resourceSize = 0; + } + } + if (policyDocumentResources.length > 0) { + policyDocuments.push(createPolicyDocument(policyDocumentResources)); + } + return policyDocuments; +}; diff --git a/packages/amplify-graphql-auth-transformer/src/utils/index.ts b/packages/amplify-graphql-auth-transformer/src/utils/index.ts new file mode 100644 index 00000000000..1b67a600293 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/utils/index.ts @@ -0,0 +1,152 @@ +import { ModelDirectiveConfiguration, SubscriptionLevel } from '@aws-amplify/graphql-model-transformer'; +import { DirectiveWrapper } from '@aws-amplify/graphql-transformer-core'; +import { AppSyncAuthMode } from '@aws-amplify/graphql-transformer-interfaces'; +import { TransformerContextProvider } from '@aws-amplify/graphql-transformer-interfaces'; +import { Stack } from '@aws-cdk/core'; +import { DirectiveNode, ObjectTypeDefinitionNode } from 'graphql'; +import { toCamelCase, plurality, graphqlName, toUpper } from 'graphql-transformer-common'; +import { + AuthProvider, + AuthRule, + AuthTransformerConfig, + ConfiguredAuthProviders, + RoleDefinition, + RolesByProvider, + SearchableConfig, +} from './definitions'; + +export * from './constants'; +export * from './definitions'; +export * from './validations'; +export * from './schema'; +export * from './iam'; + +export const splitRoles = (roles: Array): RolesByProvider => { + return { + cogntoStaticRoles: roles.filter(r => r.static && r.provider === 'userPools'), + cognitoDynamicRoles: roles.filter(r => !r.static && r.provider === 'userPools'), + oidcStaticRoles: roles.filter(r => r.static && r.provider === 'oidc'), + oidcDynamicRoles: roles.filter(r => !r.static && r.provider === 'oidc'), + iamRoles: roles.filter(r => r.provider === 'iam'), + apiKeyRoles: roles.filter(r => r.provider === 'apiKey'), + }; +}; +/** + * Ensure the following defaults + * - provider + * - iam policy generation + */ +export const ensureAuthRuleDefaults = (rules: AuthRule[]) => { + // We assign the default provider if an override is not present make further handling easier. + for (const rule of rules) { + if (!rule.provider) { + switch (rule.allow) { + case 'owner': + case 'groups': + rule.provider = 'userPools'; + break; + case 'private': + rule.provider = 'userPools'; + break; + case 'public': + rule.provider = 'apiKey'; + break; + default: + throw new Error(`Need to specify an allow to assigned a provider: ${rule}`); + } + } + // by default we generate an IAM policy for every rule + if (rule.provider === 'iam' && !rule.generateIAMPolicy) { + rule.generateIAMPolicy = true; + } + } +}; + +export const getModelConfig = (directive: DirectiveNode, typeName: string, isDataStoreEnabled = false): ModelDirectiveConfiguration => { + const directiveWrapped: DirectiveWrapper = new DirectiveWrapper(directive); + const options = directiveWrapped.getArguments({ + queries: { + get: toCamelCase(['get', typeName]), + list: toCamelCase(['list', plurality(typeName, true)]), + ...(isDataStoreEnabled ? { sync: toCamelCase(['sync', plurality(typeName, true)]) } : undefined), + }, + mutations: { + create: toCamelCase(['create', typeName]), + update: toCamelCase(['update', typeName]), + delete: toCamelCase(['delete', typeName]), + }, + subscriptions: { + level: SubscriptionLevel.on, + onCreate: [toCamelCase(['onCreate', typeName])], + onDelete: [toCamelCase(['onDelete', typeName])], + onUpdate: [toCamelCase(['onUpdate', typeName])], + }, + timestamps: { + createdAt: 'createdAt', + updatedAt: 'updatedAt', + }, + }); + return options; +}; + +export const getSearchableConfig = (directive: DirectiveNode, typeName: string): SearchableConfig | null => { + const directiveWrapped: DirectiveWrapper = new DirectiveWrapper(directive); + const options = directiveWrapped.getArguments({ + queries: { + search: graphqlName(`search${plurality(toUpper(typeName), true)}`), + }, + }); + return options; +}; +/** + * gets stack name if the field is paired with function, predictions, or by itself + */ +export const getStackForField = ( + ctx: TransformerContextProvider, + obj: ObjectTypeDefinitionNode, + fieldName: string, + hasModelDirective: boolean, +): Stack => { + const fieldNode = obj.fields.find(f => f.name.value === fieldName); + const fieldDirectives = fieldNode.directives.map(d => d.name.value); + if (fieldDirectives.includes('function')) { + return ctx.stackManager.getStack('FunctionDirectiveStack'); + } else if (fieldDirectives.includes('predictions')) { + return ctx.stackManager.getStack('PredictionsDirectiveStack'); + } else if (hasModelDirective) { + return ctx.stackManager.getStack(obj.name.value); + } else { + return ctx.stackManager.rootStack; + } +}; + +export const getConfiguredAuthProviders = (config: AuthTransformerConfig): ConfiguredAuthProviders => { + const providers = [ + config.authConfig.defaultAuthentication.authenticationType, + ...config.authConfig.additionalAuthenticationProviders.map(p => p.authenticationType), + ]; + const getAuthProvider = (authType: AppSyncAuthMode): AuthProvider => { + switch (authType) { + case 'AMAZON_COGNITO_USER_POOLS': + return 'userPools'; + case 'API_KEY': + return 'apiKey'; + case 'AWS_IAM': + return 'iam'; + case 'OPENID_CONNECT': + return 'oidc'; + } + }; + const hasIAM = providers.some(p => p === 'AWS_IAM'); + const configuredProviders: ConfiguredAuthProviders = { + default: getAuthProvider(config.authConfig.defaultAuthentication.authenticationType), + onlyDefaultAuthProviderConfigured: config.authConfig.additionalAuthenticationProviders.length === 0, + hasAdminUIEnabled: hasIAM && config.addAwsIamAuthInOutputSchema, + adminUserPoolID: config.adminUserPoolID!, + hasApiKey: providers.some(p => p === 'API_KEY'), + hasUserPools: providers.some(p => p === 'AMAZON_COGNITO_USER_POOLS'), + hasOIDC: providers.some(p => p === 'OPENID_CONNECT'), + hasIAM, + }; + return configuredProviders; +}; diff --git a/packages/amplify-graphql-auth-transformer/src/utils/schema.ts b/packages/amplify-graphql-auth-transformer/src/utils/schema.ts new file mode 100644 index 00000000000..d0cb99c4b0e --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/utils/schema.ts @@ -0,0 +1,209 @@ +import { ModelDirectiveConfiguration, SubscriptionLevel } from '@aws-amplify/graphql-model-transformer'; +import { + QueryFieldType, + MutationFieldType, + TransformerTransformSchemaStepContextProvider, +} from '@aws-amplify/graphql-transformer-interfaces'; +import { ObjectTypeDefinitionNode, FieldDefinitionNode, DirectiveNode, NamedTypeNode } from 'graphql'; +import { + blankObjectExtension, + extendFieldWithDirectives, + extensionWithDirectives, + isListType, + makeInputValueDefinition, + makeNamedType, + plurality, + toCamelCase, +} from 'graphql-transformer-common'; +import { RoleDefinition } from './definitions'; + +export const collectFieldNames = (object: ObjectTypeDefinitionNode): Array => { + return object.fields!.map((field: FieldDefinitionNode) => field.name.value); +}; + +export const fieldIsList = (fields: ReadonlyArray, fieldName: string) => { + return fields.some(field => field.name.value === fieldName && isListType(field.type)); +}; + +export const extendTypeWithDirectives = ( + ctx: TransformerTransformSchemaStepContextProvider, + typeName: string, + directives: Array, +): void => { + let objectTypeExtension = blankObjectExtension(typeName); + objectTypeExtension = extensionWithDirectives(objectTypeExtension, directives); + ctx.output.addObjectExtension(objectTypeExtension); +}; + +export const addDirectivesToField = ( + ctx: TransformerTransformSchemaStepContextProvider, + typeName: string, + fieldName: string, + directives: Array, +) => { + const type = ctx.output.getType(typeName) as ObjectTypeDefinitionNode; + if (type) { + const field = type.fields?.find(f => f.name.value === fieldName); + if (field) { + const newFields = [...type.fields!.filter(f => f.name.value !== field.name.value), extendFieldWithDirectives(field, directives)]; + + const newType = { + ...type, + fields: newFields, + }; + + ctx.output.putType(newType); + } + } +}; + +export const addSubscriptionArguments = ( + ctx: TransformerTransformSchemaStepContextProvider, + operationName: string, + subscriptionRoles: Array, +) => { + let subscription = ctx.output.getSubscription()!; + let createField: FieldDefinitionNode = subscription!.fields!.find(field => field.name.value === operationName) as FieldDefinitionNode; + const subcriptionArgumentList = subscriptionRoles.map(role => { + return makeInputValueDefinition(role.entity!, makeNamedType('String')); + }); + createField = { + ...createField, + arguments: subcriptionArgumentList, + }; + subscription = { + ...subscription, + fields: subscription!.fields!.map(field => (field.name.value === operationName ? createField : field)), + }; + ctx.output.putType(subscription); +}; + +export const addDirectivesToOperation = ( + ctx: TransformerTransformSchemaStepContextProvider, + typeName: string, + operationName: string, + directives: Array, +) => { + // add directives to the given operation + addDirectivesToField(ctx, typeName, operationName, directives); + + // add the directives to the result type of the operation + const type = ctx.output.getType(typeName) as ObjectTypeDefinitionNode; + if (type) { + const field = type.fields!.find(f => f.name.value === operationName); + + if (field) { + const returnFieldType = field.type as NamedTypeNode; + + if (returnFieldType.name) { + const returnTypeName = returnFieldType.name.value; + + extendTypeWithDirectives(ctx, returnTypeName, directives); + } + } + } +}; + +export const getQueryFieldNames = ( + modelDirectiveConfig: ModelDirectiveConfiguration, +): Set<{ fieldName: string; typeName: string; type: QueryFieldType }> => { + const fields: Set<{ fieldName: string; typeName: string; type: QueryFieldType }> = new Set(); + if (modelDirectiveConfig?.queries?.get) { + fields.add({ + typeName: 'Query', + fieldName: modelDirectiveConfig.queries.get, + type: QueryFieldType.GET, + }); + } + + if (modelDirectiveConfig?.queries?.list) { + fields.add({ + typeName: 'Query', + fieldName: modelDirectiveConfig.queries.list, + type: QueryFieldType.LIST, + }); + } + + if (modelDirectiveConfig?.queries?.sync) { + fields.add({ + typeName: 'Query', + fieldName: modelDirectiveConfig.queries.sync, + type: QueryFieldType.SYNC, + }); + } + return fields; +}; + +export const getMutationFieldNames = ( + modelDirectiveConfig: ModelDirectiveConfiguration, +): Set<{ fieldName: string; typeName: string; type: MutationFieldType }> => { + // Todo: get fields names from the directives + const getMutationType = (type: string): MutationFieldType => { + switch (type) { + case 'create': + return MutationFieldType.CREATE; + case 'update': + return MutationFieldType.UPDATE; + case 'delete': + return MutationFieldType.DELETE; + default: + throw new Error('Unknown mutation type'); + } + }; + + const fieldNames: Set<{ fieldName: string; typeName: string; type: MutationFieldType }> = new Set(); + for (let [mutationType, mutationName] of Object.entries(modelDirectiveConfig?.mutations || {})) { + if (mutationName) { + fieldNames.add({ + typeName: 'Mutation', + fieldName: mutationName, + type: getMutationType(mutationType), + }); + } + } + + return fieldNames; +}; + +export const getSubscriptionFieldNames = ( + modelDirectiveConfig: ModelDirectiveConfiguration, +): Set<{ + fieldName: string; + typeName: string; +}> => { + const fields: Set<{ + fieldName: string; + typeName: string; + }> = new Set(); + + if (modelDirectiveConfig?.subscriptions?.level === SubscriptionLevel.on) { + if (modelDirectiveConfig?.subscriptions?.onCreate && modelDirectiveConfig.mutations?.create) { + for (const fieldName of modelDirectiveConfig.subscriptions.onCreate) { + fields.add({ + typeName: 'Subscription', + fieldName: fieldName, + }); + } + } + + if (modelDirectiveConfig?.subscriptions?.onUpdate && modelDirectiveConfig.mutations?.update) { + for (const fieldName of modelDirectiveConfig.subscriptions.onUpdate) { + fields.add({ + typeName: 'Subscription', + fieldName: fieldName, + }); + } + } + + if (modelDirectiveConfig?.subscriptions?.onDelete && modelDirectiveConfig.mutations?.delete) { + for (const fieldName of modelDirectiveConfig.subscriptions.onDelete) { + fields.add({ + typeName: 'Subscription', + fieldName: fieldName, + }); + } + } + } + + return fields; +}; diff --git a/packages/amplify-graphql-auth-transformer/src/utils/validations.ts b/packages/amplify-graphql-auth-transformer/src/utils/validations.ts new file mode 100644 index 00000000000..d68646b90e9 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/utils/validations.ts @@ -0,0 +1,123 @@ +import { InvalidDirectiveError } from '@aws-amplify/graphql-transformer-core'; +import { AuthRule, ConfiguredAuthProviders } from './definitions'; + +export const validateRuleAuthStrategy = (rule: AuthRule, configuredAuthProviders: ConfiguredAuthProviders) => { + // + // Groups + // + if (rule.allow === 'groups' && rule.provider !== 'userPools' && rule.provider !== 'oidc') { + throw new InvalidDirectiveError( + `@auth directive with 'groups' strategy only supports 'userPools' and 'oidc' providers, but found '${rule.provider}' assigned.`, + ); + } + if (rule.allow === 'groups' && !rule.groups && !rule.groupsField) { + throw new InvalidDirectiveError(`@auth directive with 'groups' should have a defined groups list or a groupsField.`); + } + + // + // Owner + // + if (rule.allow === 'owner') { + if (rule.provider !== null && rule.provider !== 'userPools' && rule.provider !== 'oidc') { + throw new InvalidDirectiveError( + `@auth directive with 'owner' strategy only supports 'userPools' (default) and 'oidc' providers, but \ +found '${rule.provider}' assigned.`, + ); + } + } + + // + // Public + // + if (rule.allow === 'public') { + if (rule.provider !== null && rule.provider !== 'apiKey' && rule.provider !== 'iam') { + throw new InvalidDirectiveError( + `@auth directive with 'public' strategy only supports 'apiKey' (default) and 'iam' providers, but \ +found '${rule.provider}' assigned.`, + ); + } + } + + // + // Private + // + if (rule.allow === 'private') { + if (rule.provider !== null && rule.provider !== 'userPools' && rule.provider !== 'iam') { + throw new InvalidDirectiveError( + `@auth directive with 'private' strategy only supports 'userPools' (default) and 'iam' providers, but \ +found '${rule.provider}' assigned.`, + ); + } + } + + // + // Validate provider values against project configuration. + // + if (rule.provider === 'apiKey' && configuredAuthProviders.hasApiKey === false) { + throw new InvalidDirectiveError( + `@auth directive with 'apiKey' provider found, but the project has no API Key authentication provider configured.`, + ); + } else if (rule.provider === 'oidc' && configuredAuthProviders.hasOIDC === false) { + throw new InvalidDirectiveError( + `@auth directive with 'oidc' provider found, but the project has no OPENID_CONNECT authentication provider configured.`, + ); + } else if (rule.provider === 'userPools' && configuredAuthProviders.hasUserPools === false) { + throw new InvalidDirectiveError( + `@auth directive with 'userPools' provider found, but the project has no Cognito User Pools authentication provider configured.`, + ); + } else if (rule.provider === 'iam' && configuredAuthProviders.hasIAM === false) { + throw new InvalidDirectiveError( + `@auth directive with 'iam' provider found, but the project has no IAM authentication provider configured.`, + ); + } +}; + +export const validateRules = (rules: AuthRule[], configuredAuthProviders: ConfiguredAuthProviders) => { + for (const rule of rules) { + validateRuleAuthStrategy(rule, configuredAuthProviders); + commonRuleValidation(rule); + } +}; + +export const validateFieldRules = ( + rules: AuthRule[], + isParentTypeBuiltinType: boolean, + parentHasModelDirective: boolean, + authProviderConfig: ConfiguredAuthProviders, +) => { + for (const rule of rules) { + validateRuleAuthStrategy(rule, authProviderConfig); + + if (isParentTypeBuiltinType && rule.operations && rule.operations.length > 0) { + throw new InvalidDirectiveError( + `@auth rules on fields within Query, Mutation, Subscription cannot specify 'operations' argument as these rules \ +are already on an operation already.`, + ); + } + + if (!parentHasModelDirective && rule.operations && rule.operations.length > 0) { + throw new InvalidDirectiveError( + `@auth rules on fields within types that does not have @model directive cannot specify 'operations' argument as there are \ +operations will be generated by the CLI.`, + ); + } + + commonRuleValidation(rule); + } +}; + +// commmon rule validation between obj and field +export const commonRuleValidation = (rule: AuthRule) => { + const { identityClaim, allow, groups, groupsField, groupClaim } = rule; + if (allow === 'groups' && identityClaim) { + throw new InvalidDirectiveError(` + @auth identityClaim can only be used for 'allow: owner'`); + } + if (allow === 'owner' && groupClaim) { + throw new InvalidDirectiveError(` + @auth groupClaim can only be used 'allow: groups'`); + } + if (groupsField && groups) { + throw new InvalidDirectiveError('This rule has groupsField and groups, please use one or the other'); + } +}; diff --git a/packages/amplify-graphql-auth-transformer/tsconfig.json b/packages/amplify-graphql-auth-transformer/tsconfig.json new file mode 100644 index 00000000000..e00f8011a38 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "strict": false, // TODO enable + "rootDir": "src", + "outDir": "lib" + }, + "references": [ + {"path": "../amplify-graphql-transformer-interfaces"}, + {"path": "../amplify-graphql-transformer-core"}, + {"path": "../amplify-graphql-model-transformer"}, + {"path": "../graphql-mapping-template"}, + {"path": "../graphql-transformer-common"} + ] +} diff --git a/packages/amplify-graphql-function-transformer/src/__tests__/__snapshots__/amplify-graphql-function-transformer.test.ts.snap b/packages/amplify-graphql-function-transformer/src/__tests__/__snapshots__/amplify-graphql-function-transformer.test.ts.snap index cd54de62ac8..96ab67a114d 100644 --- a/packages/amplify-graphql-function-transformer/src/__tests__/__snapshots__/amplify-graphql-function-transformer.test.ts.snap +++ b/packages/amplify-graphql-function-transformer/src/__tests__/__snapshots__/amplify-graphql-function-transformer.test.ts.snap @@ -3,7 +3,7 @@ exports[`it generates the expected resources 1`] = ` Object { "InvokeEchofunctionLambdaDataSource.req.vtl": "## [Start] Invoke AWS Lambda data source: EchofunctionLambdaDataSource. ** -{ +$util.toJson({ \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"Invoke\\", \\"payload\\": { @@ -15,7 +15,7 @@ Object { \\"request\\": $util.toJson($ctx.request), \\"prev\\": $util.toJson($ctx.prev) } -} +}) ## [End] Invoke AWS Lambda data source: EchofunctionLambdaDataSource. **", "InvokeEchofunctionLambdaDataSource.res.vtl": "## [Start] Handle error or return result. ** #if( $ctx.error ) @@ -23,11 +23,6 @@ Object { #end $util.toJson($ctx.result) ## [End] Handle error or return result. **", - "Query.echo.req.vtl": "## [Start] Stash resolver specific context.. ** -$util.qr($ctx.stash.put(\\"typeName\\", \\"Query\\")) -$util.qr($ctx.stash.put(\\"fieldName\\", \\"echo\\")) -{} -## [End] Stash resolver specific context.. **", "Query.echo.res.vtl": "$util.toJson($ctx.prev.result)", } `; diff --git a/packages/amplify-graphql-function-transformer/src/__tests__/amplify-graphql-function-transformer.test.ts b/packages/amplify-graphql-function-transformer/src/__tests__/amplify-graphql-function-transformer.test.ts index 7f0ee96fc67..4f3dc104065 100644 --- a/packages/amplify-graphql-function-transformer/src/__tests__/amplify-graphql-function-transformer.test.ts +++ b/packages/amplify-graphql-function-transformer/src/__tests__/amplify-graphql-function-transformer.test.ts @@ -116,9 +116,7 @@ test('it generates the expected resources', () => { PipelineConfig: { Functions: [{ 'Fn::GetAtt': [anything(), 'FunctionId'] }], }, - RequestMappingTemplateS3Location: { - 'Fn::Join': ['', ['s3://', { Ref: anything() }, '/', { Ref: anything() }, '/pipelineFunctions/Query.echo.req.vtl']], - }, + RequestMappingTemplate: anything(), ResponseMappingTemplateS3Location: { 'Fn::Join': ['', ['s3://', { Ref: anything() }, '/', { Ref: anything() }, '/pipelineFunctions/Query.echo.res.vtl']], }, diff --git a/packages/amplify-graphql-function-transformer/src/graphql-function-transformer.ts b/packages/amplify-graphql-function-transformer/src/graphql-function-transformer.ts index c6a193ddd58..2fd2e60cd5b 100644 --- a/packages/amplify-graphql-function-transformer/src/graphql-function-transformer.ts +++ b/packages/amplify-graphql-function-transformer/src/graphql-function-transformer.ts @@ -1,8 +1,15 @@ -import { DirectiveWrapper, MappingTemplate, TransformerPluginBase } from '@aws-amplify/graphql-transformer-core'; +import { + DirectiveWrapper, + IAM_AUTH_ROLE_PARAMETER, + IAM_UNAUTH_ROLE_PARAMETER, + MappingTemplate, + TransformerPluginBase, +} from '@aws-amplify/graphql-transformer-core'; import { TransformerContextProvider, TransformerSchemaVisitStepContextProvider } from '@aws-amplify/graphql-transformer-interfaces'; import * as lambda from '@aws-cdk/aws-lambda'; +import { AuthorizationType } from '@aws-cdk/aws-appsync'; import * as cdk from '@aws-cdk/core'; -import { obj, str, ref, printBlock, compoundExpression, qref, raw, iff } from 'graphql-mapping-template'; +import { obj, str, toJson, ref, printBlock, compoundExpression, qref, raw, iff, Expression } from 'graphql-mapping-template'; import { FunctionResourceIDs, ResolverResourceIDs, ResourceConstants } from 'graphql-transformer-common'; import { DirectiveNode, ObjectTypeDefinitionNode, InterfaceTypeDefinitionNode, FieldDefinitionNode } from 'graphql'; @@ -88,19 +95,21 @@ export class FunctionTransformer extends TransformerPluginBase { functionId, MappingTemplate.s3MappingTemplateFromString( printBlock(`Invoke AWS Lambda data source: ${dataSourceId}`)( - obj({ - version: str('2018-05-29'), - operation: str('Invoke'), - payload: obj({ - typeName: ref('ctx.stash.get("typeName")'), - fieldName: ref('ctx.stash.get("fieldName")'), - arguments: ref('util.toJson($ctx.arguments)'), - identity: ref('util.toJson($ctx.identity)'), - source: ref('util.toJson($ctx.source)'), - request: ref('util.toJson($ctx.request)'), - prev: ref('util.toJson($ctx.prev)'), + toJson( + obj({ + version: str('2018-05-29'), + operation: str('Invoke'), + payload: obj({ + typeName: ref('ctx.stash.get("typeName")'), + fieldName: ref('ctx.stash.get("fieldName")'), + arguments: ref('util.toJson($ctx.arguments)'), + identity: ref('util.toJson($ctx.identity)'), + source: ref('util.toJson($ctx.source)'), + request: ref('util.toJson($ctx.request)'), + prev: ref('util.toJson($ctx.prev)'), + }), }), - }), + ), ), `${functionId}.req.vtl`, ), @@ -124,20 +133,37 @@ export class FunctionTransformer extends TransformerPluginBase { const resolverId = ResolverResourceIDs.ResolverResourceID(config.resolverTypeName, config.resolverFieldName); let resolver = createdResources.get(resolverId); + const requestTemplate: Array = [ + qref(`$ctx.stash.put("typeName", "${config.resolverTypeName}")`), + qref(`$ctx.stash.put("fieldName", "${config.resolverFieldName}")`), + ]; + const authModes = [context.authConfig.defaultAuthentication, ...(context.authConfig.additionalAuthenticationProviders || [])].map( + mode => mode?.authenticationType, + ); + if (authModes.includes(AuthorizationType.IAM)) { + const authRoleParameter = (context.stackManager.getParameter(IAM_AUTH_ROLE_PARAMETER) as cdk.CfnParameter).valueAsString; + const unauthRoleParameter = (context.stackManager.getParameter(IAM_UNAUTH_ROLE_PARAMETER) as cdk.CfnParameter).valueAsString; + requestTemplate.push( + qref( + `$ctx.stash.put("authRole", "arn:aws:sts::${ + cdk.Stack.of(context.stackManager.rootStack).account + }:assumed-role/${authRoleParameter}/CognitoIdentityCredentials")`, + ), + qref( + `$ctx.stash.put("unauthRole", "arn:aws:sts::${ + cdk.Stack.of(context.stackManager.rootStack).account + }:assumed-role/${unauthRoleParameter}/CognitoIdentityCredentials")`, + ), + ); + } + requestTemplate.push(obj({})); + if (resolver === undefined) { + // TODO: update function to use resolver manager resolver = context.api.host.addResolver( config.resolverTypeName, config.resolverFieldName, - MappingTemplate.s3MappingTemplateFromString( - printBlock('Stash resolver specific context.')( - compoundExpression([ - qref(`$ctx.stash.put("typeName", "${config.resolverTypeName}")`), - qref(`$ctx.stash.put("fieldName", "${config.resolverFieldName}")`), - obj({}), - ]), - ), - `${config.resolverTypeName}.${config.resolverFieldName}.req.vtl`, - ), + MappingTemplate.inlineTemplateFromString(printBlock('Stash resolver specific context.')(compoundExpression(requestTemplate))), MappingTemplate.s3MappingTemplateFromString( '$util.toJson($ctx.prev.result)', `${config.resolverTypeName}.${config.resolverFieldName}.res.vtl`, @@ -146,7 +172,6 @@ export class FunctionTransformer extends TransformerPluginBase { [], stack, ); - createdResources.set(resolverId, resolver); } @@ -159,7 +184,7 @@ export class FunctionTransformer extends TransformerPluginBase { function lambdaArnResource(env: cdk.CfnParameter, name: string, region?: string): string { const substitutions: { [key: string]: string } = {}; if (name.includes('${env}')) { - substitutions.env = (env as unknown) as string; + substitutions.env = env as unknown as string; } return cdk.Fn.conditionIf( ResourceConstants.CONDITIONS.HasEnvironmentParameter, diff --git a/packages/amplify-graphql-index-transformer/src/__tests__/__snapshots__/amplify-graphql-index-transformer.test.ts.snap b/packages/amplify-graphql-index-transformer/src/__tests__/__snapshots__/amplify-graphql-index-transformer.test.ts.snap index 094ac57e866..fc6402fe39c 100644 --- a/packages/amplify-graphql-index-transformer/src/__tests__/__snapshots__/amplify-graphql-index-transformer.test.ts.snap +++ b/packages/amplify-graphql-index-transformer/src/__tests__/__snapshots__/amplify-graphql-index-transformer.test.ts.snap @@ -13,7 +13,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -41,25 +47,6 @@ $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) #end {}", "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -124,14 +111,21 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -201,13 +195,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -217,7 +212,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -373,35 +374,67 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.getTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getTest.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTest.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", "Query.listByEmailKindDate.req.vtl": "## [Start] Set query expression for key ** #set( $modelQueryExpression = {} ) ## [Start] Validate key arguments. ** @@ -520,12 +553,38 @@ $util.toJson($GetRequest) #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.listByEmailKindDate.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", + "Query.listTests.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listTests.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -535,8 +594,20 @@ $util.toJson($ctx.result)", #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -560,13 +631,13 @@ $util.toJson($ctx.result)", #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listTests.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listTests.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Query.testsByCategory.req.vtl": "## [Start] Set query expression for key ** #set( $modelQueryExpression = {} ) ## [Start] Validate key arguments. ** @@ -639,12 +710,77 @@ $util.toJson($ListRequest) #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.testsByCategory.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", + "Subscription.onCreateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", } `; @@ -661,7 +797,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -689,25 +831,6 @@ $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) #end {}", "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -772,14 +895,21 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -849,13 +979,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -865,7 +996,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -1021,35 +1158,67 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.getTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getTest.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTest.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", "Query.listByEmailKindDate.req.vtl": "## [Start] Set query expression for key ** #set( $modelQueryExpression = {} ) ## [Start] Validate key arguments. ** @@ -1168,12 +1337,38 @@ $util.toJson($GetRequest) #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.listByEmailKindDate.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", + "Query.listTests.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listTests.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -1183,8 +1378,20 @@ $util.toJson($ctx.result)", #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -1208,13 +1415,58 @@ $util.toJson($ctx.result)", #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listTests.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listTests.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Subscription.onCreateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", } `; @@ -1231,7 +1483,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -1259,25 +1517,6 @@ $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) #end {}", "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -1342,14 +1581,21 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -1419,13 +1665,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -1435,7 +1682,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -1591,35 +1844,67 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.getTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getTest.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTest.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", "Query.listByEmailKindDate.req.vtl": "## [Start] Set query expression for key ** #set( $modelQueryExpression = {} ) ## [Start] Validate key arguments. ** @@ -1738,12 +2023,38 @@ $util.toJson($GetRequest) #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.listByEmailKindDate.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", + "Query.listTests.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listTests.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -1753,8 +2064,20 @@ $util.toJson($ctx.result)", #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -1778,13 +2101,13 @@ $util.toJson($ctx.result)", #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listTests.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listTests.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Query.testsByCategory.req.vtl": "## [Start] Set query expression for key ** #set( $modelQueryExpression = {} ) ## [Start] Validate key arguments. ** @@ -1857,7 +2180,27 @@ $util.toJson($ListRequest) #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.testsByCategory.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) @@ -1895,36 +2238,82 @@ $util.toJson($ctx.result)", #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.testsByEmail.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", + "Subscription.onCreateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", } `; exports[`GSI composite sort keys are wrapped in conditional to check presence in mutation 1`] = ` "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -2136,7 +2525,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -2149,25 +2544,6 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { {}", "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -2232,14 +2608,21 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -2307,13 +2690,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -2323,7 +2707,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -2464,14 +2854,21 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Query.getTest.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +## [End] ResponseTemplate. **", + "Query.getTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getTest.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"email\\": $util.dynamodb.toDynamoDB($ctx.args.email), \\"createdAt\\": $util.dynamodb.toDynamoDB($ctx.args.createdAt) @@ -2481,25 +2878,50 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getTest.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) -#else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) +#else + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTest.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", "Query.listByEmailKindDate.req.vtl": "## [Start] Set query expression for key ** #set( $modelQueryExpression = {} ) ## [Start] Validate key arguments. ** @@ -2618,13 +3040,39 @@ $util.toJson($GetRequest) #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.listByEmailKindDate.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", - "Query.listTests.postAuth.1.req.vtl": "## [Start] Set query expression for key ** + "Query.listTests.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listTests.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( $util.isNull($ctx.args.email) && !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"When providing argument 'sortDirection' you must also provide argument 'email'.\\", \\"InvalidArgumentsError\\") #end @@ -2695,8 +3143,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -2720,13 +3180,13 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listTests.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listTests.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Query.testsByCategory.req.vtl": "## [Start] Set query expression for key ** #set( $modelQueryExpression = {} ) ## [Start] Validate key arguments. ** @@ -2799,7 +3259,27 @@ $util.toJson($ListRequest) #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.testsByCategory.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) @@ -2837,12 +3317,77 @@ $util.toJson($ctx.result)", #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.testsByEmail.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", + "Subscription.onCreateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", } `; @@ -2859,7 +3404,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.addContentToCategory.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.addContentToCategory.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.addContentToCategory.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -2887,25 +3438,6 @@ $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) #end {}", "Mutation.addContentToCategory.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -2970,13 +3502,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"ContentCategory\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.addContentToCategory.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.addContentToCategory.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createBlog.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -2988,26 +3521,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createBlog.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createBlog.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createBlog.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -3072,13 +3592,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Blog\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createBlog.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createBlog.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createCall.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -3090,7 +3611,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createCall.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createCall.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createCall.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -3103,25 +3630,6 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { {}", "Mutation.createCall.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -3186,13 +3694,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Call\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createCall.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createCall.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createItem.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -3204,7 +3713,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createItem.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createItem.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createItem.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -3224,25 +3739,6 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { $util.qr($ctx.args.input.put(\\"status#createdAt\\",\\"\${mergedValues.status}#\${mergedValues.createdAt}\\")) {}", "Mutation.createItem.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -3307,13 +3803,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Item\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createItem.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createItem.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createPerson.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -3325,7 +3822,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createPerson.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createPerson.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createPerson.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -3344,7 +3847,7 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { #end $util.qr($ctx.args.input.put(\\"firstName#lastName\\",\\"\${mergedValues.firstName}#\${mergedValues.lastName}\\")) {}", - "Mutation.createPerson.postAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createPerson.preAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -3371,7 +3874,7 @@ $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) $util.qr($ctx.args.input.put(\\"age#birthDate\\",\\"\${mergedValues.age}#\${mergedValues.birthDate}\\")) #end {}", - "Mutation.createPerson.postAuth.3.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createPerson.preAuth.3.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -3399,25 +3902,6 @@ $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) #end {}", "Mutation.createPerson.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -3482,13 +3966,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Person\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createPerson.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createPerson.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createReview.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -3500,7 +3985,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createReview.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createReview.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createReview.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -3512,7 +4003,7 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { ## [End] Set the primary key. ** {}", - "Mutation.createReview.postAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createReview.preAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -3540,25 +4031,6 @@ $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) #end {}", "Mutation.createReview.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -3623,13 +4095,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Review\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createReview.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createReview.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -3641,7 +4114,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -3654,25 +4133,6 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { {}", "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -3737,13 +4197,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createTodo.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -3755,26 +4216,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTodo.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createTodo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTodo.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -3839,13 +4287,20 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Todo\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTodo.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTodo.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteBlog.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteBlog.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -3903,14 +4358,21 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteBlog.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteBlog.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteCall.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteCall.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteCall.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -3978,14 +4440,21 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteCall.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteCall.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteContentFromCategory.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteContentFromCategory.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteContentFromCategory.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -4055,14 +4524,21 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteContentFromCategory.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteContentFromCategory.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteItem.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteItem.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteItem.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -4131,14 +4607,21 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) $util.qr($DeleteRequest.put(\\"_version\\", $util.defaultIfNull($ctx.args.input[\\"_version\\"], \\"0\\"))) $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteItem.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteItem.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deletePerson.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deletePerson.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deletePerson.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -4149,7 +4632,7 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { })) ## [End] Set the primary key. ** {}", - "Mutation.deletePerson.postAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.deletePerson.preAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -4162,7 +4645,7 @@ $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) #end $util.qr($ctx.args.input.put(\\"age#birthDate\\",\\"\${mergedValues.age}#\${mergedValues.birthDate}\\")) {}", - "Mutation.deletePerson.postAuth.3.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.deletePerson.preAuth.3.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -4232,14 +4715,21 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deletePerson.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deletePerson.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteReview.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteReview.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteReview.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -4250,7 +4740,7 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { })) ## [End] Set the primary key. ** {}", - "Mutation.deleteReview.postAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.deleteReview.preAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -4320,14 +4810,21 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteReview.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteReview.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -4395,13 +4892,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteTodo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteTodo.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -4459,14 +4963,21 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTodo.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTodo.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.testDelete.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.testDelete.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.testDelete.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -4534,13 +5045,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.testDelete.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.testDelete.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateBlog.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -4550,6 +5062,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateBlog.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateBlog.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -4679,13 +5197,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateBlog.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateBlog.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateCall.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -4695,7 +5214,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateCall.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateCall.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateCall.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -4836,13 +5361,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateCall.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateCall.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateItem.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -4852,7 +5378,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateItem.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateItem.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateItem.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -5001,13 +5533,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateItem.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateItem.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updatePerson.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -5017,7 +5550,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updatePerson.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updatePerson.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updatePerson.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -5036,7 +5575,7 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { #end $util.qr($ctx.args.input.put(\\"firstName#lastName\\",\\"\${mergedValues.firstName}#\${mergedValues.lastName}\\")) {}", - "Mutation.updatePerson.postAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updatePerson.preAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -5063,7 +5602,7 @@ $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) $util.qr($ctx.args.input.put(\\"age#birthDate\\",\\"\${mergedValues.age}#\${mergedValues.birthDate}\\")) #end {}", - "Mutation.updatePerson.postAuth.3.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updatePerson.preAuth.3.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -5219,13 +5758,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updatePerson.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updatePerson.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateReview.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -5235,7 +5775,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateReview.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateReview.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateReview.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -5247,7 +5793,7 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { ## [End] Set the primary key. ** {}", - "Mutation.updateReview.postAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateReview.preAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -5403,13 +5949,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateReview.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateReview.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -5419,7 +5966,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -5560,13 +6113,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTodo.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -5576,6 +6130,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateTodo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateTodo.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -5705,13 +6265,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTodo.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTodo.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Query.byCreatedAt.req.vtl": "## [Start] Set query expression for key ** #if( !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"sortDirection is not supported for List operations without a Sort key defined.\\", \\"InvalidArgumentsError\\") @@ -5744,35 +6305,92 @@ $util.toJson($UpdateItem) #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.byCreatedAt.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", + "Query.getBlog.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getBlog.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getBlog.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getBlog.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.getCall.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", - "Query.getCall.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getCall.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"receiverId\\": $util.dynamodb.toDynamoDB($ctx.args.receiverId), \\"senderId\\": $util.dynamodb.toDynamoDB($ctx.args.senderId) @@ -5782,26 +6400,57 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getCall.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getCall.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getCall.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.getItem.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", - "Query.getItem.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getItem.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"orderId\\": $util.dynamodb.toDynamoDB($ctx.args.orderId), \\"status#createdAt\\": $util.dynamodb.toDynamoDB(\\"\${ctx.args.status}#\${ctx.args.createdAt}\\") @@ -5811,26 +6460,57 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getItem.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getItem.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getItem.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", - "Query.getPerson.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +## [End] Get Response template. **", + "Query.getPerson.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getPerson.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id), \\"firstName#lastName\\": $util.dynamodb.toDynamoDB(\\"\${ctx.args.firstName}#\${ctx.args.lastName}\\") @@ -5840,25 +6520,50 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getPerson.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getPerson.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getPerson.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", "Query.getPersonByNameByDate.req.vtl": "## [Start] Set query expression for key ** #set( $modelQueryExpression = {} ) ## [Start] Validate key arguments. ** @@ -5977,13 +6682,39 @@ $util.toJson($GetRequest) #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.getPersonByNameByDate.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", - "Query.getReview.postAuth.1.req.vtl": "## [Start] Set the primary key. ** + "Query.getReview.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getReview.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"owner\\": $util.dynamodb.toDynamoDB($ctx.args.owner), \\"serviceId\\": $util.dynamodb.toDynamoDB($ctx.args.serviceId) @@ -5993,26 +6724,57 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getReview.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getReview.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getReview.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.getTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", - "Query.getTest.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getTest.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"email\\": $util.dynamodb.toDynamoDB($ctx.args.email), \\"createdAt\\": $util.dynamodb.toDynamoDB($ctx.args.createdAt) @@ -6022,47 +6784,103 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getTest.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTest.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.getTodo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getTodo.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTodo.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTodo.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", "Query.itemsByCreatedAt.req.vtl": "## [Start] Set query expression for key ** #set( $modelQueryExpression = {} ) ## [Start] Validate key arguments. ** @@ -6135,7 +6953,27 @@ $util.toJson($GetRequest) #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.itemsByCreatedAt.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) @@ -6213,12 +7051,38 @@ $util.toJson($ctx.result)", #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.itemsByStatus.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", + "Query.listBlogs.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listBlogs.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -6228,8 +7092,20 @@ $util.toJson($ctx.result)", #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -6253,13 +7129,13 @@ $util.toJson($ctx.result)", #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listBlogs.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listBlogs.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Query.listByEmailKindDate.req.vtl": "## [Start] Set query expression for key ** #set( $modelQueryExpression = {} ) ## [Start] Validate key arguments. ** @@ -6378,13 +7254,39 @@ $util.toJson($ListRequest) #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.listByEmailKindDate.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", - "Query.listCalls.postAuth.1.req.vtl": "## [Start] Set query expression for key ** + "Query.listCalls.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listCalls.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( $util.isNull($ctx.args.receiverId) && !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"When providing argument 'sortDirection' you must also provide argument 'receiverId'.\\", \\"InvalidArgumentsError\\") #end @@ -6455,8 +7357,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -6480,13 +7394,13 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listCalls.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listCalls.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Query.listContentByCategory.req.vtl": "## [Start] Set query expression for key ** #set( $modelQueryExpression = {} ) ## [Start] Validate key arguments. ** @@ -6622,13 +7536,39 @@ $util.toJson($ListRequest) #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.listContentByCategory.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", - "Query.listItems.postAuth.1.req.vtl": "## [Start] Set query expression for key ** + "Query.listItems.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listItems.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( $util.isNull($ctx.args.orderId) && !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"When providing argument 'sortDirection' you must also provide argument 'orderId'.\\", \\"InvalidArgumentsError\\") #end @@ -6745,8 +7685,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -6770,14 +7722,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listItems.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listItems.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Query.listPeople.postAuth.1.req.vtl": "## [Start] Set query expression for key ** +## [End] ResponseTemplate. **", + "Query.listPeople.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listPeople.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( $util.isNull($ctx.args.id) && !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"When providing argument 'sortDirection' you must also provide argument 'id'.\\", \\"InvalidArgumentsError\\") #end @@ -6894,8 +7852,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -6919,14 +7889,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listPeople.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listPeople.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Query.listReviews.postAuth.1.req.vtl": "## [Start] Set query expression for key ** +## [End] ResponseTemplate. **", + "Query.listReviews.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listReviews.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( $util.isNull($ctx.args.owner) && !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"When providing argument 'sortDirection' you must also provide argument 'owner'.\\", \\"InvalidArgumentsError\\") #end @@ -6997,8 +7973,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -7022,13 +8010,13 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listReviews.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listReviews.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Query.listReviewsById.req.vtl": "## [Start] Set query expression for key ** #if( !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"sortDirection is not supported for List operations without a Sort key defined.\\", \\"InvalidArgumentsError\\") @@ -7061,7 +8049,27 @@ $util.toJson($ListRequest) #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.listReviewsById.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) @@ -7139,7 +8147,27 @@ $util.toJson($ctx.result)", #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.listReviewsByService.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) @@ -7263,13 +8291,39 @@ $util.toJson($ctx.result)", #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.listReviewsByStatus.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", - "Query.listTests.postAuth.1.req.vtl": "## [Start] Set query expression for key ** + "Query.listTests.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listTests.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( $util.isNull($ctx.args.email) && !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"When providing argument 'sortDirection' you must also provide argument 'email'.\\", \\"InvalidArgumentsError\\") #end @@ -7340,8 +8394,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -7365,14 +8431,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listTests.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listTests.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Query.syncItems.postAuth.1.req.vtl": "## [Start] Set map initialization for @key ** +## [End] ResponseTemplate. **", + "Query.syncItems.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.syncItems.preAuth.1.req.vtl": "## [Start] Set map initialization for @key ** #set( $index = \\"\\" ) #set( $scan = true ) #set( $filterMap = {} ) @@ -7505,7 +8577,7 @@ null #end ## [End] Set query expression for @key ** ", - "Query.syncItems.postAuth.2.req.vtl": "## [Start] Set map initialization for @key ** + "Query.syncItems.preAuth.2.req.vtl": "## [Start] Set map initialization for @key ** #set( $index = \\"\\" ) #set( $scan = true ) #set( $filterMap = {} ) @@ -7635,11 +8707,32 @@ null ## [End] Set query expression for @key ** ", "Query.syncItems.req.vtl": "## [Start] Sync Request template. ** +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $filter = $filterExpression ) + #end +#end { \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"Sync\\", - \\"filter\\": #if( $context.args.filter ) -$util.transform.toDynamoDBFilterExpression($ctx.args.filter) + \\"filter\\": #if( $filter ) +$util.toJson($filter) #else null #end, @@ -7648,13 +8741,13 @@ null \\"nextToken\\": $util.toJson($util.defaultIfNull($ctx.args.nextToken, null)) } ## [End] Sync Request template. **", - "Query.syncItems.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.syncItems.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Query.testsByCategory.req.vtl": "## [Start] Set query expression for key ** #set( $modelQueryExpression = {} ) ## [Start] Validate key arguments. ** @@ -7727,7 +8820,27 @@ null #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.testsByCategory.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) @@ -7765,7 +8878,27 @@ $util.toJson($ctx.result)", #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.testsByEmail.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) @@ -7843,12 +8976,332 @@ $util.toJson($ctx.result)", #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.testsByEmailByUpdatedAt.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", + "Subscription.onCreateBlog.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateBlog.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateBlog.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateCall.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateCall.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateCall.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateContentCategory.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateContentCategory.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateContentCategory.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateItem.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateItem.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateItem.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreatePerson.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreatePerson.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreatePerson.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateTodo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTodo.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTodo.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteBlog.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteBlog.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteBlog.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteCall.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteCall.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteCall.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteContentCategory.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteContentCategory.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteContentCategory.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteItem.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteItem.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteItem.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeletePerson.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeletePerson.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeletePerson.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTodo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTodo.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTodo.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateBlog.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateBlog.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateBlog.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateCall.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateCall.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateCall.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateItem.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateItem.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateItem.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdatePerson.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdatePerson.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdatePerson.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTodo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTodo.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTodo.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", } `; @@ -7865,7 +9318,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.addContentToCategory.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.addContentToCategory.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.addContentToCategory.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -7893,25 +9352,6 @@ $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) #end {}", "Mutation.addContentToCategory.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -7976,13 +9416,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"ContentCategory\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.addContentToCategory.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.addContentToCategory.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createBlog.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -7994,26 +9435,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createBlog.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createBlog.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createBlog.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -8078,13 +9506,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Blog\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createBlog.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createBlog.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createItem.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -8096,45 +9525,32 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createItem.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createItem.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createItem.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** ## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"orderId\\": $util.dynamodb.toDynamoDB($mergedValues.orderId), - \\"status#createdAt\\": $util.dynamodb.toDynamoDB(\\"\${mergedValues.status}#\${mergedValues.createdAt}\\") -})) -## [End] Set the primary key. ** -#if( $util.isNull($ctx.stash.metadata.dynamodbNameOverrideMap) ) - $util.qr($ctx.stash.metadata.put(\\"dynamodbNameOverrideMap\\", { - \\"status#createdAt\\": \\"statusCreatedAt\\" -})) -#else - $util.qr($ctx.stash.metadata.dynamodbNameOverrideMap.put(\\"status#createdAt\\", \\"statusCreatedAt\\")) -#end -$util.qr($ctx.args.input.put(\\"status#createdAt\\",\\"\${mergedValues.status}#\${mergedValues.createdAt}\\")) -{}", - "Mutation.createItem.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } + \\"status#createdAt\\": $util.dynamodb.toDynamoDB(\\"\${mergedValues.status}#\${mergedValues.createdAt}\\") +})) +## [End] Set the primary key. ** +#if( $util.isNull($ctx.stash.metadata.dynamodbNameOverrideMap) ) + $util.qr($ctx.stash.metadata.put(\\"dynamodbNameOverrideMap\\", { + \\"status#createdAt\\": \\"statusCreatedAt\\" })) +#else + $util.qr($ctx.stash.metadata.dynamodbNameOverrideMap.put(\\"status#createdAt\\", \\"statusCreatedAt\\")) #end -## End - key condition ** +$util.qr($ctx.args.input.put(\\"status#createdAt\\",\\"\${mergedValues.status}#\${mergedValues.createdAt}\\")) +{}", + "Mutation.createItem.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -8199,13 +9615,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Item\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createItem.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createItem.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -8217,7 +9634,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -8230,25 +9653,6 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { {}", "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -8313,13 +9717,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createTodo.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -8331,26 +9736,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTodo.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createTodo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTodo.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -8415,13 +9807,20 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Todo\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTodo.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTodo.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteBlog.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteBlog.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -8479,14 +9878,21 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteBlog.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteBlog.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteContentFromCategory.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteContentFromCategory.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteContentFromCategory.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -8556,14 +9962,21 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteContentFromCategory.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteContentFromCategory.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteItem.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteItem.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteItem.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -8631,14 +10044,21 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteItem.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteItem.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -8706,13 +10126,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteTodo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteTodo.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -8770,13 +10197,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTodo.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTodo.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateBlog.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -8786,6 +10214,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateBlog.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateBlog.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -8915,13 +10349,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateBlog.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateBlog.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateItem.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -8931,7 +10366,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateItem.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateItem.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateItem.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -9079,13 +10520,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateItem.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateItem.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -9095,7 +10537,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -9236,13 +10684,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTodo.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -9252,6 +10701,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateTodo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateTodo.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -9381,13 +10836,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTodo.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTodo.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Query.byCreatedAt.req.vtl": "## [Start] Set query expression for key ** #if( !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"sortDirection is not supported for List operations without a Sort key defined.\\", \\"InvalidArgumentsError\\") @@ -9420,35 +10876,92 @@ $util.toJson($UpdateItem) #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.byCreatedAt.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", + "Query.getBlog.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getBlog.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getBlog.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getBlog.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", - "Query.getItem.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +## [End] Get Response template. **", + "Query.getItem.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getItem.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"orderId\\": $util.dynamodb.toDynamoDB($ctx.args.orderId), \\"status#createdAt\\": $util.dynamodb.toDynamoDB(\\"\${ctx.args.status}#\${ctx.args.createdAt}\\") @@ -9458,26 +10971,57 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getItem.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getItem.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getItem.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", - "Query.getTest.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +## [End] Get Response template. **", + "Query.getTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getTest.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"email\\": $util.dynamodb.toDynamoDB($ctx.args.email), \\"createdAt\\": $util.dynamodb.toDynamoDB($ctx.args.createdAt) @@ -9487,47 +11031,103 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getTest.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTest.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getTodo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getTodo.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTodo.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTodo.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", "Query.itemsByCreatedAt.req.vtl": "## [Start] Set query expression for key ** #set( $modelQueryExpression = {} ) ## [Start] Validate key arguments. ** @@ -9600,7 +11200,27 @@ $util.toJson($GetRequest) #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.itemsByCreatedAt.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) @@ -9678,12 +11298,38 @@ $util.toJson($ctx.result)", #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.itemsByStatus.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", + "Query.listBlogs.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listBlogs.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -9693,8 +11339,20 @@ $util.toJson($ctx.result)", #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -9718,13 +11376,13 @@ $util.toJson($ctx.result)", #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listBlogs.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listBlogs.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Query.listByEmailKindDate.req.vtl": "## [Start] Set query expression for key ** #set( $modelQueryExpression = {} ) ## [Start] Validate key arguments. ** @@ -9843,7 +11501,27 @@ $util.toJson($ListRequest) #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.listByEmailKindDate.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) @@ -9984,13 +11662,39 @@ $util.toJson($ctx.result)", #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.listContentByCategory.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", - "Query.listItems.postAuth.1.req.vtl": "## [Start] Set query expression for key ** + "Query.listItems.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listItems.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( $util.isNull($ctx.args.orderId) && !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"When providing argument 'sortDirection' you must also provide argument 'orderId'.\\", \\"InvalidArgumentsError\\") #end @@ -10107,8 +11811,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -10132,14 +11848,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listItems.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listItems.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Query.listTests.postAuth.1.req.vtl": "## [Start] Set query expression for key ** +## [End] ResponseTemplate. **", + "Query.listTests.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listTests.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( $util.isNull($ctx.args.email) && !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"When providing argument 'sortDirection' you must also provide argument 'email'.\\", \\"InvalidArgumentsError\\") #end @@ -10210,8 +11932,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -10235,13 +11969,13 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listTests.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listTests.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Query.testsByCategory.req.vtl": "## [Start] Set query expression for key ** #set( $modelQueryExpression = {} ) ## [Start] Validate key arguments. ** @@ -10314,7 +12048,27 @@ $util.toJson($ListRequest) #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.testsByCategory.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) @@ -10352,7 +12106,27 @@ $util.toJson($ctx.result)", #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.testsByEmail.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) @@ -10430,11 +12204,241 @@ $util.toJson($ctx.result)", #set( $QueryRequest.scanIndexForward = true ) #end #if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) #set( $QueryRequest.filter = $util.parseJson(\\"$util.transform.toDynamoDBFilterExpression($ctx.args.filter)\\") ) #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $QueryRequest.filter = $filterExpression ) + #end +#end $util.toJson($QueryRequest)", "Query.testsByEmailByUpdatedAt.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)", + "Subscription.onCreateBlog.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateBlog.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateBlog.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateContentCategory.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateContentCategory.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateContentCategory.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateItem.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateItem.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateItem.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateTodo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTodo.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTodo.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteBlog.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteBlog.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteBlog.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteContentCategory.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteContentCategory.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteContentCategory.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteItem.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteItem.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteItem.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTodo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTodo.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTodo.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateBlog.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateBlog.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateBlog.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateItem.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateItem.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateItem.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTodo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTodo.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTodo.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", } `; diff --git a/packages/amplify-graphql-index-transformer/src/__tests__/__snapshots__/amplify-graphql-primary-key-transformer.test.ts.snap b/packages/amplify-graphql-index-transformer/src/__tests__/__snapshots__/amplify-graphql-primary-key-transformer.test.ts.snap index 327c5ae5eca..4ec7e6b8267 100644 --- a/packages/amplify-graphql-index-transformer/src/__tests__/__snapshots__/amplify-graphql-primary-key-transformer.test.ts.snap +++ b/packages/amplify-graphql-index-transformer/src/__tests__/__snapshots__/amplify-graphql-primary-key-transformer.test.ts.snap @@ -13,7 +13,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -33,25 +39,6 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { $util.qr($ctx.args.input.put(\\"kind#other\\",\\"\${mergedValues.kind}#\${mergedValues.other}\\")) {}", "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -116,14 +103,21 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -191,13 +185,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -207,7 +202,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -355,14 +356,21 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Query.getTest.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +## [End] ResponseTemplate. **", + "Query.getTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getTest.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"email\\": $util.dynamodb.toDynamoDB($ctx.args.email), \\"kind#other\\": $util.dynamodb.toDynamoDB(\\"\${ctx.args.kind}#\${ctx.args.other}\\") @@ -372,26 +380,57 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getTest.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTest.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", - "Query.listTests.postAuth.1.req.vtl": "## [Start] Set query expression for key ** +## [End] Get Response template. **", + "Query.listTests.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listTests.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( $util.isNull($ctx.args.email) && !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"When providing argument 'sortDirection' you must also provide argument 'email'.\\", \\"InvalidArgumentsError\\") #end @@ -508,8 +547,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -533,13 +584,58 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listTests.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listTests.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Subscription.onCreateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", } `; @@ -556,7 +652,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -569,25 +671,6 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { {}", "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -652,14 +735,21 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -727,13 +817,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -743,7 +834,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -884,14 +981,21 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Query.getTest.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +## [End] ResponseTemplate. **", + "Query.getTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getTest.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"email\\": $util.dynamodb.toDynamoDB($ctx.args.email), \\"kind\\": $util.dynamodb.toDynamoDB($ctx.args.kind) @@ -901,26 +1005,57 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getTest.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTest.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", - "Query.listTests.postAuth.1.req.vtl": "## [Start] Set query expression for key ** +## [End] Get Response template. **", + "Query.listTests.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listTests.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( $util.isNull($ctx.args.email) && !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"When providing argument 'sortDirection' you must also provide argument 'email'.\\", \\"InvalidArgumentsError\\") #end @@ -991,8 +1126,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -1016,13 +1163,58 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listTests.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listTests.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Subscription.onCreateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", } `; @@ -1039,7 +1231,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -1051,25 +1249,6 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { {}", "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -1134,14 +1313,21 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -1208,13 +1394,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -1224,7 +1411,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -1364,14 +1557,21 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Query.getTest.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +## [End] ResponseTemplate. **", + "Query.getTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getTest.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"email\\": $util.dynamodb.toDynamoDB($ctx.args.email) })) @@ -1380,26 +1580,57 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getTest.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTest.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.listTests.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", - "Query.listTests.postAuth.1.req.vtl": "## [Start] Set query expression for key ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listTests.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"sortDirection is not supported for List operations without a Sort key defined.\\", \\"InvalidArgumentsError\\") #end @@ -1427,8 +1658,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -1452,13 +1695,58 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listTests.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listTests.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Subscription.onCreateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", } `; @@ -1475,7 +1763,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -1488,25 +1782,6 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { {}", "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -1571,14 +1846,21 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -1646,13 +1928,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -1662,7 +1945,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -1803,14 +2092,21 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Query.getTest.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +## [End] ResponseTemplate. **", + "Query.getTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getTest.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"status\\": $util.dynamodb.toDynamoDB($ctx.args.status), \\"lastStatus\\": $util.dynamodb.toDynamoDB($ctx.args.lastStatus) @@ -1820,26 +2116,57 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getTest.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTest.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.listTests.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", - "Query.listTests.postAuth.1.req.vtl": "## [Start] Set query expression for key ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listTests.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( $util.isNull($ctx.args.status) && !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"When providing argument 'sortDirection' you must also provide argument 'status'.\\", \\"InvalidArgumentsError\\") #end @@ -1910,8 +2237,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -1935,13 +2274,58 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listTests.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listTests.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Subscription.onCreateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", } `; @@ -1958,7 +2342,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -1971,25 +2361,6 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { {}", "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -2054,14 +2425,21 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -2129,13 +2507,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.testCreate.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -2147,7 +2526,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.testCreate.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.testCreate.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.testCreate.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -2160,25 +2545,6 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { {}", "Mutation.testCreate.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -2243,14 +2609,21 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.testCreate.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.testCreate.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.testDelete.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.testDelete.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.testDelete.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -2318,13 +2691,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.testDelete.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.testDelete.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.testUpdate.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -2334,7 +2708,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.testUpdate.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.testUpdate.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.testUpdate.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -2475,13 +2855,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.testUpdate.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.testUpdate.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -2491,7 +2872,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -2632,14 +3019,21 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Query.getTest.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +## [End] ResponseTemplate. **", + "Query.getTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getTest.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"email\\": $util.dynamodb.toDynamoDB($ctx.args.email) })) @@ -2648,26 +3042,57 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getTest.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTest.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.listTests.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", - "Query.listTests.postAuth.1.req.vtl": "## [Start] Set query expression for key ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listTests.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"sortDirection is not supported for List operations without a Sort key defined.\\", \\"InvalidArgumentsError\\") #end @@ -2695,8 +3120,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -2720,14 +3157,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listTests.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listTests.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Query.testGet.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +## [End] ResponseTemplate. **", + "Query.testGet.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.testGet.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id), \\"email\\": $util.dynamodb.toDynamoDB($ctx.args.email) @@ -2737,26 +3180,57 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.testGet.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.testGet.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.testGet.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", - "Query.testList.postAuth.1.req.vtl": "## [Start] Set query expression for key ** +## [End] Get Response template. **", + "Query.testList.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.testList.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( $util.isNull($ctx.args.id) && !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"When providing argument 'sortDirection' you must also provide argument 'id'.\\", \\"InvalidArgumentsError\\") #end @@ -2827,8 +3301,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -2852,13 +3338,58 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.testList.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.testList.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Subscription.onCreateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", } `; @@ -2875,7 +3406,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -2887,25 +3424,6 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { {}", "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -2970,14 +3488,21 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -3044,13 +3569,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.testCreate.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -3062,7 +3588,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.testCreate.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.testCreate.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.testCreate.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -3075,25 +3607,6 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { {}", "Mutation.testCreate.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -3158,14 +3671,21 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.testCreate.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.testCreate.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.testDelete.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.testDelete.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.testDelete.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -3233,13 +3753,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.testDelete.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.testDelete.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.testUpdate.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -3249,7 +3770,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.testUpdate.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.testUpdate.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.testUpdate.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -3390,13 +3917,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.testUpdate.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.testUpdate.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -3406,7 +3934,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateTest.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -3546,14 +4080,21 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Query.getTest.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +## [End] ResponseTemplate. **", + "Query.getTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getTest.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"email\\": $util.dynamodb.toDynamoDB($ctx.args.email) })) @@ -3562,26 +4103,57 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getTest.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTest.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.listTests.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", - "Query.listTests.postAuth.1.req.vtl": "## [Start] Set query expression for key ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listTests.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"sortDirection is not supported for List operations without a Sort key defined.\\", \\"InvalidArgumentsError\\") #end @@ -3609,8 +4181,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -3634,14 +4218,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listTests.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listTests.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Query.testGet.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +## [End] ResponseTemplate. **", + "Query.testGet.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.testGet.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id), \\"email\\": $util.dynamodb.toDynamoDB($ctx.args.email) @@ -3651,26 +4241,57 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.testGet.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.testGet.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.testGet.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", - "Query.testList.postAuth.1.req.vtl": "## [Start] Set query expression for key ** +## [End] Get Response template. **", + "Query.testList.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.testList.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( $util.isNull($ctx.args.id) && !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"When providing argument 'sortDirection' you must also provide argument 'id'.\\", \\"InvalidArgumentsError\\") #end @@ -3741,8 +4362,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -3766,12 +4399,57 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.testList.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.testList.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Subscription.onCreateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", } `; diff --git a/packages/amplify-graphql-index-transformer/src/resolvers.ts b/packages/amplify-graphql-index-transformer/src/resolvers.ts index d2bc85396b5..699472a0c8f 100644 --- a/packages/amplify-graphql-index-transformer/src/resolvers.ts +++ b/packages/amplify-graphql-index-transformer/src/resolvers.ts @@ -12,13 +12,17 @@ import { bool, compoundExpression, DynamoDBMappingTemplate, + equals, Expression, forEach, ifElse, iff, + int, + isNullOrEmpty, list, methodCall, nul, + not, obj, print, printBlock, @@ -302,7 +306,7 @@ function setQuerySnippet(config: PrimaryKeyDirectiveConfiguration, ctx: Transfor expressions.push( set(ref(ResourceConstants.SNIPPETS.ModelQueryExpression), obj({})), - applyKeyExpressionForCompositeKey(keyNames, keyTypes, ResourceConstants.SNIPPETS.ModelQueryExpression), + applyKeyExpressionForCompositeKey(keyNames, keyTypes, ResourceConstants.SNIPPETS.ModelQueryExpression)!, ); return block(`Set query expression for key`, expressions); @@ -427,6 +431,7 @@ function makeQueryResolver(config: IndexDirectiveConfiguration, ctx: Transformer const dataSource = ctx.api.host.getDataSource(`${object.name.value}Table`); const queryTypeName = ctx.output.getQueryTypeName() as string; const table = getTable(ctx, object); + const authFilter = ref('ctx.stash.authFilter'); const requestVariable = 'QueryRequest'; assert(dataSource); @@ -457,10 +462,35 @@ function makeQueryResolver(config: IndexDirectiveConfiguration, ctx: Transformer set(ref(`${requestVariable}.scanIndexForward`), bool(true)), ), iff(ref('context.args.nextToken'), set(ref(`${requestVariable}.nextToken`), ref('context.args.nextToken')), true), + ifElse( + not(isNullOrEmpty(authFilter)), + compoundExpression([ + set(ref('filter'), authFilter), + iff( + not(isNullOrEmpty(ref('ctx.args.filter'))), + set(ref('filter'), obj({ and: list([ref('filter'), ref('ctx.args.filter')]) })), + ), + ]), + iff(not(isNullOrEmpty(ref('ctx.args.filter'))), set(ref('filter'), ref('ctx.args.filter'))), + ), iff( - ref('context.args.filter'), - set(ref(`${requestVariable}.filter`), ref('util.parseJson("$util.transform.toDynamoDBFilterExpression($ctx.args.filter)")')), - true, + not(isNullOrEmpty(ref('filter'))), + compoundExpression([ + set( + ref(`filterExpression`), + methodCall(ref('util.parseJson'), methodCall(ref('util.transform.toDynamoDBFilterExpression'), ref('filter'))), + ), + iff( + not(methodCall(ref('util.isNullOrBlank'), ref('filterExpression.expression'))), + compoundExpression([ + iff( + equals(methodCall(ref('filterEpression.expressionValues.size')), int(0)), + qref(methodCall(ref('filterEpression.remove'), str('expressionValues'))), + ), + set(ref(`${requestVariable}.filter`), ref(`filterExpression`)), + ]), + ), + ]), ), raw(`$util.toJson($${requestVariable})`), ]), @@ -522,7 +552,7 @@ function addIndexToResolverSlot(resolver: TransformerResolverProvider, lines: st const res = resolver as any; res.addToSlot( - 'postAuth', + 'preAuth', MappingTemplate.s3MappingTemplateFromString( lines.join('\n') + '\n' + (!isSync ? '{}' : ''), `${res.typeName}.${res.fieldName}.{slotName}.{slotIndex}.req.vtl`, diff --git a/packages/amplify-graphql-index-transformer/src/schema.ts b/packages/amplify-graphql-index-transformer/src/schema.ts index 759b1d24800..3ffb35f72ce 100644 --- a/packages/amplify-graphql-index-transformer/src/schema.ts +++ b/packages/amplify-graphql-index-transformer/src/schema.ts @@ -322,6 +322,16 @@ export function ensureQueryField(config: IndexDirectiveConfiguration, ctx: Trans if (!queryField) { return; } + // add query field to metadata + const keyName = `${object.name.value}:indicies`; + let indicies: Set; + if (!ctx.metadata.has(keyName)) { + indicies = new Set([queryField]); + } else { + indicies = ctx.metadata.get>(keyName)!; + indicies.add(queryField); + } + ctx.metadata.set(keyName, indicies); const args = [createHashField(config)]; diff --git a/packages/amplify-graphql-model-transformer/src/__tests__/__snapshots__/model-transformer.test.ts.snap b/packages/amplify-graphql-model-transformer/src/__tests__/__snapshots__/model-transformer.test.ts.snap index cedcc76d586..11190fa63cd 100644 --- a/packages/amplify-graphql-model-transformer/src/__tests__/__snapshots__/model-transformer.test.ts.snap +++ b/packages/amplify-graphql-model-transformer/src/__tests__/__snapshots__/model-transformer.test.ts.snap @@ -583,7 +583,7 @@ input DeleteCommentInput { " `; -exports[`ModelTransformer: should generate sync resolver with ConflictHandlerType.AUTOMERGE 1`] = ` +exports[`ModelTransformer: should generate sync resolver with ConflictHandlerType.Automerge 1`] = ` Object { "Mutation.createAuthor.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) @@ -596,26 +596,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createAuthor.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createAuthor.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -680,13 +667,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Author\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createAuthor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createAuthor.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createComment.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -698,26 +686,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createComment.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createComment.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -782,13 +757,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Comment\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createComment.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createComment.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createEmail.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -800,26 +776,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createEmail.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createEmail.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -884,13 +847,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Email\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createEmail.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createEmail.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createPost.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -902,26 +866,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createPost.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createPost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createPost.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -986,13 +937,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Post\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createPost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createPost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createRequire.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -1004,26 +956,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createRequire.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createRequire.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -1088,13 +1027,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Require\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createRequire.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createRequire.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -1106,26 +1046,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -1190,13 +1117,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createUser.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -1208,26 +1136,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createUser.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createUser.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -1292,13 +1207,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"User\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createUser.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createUser.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.customCreatePost.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -1310,26 +1226,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.customCreatePost.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.customCreatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.customCreatePost.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -1394,13 +1297,20 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Post\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.customCreatePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.customCreatePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.customDeletePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.customDeletePost.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -1458,13 +1368,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.customDeletePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.customDeletePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.customUpdatePost.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -1474,6 +1385,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.customUpdatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.customUpdatePost.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -1603,13 +1520,20 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.customUpdatePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.customUpdatePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteAuthor.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -1667,13 +1591,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteAuthor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteAuthor.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteComment.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -1731,13 +1662,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteComment.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteComment.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteEmail.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -1795,13 +1733,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteEmail.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteEmail.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deletePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deletePost.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -1860,13 +1805,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) $util.qr($DeleteRequest.put(\\"_version\\", $util.defaultIfNull($ctx.args.input[\\"_version\\"], \\"0\\"))) $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deletePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deletePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteRequire.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -1924,13 +1876,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteRequire.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteRequire.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteTest.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -1988,13 +1947,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteUser.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -2052,13 +2018,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteUser.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteUser.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateAuthor.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -2068,6 +2035,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateAuthor.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -2197,13 +2170,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateAuthor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateAuthor.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateComment.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -2213,6 +2187,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateComment.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -2342,13 +2322,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateComment.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateComment.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateEmail.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -2358,6 +2339,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateEmail.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -2487,13 +2474,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateEmail.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateEmail.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updatePost.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -2503,6 +2491,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updatePost.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -2633,13 +2627,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updatePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updatePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateRequire.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -2649,6 +2644,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateRequire.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -2778,13 +2779,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateRequire.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateRequire.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -2794,6 +2796,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateTest.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -2923,13 +2931,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateUser.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -2939,6 +2948,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateUser.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -3068,35 +3083,73 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateUser.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateUser.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.customGetPost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.customGetPost.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.customGetPost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.customGetPost.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.customListPost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.customListPost.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -3106,8 +3159,20 @@ $util.toJson($GetRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -3131,189 +3196,443 @@ $util.toJson($GetRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.customListPost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.customListPost.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.getAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getAuthor.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getAuthor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getAuthor.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getComment.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getComment.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getComment.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getEmail.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getEmail.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getEmail.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getEntity.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getEntity.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getEntity.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getEntity.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getPost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getPost.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getPost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getPost.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getRequire.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getRequire.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getRequire.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getTest.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTest.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getUser.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getUser.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getUser.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.listAuthors.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listAuthors.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -3323,9 +3642,21 @@ $util.toJson($GetRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) - #if( !$util.isNullOrBlank($filterExpression.expression) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) #end @@ -3348,13 +3679,19 @@ $util.toJson($GetRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listAuthors.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listAuthors.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listComments.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listComments.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -3364,8 +3701,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -3389,13 +3738,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listComments.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listComments.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listEmails.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listEmails.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -3405,8 +3760,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -3430,13 +3797,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listEmails.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listEmails.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listPosts.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listPosts.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -3446,8 +3819,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -3471,13 +3856,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listPosts.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listPosts.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listRequires.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listRequires.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -3487,8 +3878,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -3512,13 +3915,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listRequires.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listRequires.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listTests.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listTests.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -3528,8 +3937,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -3553,13 +3974,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listTests.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listTests.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listUsers.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listUsers.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -3569,8 +3996,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -3594,19 +4033,46 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listUsers.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listUsers.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.syncPosts.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.syncPosts.req.vtl": "## [Start] Sync Request template. ** +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $filter = $filterExpression ) + #end +#end { \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"Sync\\", - \\"filter\\": #if( $context.args.filter ) -$util.transform.toDynamoDBFilterExpression($ctx.args.filter) + \\"filter\\": #if( $filter ) +$util.toJson($filter) #else null #end, @@ -3615,13 +4081,328 @@ null \\"nextToken\\": $util.toJson($util.defaultIfNull($ctx.args.nextToken, null)) } ## [End] Sync Request template. **", - "Query.syncPosts.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.syncPosts.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Subscription.onCreateAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateAuthor.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateAuthor.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateComment.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateComment.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateEmail.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateEmail.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreatePost.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreatePost.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateRequire.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateRequire.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateUser.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateUser.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteAuthor.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteAuthor.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteComment.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteComment.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteEmail.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteEmail.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeletePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeletePost.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeletePost.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteRequire.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteRequire.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteUser.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteUser.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateAuthor.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateAuthor.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateComment.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateComment.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateEmail.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateEmail.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdatePost.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdatePost.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateRequire.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateRequire.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateUser.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateUser.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", } `; @@ -3638,26 +4419,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createAuthor.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createAuthor.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -3722,13 +4490,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Author\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createAuthor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createAuthor.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createComment.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -3740,26 +4509,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createComment.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createComment.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -3824,13 +4580,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Comment\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createComment.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createComment.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createEmail.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -3842,26 +4599,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createEmail.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createEmail.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -3926,13 +4670,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Email\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createEmail.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createEmail.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createPost.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -3944,26 +4689,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createPost.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createPost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createPost.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -4028,13 +4760,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Post\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createPost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createPost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createRequire.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -4046,26 +4779,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createRequire.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createRequire.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -4130,13 +4850,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Require\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createRequire.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createRequire.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -4148,26 +4869,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -4232,13 +4940,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createUser.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -4250,26 +4959,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createUser.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createUser.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -4334,44 +5030,32 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"User\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createUser.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createUser.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) - $util.error($ctx.error.message, $ctx.error.type) -#else - $util.toJson($ctx.result) -#end -## [End] Get ResponseTemplate. **", - "Mutation.customCreatePost.init.1.req.vtl": "## [Start] Initialization default values. ** -$util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) -#set( $createdAt = $util.time.nowISO8601() ) -$util.qr($ctx.stash.defaultValues.put(\\"id\\", $util.autoId())) -$util.qr($ctx.stash.defaultValues.put(\\"createdAt\\", $createdAt)) -$util.qr($ctx.stash.defaultValues.put(\\"updatedAt\\", $createdAt)) -$util.toJson({ - \\"version\\": \\"2018-05-29\\", - \\"payload\\": {} -}) -## [End] Initialization default values. **", - "Mutation.customCreatePost.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + $util.error($ctx.error.message, $ctx.error.type) +#else + $util.toJson($ctx.result) #end -## End - key condition ** +## [End] ResponseTemplate. **", + "Mutation.customCreatePost.init.1.req.vtl": "## [Start] Initialization default values. ** +$util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) +#set( $createdAt = $util.time.nowISO8601() ) +$util.qr($ctx.stash.defaultValues.put(\\"id\\", $util.autoId())) +$util.qr($ctx.stash.defaultValues.put(\\"createdAt\\", $createdAt)) +$util.qr($ctx.stash.defaultValues.put(\\"updatedAt\\", $createdAt)) +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Initialization default values. **", + "Mutation.customCreatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.customCreatePost.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -4436,13 +5120,20 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Post\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.customCreatePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.customCreatePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.customDeletePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.customDeletePost.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -4500,13 +5191,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.customDeletePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.customDeletePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.customUpdatePost.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -4516,6 +5208,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.customUpdatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.customUpdatePost.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -4645,13 +5343,20 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.customUpdatePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.customUpdatePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteAuthor.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -4709,13 +5414,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteAuthor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteAuthor.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteComment.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -4773,13 +5485,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteComment.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteComment.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteEmail.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -4837,13 +5556,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteEmail.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteEmail.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deletePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deletePost.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -4902,13 +5628,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) $util.qr($DeleteRequest.put(\\"_version\\", $util.defaultIfNull($ctx.args.input[\\"_version\\"], \\"0\\"))) $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deletePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deletePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteRequire.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -4966,13 +5699,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteRequire.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteRequire.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteTest.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -5030,13 +5770,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteUser.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -5094,13 +5841,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteUser.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteUser.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateAuthor.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -5110,6 +5858,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateAuthor.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -5239,13 +5993,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateAuthor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateAuthor.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateComment.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -5255,6 +6010,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateComment.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -5384,13 +6145,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateComment.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateComment.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateEmail.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -5400,6 +6162,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateEmail.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -5529,13 +6297,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateEmail.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateEmail.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updatePost.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -5545,6 +6314,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updatePost.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -5675,13 +6450,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updatePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updatePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateRequire.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -5691,6 +6467,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateRequire.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -5820,13 +6602,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateRequire.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateRequire.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -5836,6 +6619,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateTest.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -5965,13 +6754,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateUser.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -5981,6 +6771,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateUser.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -6110,35 +6906,73 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateUser.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateUser.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.customGetPost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.customGetPost.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.customGetPost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.customGetPost.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.customListPost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.customListPost.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -6148,8 +6982,20 @@ $util.toJson($GetRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -6173,189 +7019,443 @@ $util.toJson($GetRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.customListPost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.customListPost.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.getAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getAuthor.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getAuthor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getAuthor.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.getComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getComment.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getComment.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getComment.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.getEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getEmail.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getEmail.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getEmail.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.getEntity.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getEntity.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getEntity.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getEntity.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.getPost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getPost.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getPost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getPost.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.getRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getRequire.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getRequire.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getRequire.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.getTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getTest.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTest.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.getUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getUser.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getUser.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getUser.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.listAuthors.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listAuthors.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -6365,8 +7465,20 @@ $util.toJson($GetRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -6390,13 +7502,19 @@ $util.toJson($GetRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listAuthors.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listAuthors.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listComments.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listComments.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -6406,8 +7524,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -6431,13 +7561,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listComments.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listComments.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listEmails.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listEmails.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -6447,8 +7583,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -6472,13 +7620,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listEmails.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listEmails.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listPosts.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listPosts.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -6488,8 +7642,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -6513,13 +7679,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listPosts.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listPosts.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listRequires.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listRequires.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -6529,8 +7701,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -6554,13 +7738,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listRequires.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listRequires.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listTests.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listTests.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -6570,8 +7760,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -6595,13 +7797,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listTests.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listTests.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listUsers.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listUsers.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -6611,8 +7819,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -6636,38 +7856,380 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listUsers.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listUsers.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.syncPosts.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.syncPosts.req.vtl": "## [Start] Sync Request template. ** +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $filter = $filterExpression ) + #end +#end { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"Sync\\", - \\"filter\\": #if( $context.args.filter ) -$util.transform.toDynamoDBFilterExpression($ctx.args.filter) - #else -null - #end, - \\"limit\\": $util.defaultIfNull($ctx.args.limit, 100), - \\"lastSync\\": $util.toJson($util.defaultIfNull($ctx.args.lastSync, null)), - \\"nextToken\\": $util.toJson($util.defaultIfNull($ctx.args.nextToken, null)) -} -## [End] Sync Request template. **", - "Query.syncPosts.res.vtl": "## [Start] Get ResponseTemplate. ** -#if( $ctx.error ) - $util.error($ctx.error.message, $ctx.error.type, $ctx.result) -#else - $util.toJson($ctx.result) -#end -## [End] Get ResponseTemplate. **", + \\"operation\\": \\"Sync\\", + \\"filter\\": #if( $filter ) +$util.toJson($filter) + #else +null + #end, + \\"limit\\": $util.defaultIfNull($ctx.args.limit, 100), + \\"lastSync\\": $util.toJson($util.defaultIfNull($ctx.args.lastSync, null)), + \\"nextToken\\": $util.toJson($util.defaultIfNull($ctx.args.nextToken, null)) +} +## [End] Sync Request template. **", + "Query.syncPosts.res.vtl": "## [Start] ResponseTemplate. ** +#if( $ctx.error ) + $util.error($ctx.error.message, $ctx.error.type, $ctx.result) +#else + $util.toJson($ctx.result) +#end +## [End] ResponseTemplate. **", + "Subscription.onCreateAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateAuthor.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateAuthor.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateComment.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateComment.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateEmail.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateEmail.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreatePost.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreatePost.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateRequire.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateRequire.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateUser.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateUser.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteAuthor.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteAuthor.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteComment.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteComment.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteEmail.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteEmail.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeletePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeletePost.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeletePost.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteRequire.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteRequire.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteUser.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteUser.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateAuthor.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateAuthor.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateComment.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateComment.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateEmail.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateEmail.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdatePost.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdatePost.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateRequire.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateRequire.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateUser.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateUser.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", } `; -exports[`ModelTransformer: should generate sync resolver with ConflictHandlerType.OPTIMISTIC 1`] = ` +exports[`ModelTransformer: should generate sync resolver with ConflictHandlerType.Optimistic 1`] = ` Object { "Mutation.createAuthor.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) @@ -6680,26 +8242,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createAuthor.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createAuthor.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -6764,13 +8313,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Author\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createAuthor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createAuthor.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createComment.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -6782,26 +8332,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createComment.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createComment.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -6866,13 +8403,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Comment\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createComment.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createComment.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createEmail.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -6884,26 +8422,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createEmail.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createEmail.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -6968,13 +8493,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Email\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createEmail.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createEmail.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createPost.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -6986,26 +8512,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createPost.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createPost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createPost.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -7070,13 +8583,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Post\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createPost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createPost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createRequire.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -7088,26 +8602,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createRequire.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createRequire.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -7172,13 +8673,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Require\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createRequire.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createRequire.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -7190,26 +8692,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -7274,13 +8763,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createUser.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -7292,26 +8782,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createUser.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createUser.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -7376,13 +8853,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"User\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createUser.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createUser.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.customCreatePost.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -7394,26 +8872,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.customCreatePost.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.customCreatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.customCreatePost.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -7478,13 +8943,20 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Post\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.customCreatePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.customCreatePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.customDeletePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.customDeletePost.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -7542,13 +9014,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.customDeletePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.customDeletePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.customUpdatePost.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -7558,6 +9031,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.customUpdatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.customUpdatePost.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -7687,13 +9166,20 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.customUpdatePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.customUpdatePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteAuthor.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -7751,13 +9237,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteAuthor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteAuthor.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteComment.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -7815,13 +9308,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteComment.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteComment.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteEmail.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -7879,13 +9379,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteEmail.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteEmail.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deletePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deletePost.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -7944,13 +9451,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) $util.qr($DeleteRequest.put(\\"_version\\", $util.defaultIfNull($ctx.args.input[\\"_version\\"], \\"0\\"))) $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deletePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deletePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteRequire.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -8008,13 +9522,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteRequire.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteRequire.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteTest.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -8072,13 +9593,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteUser.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -8136,13 +9664,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteUser.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteUser.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateAuthor.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -8152,6 +9681,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateAuthor.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -8281,13 +9816,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateAuthor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateAuthor.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateComment.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -8297,6 +9833,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateComment.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -8426,13 +9968,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateComment.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateComment.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateEmail.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -8442,6 +9985,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateEmail.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -8571,13 +10120,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateEmail.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateEmail.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updatePost.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -8587,6 +10137,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updatePost.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -8717,13 +10273,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updatePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updatePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateRequire.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -8733,6 +10290,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateRequire.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -8862,13 +10425,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateRequire.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateRequire.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -8878,6 +10442,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateTest.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -9007,13 +10577,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateUser.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -9023,6 +10594,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateUser.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -9152,35 +10729,73 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateUser.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateUser.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.customGetPost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.customGetPost.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.customGetPost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.customGetPost.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.customListPost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.customListPost.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -9190,8 +10805,20 @@ $util.toJson($GetRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -9215,189 +10842,443 @@ $util.toJson($GetRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.customListPost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.customListPost.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.getAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getAuthor.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getAuthor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getAuthor.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getComment.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getComment.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getComment.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getEmail.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getEmail.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getEmail.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getEntity.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getEntity.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getEntity.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getEntity.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getPost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getPost.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getPost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getPost.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getRequire.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" +} ) +#if( $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues } ) -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getRequire.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getRequire.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getTest.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTest.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getUser.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getUser.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getUser.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.listAuthors.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listAuthors.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -9407,8 +11288,20 @@ $util.toJson($GetRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -9432,13 +11325,19 @@ $util.toJson($GetRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listAuthors.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listAuthors.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listComments.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listComments.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -9448,8 +11347,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -9473,13 +11384,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listComments.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listComments.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listEmails.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listEmails.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -9489,8 +11406,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -9514,13 +11443,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listEmails.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listEmails.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listPosts.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listPosts.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -9530,8 +11465,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -9555,13 +11502,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listPosts.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listPosts.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listRequires.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listRequires.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -9571,8 +11524,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -9596,13 +11561,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listRequires.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listRequires.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listTests.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listTests.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -9612,8 +11583,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -9637,13 +11620,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listTests.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listTests.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listUsers.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listUsers.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -9653,8 +11642,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -9678,19 +11679,46 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listUsers.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listUsers.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.syncPosts.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.syncPosts.req.vtl": "## [Start] Sync Request template. ** +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $filter = $filterExpression ) + #end +#end { \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"Sync\\", - \\"filter\\": #if( $context.args.filter ) -$util.transform.toDynamoDBFilterExpression($ctx.args.filter) + \\"filter\\": #if( $filter ) +$util.toJson($filter) #else null #end, @@ -9699,13 +11727,328 @@ null \\"nextToken\\": $util.toJson($util.defaultIfNull($ctx.args.nextToken, null)) } ## [End] Sync Request template. **", - "Query.syncPosts.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.syncPosts.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Subscription.onCreateAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateAuthor.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateAuthor.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateComment.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateComment.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateEmail.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateEmail.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreatePost.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreatePost.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateRequire.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateRequire.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateUser.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateUser.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteAuthor.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteAuthor.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteComment.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteComment.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteEmail.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteEmail.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeletePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeletePost.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeletePost.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteRequire.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteRequire.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteUser.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteUser.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateAuthor.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateAuthor.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateComment.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateComment.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateEmail.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateEmail.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateEmail.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdatePost.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdatePost.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateRequire.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateRequire.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateRequire.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateUser.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateUser.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", } `; @@ -9873,25 +12216,6 @@ type Subscription { exports[`ModelTransformer: should have timestamps as nullable fields when the type makes it non-nullable 2`] = ` "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -10092,25 +12416,6 @@ $util.toJson($UpdateItem) exports[`ModelTransformer: should not add default primary key when ID is defined 1`] = ` "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -10448,25 +12753,6 @@ type Subscription { exports[`ModelTransformer: should not to auto generate createdAt and updatedAt when the type in schema is not AWSDateTime 2`] = ` "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -10819,25 +13105,6 @@ type Subscription { exports[`ModelTransformer: should not to include createdAt and updatedAt field when timestamps is set to null 2`] = ` "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -11192,25 +13459,6 @@ type Subscription { exports[`ModelTransformer: should support timestamp parameters when generating pipelineFunctions and output schema 2`] = ` "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** diff --git a/packages/amplify-graphql-model-transformer/src/__tests__/model-transformer.test.ts b/packages/amplify-graphql-model-transformer/src/__tests__/model-transformer.test.ts index 557b0565fb5..420ae5e4e38 100644 --- a/packages/amplify-graphql-model-transformer/src/__tests__/model-transformer.test.ts +++ b/packages/amplify-graphql-model-transformer/src/__tests__/model-transformer.test.ts @@ -881,7 +881,7 @@ describe('ModelTransformer: ', () => { validateModelSchema(parse(out.schema)); }); - it('should generate sync resolver with ConflictHandlerType.AUTOMERGE', () => { + it('should generate sync resolver with ConflictHandlerType.Automerge', () => { const validSchema = ` type Post @model { id: ID! @@ -950,7 +950,7 @@ describe('ModelTransformer: ', () => { validateModelSchema(parse(definition)); }); - it('should generate sync resolver with ConflictHandlerType.OPTIMISTIC', () => { + it('should generate sync resolver with ConflictHandlerType.Optimistic', () => { const validSchema = ` type Post @model { id: ID! diff --git a/packages/amplify-graphql-model-transformer/src/definitions.ts b/packages/amplify-graphql-model-transformer/src/definitions.ts index e1aafe51b0e..77d4eb31c58 100644 --- a/packages/amplify-graphql-model-transformer/src/definitions.ts +++ b/packages/amplify-graphql-model-transformer/src/definitions.ts @@ -13,4 +13,4 @@ export const BOOLEAN_FUNCTIONS = new Set(['attributeExists', 'attributeT export const ATTRIBUTE_TYPES = ['binary', 'binarySet', 'bool', 'list', 'map', 'number', 'numberSet', 'string', 'stringSet', '_null']; - +export const OPERATION_KEY = '__operation'; diff --git a/packages/amplify-graphql-model-transformer/src/graphql-model-transformer.ts b/packages/amplify-graphql-model-transformer/src/graphql-model-transformer.ts index 544ccc833f8..0d67a92cd98 100644 --- a/packages/amplify-graphql-model-transformer/src/graphql-model-transformer.ts +++ b/packages/amplify-graphql-model-transformer/src/graphql-model-transformer.ts @@ -54,6 +54,7 @@ import { makeUpdateInputField, } from './graphql-types'; import { + generateAuthExpressionForSandboxMode, generateCreateInitSlotTemplate, generateCreateRequestTemplate, generateDefaultResponseMappingTemplate, @@ -64,7 +65,12 @@ import { generateUpdateInitSlotTemplate, generateUpdateRequestTemplate, } from './resolvers'; -import { generateGetRequestTemplate, generateListRequestTemplate, generateSyncRequestTemplate } from './resolvers/query'; +import { + generateGetRequestTemplate, + generateGetResponseTemplate, + generateListRequestTemplate, + generateSyncRequestTemplate, +} from './resolvers/query'; import { DirectiveWrapper, FieldWrapper, @@ -88,17 +94,17 @@ export type ModelDirectiveConfiguration = { list: OptionalAndNullable; sync: OptionalAndNullable; }>; - mutations: { + mutations: OptionalAndNullable<{ create: OptionalAndNullable; update: OptionalAndNullable; delete: OptionalAndNullable; - } | null; - subscriptions: { + }>; + subscriptions: OptionalAndNullable<{ onCreate: OptionalAndNullable[]; onUpdate: OptionalAndNullable[]; onDelete: OptionalAndNullable[]; - level: Partial; - } | null; + level: SubscriptionLevel; + }>; timestamps: OptionalAndNullable<{ createdAt: OptionalAndNullable; updatedAt: OptionalAndNullable; @@ -169,12 +175,13 @@ export class ModelTransformer extends TransformerModelBase implements Transforme `'${definition.name.value}' is a reserved type name and currently in use within the default schema element.`, ); } - // todo: get model configuration with default values and store it in the map const typeName = definition.name.value; + if (ctx.isProjectUsingDataStore()) { SyncUtils.validateResolverConfigForType(ctx, typeName); } + const directiveWrapped: DirectiveWrapper = new DirectiveWrapper(directive); const options = directiveWrapped.getArguments({ queries: { @@ -188,7 +195,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme delete: toCamelCase(['delete', typeName]), }, subscriptions: { - level: SubscriptionLevel.public, + level: SubscriptionLevel.on, onCreate: [this.ensureValidSubscriptionName(toCamelCase(['onCreate', typeName]))], onDelete: [this.ensureValidSubscriptionName(toCamelCase(['onDelete', typeName]))], onUpdate: [this.ensureValidSubscriptionName(toCamelCase(['onUpdate', typeName]))], @@ -241,8 +248,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme generateResolvers = (context: TransformerContextProvider): void => { for (let type of this.typesWithModelDirective) { - const def = context.output.getObject(type); - + const def = context.output.getObject(type)!; // This name is used by the mock functionality. Changing this can break mock. const tableLogicalName = `${def!.name.value}Table`; const stack = context.stackManager.getStackFor(tableLogicalName, def!.name.value); @@ -265,7 +271,13 @@ export class ModelTransformer extends TransformerModelBase implements Transforme default: throw new Error('Unknown query field type'); } - + resolver.addToSlot( + 'postAuth', + MappingTemplate.s3MappingTemplateFromString( + generateAuthExpressionForSandboxMode(context), + `${query.typeName}.${query.fieldName}.{slotName}.{slotIndex}.req.vtl`, + ), + ); resolver.mapToStack(stack); context.resolvers.addResolver(query.typeName, query.fieldName, resolver); } @@ -284,11 +296,49 @@ export class ModelTransformer extends TransformerModelBase implements Transforme resolver = this.generateUpdateResolver(context, def!, mutation.typeName, mutation.fieldName); break; default: - throw new Error('Unknown query field type'); + throw new Error('Unknown mutation field type'); } + resolver.addToSlot( + 'postAuth', + MappingTemplate.s3MappingTemplateFromString( + generateAuthExpressionForSandboxMode(context), + `${mutation.typeName}.${mutation.fieldName}.{slotName}.{slotIndex}.req.vtl`, + ), + ); resolver.mapToStack(stack); context.resolvers.addResolver(mutation.typeName, mutation.fieldName, resolver); } + + const subscriptionLevel = this.modelDirectiveConfig.get(def.name.value)?.subscriptions?.level; + // in order to create subscription resolvers the level needs to be on + if (subscriptionLevel === SubscriptionLevel.on) { + const subscriptionFields = this.getSubscriptionFieldNames(context, def!); + for (let subscription of subscriptionFields.values()) { + let resolver; + switch (subscription.type) { + case SubscriptionFieldType.ON_CREATE: + resolver = this.generateOnCreateResolver(context, def, subscription.typeName, subscription.fieldName); + break; + case SubscriptionFieldType.ON_UPDATE: + resolver = this.generateOnUpdateResolver(context, def, subscription.typeName, subscription.fieldName); + break; + case SubscriptionFieldType.ON_DELETE: + resolver = this.generateOnDeleteResolver(context, def, subscription.typeName, subscription.fieldName); + break; + default: + throw new Error('Unknown subscription field type'); + } + resolver.addToSlot( + 'postAuth', + MappingTemplate.s3MappingTemplateFromString( + generateAuthExpressionForSandboxMode(context), + `${subscription.typeName}.${subscription.fieldName}.{slotName}.{slotIndex}.req.vtl`, + ), + ); + resolver.mapToStack(stack); + context.resolvers.addResolver(subscription.typeName, subscription.fieldName, resolver); + } + } } }; @@ -307,10 +357,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme fieldName, dataSource, MappingTemplate.s3MappingTemplateFromString(generateGetRequestTemplate(), `${typeName}.${fieldName}.req.vtl`), - MappingTemplate.s3MappingTemplateFromString( - generateDefaultResponseMappingTemplate(isSyncEnabled), - `${typeName}.${fieldName}.res.vtl`, - ), + MappingTemplate.s3MappingTemplateFromString(generateGetResponseTemplate(isSyncEnabled), `${typeName}.${fieldName}.res.vtl`), ); } return this.resolverMap[resolverKey]; @@ -359,7 +406,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme `${typeName}.${fieldName}.req.vtl`, ), MappingTemplate.s3MappingTemplateFromString( - generateDefaultResponseMappingTemplate(isSyncEnabled), + generateDefaultResponseMappingTemplate(isSyncEnabled, true), `${typeName}.${fieldName}.res.vtl`, ), ); @@ -391,7 +438,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme dataSource, MappingTemplate.s3MappingTemplateFromString(generateDeleteRequestTemplate(isSyncEnabled), `${typeName}.${fieldName}.req.vtl`), MappingTemplate.s3MappingTemplateFromString( - generateDefaultResponseMappingTemplate(isSyncEnabled), + generateDefaultResponseMappingTemplate(isSyncEnabled, true), `${typeName}.${fieldName}.res.vtl`, ), ); @@ -701,7 +748,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme dataSource, MappingTemplate.s3MappingTemplateFromString(generateCreateRequestTemplate(type.name.value), `${typeName}.${fieldName}.req.vtl`), MappingTemplate.s3MappingTemplateFromString( - generateDefaultResponseMappingTemplate(isSyncEnabled), + generateDefaultResponseMappingTemplate(isSyncEnabled, true), `${typeName}.${fieldName}.res.vtl`, ), ); @@ -1164,7 +1211,6 @@ export class ModelTransformer extends TransformerModelBase implements Transforme SyncUtils.createSyncLambdaIAMPolicy(stack, syncConfig.LambdaConflictHandler.name, syncConfig.LambdaConflictHandler.region), ); } - return role; } diff --git a/packages/amplify-graphql-model-transformer/src/index.ts b/packages/amplify-graphql-model-transformer/src/index.ts index d419f3ed214..10267d40d30 100644 --- a/packages/amplify-graphql-model-transformer/src/index.ts +++ b/packages/amplify-graphql-model-transformer/src/index.ts @@ -1,3 +1,4 @@ -export { ModelTransformer } from './graphql-model-transformer'; +export { ModelTransformer, ModelDirectiveConfiguration, SubscriptionLevel } from './graphql-model-transformer'; +export { OPERATION_KEY } from './definitions'; export * from './graphql-types'; export * from './resolvers'; diff --git a/packages/amplify-graphql-model-transformer/src/resolvers/common.ts b/packages/amplify-graphql-model-transformer/src/resolvers/common.ts index ed2fcd07e41..01c9059ac81 100644 --- a/packages/amplify-graphql-model-transformer/src/resolvers/common.ts +++ b/packages/amplify-graphql-model-transformer/src/resolvers/common.ts @@ -15,7 +15,13 @@ import { ifElse, printBlock, toJson, + qref, + str, + not, } from 'graphql-mapping-template'; +import { OPERATION_KEY } from '../definitions'; + +const API_KEY = 'API Key Authorization'; /** * Helper method to generate code that converts DynamoDB condition object to condition @@ -57,9 +63,11 @@ export const generateConditionSlot = (inputConditionObjectName: string, conditio /** * Generate common response template used by most of the resolvers. + * Append operation if response is coming from a mutation, this is to protect field resolver for subscriptions */ -export const generateDefaultResponseMappingTemplate = (isSyncEnabled: boolean): string => { +export const generateDefaultResponseMappingTemplate = (isSyncEnabled: boolean, mutation = false): string => { const statements: Expression[] = []; + if (mutation) statements.push(qref(methodCall(ref('ctx.result.put'), str(OPERATION_KEY), str('Mutation')))); if (isSyncEnabled) { statements.push( ifElse( @@ -74,14 +82,30 @@ export const generateDefaultResponseMappingTemplate = (isSyncEnabled: boolean): ); } - return printBlock('Get ResponseTemplate')(compoundExpression(statements)); + return printBlock('ResponseTemplate')(compoundExpression(statements)); }; /** - * Util function to gernate resolver key used to keep track of all the resolvers in memory + * Util function to generate resolver key used to keep track of all the resolvers in memory * @param typeName Name of the type * @param fieldName Name of the field */ export const generateResolverKey = (typeName: string, fieldName: string): string => { return `${typeName}.${fieldName}`; }; + +/** + * Util function to generate sandbox mode expression + * @param ctx context to get sandbox mode + */ +export const generateAuthExpressionForSandboxMode = (ctx: any): string => { + const enabled = ctx.resourceHelper.api.sandboxModeEnabled; + let exp; + + if (enabled) exp = iff(notEquals(methodCall(ref('util.authType')), str(API_KEY)), methodCall(ref('util.unauthorized'))); + else exp = methodCall(ref('util.unauthorized')); + + return printBlock(`Sandbox Mode ${enabled ? 'Enabled' : 'Disabled'}`)( + compoundExpression([iff(not(ref('ctx.stash.get("hasAuth")')), exp), toJson(obj({}))]), + ); +}; diff --git a/packages/amplify-graphql-model-transformer/src/resolvers/mutation.ts b/packages/amplify-graphql-model-transformer/src/resolvers/mutation.ts index 3aa5f732ba1..240b3899497 100644 --- a/packages/amplify-graphql-model-transformer/src/resolvers/mutation.ts +++ b/packages/amplify-graphql-model-transformer/src/resolvers/mutation.ts @@ -152,8 +152,6 @@ export const generateUpdateRequestTemplate = (modelName: string, isSyncEnabled: */ export const generateCreateRequestTemplate = (modelName: string): string => { const statements: Expression[] = [ - // set key the condition - ...generateKeyConditionTemplate(false), // Generate conditions comment('Set the default values to put request'), set(ref('mergedValues'), methodCall(ref('util.defaultIfNull'), ref('ctx.stash.defaultValues'), obj({}))), @@ -174,7 +172,6 @@ export const generateCreateRequestTemplate = (modelName: string): string => { ), // add conditions - iff(ref('context.args.condition'), qref(methodCall(ref('ctx.stash.conditions.add'), ref('context.args.condition')))), // key conditions ...generateKeyConditionTemplate(false), diff --git a/packages/amplify-graphql-model-transformer/src/resolvers/query.ts b/packages/amplify-graphql-model-transformer/src/resolvers/query.ts index d73bfb587be..ac92ee42a72 100644 --- a/packages/amplify-graphql-model-transformer/src/resolvers/query.ts +++ b/packages/amplify-graphql-model-transformer/src/resolvers/query.ts @@ -16,27 +16,86 @@ import { equals, bool, and, + isNullOrEmpty, + list, + forEach, nul, } from 'graphql-mapping-template'; import { ResourceConstants } from 'graphql-transformer-common'; +const authFilter = ref('ctx.stash.authFilter'); + /** * Generate get query resolver template */ export const generateGetRequestTemplate = (): string => { const statements: Expression[] = [ - set(ref('GetRequest'), obj({ version: str('2018-05-29'), operation: str('GetItem') })), + set(ref('GetRequest'), obj({ version: str('2018-05-29'), operation: str('Query') })), ifElse( ref('ctx.stash.metadata.modelObjectKey'), - set(ref('key'), ref('ctx.stash.metadata.modelObjectKey')), - compoundExpression([set(ref('key'), obj({ id: methodCall(ref('util.dynamodb.toDynamoDB'), ref('ctx.args.id')) }))]), + compoundExpression([ + set(ref('expression'), str('')), + set(ref('expressionNames'), obj({})), + set(ref('expressionValues'), obj({})), + forEach(ref('item'), ref('ctx.stash.metadata.modelObjectKey.entrySet()'), [ + set(ref('expression'), str('$expression#keyCount$velocityCount = :valueCount$velocityCount AND ')), + qref(methodCall(ref('expressionNames.put'), str('#keyCount$velocityCount'), ref('item.key'))), + qref(methodCall(ref('expressionValues.put'), str(':valueCount$velocityCount'), ref('item.value'))), + ]), + set(ref('expression'), methodCall(ref('expression.replaceAll'), str('AND $'), str(''))), + set( + ref('query'), + obj({ expression: ref('expression'), expressionNames: ref('expressionNames'), expressionValues: ref('expressionValues') }), + ), + ]), + set( + ref('query'), + obj({ + expression: str('id = :id'), + expressionValues: obj({ + ':id': methodCall(ref('util.parseJson'), methodCall(ref('util.dynamodb.toDynamoDBJson'), ref('ctx.args.id'))), + }), + }), + ), + ), + qref(methodCall(ref('GetRequest.put'), str('query'), ref('query'))), + iff( + not(isNullOrEmpty(authFilter)), + qref( + methodCall( + ref('GetRequest.put'), + str('filter'), + methodCall(ref('util.parseJson'), methodCall(ref('util.transform.toDynamoDBFilterExpression'), authFilter)), + ), + ), ), - qref(methodCall(ref('GetRequest.put'), str('key'), ref('key'))), toJson(ref('GetRequest')), ]; return printBlock('Get Request template')(compoundExpression(statements)); }; +export const generateGetResponseTemplate = (isSyncEnabled: boolean): string => { + const statements = new Array(); + if (isSyncEnabled) { + statements.push( + iff(ref('ctx.error'), methodCall(ref('util.error'), ref('ctx.error.message'), ref('ctx.error.type'), ref('ctx.result'))), + ); + } else { + statements.push(iff(ref('ctx.error'), methodCall(ref('util.error'), ref('ctx.error.message'), ref('ctx.error.type')))); + } + statements.push( + ifElse( + and([not(ref('ctx.result.items.isEmpty()')), equals(ref('ctx.result.scannedCount'), int(1))]), + toJson(ref('ctx.result.items[0]')), + compoundExpression([ + iff(and([ref('ctx.result.items.isEmpty()'), equals(ref('ctx.result.scannedCount'), int(1))]), ref('util.unauthorized()')), + toJson(nul()), + ]), + ), + ); + return printBlock('Get Response template')(compoundExpression(statements)); +}; + export const generateListRequestTemplate = (): string => { const requestVariable = 'ListRequest'; const modelQueryObj = 'ctx.stash.modelQueryExpression'; @@ -51,12 +110,20 @@ export const generateListRequestTemplate = (): string => { }), ), iff(ref('context.args.nextToken'), set(ref(`${requestVariable}.nextToken`), ref('context.args.nextToken'))), + ifElse( + not(isNullOrEmpty(authFilter)), + compoundExpression([ + set(ref('filter'), authFilter), + iff(not(isNullOrEmpty(ref('ctx.args.filter'))), set(ref('filter'), obj({ and: list([ref('filter'), ref('ctx.args.filter')]) }))), + ]), + iff(not(isNullOrEmpty(ref('ctx.args.filter'))), set(ref('filter'), ref('ctx.args.filter'))), + ), iff( - ref('context.args.filter'), + not(isNullOrEmpty(ref('filter'))), compoundExpression([ set( ref(`filterExpression`), - methodCall(ref('util.parseJson'), methodCall(ref('util.transform.toDynamoDBFilterExpression'), ref('ctx.args.filter'))), + methodCall(ref('util.parseJson'), methodCall(ref('util.transform.toDynamoDBFilterExpression'), ref('filter'))), ), iff( not(methodCall(ref('util.isNullOrBlank'), ref('filterExpression.expression'))), @@ -95,10 +162,37 @@ export const generateListRequestTemplate = (): string => { export const generateSyncRequestTemplate = (): string => { return printBlock('Sync Request template')( compoundExpression([ + ifElse( + not(isNullOrEmpty(authFilter)), + compoundExpression([ + set(ref('filter'), authFilter), + iff(not(isNullOrEmpty(ref('ctx.args.filter'))), set(ref('filter'), obj({ and: list([ref('filter'), ref('ctx.args.filter')]) }))), + ]), + iff(not(isNullOrEmpty(ref('ctx.args.filter'))), set(ref('filter'), ref('ctx.args.filter'))), + ), + iff( + not(isNullOrEmpty(ref('filter'))), + compoundExpression([ + set( + ref(`filterExpression`), + methodCall(ref('util.parseJson'), methodCall(ref('util.transform.toDynamoDBFilterExpression'), ref('filter'))), + ), + iff( + not(methodCall(ref('util.isNullOrBlank'), ref('filterExpression.expression'))), + compoundExpression([ + iff( + equals(methodCall(ref('filterEpression.expressionValues.size')), int(0)), + qref(methodCall(ref('filterEpression.remove'), str('expressionValues'))), + ), + set(ref('filter'), ref('filterExpression')), + ]), + ), + ]), + ), obj({ version: str('2018-05-29'), operation: str('Sync'), - filter: ifElse(ref('context.args.filter'), ref('util.transform.toDynamoDBFilterExpression($ctx.args.filter)'), nul()), + filter: ifElse(ref('filter'), ref('util.toJson($filter)'), nul()), limit: ref(`util.defaultIfNull($ctx.args.limit, ${ResourceConstants.DEFAULT_SYNC_QUERY_PAGE_LIMIT})`), lastSync: ref('util.toJson($util.defaultIfNull($ctx.args.lastSync, null))'), nextToken: ref('util.toJson($util.defaultIfNull($ctx.args.nextToken, null))'), diff --git a/packages/amplify-graphql-predictions-transformer/src/graphql-predictions-transformer.ts b/packages/amplify-graphql-predictions-transformer/src/graphql-predictions-transformer.ts index bd3b5eb2885..db57b7e0e75 100644 --- a/packages/amplify-graphql-predictions-transformer/src/graphql-predictions-transformer.ts +++ b/packages/amplify-graphql-predictions-transformer/src/graphql-predictions-transformer.ts @@ -1,5 +1,12 @@ import * as path from 'path'; -import { DirectiveWrapper, InvalidDirectiveError, MappingTemplate, TransformerPluginBase } from '@aws-amplify/graphql-transformer-core'; +import { + DirectiveWrapper, + IAM_AUTH_ROLE_PARAMETER, + IAM_UNAUTH_ROLE_PARAMETER, + InvalidDirectiveError, + MappingTemplate, + TransformerPluginBase, +} from '@aws-amplify/graphql-transformer-core'; import { TransformerContextProvider, TransformerSchemaVisitStepContextProvider, @@ -50,6 +57,7 @@ import { translateTextAmzTarget, PREDICTIONS_DIRECTIVE_STACK, } from './utils/constants'; +import { AuthorizationType } from '@aws-cdk/aws-appsync'; type PredictionsDirectiveConfiguration = { actions: string[] | undefined; @@ -91,7 +99,7 @@ export class PredictionsTransformer extends TransformerPluginBase { } as PredictionsDirectiveConfiguration); if (!Array.isArray(args.actions)) { - args.actions = [(args.actions as unknown) as string]; + args.actions = [args.actions as unknown as string]; } validateActions(args.actions); @@ -318,23 +326,50 @@ function createResolver( if (referencesEnv(bucketName)) { const env = context.stackManager.getParameter(ResourceConstants.PARAMETERS.Env) as cdk.CfnParameter; - substitutions.env = (env as unknown) as string; + substitutions.env = env as unknown as string; + } + const requestTemplate = [ + cdk.Fn.conditionIf( + ResourceConstants.CONDITIONS.HasEnvironmentParameter, + cdk.Fn.sub(`$util.qr($ctx.stash.put("s3Bucket", "${bucketName}"))`, substitutions), + cdk.Fn.sub(`$util.qr($ctx.stash.put("s3Bucket", "${removeEnvReference(bucketName)}"))`, { + hash: cdk.Fn.select(3, cdk.Fn.split('-', cdk.Fn.ref('AWS::StackName'))), + }), + ) as unknown as string, + print(compoundExpression([qref('$ctx.stash.put("isList", false)')])), + ]; + // TODO: predictions should use resolver manager + const authModes = [context.authConfig.defaultAuthentication, ...(context.authConfig.additionalAuthenticationProviders || [])].map( + mode => mode?.authenticationType, + ); + if (authModes.includes(AuthorizationType.IAM)) { + const authRoleParameter = (context.stackManager.getParameter(IAM_AUTH_ROLE_PARAMETER) as cdk.CfnParameter).valueAsString; + const unauthRoleParameter = (context.stackManager.getParameter(IAM_UNAUTH_ROLE_PARAMETER) as cdk.CfnParameter).valueAsString; + requestTemplate.push( + `$util.qr($ctx.stash.put("authRole", "arn:aws:sts::${ + cdk.Stack.of(context.stackManager.rootStack).account + }:assumed-role/${authRoleParameter}/CognitoIdentityCredentials"))`, + `$util.qr($ctx.stash.put("unauthRole", "arn:aws:sts::${ + cdk.Stack.of(context.stackManager.rootStack).account + }:assumed-role/${unauthRoleParameter}/CognitoIdentityCredentials"))`, + ); } + requestTemplate.push(print(obj({}))); return context.api.host.addResolver( config.resolverTypeName, config.resolverFieldName, MappingTemplate.inlineTemplateFromString( - (cdk.Fn.join('\n', [ - (cdk.Fn.conditionIf( + cdk.Fn.join('\n', [ + cdk.Fn.conditionIf( ResourceConstants.CONDITIONS.HasEnvironmentParameter, cdk.Fn.sub(`$util.qr($ctx.stash.put("s3Bucket", "${bucketName}"))`, substitutions), cdk.Fn.sub(`$util.qr($ctx.stash.put("s3Bucket", "${removeEnvReference(bucketName)}"))`, { hash: cdk.Fn.select(3, cdk.Fn.split('-', cdk.Fn.ref('AWS::StackName'))), }), - ) as unknown) as string, + ) as unknown as string, print(compoundExpression([qref('$ctx.stash.put("isList", false)'), obj({})])), - ]) as unknown) as string, + ]) as unknown as string, ), MappingTemplate.inlineTemplateFromString( print( @@ -398,11 +433,11 @@ function removeEnvReference(value: string): string { function joinWithEnv(context: TransformerContextProvider, separator: string, listToJoin: any[]): string { const env = context.stackManager.getParameter(ResourceConstants.PARAMETERS.Env) as cdk.CfnParameter; - return (cdk.Fn.conditionIf( + return cdk.Fn.conditionIf( ResourceConstants.CONDITIONS.HasEnvironmentParameter, cdk.Fn.join(separator, [...listToJoin, env]), cdk.Fn.join(separator, listToJoin), - ) as unknown) as string; + ) as unknown as string; } function needsList(action: string, isCurrentlyList: boolean): boolean { @@ -500,14 +535,14 @@ function getStorageArn(context: TransformerContextProvider, bucketName: string): if (referencesEnv(bucketName)) { const env = context.stackManager.getParameter(ResourceConstants.PARAMETERS.Env) as cdk.CfnParameter; - substitutions.env = (env as unknown) as string; + substitutions.env = env as unknown as string; } - return (cdk.Fn.conditionIf( + return cdk.Fn.conditionIf( ResourceConstants.CONDITIONS.HasEnvironmentParameter, cdk.Fn.sub(s3ArnKey(bucketName), substitutions), cdk.Fn.sub(s3ArnKey(removeEnvReference(bucketName)), { hash: cdk.Fn.select(3, cdk.Fn.split('-', cdk.Fn.ref('AWS::StackName'))) }), - ) as unknown) as string; + ) as unknown as string; } function createActionFunction(context: TransformerContextProvider, stack: cdk.Stack, action: string, datasourceName: string) { diff --git a/packages/amplify-graphql-relational-transformer/src/__tests__/__snapshots__/amplify-graphql-has-many-transformer.test.ts.snap b/packages/amplify-graphql-relational-transformer/src/__tests__/__snapshots__/amplify-graphql-has-many-transformer.test.ts.snap index d06564b1739..e12a63b0af5 100644 --- a/packages/amplify-graphql-relational-transformer/src/__tests__/__snapshots__/amplify-graphql-has-many-transformer.test.ts.snap +++ b/packages/amplify-graphql-relational-transformer/src/__tests__/__snapshots__/amplify-graphql-has-many-transformer.test.ts.snap @@ -7639,7 +7639,7 @@ Object { "directives": Array [], "kind": "FieldDefinition", "loc": Object { - "end": 5275, + "end": 5260, "start": 5241, }, "name": Object { @@ -7653,22 +7653,22 @@ Object { "type": Object { "kind": "ListType", "loc": Object { - "end": 5275, + "end": 5260, "start": 5248, }, "type": Object { "kind": "NamedType", "loc": Object { - "end": 5274, + "end": 5259, "start": 5249, }, "name": Object { "kind": "Name", "loc": Object { - "end": 5274, + "end": 5259, "start": 5249, }, - "value": "ModelPostEditorConnection", + "value": "PostEditor", }, }, }, @@ -7679,28 +7679,28 @@ Object { "directives": Array [], "kind": "FieldDefinition", "loc": Object { - "end": 5295, - "start": 5278, + "end": 5280, + "start": 5263, }, "name": Object { "kind": "Name", "loc": Object { - "end": 5287, - "start": 5278, + "end": 5272, + "start": 5263, }, "value": "nextToken", }, "type": Object { "kind": "NamedType", "loc": Object { - "end": 5295, - "start": 5289, + "end": 5280, + "start": 5274, }, "name": Object { "kind": "Name", "loc": Object { - "end": 5295, - "start": 5289, + "end": 5280, + "start": 5274, }, "value": "String", }, @@ -7710,7 +7710,7 @@ Object { "interfaces": Array [], "kind": "ObjectTypeDefinition", "loc": Object { - "end": 5297, + "end": 5282, "start": 5206, }, "name": Object { @@ -7732,28 +7732,28 @@ Object { "directives": Array [], "kind": "InputValueDefinition", "loc": Object { - "end": 5352, - "start": 5336, + "end": 5337, + "start": 5321, }, "name": Object { "kind": "Name", "loc": Object { - "end": 5338, - "start": 5336, + "end": 5323, + "start": 5321, }, "value": "id", }, "type": Object { "kind": "NamedType", "loc": Object { - "end": 5352, - "start": 5340, + "end": 5337, + "start": 5325, }, "name": Object { "kind": "Name", "loc": Object { - "end": 5352, - "start": 5340, + "end": 5337, + "start": 5325, }, "value": "ModelIDInput", }, @@ -7765,28 +7765,28 @@ Object { "directives": Array [], "kind": "InputValueDefinition", "loc": Object { - "end": 5375, - "start": 5355, + "end": 5360, + "start": 5340, }, "name": Object { "kind": "Name", "loc": Object { - "end": 5361, - "start": 5355, + "end": 5346, + "start": 5340, }, "value": "postID", }, "type": Object { "kind": "NamedType", "loc": Object { - "end": 5375, - "start": 5363, + "end": 5360, + "start": 5348, }, "name": Object { "kind": "Name", "loc": Object { - "end": 5375, - "start": 5363, + "end": 5360, + "start": 5348, }, "value": "ModelIDInput", }, @@ -7798,28 +7798,28 @@ Object { "directives": Array [], "kind": "InputValueDefinition", "loc": Object { - "end": 5400, - "start": 5378, + "end": 5385, + "start": 5363, }, "name": Object { "kind": "Name", "loc": Object { - "end": 5386, - "start": 5378, + "end": 5371, + "start": 5363, }, "value": "editorID", }, "type": Object { "kind": "NamedType", "loc": Object { - "end": 5400, - "start": 5388, + "end": 5385, + "start": 5373, }, "name": Object { "kind": "Name", "loc": Object { - "end": 5400, - "start": 5388, + "end": 5385, + "start": 5373, }, "value": "ModelIDInput", }, @@ -7831,34 +7831,34 @@ Object { "directives": Array [], "kind": "InputValueDefinition", "loc": Object { - "end": 5436, - "start": 5403, + "end": 5421, + "start": 5388, }, "name": Object { "kind": "Name", "loc": Object { - "end": 5406, - "start": 5403, + "end": 5391, + "start": 5388, }, "value": "and", }, "type": Object { "kind": "ListType", "loc": Object { - "end": 5436, - "start": 5408, + "end": 5421, + "start": 5393, }, "type": Object { "kind": "NamedType", "loc": Object { - "end": 5435, - "start": 5409, + "end": 5420, + "start": 5394, }, "name": Object { "kind": "Name", "loc": Object { - "end": 5435, - "start": 5409, + "end": 5420, + "start": 5394, }, "value": "ModelPostEditorFilterInput", }, @@ -7871,34 +7871,34 @@ Object { "directives": Array [], "kind": "InputValueDefinition", "loc": Object { - "end": 5471, - "start": 5439, + "end": 5456, + "start": 5424, }, "name": Object { "kind": "Name", "loc": Object { - "end": 5441, - "start": 5439, + "end": 5426, + "start": 5424, }, "value": "or", }, "type": Object { "kind": "ListType", "loc": Object { - "end": 5471, - "start": 5443, + "end": 5456, + "start": 5428, }, "type": Object { "kind": "NamedType", "loc": Object { - "end": 5470, - "start": 5444, + "end": 5455, + "start": 5429, }, "name": Object { "kind": "Name", "loc": Object { - "end": 5470, - "start": 5444, + "end": 5455, + "start": 5429, }, "value": "ModelPostEditorFilterInput", }, @@ -7911,28 +7911,28 @@ Object { "directives": Array [], "kind": "InputValueDefinition", "loc": Object { - "end": 5505, - "start": 5474, + "end": 5490, + "start": 5459, }, "name": Object { "kind": "Name", "loc": Object { - "end": 5477, - "start": 5474, + "end": 5462, + "start": 5459, }, "value": "not", }, "type": Object { "kind": "NamedType", "loc": Object { - "end": 5505, - "start": 5479, + "end": 5490, + "start": 5464, }, "name": Object { "kind": "Name", "loc": Object { - "end": 5505, - "start": 5479, + "end": 5490, + "start": 5464, }, "value": "ModelPostEditorFilterInput", }, @@ -7941,14 +7941,14 @@ Object { ], "kind": "InputObjectTypeDefinition", "loc": Object { - "end": 5507, - "start": 5299, + "end": 5492, + "start": 5284, }, "name": Object { "kind": "Name", "loc": Object { - "end": 5331, - "start": 5305, + "end": 5316, + "start": 5290, }, "value": "ModelPostEditorFilterInput", }, @@ -7956,7 +7956,7 @@ Object { ], "kind": "Document", "loc": Object { - "end": 5509, + "end": 5494, "start": 0, }, } @@ -8018,6 +8018,27 @@ Object { $util.qr($query.expressionValues.put(\\":sortKey\\", { \\"S\\": \\"$ctx.args.childName.ge\\" })) #end ## [End] Applying Key Condition ** + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end + #else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end + #end + #if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $filter = $filterExpression ) + #end + #end { \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"Query\\", @@ -8031,8 +8052,8 @@ false #else true #end, - \\"filter\\": #if( $context.args.filter ) -$util.transform.toDynamoDBFilterExpression($ctx.args.filter) + \\"filter\\": #if( $filter ) +$util.toJson($filter) #else null #end, @@ -8130,6 +8151,27 @@ $util.error($ctx.error.message, $ctx.error.type) ## [End] Applying Key Condition ** + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end + #else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end + #end + #if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $filter = $filterExpression ) + #end + #end { \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"Query\\", @@ -8143,8 +8185,8 @@ false #else true #end, - \\"filter\\": #if( $context.args.filter ) -$util.transform.toDynamoDBFilterExpression($ctx.args.filter) + \\"filter\\": #if( $filter ) +$util.toJson($filter) #else null #end, @@ -8175,7 +8217,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createChild.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createChild.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createChild.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -8188,25 +8236,6 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { {}", "Mutation.createChild.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -8271,13 +8300,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Child\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createChild.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createChild.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createComment.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -8289,26 +8319,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createComment.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createComment.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -8373,13 +8390,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Comment\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createComment.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createComment.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createFriendship.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -8391,26 +8409,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createFriendship.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createFriendship.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createFriendship.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -8475,13 +8480,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Friendship\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createFriendship.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createFriendship.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createParent.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -8493,26 +8499,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createParent.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createParent.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createParent.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -8577,13 +8570,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Parent\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createParent.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createParent.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createPost.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -8595,7 +8589,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createPost.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createPost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createPost.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -8607,25 +8607,6 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { {}", "Mutation.createPost.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -8690,13 +8671,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Post\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createPost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createPost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createPostAuthor.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -8708,26 +8690,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createPostAuthor.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createPostAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createPostAuthor.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -8792,13 +8761,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"PostAuthor\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createPostAuthor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createPostAuthor.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createPostEditor.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -8810,26 +8780,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createPostEditor.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createPostEditor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createPostEditor.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -8894,13 +8851,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"PostEditor\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createPostEditor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createPostEditor.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createPostModel.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -8912,26 +8870,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createPostModel.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createPostModel.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createPostModel.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -8996,13 +8941,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"PostModel\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createPostModel.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createPostModel.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -9014,26 +8960,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTest.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -9098,13 +9031,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createTest1.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -9116,7 +9050,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createTest1.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createTest1.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createTest1.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -9136,25 +9076,6 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { $util.qr($ctx.args.input.put(\\"email#name\\",\\"\${mergedValues.email}#\${mergedValues.name}\\")) {}", "Mutation.createTest1.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -9219,13 +9140,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Test1\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createTest1.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createTest1.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createUser.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -9237,7 +9159,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createUser.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createUser.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -9257,25 +9185,6 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { $util.qr($ctx.args.input.put(\\"name#surname\\",\\"\${mergedValues.name}#\${mergedValues.surname}\\")) {}", "Mutation.createUser.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -9340,13 +9249,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"User\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createUser.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createUser.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createUserModel.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -9358,7 +9268,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createUserModel.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createUserModel.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createUserModel.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -9370,7 +9286,7 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { ## [End] Set the primary key. ** {}", - "Mutation.createUserModel.postAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.createUserModel.preAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -9398,25 +9314,6 @@ $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) #end {}", "Mutation.createUserModel.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) -#end -## End - key condition ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -9481,14 +9378,21 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"UserModel\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createUserModel.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createUserModel.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteChild.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteChild.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteChild.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -9556,13 +9460,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteChild.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteChild.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteComment.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -9620,13 +9531,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteComment.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteComment.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteFriendship.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteFriendship.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -9684,13 +9602,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteFriendship.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteFriendship.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteParent.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteParent.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -9748,14 +9673,21 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteParent.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteParent.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deletePost.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deletePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deletePost.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -9822,13 +9754,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deletePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deletePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deletePostAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deletePostAuthor.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -9886,13 +9825,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deletePostAuthor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deletePostAuthor.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deletePostEditor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deletePostEditor.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -9950,13 +9896,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deletePostEditor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deletePostEditor.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deletePostModel.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deletePostModel.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -10014,13 +9967,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deletePostModel.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deletePostModel.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteTest.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -10078,14 +10038,21 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteTest1.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteTest1.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteTest1.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -10153,14 +10120,21 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteTest1.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteTest1.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteUser.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteUser.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -10228,14 +10202,21 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteUser.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteUser.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Mutation.deleteUserModel.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** +## [End] ResponseTemplate. **", + "Mutation.deleteUserModel.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.deleteUserModel.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -10246,7 +10227,7 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { })) ## [End] Set the primary key. ** {}", - "Mutation.deleteUserModel.postAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.deleteUserModel.preAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -10316,13 +10297,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteUserModel.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteUserModel.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateChild.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -10332,7 +10314,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateChild.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateChild.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateChild.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -10473,13 +10461,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateChild.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateChild.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateComment.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -10489,6 +10478,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateComment.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -10618,13 +10613,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateComment.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateComment.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateFriendship.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -10634,6 +10630,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateFriendship.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateFriendship.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -10763,13 +10765,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateFriendship.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateFriendship.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateParent.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -10779,6 +10782,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateParent.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateParent.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -10908,13 +10917,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateParent.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateParent.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updatePost.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -10924,7 +10934,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updatePost.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updatePost.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -11064,13 +11080,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updatePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updatePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updatePostAuthor.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -11080,6 +11097,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updatePostAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updatePostAuthor.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -11209,13 +11232,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updatePostAuthor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updatePostAuthor.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updatePostEditor.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -11225,6 +11249,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updatePostEditor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updatePostEditor.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -11354,13 +11384,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updatePostEditor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updatePostEditor.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updatePostModel.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -11370,6 +11401,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updatePostModel.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updatePostModel.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -11499,13 +11536,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updatePostModel.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updatePostModel.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTest.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -11515,6 +11553,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateTest.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -11644,13 +11688,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTest.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateTest1.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -11660,7 +11705,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateTest1.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateTest1.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateTest1.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -11808,13 +11859,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateTest1.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateTest1.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateUser.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -11824,7 +11876,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateUser.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateUser.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -11972,13 +12030,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateUser.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateUser.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateUserModel.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -11988,7 +12047,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.updateUserModel.postAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateUserModel.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.updateUserModel.preAuth.1.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -12000,7 +12065,7 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { ## [End] Set the primary key. ** {}", - "Mutation.updateUserModel.postAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** + "Mutation.updateUserModel.preAuth.2.req.vtl": "## [Start] Merge default values and inputs. ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) $util.qr($mergedValues.putAll($util.defaultIfNull($ctx.args.input, {}))) ## [End] Merge default values and inputs. ** @@ -12156,45 +12221,81 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateUserModel.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateUserModel.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Parent.child.req.vtl": "#if( $util.isNull($ctx.source.childID) || $util.isNull($ctx.source.childName) ) #return #else -{ - \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\", - \\"key\\": { - \\"id\\": $util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.childID, \\"___xamznone____\\")), - \\"name\\": $util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.childName, \\"___xamznone____\\")) - } + #set( $GetRequest = { + \\"version\\": \\"2018-05-29\\", + \\"operation\\": \\"Query\\" +} ) + $util.qr($GetRequest.put(\\"query\\", { + \\"expression\\": \\"#partitionKey = :partitionValue AND #sortKeyName = :sortKeyName\\", + \\"expressionNames\\": { + \\"#partitionKey\\": \\"id\\", + \\"#sortKeyName\\": \\"name\\" + }, + \\"expressionValues\\": { + \\":partitionValue\\": $util.parseJson($util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.childID, \\"___xamznone____\\"))), + \\":sortKeyName\\": $util.parseJson($util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.childName, \\"___xamznone____\\"))) } +})) + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) + #end + $util.toJson($GetRequest) #end", "Parent.child.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else -$util.toJson($ctx.result) + #if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) + #else + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) + #end #end", "Post.author.req.vtl": "#if( $util.isNull($ctx.source.owner) ) #return #else -{ - \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\", - \\"key\\": { - \\"id\\": $util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.owner, \\"___xamznone____\\")) - } + #set( $GetRequest = { + \\"version\\": \\"2018-05-29\\", + \\"operation\\": \\"Query\\" +} ) + $util.qr($GetRequest.put(\\"query\\", { + \\"expression\\": \\"#partitionKey = :partitionValue\\", + \\"expressionNames\\": { + \\"#partitionKey\\": \\"id\\" + }, + \\"expressionValues\\": { + \\":partitionValue\\": $util.parseJson($util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.owner, \\"___xamznone____\\"))) } +})) + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) + #end + $util.toJson($GetRequest) #end", "Post.author.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else -$util.toJson($ctx.result) + #if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) + #else + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) + #end #end", "Post.authors.req.vtl": "#if( $util.isNull($ctx.source.authorID) ) #set( $result = { @@ -12273,6 +12374,27 @@ $util.toJson($ctx.result) ## [End] Applying Key Condition ** + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end + #else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end + #end + #if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $filter = $filterExpression ) + #end + #end { \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"Query\\", @@ -12286,8 +12408,8 @@ false #else true #end, - \\"filter\\": #if( $context.args.filter ) -$util.transform.toDynamoDBFilterExpression($ctx.args.filter) + \\"filter\\": #if( $filter ) +$util.toJson($filter) #else null #end, @@ -12323,6 +12445,27 @@ $util.error($ctx.error.message, $ctx.error.type) \\":partitionKey\\": $util.dynamodb.toDynamoDB($context.source.id) } } ) + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end + #else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end + #end + #if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $filter = $filterExpression ) + #end + #end { \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"Query\\", @@ -12336,8 +12479,8 @@ false #else true #end, - \\"filter\\": #if( $context.args.filter ) -$util.transform.toDynamoDBFilterExpression($ctx.args.filter) + \\"filter\\": #if( $filter ) +$util.toJson($filter) #else null #end, @@ -12412,6 +12555,27 @@ $util.error($ctx.error.message, $ctx.error.type) $util.qr($query.expressionValues.put(\\":sortKey\\", { \\"S\\": \\"$ctx.args.editorID.ge\\" })) #end ## [End] Applying Key Condition ** + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end + #else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end + #end + #if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $filter = $filterExpression ) + #end + #end { \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"Query\\", @@ -12425,8 +12589,8 @@ false #else true #end, - \\"filter\\": #if( $context.args.filter ) -$util.transform.toDynamoDBFilterExpression($ctx.args.filter) + \\"filter\\": #if( $filter ) +$util.toJson($filter) #else null #end, @@ -12450,50 +12614,101 @@ $util.error($ctx.error.message, $ctx.error.type) "PostAuthor.post.req.vtl": "#if( $util.isNull($ctx.source.postID) ) #return #else -{ - \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\", - \\"key\\": { - \\"id\\": $util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.postID, \\"___xamznone____\\")) - } + #set( $GetRequest = { + \\"version\\": \\"2018-05-29\\", + \\"operation\\": \\"Query\\" +} ) + $util.qr($GetRequest.put(\\"query\\", { + \\"expression\\": \\"#partitionKey = :partitionValue\\", + \\"expressionNames\\": { + \\"#partitionKey\\": \\"id\\" + }, + \\"expressionValues\\": { + \\":partitionValue\\": $util.parseJson($util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.postID, \\"___xamznone____\\"))) } +})) + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) + #end + $util.toJson($GetRequest) #end", "PostAuthor.post.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else -$util.toJson($ctx.result) + #if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) + #else + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) + #end #end", "PostEditor.editor.req.vtl": "#if( $util.isNull($ctx.source.editorID) ) #return #else -{ - \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\", - \\"key\\": { - \\"id\\": $util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.editorID, \\"___xamznone____\\")) - } + #set( $GetRequest = { + \\"version\\": \\"2018-05-29\\", + \\"operation\\": \\"Query\\" +} ) + $util.qr($GetRequest.put(\\"query\\", { + \\"expression\\": \\"#partitionKey = :partitionValue\\", + \\"expressionNames\\": { + \\"#partitionKey\\": \\"id\\" + }, + \\"expressionValues\\": { + \\":partitionValue\\": $util.parseJson($util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.editorID, \\"___xamznone____\\"))) } +})) + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) + #end + $util.toJson($GetRequest) #end", "PostEditor.editor.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else -$util.toJson($ctx.result) + #if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) + #else + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) + #end #end", "PostEditor.post.req.vtl": "#if( $util.isNull($ctx.source.postID) ) #return #else -{ - \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\", - \\"key\\": { - \\"id\\": $util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.postID, \\"___xamznone____\\")) - } + #set( $GetRequest = { + \\"version\\": \\"2018-05-29\\", + \\"operation\\": \\"Query\\" +} ) + $util.qr($GetRequest.put(\\"query\\", { + \\"expression\\": \\"#partitionKey = :partitionValue\\", + \\"expressionNames\\": { + \\"#partitionKey\\": \\"id\\" + }, + \\"expressionValues\\": { + \\":partitionValue\\": $util.parseJson($util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.postID, \\"___xamznone____\\"))) } +})) + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) + #end + $util.toJson($GetRequest) #end", "PostEditor.post.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else -$util.toJson($ctx.result) + #if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) + #else + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) + #end #end", "PostModel.authors.req.vtl": "#if( $util.isNull($ctx.source.authorID) ) #set( $result = { @@ -12513,6 +12728,27 @@ $util.toJson($ctx.result) \\":sortKey\\": $util.dynamodb.toDynamoDB(\\"\${context.source.authorName}#\${context.source.authorSurname}\\") } } ) + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end + #else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end + #end + #if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $filter = $filterExpression ) + #end + #end { \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"Query\\", @@ -12526,8 +12762,8 @@ false #else true #end, - \\"filter\\": #if( $context.args.filter ) -$util.transform.toDynamoDBFilterExpression($ctx.args.filter) + \\"filter\\": #if( $filter ) +$util.toJson($filter) #else null #end, @@ -12551,21 +12787,45 @@ $util.error($ctx.error.message, $ctx.error.type) "PostModel.singleAuthor.req.vtl": "#if( $util.isNull($ctx.source.authorID) || $util.isNull($ctx.source.authorName) || $util.isNull($ctx.source.authorSurname) ) #return #else -{ - \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\", - \\"key\\": { - \\"id\\": $util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.authorID, \\"___xamznone____\\")), - \\"name#surname\\": $util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank(\\"\${ctx.source.authorName}#\${ctx.source.authorSurname}\\", \\"___xamznone____\\")) - } + #set( $GetRequest = { + \\"version\\": \\"2018-05-29\\", + \\"operation\\": \\"Query\\" +} ) + $util.qr($GetRequest.put(\\"query\\", { + \\"expression\\": \\"#partitionKey = :partitionValue AND #sortKeyName = :sortKeyName\\", + \\"expressionNames\\": { + \\"#partitionKey\\": \\"id\\", + \\"#sortKeyName\\": \\"name#surname\\" + }, + \\"expressionValues\\": { + \\":partitionValue\\": $util.parseJson($util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.authorID, \\"___xamznone____\\"))), + \\":sortKeyName\\": $util.parseJson($util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank(\\"\${ctx.source.authorName}#\${ctx.source.authorSurname}\\", \\"___xamznone____\\"))) } +})) + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) + #end + $util.toJson($GetRequest) #end", "PostModel.singleAuthor.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else -$util.toJson($ctx.result) + #if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) + #else + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) + #end #end", - "Query.getChild.postAuth.1.req.vtl": "## [Start] Set the primary key. ** + "Query.getChild.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getChild.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id), \\"name\\": $util.dynamodb.toDynamoDB($ctx.args.name) @@ -12575,92 +12835,216 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getChild.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getChild.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getChild.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getComment.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getComment.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getComment.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getFriendship.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getFriendship.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getFriendship.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getFriendship.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getParent.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getParent.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getParent.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getParent.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", - "Query.getPost.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +## [End] Get Response template. **", + "Query.getPost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getPost.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"title\\": $util.dynamodb.toDynamoDB($ctx.args.title) })) @@ -12669,92 +13053,216 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getPost.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getPost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getPost.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.getPostAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getPostAuthor.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getPostAuthor.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getPostAuthor.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.getPostModel.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getPostModel.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getPostModel.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getPostModel.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.getTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getTest.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTest.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTest.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", - "Query.getTest1.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +## [End] Get Response template. **", + "Query.getTest1.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getTest1.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id), \\"email#name\\": $util.dynamodb.toDynamoDB(\\"\${ctx.args.email}#\${ctx.args.name}\\") @@ -12764,26 +13272,57 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getTest1.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getTest1.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getTest1.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", - "Query.getUser.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +## [End] Get Response template. **", + "Query.getUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getUser.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id), \\"name#surname\\": $util.dynamodb.toDynamoDB(\\"\${ctx.args.name}#\${ctx.args.surname}\\") @@ -12793,26 +13332,57 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getUser.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getUser.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getUser.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", - "Query.getUserModel.postAuth.1.req.vtl": "## [Start] Set the primary key. ** +## [End] Get Response template. **", + "Query.getUserModel.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.getUserModel.preAuth.1.req.vtl": "## [Start] Set the primary key. ** $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id), \\"rollNumber\\": $util.dynamodb.toDynamoDB($ctx.args.rollNumber) @@ -12822,26 +13392,57 @@ $util.qr($ctx.stash.metadata.put(\\"modelObjectKey\\", { "Query.getUserModel.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getUserModel.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getUserModel.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.listChildren.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", - "Query.listChildren.postAuth.1.req.vtl": "## [Start] Set query expression for key ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listChildren.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( $util.isNull($ctx.args.id) && !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"When providing argument 'sortDirection' you must also provide argument 'id'.\\", \\"InvalidArgumentsError\\") #end @@ -12912,8 +13513,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -12937,13 +13550,19 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listChildren.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listChildren.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listComments.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listComments.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -12953,8 +13572,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -12978,13 +13609,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listComments.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listComments.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listFriendships.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listFriendships.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -12994,8 +13631,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -13019,13 +13668,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listFriendships.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listFriendships.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listParents.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listParents.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -13035,8 +13690,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -13060,13 +13727,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listParents.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listParents.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listPostAuthors.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listPostAuthors.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -13076,8 +13749,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -13101,13 +13786,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listPostAuthors.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listPostAuthors.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listPostModels.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listPostModels.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -13117,8 +13808,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -13142,14 +13845,20 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listPostModels.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listPostModels.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Query.listPosts.postAuth.1.req.vtl": "## [Start] Set query expression for key ** +## [End] ResponseTemplate. **", + "Query.listPosts.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listPosts.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"sortDirection is not supported for List operations without a Sort key defined.\\", \\"InvalidArgumentsError\\") #end @@ -13177,8 +13886,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -13202,14 +13923,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listPosts.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listPosts.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Query.listTest1s.postAuth.1.req.vtl": "## [Start] Set query expression for key ** +## [End] ResponseTemplate. **", + "Query.listTest1s.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listTest1s.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( $util.isNull($ctx.args.id) && !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"When providing argument 'sortDirection' you must also provide argument 'id'.\\", \\"InvalidArgumentsError\\") #end @@ -13326,8 +14053,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -13351,13 +14090,19 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listTest1s.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listTest1s.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listTests.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listTests.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -13367,8 +14112,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -13392,14 +14149,20 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listTests.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listTests.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Query.listUserModels.postAuth.1.req.vtl": "## [Start] Set query expression for key ** +## [End] ResponseTemplate. **", + "Query.listUserModels.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listUserModels.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( $util.isNull($ctx.args.id) && !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"When providing argument 'sortDirection' you must also provide argument 'id'.\\", \\"InvalidArgumentsError\\") #end @@ -13470,8 +14233,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -13495,14 +14270,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listUserModels.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listUserModels.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", - "Query.listUsers.postAuth.1.req.vtl": "## [Start] Set query expression for key ** +## [End] ResponseTemplate. **", + "Query.listUsers.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Query.listUsers.preAuth.1.req.vtl": "## [Start] Set query expression for key ** #if( $util.isNull($ctx.args.id) && !$util.isNull($ctx.args.sortDirection) ) $util.error(\\"When providing argument 'sortDirection' you must also provide argument 'id'.\\", \\"InvalidArgumentsError\\") #end @@ -13619,8 +14400,20 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -13644,13 +14437,553 @@ $util.qr($ctx.stash.put(\\"modelQueryExpression\\", $modelQueryExpression)) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listUsers.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listUsers.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Subscription.onCreateChild.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateChild.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateChild.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateComment.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateComment.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateFriendship.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateFriendship.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateFriendship.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateParent.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateParent.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateParent.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreatePost.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreatePost.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreatePostAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreatePostAuthor.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreatePostAuthor.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreatePostEditor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreatePostEditor.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreatePostEditor.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreatePostModel.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreatePostModel.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreatePostModel.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateTest1.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateTest1.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateTest1.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateUser.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateUser.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateUserModel.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateUserModel.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateUserModel.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteChild.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteChild.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteChild.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteComment.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteComment.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteFriendship.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteFriendship.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteFriendship.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteParent.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteParent.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteParent.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeletePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeletePost.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeletePost.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeletePostAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeletePostAuthor.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeletePostAuthor.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeletePostEditor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeletePostEditor.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeletePostEditor.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeletePostModel.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeletePostModel.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeletePostModel.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteTest1.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteTest1.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteTest1.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteUser.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteUser.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteUserModel.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteUserModel.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteUserModel.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateChild.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateChild.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateChild.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateComment.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateComment.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateComment.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateFriendship.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateFriendship.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateFriendship.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateParent.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateParent.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateParent.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdatePost.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdatePost.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdatePostAuthor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdatePostAuthor.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdatePostAuthor.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdatePostEditor.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdatePostEditor.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdatePostEditor.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdatePostModel.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdatePostModel.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdatePostModel.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTest.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTest.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTest.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateTest1.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateTest1.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateTest1.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateUser.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateUser.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateUser.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateUserModel.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateUserModel.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateUserModel.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", "Test.otherParts.req.vtl": "#if( $util.isNull($ctx.source.id) ) #set( $result = { \\"items\\": [] @@ -13728,6 +15061,27 @@ $util.toJson($ListRequest) ## [End] Applying Key Condition ** + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end + #else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end + #end + #if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $filter = $filterExpression ) + #end + #end { \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"Query\\", @@ -13741,8 +15095,8 @@ false #else true #end, - \\"filter\\": #if( $context.args.filter ) -$util.transform.toDynamoDBFilterExpression($ctx.args.filter) + \\"filter\\": #if( $filter ) +$util.toJson($filter) #else null #end, @@ -13839,6 +15193,27 @@ $util.error($ctx.error.message, $ctx.error.type) ## [End] Applying Key Condition ** + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end + #else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end + #end + #if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $filter = $filterExpression ) + #end + #end { \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"Query\\", @@ -13852,8 +15227,8 @@ false #else true #end, - \\"filter\\": #if( $context.args.filter ) -$util.transform.toDynamoDBFilterExpression($ctx.args.filter) + \\"filter\\": #if( $filter ) +$util.toJson($filter) #else null #end, @@ -13928,6 +15303,27 @@ $util.error($ctx.error.message, $ctx.error.type) $util.qr($query.expressionValues.put(\\":sortKey\\", { \\"S\\": \\"$ctx.args.friendID.ge\\" })) #end ## [End] Applying Key Condition ** + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end + #else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end + #end + #if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $filter = $filterExpression ) + #end + #end { \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"Query\\", @@ -13941,8 +15337,8 @@ false #else true #end, - \\"filter\\": #if( $context.args.filter ) -$util.transform.toDynamoDBFilterExpression($ctx.args.filter) + \\"filter\\": #if( $filter ) +$util.toJson($filter) #else null #end, @@ -14017,6 +15413,27 @@ $util.error($ctx.error.message, $ctx.error.type) $util.qr($query.expressionValues.put(\\":sortKey\\", { \\"S\\": \\"$ctx.args.postID.ge\\" })) #end ## [End] Applying Key Condition ** + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end + #else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end + #end + #if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $filter = $filterExpression ) + #end + #end { \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"Query\\", @@ -14030,8 +15447,8 @@ false #else true #end, - \\"filter\\": #if( $context.args.filter ) -$util.transform.toDynamoDBFilterExpression($ctx.args.filter) + \\"filter\\": #if( $filter ) +$util.toJson($filter) #else null #end, @@ -14106,6 +15523,27 @@ $util.error($ctx.error.message, $ctx.error.type) $util.qr($query.expressionValues.put(\\":sortKey\\", { \\"S\\": \\"$ctx.args.postID.ge\\" })) #end ## [End] Applying Key Condition ** + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end + #else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end + #end + #if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $filter = $filterExpression ) + #end + #end { \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"Query\\", @@ -14119,8 +15557,8 @@ false #else true #end, - \\"filter\\": #if( $context.args.filter ) -$util.transform.toDynamoDBFilterExpression($ctx.args.filter) + \\"filter\\": #if( $filter ) +$util.toJson($filter) #else null #end, diff --git a/packages/amplify-graphql-relational-transformer/src/__tests__/__snapshots__/amplify-graphql-many-to-many-transformer.test.ts.snap b/packages/amplify-graphql-relational-transformer/src/__tests__/__snapshots__/amplify-graphql-many-to-many-transformer.test.ts.snap index 3e58971d8e4..e837c760e3c 100644 --- a/packages/amplify-graphql-relational-transformer/src/__tests__/__snapshots__/amplify-graphql-many-to-many-transformer.test.ts.snap +++ b/packages/amplify-graphql-relational-transformer/src/__tests__/__snapshots__/amplify-graphql-many-to-many-transformer.test.ts.snap @@ -317,6 +317,27 @@ Object { $util.qr($query.expressionValues.put(\\":sortKey\\", { \\"S\\": \\"$ctx.args.fooID.ge\\" })) #end ## [End] Applying Key Condition ** + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end + #else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end + #end + #if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $filter = $filterExpression ) + #end + #end { \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"Query\\", @@ -330,8 +351,8 @@ false #else true #end, - \\"filter\\": #if( $context.args.filter ) -$util.transform.toDynamoDBFilterExpression($ctx.args.filter) + \\"filter\\": #if( $filter ) +$util.toJson($filter) #else null #end, @@ -406,6 +427,27 @@ $util.error($ctx.error.message, $ctx.error.type) $util.qr($query.expressionValues.put(\\":sortKey\\", { \\"S\\": \\"$ctx.args.barID.ge\\" })) #end ## [End] Applying Key Condition ** + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end + #else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end + #end + #if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) + #if( !$util.isNullOrBlank($filterExpression.expression) ) + #if( $filterEpression.expressionValues.size() == 0 ) + $util.qr($filterEpression.remove(\\"expressionValues\\")) + #end + #set( $filter = $filterExpression ) + #end + #end { \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"Query\\", @@ -419,8 +461,8 @@ false #else true #end, - \\"filter\\": #if( $context.args.filter ) -$util.transform.toDynamoDBFilterExpression($ctx.args.filter) + \\"filter\\": #if( $filter ) +$util.toJson($filter) #else null #end, @@ -444,34 +486,68 @@ $util.error($ctx.error.message, $ctx.error.type) "FooBar.bar.req.vtl": "#if( $util.isNull($ctx.source.barID) ) #return #else -{ - \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\", - \\"key\\": { - \\"id\\": $util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.barID, \\"___xamznone____\\")) - } + #set( $GetRequest = { + \\"version\\": \\"2018-05-29\\", + \\"operation\\": \\"Query\\" +} ) + $util.qr($GetRequest.put(\\"query\\", { + \\"expression\\": \\"#partitionKey = :partitionValue\\", + \\"expressionNames\\": { + \\"#partitionKey\\": \\"id\\" + }, + \\"expressionValues\\": { + \\":partitionValue\\": $util.parseJson($util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.barID, \\"___xamznone____\\"))) } +})) + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) + #end + $util.toJson($GetRequest) #end", "FooBar.bar.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else -$util.toJson($ctx.result) + #if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) + #else + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) + #end #end", "FooBar.foo.req.vtl": "#if( $util.isNull($ctx.source.fooID) ) #return #else -{ - \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\", - \\"key\\": { - \\"id\\": $util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.fooID, \\"___xamznone____\\")) - } + #set( $GetRequest = { + \\"version\\": \\"2018-05-29\\", + \\"operation\\": \\"Query\\" +} ) + $util.qr($GetRequest.put(\\"query\\", { + \\"expression\\": \\"#partitionKey = :partitionValue\\", + \\"expressionNames\\": { + \\"#partitionKey\\": \\"id\\" + }, + \\"expressionValues\\": { + \\":partitionValue\\": $util.parseJson($util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.fooID, \\"___xamznone____\\"))) } +})) + #if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) + #end + $util.toJson($GetRequest) #end", "FooBar.foo.res.vtl": "#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else -$util.toJson($ctx.result) + #if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) + #else + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) + #end #end", "Mutation.createBar.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) @@ -484,26 +560,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createBar.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createBar.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createBar.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -568,13 +631,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Bar\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createBar.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createBar.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createFoo.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -586,26 +650,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createFoo.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createFoo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createFoo.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -670,13 +721,14 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Foo\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createFoo.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createFoo.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.createFooBar.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $createdAt = $util.time.nowISO8601() ) @@ -688,26 +740,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createFooBar.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createFooBar.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createFooBar.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -772,13 +811,20 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"FooBar\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createFooBar.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createFooBar.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteBar.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteBar.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -836,13 +882,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteBar.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteBar.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteFoo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteFoo.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -900,13 +953,20 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteFoo.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteFoo.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deleteFooBar.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deleteFooBar.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -964,13 +1024,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deleteFooBar.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deleteFooBar.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateBar.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -980,6 +1041,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateBar.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateBar.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -1109,13 +1176,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateBar.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateBar.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateFoo.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -1125,6 +1193,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateFoo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateFoo.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -1254,13 +1328,14 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateFoo.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateFoo.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updateFooBar.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -1270,6 +1345,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updateFooBar.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updateFooBar.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -1399,79 +1480,179 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updateFooBar.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updateFooBar.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.getBar.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getBar.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getBar.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getBar.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.getFoo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getFoo.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getFoo.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getFoo.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) #end -## [End] Get ResponseTemplate. **", +## [End] Get Response template. **", + "Query.getFooBar.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getFooBar.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getFooBar.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getFooBar.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.listBars.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listBars.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -1481,8 +1662,20 @@ $util.toJson($GetRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -1506,13 +1699,19 @@ $util.toJson($GetRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listBars.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listBars.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listFooBars.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listFooBars.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -1522,8 +1721,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -1547,13 +1758,19 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listFooBars.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listFooBars.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.listFoos.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listFoos.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -1563,8 +1780,20 @@ $util.toJson($ListRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -1588,12 +1817,147 @@ $util.toJson($ListRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listFoos.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listFoos.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Subscription.onCreateBar.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateBar.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateBar.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateFoo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateFoo.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateFoo.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onCreateFooBar.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreateFooBar.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreateFooBar.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteBar.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteBar.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteBar.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteFoo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteFoo.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteFoo.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeleteFooBar.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeleteFooBar.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeleteFooBar.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateBar.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateBar.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateBar.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateFoo.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateFoo.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateFoo.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdateFooBar.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdateFooBar.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdateFooBar.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", } `; diff --git a/packages/amplify-graphql-relational-transformer/src/resolvers.ts b/packages/amplify-graphql-relational-transformer/src/resolvers.ts index 97da8250ec7..3b03a2f818d 100644 --- a/packages/amplify-graphql-relational-transformer/src/resolvers.ts +++ b/packages/amplify-graphql-relational-transformer/src/resolvers.ts @@ -6,6 +6,7 @@ import { Table } from '@aws-cdk/aws-dynamodb'; import * as cdk from '@aws-cdk/core'; import { ObjectTypeDefinitionNode } from 'graphql'; import { + and, bool, compoundExpression, DynamoDBMappingTemplate, @@ -13,16 +14,22 @@ import { Expression, ifElse, iff, + int, + isNullOrEmpty, list, + methodCall, + not, nul, obj, ObjectNode, or, print, + qref, raw, ref, set, str, + toJson, } from 'graphql-mapping-template'; import { applyCompositeKeyConditionExpression, @@ -36,6 +43,8 @@ import { import { HasManyDirectiveConfiguration, HasOneDirectiveConfiguration } from './types'; import { getConnectionAttributeName } from './utils'; +const authFilter = ref('ctx.stash.authFilter'); + export function makeGetItemConnectionWithKeyResolver(config: HasOneDirectiveConfiguration, ctx: TransformerContextProvider) { const { connectionFields, field, fields, object, relatedType, relatedTypeIndex } = config; assert(relatedTypeIndex.length > 0); @@ -44,8 +53,14 @@ export function makeGetItemConnectionWithKeyResolver(config: HasOneDirectiveConf const { keySchema } = table as any; const dataSource = ctx.api.host.getDataSource(`${relatedType.name.value}Table`); const partitionKeyName = keySchema[0].attributeName; - const keyObj = { - [partitionKeyName]: ref(`util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.${localFields[0]}, "${NONE_VALUE}"))`), + let totalExpressions = [`#partitionKey = :partitionValue`]; + let totalExpressionNames: Record = { + [`#partitionKey`]: str(partitionKeyName), + }; + let totalExpressionValues: Record = { + [`:partitionValue`]: ref( + `util.parseJson($util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.${localFields[0]}, "${NONE_VALUE}")))`, + ), }; // Add a composite sort key or simple sort key if there is one. @@ -54,11 +69,18 @@ export function makeGetItemConnectionWithKeyResolver(config: HasOneDirectiveConf const sortKeyName = keySchema[1].attributeName; const condensedSortKeyValue = condenseRangeKey(rangeKeyFields.map(keyField => `\${ctx.source.${keyField}}`)); - keyObj[sortKeyName] = ref(`util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank("${condensedSortKeyValue}", "${NONE_VALUE}"))`); + totalExpressions.push(`#sortKeyName = :sortKeyName`); + totalExpressionNames['#sortKeyName'] = str(sortKeyName); + totalExpressionValues[':sortKeyName'] = ref( + `util.parseJson($util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank("${condensedSortKeyValue}", "${NONE_VALUE}")))`, + ); } else if (relatedTypeIndex.length === 2) { const sortKeyName = keySchema[1].attributeName; - - keyObj[sortKeyName] = ref(`util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.${localFields[1]}, "${NONE_VALUE}"))`); + totalExpressions.push(`#sortKeyName = :sortKeyName`); + totalExpressionNames['#sortKeyName'] = str(sortKeyName); + totalExpressionValues[':sortKeyName'] = ref( + `util.parseJson($util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.${localFields[1]}, "${NONE_VALUE}")))`, + ); } const resolver = ctx.resolvers.generateQueryResolver( @@ -71,16 +93,50 @@ export function makeGetItemConnectionWithKeyResolver(config: HasOneDirectiveConf or(localFields.map(f => raw(`$util.isNull($ctx.source.${f})`))), raw('#return'), compoundExpression([ - DynamoDBMappingTemplate.getItem({ - key: obj(keyObj), - }), + set(ref('GetRequest'), obj({ version: str('2018-05-29'), operation: str('Query') })), + qref( + methodCall( + ref('GetRequest.put'), + str('query'), + obj({ + expression: str(totalExpressions.join(' AND ')), + expressionNames: obj(totalExpressionNames), + expressionValues: obj(totalExpressionValues), + }), + ), + ), + iff( + not(isNullOrEmpty(authFilter)), + qref( + methodCall( + ref('GetRequest.put'), + str('filter'), + methodCall(ref('util.parseJson'), methodCall(ref('util.transform.toDynamoDBFilterExpression'), authFilter)), + ), + ), + ), + toJson(ref('GetRequest')), ]), ), ), `${object.name.value}.${field.name.value}.req.vtl`, ), MappingTemplate.s3MappingTemplateFromString( - print(DynamoDBMappingTemplate.dynamoDBResponse(false)), + print( + DynamoDBMappingTemplate.dynamoDBResponse( + false, + compoundExpression([ + ifElse( + and([not(ref('ctx.result.items.isEmpty()')), equals(ref('ctx.result.scannedCount'), int(1))]), + toJson(ref('ctx.result.items[0]')), + compoundExpression([ + iff(and([ref('ctx.result.items.isEmpty()'), equals(ref('ctx.result.scannedCount'), int(1))]), ref('util.unauthorized()')), + toJson(nul()), + ]), + ), + ]), + ), + ), `${object.name.value}.${field.name.value}.res.vtl`, ), ); @@ -115,6 +171,36 @@ export function makeQueryConnectionWithKeyResolver(config: HasManyDirectiveConfi setup.push(applyCompositeKeyConditionExpression(sortKeyFieldNames, 'query', toCamelCase(sortKeyFieldNames), sortKeyFieldName)); } } + // add setup filter to query + setup.push( + ifElse( + not(isNullOrEmpty(authFilter)), + compoundExpression([ + set(ref('filter'), authFilter), + iff(not(isNullOrEmpty(ref('ctx.args.filter'))), set(ref('filter'), obj({ and: list([ref('filter'), ref('ctx.args.filter')]) }))), + ]), + iff(not(isNullOrEmpty(ref('ctx.args.filter'))), set(ref('filter'), ref('ctx.args.filter'))), + ), + iff( + not(isNullOrEmpty(ref('filter'))), + compoundExpression([ + set( + ref(`filterExpression`), + methodCall(ref('util.parseJson'), methodCall(ref('util.transform.toDynamoDBFilterExpression'), ref('filter'))), + ), + iff( + not(methodCall(ref('util.isNullOrBlank'), ref('filterExpression.expression'))), + compoundExpression([ + iff( + equals(methodCall(ref('filterEpression.expressionValues.size')), int(0)), + qref(methodCall(ref('filterEpression.remove'), str('expressionValues'))), + ), + set(ref('filter'), ref('filterExpression')), + ]), + ), + ]), + ), + ); const queryArguments = { query: raw('$util.toJson($query)'), @@ -123,7 +209,7 @@ export function makeQueryConnectionWithKeyResolver(config: HasManyDirectiveConfi ifElse(equals(ref('context.args.sortDirection'), str('ASC')), bool(true), bool(false)), bool(true), ), - filter: ifElse(ref('context.args.filter'), ref('util.transform.toDynamoDBFilterExpression($ctx.args.filter)'), nul()), + filter: ifElse(ref('filter'), ref('util.toJson($filter)'), nul()), limit: ref('limit'), nextToken: ifElse(ref('context.args.nextToken'), ref('util.toJson($context.args.nextToken)'), nul()), } as any; diff --git a/packages/amplify-graphql-relational-transformer/src/schema.ts b/packages/amplify-graphql-relational-transformer/src/schema.ts index db278a06b0a..905af1548cd 100644 --- a/packages/amplify-graphql-relational-transformer/src/schema.ts +++ b/packages/amplify-graphql-relational-transformer/src/schema.ts @@ -65,7 +65,7 @@ function generateModelXConnectionType( let connectionTypeExtension = blankObjectExtension(tableXConnectionName); connectionTypeExtension = extensionWithFields(connectionTypeExtension, [ - makeField('items', [], makeListType(makeNamedType(tableXConnectionName))), + makeField('items', [], makeListType(makeNamedType(relatedType.name.value))), ]); connectionTypeExtension = extensionWithFields(connectionTypeExtension, [makeField('nextToken', [], makeNamedType('String'))]); diff --git a/packages/amplify-graphql-searchable-transformer/src/__tests__/__snapshots__/amplify-graphql-searchable-transformer.tests.ts.snap b/packages/amplify-graphql-searchable-transformer/src/__tests__/__snapshots__/amplify-graphql-searchable-transformer.tests.ts.snap index 4f2f780d9da..293b873f10d 100644 --- a/packages/amplify-graphql-searchable-transformer/src/__tests__/__snapshots__/amplify-graphql-searchable-transformer.tests.ts.snap +++ b/packages/amplify-graphql-searchable-transformer/src/__tests__/__snapshots__/amplify-graphql-searchable-transformer.tests.ts.snap @@ -604,26 +604,13 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", - "Mutation.createPost.req.vtl": "## [Start] Create Request template. ** -## Begin - key condition ** -#if( $ctx.stash.metadata.modelObjectKey ) - #set( $keyConditionExpr = {} ) - #set( $keyConditionExprNames = {} ) - #foreach( $entry in $ctx.stash.metadata.modelObjectKey.entrySet() ) - $util.qr($keyConditionExpr.put(\\"keyCondition$velocityCount\\", { - \\"attributeExists\\": false -})) - $util.qr($keyConditionExprNames.put(\\"#keyCondition$velocityCount\\", \\"$entry.key\\")) - #end - $util.qr($ctx.stash.conditions.add($keyConditionExpr)) -#else - $util.qr($ctx.stash.conditions.add({ - \\"id\\": { - \\"attributeExists\\": false - } -})) + "Mutation.createPost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## End - key condition ** +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Mutation.createPost.req.vtl": "## [Start] Create Request template. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) ## copy the values from input ** @@ -688,13 +675,20 @@ $util.qr($mergedValues.put(\\"__typename\\", \\"Post\\")) #end $util.toJson($PutObject) ## [End] Create Request template. **", - "Mutation.createPost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.createPost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Mutation.deletePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.deletePost.req.vtl": "## [Start] Delete Request template. ** #set( $DeleteRequest = { \\"version\\": \\"2018-05-29\\", @@ -752,13 +746,14 @@ $util.qr($DeleteRequest.put(\\"key\\", $Key)) #end $util.toJson($DeleteRequest) ## [End] Delete Request template. **", - "Mutation.deletePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.deletePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Mutation.updatePost.init.1.req.vtl": "## [Start] Initialization default values. ** $util.qr($ctx.stash.put(\\"defaultValues\\", $util.defaultIfNull($ctx.stash.defaultValues, {}))) #set( $updatedAt = $util.time.nowISO8601() ) @@ -768,6 +763,12 @@ $util.toJson({ \\"payload\\": {} }) ## [End] Initialization default values. **", + "Mutation.updatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Mutation.updatePost.req.vtl": "## [Start] Mutation Update resolver. ** ## Set the default values to put request ** #set( $mergedValues = $util.defaultIfNull($ctx.stash.defaultValues, {}) ) @@ -897,35 +898,73 @@ $util.qr($update.put(\\"expression\\", \\"$expression\\")) #end $util.toJson($UpdateItem) ## [End] Mutation Update resolver. **", - "Mutation.updatePost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Mutation.updatePost.res.vtl": "## [Start] ResponseTemplate. ** +$util.qr($ctx.result.put(\\"__operation\\", \\"Mutation\\")) #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", + "Query.getPost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.getPost.req.vtl": "## [Start] Get Request template. ** #set( $GetRequest = { \\"version\\": \\"2018-05-29\\", - \\"operation\\": \\"GetItem\\" + \\"operation\\": \\"Query\\" } ) #if( $ctx.stash.metadata.modelObjectKey ) - #set( $key = $ctx.stash.metadata.modelObjectKey ) + #set( $expression = \\"\\" ) + #set( $expressionNames = {} ) + #set( $expressionValues = {} ) + #foreach( $item in $ctx.stash.metadata.modelObjectKey.entrySet() ) + #set( $expression = \\"$expression#keyCount$velocityCount = :valueCount$velocityCount AND \\" ) + $util.qr($expressionNames.put(\\"#keyCount$velocityCount\\", $item.key)) + $util.qr($expressionValues.put(\\":valueCount$velocityCount\\", $item.value)) + #end + #set( $expression = $expression.replaceAll(\\"AND $\\", \\"\\") ) + #set( $query = { + \\"expression\\": $expression, + \\"expressionNames\\": $expressionNames, + \\"expressionValues\\": $expressionValues +} ) #else - #set( $key = { - \\"id\\": $util.dynamodb.toDynamoDB($ctx.args.id) + #set( $query = { + \\"expression\\": \\"id = :id\\", + \\"expressionValues\\": { + \\":id\\": $util.parseJson($util.dynamodb.toDynamoDBJson($ctx.args.id)) + } } ) #end -$util.qr($GetRequest.put(\\"key\\", $key)) +$util.qr($GetRequest.put(\\"query\\", $query)) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + $util.qr($GetRequest.put(\\"filter\\", $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.stash.authFilter)))) +#end $util.toJson($GetRequest) ## [End] Get Request template. **", - "Query.getPost.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.getPost.res.vtl": "## [Start] Get Response template. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) +#end +#if( !$ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) + $util.toJson($ctx.result.items[0]) #else - $util.toJson($ctx.result) + #if( $ctx.result.items.isEmpty() && $ctx.result.scannedCount == 1 ) +$util.unauthorized() + #end + $util.toJson(null) +#end +## [End] Get Response template. **", + "Query.listPosts.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() #end -## [End] Get ResponseTemplate. **", +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", "Query.listPosts.req.vtl": "## [Start] List Request. ** #set( $limit = $util.defaultIfNull($context.args.limit, 100) ) #set( $ListRequest = { @@ -935,8 +974,20 @@ $util.toJson($GetRequest) #if( $context.args.nextToken ) #set( $ListRequest.nextToken = $context.args.nextToken ) #end -#if( $context.args.filter ) - #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter)) ) +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = { + \\"and\\": [$filter, $ctx.args.filter] +} ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( !$util.isNullOrEmpty($filter) ) + #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) ) #if( !$util.isNullOrBlank($filterExpression.expression) ) #if( $filterEpression.expressionValues.size() == 0 ) $util.qr($filterEpression.remove(\\"expressionValues\\")) @@ -960,13 +1011,13 @@ $util.toJson($GetRequest) #end $util.toJson($ListRequest) ## [End] List Request. **", - "Query.listPosts.res.vtl": "## [Start] Get ResponseTemplate. ** + "Query.listPosts.res.vtl": "## [Start] ResponseTemplate. ** #if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result) #end -## [End] Get ResponseTemplate. **", +## [End] ResponseTemplate. **", "Query.searchPosts.req.vtl": "#set( $indexPath = \\"/post/doc/_search\\" ) #set( $nonKeywordFields = [] ) #set( $sortValues = [] ) @@ -1006,6 +1057,25 @@ $util.toJson($ListRequest) $util.qr($aggregateValues.put(\\"$aggItem.name\\", {\\"$aggItem.type\\": {\\"field\\": \\"\${aggItem.field}.keyword\\"}})) #end #end +#if( !$util.isNullOrEmpty($ctx.stash.authFilter) ) + #set( $filter = $ctx.stash.authFilter ) + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = [{ + \\"bool\\": { + \\"must\\": [$ctx.stash.authFilter, $util.transform.toElasticsearchQueryDSL($ctx.args.filter)] + } +}] ) + #end +#else + #if( !$util.isNullOrEmpty($ctx.args.filter) ) + #set( $filter = $ctx.args.filter ) + #end +#end +#if( $util.isNullOrEmpty($filter) ) + #set( $filter = { + \\"match_all\\": {} +} ) +#end { \\"version\\": \\"2018-05-29\\", \\"operation\\": \\"GET\\", @@ -1017,13 +1087,7 @@ $util.toJson($ListRequest) \\"size\\": #if( $context.args.limit ) $context.args.limit #else 100 #end, \\"sort\\": $sortValues, \\"version\\": false, - \\"query\\": #if( $context.args.filter ) -$util.transform.toElasticsearchQueryDSL($ctx.args.filter) -#else -{ - \\"match_all\\": {} - } -#end, + \\"query\\": $util.toJson($filter), \\"aggs\\": $util.toJson($aggregateValues) } } @@ -1059,6 +1123,51 @@ $util.toJson({ \\"nextToken\\": $nextToken, \\"aggregateItems\\": $aggregateValues })", + "Subscription.onCreatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onCreatePost.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onCreatePost.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onDeletePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onDeletePost.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onDeletePost.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", + "Subscription.onUpdatePost.postAuth.1.req.vtl": "## [Start] Sandbox Mode Disabled. ** +#if( !$ctx.stash.get(\\"hasAuth\\") ) + $util.unauthorized() +#end +$util.toJson({}) +## [End] Sandbox Mode Disabled. **", + "Subscription.onUpdatePost.req.vtl": "## [Start] Subscription Request template. ** +$util.toJson({ + \\"version\\": \\"2018-05-29\\", + \\"payload\\": {} +}) +## [End] Subscription Request template. **", + "Subscription.onUpdatePost.res.vtl": "## [Start] Subscription Response template. ** +$util.toJson(null) +## [End] Subscription Response template. **", } `; diff --git a/packages/amplify-graphql-searchable-transformer/src/generate-resolver-vtl.ts b/packages/amplify-graphql-searchable-transformer/src/generate-resolver-vtl.ts index ccef9dc1ca9..9c93786731f 100644 --- a/packages/amplify-graphql-searchable-transformer/src/generate-resolver-vtl.ts +++ b/packages/amplify-graphql-searchable-transformer/src/generate-resolver-vtl.ts @@ -17,9 +17,13 @@ import { Expression, bool, methodCall, + isNullOrEmpty, + not, } from 'graphql-mapping-template'; import { ResourceConstants } from 'graphql-transformer-common'; +const authFilter = ref('ctx.stash.authFilter'); + export function requestTemplate(primaryKey: string, nonKeywordFields: Expression[], includeVersion: boolean = false, type: string): string { return print( compoundExpression([ @@ -64,19 +68,32 @@ export function requestTemplate(primaryKey: string, nonKeywordFields: Expression qref('$aggregateValues.put("$aggItem.name", {"$aggItem.type": {"field": "${aggItem.field}.keyword"}})'), ), ]), + ifElse( + not(isNullOrEmpty(authFilter)), + compoundExpression([ + set(ref('filter'), authFilter), + iff( + not(isNullOrEmpty(ref('ctx.args.filter'))), + set( + ref('filter'), + list([ + obj({ + bool: obj({ must: list([ref('ctx.stash.authFilter'), ref('util.transform.toElasticsearchQueryDSL($ctx.args.filter)')]) }), + }), + ]), + ), + ), + ]), + iff(not(isNullOrEmpty(ref('ctx.args.filter'))), set(ref('filter'), ref('ctx.args.filter'))), + ), + iff(isNullOrEmpty(ref('filter')), set(ref('filter'), obj({ match_all: obj({}) }))), SearchableMappingTemplate.searchTemplate({ path: str('$indexPath'), size: ifElse(ref('context.args.limit'), ref('context.args.limit'), int(ResourceConstants.DEFAULT_SEARCHABLE_PAGE_LIMIT), true), search_after: ref('util.base64Decode($context.args.nextToken)'), from: ref('context.args.from'), version: bool(includeVersion), - query: ifElse( - ref('context.args.filter'), - ref('util.transform.toElasticsearchQueryDSL($ctx.args.filter)'), - obj({ - match_all: obj({}), - }), - ), + query: methodCall(ref('util.toJson'), ref('filter')), sort: ref('sortValues'), aggs: ref('util.toJson($aggregateValues)'), }), diff --git a/packages/amplify-graphql-searchable-transformer/src/graphql-searchable-transformer.ts b/packages/amplify-graphql-searchable-transformer/src/graphql-searchable-transformer.ts index a94a93ee74e..d1832a755d3 100644 --- a/packages/amplify-graphql-searchable-transformer/src/graphql-searchable-transformer.ts +++ b/packages/amplify-graphql-searchable-transformer/src/graphql-searchable-transformer.ts @@ -138,7 +138,7 @@ export class SearchableModelTransformer extends TransformerPluginBase { MappingTemplate.s3MappingTemplateFromString(responseTemplate(false), `${typeName}.${def.fieldName}.res.vtl`), ); resolver.mapToStack(stack); - context.resolvers.addResolver(type, def.fieldName, resolver); + context.resolvers.addResolver(typeName, def.fieldName, resolver); } createStackOutputs(stack, domain.domainEndpoint, context.api.apiId, domain.domainArn); diff --git a/packages/amplify-graphql-transformer-core/src/config/index.ts b/packages/amplify-graphql-transformer-core/src/config/index.ts index 7cfa3497922..58b0911cbdb 100644 --- a/packages/amplify-graphql-transformer-core/src/config/index.ts +++ b/packages/amplify-graphql-transformer-core/src/config/index.ts @@ -1,21 +1,2 @@ export { TransformerProjectConfig } from './project-config'; -export { - TransformConfig, - ConflictDetectionType, - ConflictHandlerType, - ResolverConfig, - SyncConfig, - SyncConfigLambda, - SyncConfigOptimistic, - SyncConfigServer, - LambdaConflictHandler, - AppSyncAuthConfiguration, - AppSyncAuthConfigurationAPIKeyEntry, - AppSyncAuthConfigurationEntry, - AppSyncAuthConfigurationIAMEntry, - ApiKeyConfig, - AppSyncAuthConfigurationOIDCEntry, - AppSyncAuthConfigurationUserPoolEntry, - AppSyncAuthMode, - UserPoolConfig, -} from './transformer-config'; +export * from './transformer-config'; diff --git a/packages/amplify-graphql-transformer-core/src/config/transformer-config.ts b/packages/amplify-graphql-transformer-core/src/config/transformer-config.ts index c98cfad4f3d..1b044d1a36e 100644 --- a/packages/amplify-graphql-transformer-core/src/config/transformer-config.ts +++ b/packages/amplify-graphql-transformer-core/src/config/transformer-config.ts @@ -4,56 +4,13 @@ export interface TransformMigrationConfig { }; } -// Auth Config -export type AppSyncAuthMode = 'API_KEY' | 'AMAZON_COGNITO_USER_POOLS' | 'AWS_IAM' | 'OPENID_CONNECT'; -export type AppSyncAuthConfiguration = { - defaultAuthentication: AppSyncAuthConfigurationEntry; - additionalAuthenticationProviders: Array; -}; - -export type AppSyncAuthConfigurationEntry = - | AppSyncAuthConfigurationUserPoolEntry - | AppSyncAuthConfigurationAPIKeyEntry - | AppSyncAuthConfigurationIAMEntry - | AppSyncAuthConfigurationOIDCEntry; -export type AppSyncAuthConfigurationAPIKeyEntry = { - authenticationType: 'API_KEY'; - apiKeyConfig: ApiKeyConfig; -}; -export type AppSyncAuthConfigurationUserPoolEntry = { - authenticationType: 'AMAZON_COGNITO_USER_POOLS'; - userPoolConfig: UserPoolConfig; -}; -export type AppSyncAuthConfigurationIAMEntry = { - authenticationType: 'AWS_IAM'; -}; - -export type AppSyncAuthConfigurationOIDCEntry = { - authenticationType: 'OPENID_CONNECT'; - openIDConnectConfig: OpenIDConnectConfig; -}; - -export type ApiKeyConfig = { - description?: string; - apiKeyExpirationDays: number; -}; -export type UserPoolConfig = { - userPoolId: string; -}; -export type OpenIDConnectConfig = { - name: string; - issuerUrl: string; - clientId?: string; - iatTTL?: number; - authTTL?: number; -}; - // Sync Config export const enum ConflictHandlerType { OPTIMISTIC = 'OPTIMISTIC_CONCURRENCY', AUTOMERGE = 'AUTOMERGE', LAMBDA = 'LAMBDA', } + export type ConflictDetectionType = 'VERSION' | 'NONE'; export type SyncConfigOptimistic = { ConflictDetection: ConflictDetectionType; @@ -79,10 +36,6 @@ export type ResolverConfig = { project?: SyncConfig; models?: Record; }; -/** - * The transform config is specified in transform.conf.json within an Amplify - * API project directory. - */ export interface TransformConfig { /** * The transform library uses a "StackMapping" to determine which stack @@ -95,7 +48,9 @@ export interface TransformConfig { * overrides to get specific behavior out of the transformer. Users may * override the default stack mapping to customize behavior. */ - StackMapping?: Record; + StackMapping?: { + [resourceId: string]: string; + }; /** * Provide build time options to GraphQL Transformer constructor functions. @@ -103,9 +58,10 @@ export interface TransformConfig { * need to be set at build time. E.G. DeletionPolicies cannot depend on parameters. */ TransformerOptions?: { - [transformer: string]: Record; + [transformer: string]: { + [option: string]: any; + }; }; - /** * Object which states info about a resolver's configuration * Such as sync configuration for appsync local support diff --git a/packages/amplify-graphql-transformer-core/src/graphql-api.ts b/packages/amplify-graphql-transformer-core/src/graphql-api.ts index 71d9fa52dc8..21bcaf042b1 100644 --- a/packages/amplify-graphql-transformer-core/src/graphql-api.ts +++ b/packages/amplify-graphql-transformer-core/src/graphql-api.ts @@ -113,6 +113,7 @@ export class IamResource implements APIIAMResourceProvider { export type TransformerAPIProps = GraphqlApiProps & { readonly createApiKey?: boolean; readonly host?: TransformHostProvider; + readonly sandboxModeEnabled?: boolean; }; export class GraphQLApi extends GraphqlApiBase implements GraphQLAPIProvider { /** @@ -125,7 +126,7 @@ export class GraphQLApi extends GraphqlApiBase implements GraphQLAPIProvider { * The TransformHost object provides resource creation utilities in AWS * such as a LambdaDataSource or a DynamoDBDataSource */ - public readonly host: TransformHostProvider + public readonly host: TransformHostProvider; /** * the ARN of the API @@ -161,6 +162,11 @@ export class GraphQLApi extends GraphqlApiBase implements GraphQLAPIProvider { */ public readonly apiKey?: string; + /** + * Global Sandbox Mode for GraphQL API + */ + public readonly sandboxModeEnabled?: boolean; + private schemaResource: CfnGraphQLSchema; private api: CfnGraphQLApi; private apiKeyResource?: CfnApiKey; @@ -198,7 +204,9 @@ export class GraphQLApi extends GraphqlApiBase implements GraphQLAPIProvider { this.schema = props.schema ?? new TransformerSchema(); this.schemaResource = this.schema.bind(this); - if (props.createApiKey && modes.some(mode => mode.authorizationType === AuthorizationType.API_KEY)) { + const hasApiKey = modes.some(mode => mode.authorizationType === AuthorizationType.API_KEY); + + if (props.createApiKey && hasApiKey) { const config = modes.find((mode: AuthorizationMode) => { return mode.authorizationType === AuthorizationType.API_KEY && mode.apiKeyConfig; })?.apiKeyConfig; @@ -207,13 +215,14 @@ export class GraphQLApi extends GraphqlApiBase implements GraphQLAPIProvider { this.apiKey = this.apiKeyResource.attrApiKey; } + if (hasApiKey && props.sandboxModeEnabled) this.sandboxModeEnabled = true; + if (props.host) { this.host = props.host; this.host.setAPI(this); - } - else { + } else { this.host = new DefaultTransformHost({ - api: this + api: this, }); } } diff --git a/packages/amplify-graphql-transformer-core/src/index.ts b/packages/amplify-graphql-transformer-core/src/index.ts index 6ddfd7b974a..3ab2126bd4f 100644 --- a/packages/amplify-graphql-transformer-core/src/index.ts +++ b/packages/amplify-graphql-transformer-core/src/index.ts @@ -8,25 +8,27 @@ export { ConflictHandlerType, ResolverConfig, SyncConfig, - SyncConfigLambda, SyncConfigOptimistic, SyncConfigServer, + SyncConfigLambda, TransformConfig, TransformerProjectConfig, - AppSyncAuthConfiguration, - AppSyncAuthConfigurationAPIKeyEntry, - AppSyncAuthConfigurationEntry, - AppSyncAuthConfigurationIAMEntry, - ApiKeyConfig, - AppSyncAuthConfigurationOIDCEntry, - AppSyncAuthConfigurationUserPoolEntry, - AppSyncAuthMode, - UserPoolConfig, - LambdaConflictHandler, } from './config/index'; -export { collectDirectives, collectDirectivesByTypeNames, DirectiveWrapper } from './utils'; +export { + collectDirectives, + collectDirectivesByTypeNames, + DirectiveWrapper, + IAM_AUTH_ROLE_PARAMETER, + IAM_UNAUTH_ROLE_PARAMETER, +} from './utils'; export * from './errors'; -export { TransformerModelBase, TransformerModelEnhancerBase, TransformerPluginBase } from './transformation/transformer-plugin-base'; +export { + TransformerModelBase, + TransformerModelEnhancerBase, + TransformerPluginBase, + TransformerAuthBase, +} from './transformation/transformer-plugin-base'; +export { TransformerResolver } from './transformer-context'; /** * Returns the extra set of directives that are supported by AppSync service */ diff --git a/packages/amplify-graphql-transformer-core/src/transform-host.ts b/packages/amplify-graphql-transformer-core/src/transform-host.ts index a72f94cf87d..5ede7441a0a 100644 --- a/packages/amplify-graphql-transformer-core/src/transform-host.ts +++ b/packages/amplify-graphql-transformer-core/src/transform-host.ts @@ -26,6 +26,7 @@ export interface DefaultTransformHostOptions { export class DefaultTransformHost implements TransformHostProvider { private dataSources: Map = new Map(); + private resolvers: Map = new Map(); private api: GraphQLApi; public constructor(options: DefaultTransformHostOptions) { @@ -45,6 +46,16 @@ export class DefaultTransformHost implements TransformHostProvider { } }; + public hasResolver = (typeName: string, fieldName: string) => { + return this.resolvers.has(`${typeName}:${fieldName}`); + }; + + public getResolver = (typeName: string, fieldName: string): CfnResolver | void => { + if (this.resolvers.has(`${typeName}:${fieldName}`)) { + return this.resolvers.get(`${typeName}:${fieldName}`); + } + }; + addSearchableDataSource( name: string, awsRegion: string, @@ -125,7 +136,7 @@ export class DefaultTransformHost implements TransformHostProvider { dataSourceName?: string, pipelineConfig?: string[], stack?: Stack, - ) { + ): CfnResolver { if (dataSourceName && !Token.isUnresolved(dataSourceName) && !this.dataSources.has(dataSourceName)) { throw new Error(`DataSource ${dataSourceName} is missing in the API`); } @@ -168,6 +179,7 @@ export class DefaultTransformHost implements TransformHostProvider { }, }); this.api.addSchemaDependency(resolver); + this.resolvers.set(`${typeName}:${fieldName}`, resolver); return resolver; } else { throw new Error('Resolver needs either dataSourceName or pipelineConfig to be passed'); diff --git a/packages/amplify-graphql-transformer-core/src/transformation/sync-utils.ts b/packages/amplify-graphql-transformer-core/src/transformation/sync-utils.ts index 7d207ffa4e2..a703a99e82b 100644 --- a/packages/amplify-graphql-transformer-core/src/transformation/sync-utils.ts +++ b/packages/amplify-graphql-transformer-core/src/transformation/sync-utils.ts @@ -90,7 +90,7 @@ export function syncDataSourceConfig(): DeltaSyncConfig { export function validateResolverConfigForType(ctx: TransformerSchemaVisitStepContextProvider, typeName: string): void { const resolverConfig = ctx.getResolverConfig(); const typeResolverConfig = resolverConfig?.models?.[typeName]; - if (!typeResolverConfig || !typeResolverConfig.ConflictDetection || !typeResolverConfig.ConflictHandler) { + if (typeResolverConfig && (!typeResolverConfig.ConflictDetection || !typeResolverConfig.ConflictHandler)) { console.warn(`Invalid resolverConfig for type ${typeName}. Using the project resolverConfig instead.`); } } diff --git a/packages/amplify-graphql-transformer-core/src/transformation/transform.ts b/packages/amplify-graphql-transformer-core/src/transformation/transform.ts index 2571efec502..0ec4d164fc1 100644 --- a/packages/amplify-graphql-transformer-core/src/transformation/transform.ts +++ b/packages/amplify-graphql-transformer-core/src/transformation/transform.ts @@ -4,6 +4,7 @@ import { GraphQLAPIProvider, TransformerPluginProvider, TransformHostProvider, + AppSyncAuthConfiguration, } from '@aws-amplify/graphql-transformer-interfaces'; import { AuthorizationMode, AuthorizationType } from '@aws-cdk/aws-appsync'; import { App, Aws, CfnOutput, Fn } from '@aws-cdk/core'; @@ -23,13 +24,13 @@ import { TypeExtensionNode, UnionTypeDefinitionNode, } from 'graphql'; -import { AppSyncAuthConfiguration, TransformConfig } from '../config/transformer-config'; import { InvalidTransformerError, SchemaValidationError, UnknownDirectiveError } from '../errors'; import { GraphQLApi } from '../graphql-api'; import { TransformerContext } from '../transformer-context'; import { TransformerOutput } from '../transformer-context/output'; import { StackManager } from '../transformer-context/stack-manager'; -import { adoptAuthModes } from '../utils/authType'; +import { adoptAuthModes, IAM_AUTH_ROLE_PARAMETER, IAM_UNAUTH_ROLE_PARAMETER } from '../utils/authType'; +import { TransformConfig } from '../config'; import * as SyncUtils from './sync-utils'; import Template, { DeploymentResources } from './types'; @@ -42,7 +43,7 @@ import { matchInputFieldDirective, sortTransformerPlugins, } from './utils'; -import { validateModelSchema } from './validation'; +import { validateModelSchema, validateAuthModes } from './validation'; // eslint-disable-next-line @typescript-eslint/ban-types function isFunction(obj: any): obj is Function { @@ -70,6 +71,7 @@ export interface GraphQLTransformOptions { readonly stacks?: Record; readonly featureFlags?: FeatureFlagProvider; readonly host?: TransformHostProvider; + readonly sandboxModeEnabled?: boolean; } export type StackMapping = { [resourceId: string]: string }; export class GraphQLTransform { @@ -103,6 +105,8 @@ export class GraphQLTransform { additionalAuthenticationProviders: [], }; + validateAuthModes(this.authConfig); + this.buildParameters = options.buildParameters || {}; this.stackMappingOverrides = options.stackMapping || {}; this.transformConfig = options.transformConfig || {}; @@ -124,6 +128,7 @@ export class GraphQLTransform { this.app, parsedDocument, this.stackMappingOverrides, + this.authConfig, this.options.featureFlags, this.transformConfig.ResolverConfig, ); @@ -136,6 +141,7 @@ export class GraphQLTransform { aws_iam: true, aws_oidc: true, aws_cognito_user_pools: true, + allow_public_data_access_with_api_key: true, deprecated: true, }, ); @@ -143,6 +149,7 @@ export class GraphQLTransform { for (const transformer of this.transformers) { allModelDefinitions = allModelDefinitions.concat(...transformer.typeDefinitions, transformer.directive); } + const errors = validateModelSchema({ kind: Kind.DOCUMENT, definitions: allModelDefinitions, @@ -214,7 +221,6 @@ export class GraphQLTransform { // Synth the API and make it available to allow transformer plugins to manipulate the API const stackManager = context.stackManager as StackManager; const output: TransformerOutput = context.output as TransformerOutput; - const api = this.generateGraphQlApi(stackManager, output); // generate resolvers @@ -258,6 +264,7 @@ export class GraphQLTransform { name: `${apiName}-${envName.valueAsString}`, authorizationConfig, host: this.options.host, + sandboxModeEnabled: this.options.sandboxModeEnabled, }); const authModes = [authorizationConfig.defaultAuthorization, ...(authorizationConfig.additionalAuthorizationModes || [])].map( mode => mode?.authorizationType, @@ -286,6 +293,11 @@ export class GraphQLTransform { }); } + if (authModes.includes(AuthorizationType.IAM)) { + stackManager.addParameter(IAM_AUTH_ROLE_PARAMETER, { type: 'String' }); + stackManager.addParameter(IAM_UNAUTH_ROLE_PARAMETER, { type: 'String' }); + } + new CfnOutput(rootStack, 'GraphQLAPIIdOutput', { value: api.apiId, description: 'Your GraphQL API ID.', diff --git a/packages/amplify-graphql-transformer-core/src/transformation/transformer-plugin-base.ts b/packages/amplify-graphql-transformer-core/src/transformation/transformer-plugin-base.ts index f0f9c86d910..9dad23a4873 100644 --- a/packages/amplify-graphql-transformer-core/src/transformation/transformer-plugin-base.ts +++ b/packages/amplify-graphql-transformer-core/src/transformation/transformer-plugin-base.ts @@ -10,6 +10,7 @@ import { DataSourceInstance, TransformerPluginProvider, TransformerModelEnhancementProvider, + TransformerAuthProvider, } from '@aws-amplify/graphql-transformer-interfaces'; import { @@ -176,3 +177,9 @@ export abstract class TransformerModelEnhancerBase extends TransformerModelBase super(name, doc, type); } } + +export abstract class TransformerAuthBase extends TransformerPluginBase implements TransformerAuthProvider { + constructor(name: string, doc: DocumentNode | string, type: TransformerPluginType = TransformerPluginType.AUTH) { + super(name, doc, type); + } +} diff --git a/packages/amplify-graphql-transformer-core/src/transformation/utils.ts b/packages/amplify-graphql-transformer-core/src/transformation/utils.ts index e7cb2863963..24523f2256c 100644 --- a/packages/amplify-graphql-transformer-core/src/transformation/utils.ts +++ b/packages/amplify-graphql-transformer-core/src/transformation/utils.ts @@ -171,6 +171,7 @@ export function sortTransformerPlugins(plugins: TransformerPluginProvider[]): Tr TransformerPluginType.DATA_SOURCE_PROVIDER, TransformerPluginType.DATA_SOURCE_ENHANCER, TransformerPluginType.GENERIC, + TransformerPluginType.AUTH, ]; return plugins.sort((a, b) => { const aIdx = SORT_ORDER.indexOf(a.pluginType); diff --git a/packages/amplify-graphql-transformer-core/src/transformation/validation.ts b/packages/amplify-graphql-transformer-core/src/transformation/validation.ts index 4e94fd7b6e4..a74afcd62bc 100644 --- a/packages/amplify-graphql-transformer-core/src/transformation/validation.ts +++ b/packages/amplify-graphql-transformer-core/src/transformation/validation.ts @@ -54,6 +54,9 @@ import { NoUndefinedVariables } from 'graphql/validation/rules/NoUndefinedVariab import { NoUnusedVariables } from 'graphql/validation/rules/NoUnusedVariables'; import { UniqueDirectivesPerLocation } from 'graphql/validation/rules/UniqueDirectivesPerLocation'; +// AuthMode Types +import { AppSyncAuthConfiguration, AppSyncAuthMode } from '@aws-amplify/graphql-transformer-interfaces'; + /** * This set includes all validation rules defined by the GraphQL spec. * @@ -109,6 +112,7 @@ directive @aws_api_key on FIELD_DEFINITION | OBJECT directive @aws_iam on FIELD_DEFINITION | OBJECT directive @aws_oidc on FIELD_DEFINITION | OBJECT directive @aws_cognito_user_pools(cognito_groups: [String!]) on FIELD_DEFINITION | OBJECT +directive @allow_public_data_access_with_api_key(in: [String!]) on OBJECT # Allows transformer libraries to deprecate directive arguments. directive @deprecated(reason: String) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION | ENUM | ENUM_VALUE @@ -142,3 +146,21 @@ export const validateModelSchema = (doc: DocumentNode) => { const schema = buildASTSchema(fullDocument); return validate(schema, fullDocument, specifiedRules); }; + +export const validateAuthModes = (authConfig: AppSyncAuthConfiguration) => { + let additionalAuthModes: AppSyncAuthMode[] = []; + + if (authConfig.additionalAuthenticationProviders) { + additionalAuthModes = authConfig.additionalAuthenticationProviders.map(p => p.authenticationType).filter(t => !!t); + } + + const authModes: AppSyncAuthMode[] = [...additionalAuthModes, authConfig.defaultAuthentication.authenticationType]; + + for (let i = 0; i < authModes.length; i++) { + const mode = authModes[i]; + + if (mode !== 'API_KEY' && mode !== 'AMAZON_COGNITO_USER_POOLS' && mode !== 'AWS_IAM' && mode !== 'OPENID_CONNECT') { + throw new Error(`Invalid auth mode ${mode}`); + } + } +}; diff --git a/packages/amplify-graphql-transformer-core/src/transformer-context/datasource.ts b/packages/amplify-graphql-transformer-core/src/transformer-context/datasource.ts index ded8e6cd888..544438499a3 100644 --- a/packages/amplify-graphql-transformer-core/src/transformer-context/datasource.ts +++ b/packages/amplify-graphql-transformer-core/src/transformer-context/datasource.ts @@ -23,4 +23,8 @@ export class TransformerDataSourceManager implements TransformerDataSourceManage collectDataSources = (): Readonly> => { return this.dataSourceMap; }; + + has = (name: string): boolean => { + return this.dataSourceMap.has(name); + }; } diff --git a/packages/amplify-graphql-transformer-core/src/transformer-context/index.ts b/packages/amplify-graphql-transformer-core/src/transformer-context/index.ts index 59f32bab104..266dc3a4f79 100644 --- a/packages/amplify-graphql-transformer-core/src/transformer-context/index.ts +++ b/packages/amplify-graphql-transformer-core/src/transformer-context/index.ts @@ -5,7 +5,9 @@ import { TransformerContextOutputProvider, TransformerContextProvider, TransformerDataSourceManagerProvider, + AppSyncAuthConfiguration, } from '@aws-amplify/graphql-transformer-interfaces'; +import { TransformerContextMetadataProvider } from '@aws-amplify/graphql-transformer-interfaces/src/transformer-context/transformer-context-provider'; import { App } from '@aws-cdk/core'; import { DocumentNode } from 'graphql'; import { ResolverConfig } from '../config/transformer-config'; @@ -17,6 +19,25 @@ import { TransformerContextProviderRegistry } from './provider-registry'; import { ResolverManager } from './resolver'; import { TransformerResourceHelper } from './resource-helper'; import { StackManager } from './stack-manager'; +export { TransformerResolver } from './resolver'; +export class TransformerContextMetadata implements TransformerContextMetadataProvider { + /** + * Used by transformers to pass information between one another. + */ + private metadata: { [key: string]: any } = new Map(); + + public get(key: string): T | undefined { + return this.metadata[key] as T; + } + + public set(key: string, val: T): void { + this.metadata[key] = val; + } + + public has(key: string) { + return this.metadata[key] !== undefined; + } +} export class TransformerContext implements TransformerContextProvider { public readonly output: TransformerContextOutputProvider; @@ -27,12 +48,15 @@ export class TransformerContext implements TransformerContextProvider { public readonly resourceHelper: TransformerResourceHelper; public readonly featureFlags: FeatureFlagProvider; public _api?: GraphQLAPIProvider; + public readonly authConfig: AppSyncAuthConfiguration; private resolverConfig: ResolverConfig | undefined; + public metadata: TransformerContextMetadata; constructor( app: App, public readonly inputDocument: DocumentNode, stackMapping: Record, + authConfig: AppSyncAuthConfiguration, featureFlags?: FeatureFlagProvider, resolverConfig?: ResolverConfig, ) { @@ -42,9 +66,11 @@ export class TransformerContext implements TransformerContextProvider { this.providerRegistry = new TransformerContextProviderRegistry(); const stackManager = new StackManager(app, stackMapping); this.stackManager = stackManager; + this.authConfig = authConfig; this.resourceHelper = new TransformerResourceHelper(stackManager); this.featureFlags = featureFlags ?? new NoopFeatureFlagProvider(); this.resolverConfig = resolverConfig; + this.metadata = new TransformerContextMetadata(); } /** diff --git a/packages/amplify-graphql-transformer-core/src/transformer-context/resolver.ts b/packages/amplify-graphql-transformer-core/src/transformer-context/resolver.ts index ec0dc0059ba..00e8128bd0a 100644 --- a/packages/amplify-graphql-transformer-core/src/transformer-context/resolver.ts +++ b/packages/amplify-graphql-transformer-core/src/transformer-context/resolver.ts @@ -7,13 +7,14 @@ import { TransformerResolverProvider, TransformerResolversManagerProvider, } from '@aws-amplify/graphql-transformer-interfaces'; -import { CfnFunctionConfiguration } from '@aws-cdk/aws-appsync'; -import { isResolvableObject, Stack } from '@aws-cdk/core'; +import { AuthorizationType, CfnFunctionConfiguration } from '@aws-cdk/aws-appsync'; +import { isResolvableObject, Stack, CfnParameter } from '@aws-cdk/core'; import assert from 'assert'; import { toPascalCase } from 'graphql-transformer-common'; import { dedent } from 'ts-dedent'; import { MappingTemplate, S3MappingTemplate } from '../cdk-compat'; import * as SyncUtils from '../transformation/sync-utils'; +import { IAM_AUTH_ROLE_PARAMETER, IAM_UNAUTH_ROLE_PARAMETER } from '../utils'; import { StackManager } from './stack-manager'; type Slot = { @@ -95,6 +96,11 @@ export class ResolverManager implements TransformerResolversManagerProvider { } }; + hasResolver = (typeName: string, fieldName: string): boolean => { + const key = `${typeName}.${fieldName}`; + return this.resolvers.has(key); + }; + removeResolver = (typeName: string, fieldName: string): TransformerResolverProvider => { const key = `${typeName}.${fieldName}`; if (this.resolvers.has(key)) { @@ -234,24 +240,38 @@ export class TransformerResolver implements TransformerResolverProvider { } break; default: - throw new Error('Unknow DataSource type'); + throw new Error('Unknown DataSource type'); } } + let initResolver = dedent` + $util.qr($ctx.stash.put("typeName", "${this.typeName}")) + $util.qr($ctx.stash.put("fieldName", "${this.fieldName}")) + $util.qr($ctx.stash.put("conditions", [])) + $util.qr($ctx.stash.put("metadata", {})) + $util.qr($ctx.stash.metadata.put("dataSourceType", "${dataSourceType}")) + $util.qr($ctx.stash.metadata.put("apiId", "${api.apiId}")) + ${dataSource} + `; + const authModes = [context.authConfig.defaultAuthentication, ...(context.authConfig.additionalAuthenticationProviders || [])].map( + mode => mode?.authenticationType, + ); + if (authModes.includes(AuthorizationType.IAM)) { + const authRoleParameter = (context.stackManager.getParameter(IAM_AUTH_ROLE_PARAMETER) as CfnParameter).valueAsString; + const unauthRoleParameter = (context.stackManager.getParameter(IAM_UNAUTH_ROLE_PARAMETER) as CfnParameter).valueAsString; + initResolver += dedent`\n + $util.qr($ctx.stash.put("authRole", "arn:aws:sts::${ + Stack.of(context.stackManager.rootStack).account + }:assumed-role/${authRoleParameter}/CognitoIdentityCredentials")) + $util.qr($ctx.stash.put("unauthRole", "arn:aws:sts::${ + Stack.of(context.stackManager.rootStack).account + }:assumed-role/${unauthRoleParameter}/CognitoIdentityCredentials")) + `; + } + initResolver += '\n$util.toJson({})'; api.host.addResolver( this.typeName, this.fieldName, - MappingTemplate.inlineTemplateFromString( - dedent` - $util.qr($ctx.stash.put("typeName", "${this.typeName}")) - $util.qr($ctx.stash.put("fieldName", "${this.fieldName}")) - $util.qr($ctx.stash.put("conditions", [])) - $util.qr($ctx.stash.put("metadata", {})) - $util.qr($ctx.stash.metadata.put("dataSourceType", "${dataSourceType}")) - $util.qr($ctx.stash.metadata.put("apiId", "${api.apiId}")) - ${dataSource} - $util.toJson({}) - `, - ), + MappingTemplate.inlineTemplateFromString(initResolver), MappingTemplate.inlineTemplateFromString('$util.toJson($ctx.prev.result)'), undefined, [...requestFns, dataSourceProviderFn, ...responseFns].map(fn => fn.functionId), diff --git a/packages/amplify-graphql-transformer-core/src/transformer-context/stack-manager.ts b/packages/amplify-graphql-transformer-core/src/transformer-context/stack-manager.ts index 003f41ec957..40faf98fe1c 100644 --- a/packages/amplify-graphql-transformer-core/src/transformer-context/stack-manager.ts +++ b/packages/amplify-graphql-transformer-core/src/transformer-context/stack-manager.ts @@ -23,6 +23,7 @@ export class StackManager implements StackManagerProvider { } createStack = (stackName: string): Stack => { const newStack = new TransformerNestedStack(this.rootStack, stackName); + this.stacks.set(stackName, newStack); return newStack; }; diff --git a/packages/amplify-graphql-transformer-core/src/utils/authType.ts b/packages/amplify-graphql-transformer-core/src/utils/authType.ts index 2be8d32a082..945da6dd5db 100644 --- a/packages/amplify-graphql-transformer-core/src/utils/authType.ts +++ b/packages/amplify-graphql-transformer-core/src/utils/authType.ts @@ -1,8 +1,8 @@ import { AuthorizationConfig, AuthorizationMode, AuthorizationType } from '@aws-cdk/aws-appsync'; import { UserPool } from '@aws-cdk/aws-cognito'; import { Duration, Expiration } from '@aws-cdk/core'; -import { AppSyncAuthConfiguration, AppSyncAuthConfigurationEntry, AppSyncAuthMode } from '../config'; import { StackManager } from '../transformer-context/stack-manager'; +import { AppSyncAuthConfiguration, AppSyncAuthConfigurationEntry, AppSyncAuthMode } from '@aws-amplify/graphql-transformer-interfaces'; const authTypeMap: Record = { API_KEY: AuthorizationType.API_KEY, @@ -10,6 +10,10 @@ const authTypeMap: Record = { AWS_IAM: AuthorizationType.IAM, OPENID_CONNECT: AuthorizationType.OIDC, }; + +export const IAM_AUTH_ROLE_PARAMETER = 'authRoleName'; +export const IAM_UNAUTH_ROLE_PARAMETER = 'unauthRoleName'; + export function adoptAuthModes(stack: StackManager, authConfig: AppSyncAuthConfiguration): AuthorizationConfig { return { defaultAuthorization: adoptAuthMode(stack, authConfig.defaultAuthentication), @@ -24,8 +28,10 @@ export function adoptAuthMode(stackManager: StackManager, entry: AppSyncAuthConf return { authorizationType: authType, apiKeyConfig: { - description: entry.apiKeyConfig.description, - expires: Expiration.after(Duration.days(entry.apiKeyConfig.apiKeyExpirationDays)), + description: entry.apiKeyConfig?.description, + expires: entry.apiKeyConfig?.apiKeyExpirationDays + ? Expiration.after(Duration.days(entry.apiKeyConfig.apiKeyExpirationDays)) + : undefined, }, }; case AuthorizationType.USER_POOL: diff --git a/packages/amplify-graphql-transformer-core/src/utils/index.ts b/packages/amplify-graphql-transformer-core/src/utils/index.ts index ab2e7da49c9..7389a33dfb1 100644 --- a/packages/amplify-graphql-transformer-core/src/utils/index.ts +++ b/packages/amplify-graphql-transformer-core/src/utils/index.ts @@ -2,3 +2,4 @@ export { DirectiveWrapper } from './directive-wrapper'; export { collectDirectives, collectDirectivesByTypeNames } from './type-map-utils'; export { stripDirectives } from './strip-directives'; export { DEFAULT_SCHEMA_DEFINITION } from './defaultSchema'; +export { IAM_AUTH_ROLE_PARAMETER, IAM_UNAUTH_ROLE_PARAMETER } from './authType'; diff --git a/packages/amplify-graphql-transformer-interfaces/src/graphql-api-provider.ts b/packages/amplify-graphql-transformer-interfaces/src/graphql-api-provider.ts index 4e7ce993724..6514c3e48a0 100644 --- a/packages/amplify-graphql-transformer-interfaces/src/graphql-api-provider.ts +++ b/packages/amplify-graphql-transformer-interfaces/src/graphql-api-provider.ts @@ -1,6 +1,51 @@ import { CfnResource, Construct, IAsset, IConstruct } from '@aws-cdk/core'; import { Grant, IGrantable, IRole } from '@aws-cdk/aws-iam'; -import {TransformHostProvider} from './transform-host-provider'; +import { TransformHostProvider } from './transform-host-provider'; + +// Auth Config +export type AppSyncAuthMode = 'API_KEY' | 'AMAZON_COGNITO_USER_POOLS' | 'AWS_IAM' | 'OPENID_CONNECT'; +export type AppSyncAuthConfiguration = { + defaultAuthentication: AppSyncAuthConfigurationEntry; + additionalAuthenticationProviders: Array; +}; + +export type AppSyncAuthConfigurationEntry = + | AppSyncAuthConfigurationUserPoolEntry + | AppSyncAuthConfigurationAPIKeyEntry + | AppSyncAuthConfigurationIAMEntry + | AppSyncAuthConfigurationOIDCEntry; +export type AppSyncAuthConfigurationAPIKeyEntry = { + authenticationType: 'API_KEY'; + apiKeyConfig?: ApiKeyConfig; +}; +export type AppSyncAuthConfigurationUserPoolEntry = { + authenticationType: 'AMAZON_COGNITO_USER_POOLS'; + userPoolConfig?: UserPoolConfig; +}; +export type AppSyncAuthConfigurationIAMEntry = { + authenticationType: 'AWS_IAM'; +}; + +export type AppSyncAuthConfigurationOIDCEntry = { + authenticationType: 'OPENID_CONNECT'; + openIDConnectConfig?: OpenIDConnectConfig; +}; + +export interface ApiKeyConfig { + description?: string; + apiKeyExpirationDays: number; + apiKeyExpirationDate?: Date; +} +export interface UserPoolConfig { + userPoolId: string; +} +export interface OpenIDConnectConfig { + name: string; + issuerUrl: string; + clientId?: string; + iatTTL?: number; + authTTL?: number; +} export interface AppSyncFunctionConfigurationProvider extends IConstruct { readonly arn: string; diff --git a/packages/amplify-graphql-transformer-interfaces/src/index.ts b/packages/amplify-graphql-transformer-interfaces/src/index.ts index 5271dfc2c34..36be2b3a84a 100644 --- a/packages/amplify-graphql-transformer-interfaces/src/index.ts +++ b/packages/amplify-graphql-transformer-interfaces/src/index.ts @@ -21,8 +21,9 @@ export { MutationFieldType, QueryFieldType, SubscriptionFieldType, - TransformerModelEnhancementProvider, TransformerModelProvider, + TransformerModelEnhancementProvider, + TransformerAuthProvider, } from './transformer-model-provider'; export { FeatureFlagProvider } from './feature-flag-provider'; @@ -36,6 +37,15 @@ export { InlineMappingTemplateProvider, APIIAMResourceProvider, TemplateType as MappingTemplateType, + AppSyncAuthConfiguration, + AppSyncAuthConfigurationAPIKeyEntry, + AppSyncAuthConfigurationEntry, + AppSyncAuthConfigurationIAMEntry, + ApiKeyConfig, + AppSyncAuthConfigurationOIDCEntry, + AppSyncAuthConfigurationUserPoolEntry, + AppSyncAuthMode, + UserPoolConfig, } from './graphql-api-provider'; export { TransformHostProvider, DynamoDbDataSourceOptions } from './transform-host-provider'; diff --git a/packages/amplify-graphql-transformer-interfaces/src/transform-host-provider.ts b/packages/amplify-graphql-transformer-interfaces/src/transform-host-provider.ts index 6ef36c63475..de89ebcea1b 100644 --- a/packages/amplify-graphql-transformer-interfaces/src/transform-host-provider.ts +++ b/packages/amplify-graphql-transformer-interfaces/src/transform-host-provider.ts @@ -73,4 +73,7 @@ export interface TransformHostProvider { getDataSource: (name: string) => BaseDataSource | void; hasDataSource: (name: string) => boolean; + + getResolver: (typeName: string, fieldName: string) => CfnResolver | void; + hasResolver: (typeName: string, fieldName: string) => boolean; } diff --git a/packages/amplify-graphql-transformer-interfaces/src/transformer-context/stack-manager-provider.ts b/packages/amplify-graphql-transformer-interfaces/src/transformer-context/stack-manager-provider.ts index b528c7eeec1..70d1e23842b 100644 --- a/packages/amplify-graphql-transformer-interfaces/src/transformer-context/stack-manager-provider.ts +++ b/packages/amplify-graphql-transformer-interfaces/src/transformer-context/stack-manager-provider.ts @@ -1,6 +1,7 @@ import { CfnParameter, CfnParameterProps, Stack } from '@aws-cdk/core'; export interface StackManagerProvider { + readonly rootStack: Stack; getStack: (stackName: string) => Stack; createStack: (stackName: string) => Stack; hasStack: (stackName: string) => boolean; diff --git a/packages/amplify-graphql-transformer-interfaces/src/transformer-context/transformer-context-provider.ts b/packages/amplify-graphql-transformer-interfaces/src/transformer-context/transformer-context-provider.ts index afaa8317841..1d3c41c133e 100644 --- a/packages/amplify-graphql-transformer-interfaces/src/transformer-context/transformer-context-provider.ts +++ b/packages/amplify-graphql-transformer-interfaces/src/transformer-context/transformer-context-provider.ts @@ -4,11 +4,18 @@ import { TransformerProviderRegistry } from './transformer-provider-registry'; import { DocumentNode } from 'graphql'; import { TransformerContextOutputProvider } from './transformer-context-output-provider'; import { StackManagerProvider } from './stack-manager-provider'; -import { GraphQLAPIProvider } from '../graphql-api-provider'; +import { AppSyncAuthConfiguration, GraphQLAPIProvider } from '../graphql-api-provider'; import { TransformerResourceProvider } from './resource-resource-provider'; import { FeatureFlagProvider } from '../feature-flag-provider'; +export interface TransformerContextMetadataProvider { + set(key: string, value: T): void; + get(key: string): T | undefined; + has(key: string): boolean; +} + export interface TransformerContextProvider { + metadata: TransformerContextMetadataProvider; resolvers: TransformerResolversManagerProvider; dataSources: TransformerDataSourceManagerProvider; providerRegistry: TransformerProviderRegistry; @@ -19,6 +26,7 @@ export interface TransformerContextProvider { api: GraphQLAPIProvider; resourceHelper: TransformerResourceProvider; featureFlags: FeatureFlagProvider; + authConfig: AppSyncAuthConfiguration; isProjectUsingDataStore(): boolean; getResolverConfig(): ResolverConfig | undefined; @@ -26,15 +34,30 @@ export interface TransformerContextProvider { export type TransformerBeforeStepContextProvider = Pick< TransformerContextProvider, - 'inputDocument' | 'featureFlags' | 'isProjectUsingDataStore' + 'inputDocument' | 'featureFlags' | 'isProjectUsingDataStore' | 'getResolverConfig' | 'authConfig' >; export type TransformerSchemaVisitStepContextProvider = Pick< TransformerContextProvider, - 'inputDocument' | 'output' | 'providerRegistry' | 'featureFlags' | 'isProjectUsingDataStore' | 'getResolverConfig' + | 'inputDocument' + | 'output' + | 'providerRegistry' + | 'featureFlags' + | 'isProjectUsingDataStore' + | 'getResolverConfig' + | 'metadata' + | 'authConfig' >; export type TransformerValidationStepContextProvider = Pick< TransformerContextProvider, - 'inputDocument' | 'output' | 'providerRegistry' | 'dataSources' | 'featureFlags' | 'isProjectUsingDataStore' | 'getResolverConfig' + | 'inputDocument' + | 'output' + | 'providerRegistry' + | 'dataSources' + | 'featureFlags' + | 'isProjectUsingDataStore' + | 'getResolverConfig' + | 'metadata' + | 'authConfig' >; export type TransformerPrepareStepContextProvider = TransformerValidationStepContextProvider; export type TransformerTransformSchemaStepContextProvider = TransformerValidationStepContextProvider; diff --git a/packages/amplify-graphql-transformer-interfaces/src/transformer-context/transformer-datasource-provider.ts b/packages/amplify-graphql-transformer-interfaces/src/transformer-context/transformer-datasource-provider.ts index c1472951639..8350f8be702 100644 --- a/packages/amplify-graphql-transformer-interfaces/src/transformer-context/transformer-datasource-provider.ts +++ b/packages/amplify-graphql-transformer-interfaces/src/transformer-context/transformer-datasource-provider.ts @@ -22,6 +22,7 @@ export type DataSourceInstance = ITable | CfnDomain | HttpDataSource | IFunction export interface TransformerDataSourceManagerProvider { add(type: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode, dataSourceInstance: DataSourceInstance): void; get(type: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode): DataSourceInstance; + has(name: string): boolean; } export interface DataSourceProvider extends BackedDataSource {} diff --git a/packages/amplify-graphql-transformer-interfaces/src/transformer-context/transformer-resolver-provider.ts b/packages/amplify-graphql-transformer-interfaces/src/transformer-context/transformer-resolver-provider.ts index 2688c9c192b..b369c6bb234 100644 --- a/packages/amplify-graphql-transformer-interfaces/src/transformer-context/transformer-resolver-provider.ts +++ b/packages/amplify-graphql-transformer-interfaces/src/transformer-context/transformer-resolver-provider.ts @@ -17,6 +17,7 @@ export interface TransformerResolverProvider { export interface TransformerResolversManagerProvider { addResolver: (typeName: string, fieldName: string, resolver: TransformerResolverProvider) => TransformerResolverProvider; getResolver: (typeName: string, fieldName: string) => TransformerResolverProvider | void; + hasResolver: (typeName: string, fieldName: string) => boolean; removeResolver: (typeName: string, fieldName: string) => TransformerResolverProvider; collectResolvers: () => Map; diff --git a/packages/amplify-graphql-transformer-interfaces/src/transformer-model-provider.ts b/packages/amplify-graphql-transformer-interfaces/src/transformer-model-provider.ts index 9bf6090705e..ee5d4372e67 100644 --- a/packages/amplify-graphql-transformer-interfaces/src/transformer-model-provider.ts +++ b/packages/amplify-graphql-transformer-interfaces/src/transformer-model-provider.ts @@ -129,4 +129,6 @@ export interface TransformerModelProvider extends TransformerPluginProvider { ) => ObjectTypeDefinitionNode; } +export interface TransformerAuthProvider extends TransformerPluginProvider {} + export interface TransformerModelEnhancementProvider extends Partial {} diff --git a/packages/amplify-graphql-transformer-interfaces/src/transformer-plugin-provider.ts b/packages/amplify-graphql-transformer-interfaces/src/transformer-plugin-provider.ts index e506f490beb..076831255b5 100644 --- a/packages/amplify-graphql-transformer-interfaces/src/transformer-plugin-provider.ts +++ b/packages/amplify-graphql-transformer-interfaces/src/transformer-plugin-provider.ts @@ -25,6 +25,7 @@ export enum TransformerPluginType { DATA_SOURCE_PROVIDER = 'DATA_SOURCE_PROVIDER', DATA_SOURCE_ENHANCER = 'DATA_SOURCE_ENHANCER', GENERIC = 'GENERIC', + AUTH = 'AUTH', } export interface TransformerPluginProvider { pluginType: TransformerPluginType; diff --git a/packages/amplify-headless-interface/src/interface/api/add.ts b/packages/amplify-headless-interface/src/interface/api/add.ts index 51f44124538..081eaf07e57 100644 --- a/packages/amplify-headless-interface/src/interface/api/add.ts +++ b/packages/amplify-headless-interface/src/interface/api/add.ts @@ -130,6 +130,7 @@ export type AppSyncAuthType = export interface AppSyncAPIKeyAuthType { mode: 'API_KEY'; expirationTime?: number; + apiKeyExpirationDate?: Date; keyDescription?: string; } diff --git a/packages/amplify-migration-tests/src/__tests__/migration_tests/transformer_migration/api.key.migration-2.test.ts b/packages/amplify-migration-tests/src/__tests__/migration_tests/transformer_migration/api.key.migration-2.test.ts index cdac286a907..93e9f286d53 100644 --- a/packages/amplify-migration-tests/src/__tests__/migration_tests/transformer_migration/api.key.migration-2.test.ts +++ b/packages/amplify-migration-tests/src/__tests__/migration_tests/transformer_migration/api.key.migration-2.test.ts @@ -1,5 +1,5 @@ import { - addApiWithSchema, + addApiWithoutSchema, addFeatureFlag, amplifyPush, amplifyPushForce, @@ -28,7 +28,8 @@ describe('amplify key force push', () => { const initialSchema = 'migrations_key/initial_schema.graphql'; // init, add api and push with installed cli await initJSProjectWithProfile(projRoot, { name: projectName }); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); // add feature flag addFeatureFlag(projRoot, 'graphqltransformer', 'secondaryKeyAsGSI', true); diff --git a/packages/amplify-migration-tests/src/__tests__/migration_tests/transformer_migration/api.key.migration.test.ts b/packages/amplify-migration-tests/src/__tests__/migration_tests/transformer_migration/api.key.migration.test.ts index c8a75b766cb..ad38a22425a 100644 --- a/packages/amplify-migration-tests/src/__tests__/migration_tests/transformer_migration/api.key.migration.test.ts +++ b/packages/amplify-migration-tests/src/__tests__/migration_tests/transformer_migration/api.key.migration.test.ts @@ -1,5 +1,5 @@ import { - addApiWithSchema, + addApiWithoutSchema, addFeatureFlag, amplifyPush, amplifyPushForce, @@ -28,7 +28,8 @@ describe('amplify key force push', () => { const initialSchema = 'migrations_key/simple_key.graphql'; // init, add api and push with installed cli await initJSProjectWithProfile(projRoot, { name: projectName }); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); // gql-compile and force push with codebase cli await apiGqlCompile(projRoot, true); diff --git a/packages/amplify-migration-tests/src/__tests__/migration_tests/transformer_migration/api.searchable.migration.test.ts b/packages/amplify-migration-tests/src/__tests__/migration_tests/transformer_migration/api.searchable.migration.test.ts index b1c7194472d..0b0c0b5d5e9 100644 --- a/packages/amplify-migration-tests/src/__tests__/migration_tests/transformer_migration/api.searchable.migration.test.ts +++ b/packages/amplify-migration-tests/src/__tests__/migration_tests/transformer_migration/api.searchable.migration.test.ts @@ -1,5 +1,5 @@ import { - addApiWithSchema, + addApiWithoutSchema, amplifyPush, amplifyPushUpdate, createNewProjectDir, @@ -26,7 +26,8 @@ describe('amplify searchable migration', () => { const nextSchema = 'migrations_searchable/updated_searchable.graphql'; // init, add api and push with installed cli await initJSProjectWithProfile(projRoot, { name: projectName }); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); // update and push with codebase cli updateApiSchema(projRoot, projectName, nextSchema); diff --git a/packages/amplify-migration-tests/src/__tests__/update_tests/api_migration_update.test.ts b/packages/amplify-migration-tests/src/__tests__/update_tests/api_migration_update.test.ts index abdbef5886f..a9589a7c264 100644 --- a/packages/amplify-migration-tests/src/__tests__/update_tests/api_migration_update.test.ts +++ b/packages/amplify-migration-tests/src/__tests__/update_tests/api_migration_update.test.ts @@ -1,6 +1,6 @@ import { - addApiWithSchema, - addApiWithSchemaAndConflictDetection, + addApiWithoutSchema, + addApiWithBlankSchemaAndConflictDetection, amplifyPush, amplifyPushUpdate, createNewProjectDir, @@ -11,7 +11,7 @@ import { getTransformConfig, updateApiSchema, updateApiWithMultiAuth, - updateAPIWithResolutionStrategy, + updateAPIWithResolutionStrategyWithModels, } from 'amplify-e2e-core'; import { existsSync } from 'fs'; import { TRANSFORM_CURRENT_VERSION } from 'graphql-transformer-core'; @@ -38,7 +38,8 @@ describe('api migration update test', () => { const nextSchema = 'next_key_blog.graphql'; // init the project and add api with installed cli await initJSProjectWithProfile(projRoot, { name: projectName }); - await addApiWithSchema(projRoot, initialSchema); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, projectName, initialSchema); await amplifyPush(projRoot); // update api and push with the CLI to be released (the codebase) updateApiSchema(projRoot, projectName, nextSchema); @@ -53,7 +54,8 @@ describe('api migration update test', () => { it('api update migration with multiauth', async () => { // init and add api with installed CLI await initJSProjectWithProfile(projRoot, { name: 'simplemodelmultiauth' }); - await addApiWithSchema(projRoot, 'simple_model.graphql'); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, 'simplemodelmultiauth', 'simple_model.graphql'); // update and push with codebase await updateApiWithMultiAuth(projRoot, { testingWithLatestCodebase: true }); await amplifyPush(projRoot, true); @@ -98,7 +100,8 @@ describe('api migration update test', () => { const name = `syncenabled`; // init and add api with locally installed cli await initJSProjectWithProfile(projRoot, { name }); - await addApiWithSchemaAndConflictDetection(projRoot, 'simple_model.graphql'); + await addApiWithBlankSchemaAndConflictDetection(projRoot); + await updateApiSchema(projRoot, name, 'simple_model.graphql'); let transformConfig = getTransformConfig(projRoot, name); expect(transformConfig).toBeDefined(); @@ -108,7 +111,7 @@ describe('api migration update test', () => { expect(transformConfig.ResolverConfig.project.ConflictHandler).toEqual('AUTOMERGE'); //update and push with codebase - await updateAPIWithResolutionStrategy(projRoot, { testingWithLatestCodebase: true }); + await updateAPIWithResolutionStrategyWithModels(projRoot, { testingWithLatestCodebase: true }); transformConfig = getTransformConfig(projRoot, name); expect(transformConfig).toBeDefined(); diff --git a/packages/amplify-migration-tests/src/__tests__/update_tests/function_migration_update.test.ts b/packages/amplify-migration-tests/src/__tests__/update_tests/function_migration_update.test.ts index 1755e98afef..4a42e1e1027 100644 --- a/packages/amplify-migration-tests/src/__tests__/update_tests/function_migration_update.test.ts +++ b/packages/amplify-migration-tests/src/__tests__/update_tests/function_migration_update.test.ts @@ -1,5 +1,5 @@ import { - addApiWithSchema, + addApiWithoutSchema, addFunction, addLayer, amplifyPush, @@ -15,8 +15,10 @@ import { LayerRuntime, loadFunctionTestFile, overrideFunctionSrcNode, + updateApiSchema, updateFunction, validateLayerMetadata, + createRandomName, } from 'amplify-e2e-core'; import { v4 as uuid } from 'uuid'; import { initJSProjectWithProfile } from '../../migration-helpers'; @@ -34,7 +36,10 @@ describe('amplify function migration', () => { }); it('existing lambda updated with additional permissions should be able to scan ddb', async () => { - await initJSProjectWithProfile(projRoot, {}); + const appName = createRandomName(); + await initJSProjectWithProfile(projRoot, { + name: appName, + }); const random = Math.floor(Math.random() * 10000); const fnName = `integtestfn${random}`; @@ -58,7 +63,8 @@ describe('amplify function migration', () => { expect(functionName).toBeDefined(); expect(region).toBeDefined(); - await addApiWithSchema(projRoot, 'simple_model.graphql'); + await addApiWithoutSchema(projRoot); + await updateApiSchema(projRoot, appName, 'simple_model.graphql'); await updateFunction( projRoot, { diff --git a/packages/amplify-provider-awscloudformation/package.json b/packages/amplify-provider-awscloudformation/package.json index 002a0d8a2bf..e75fb1a834b 100644 --- a/packages/amplify-provider-awscloudformation/package.json +++ b/packages/amplify-provider-awscloudformation/package.json @@ -24,6 +24,7 @@ "watch": "tsc --watch" }, "dependencies": { + "@aws-amplify/graphql-auth-transformer": "0.1.0", "@aws-amplify/graphql-default-value-transformer": "0.2.0", "@aws-amplify/graphql-function-transformer": "0.4.5", "@aws-amplify/graphql-http-transformer": "0.5.5", diff --git a/packages/amplify-provider-awscloudformation/src/__tests__/utils/api-key-helpers.test.ts b/packages/amplify-provider-awscloudformation/src/__tests__/utils/api-key-helpers.test.ts new file mode 100644 index 00000000000..ac142f3421f --- /dev/null +++ b/packages/amplify-provider-awscloudformation/src/__tests__/utils/api-key-helpers.test.ts @@ -0,0 +1,91 @@ +import { getAppSyncApiConfig, getApiKeyConfig, apiKeyIsActive, hasApiKey } from '../../utils/api-key-helpers'; + +jest.mock('amplify-cli-core', () => { + const original = jest.requireActual('amplify-cli-core'); + const amplifyMeta = { + api: { + myapp: { + service: 'AppSync', + output: { + authConfig: { + defaultAuthentication: { + authenticationType: 'AWS_IAM', + }, + additionalAuthenticationProviders: [ + { + authenticationType: 'API_KEY', + apiKeyConfig: { + apiKeyExpirationDays: 2, + apiKeyExpirationDate: '2021-08-20T20:38:07.585Z', + description: '', + }, + }, + ], + }, + }, + }, + }, + }; + + return { + ...original, + stateManager: { + getMeta: jest.fn().mockImplementation(() => amplifyMeta), + }, + }; +}); + +describe('getAppSyncApiConfig', () => { + it('returns the api object', async () => { + const result = getAppSyncApiConfig(); + + expect(result).toStrictEqual({ + service: 'AppSync', + output: { + authConfig: { + defaultAuthentication: { + authenticationType: 'AWS_IAM', + }, + additionalAuthenticationProviders: [ + { + authenticationType: 'API_KEY', + apiKeyConfig: { + apiKeyExpirationDays: 2, + apiKeyExpirationDate: '2021-08-20T20:38:07.585Z', + description: '', + }, + }, + ], + }, + }, + }); + }); +}); + +describe('getApiKeyConfig', () => { + it('returns the api key config', () => { + const result = getApiKeyConfig(); + + expect(result).toStrictEqual({ + apiKeyExpirationDays: 2, + apiKeyExpirationDate: '2021-08-20T20:38:07.585Z', + description: '', + }); + }); +}); + +describe('apiKeyIsActive', () => { + describe('with expired key', () => { + it('returns false', () => { + expect(apiKeyIsActive()).toBe(false); + }); + }); +}); + +describe('hasApiKey', () => { + describe('if api key config is present', () => { + it('returns true if api key is present', () => { + expect(hasApiKey()).toBe(true); + }); + }); +}); diff --git a/packages/amplify-provider-awscloudformation/src/__tests__/utils/sandbox-mode-helpers.test.ts b/packages/amplify-provider-awscloudformation/src/__tests__/utils/sandbox-mode-helpers.test.ts new file mode 100644 index 00000000000..c653c5ff48f --- /dev/null +++ b/packages/amplify-provider-awscloudformation/src/__tests__/utils/sandbox-mode-helpers.test.ts @@ -0,0 +1,117 @@ +import { showSandboxModePrompts, removeSandboxDirectiveFromSchema, showGlobalSandboxModeWarning } from '../../utils/sandbox-mode-helpers'; +import { $TSContext } from 'amplify-cli-core'; +import chalk from 'chalk'; +import * as prompts from 'amplify-prompts'; +import * as apiKeyHelpers from '../../utils/api-key-helpers'; + +let ctx; +let apiKeyPresent = true; + +describe('sandbox mode helpers', () => { + beforeEach(() => { + const envName = 'dev'; + ctx = { + amplify: { + getEnvInfo() { + return { envName }; + }, + invokePluginMethod: jest.fn(), + }, + } as unknown as $TSContext; + + jest.spyOn(prompts.printer, 'info').mockImplementation(); + jest.spyOn(apiKeyHelpers, 'hasApiKey').mockReturnValue(apiKeyPresent); + }); + + describe('showSandboxModePrompts', () => { + describe('missing api key', () => { + beforeAll(() => { + apiKeyPresent = false; + }); + + it('displays warning', async () => { + await showSandboxModePrompts(ctx); + + expect(prompts.printer.info).toBeCalledWith( + ` +⚠️ WARNING: Global Sandbox Mode has been enabled, which requires a valid API key. If +you'd like to disable, remove ${chalk.green('"type AMPLIFY_GLOBAL @allow_public_data_access_with_api_key"')} +from your GraphQL schema and run 'amplify push' again. If you'd like to proceed with +sandbox mode disabled in '${ctx.amplify.getEnvInfo().envName}', do not create an API Key. +`, + 'yellow', + ); + expect(ctx.amplify.invokePluginMethod).toBeCalledWith(ctx, 'api', undefined, 'promptToAddApiKey', [ctx]); + }); + }); + }); + + describe('showGlobalSandboxModeWarning', () => { + it('prints sandbox api key message', () => { + showGlobalSandboxModeWarning(); + + expect(prompts.printer.info).toBeCalledWith( + ` +⚠️ WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql-transformer/auth +`, + 'yellow', + ); + }); + }); + + describe('removeSandboxDirectiveFromSchema', () => { + it('removes sandbox mode directive', () => { + const schema = ` +type AMPLIFY_GLOBAL @allow_public_data_access_with_api_key(in: "dev") + `; + + expect(removeSandboxDirectiveFromSchema(schema)).toEqual(` + + `); + }); + + it('does not change user schema with directive', () => { + const schema = ` +type AMPLIFY_GLOBAL @allow_public_data_access_with_api_key(in: "dev10105") # FOR TESTING ONLY! + +type Todo @model { + id: ID! + name: String! + description: String +} + `; + + expect(removeSandboxDirectiveFromSchema(schema)).toEqual(` + # FOR TESTING ONLY! + +type Todo @model { + id: ID! + name: String! + description: String +} + `); + }); + + it('does not change user schema with directive and single quotes', () => { + const schema = ` +type AMPLIFY_GLOBAL @allow_public_data_access_with_api_key(in: 'dev10105') # FOR TESTING ONLY! + +type Todo @model { + id: ID! + name: String! + description: String +} + `; + + expect(removeSandboxDirectiveFromSchema(schema)).toEqual(` + # FOR TESTING ONLY! + +type Todo @model { + id: ID! + name: String! + description: String +} + `); + }); + }); +}); diff --git a/packages/amplify-provider-awscloudformation/src/graphql-transformer/transform-graphql-schema.ts b/packages/amplify-provider-awscloudformation/src/graphql-transformer/transform-graphql-schema.ts index 29429ef53f7..55ebedb2f44 100644 --- a/packages/amplify-provider-awscloudformation/src/graphql-transformer/transform-graphql-schema.ts +++ b/packages/amplify-provider-awscloudformation/src/graphql-transformer/transform-graphql-schema.ts @@ -3,14 +3,16 @@ import path from 'path'; import importGlobal from 'import-global'; import { print } from 'graphql'; import importFrom from 'import-from'; -import { TransformerPluginProvider } from '@aws-amplify/graphql-transformer-interfaces'; +import { TransformerPluginProvider, AppSyncAuthConfiguration } from '@aws-amplify/graphql-transformer-interfaces'; import { getAppSyncServiceExtraDirectives, GraphQLTransform, collectDirectivesByTypeNames, + collectDirectives, TransformerProjectConfig, } from '@aws-amplify/graphql-transformer-core'; import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'; +import { AuthTransformer } from '@aws-amplify/graphql-auth-transformer'; import { FunctionTransformer } from '@aws-amplify/graphql-function-transformer'; import { HttpTransformer } from '@aws-amplify/graphql-http-transformer'; import { PredictionsTransformer } from '@aws-amplify/graphql-predictions-transformer'; @@ -28,12 +30,17 @@ import { hashDirectory } from '../upload-appsync-files'; import { writeDeploymentToDisk } from './utils'; import { loadProject as readTransformerConfiguration } from './transform-config'; import { loadProject } from 'graphql-transformer-core'; -import { AppSyncAuthConfiguration } from '@aws-amplify/graphql-transformer-core'; import { Template } from '@aws-amplify/graphql-transformer-core/lib/config/project-config'; import { AmplifyCLIFeatureFlagAdapter } from '../utils/amplify-cli-feature-flag-adapter'; -import { JSONUtilities } from 'amplify-cli-core'; +import { JSONUtilities, stateManager, $TSContext } from 'amplify-cli-core'; import { searchablePushChecks } from '../transform-graphql-schema'; import { ResourceConstants } from 'graphql-transformer-common'; +import { isAmplifyAdminApp } from '../utils/admin-helpers'; +import { + showSandboxModePrompts, + getSandboxModeEnvNameFromDirectiveSet, + removeSandboxDirectiveFromSchema, +} from '../utils/sandbox-mode-helpers'; const API_CATEGORY = 'api'; const STORAGE_CATEGORY = 'storage'; @@ -55,7 +62,10 @@ function warnOnAuth(context, map) { } } -function getTransformerFactory(context, resourceDir) { +function getTransformerFactory( + context: $TSContext, + resourceDir: string, +): (options: TransformerFactoryArgs) => Promise { return async (options?: TransformerFactoryArgs) => { const modelTransformer = new ModelTransformer(); const indexTransformer = new IndexTransformer(); @@ -147,7 +157,19 @@ function getTransformerFactory(context, resourceDir) { // TODO: Build dependency mechanism into transformers. Auth runs last // so any resolvers that need to be protected will already be created. - // transformerList.push(new ModelAuthTransformer({ authConfig })); + + let amplifyAdminEnabled: boolean = false; + let adminUserPoolID: string; + try { + const amplifyMeta = stateManager.getMeta(); + const appId = amplifyMeta?.providers?.[providerName]?.AmplifyAppId; + const res = await isAmplifyAdminApp(appId); + amplifyAdminEnabled = res.isAdminApp; + adminUserPoolID = res.userPoolID; + } catch (err) { + console.info('App not deployed yet.'); + } + transformerList.push(new AuthTransformer({ authConfig: options?.authConfig, addAwsIamAuthInOutputSchema: false, adminUserPoolID })); return transformerList; }; @@ -224,7 +246,7 @@ export async function transformGraphQLSchema(context, options) { } } - let { authConfig } = options; + let { authConfig }: { authConfig: AppSyncAuthConfiguration } = options; // // If we don't have an authConfig from the caller, use it from the @@ -283,6 +305,17 @@ export async function transformGraphQLSchema(context, options) { const transformerListFactory = getTransformerFactory(context, resourceDir); + const { envName } = context.amplify._getEnvInfo(); + const sandboxModeEnv = getSandboxModeEnvNameFromDirectiveSet(collectDirectives(project.schema)); + const sandboxModeEnabled = envName === sandboxModeEnv; + + if (sandboxModeEnabled && options.promptApiKeyCreation) { + const apiKeyConfig = await showSandboxModePrompts(context); + if (apiKeyConfig) { + authConfig.additionalAuthenticationProviders.push(apiKeyConfig); + } + } + let searchableTransformerFlag = false; if (directiveMap.directives.includes('searchable')) { @@ -294,17 +327,19 @@ export async function transformGraphQLSchema(context, options) { buildParameters, projectDirectory: resourceDir, transformersFactory: transformerListFactory, - transformersFactoryArgs: { addSearchableTransformer: searchableTransformerFlag, storageConfig }, + transformersFactoryArgs: { addSearchableTransformer: searchableTransformerFlag, storageConfig, authConfig }, rootStackFileName: 'cloudformation-template.json', currentCloudBackendDirectory: previouslyDeployedBackendDir, minify: options.minify, projectConfig: project, lastDeployedProjectConfig, authConfig, + sandboxModeEnabled, }; + const transformerOutput = await buildAPIProject(buildConfig); - context.print.success(`\nGraphQL schema compiled successfully.\n\nEdit your schema at ${schemaFilePath} or \ + context.print.success(`GraphQL schema compiled successfully.\n\nEdit your schema at ${schemaFilePath} or \ place .graphql files in a directory at ${schemaDirPath}`); if (!options.dryRun) { @@ -314,6 +349,17 @@ place .graphql files in a directory at ${schemaDirPath}`); return transformerOutput; } +async function addGraphQLAuthRequirement(context, authType) { + return await context.amplify.invokePluginMethod(context, 'api', undefined, 'addGraphQLAuthorizationMode', [ + context, + { + authType: authType, + printLeadText: true, + authSettings: undefined, + }, + ]); +} + function getProjectBucket(context) { const projectDetails = context.amplify.getProjectDetails(); const projectBucket = projectDetails.amplifyMeta.providers ? projectDetails.amplifyMeta.providers[providerName].DeploymentBucketName : ''; @@ -336,8 +382,8 @@ async function getPreviousDeploymentRootKey(previouslyDeployedBackendDir) { } } -export async function getDirectiveDefinitions(context, resourceDir) { - const transformList = await getTransformerFactory(context, resourceDir)({ addSearchableTransformer: true }); +export async function getDirectiveDefinitions(context: $TSContext, resourceDir: string) { + const transformList = await getTransformerFactory(context, resourceDir)({ addSearchableTransformer: true, authConfig: {} }); const appSynDirectives = getAppSyncServiceExtraDirectives(); const transformDirectives = transformList .map(transformPluginInst => [transformPluginInst.directive, ...transformPluginInst.typeDefinitions].map(node => print(node)).join('\n')) @@ -384,6 +430,7 @@ function getBucketName(context, s3ResourceName, backEndDir) { type TransformerFactoryArgs = { addSearchableTransformer: boolean; + authConfig: any; storageConfig?: any; }; export type ProjectOptions = { @@ -392,7 +439,7 @@ export type ProjectOptions = { S3DeploymentRootKey: string; }; projectDirectory?: string; - transformersFactory: (options: T) => TransformerPluginProvider[]; + transformersFactory: (options: T) => Promise; transformersFactoryArgs: T; rootStackFileName: 'cloudformation-template.json'; currentCloudBackendDirectory: string; @@ -402,6 +449,7 @@ export type ProjectOptions = { dryRun?: boolean; authConfig?: AppSyncAuthConfiguration; stacks: Record; + sandboxModeEnabled?: boolean; }; export async function buildAPIProject(opts: ProjectOptions) { @@ -419,6 +467,9 @@ export async function buildAPIProject(opts: ProjectOptions) { buildParameters: opts.buildParameters, stacks: opts.projectConfig.stacks || {}, featureFlags: new AmplifyCLIFeatureFlagAdapter(), + sandboxModeEnabled: opts.sandboxModeEnabled, }); - return transform.transform(userProjectConfig.schema.toString()); + + let schema = userProjectConfig.schema.toString(); + if (opts.sandboxModeEnabled) schema = removeSandboxDirectiveFromSchema(schema); + + return transform.transform(schema); } diff --git a/packages/amplify-provider-awscloudformation/src/push-resources.ts b/packages/amplify-provider-awscloudformation/src/push-resources.ts index a84782bcff0..9a289453fd0 100644 --- a/packages/amplify-provider-awscloudformation/src/push-resources.ts +++ b/packages/amplify-provider-awscloudformation/src/push-resources.ts @@ -148,6 +148,7 @@ export async function run(context: $TSContext, resourceDefinition: $TSObject) { await transformGraphQLSchema(context, { handleMigration: opts => updateStackForAPIMigration(context, 'api', undefined, opts), minify: options['minify'], + promptApiKeyCreation: true, }); // If there is a deployment already in progress we have to fail the push operation as another @@ -389,8 +390,9 @@ export async function run(context: $TSContext, resourceDefinition: $TSObject) { if (iterativeDeploymentWasInvoked) { await deploymentStateManager.failDeployment(); } - spinner.fail('An error occurred when pushing the resources to the cloud'); - + if(!await canAutoResolveGraphQLAuthError(error.message)) { + spinner.fail('An error occurred when pushing the resources to the cloud'); + } rollbackLambdaLayers(layerResources); logger('run', [resourceDefinition])(error); @@ -399,6 +401,16 @@ export async function run(context: $TSContext, resourceDefinition: $TSObject) { } } +async function canAutoResolveGraphQLAuthError(message: string) { + if (message === `@auth directive with 'iam' provider found, but the project has no IAM authentication provider configured.` + || message === `@auth directive with 'userPools' provider found, but the project has no Cognito User Pools authentication provider configured.` + || message === `@auth directive with 'oidc' provider found, but the project has no OPENID_CONNECT authentication provider configured.` + || message === `@auth directive with 'apiKey' provider found, but the project has no API Key authentication provider configured.` + || message === `@auth directive with 'function' provider found, but the project has no Lambda authentication provider configured.`) { + return true; + } +} + export async function updateStackForAPIMigration(context: $TSContext, category: string, resourceName: string, options: $TSAny) { const { resourcesToBeCreated, resourcesToBeUpdated, resourcesToBeDeleted, allResources } = await context.amplify.getResourceStatus( category, @@ -827,7 +839,7 @@ async function formNestedStack( nestedStack.Description = 'Root Stack for AWS Amplify Console'; } } catch (err) { - console.info('App not deployed yet.'); + // if it is not an AmplifyAdmin app, do nothing } const { amplifyMeta } = projectDetails; diff --git a/packages/amplify-provider-awscloudformation/src/transform-graphql-schema.ts b/packages/amplify-provider-awscloudformation/src/transform-graphql-schema.ts index a29a482b8fc..18207eb6b9a 100644 --- a/packages/amplify-provider-awscloudformation/src/transform-graphql-schema.ts +++ b/packages/amplify-provider-awscloudformation/src/transform-graphql-schema.ts @@ -173,7 +173,7 @@ function getTransformerFactory(context, resourceDir, authConfig?) { const res = await isAmplifyAdminApp(appId); amplifyAdminEnabled = res.isAdminApp; } catch (err) { - console.info('App not deployed yet.'); + // if it is not an AmplifyAdmin app, do nothing } transformerList.push(new ModelAuthTransformer({ authConfig, addAwsIamAuthInOutputSchema: amplifyAdminEnabled })); @@ -512,8 +512,10 @@ export async function transformGraphQLSchema(context, options) { featureFlags: ff, sanityCheckRules: sanityCheckRulesList, }; + const transformerOutput = await buildAPIProject(buildConfig); - context.print.success(`\nGraphQL schema compiled successfully.\n\nEdit your schema at ${schemaFilePath} or \ + + context.print.success(`GraphQL schema compiled successfully.\n\nEdit your schema at ${schemaFilePath} or \ place .graphql files in a directory at ${schemaDirPath}`); if (!options.dryRun) { @@ -523,6 +525,17 @@ place .graphql files in a directory at ${schemaDirPath}`); return transformerOutput; } +async function addGraphQLAuthRequirement(context, authType) { + return await context.amplify.invokePluginMethod(context, 'api', undefined, 'addGraphQLAuthorizationMode', [ + context, + { + authType: authType, + printLeadText: true, + authSettings: undefined, + }, + ]); +} + function getProjectBucket(context) { const projectDetails = context.amplify.getProjectDetails(); const projectBucket = projectDetails.amplifyMeta.providers ? projectDetails.amplifyMeta.providers[providerName].DeploymentBucketName : ''; diff --git a/packages/amplify-provider-awscloudformation/src/utils/admin-helpers.ts b/packages/amplify-provider-awscloudformation/src/utils/admin-helpers.ts index 0cd6143c3db..13c24707899 100644 --- a/packages/amplify-provider-awscloudformation/src/utils/admin-helpers.ts +++ b/packages/amplify-provider-awscloudformation/src/utils/admin-helpers.ts @@ -17,7 +17,7 @@ export function doAdminTokensExist(appId: string): boolean { return !!stateManager.getAmplifyAdminConfigEntry(appId); } -export async function isAmplifyAdminApp(appId: string): Promise<{ isAdminApp: boolean; region: string }> { +export async function isAmplifyAdminApp(appId: string): Promise<{ isAdminApp: boolean; region: string; userPoolID: string }> { if (!appId) { throw `Failed to check if Admin UI is enabled: appId is undefined`; } @@ -25,7 +25,8 @@ export async function isAmplifyAdminApp(appId: string): Promise<{ isAdminApp: bo if (appState.appId && appState.region && appState.region !== 'us-east-1') { appState = await getAdminAppState(appId, appState.region); } - return { isAdminApp: !!appState.appId, region: appState.region }; + const userPoolID = appState.loginAuthConfig ? JSON.parse(appState.loginAuthConfig).aws_user_pools_id : ''; + return { isAdminApp: !!appState.appId, region: appState.region, userPoolID }; } export async function getTempCredsWithAdminTokens(context: $TSContext, appId: string): Promise { diff --git a/packages/amplify-provider-awscloudformation/src/utils/api-key-helpers.ts b/packages/amplify-provider-awscloudformation/src/utils/api-key-helpers.ts new file mode 100644 index 00000000000..e9362dfb763 --- /dev/null +++ b/packages/amplify-provider-awscloudformation/src/utils/api-key-helpers.ts @@ -0,0 +1,51 @@ +import { stateManager } from 'amplify-cli-core'; +import { ApiKeyConfig } from '@aws-amplify/graphql-transformer-interfaces'; + +export function getAppSyncApiConfig(): any { + const apiConfig = stateManager.getMeta()?.api; + let appSyncApi; + + Object.keys(apiConfig).forEach(k => { + if (apiConfig[k]['service'] === 'AppSync') appSyncApi = apiConfig[k]; + }); + + return appSyncApi; +} + +function getDefaultIfApiKey(): ApiKeyConfig { + const authConfig = getAppSyncApiConfig()?.output?.authConfig; + const { defaultAuthentication } = authConfig; + + if (defaultAuthentication.authenticationType === 'API_KEY') return defaultAuthentication.apiKeyConfig; +} + +function getAdditionalApiKeyConfig(): ApiKeyConfig { + const authConfig = getAppSyncApiConfig()?.output?.authConfig; + const { additionalAuthenticationProviders } = authConfig; + let apiKeyConfig; + + additionalAuthenticationProviders.forEach(authProvider => { + if (authProvider.authenticationType === 'API_KEY') apiKeyConfig = authProvider.apiKeyConfig; + }); + + return apiKeyConfig; +} + +export function getApiKeyConfig(): ApiKeyConfig { + const emptyConfig = {} as ApiKeyConfig; + return getDefaultIfApiKey() || getAdditionalApiKeyConfig() || emptyConfig; +} + +export function apiKeyIsActive(): boolean { + const today = new Date(); + const { apiKeyExpirationDate } = getApiKeyConfig() || {}; + + if (!apiKeyExpirationDate) return false; + + return new Date(apiKeyExpirationDate) > today; +} + +export function hasApiKey(): boolean { + const apiKeyConfig = getApiKeyConfig(); + return !!apiKeyConfig && !!apiKeyConfig?.apiKeyExpirationDays; +} diff --git a/packages/amplify-provider-awscloudformation/src/utils/sandbox-mode-helpers.ts b/packages/amplify-provider-awscloudformation/src/utils/sandbox-mode-helpers.ts new file mode 100644 index 00000000000..8aca7711d5f --- /dev/null +++ b/packages/amplify-provider-awscloudformation/src/utils/sandbox-mode-helpers.ts @@ -0,0 +1,43 @@ +import chalk from 'chalk'; +import { $TSContext } from 'amplify-cli-core'; +import { hasApiKey } from './api-key-helpers'; +import { printer } from 'amplify-prompts'; + +export async function showSandboxModePrompts(context: $TSContext): Promise { + if (hasApiKey()) return showGlobalSandboxModeWarning(); + else { + printer.info( + ` +⚠️ WARNING: Global Sandbox Mode has been enabled, which requires a valid API key. If +you'd like to disable, remove ${chalk.green('"type AMPLIFY_GLOBAL @allow_public_data_access_with_api_key"')} +from your GraphQL schema and run 'amplify push' again. If you'd like to proceed with +sandbox mode disabled in '${context.amplify.getEnvInfo().envName}', do not create an API Key. +`, + 'yellow', + ); + return await context.amplify.invokePluginMethod(context, 'api', undefined, 'promptToAddApiKey', [context]); + } +} + +export function showGlobalSandboxModeWarning(): void { + printer.info( + ` +⚠️ WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql-transformer/auth +`, + 'yellow', + ); +} + +export function getSandboxModeEnvNameFromDirectiveSet(input: any): string { + const sandboxModeDirective = input.find((el: any) => el.name.value === 'allow_public_data_access_with_api_key'); + + if (!sandboxModeDirective) return ''; + + const inField = sandboxModeDirective.arguments.find((el: any) => el.name.value === 'in'); + return inField.value.value; +} + +export function removeSandboxDirectiveFromSchema(schema): string { + const ampGlobalRegex = /(type AMPLIFY_GLOBAL @allow_public_data_access_with_api_key\(in:)+(.*?)+(\))/g; + return schema.replace(ampGlobalRegex, ''); +} diff --git a/packages/graphql-auth-transformer/src/ModelAuthTransformer.ts b/packages/graphql-auth-transformer/src/ModelAuthTransformer.ts index cf2fab44ac3..6e41670abd6 100644 --- a/packages/graphql-auth-transformer/src/ModelAuthTransformer.ts +++ b/packages/graphql-auth-transformer/src/ModelAuthTransformer.ts @@ -98,6 +98,7 @@ export type AppSyncAuthConfigurationEntry = { export type ApiKeyConfig = { description?: string; apiKeyExpirationDays: number; + apiKeyExpirationDate?: Date; }; export type UserPoolConfig = { userPoolId: string; @@ -1387,9 +1388,8 @@ operations will be generated by the CLI.`, // In create mutations, the dynamic group and ownership authorization checks // are done before calling PutItem. - const dynamicGroupAuthorizationExpression = this.resources.dynamicGroupAuthorizationExpressionForCreateOperations( - dynamicGroupAuthorizationRules, - ); + const dynamicGroupAuthorizationExpression = + this.resources.dynamicGroupAuthorizationExpressionForCreateOperations(dynamicGroupAuthorizationRules); const fieldIsList = (fieldName: string) => { const field = parent.fields.find(field => field.name.value === fieldName); if (field) { @@ -1547,9 +1547,8 @@ operations will be generated by the CLI.`, ]), ); - const throwIfNotStaticGroupAuthorizedOrAuthConditionIsEmpty = this.resources.throwIfNotStaticGroupAuthorizedOrAuthConditionIsEmpty( - field, - ); + const throwIfNotStaticGroupAuthorizedOrAuthConditionIsEmpty = + this.resources.throwIfNotStaticGroupAuthorizedOrAuthConditionIsEmpty(field); // If we've any modes to check, then add the authMode check code block // to the start of the resolver. diff --git a/packages/graphql-mapping-template/src/print.ts b/packages/graphql-mapping-template/src/print.ts index bd5a90f853c..b871264e156 100644 --- a/packages/graphql-mapping-template/src/print.ts +++ b/packages/graphql-mapping-template/src/print.ts @@ -115,7 +115,7 @@ function printReference(node: ReferenceNode): string { } function printQuietReference(node: QuietReferenceNode, indent: string = ''): string { - const val = typeof node.value === 'string' ? node.value : printExpr(node.value) + const val = typeof node.value === 'string' ? node.value : printExpr(node.value); return `${indent}$util.qr(${val})`; } diff --git a/packages/graphql-transformer-core/src/collectDirectives.ts b/packages/graphql-transformer-core/src/collectDirectives.ts index ee8ae2a16a4..4cd2c103b38 100644 --- a/packages/graphql-transformer-core/src/collectDirectives.ts +++ b/packages/graphql-transformer-core/src/collectDirectives.ts @@ -62,6 +62,9 @@ export function collectDirectivesByTypeNames(sdl: string) { } export function collectDirectivesByType(sdl: string): Object { + if (!sdl) { + return {}; + } const doc = parse(sdl); // defined types with directives list let types = {}; diff --git a/packages/graphql-transformers-e2e-tests/package.json b/packages/graphql-transformers-e2e-tests/package.json index 36e665c2cc2..b7324a29e4b 100644 --- a/packages/graphql-transformers-e2e-tests/package.json +++ b/packages/graphql-transformers-e2e-tests/package.json @@ -35,6 +35,7 @@ "@aws-amplify/graphql-index-transformer": "0.4.0", "@aws-amplify/graphql-model-transformer": "0.6.4", "@aws-amplify/graphql-transformer-core": "0.9.2", + "@aws-amplify/graphql-transformer-interfaces": "1.10.0", "@types/node": "^12.12.6", "aws-amplify": "^4.2.8", "aws-appsync": "^4.1.1", diff --git a/packages/graphql-transformers-e2e-tests/src/__tests__/AuthV2Transformer.e2e.test.ts b/packages/graphql-transformers-e2e-tests/src/__tests__/AuthV2Transformer.e2e.test.ts new file mode 100644 index 00000000000..5721d076abd --- /dev/null +++ b/packages/graphql-transformers-e2e-tests/src/__tests__/AuthV2Transformer.e2e.test.ts @@ -0,0 +1,3329 @@ +import { IndexTransformer, PrimaryKeyTransformer } from '@aws-amplify/graphql-index-transformer'; +import { HasOneTransformer } from '@aws-amplify/graphql-relational-transformer'; +import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'; +import { GraphQLTransform } from '@aws-amplify/graphql-transformer-core'; +import { AppSyncAuthConfiguration } from '@aws-amplify/graphql-transformer-interfaces'; +import { AuthTransformer } from '@aws-amplify/graphql-auth-transformer'; +import { Output } from 'aws-sdk/clients/cloudformation'; +import { CloudFormationClient } from '../CloudFormationClient'; +import { S3Client } from '../S3Client'; +import { cleanupStackAfterTest, deploy } from '../deployNestedStacks'; +import { default as CognitoClient } from 'aws-sdk/clients/cognitoidentityserviceprovider'; +import { default as S3 } from 'aws-sdk/clients/s3'; +import moment from 'moment'; +import { + createUserPool, + createUserPoolClient, + configureAmplify, + addUserToGroup, + authenticateUser, + createGroup, + signupUser, +} from '../cognitoUtils'; +import { ResourceConstants } from 'graphql-transformer-common'; +import { GraphQLClient } from '../GraphQLClient'; + +jest.setTimeout(2000000); + +describe('@model with @auth', () => { + // setup clients + const cf = new CloudFormationClient('us-west-2'); + const customS3Client = new S3Client('us-west-2'); + const cognitoClient = new CognitoClient({ apiVersion: '2016-04-19', region: 'us-west-2' }); + const awsS3Client = new S3({ region: 'us-west-2' }); + + // stack info + const BUILD_TIMESTAMP = moment().format('YYYYMMDDHHmmss'); + const STACK_NAME = `AuthV2TransformerTests-${BUILD_TIMESTAMP}`; + const BUCKET_NAME = `appsync-auth-v2-transformer-test-bucket-${BUILD_TIMESTAMP}`; + const LOCAL_FS_BUILD_DIR = '/tmp/authv2_transformer_tests/'; + const S3_ROOT_DIR_KEY = 'deployments'; + let USER_POOL_ID: string; + let GRAPHQL_ENDPOINT: string; + /** + * Client 1 is logged in and is a member of the Admin group. + */ + let GRAPHQL_CLIENT_1: GraphQLClient; + + /** + * Client 1 is logged in and is a member of the Admin group via an access token. + */ + let GRAPHQL_CLIENT_1_ACCESS: GraphQLClient; + + /** + * Client 2 is logged in and is a member of the Devs group. + */ + let GRAPHQL_CLIENT_2: GraphQLClient; + + /** + * Client 3 is logged in and is a member of the Devs-Admin group via an access token. + */ + let GRAPHQL_CLIENT_3: GraphQLClient; + + // env info + const USERNAME1 = 'user1@test.com'; + const USERNAME2 = 'user2@test.com'; + const USERNAME3 = 'user3@test.com'; + const TMP_PASSWORD = 'Password123!'; + const REAL_PASSWORD = 'Password1234!'; + + const ADMIN_GROUP_NAME = 'Admin'; + const DEVS_GROUP_NAME = 'Devs'; + const DEVS_ADMIN_GROUP_NAME = 'Devs-Admin'; + const PARTICIPANT_GROUP_NAME = 'Participant'; + const WATCHER_GROUP_NAME = 'Watcher'; + + function outputValueSelector(key: string) { + return (outputs: Output[]) => { + const output = outputs.find((o: Output) => o.OutputKey === key); + return output ? output.OutputValue : null; + }; + } + beforeAll(async () => { + const validSchema = ` + type Post @model @auth(rules: [{ allow: owner }]) { + id: ID! + title: String! + createdAt: AWSDateTime + updatedAt: AWSDateTime + owner: String + } + type Salary + @model + @auth(rules: [{ allow: owner }, { allow: groups, groups: ["Admin"] }]) { + id: ID! + wage: Int + owner: String + } + type AdminNote + @model + @auth( + rules: [{ allow: groups, groups: ["Admin"], groupClaim: "cognito:groups" }] + ) { + id: ID! + content: String! + } + type ManyGroupProtected + @model + @auth(rules: [{ allow: groups, groupsField: "groups" }]) { + id: ID! + value: Int + groups: [String] + } + type SingleGroupProtected + @model + @auth(rules: [{ allow: groups, groupsField: "group" }]) { + id: ID! + value: Int + group: String + } + type PWProtected + @auth( + rules: [ + { + allow: groups + groups: ["Devs"] + } + { + allow: groups + groupsField: "participants" + operations: [read, update, delete] + } + { allow: groups, groupsField: "watchers", operations: [read] } + ] + ) + @model { + id: ID! + content: String! + participants: String + watchers: String + } + type AllThree + @auth( + rules: [ + { allow: owner, identityClaim: "username" } + { allow: owner, ownerField: "editors", identityClaim: "cognito:username" } + { allow: groups, groups: ["Admin", "Execs"] } + { allow: groups, groupsField: "groups" } + { allow: groups, groupsField: "alternativeGroup" } + ] + ) + @model { + id: ID! + owner: String + editors: [String] + groups: [String] + alternativeGroup: String + } + # The owner should always start with https://cognito-idp + type TestIdentity + @model + @auth(rules: [{ allow: owner, identityClaim: "iss" }]) { + id: ID! + title: String! + owner: String + } + type OwnerReadProtected + @model + @auth(rules: [{ allow: groups, groups: ["Admin"]},{ allow: owner, operations: [read] }]) { + id: ID! @primaryKey(sortKeyFields: ["sk"]) + sk: String! + content: String + owner: String + } + type OwnerCreateUpdateDeleteProtected + @model + @auth(rules: [{ allow: owner, operations: [create, update, delete] }]) { + id: ID! + content: String + owner: String + } + type Performance + @model + @auth( + rules: [ + { allow: groups, groups: ["Admin"] } + { allow: private, operations: [read] } + ] + ) { + id: ID + performer: String! + description: String! + time: AWSDateTime + stage: Stage @hasOne + } + type Stage + @model + @auth( + rules: [ + { allow: groups, groups: ["Admin"] } + { allow: private, operations: [read] } + ] + ) { + id: ID! + name: String! + }`; + try { + await awsS3Client.createBucket({ Bucket: BUCKET_NAME }).promise(); + } catch (e) { + throw Error(`Could not create bucket: ${e}`); + } + const authConfig: AppSyncAuthConfiguration = { + defaultAuthentication: { + authenticationType: 'AMAZON_COGNITO_USER_POOLS', + }, + additionalAuthenticationProviders: [], + }; + const transformer = new GraphQLTransform({ + authConfig, + transformers: [ + new ModelTransformer(), + new PrimaryKeyTransformer(), + new IndexTransformer(), + new HasOneTransformer(), + new AuthTransformer({ + authConfig, + addAwsIamAuthInOutputSchema: false, + }), + ], + }); + const userPoolResponse = await createUserPool(cognitoClient, `UserPool${STACK_NAME}`); + USER_POOL_ID = userPoolResponse.UserPool.Id; + const userPoolClientResponse = await createUserPoolClient(cognitoClient, USER_POOL_ID, `UserPool${STACK_NAME}`); + const userPoolClientId = userPoolClientResponse.UserPoolClient.ClientId; + try { + const out = transformer.transform(validSchema); + const finishedStack = await deploy( + customS3Client, + cf, + STACK_NAME, + out, + { AuthCognitoUserPoolId: USER_POOL_ID }, + LOCAL_FS_BUILD_DIR, + BUCKET_NAME, + S3_ROOT_DIR_KEY, + BUILD_TIMESTAMP, + ); + // Wait for any propagation to avoid random + // "The security token included in the request is invalid" errors + await new Promise(res => setTimeout(() => res(), 5000)); + + expect(finishedStack).toBeDefined(); + const getApiEndpoint = outputValueSelector(ResourceConstants.OUTPUTS.GraphQLAPIEndpointOutput); + const getApiKey = outputValueSelector(ResourceConstants.OUTPUTS.GraphQLAPIApiKeyOutput); + GRAPHQL_ENDPOINT = getApiEndpoint(finishedStack.Outputs); + + const apiKey = getApiKey(finishedStack.Outputs); + expect(apiKey).not.toBeTruthy(); + + // Verify we have all the details + expect(GRAPHQL_ENDPOINT).toBeTruthy(); + expect(USER_POOL_ID).toBeTruthy(); + expect(userPoolClientId).toBeTruthy(); + + // Configure Amplify, create users, and sign in + configureAmplify(USER_POOL_ID, userPoolClientId); + + await signupUser(USER_POOL_ID, USERNAME1, TMP_PASSWORD); + await signupUser(USER_POOL_ID, USERNAME2, TMP_PASSWORD); + await signupUser(USER_POOL_ID, USERNAME3, TMP_PASSWORD); + await createGroup(USER_POOL_ID, ADMIN_GROUP_NAME); + await createGroup(USER_POOL_ID, PARTICIPANT_GROUP_NAME); + await createGroup(USER_POOL_ID, WATCHER_GROUP_NAME); + await createGroup(USER_POOL_ID, DEVS_GROUP_NAME); + await createGroup(USER_POOL_ID, DEVS_ADMIN_GROUP_NAME); + await addUserToGroup(ADMIN_GROUP_NAME, USERNAME1, USER_POOL_ID); + await addUserToGroup(PARTICIPANT_GROUP_NAME, USERNAME1, USER_POOL_ID); + await addUserToGroup(WATCHER_GROUP_NAME, USERNAME1, USER_POOL_ID); + await addUserToGroup(DEVS_GROUP_NAME, USERNAME2, USER_POOL_ID); + await addUserToGroup(DEVS_ADMIN_GROUP_NAME, USERNAME3, USER_POOL_ID); + const authResAfterGroup: any = await authenticateUser(USERNAME1, TMP_PASSWORD, REAL_PASSWORD); + + const idToken = authResAfterGroup.getIdToken().getJwtToken(); + GRAPHQL_CLIENT_1 = new GraphQLClient(GRAPHQL_ENDPOINT, { Authorization: idToken }); + + const accessToken = authResAfterGroup.getAccessToken().getJwtToken(); + GRAPHQL_CLIENT_1_ACCESS = new GraphQLClient(GRAPHQL_ENDPOINT, { Authorization: accessToken }); + + const authRes2AfterGroup: any = await authenticateUser(USERNAME2, TMP_PASSWORD, REAL_PASSWORD); + const idToken2 = authRes2AfterGroup.getIdToken().getJwtToken(); + GRAPHQL_CLIENT_2 = new GraphQLClient(GRAPHQL_ENDPOINT, { Authorization: idToken2 }); + + const authRes3AfterGroup: any = await authenticateUser(USERNAME3, TMP_PASSWORD, REAL_PASSWORD); + const idToken3 = authRes3AfterGroup.getIdToken().getJwtToken(); + GRAPHQL_CLIENT_3 = new GraphQLClient(GRAPHQL_ENDPOINT, { Authorization: idToken3 }); + } catch (e) { + console.error(`Could not setup transformer ${e}`); + expect(true).toBe(false); + } + }); + + afterAll(async () => { + await cleanupStackAfterTest(BUCKET_NAME, STACK_NAME, cf, { cognitoClient, userPoolId: USER_POOL_ID }); + }); + + /** + * Test queries below + */ + test('Test createPost mutation', async () => { + const response = await GRAPHQL_CLIENT_1.query( + `mutation { + createPost(input: { title: "Hello, World!" }) { + id + title + createdAt + updatedAt + owner + } + }`, + {}, + ); + expect(response.data.createPost.id).toBeDefined(); + expect(response.data.createPost.title).toEqual('Hello, World!'); + expect(response.data.createPost.createdAt).toBeDefined(); + expect(response.data.createPost.updatedAt).toBeDefined(); + expect(response.data.createPost.owner).toEqual(USERNAME1); + + const response2 = await GRAPHQL_CLIENT_1_ACCESS.query( + `mutation { + createPost(input: { title: "Hello, World!" }) { + id + title + createdAt + updatedAt + owner + } + }`, + {}, + ); + expect(response2.data.createPost.id).toBeDefined(); + expect(response2.data.createPost.title).toEqual('Hello, World!'); + expect(response2.data.createPost.createdAt).toBeDefined(); + expect(response2.data.createPost.updatedAt).toBeDefined(); + expect(response2.data.createPost.owner).toEqual(USERNAME1); + }); + + test('Test getPost query when authorized', async () => { + const response = await GRAPHQL_CLIENT_1.query( + `mutation { + createPost(input: { title: "Hello, World!" }) { + id + title + createdAt + updatedAt + owner + } + }`, + {}, + ); + expect(response.data.createPost.id).toBeDefined(); + expect(response.data.createPost.title).toEqual('Hello, World!'); + expect(response.data.createPost.createdAt).toBeDefined(); + expect(response.data.createPost.updatedAt).toBeDefined(); + expect(response.data.createPost.owner).toEqual(USERNAME1); + const getResponse = await GRAPHQL_CLIENT_1.query( + `query { + getPost(id: "${response.data.createPost.id}") { + id + title + createdAt + updatedAt + owner + } + }`, + {}, + ); + expect(getResponse.data.getPost.id).toBeDefined(); + expect(getResponse.data.getPost.title).toEqual('Hello, World!'); + expect(getResponse.data.getPost.createdAt).toBeDefined(); + expect(getResponse.data.getPost.updatedAt).toBeDefined(); + expect(getResponse.data.getPost.owner).toEqual(USERNAME1); + + const getResponseAccess = await GRAPHQL_CLIENT_1_ACCESS.query( + `query { + getPost(id: "${response.data.createPost.id}") { + id + title + createdAt + updatedAt + owner + } + }`, + {}, + ); + expect(getResponseAccess.data.getPost.id).toBeDefined(); + expect(getResponseAccess.data.getPost.title).toEqual('Hello, World!'); + expect(getResponseAccess.data.getPost.createdAt).toBeDefined(); + expect(getResponseAccess.data.getPost.updatedAt).toBeDefined(); + expect(getResponseAccess.data.getPost.owner).toEqual(USERNAME1); + }); + + test('Test getPost query when not authorized', async () => { + const response = await GRAPHQL_CLIENT_1.query( + `mutation { + createPost(input: { title: "Hello, World!" }) { + id + title + createdAt + updatedAt + owner + } + }`, + {}, + ); + expect(response.data.createPost.id).toBeDefined(); + expect(response.data.createPost.title).toEqual('Hello, World!'); + expect(response.data.createPost.createdAt).toBeDefined(); + expect(response.data.createPost.updatedAt).toBeDefined(); + expect(response.data.createPost.owner).toBeDefined(); + const getResponse = await GRAPHQL_CLIENT_2.query( + `query { + getPost(id: "${response.data.createPost.id}") { + id + title + createdAt + updatedAt + owner + } + }`, + {}, + ); + expect(getResponse.data.getPost).toEqual(null); + expect(getResponse.errors.length).toEqual(1); + expect((getResponse.errors[0] as any).errorType).toEqual('Unauthorized'); + }); + + test('Test updatePost mutation when authorized', async () => { + const response = await GRAPHQL_CLIENT_1.query( + `mutation { + createPost(input: { title: "Hello, World!" }) { + id + title + createdAt + updatedAt + owner + } + }`, + {}, + ); + expect(response.data.createPost.id).toBeDefined(); + expect(response.data.createPost.title).toEqual('Hello, World!'); + expect(response.data.createPost.createdAt).toBeDefined(); + expect(response.data.createPost.updatedAt).toBeDefined(); + expect(response.data.createPost.owner).toEqual(USERNAME1); + const updateResponse = await GRAPHQL_CLIENT_1.query( + `mutation { + updatePost(input: { id: "${response.data.createPost.id}", title: "Bye, World!" }) { + id + title + createdAt + updatedAt + owner + } + }`, + {}, + ); + expect(updateResponse.data.updatePost.id).toEqual(response.data.createPost.id); + expect(updateResponse.data.updatePost.title).toEqual('Bye, World!'); + expect(updateResponse.data.updatePost.updatedAt > response.data.createPost.updatedAt).toEqual(true); + + const updateResponseAccess = await GRAPHQL_CLIENT_1_ACCESS.query( + `mutation { + updatePost(input: { id: "${response.data.createPost.id}", title: "Bye, World!" }) { + id + title + createdAt + updatedAt + owner + } + }`, + {}, + ); + expect(updateResponseAccess.data.updatePost.id).toEqual(response.data.createPost.id); + expect(updateResponseAccess.data.updatePost.title).toEqual('Bye, World!'); + expect(updateResponseAccess.data.updatePost.updatedAt > response.data.createPost.updatedAt).toEqual(true); + }); + + test('Test updatePost mutation when not authorized', async () => { + const response = await GRAPHQL_CLIENT_1.query( + `mutation { + createPost(input: { title: "Hello, World!" }) { + id + title + createdAt + updatedAt + owner + } + }`, + {}, + ); + expect(response.data.createPost.id).toBeDefined(); + expect(response.data.createPost.title).toEqual('Hello, World!'); + expect(response.data.createPost.createdAt).toBeDefined(); + expect(response.data.createPost.updatedAt).toBeDefined(); + expect(response.data.createPost.owner).toBeDefined(); + const updateResponse = await GRAPHQL_CLIENT_2.query( + `mutation { + updatePost(input: { id: "${response.data.createPost.id}", title: "Bye, World!" }) { + id + title + createdAt + updatedAt + owner + } + }`, + {}, + ); + expect(updateResponse.data.updatePost).toEqual(null); + expect(updateResponse.errors.length).toEqual(1); + expect((updateResponse.errors[0] as any).data).toBeNull(); + expect((updateResponse.errors[0] as any).errorType).toEqual('Unauthorized'); + }); + + test('Test deletePost mutation when authorized', async () => { + const response = await GRAPHQL_CLIENT_1.query( + `mutation { + createPost(input: { title: "Hello, World!" }) { + id + title + createdAt + updatedAt + owner + } + }`, + {}, + ); + expect(response.data.createPost.id).toBeDefined(); + expect(response.data.createPost.title).toEqual('Hello, World!'); + expect(response.data.createPost.createdAt).toBeDefined(); + expect(response.data.createPost.updatedAt).toBeDefined(); + expect(response.data.createPost.owner).toEqual(USERNAME1); + const deleteResponse = await GRAPHQL_CLIENT_1.query( + `mutation { + deletePost(input: { id: "${response.data.createPost.id}" }) { + id + } + }`, + {}, + ); + expect(deleteResponse.data.deletePost.id).toEqual(response.data.createPost.id); + + const responseAccess = await GRAPHQL_CLIENT_1_ACCESS.query( + `mutation { + createPost(input: { title: "Hello, World!" }) { + id + title + createdAt + updatedAt + owner + } + }`, + {}, + ); + expect(responseAccess.data.createPost.id).toBeDefined(); + expect(responseAccess.data.createPost.title).toEqual('Hello, World!'); + expect(responseAccess.data.createPost.createdAt).toBeDefined(); + expect(responseAccess.data.createPost.updatedAt).toBeDefined(); + expect(responseAccess.data.createPost.owner).toEqual(USERNAME1); + const deleteResponseAccess = await GRAPHQL_CLIENT_1_ACCESS.query( + `mutation { + deletePost(input: { id: "${responseAccess.data.createPost.id}" }) { + id + } + }`, + {}, + ); + expect(deleteResponseAccess.data.deletePost.id).toEqual(responseAccess.data.createPost.id); + }); + + test('Test deletePost mutation when not authorized', async () => { + const response = await GRAPHQL_CLIENT_1.query( + `mutation { + createPost(input: { title: "Hello, World!" }) { + id + title + createdAt + updatedAt + owner + } + }`, + {}, + ); + expect(response.data.createPost.id).toBeDefined(); + expect(response.data.createPost.title).toEqual('Hello, World!'); + expect(response.data.createPost.createdAt).toBeDefined(); + expect(response.data.createPost.updatedAt).toBeDefined(); + expect(response.data.createPost.owner).toEqual(USERNAME1); + const deleteResponse = await GRAPHQL_CLIENT_2.query( + `mutation { + deletePost(input: { id: "${response.data.createPost.id}" }) { + id + } + }`, + {}, + ); + expect(deleteResponse.data.deletePost).toEqual(null); + expect(deleteResponse.errors.length).toEqual(1); + expect((deleteResponse.errors[0] as any).data).toBeNull(); + expect((deleteResponse.errors[0] as any).errorType).toEqual('Unauthorized'); + }); + + test('Test listPosts query when authorized', async () => { + const firstPost = await GRAPHQL_CLIENT_1.query( + `mutation { + createPost(input: { title: "testing list" }) { + id + title + createdAt + updatedAt + owner + } + }`, + {}, + ); + expect(firstPost.data.createPost.id).toBeDefined(); + expect(firstPost.data.createPost.title).toEqual('testing list'); + expect(firstPost.data.createPost.createdAt).toBeDefined(); + expect(firstPost.data.createPost.updatedAt).toBeDefined(); + expect(firstPost.data.createPost.owner).toEqual(USERNAME1); + await GRAPHQL_CLIENT_2.query( + `mutation { + createPost(input: { title: "testing list" }) { + id + title + createdAt + updatedAt + owner + } + }`, + {}, + ); + // There are two posts but only 1 created by me. + const listResponse = await GRAPHQL_CLIENT_1.query( + `query { + listPosts(filter: { title: { eq: "testing list" } }, limit: 25) { + items { + id + } + } + }`, + {}, + ); + expect(listResponse.data.listPosts.items.length).toEqual(1); + + const listResponseAccess = await GRAPHQL_CLIENT_1_ACCESS.query( + `query { + listPosts(filter: { title: { eq: "testing list" } }, limit: 25) { + items { + id + } + } + }`, + {}, + ); + expect(listResponseAccess.data.listPosts.items.length).toEqual(1); + }); + + /** + * Static Group Auth + */ + test(`Test createSalary w/ Admin group protection authorized`, async () => { + const req = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createSalary(input: { wage: 10 }) { + id + wage + } + } + `, + {}, + ); + expect(req.data.createSalary.id).toBeDefined(); + expect(req.data.createSalary.wage).toEqual(10); + }); + + test(`Test update my own salary without admin permission`, async () => { + const req = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createSalary(input: { wage: 10 }) { + id + wage + } + } + `, + {}, + ); + + expect(req.data.createSalary.wage).toEqual(10); + const req2 = await GRAPHQL_CLIENT_2.query( + ` + mutation { + updateSalary(input: { id: "${req.data.createSalary.id}", wage: 14 }) { + id + wage + } + } + `, + {}, + ); + + expect(req2.data.updateSalary.wage).toEqual(14); + }); + + test(`Test updating someone else's salary as an admin`, async () => { + const req = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createSalary(input: { wage: 11 }) { + id + wage + } + } + `, + {}, + ); + + expect(req.data.createSalary.id).toBeDefined(); + expect(req.data.createSalary.wage).toEqual(11); + const req2 = await GRAPHQL_CLIENT_1.query( + ` + mutation { + updateSalary(input: { id: "${req.data.createSalary.id}", wage: 12 }) { + id + wage + } + } + `, + {}, + ); + + expect(req2.data.updateSalary.id).toEqual(req.data.createSalary.id); + expect(req2.data.updateSalary.wage).toEqual(12); + }); + + test(`Test updating someone else's salary when I am not admin.`, async () => { + const req = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createSalary(input: { wage: 13 }) { + id + wage + } + } + `, + {}, + ); + + expect(req.data.createSalary.id).toBeDefined(); + expect(req.data.createSalary.wage).toEqual(13); + const req2 = await GRAPHQL_CLIENT_2.query( + ` + mutation { + updateSalary(input: { id: "${req.data.createSalary.id}", wage: 14 }) { + id + wage + } + } + `, + {}, + ); + expect(req2.data.updateSalary).toEqual(null); + expect(req2.errors.length).toEqual(1); + expect((req2.errors[0] as any).data).toBeNull(); + expect((req2.errors[0] as any).errorType).toEqual('Unauthorized'); + }); + + test(`Test deleteSalary w/ Admin group protection authorized`, async () => { + const req = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createSalary(input: { wage: 15 }) { + id + wage + } + } + `, + {}, + ); + + expect(req.data.createSalary.id).toBeDefined(); + expect(req.data.createSalary.wage).toEqual(15); + const req2 = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteSalary(input: { id: "${req.data.createSalary.id}" }) { + id + wage + } + } + `, + {}, + ); + + expect(req2.data.deleteSalary.id).toEqual(req.data.createSalary.id); + expect(req2.data.deleteSalary.wage).toEqual(15); + }); + + test(`Test deleteSalary w/ Admin group protection not authorized`, async () => { + const req = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createSalary(input: { wage: 16 }) { + id + wage + } + } + `, + {}, + ); + + expect(req.data.createSalary.id).toBeDefined(); + expect(req.data.createSalary.wage).toEqual(16); + const req2 = await GRAPHQL_CLIENT_2.query( + ` + mutation { + deleteSalary(input: { id: "${req.data.createSalary.id}" }) { + id + wage + } + } + `, + {}, + ); + expect(req2.data.deleteSalary).toEqual(null); + expect(req2.errors.length).toEqual(1); + expect((req2.errors[0] as any).data).toBeNull(); + expect((req2.errors[0] as any).errorType).toEqual('Unauthorized'); + }); + + test(`Test and Admin can get a salary created by any user`, async () => { + const req = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createSalary(input: { wage: 15 }) { + id + wage + } + } + `, + {}, + ); + + expect(req.data.createSalary.id).toBeDefined(); + expect(req.data.createSalary.wage).toEqual(15); + const req2 = await GRAPHQL_CLIENT_1.query( + ` + query { + getSalary(id: "${req.data.createSalary.id}") { + id + wage + } + } + `, + {}, + ); + expect(req2.data.getSalary.id).toEqual(req.data.createSalary.id); + expect(req2.data.getSalary.wage).toEqual(15); + }); + + test(`Test owner can create and get a salary when not admin`, async () => { + const req = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createSalary(input: { wage: 15 }) { + id + wage + } + } + `, + {}, + ); + + expect(req.data.createSalary.id).toBeDefined(); + expect(req.data.createSalary.wage).toEqual(15); + const req2 = await GRAPHQL_CLIENT_2.query( + ` + query { + getSalary(id: "${req.data.createSalary.id}") { + id + wage + } + } + `, + {}, + ); + expect(req2.data.getSalary.id).toEqual(req.data.createSalary.id); + expect(req2.data.getSalary.wage).toEqual(15); + }); + + test(`Test getSalary w/ Admin group protection not authorized`, async () => { + const req = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createSalary(input: { wage: 16 }) { + id + wage + } + } + `, + {}, + ); + + expect(req.data.createSalary.id).toBeDefined(); + expect(req.data.createSalary.wage).toEqual(16); + const req2 = await GRAPHQL_CLIENT_2.query( + ` + query { + getSalary(id: "${req.data.createSalary.id}") { + id + wage + } + } + `, + {}, + ); + expect(req2.data.getSalary).toEqual(null); + expect(req2.errors.length).toEqual(1); + expect((req2.errors[0] as any).errorType).toEqual('Unauthorized'); + }); + + test(`Test listSalaries w/ Admin group protection authorized`, async () => { + const req = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createSalary(input: { wage: 101 }) { + id + wage + } + } + `, + {}, + ); + + expect(req.data.createSalary.id).toBeDefined(); + expect(req.data.createSalary.wage).toEqual(101); + const req2 = await GRAPHQL_CLIENT_1.query( + ` + query { + listSalaries(filter: { wage: { eq: 101 }}) { + items { + id + wage + } + } + } + `, + {}, + ); + expect(req2.data.listSalaries.items.length).toEqual(1); + expect(req2.data.listSalaries.items[0].id).toEqual(req.data.createSalary.id); + expect(req2.data.listSalaries.items[0].wage).toEqual(101); + }); + + test(`Test listSalaries w/ Admin group protection not authorized`, async () => { + const req = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createSalary(input: { wage: 102 }) { + id + wage + } + } + `, + {}, + ); + + expect(req.data.createSalary.id).toBeDefined(); + expect(req.data.createSalary.wage).toEqual(102); + const req2 = await GRAPHQL_CLIENT_2.query( + ` + query { + listSalaries(filter: { wage: { eq: 102 }}) { + items { + id + wage + } + } + } + `, + {}, + ); + expect(req2.data.listSalaries.items).toEqual([]); + }); + + /** + * Dynamic Group Auth + */ + test(`Test createManyGroupProtected w/ dynamic group protection authorized`, async () => { + const req = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createManyGroupProtected(input: { value: 10, groups: ["Admin"] }) { + id + value + groups + } + } + `, + {}, + ); + + expect(req.data.createManyGroupProtected.id).toBeDefined(); + expect(req.data.createManyGroupProtected.value).toEqual(10); + expect(req.data.createManyGroupProtected.groups).toEqual(['Admin']); + }); + + test(`Test createManyGroupProtected w/ dynamic group protection when not authorized`, async () => { + const req = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createManyGroupProtected(input: { value: 10, groups: ["Admin"] }) { + id + value + groups + } + } + `, + {}, + ); + + expect(req.data.createManyGroupProtected).toEqual(null); + expect(req.errors.length).toEqual(1); + expect((req.errors[0] as any).errorType).toEqual('Unauthorized'); + }); + + test(`Test updateSingleGroupProtected when user is not authorized but has a group that is a substring of the allowed group`, async () => { + const req = await GRAPHQL_CLIENT_3.query( + `mutation { + createSingleGroupProtected(input: { value: 11, group: "Devs-Admin" }) { + id + value + group + } + } + `, + {}, + ); + + const req2 = await GRAPHQL_CLIENT_2.query( + `mutation { + updateSingleGroupProtected(input: {id: "${req.data.createSingleGroupProtected.id}", value: 5 }) { + id + value + group + } + } + `, + {}, + ); + + const req3 = await GRAPHQL_CLIENT_3.query( + `query { + getSingleGroupProtected(id: "${req.data.createSingleGroupProtected.id}") { + id + value + group + } + } + `, + {}, + ); + + expect(req.data.createSingleGroupProtected.value).toEqual(11); + expect(req.data.createSingleGroupProtected.value).toEqual(req3.data.getSingleGroupProtected.value); + expect((req2.errors[0] as any).data).toBeNull(); + expect((req2.errors[0] as any).errorType).toEqual('Unauthorized'); + }); + + test(`Test createSingleGroupProtected w/ dynamic group protection authorized`, async () => { + const req = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createSingleGroupProtected(input: { value: 10, group: "Admin" }) { + id + value + group + } + } + `, + {}, + ); + + expect(req.data.createSingleGroupProtected.id).toBeDefined(); + expect(req.data.createSingleGroupProtected.value).toEqual(10); + expect(req.data.createSingleGroupProtected.group).toEqual('Admin'); + }); + + test(`Test createSingleGroupProtected w/ dynamic group protection when not authorized`, async () => { + const req = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createSingleGroupProtected(input: { value: 10, group: "Admin" }) { + id + value + group + } + } + `, + {}, + ); + + expect(req.data.createSingleGroupProtected).toEqual(null); + expect(req.errors.length).toEqual(1); + expect((req.errors[0] as any).errorType).toEqual('Unauthorized'); + }); + + test(`Test listPWProtecteds when the user is authorized.`, async () => { + const req = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createPWProtected(input: { content: "Foobie", participants: "${PARTICIPANT_GROUP_NAME}", watchers: "${WATCHER_GROUP_NAME}" }) { + id + content + participants + watchers + } + } + `, + {}, + ); + + expect(req.data.createPWProtected).toBeTruthy(); + + const uReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + updatePWProtected(input: { id: "${req.data.createPWProtected.id}", content: "Foobie2" }) { + id + content + participants + watchers + } + } + `, + {}, + ); + expect(uReq.data.updatePWProtected).toBeTruthy(); + + const req2 = await GRAPHQL_CLIENT_1.query( + ` + query { + listPWProtecteds { + items { + id + content + participants + watchers + } + nextToken + } + } + `, + {}, + ); + expect(req2.data.listPWProtecteds.items.length).toEqual(1); + expect(req2.data.listPWProtecteds.items[0].id).toEqual(req.data.createPWProtected.id); + expect(req2.data.listPWProtecteds.items[0].content).toEqual('Foobie2'); + + const req3 = await GRAPHQL_CLIENT_1.query( + ` + query { + getPWProtected(id: "${req.data.createPWProtected.id}") { + id + content + participants + watchers + } + } + `, + {}, + ); + + expect(req3.data.getPWProtected).toBeTruthy(); + + const dReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deletePWProtected(input: { id: "${req.data.createPWProtected.id}" }) { + id + content + participants + watchers + } + } + `, + {}, + ); + expect(dReq.data.deletePWProtected).toBeTruthy(); + }); + + test(`Test listPWProtecteds when groups is null in dynamodb.`, async () => { + const req = await GRAPHQL_CLIENT_2.query( + `mutation { + createPWProtected(input: { content: "Foobie" }) { + id + content + participants + watchers + } + } + `, + {}, + ); + + expect(req.data.createPWProtected).toBeTruthy(); + + const req2 = await GRAPHQL_CLIENT_1.query( + ` + query { + listPWProtecteds { + items { + id + content + participants + watchers + } + nextToken + } + } + `, + {}, + ); + expect(req2.data.listPWProtecteds.items.length).toEqual(0); + + const req3 = await GRAPHQL_CLIENT_1.query( + ` + query { + getPWProtected(id: "${req.data.createPWProtected.id}") { + id + content + participants + watchers + } + } + `, + {}, + ); + + expect(req3.data.getPWProtected).toEqual(null); + expect(req3.errors.length).toEqual(1); + expect((req3.errors[0] as any).errorType).toEqual('Unauthorized'); + }); + + test(`Test Protecteds when the user is not authorized.`, async () => { + const req = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createPWProtected(input: { content: "Barbie", participants: "${PARTICIPANT_GROUP_NAME}", watchers: "${WATCHER_GROUP_NAME}" }) { + id + content + participants + watchers + } + } + `, + {}, + ); + + expect(req.data.createPWProtected).toBeTruthy(); + + const req2 = await GRAPHQL_CLIENT_3.query( + ` + query { + listPWProtecteds { + items { + id + content + participants + watchers + } + nextToken + } + } + `, + {}, + ); + + expect(req2.data.listPWProtecteds.items.length).toEqual(0); + expect(req2.data.listPWProtecteds.nextToken).toBeNull(); + + const uReq = await GRAPHQL_CLIENT_3.query( + ` + mutation { + updatePWProtected(input: { id: "${req.data.createPWProtected.id}", content: "Foobie2" }) { + id + content + participants + watchers + } + } + `, + {}, + ); + expect(uReq.data.updatePWProtected).toBeNull(); + + const req3 = await GRAPHQL_CLIENT_3.query( + ` + query { + getPWProtected(id: "${req.data.createPWProtected.id}") { + id + content + participants + watchers + } + } + `, + {}, + ); + + expect(req3.data.getPWProtected).toBeNull(); + + const dReq = await GRAPHQL_CLIENT_3.query( + ` + mutation { + deletePWProtected(input: { id: "${req.data.createPWProtected.id}" }) { + id + content + participants + watchers + } + } + `, + {}, + ); + expect(dReq.data.deletePWProtected).toBeNull(); + + // The record should still exist after delete. + const getReq = await GRAPHQL_CLIENT_1.query( + ` + query { + getPWProtected(id: "${req.data.createPWProtected.id}") { + id + content + participants + watchers + } + } + `, + {}, + ); + expect(getReq.data.getPWProtected).toBeTruthy(); + }); + + test(`Test creating, updating, and deleting an admin note as an admin`, async () => { + const req = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAdminNote(input: { content: "Hello" }) { + id + content + } + } + `, + {}, + ); + + expect(req.data.createAdminNote.id).toBeDefined(); + expect(req.data.createAdminNote.content).toEqual('Hello'); + const req2 = await GRAPHQL_CLIENT_1.query( + ` + mutation { + updateAdminNote(input: { id: "${req.data.createAdminNote.id}", content: "Hello 2" }) { + id + content + } + } + `, + {}, + ); + + expect(req2.data.updateAdminNote.id).toEqual(req.data.createAdminNote.id); + expect(req2.data.updateAdminNote.content).toEqual('Hello 2'); + const req3 = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAdminNote(input: { id: "${req.data.createAdminNote.id}" }) { + id + content + } + } + `, + {}, + ); + + expect(req3.data.deleteAdminNote.id).toEqual(req.data.createAdminNote.id); + expect(req3.data.deleteAdminNote.content).toEqual('Hello 2'); + }); + + test(`Test creating, updating, and deleting an admin note as a non admin`, async () => { + const adminReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAdminNote(input: { content: "Hello" }) { + id + content + } + } + `, + {}, + ); + expect(adminReq.data.createAdminNote.id).toBeDefined(); + expect(adminReq.data.createAdminNote.content).toEqual('Hello'); + + const req = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createAdminNote(input: { content: "Hello" }) { + id + content + } + } + `, + {}, + ); + + expect(req.errors.length).toEqual(1); + expect((req.errors[0] as any).errorType).toEqual('Unauthorized'); + + const req2 = await GRAPHQL_CLIENT_2.query( + ` + mutation { + updateAdminNote(input: { id: "${adminReq.data.createAdminNote.id}", content: "Hello 2" }) { + id + content + } + } + `, + {}, + ); + + expect(req2.errors.length).toEqual(1); + expect((req2.errors[0] as any).errorType).toEqual('Unauthorized'); + + const req3 = await GRAPHQL_CLIENT_2.query( + ` + mutation { + deleteAdminNote(input: { id: "${adminReq.data.createAdminNote.id}" }) { + id + content + } + } + `, + {}, + ); + + expect(req3.errors.length).toEqual(1); + expect((req3.errors[0] as any).errorType).toEqual('Unauthorized'); + }); + + /** + * Get Query Tests + */ + + test(`Test getAllThree as admin.`, async () => { + const ownedBy2 = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAllThree(input: { + owner: "user2@test.com" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedBy2.data.createAllThree).toBeTruthy(); + + const fetchOwnedBy2AsAdmin = await GRAPHQL_CLIENT_1.query( + ` + query { + getAllThree(id: "${ownedBy2.data.createAllThree.id}") { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(fetchOwnedBy2AsAdmin.data.getAllThree).toBeTruthy(); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedBy2.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedBy2.data.createAllThree.id); + }); + + test(`Test getAllThree as owner.`, async () => { + const ownedBy2 = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAllThree(input: { + owner: "user2@test.com" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedBy2.data.createAllThree).toBeTruthy(); + + const fetchOwnedBy2AsOwner = await GRAPHQL_CLIENT_2.query( + ` + query { + getAllThree(id: "${ownedBy2.data.createAllThree.id}") { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(fetchOwnedBy2AsOwner.data.getAllThree).toBeTruthy(); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedBy2.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedBy2.data.createAllThree.id); + }); + + test(`Test getAllThree as one of a set of editors.`, async () => { + const ownedBy2 = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAllThree(input: { + editors: ["user2@test.com"] + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedBy2.data.createAllThree).toBeTruthy(); + + const fetchOwnedBy2AsEditor = await GRAPHQL_CLIENT_2.query( + ` + query { + getAllThree(id: "${ownedBy2.data.createAllThree.id}") { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(fetchOwnedBy2AsEditor.data.getAllThree).toBeTruthy(); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedBy2.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedBy2.data.createAllThree.id); + }); + + test(`Test getAllThree as a member of a dynamic group.`, async () => { + const ownedByAdmins = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAllThree(input: { + groups: ["Devs"] + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByAdmins.data.createAllThree).toBeTruthy(); + + const fetchOwnedByAdminsAsAdmin = await GRAPHQL_CLIENT_2.query( + ` + query { + getAllThree(id: "${ownedByAdmins.data.createAllThree.id}") { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(fetchOwnedByAdminsAsAdmin.data.getAllThree).toBeTruthy(); + + const fetchOwnedByAdminsAsNonAdmin = await GRAPHQL_CLIENT_3.query( + ` + query { + getAllThree(id: "${ownedByAdmins.data.createAllThree.id}") { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(fetchOwnedByAdminsAsNonAdmin.errors.length).toEqual(1); + expect((fetchOwnedByAdminsAsNonAdmin.errors[0] as any).errorType).toEqual('Unauthorized'); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedByAdmins.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedByAdmins.data.createAllThree.id); + }); + + test(`Test getAllThree as a member of the alternative group.`, async () => { + const ownedByAdmins = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAllThree(input: { + alternativeGroup: "Devs" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByAdmins.data.createAllThree).toBeTruthy(); + + const fetchOwnedByAdminsAsAdmin = await GRAPHQL_CLIENT_2.query( + ` + query { + getAllThree(id: "${ownedByAdmins.data.createAllThree.id}") { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(fetchOwnedByAdminsAsAdmin.data.getAllThree).toBeTruthy(); + + const fetchOwnedByAdminsAsNonAdmin = await GRAPHQL_CLIENT_3.query( + ` + query { + getAllThree(id: "${ownedByAdmins.data.createAllThree.id}") { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(fetchOwnedByAdminsAsNonAdmin.errors.length).toEqual(1); + expect((fetchOwnedByAdminsAsNonAdmin.errors[0] as any).errorType).toEqual('Unauthorized'); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedByAdmins.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedByAdmins.data.createAllThree.id); + }); + + /** + * List Query Tests + */ + + test(`Test listAllThrees as admin.`, async () => { + const ownedBy2 = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAllThree(input: { + owner: "user2@test.com" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedBy2.data.createAllThree).toBeTruthy(); + + const fetchOwnedBy2AsAdmin = await GRAPHQL_CLIENT_1.query( + ` + query { + listAllThrees { + items { + id + owner + editors + groups + alternativeGroup + } + } + } + `, + {}, + ); + expect(fetchOwnedBy2AsAdmin.data.listAllThrees.items).toHaveLength(1); + expect(fetchOwnedBy2AsAdmin.data.listAllThrees.items[0].id).toEqual(ownedBy2.data.createAllThree.id); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedBy2.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedBy2.data.createAllThree.id); + }); + + test(`Test listAllThrees as owner.`, async () => { + const ownedBy2 = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAllThree(input: { + owner: "user2@test.com" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedBy2.data.createAllThree).toBeTruthy(); + + const fetchOwnedBy2AsOwner = await GRAPHQL_CLIENT_2.query( + ` + query { + listAllThrees { + items { + id + owner + editors + groups + alternativeGroup + } + } + } + `, + {}, + ); + expect(fetchOwnedBy2AsOwner.data.listAllThrees.items).toHaveLength(1); + expect(fetchOwnedBy2AsOwner.data.listAllThrees.items[0].id).toEqual(ownedBy2.data.createAllThree.id); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedBy2.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedBy2.data.createAllThree.id); + }); + + test(`Test listAllThrees as one of a set of editors.`, async () => { + const ownedBy2 = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAllThree(input: { + editors: ["user2@test.com"] + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedBy2.data.createAllThree).toBeTruthy(); + + const fetchOwnedBy2AsEditor = await GRAPHQL_CLIENT_2.query( + ` + query { + listAllThrees { + items { + id + owner + editors + groups + alternativeGroup + } + } + } + `, + {}, + ); + expect(fetchOwnedBy2AsEditor.data.listAllThrees.items).toHaveLength(1); + expect(fetchOwnedBy2AsEditor.data.listAllThrees.items[0].id).toEqual(ownedBy2.data.createAllThree.id); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedBy2.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedBy2.data.createAllThree.id); + }); + + test(`Test listAllThrees as a member of a dynamic group.`, async () => { + const ownedByAdmins = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAllThree(input: { + groups: ["Devs"] + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByAdmins.data.createAllThree).toBeTruthy(); + + const fetchOwnedByAdminsAsAdmin = await GRAPHQL_CLIENT_2.query( + ` + query { + listAllThrees { + items { + id + owner + editors + groups + alternativeGroup + } + } + } + `, + {}, + ); + expect(fetchOwnedByAdminsAsAdmin.data.listAllThrees.items).toHaveLength(1); + expect(fetchOwnedByAdminsAsAdmin.data.listAllThrees.items[0].id).toEqual(ownedByAdmins.data.createAllThree.id); + + const fetchOwnedByAdminsAsNonAdmin = await GRAPHQL_CLIENT_3.query( + ` + query { + listAllThrees { + items { + id + owner + editors + groups + alternativeGroup + } + } + } + `, + {}, + ); + expect(fetchOwnedByAdminsAsNonAdmin.data.listAllThrees.items).toHaveLength(0); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedByAdmins.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedByAdmins.data.createAllThree.id); + }); + + test(`Test getAllThree as a member of the alternative group.`, async () => { + const ownedByAdmins = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAllThree(input: { + alternativeGroup: "Devs" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByAdmins.data.createAllThree).toBeTruthy(); + + const fetchOwnedByAdminsAsAdmin = await GRAPHQL_CLIENT_2.query( + ` + query { + listAllThrees { + items { + id + owner + editors + groups + alternativeGroup + } + } + } + `, + {}, + ); + expect(fetchOwnedByAdminsAsAdmin.data.listAllThrees.items).toHaveLength(1); + expect(fetchOwnedByAdminsAsAdmin.data.listAllThrees.items[0].id).toEqual(ownedByAdmins.data.createAllThree.id); + + const fetchOwnedByAdminsAsNonAdmin = await GRAPHQL_CLIENT_3.query( + ` + query { + listAllThrees { + items { + id + owner + editors + groups + alternativeGroup + } + } + } + `, + {}, + ); + expect(fetchOwnedByAdminsAsNonAdmin.data.listAllThrees.items).toHaveLength(0); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedByAdmins.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedByAdmins.data.createAllThree.id); + }); + + /** + * Create Mutation Tests + */ + + test(`Test createAllThree as admin.`, async () => { + const ownedBy2 = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAllThree(input: { + owner: "user2@test.com" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedBy2.data.createAllThree).toBeTruthy(); + // set by input + expect(ownedBy2.data.createAllThree.owner).toEqual('user2@test.com'); + // not auto filled as the admin condition was met + expect(ownedBy2.data.createAllThree.editors).toBeNull(); + expect(ownedBy2.data.createAllThree.groups).toBeNull(); + expect(ownedBy2.data.createAllThree.alternativeGroup).toBeNull(); + + const ownedBy2NoEditors = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAllThree(input: { + owner: "user2@test.com", + editors: [] + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedBy2NoEditors.data.createAllThree).toBeTruthy(); + // set by input + expect(ownedBy2NoEditors.data.createAllThree.owner).toEqual('user2@test.com'); + // set by input + expect(ownedBy2NoEditors.data.createAllThree.editors).toHaveLength(0); + expect(ownedBy2NoEditors.data.createAllThree.groups).toBeNull(); + expect(ownedBy2NoEditors.data.createAllThree.alternativeGroup).toBeNull(); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedBy2.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedBy2.data.createAllThree.id); + + const deleteReq2 = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedBy2NoEditors.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq2.data.deleteAllThree.id).toEqual(ownedBy2NoEditors.data.createAllThree.id); + }); + + test(`Test createAllThree as owner.`, async () => { + const ownedBy2 = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createAllThree(input: { + owner: "user2@test.com", + editors: [] + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedBy2.data.createAllThree).toBeTruthy(); + expect(ownedBy2.data.createAllThree.owner).toEqual('user2@test.com'); + expect(ownedBy2.data.createAllThree.editors).toHaveLength(0); + expect(ownedBy2.data.createAllThree.groups).toBeNull(); + expect(ownedBy2.data.createAllThree.alternativeGroup).toBeNull(); + + const ownedBy1 = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createAllThree(input: { + owner: "user1@test.com", + editors: [] + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedBy1.errors.length).toEqual(1); + expect((ownedBy1.errors[0] as any).errorType).toEqual('Unauthorized'); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedBy2.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedBy2.data.createAllThree.id); + }); + + test(`Test createAllThree as one of a set of editors.`, async () => { + const ownedBy2 = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createAllThree(input: { + owner: null, + editors: ["user2@test.com"] + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedBy2.data.createAllThree).toBeTruthy(); + expect(ownedBy2.data.createAllThree.owner).toBeNull(); + expect(ownedBy2.data.createAllThree.editors[0]).toEqual('user2@test.com'); + expect(ownedBy2.data.createAllThree.groups).toBeNull(); + expect(ownedBy2.data.createAllThree.alternativeGroup).toBeNull(); + + const ownedBy2WithDefaultOwner = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createAllThree(input: { + editors: ["user2@test.com"] + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedBy2WithDefaultOwner.data.createAllThree).toBeTruthy(); + expect(ownedBy2WithDefaultOwner.data.createAllThree.owner).toEqual('user2@test.com'); + expect(ownedBy2WithDefaultOwner.data.createAllThree.editors[0]).toEqual('user2@test.com'); + expect(ownedBy2WithDefaultOwner.data.createAllThree.groups).toBeNull(); + expect(ownedBy2WithDefaultOwner.data.createAllThree.alternativeGroup).toBeNull(); + + const ownedByEditorsUnauthed = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createAllThree(input: { + owner: null, + editors: ["user1@test.com"] + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByEditorsUnauthed.errors.length).toEqual(1); + expect((ownedByEditorsUnauthed.errors[0] as any).errorType).toEqual('Unauthorized'); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedBy2.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedBy2.data.createAllThree.id); + + const deleteReq2 = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedBy2WithDefaultOwner.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq2.data.deleteAllThree.id).toEqual(ownedBy2WithDefaultOwner.data.createAllThree.id); + }); + + test(`Test createAllThree as a member of a dynamic group.`, async () => { + const ownedByDevs = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createAllThree(input: { + owner: null, + editors: [], + groups: ["Devs"] + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByDevs.data.createAllThree).toBeTruthy(); + expect(ownedByDevs.data.createAllThree.owner).toBeNull(); + expect(ownedByDevs.data.createAllThree.editors).toHaveLength(0); + expect(ownedByDevs.data.createAllThree.groups[0]).toEqual('Devs'); + expect(ownedByDevs.data.createAllThree.alternativeGroup).toBeNull(); + + const ownedByAdminsUnauthed = await GRAPHQL_CLIENT_3.query( + ` + mutation { + createAllThree(input: { + owner: null, + editors: [], + groups: ["Devs"] + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByAdminsUnauthed.errors.length).toEqual(1); + expect((ownedByAdminsUnauthed.errors[0] as any).errorType).toEqual('Unauthorized'); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedByDevs.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedByDevs.data.createAllThree.id); + }); + + test(`Test createAllThree as a member of the alternative group.`, async () => { + const ownedByAdmins = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createAllThree(input: { + owner: null, + editors: [], + alternativeGroup: "Devs" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByAdmins.data.createAllThree).toBeTruthy(); + expect(ownedByAdmins.data.createAllThree.owner).toBeNull(); + expect(ownedByAdmins.data.createAllThree.editors).toHaveLength(0); + expect(ownedByAdmins.data.createAllThree.alternativeGroup).toEqual('Devs'); + + const ownedByAdminsUnauthed = await GRAPHQL_CLIENT_3.query( + ` + mutation { + createAllThree(input: { + owner: null, + editors: [], + alternativeGroup: "Admin" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByAdminsUnauthed.errors.length).toEqual(1); + expect((ownedByAdminsUnauthed.errors[0] as any).errorType).toEqual('Unauthorized'); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedByAdmins.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedByAdmins.data.createAllThree.id); + }); + + /** + * Update Mutation Tests + */ + + test(`Test updateAllThree and deleteAllThree as admin.`, async () => { + const ownedBy2 = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAllThree(input: { + editors: [] + owner: "user2@test.com" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedBy2.data.createAllThree).toBeTruthy(); + // set by input + expect(ownedBy2.data.createAllThree.owner).toEqual('user2@test.com'); + // auto filled as logged in user. + expect(ownedBy2.data.createAllThree.editors).toHaveLength(0); + expect(ownedBy2.data.createAllThree.groups).toBeNull(); + expect(ownedBy2.data.createAllThree.alternativeGroup).toBeNull(); + + const ownedByTwoUpdate = await GRAPHQL_CLIENT_1.query( + ` + mutation { + updateAllThree(input: { + id: "${ownedBy2.data.createAllThree.id}", + alternativeGroup: "Devs" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByTwoUpdate.data.updateAllThree).toBeTruthy(); + // set by input + expect(ownedByTwoUpdate.data.updateAllThree.owner).toEqual('user2@test.com'); + // set by input + expect(ownedByTwoUpdate.data.updateAllThree.editors).toHaveLength(0); + expect(ownedByTwoUpdate.data.updateAllThree.groups).toBeNull(); + expect(ownedByTwoUpdate.data.updateAllThree.alternativeGroup).toEqual('Devs'); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedBy2.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedBy2.data.createAllThree.id); + }); + + test(`Test updateAllThree and deleteAllThree as owner.`, async () => { + const ownedBy2 = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createAllThree(input: { + owner: "user2@test.com", + editors: [] + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedBy2.data.createAllThree).toBeTruthy(); + expect(ownedBy2.data.createAllThree.owner).toEqual('user2@test.com'); + expect(ownedBy2.data.createAllThree.editors).toHaveLength(0); + expect(ownedBy2.data.createAllThree.groups).toBeNull(); + expect(ownedBy2.data.createAllThree.alternativeGroup).toBeNull(); + + const ownedBy2Update = await GRAPHQL_CLIENT_2.query( + ` + mutation { + updateAllThree(input: { + id: "${ownedBy2.data.createAllThree.id}", + alternativeGroup: "Devs" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedBy2Update.data.updateAllThree).toBeTruthy(); + // set by input + expect(ownedBy2Update.data.updateAllThree.owner).toEqual('user2@test.com'); + // set by input + expect(ownedBy2Update.data.updateAllThree.editors).toHaveLength(0); + expect(ownedBy2Update.data.updateAllThree.groups).toBeNull(); + expect(ownedBy2Update.data.updateAllThree.alternativeGroup).toEqual('Devs'); + + const deleteReq = await GRAPHQL_CLIENT_2.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedBy2.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedBy2.data.createAllThree.id); + }); + + test(`Test updateAllThree and deleteAllThree as one of a set of editors.`, async () => { + const ownedBy2 = await GRAPHQL_CLIENT_2.query( + ` + mutation { + createAllThree(input: { + owner: null, + editors: ["user2@test.com"] + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedBy2.data.createAllThree).toBeTruthy(); + expect(ownedBy2.data.createAllThree.owner).toBeNull(); + expect(ownedBy2.data.createAllThree.editors[0]).toEqual('user2@test.com'); + expect(ownedBy2.data.createAllThree.groups).toBeNull(); + expect(ownedBy2.data.createAllThree.alternativeGroup).toBeNull(); + + const ownedByUpdate = await GRAPHQL_CLIENT_2.query( + ` + mutation { + updateAllThree(input: { + id: "${ownedBy2.data.createAllThree.id}", + alternativeGroup: "Devs" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByUpdate.data.updateAllThree).toBeTruthy(); + // set by input + expect(ownedByUpdate.data.updateAllThree.owner).toBeNull(); + // set by input + expect(ownedByUpdate.data.updateAllThree.editors[0]).toEqual('user2@test.com'); + expect(ownedByUpdate.data.updateAllThree.groups).toBeNull(); + expect(ownedByUpdate.data.updateAllThree.alternativeGroup).toEqual('Devs'); + + const deleteReq = await GRAPHQL_CLIENT_2.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedBy2.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedBy2.data.createAllThree.id); + }); + + test(`Test updateAllThree and deleteAllThree as a member of a dynamic group.`, async () => { + const ownedByDevs = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAllThree(input: { + owner: null, + editors: [], + groups: ["Devs"] + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByDevs.data.createAllThree).toBeTruthy(); + expect(ownedByDevs.data.createAllThree.owner).toBeNull(); + expect(ownedByDevs.data.createAllThree.editors).toHaveLength(0); + expect(ownedByDevs.data.createAllThree.groups[0]).toEqual('Devs'); + expect(ownedByDevs.data.createAllThree.alternativeGroup).toBeNull(); + + const ownedByUpdate = await GRAPHQL_CLIENT_2.query( + ` + mutation { + updateAllThree(input: { + id: "${ownedByDevs.data.createAllThree.id}", + alternativeGroup: "Devs" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByUpdate.data.updateAllThree).toBeTruthy(); + // set by input + expect(ownedByUpdate.data.updateAllThree.owner).toBeNull(); + // set by input + expect(ownedByUpdate.data.updateAllThree.editors).toHaveLength(0); + expect(ownedByUpdate.data.updateAllThree.groups[0]).toEqual('Devs'); + expect(ownedByUpdate.data.updateAllThree.alternativeGroup).toEqual('Devs'); + + const ownedByAdminsUnauthed = await GRAPHQL_CLIENT_3.query( + ` + mutation { + createAllThree(input: { + owner: null, + editors: [], + groups: ["Devs"] + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByAdminsUnauthed.errors.length).toEqual(1); + expect((ownedByAdminsUnauthed.errors[0] as any).errorType).toEqual('Unauthorized'); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedByDevs.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedByDevs.data.createAllThree.id); + }); + + test(`Test updateAllThree and deleteAllThree as a member of the alternative group.`, async () => { + const ownedByDevs = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAllThree(input: { + owner: null, + editors: [], + alternativeGroup: "Devs" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByDevs.data.createAllThree).toBeTruthy(); + expect(ownedByDevs.data.createAllThree.owner).toBeNull(); + expect(ownedByDevs.data.createAllThree.editors).toHaveLength(0); + expect(ownedByDevs.data.createAllThree.alternativeGroup).toEqual('Devs'); + + const ownedByUpdate = await GRAPHQL_CLIENT_2.query( + ` + mutation { + updateAllThree(input: { + id: "${ownedByDevs.data.createAllThree.id}", + alternativeGroup: "Admin" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByUpdate.data.updateAllThree).toBeTruthy(); + // set by input + expect(ownedByUpdate.data.updateAllThree.owner).toBeNull(); + // set by input + expect(ownedByUpdate.data.updateAllThree.editors).toHaveLength(0); + expect(ownedByUpdate.data.updateAllThree.groups).toBeNull(); + expect(ownedByUpdate.data.updateAllThree.alternativeGroup).toEqual('Admin'); + + const ownedByAdminsUnauthed = await GRAPHQL_CLIENT_2.query( + ` + mutation { + updateAllThree(input: { + id: "${ownedByDevs.data.createAllThree.id}", + alternativeGroup: "Dev" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByAdminsUnauthed.errors.length).toEqual(1); + expect((ownedByAdminsUnauthed.errors[0] as any).data).toBeNull(); + expect((ownedByAdminsUnauthed.errors[0] as any).errorType).toEqual('Unauthorized'); + + const ownedByDevs2 = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createAllThree(input: { + owner: null, + editors: [], + alternativeGroup: "Devs" + }) { + id + owner + editors + groups + alternativeGroup + } + } + `, + {}, + ); + expect(ownedByDevs2.data.createAllThree).toBeTruthy(); + expect(ownedByDevs2.data.createAllThree.owner).toBeNull(); + expect(ownedByDevs2.data.createAllThree.editors).toHaveLength(0); + expect(ownedByDevs2.data.createAllThree.alternativeGroup).toEqual('Devs'); + + const deleteReq2 = await GRAPHQL_CLIENT_2.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedByDevs2.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq2.data.deleteAllThree.id).toEqual(ownedByDevs2.data.createAllThree.id); + + const deleteReq = await GRAPHQL_CLIENT_1.query( + ` + mutation { + deleteAllThree(input: { id: "${ownedByDevs.data.createAllThree.id}" }) { + id + } + } + `, + {}, + ); + expect(deleteReq.data.deleteAllThree.id).toEqual(ownedByDevs.data.createAllThree.id); + }); + + test(`Test createTestIdentity as admin.`, async () => { + const ownedBy2 = await GRAPHQL_CLIENT_1.query( + ` + mutation { + createTestIdentity(input: { + title: "Test title" + }) { + id + title + owner + } + } + `, + {}, + ); + expect(ownedBy2.data.createTestIdentity).toBeTruthy(); + expect(ownedBy2.data.createTestIdentity.title).toEqual('Test title'); + expect(ownedBy2.data.createTestIdentity.owner.slice(0, 19)).toEqual('https://cognito-idp'); + + // user 2 should be able to update because they share the same issuer. + const update = await GRAPHQL_CLIENT_3.query( + ` + mutation { + updateTestIdentity(input: { + id: "${ownedBy2.data.createTestIdentity.id}", + title: "Test title update" + }) { + id + title + owner + } + } + `, + {}, + ); + expect(update.data.updateTestIdentity).toBeTruthy(); + expect(update.data.updateTestIdentity.title).toEqual('Test title update'); + expect(update.data.updateTestIdentity.owner.slice(0, 19)).toEqual('https://cognito-idp'); + + // user 2 should be able to get because they share the same issuer. + const getReq = await GRAPHQL_CLIENT_3.query( + ` + query { + getTestIdentity(id: "${ownedBy2.data.createTestIdentity.id}") { + id + title + owner + } + } + `, + {}, + ); + expect(getReq.data.getTestIdentity).toBeTruthy(); + expect(getReq.data.getTestIdentity.title).toEqual('Test title update'); + expect(getReq.data.getTestIdentity.owner.slice(0, 19)).toEqual('https://cognito-idp'); + + const listResponse = await GRAPHQL_CLIENT_3.query( + `query { + listTestIdentities(filter: { title: { eq: "Test title update" } }, limit: 100) { + items { + id + title + owner + } + } + }`, + {}, + ); + const relevantPost = listResponse.data.listTestIdentities.items.find(p => p.id === getReq.data.getTestIdentity.id); + expect(relevantPost).toBeTruthy(); + expect(relevantPost.title).toEqual('Test title update'); + expect(relevantPost.owner.slice(0, 19)).toEqual('https://cognito-idp'); + + // user 2 should be able to delete because they share the same issuer. + const delReq = await GRAPHQL_CLIENT_3.query( + ` + mutation { + deleteTestIdentity(input: { + id: "${ownedBy2.data.createTestIdentity.id}" + }) { + id + title + owner + } + } + `, + {}, + ); + expect(delReq.data.deleteTestIdentity).toBeTruthy(); + expect(delReq.data.deleteTestIdentity.title).toEqual('Test title update'); + expect(delReq.data.deleteTestIdentity.owner.slice(0, 19)).toEqual('https://cognito-idp'); + }); + + /** + * Test 'operations' argument + */ + test("Test get and list with 'read' operation set", async () => { + const response = await GRAPHQL_CLIENT_1.query( + `mutation { + createNoOwner: createOwnerReadProtected(input: { id: "1", sk: "1", content: "Hello, World! - No Owner" }) { + id + content + owner + } + createOwnerReadProtected(input: { id: "1", sk: "2", content: "Hello, World!", owner: "${USERNAME2}" }) { + id + content + owner + } + createNoOwner2: createOwnerReadProtected(input: { id: "1", sk: "3", content: "Hello, World! - No Owner 2" }) { + id + content + owner + } + }`, + {}, + ); + + expect(response.data.createOwnerReadProtected.id).toBeDefined(); + expect(response.data.createOwnerReadProtected.content).toEqual('Hello, World!'); + expect(response.data.createOwnerReadProtected.owner).toEqual(USERNAME2); + + const response2 = await GRAPHQL_CLIENT_3.query( + `query { + getOwnerReadProtected(id: "${response.data.createOwnerReadProtected.id}", sk:"2") { + id content owner + } + }`, + {}, + ); + expect(response2.data.getOwnerReadProtected).toBeNull(); + expect(response2.errors).toHaveLength(1); + + const response3 = await GRAPHQL_CLIENT_2.query( + `query { + getOwnerReadProtected(id: "${response.data.createOwnerReadProtected.id}", sk:"2") { + id content owner + } + }`, + {}, + ); + expect(response3.data.getOwnerReadProtected.id).toBeDefined(); + expect(response3.data.getOwnerReadProtected.content).toEqual('Hello, World!'); + expect(response3.data.getOwnerReadProtected.owner).toEqual(USERNAME2); + + const response4 = await GRAPHQL_CLIENT_2.query( + `query { + listOwnerReadProtecteds(id: "1") { + items { + id content owner + } + } + }`, + {}, + ); + expect(response4.data.listOwnerReadProtecteds.items.length).toEqual(1); + + const response5 = await GRAPHQL_CLIENT_3.query( + `query { + listOwnerReadProtecteds { + items { + id content owner + } + } + }`, + {}, + ); + expect(response5.data.listOwnerReadProtecteds.items).toHaveLength(0); + }); + + test("Test createOwnerCreateUpdateDeleteProtected with 'create' operation set", async () => { + const response = await GRAPHQL_CLIENT_1.query( + `mutation { + createOwnerCreateUpdateDeleteProtected(input: { content: "Hello, World!", owner: "${USERNAME1}" }) { + id + content + owner + } + }`, + {}, + ); + expect(response.data.createOwnerCreateUpdateDeleteProtected.id).toBeDefined(); + expect(response.data.createOwnerCreateUpdateDeleteProtected.content).toEqual('Hello, World!'); + expect(response.data.createOwnerCreateUpdateDeleteProtected.owner).toEqual(USERNAME1); + + const response2 = await GRAPHQL_CLIENT_1.query( + `mutation { + createOwnerCreateUpdateDeleteProtected(input: { content: "Hello, World!", owner: "${USERNAME2}" }) { + id + content + owner + } + }`, + {}, + ); + expect(response2.data.createOwnerCreateUpdateDeleteProtected).toBeNull(); + expect(response2.errors).toHaveLength(1); + }); + + test("Test updateOwnerCreateUpdateDeleteProtected with 'update' operation set", async () => { + const response = await GRAPHQL_CLIENT_1.query( + `mutation { + createOwnerCreateUpdateDeleteProtected(input: { content: "Hello, World!", owner: "${USERNAME1}" }) { + id + content + owner + } + }`, + {}, + ); + expect(response.data.createOwnerCreateUpdateDeleteProtected.id).toBeDefined(); + expect(response.data.createOwnerCreateUpdateDeleteProtected.content).toEqual('Hello, World!'); + expect(response.data.createOwnerCreateUpdateDeleteProtected.owner).toEqual(USERNAME1); + + const response2 = await GRAPHQL_CLIENT_2.query( + `mutation { + updateOwnerCreateUpdateDeleteProtected( + input: { + id: "${response.data.createOwnerCreateUpdateDeleteProtected.id}", + content: "Bye, World!" + } + ) { + id + content + owner + } + }`, + {}, + ); + expect(response2.data.updateOwnerCreateUpdateDeleteProtected).toBeNull(); + expect(response2.errors).toHaveLength(1); + + const response3 = await GRAPHQL_CLIENT_1.query( + `mutation { + updateOwnerCreateUpdateDeleteProtected( + input: { + id: "${response.data.createOwnerCreateUpdateDeleteProtected.id}", + content: "Bye, World!" + } + ) { + id + content + owner + } + }`, + {}, + ); + expect(response3.data.updateOwnerCreateUpdateDeleteProtected.id).toBeDefined(); + expect(response3.data.updateOwnerCreateUpdateDeleteProtected.content).toEqual('Bye, World!'); + expect(response3.data.updateOwnerCreateUpdateDeleteProtected.owner).toEqual(USERNAME1); + }); + + test("Test deleteOwnerCreateUpdateDeleteProtected with 'update' operation set", async () => { + const response = await GRAPHQL_CLIENT_1.query( + `mutation { + createOwnerCreateUpdateDeleteProtected(input: { content: "Hello, World!", owner: "${USERNAME1}" }) { + id + content + owner + } + }`, + {}, + ); + expect(response.data.createOwnerCreateUpdateDeleteProtected.id).toBeDefined(); + expect(response.data.createOwnerCreateUpdateDeleteProtected.content).toEqual('Hello, World!'); + expect(response.data.createOwnerCreateUpdateDeleteProtected.owner).toEqual(USERNAME1); + + const response2 = await GRAPHQL_CLIENT_2.query( + `mutation { + deleteOwnerCreateUpdateDeleteProtected( + input: { + id: "${response.data.createOwnerCreateUpdateDeleteProtected.id}" + } + ) { + id + content + owner + } + }`, + {}, + ); + expect(response2.data.deleteOwnerCreateUpdateDeleteProtected).toBeNull(); + expect(response2.errors).toHaveLength(1); + + const response3 = await GRAPHQL_CLIENT_1.query( + `mutation { + deleteOwnerCreateUpdateDeleteProtected( + input: { + id: "${response.data.createOwnerCreateUpdateDeleteProtected.id}" + } + ) { + id + content + owner + } + }`, + {}, + ); + expect(response3.data.deleteOwnerCreateUpdateDeleteProtected.id).toBeDefined(); + expect(response3.data.deleteOwnerCreateUpdateDeleteProtected.content).toEqual('Hello, World!'); + expect(response3.data.deleteOwnerCreateUpdateDeleteProtected.owner).toEqual(USERNAME1); + }); + + test('Test allow private combined with groups as Admin and non-admin users', async () => { + const create = `mutation { + p1: createPerformance(input: { + id: "P1" + performer: "Perf #1" + description: "Description" + time: "2019-11-11T00:00:00Z" + performanceStageId: "S1" + }) { + id + } + + p2: createPerformance(input: { + id: "P2" + performer: "Perf #2" + description: "Description" + time: "2019-11-11T00:00:00Z" + performanceStageId: "S1" + }) { + id + } + + s1: createStage(input: { + id: "S1" + name: "Stage #1" + }) { + id + } + } + `; + + // Create as non-admin user, should fail + const response1 = await GRAPHQL_CLIENT_3.query(create, {}); + + expect(response1.data.p1).toBeNull(); + expect(response1.data.p2).toBeNull(); + expect(response1.data.s1).toBeNull(); + expect(response1.errors.length).toEqual(3); + expect((response1.errors[0] as any).errorType).toEqual('Unauthorized'); + expect((response1.errors[1] as any).errorType).toEqual('Unauthorized'); + expect((response1.errors[2] as any).errorType).toEqual('Unauthorized'); + + // Create as Admin, should succeed + const response2 = await GRAPHQL_CLIENT_1.query(create, {}); + + expect(response2.data.p1.id).toEqual('P1'); + expect(response2.data.p2.id).toEqual('P2'); + expect(response2.data.s1.id).toEqual('S1'); + + const update = `mutation { + updatePerformance(input: { + id: "P1" + performer: "Best Perf #1" + }) { + id + performer + } + } + `; + + // Update as non-admin user, should fail + const response3 = await GRAPHQL_CLIENT_3.query(update, {}); + + expect(response3.data.updatePerformance).toBeNull(); + expect(response3.errors.length).toEqual(1); + expect((response3.errors[0] as any).errorType).toEqual('Unauthorized'); + + // Update as Admin, should succeed + const response4 = await GRAPHQL_CLIENT_1.query(update, {}); + + expect(response4.data.updatePerformance.id).toEqual('P1'); + expect(response4.data.updatePerformance.performer).toEqual('Best Perf #1'); + + // List as non-admin and Admin user as well, should succeed + const list = `query List { + listPerformances { + items { + id + performer + description + time + stage { + name + } + } + } + } + `; + + const response5 = await GRAPHQL_CLIENT_3.query(list, {}); + + expect(response5.data.listPerformances).toBeDefined(); + expect(response5.data.listPerformances.items).toBeDefined(); + expect(response5.data.listPerformances.items.length).toEqual(2); + expect(response5.data.listPerformances.items[0].id).toEqual('P2'); + expect(response5.data.listPerformances.items[0].performer).toEqual('Perf #2'); + expect(response5.data.listPerformances.items[0].stage).toBeDefined(); + expect(response5.data.listPerformances.items[0].stage.name).toEqual('Stage #1'); + expect(response5.data.listPerformances.items[1].id).toEqual('P1'); + expect(response5.data.listPerformances.items[1].performer).toEqual('Best Perf #1'); + expect(response5.data.listPerformances.items[1].stage).toBeDefined(); + expect(response5.data.listPerformances.items[1].stage.name).toEqual('Stage #1'); + + const response6 = await GRAPHQL_CLIENT_1.query(list, {}); + + expect(response6.data.listPerformances).toBeDefined(); + expect(response6.data.listPerformances.items).toBeDefined(); + expect(response6.data.listPerformances.items.length).toEqual(2); + expect(response6.data.listPerformances.items[0].id).toEqual('P2'); + expect(response6.data.listPerformances.items[0].performer).toEqual('Perf #2'); + expect(response6.data.listPerformances.items[0].stage).toBeDefined(); + expect(response6.data.listPerformances.items[0].stage.name).toEqual('Stage #1'); + expect(response6.data.listPerformances.items[1].id).toEqual('P1'); + expect(response6.data.listPerformances.items[1].performer).toEqual('Best Perf #1'); + expect(response6.data.listPerformances.items[1].stage.name).toEqual('Stage #1'); + expect(response6.data.listPerformances.items[1].stage).toBeDefined(); + + // Get as non-admin and Admin user as well, should succeed + const get = `query Get { + getPerformance(id: "P1") { + id + performer + description + time + stage { + name + } + } + } + `; + + const response7 = await GRAPHQL_CLIENT_3.query(get, {}); + + expect(response7.data.getPerformance).toBeDefined(); + expect(response7.data.getPerformance.id).toEqual('P1'); + expect(response7.data.getPerformance.performer).toEqual('Best Perf #1'); + expect(response7.data.getPerformance.stage).toBeDefined(); + expect(response7.data.getPerformance.stage.name).toEqual('Stage #1'); + + const response8 = await GRAPHQL_CLIENT_1.query(get, {}); + + expect(response8.data.getPerformance).toBeDefined(); + expect(response8.data.getPerformance.id).toEqual('P1'); + expect(response8.data.getPerformance.performer).toEqual('Best Perf #1'); + expect(response8.data.getPerformance.stage).toBeDefined(); + expect(response8.data.getPerformance.stage.name).toEqual('Stage #1'); + + const deleteMutation = `mutation { + deletePerformance(input: { + id: "P1" + }) { + id + } + } + `; + + // Delete as non-admin user, should fail + const response9 = await GRAPHQL_CLIENT_3.query(deleteMutation, {}); + + expect(response9.data.deletePerformance).toBeNull(); + expect(response9.errors.length).toEqual(1); + expect((response9.errors[0] as any).errorType).toEqual('Unauthorized'); + + // Delete as Admin, should succeed + const response10 = await GRAPHQL_CLIENT_1.query(deleteMutation, {}); + + expect(response10.data.deletePerformance).toBeDefined(); + expect(response10.data.deletePerformance.id).toEqual('P1'); + }); + + test('Test authorized user can get Performance with no created stage', async () => { + const createPerf = `mutation { + create: createPerformance(input: { + id: "P3" + performer: "Perf #3" + description: "desc" + time: "2021-11-11T00:00:00Z" + }) { + id + performer + description + time + createdAt + updatedAt + } + }`; + + const getPerf = `query { + g1: getPerformance(id: "P3") { + id + performer + description + time + stage { + id + name + createdAt + updatedAt + } + createdAt + updatedAt + } + } + `; + + const createStage = `mutation { + createStage(input: {name: "stage3", id: "003"}) { + createdAt + id + name + updatedAt + } + }`; + + const updatePerf = `mutation { + u1: updatePerformance(input: {id: "P3", performanceStageId: "003"}) { + createdAt + description + id + performer + time + updatedAt + stage { + id + name + } + } + }`; + + // first make a query to the record 'P3' + const response1 = await GRAPHQL_CLIENT_1.query(getPerf, {}); + expect(response1).toBeDefined(); + expect(response1.data.g1).toBeNull(); + + // create performance and expect stage to be null + await GRAPHQL_CLIENT_1.query(createPerf, {}); + const response2 = await GRAPHQL_CLIENT_1.query(getPerf, {}); + expect(response2).toBeDefined(); + expect(response2.data.g1).toBeDefined(); + expect(response2.data.g1.id).toEqual('P3'); + expect(response2.data.g1.description).toEqual('desc'); + expect(response2.data.g1.stage).toBeNull(); + + //create stage and then add it to perf should show stage in perf + await GRAPHQL_CLIENT_1.query(createStage, {}); + const response3 = await GRAPHQL_CLIENT_1.query(updatePerf, {}); + expect(response3).toBeDefined(); + expect(response3.data.u1).toBeDefined(); + expect(response3.data.u1.id).toEqual('P3'); + expect(response3.data.u1.stage).toMatchObject({ + id: '003', + name: 'stage3', + }); + }); +}); diff --git a/packages/graphql-transformers-e2e-tests/src/__tests__/DefaultValueTransformer.e2e.test.ts b/packages/graphql-transformers-e2e-tests/src/__tests__/DefaultValueTransformer.e2e.test.ts index 5c212a0a084..3606926f13c 100644 --- a/packages/graphql-transformers-e2e-tests/src/__tests__/DefaultValueTransformer.e2e.test.ts +++ b/packages/graphql-transformers-e2e-tests/src/__tests__/DefaultValueTransformer.e2e.test.ts @@ -65,6 +65,7 @@ beforeAll(async () => { const transformer = new GraphQLTransform({ transformers: [new ModelTransformer(), new DefaultValueTransformer()], + sandboxModeEnabled: true, }); const out = transformer.transform(validSchema); const finishedStack = await deploy( @@ -95,7 +96,7 @@ afterAll(async () => { await cleanupStackAfterTest(BUCKET_NAME, STACK_NAME, cf); }); -test('Test next token with key', async () => { +test('Default value directive', async () => { await createPost(); const posts = await listPosts(); diff --git a/packages/graphql-transformers-e2e-tests/src/__tests__/IndexTransformer.e2e.test.ts b/packages/graphql-transformers-e2e-tests/src/__tests__/IndexTransformer.e2e.test.ts index d67eb917e80..e7c68dc903a 100644 --- a/packages/graphql-transformers-e2e-tests/src/__tests__/IndexTransformer.e2e.test.ts +++ b/packages/graphql-transformers-e2e-tests/src/__tests__/IndexTransformer.e2e.test.ts @@ -100,6 +100,7 @@ beforeAll(async () => { const transformer = new GraphQLTransform({ featureFlags, transformers: [new ModelTransformer(), new PrimaryKeyTransformer(), new IndexTransformer()], + sandboxModeEnabled: true, }); const out = transformer.transform(validSchema); const finishedStack = await deploy( diff --git a/packages/graphql-transformers-e2e-tests/src/__tests__/ModelTransformer.e2e.test.ts b/packages/graphql-transformers-e2e-tests/src/__tests__/ModelTransformer.e2e.test.ts index 05b4620a6b0..fdd54564b42 100644 --- a/packages/graphql-transformers-e2e-tests/src/__tests__/ModelTransformer.e2e.test.ts +++ b/packages/graphql-transformers-e2e-tests/src/__tests__/ModelTransformer.e2e.test.ts @@ -80,6 +80,7 @@ beforeAll(async () => { `; const transformer = new GraphQLTransform({ transformers: [new ModelTransformer()], + sandboxModeEnabled: true, }); const out = transformer.transform(validSchema); diff --git a/packages/graphql-transformers-e2e-tests/src/__tests__/RelationalTransformers.e2e.test.ts b/packages/graphql-transformers-e2e-tests/src/__tests__/RelationalTransformers.e2e.test.ts index af2c9ef1b26..ae08d2726e0 100644 --- a/packages/graphql-transformers-e2e-tests/src/__tests__/RelationalTransformers.e2e.test.ts +++ b/packages/graphql-transformers-e2e-tests/src/__tests__/RelationalTransformers.e2e.test.ts @@ -133,6 +133,7 @@ type Course @model { new BelongsToTransformer(), new ManyToManyTransformer(modelTransformer, indexTransformer, hasOneTransformer), ], + sandboxModeEnabled: true, }); out = transformer.transform(validSchema); } catch (e) { diff --git a/packages/graphql-transformers-e2e-tests/src/__tests__/SearchableModelTransformerV2.e2e.test.ts b/packages/graphql-transformers-e2e-tests/src/__tests__/SearchableModelTransformerV2.e2e.test.ts index 3fb3a26fc72..6bcfcc2f814 100644 --- a/packages/graphql-transformers-e2e-tests/src/__tests__/SearchableModelTransformerV2.e2e.test.ts +++ b/packages/graphql-transformers-e2e-tests/src/__tests__/SearchableModelTransformerV2.e2e.test.ts @@ -109,6 +109,7 @@ beforeAll(async () => { const transformer = new GraphQLTransform({ featureFlags, transformers: [new ModelTransformer(), new SearchableModelTransformer()], + sandboxModeEnabled: true, }); try { await awsS3Client.createBucket({ Bucket: BUCKET_NAME }).promise(); diff --git a/packages/graphql-transformers-e2e-tests/src/deployNestedStacks.ts b/packages/graphql-transformers-e2e-tests/src/deployNestedStacks.ts index 2f13e615b2d..8970de56761 100644 --- a/packages/graphql-transformers-e2e-tests/src/deployNestedStacks.ts +++ b/packages/graphql-transformers-e2e-tests/src/deployNestedStacks.ts @@ -178,7 +178,7 @@ export async function deploy( } function addAPIKeys(stack: DeploymentResources) { - if (!stack.rootStack.Resources.GraphQLAPIKey) { + if (stack.rootStack.Parameters.CreateAPIKey && !stack.rootStack.Resources.GraphQLAPIKey) { stack.rootStack.Resources.GraphQLAPIKey = { Type: 'AWS::AppSync::ApiKey', Properties: { @@ -189,7 +189,7 @@ function addAPIKeys(stack: DeploymentResources) { }; } - if (!stack.rootStack.Outputs.GraphQLAPIKeyOutput) { + if (stack.rootStack.Parameters.CreateAPIKey && !stack.rootStack.Outputs.GraphQLAPIKeyOutput) { stack.rootStack.Outputs.GraphQLAPIKeyOutput = { Value: { 'Fn::GetAtt': ['GraphQLAPIKey', 'ApiKey'], diff --git a/yarn.lock b/yarn.lock index f72c0ce8cbd..e6d42ab0bec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -156,6 +156,200 @@ prettier "^1.19.1" yargs "^15.1.0" +"@aws-amplify/graphql-function-transformer@0.4.4": + version "0.4.4" + resolved "https://registry.yarnpkg.com/@aws-amplify/graphql-function-transformer/-/graphql-function-transformer-0.4.4.tgz#56464e9cdbc86d8951a165eeae71725a7d28aadb" + integrity sha512-ZTbivT8wiM8whlggSiVOvCllhEN4JMISPq1kUKVOA1Fzg+TBxciuBmgIoEdreYDNi2nQo6+i2udMGiKJ/CjvMg== + dependencies: + "@aws-amplify/graphql-transformer-core" "0.9.1" + "@aws-amplify/graphql-transformer-interfaces" "1.9.1" + "@aws-cdk/aws-lambda" "~1.124.0" + "@aws-cdk/core" "~1.124.0" + graphql "^14.5.8" + graphql-mapping-template "4.18.3" + graphql-transformer-common "4.19.10" + +"@aws-amplify/graphql-http-transformer@0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@aws-amplify/graphql-http-transformer/-/graphql-http-transformer-0.5.4.tgz#374cadfa01b6b1c069b083fb986bd6fc6f0fa47e" + integrity sha512-LisG3s8Cf4DvzdGMUKCXRA0tsZuFgLyp1W6z+LHP1IZjlWwTVOG6CSc33ZWX6nWFf5kfosorWIkluP+jchxzvQ== + dependencies: + "@aws-amplify/graphql-transformer-core" "0.9.1" + "@aws-amplify/graphql-transformer-interfaces" "1.9.1" + "@aws-cdk/core" "~1.124.0" + graphql "^14.5.8" + graphql-mapping-template "4.18.3" + graphql-transformer-common "4.19.10" + +"@aws-amplify/graphql-index-transformer@0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@aws-amplify/graphql-index-transformer/-/graphql-index-transformer-0.3.3.tgz#6d07bed54b20f72cf7bed617e45a1ce94512da50" + integrity sha512-ZAnQAeMHXQMIO3/DkvUzDN7F/agPd0JIP+UV91iaaA8Kv5DfPySrQbUBv7GprRkfWKr01gxbYL12iCm9VoAilQ== + dependencies: + "@aws-amplify/graphql-model-transformer" "0.6.3" + "@aws-amplify/graphql-transformer-core" "0.9.1" + "@aws-amplify/graphql-transformer-interfaces" "1.9.1" + "@aws-cdk/aws-appsync" "~1.124.0" + "@aws-cdk/aws-dynamodb" "~1.124.0" + "@aws-cdk/core" "~1.124.0" + graphql "^14.5.8" + graphql-mapping-template "4.18.3" + graphql-transformer-common "4.19.10" + +"@aws-amplify/graphql-model-transformer@0.6.3": + version "0.6.3" + resolved "https://registry.yarnpkg.com/@aws-amplify/graphql-model-transformer/-/graphql-model-transformer-0.6.3.tgz#283f440ac4c97d6aceb55f31d6d657143eb35fe2" + integrity sha512-wZuxQnM7WdSq75DtbY0czDszC9pU0JM96xESX3Unf/B++EklWW5z9wkzs05bPSHQxrYW6dFCpJEIsdcee5LIIw== + dependencies: + "@aws-amplify/graphql-transformer-core" "0.9.1" + "@aws-amplify/graphql-transformer-interfaces" "1.9.1" + "@aws-cdk/assets" "~1.124.0" + "@aws-cdk/aws-applicationautoscaling" "~1.124.0" + "@aws-cdk/aws-appsync" "~1.124.0" + "@aws-cdk/aws-autoscaling-common" "~1.124.0" + "@aws-cdk/aws-cloudformation" "~1.124.0" + "@aws-cdk/aws-cloudwatch" "~1.124.0" + "@aws-cdk/aws-codeguruprofiler" "~1.124.0" + "@aws-cdk/aws-dynamodb" "~1.124.0" + "@aws-cdk/aws-ec2" "~1.124.0" + "@aws-cdk/aws-efs" "~1.124.0" + "@aws-cdk/aws-events" "~1.124.0" + "@aws-cdk/aws-iam" "~1.124.0" + "@aws-cdk/aws-kms" "~1.124.0" + "@aws-cdk/aws-lambda" "~1.124.0" + "@aws-cdk/aws-logs" "~1.124.0" + "@aws-cdk/aws-s3" "~1.124.0" + "@aws-cdk/aws-s3-assets" "~1.124.0" + "@aws-cdk/aws-sns" "~1.124.0" + "@aws-cdk/aws-sqs" "~1.124.0" + "@aws-cdk/aws-ssm" "~1.124.0" + "@aws-cdk/cloud-assembly-schema" "~1.124.0" + "@aws-cdk/core" "~1.124.0" + "@aws-cdk/custom-resources" "~1.124.0" + "@aws-cdk/cx-api" "~1.124.0" + "@aws-cdk/region-info" "~1.124.0" + constructs "^3.3.125" + graphql "^14.5.8" + graphql-mapping-template "4.18.3" + graphql-transformer-common "4.19.10" + lodash "^4.17.21" + md5 "^2.3.0" + +"@aws-amplify/graphql-predictions-transformer@0.3.4": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@aws-amplify/graphql-predictions-transformer/-/graphql-predictions-transformer-0.3.4.tgz#88feca0db4c60a553bd83cbe97dec8ea8680bc17" + integrity sha512-+Yi2gJ7sCEhqb+ZFGUHHW66xhpohb82yYGPwk+XNUZyo1nvKkYaAdb4S0N4fr75/I9xQc3rPF3NScKEuCDdhhg== + dependencies: + "@aws-amplify/graphql-transformer-core" "0.9.1" + "@aws-amplify/graphql-transformer-interfaces" "1.9.1" + "@aws-cdk/aws-appsync" "~1.124.0" + "@aws-cdk/aws-iam" "~1.124.0" + "@aws-cdk/aws-lambda" "~1.124.0" + "@aws-cdk/core" "~1.124.0" + graphql "^14.5.8" + graphql-mapping-template "4.18.3" + graphql-transformer-common "4.19.10" + +"@aws-amplify/graphql-relational-transformer@0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@aws-amplify/graphql-relational-transformer/-/graphql-relational-transformer-0.3.0.tgz#c6560842796afa8bbed30077e166ef6950d52d54" + integrity sha512-0XlH+A/8HWhTqtdIf+izkfg8iFCKPwTGRmPT+plZ1uz899PqyLKXzDZyPxnf+BRb2D7wP8NgAUK1qLlt7zh8gA== + dependencies: + "@aws-amplify/graphql-index-transformer" "0.3.3" + "@aws-amplify/graphql-model-transformer" "0.6.3" + "@aws-amplify/graphql-transformer-core" "0.9.1" + "@aws-amplify/graphql-transformer-interfaces" "1.9.1" + "@aws-cdk/aws-appsync" "~1.124.0" + "@aws-cdk/aws-dynamodb" "~1.124.0" + "@aws-cdk/core" "~1.124.0" + graphql "^14.5.8" + graphql-mapping-template "4.18.3" + graphql-transformer-common "4.19.10" + +"@aws-amplify/graphql-searchable-transformer@0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@aws-amplify/graphql-searchable-transformer/-/graphql-searchable-transformer-0.6.2.tgz#6ae35ecd702ffa676fe547e7ccbf040e010be256" + integrity sha512-CGwfXedp+vbEXTufX4aSqctE+idjUUL+AI/Sziyv84bGt2P602YaJtlZfx9JH6H+yfuxGRDE+rva8bAUcFrTYg== + dependencies: + "@aws-amplify/graphql-transformer-core" "0.9.1" + "@aws-amplify/graphql-transformer-interfaces" "1.9.1" + "@aws-cdk/aws-appsync" "~1.124.0" + "@aws-cdk/aws-dynamodb" "~1.124.0" + "@aws-cdk/aws-ec2" "~1.124.0" + "@aws-cdk/aws-elasticsearch" "~1.124.0" + "@aws-cdk/aws-iam" "~1.124.0" + "@aws-cdk/aws-lambda" "~1.124.0" + "@aws-cdk/core" "~1.124.0" + graphql "^14.5.8" + graphql-mapping-template "4.18.3" + graphql-transformer-common "4.19.10" + +"@aws-amplify/graphql-transformer-core@0.9.1": + version "0.9.1" + resolved "https://registry.yarnpkg.com/@aws-amplify/graphql-transformer-core/-/graphql-transformer-core-0.9.1.tgz#7172c2053300026fb0c9b8e33731f1cdd5870151" + integrity sha512-hzMuA4FHe+EbUPATQrTUabaJ2ETGmHaf+JMsAllw3BkZLcicbwzvBA4iUvgyllkOXXCur3p7gWkdsOndiY0qGw== + dependencies: + "@aws-amplify/graphql-transformer-interfaces" "1.9.1" + "@aws-cdk/assets" "~1.124.0" + "@aws-cdk/aws-applicationautoscaling" "~1.124.0" + "@aws-cdk/aws-appsync" "~1.124.0" + "@aws-cdk/aws-certificatemanager" "~1.124.0" + "@aws-cdk/aws-cloudwatch" "~1.124.0" + "@aws-cdk/aws-codeguruprofiler" "~1.124.0" + "@aws-cdk/aws-cognito" "~1.124.0" + "@aws-cdk/aws-dynamodb" "~1.124.0" + "@aws-cdk/aws-ec2" "~1.124.0" + "@aws-cdk/aws-efs" "~1.124.0" + "@aws-cdk/aws-events" "~1.124.0" + "@aws-cdk/aws-iam" "~1.124.0" + "@aws-cdk/aws-kms" "~1.124.0" + "@aws-cdk/aws-lambda" "~1.124.0" + "@aws-cdk/aws-logs" "~1.124.0" + "@aws-cdk/aws-route53" "~1.124.0" + "@aws-cdk/aws-s3" "~1.124.0" + "@aws-cdk/aws-s3-assets" "~1.124.0" + "@aws-cdk/aws-sqs" "~1.124.0" + "@aws-cdk/aws-ssm" "~1.124.0" + "@aws-cdk/cloud-assembly-schema" "~1.124.0" + "@aws-cdk/core" "~1.124.0" + "@aws-cdk/custom-resources" "~1.124.0" + "@aws-cdk/cx-api" "~1.124.0" + "@aws-cdk/region-info" "~1.124.0" + change-case "^4.1.1" + constructs "^3.3.125" + deep-diff "^1.0.2" + fs-extra "^8.1.0" + glob "^7.1.6" + graphql "^14.5.8" + graphql-transformer-common "4.19.10" + lodash "^4.17.21" + md5 "^2.3.0" + ts-dedent "^2.0.0" + +"@aws-amplify/graphql-transformer-interfaces@1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@aws-amplify/graphql-transformer-interfaces/-/graphql-transformer-interfaces-1.9.1.tgz#b0c394d7ed8be1344cbd974d29fa428d8202d999" + integrity sha512-8gMCLK6nzBfehPo2shEIeYqytB6Vn2+vtA3TAAlI0tkJFPY5NfWd5agcmXtXh15n6UZay1QQPUBmDVKAWUXk3Q== + dependencies: + "@aws-cdk/aws-appsync" "~1.124.0" + "@aws-cdk/aws-cloudwatch" "~1.124.0" + "@aws-cdk/aws-dynamodb" "~1.124.0" + "@aws-cdk/aws-ec2" "~1.124.0" + "@aws-cdk/aws-elasticsearch" "~1.124.0" + "@aws-cdk/aws-events" "~1.124.0" + "@aws-cdk/aws-iam" "~1.124.0" + "@aws-cdk/aws-kms" "~1.124.0" + "@aws-cdk/aws-lambda" "~1.124.0" + "@aws-cdk/aws-logs" "~1.124.0" + "@aws-cdk/aws-rds" "~1.124.0" + "@aws-cdk/aws-s3" "~1.124.0" + "@aws-cdk/aws-sam" "~1.124.0" + "@aws-cdk/aws-secretsmanager" "~1.124.0" + "@aws-cdk/core" "~1.124.0" + "@aws-cdk/custom-resources" "~1.124.0" + constructs "^3.3.125" + graphql "^14.5.8" + "@aws-amplify/graphql-types-generator@2.8.0": version "2.8.0" resolved "https://registry.yarnpkg.com/@aws-amplify/graphql-types-generator/-/graphql-types-generator-2.8.0.tgz#4d1de0d2bebfe86863d892b175ef9ee5fea489ca" @@ -6671,6 +6865,30 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= +amplify-cli-core@1.30.0: + version "1.30.0" + resolved "https://registry.yarnpkg.com/amplify-cli-core/-/amplify-cli-core-1.30.0.tgz#dcfc7555c3194c91cfd89c7edfdf6495e9f6fd70" + integrity sha512-G9JK8eFmuKHqflBSn+8tBGFDgf2r9UItL9hupCCe9h5wC7KVWxNFR1K0At24hsifVjt9f8j1HnFjZxmJGFmdwQ== + dependencies: + ajv "^6.12.3" + amplify-cli-logger "1.1.0" + amplify-prompts "1.2.0" + chalk "^4.1.1" + ci-info "^2.0.0" + cloudform-types "^4.2.0" + dotenv "^8.2.0" + execa "^5.1.1" + fs-extra "^8.1.0" + globby "^11.0.3" + hjson "^3.2.1" + js-yaml "^4.0.0" + lodash "^4.17.21" + node-fetch "^2.6.1" + open "^7.3.1" + proxy-agent "^5.0.0" + semver "^7.3.5" + which "^2.0.2" + amplify-codegen@^2.23.1: version "2.26.2" resolved "https://registry.yarnpkg.com/amplify-codegen/-/amplify-codegen-2.26.2.tgz#f5837dae2a15eaee214fe7eb318aa577a1f7e198" @@ -6695,6 +6913,115 @@ amplify-codegen@^2.23.1: semver "^7.3.5" slash "^3.0.0" +amplify-provider-awscloudformation@4.61.1: + version "4.61.1" + resolved "https://registry.yarnpkg.com/amplify-provider-awscloudformation/-/amplify-provider-awscloudformation-4.61.1.tgz#dcafdbf61bc720e0ec6953063185fd0b31402d3f" + integrity sha512-OZa5O45m8mMJD4IARD4GMff5RNt2V84OEO22IBuPYyz8HHazUZ/IEcd5bsCYztdaU9sDCSpd2BgWqdGoYr2HIw== + dependencies: + "@aws-amplify/graphql-function-transformer" "0.4.4" + "@aws-amplify/graphql-http-transformer" "0.5.4" + "@aws-amplify/graphql-index-transformer" "0.3.3" + "@aws-amplify/graphql-model-transformer" "0.6.3" + "@aws-amplify/graphql-predictions-transformer" "0.3.4" + "@aws-amplify/graphql-relational-transformer" "0.3.0" + "@aws-amplify/graphql-searchable-transformer" "0.6.2" + "@aws-amplify/graphql-transformer-core" "0.9.1" + "@aws-amplify/graphql-transformer-interfaces" "1.9.1" + "@aws-cdk/assets" "~1.124.0" + "@aws-cdk/aws-apigatewayv2" "~1.124.0" + "@aws-cdk/aws-autoscaling" "~1.124.0" + "@aws-cdk/aws-batch" "~1.124.0" + "@aws-cdk/aws-cloudformation" "~1.124.0" + "@aws-cdk/aws-cloudwatch" "~1.124.0" + "@aws-cdk/aws-codebuild" "~1.124.0" + "@aws-cdk/aws-codecommit" "~1.124.0" + "@aws-cdk/aws-codedeploy" "~1.124.0" + "@aws-cdk/aws-codepipeline" "~1.124.0" + "@aws-cdk/aws-codepipeline-actions" "~1.124.0" + "@aws-cdk/aws-ec2" "~1.124.0" + "@aws-cdk/aws-ecr" "~1.124.0" + "@aws-cdk/aws-ecr-assets" "~1.124.0" + "@aws-cdk/aws-ecs" "~1.124.0" + "@aws-cdk/aws-elasticloadbalancing" "~1.124.0" + "@aws-cdk/aws-elasticloadbalancingv2" "~1.124.0" + "@aws-cdk/aws-events" "~1.124.0" + "@aws-cdk/aws-events-targets" "~1.124.0" + "@aws-cdk/aws-iam" "~1.124.0" + "@aws-cdk/aws-kinesis" "~1.124.0" + "@aws-cdk/aws-kinesisfirehose" "~1.124.0" + "@aws-cdk/aws-kms" "~1.124.0" + "@aws-cdk/aws-lambda" "~1.124.0" + "@aws-cdk/aws-logs" "~1.124.0" + "@aws-cdk/aws-route53" "~1.124.0" + "@aws-cdk/aws-s3" "~1.124.0" + "@aws-cdk/aws-s3-assets" "~1.124.0" + "@aws-cdk/aws-secretsmanager" "~1.124.0" + "@aws-cdk/aws-servicecatalog" "~1.124.0" + "@aws-cdk/aws-servicediscovery" "~1.124.0" + "@aws-cdk/aws-sns" "~1.124.0" + "@aws-cdk/aws-sns-subscriptions" "~1.124.0" + "@aws-cdk/aws-sqs" "~1.124.0" + "@aws-cdk/aws-stepfunctions" "~1.124.0" + "@aws-cdk/core" "~1.124.0" + "@aws-cdk/custom-resources" "~1.124.0" + "@aws-cdk/region-info" "~1.124.0" + "@octokit/rest" "^18.0.9" + amplify-cli-core "1.30.0" + amplify-cli-logger "1.1.0" + amplify-codegen "^2.23.1" + amplify-util-import "1.5.13" + archiver "^5.3.0" + aws-sdk "^2.963.0" + bottleneck "2.19.5" + cfn-lint "^1.9.7" + chalk "^4.1.1" + cloudform "^4.2.0" + cloudform-types "^4.2.0" + columnify "^1.5.4" + constructs "^3.3.125" + cors "^2.8.5" + deep-diff "^1.0.2" + extract-zip "^2.0.1" + folder-hash "^4.0.1" + fs-extra "^8.1.0" + glob "^7.1.6" + graphql "^14.5.8" + graphql-auth-transformer "6.24.24" + graphql-connection-transformer "4.21.23" + graphql-dynamodb-transformer "6.22.23" + graphql-elasticsearch-transformer "4.12.3" + graphql-function-transformer "2.5.22" + graphql-http-transformer "4.18.10" + graphql-key-transformer "2.23.23" + graphql-predictions-transformer "2.5.22" + graphql-transformer-core "6.30.0" + graphql-versioned-transformer "4.17.23" + ignore "^5.1.8" + import-from "^3.0.0" + import-global "^0.1.0" + ini "^1.3.5" + inquirer "^7.3.3" + is-wsl "^2.2.0" + jose "^2.0.2" + lodash "^4.17.21" + lodash.throttle "^4.1.1" + moment "^2.24.0" + netmask "^2.0.2" + node-fetch "^2.6.1" + ora "^4.0.3" + promise-sequential "^1.1.1" + proxy-agent "^5.0.0" + rimraf "^3.0.0" + xstate "^4.14.0" + +amplify-util-import@1.5.13: + version "1.5.13" + resolved "https://registry.yarnpkg.com/amplify-util-import/-/amplify-util-import-1.5.13.tgz#ab191c3c1cc3e6ac5cf1089fd2c9ca35042107b7" + integrity sha512-OriJeF7l3pEv4PDjVjPh7ElhMnJE2HiMoMgTs5sdZbkqyigisEoEn1EWrdfzJNT7eBsBH8xDKuZjs3yRqooc4Q== + dependencies: + amplify-cli-core "1.30.0" + aws-sdk "^2.963.0" + ansi-align@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" @@ -12650,6 +12977,17 @@ graphiql@^1.3.2: graphql-language-service "^3.1.2" markdown-it "^10.0.0" +graphql-auth-transformer@6.24.24: + version "6.24.24" + resolved "https://registry.yarnpkg.com/graphql-auth-transformer/-/graphql-auth-transformer-6.24.24.tgz#b56728f2a830f16c68ff15d7371d2fdac459cbd3" + integrity sha512-zktdk6+RnILB3QlaW1q+n8lOgbRiPOb5RMTxvXYRWKOfkQyE23uf9uzuTRpDUHtg4ldIqSPTcEE1H/+IzKURaQ== + dependencies: + graphql "^14.5.8" + graphql-connection-transformer "4.21.23" + graphql-mapping-template "4.18.3" + graphql-transformer-common "4.19.10" + graphql-transformer-core "6.30.0" + graphql-config@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/graphql-config/-/graphql-config-2.2.2.tgz#a4b577826bba9b83e7b0f6cd617be43ca67da045" @@ -12661,6 +12999,66 @@ graphql-config@^2.2.1: lodash "^4.17.4" minimatch "^3.0.4" +graphql-connection-transformer@4.21.23: + version "4.21.23" + resolved "https://registry.yarnpkg.com/graphql-connection-transformer/-/graphql-connection-transformer-4.21.23.tgz#77a1c6ad4f6d4b2708c89ee96a08ba38165d0088" + integrity sha512-R24n5Ea4og3s9vI7emMKydVCCpHaTSxpdXfSTUQCKqFwXuaIQM8pUTZqhanAkaRJzdXg7n43f2VryFwTUL4GwA== + dependencies: + cloudform-types "^4.2.0" + graphql "^14.5.8" + graphql-dynamodb-transformer "6.22.23" + graphql-key-transformer "2.23.23" + graphql-mapping-template "4.18.3" + graphql-transformer-common "4.19.10" + graphql-transformer-core "6.30.0" + +graphql-dynamodb-transformer@6.22.23: + version "6.22.23" + resolved "https://registry.yarnpkg.com/graphql-dynamodb-transformer/-/graphql-dynamodb-transformer-6.22.23.tgz#6c931fc2b4ecabbf56d7ebc1a2ed5849c542bd5f" + integrity sha512-Q7qW/NdiQy8Lu4kjWo2P4I9augDL9RePkyQQHP+x3Z2pYsXFf8Z9FuufiH1RQYZ8a89wboVpfunUByYYn1LVLw== + dependencies: + "@types/pluralize" "^0.0.29" + cloudform-types "^4.2.0" + graphql "^14.5.8" + graphql-mapping-template "4.18.3" + graphql-transformer-common "4.19.10" + graphql-transformer-core "6.30.0" + md5 "^2.2.1" + pluralize "^8.0.0" + +graphql-elasticsearch-transformer@4.12.3: + version "4.12.3" + resolved "https://registry.yarnpkg.com/graphql-elasticsearch-transformer/-/graphql-elasticsearch-transformer-4.12.3.tgz#6e8192d291c0a941c376ecc645d7ded21e0b9579" + integrity sha512-XsNtkaIfJMrV4bJltdMAlZ1v3HodC3Y+Qkyzgh8uQozHV0YhZzTpwY9tpnpKO0Z+PK34Jsuy5B3fFJlrkgUAuw== + dependencies: + cloudform-types "^4.2.0" + graphql "^14.5.8" + graphql-mapping-template "4.18.3" + graphql-transformer-common "4.19.10" + graphql-transformer-core "6.30.0" + +graphql-function-transformer@2.5.22: + version "2.5.22" + resolved "https://registry.yarnpkg.com/graphql-function-transformer/-/graphql-function-transformer-2.5.22.tgz#b3f65d74e4955f292468ee08d24d3b02b7d5e52c" + integrity sha512-Yyn20ZtrwBS444pp0Qzp+hEwQGBE+Wemg4OK7Np6gGWu1s9XTgYhzvdSkm8l36FR3SYDxKu+sWFZ96mdm6Q+Eg== + dependencies: + cloudform-types "^4.2.0" + graphql "^14.5.8" + graphql-mapping-template "4.18.3" + graphql-transformer-common "4.19.10" + graphql-transformer-core "6.30.0" + +graphql-http-transformer@4.18.10: + version "4.18.10" + resolved "https://registry.yarnpkg.com/graphql-http-transformer/-/graphql-http-transformer-4.18.10.tgz#70b69d095f492a9c77899ed3da13a50f417d918d" + integrity sha512-sPowKCAd2+Tf6KdpTj46l6i8aNI9m9nTur+sHpMKPAqS0sxhCFpBUsz0Xdy2mks6mZWKG9V4NFDh5FaoD816Og== + dependencies: + cloudform-types "^4.2.0" + graphql "^14.5.8" + graphql-mapping-template "4.18.3" + graphql-transformer-common "4.19.10" + graphql-transformer-core "6.30.0" + graphql-import@^0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/graphql-import/-/graphql-import-0.7.1.tgz#4add8d91a5f752d764b0a4a7a461fcd93136f223" @@ -12674,6 +13072,18 @@ graphql-iso-date@^3.6.1: resolved "https://registry.yarnpkg.com/graphql-iso-date/-/graphql-iso-date-3.6.1.tgz#bd2d0dc886e0f954cbbbc496bbf1d480b57ffa96" integrity sha512-AwFGIuYMJQXOEAgRlJlFL4H1ncFM8n8XmoVDTNypNOZyQ8LFDG2ppMFlsS862BSTCDcSUfHp8PD3/uJhv7t59Q== +graphql-key-transformer@2.23.23: + version "2.23.23" + resolved "https://registry.yarnpkg.com/graphql-key-transformer/-/graphql-key-transformer-2.23.23.tgz#bfd40f63a828a45306fff0230df498603278c696" + integrity sha512-GWRGRXV5zwsPDKuFwnU4bTuzeeQfXBMO0sL/V0SeslkHv6HCI/rPEkffh98bz5W0H4T7tqzfX7/y8zv7125Mfw== + dependencies: + cloudform-types "^4.2.0" + graphql "^14.5.8" + graphql-dynamodb-transformer "6.22.23" + graphql-mapping-template "4.18.3" + graphql-transformer-common "4.19.10" + graphql-transformer-core "6.30.0" + graphql-language-service-interface@^2.8.2: version "2.8.4" resolved "https://registry.yarnpkg.com/graphql-language-service-interface/-/graphql-language-service-interface-2.8.4.tgz#3ff31754e9b295b1abc26b97d286c00835aacff0" @@ -12712,6 +13122,17 @@ graphql-language-service@^3.1.2: graphql-language-service-interface "^2.8.2" graphql-language-service-types "^1.8.0" +graphql-predictions-transformer@2.5.22: + version "2.5.22" + resolved "https://registry.yarnpkg.com/graphql-predictions-transformer/-/graphql-predictions-transformer-2.5.22.tgz#4ea2b2d5afa168916901732b017b2a7d62b9b9b6" + integrity sha512-5OFl7laJ1s0B9WEv7zf98VwXh4KEJvry836k0ggOr8/Oo1i6ZUcf1UFMk8VK7p811b/hLu4pO6rPfLkNbssKBA== + dependencies: + cloudform-types "^4.2.0" + graphql "^14.5.8" + graphql-mapping-template "4.18.3" + graphql-transformer-common "4.19.10" + graphql-transformer-core "6.30.0" + graphql-request@^1.5.0: version "1.8.2" resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-1.8.2.tgz#398d10ae15c585676741bde3fc01d5ca948f8fbe" @@ -12765,11 +13186,34 @@ graphql-tools@^4.0.6: iterall "^1.1.3" uuid "^3.1.0" +graphql-transformer-core@6.30.0: + version "6.30.0" + resolved "https://registry.yarnpkg.com/graphql-transformer-core/-/graphql-transformer-core-6.30.0.tgz#c532ad8b01400bdf5044e5f43f944f013750a66b" + integrity sha512-YBxdJpUE8K9zenHaLubnLhKlJBjMYfJgzwT5Zv/IowAwyTvNUoDsnox6M1ov8kEHru2VV+eKVqQjlswKWHnXog== + dependencies: + amplify-cli-core "1.30.0" + cloudform-types "^4.2.0" + deep-diff "^1.0.2" + fs-extra "^8.1.0" + glob "^7.1.6" + graphql "^14.5.8" + graphql-transformer-common "4.19.10" + graphql-type-json@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/graphql-type-json/-/graphql-type-json-0.3.2.tgz#f53a851dbfe07bd1c8157d24150064baab41e115" integrity sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg== +graphql-versioned-transformer@4.17.23: + version "4.17.23" + resolved "https://registry.yarnpkg.com/graphql-versioned-transformer/-/graphql-versioned-transformer-4.17.23.tgz#c4157542db61b98af4460370749a4fc88c6e714f" + integrity sha512-pYBa/1o9fwX4WX4HKmxDXYtdSrOgUiuj1d0gmuYLoFPTzkl3sOoJ1WUskX5Jk8az0bvuw91hQP/NAFeU8p/tSw== + dependencies: + graphql "^14.5.8" + graphql-mapping-template "4.18.3" + graphql-transformer-common "4.19.10" + graphql-transformer-core "6.30.0" + graphql-ws@^4.3.2: version "4.9.0" resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-4.9.0.tgz#5cfd8bb490b35e86583d8322f5d5d099c26e365c"