diff --git a/.eslintrc.js b/.eslintrc.js index 60e0355d830..c9ba9fa9f9f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -323,7 +323,7 @@ module.exports = { '/packages/amplify-graphql-*transformer*/lib', '/packages/amplify-provider-awscloudformation/lib', '/packages/amplify-console-integration-tests/lib', - '/packages/amplify-cli-overrides-helper/lib', + '/packages/amplify-cli-extensibility-helper/lib', '/packages/amplify-category-auth/resources/auth-custom-resource', '/packages/amplify-category-custom/lib', '/packages/amplify-category-custom/resources', diff --git a/.gitignore b/.gitignore index 8caec8626ed..0b4b7628c72 100644 --- a/.gitignore +++ b/.gitignore @@ -69,5 +69,5 @@ packages/**/reports/junit/* test.out.log *.tsbuildinfo packages/amplify-graphiql-explorer/.eslintcache -packages/amplify-cli-overrides-helper/lib +packages/amplify-cli-extensibility-helper/lib diff --git a/packages/amplify-category-auth/package.json b/packages/amplify-category-auth/package.json index 865d1bd5f01..ba0c74fd763 100644 --- a/packages/amplify-category-auth/package.json +++ b/packages/amplify-category-auth/package.json @@ -43,7 +43,8 @@ "ora": "^4.0.3", "promise-sequential": "^1.1.1", "uuid": "^3.4.0", - "vm2": "^3.9.3" + "vm2": "^3.9.3", + "@aws-amplify/cli-extensibility-helper": "1.0.0" }, "devDependencies": { "rimraf": "^3.0.2" diff --git a/packages/amplify-category-auth/resources/overrides-resource/override.ts b/packages/amplify-category-auth/resources/overrides-resource/override.ts index 76000340d77..90f448f3ce8 100644 --- a/packages/amplify-category-auth/resources/overrides-resource/override.ts +++ b/packages/amplify-category-auth/resources/overrides-resource/override.ts @@ -1,3 +1,3 @@ -import { AmplifyAuthCognitoStackTemplate } from '@aws-amplify/cli-overrides-helper'; +import { AmplifyAuthCognitoStackTemplate } from '@aws-amplify/cli-extensibility-helper'; export function override(resources: AmplifyAuthCognitoStackTemplate) {} diff --git a/packages/amplify-category-auth/resources/overrides-resource/package.json b/packages/amplify-category-auth/resources/overrides-resource/package.json index 35910a5f41c..9aa8efc47e8 100644 --- a/packages/amplify-category-auth/resources/overrides-resource/package.json +++ b/packages/amplify-category-auth/resources/overrides-resource/package.json @@ -8,7 +8,7 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { - "@aws-amplify/cli-overrides-helper": "1.1.0-ext11.0" + "@aws-amplify/cli-extensibility-helper": "1.1.0-ext15.0" }, "devDependencies": { "typescript": "^4.2.4" diff --git a/packages/amplify-category-auth/src/__tests__/commands/update.test.ts b/packages/amplify-category-auth/src/__tests__/commands/update.test.ts index c34db693a87..fa50d69fa72 100644 --- a/packages/amplify-category-auth/src/__tests__/commands/update.test.ts +++ b/packages/amplify-category-auth/src/__tests__/commands/update.test.ts @@ -85,6 +85,9 @@ describe('auth update: ', () => { usageData: { emitError: jest.fn(), }, + input: { + options: {}, + }, } as unknown as $TSContext; const dependencies = ['analytics', 'api', 'function', 'storage']; diff --git a/packages/amplify-category-auth/src/index.js b/packages/amplify-category-auth/src/index.js index 7dd8b87c878..26a970529f4 100644 --- a/packages/amplify-category-auth/src/index.js +++ b/packages/amplify-category-auth/src/index.js @@ -24,8 +24,6 @@ const { AuthParameters } = require('./provider-utils/awscloudformation/import/ty const { getSupportedServices } = require('./provider-utils/supported-services'); const { generateAuthStackTemplate } = require('./provider-utils/awscloudformation/utils/generate-auth-stack-template'); const { AmplifyAuthTransform, AmplifyUserPoolGroupTransform } = require('./provider-utils/awscloudformation/auth-stack-builder'); -const { AmplifyAuthCognitoStackTemplate } = require('./provider-utils/awscloudformation/auth-stack-builder/types'); - const { doesConfigurationIncludeSMS, loadResourceParameters, @@ -534,5 +532,4 @@ module.exports = { AmplifyAuthTransform, AmplifyUserPoolGroupTransform, transformCategoryStack, - AmplifyAuthCognitoStackTemplate, }; diff --git a/packages/amplify-category-auth/src/provider-utils/awscloudformation/auth-stack-builder/auth-cognito-stack-builder.ts b/packages/amplify-category-auth/src/provider-utils/awscloudformation/auth-stack-builder/auth-cognito-stack-builder.ts index cc2c179dada..252ed28d5cc 100644 --- a/packages/amplify-category-auth/src/provider-utils/awscloudformation/auth-stack-builder/auth-cognito-stack-builder.ts +++ b/packages/amplify-category-auth/src/provider-utils/awscloudformation/auth-stack-builder/auth-cognito-stack-builder.ts @@ -3,7 +3,7 @@ import * as s3 from '@aws-cdk/aws-s3'; import * as iam from '@aws-cdk/aws-iam'; import * as cognito from '@aws-cdk/aws-cognito'; import * as lambda from '@aws-cdk/aws-lambda'; -import { AmplifyAuthCognitoStackTemplate } from './types'; +import { AmplifyAuthCognitoStackTemplate } from '@aws-amplify/cli-extensibility-helper'; import { CognitoStackOptions } from '../service-walkthrough-types/cognito-user-input-types'; import _ from 'lodash'; import { diff --git a/packages/amplify-category-auth/src/provider-utils/awscloudformation/auth-stack-builder/auth-user-pool-group-stack-builder.ts b/packages/amplify-category-auth/src/provider-utils/awscloudformation/auth-stack-builder/auth-user-pool-group-stack-builder.ts index 629b8b0eade..beaf44ad8b0 100644 --- a/packages/amplify-category-auth/src/provider-utils/awscloudformation/auth-stack-builder/auth-user-pool-group-stack-builder.ts +++ b/packages/amplify-category-auth/src/provider-utils/awscloudformation/auth-stack-builder/auth-user-pool-group-stack-builder.ts @@ -2,7 +2,7 @@ import * as cdk from '@aws-cdk/core'; import * as iam from '@aws-cdk/aws-iam'; import * as lambda from '@aws-cdk/aws-lambda'; import { CfnUserPoolGroup } from '@aws-cdk/aws-cognito'; -import { AmplifyUserPoolGroupStackTemplate } from './types'; +import { AmplifyUserPoolGroupStackTemplate } from '@aws-amplify/cli-extensibility-helper'; import { AmplifyUserPoolGroupStackOptions } from './user-pool-group-stack-transform'; import { AmplifyStackTemplate } from 'amplify-cli-core'; import * as fs from 'fs-extra'; diff --git a/packages/amplify-category-auth/src/provider-utils/awscloudformation/auth-stack-builder/index.ts b/packages/amplify-category-auth/src/provider-utils/awscloudformation/auth-stack-builder/index.ts index e8d2f6ea910..3a0733897bb 100644 --- a/packages/amplify-category-auth/src/provider-utils/awscloudformation/auth-stack-builder/index.ts +++ b/packages/amplify-category-auth/src/provider-utils/awscloudformation/auth-stack-builder/index.ts @@ -2,4 +2,3 @@ export { AmplifyAuthCognitoStack } from './auth-cognito-stack-builder'; export { AmplifyAuthTransform } from './auth-stack-transform'; export { AmplifyUserPoolGroupStack } from './auth-user-pool-group-stack-builder'; export { AmplifyUserPoolGroupTransform } from './user-pool-group-stack-transform'; -export { AmplifyAuthCognitoStackTemplate, AmplifyUserPoolGroupStackTemplate } from './types'; diff --git a/packages/amplify-category-auth/src/provider-utils/awscloudformation/utils/migrate-override-resource.ts b/packages/amplify-category-auth/src/provider-utils/awscloudformation/utils/migrate-override-resource.ts index d5955838c97..a856d4a602c 100644 --- a/packages/amplify-category-auth/src/provider-utils/awscloudformation/utils/migrate-override-resource.ts +++ b/packages/amplify-category-auth/src/provider-utils/awscloudformation/utils/migrate-override-resource.ts @@ -18,7 +18,7 @@ import { } from '../service-walkthrough-types/awsCognito-user-input-types'; export const migrateResourceToSupportOverride = async (resourceName: string) => { - printer.info('Starting Migration Process'); + printer.debug('Starting Migration Process'); /** * backup resource folder * get parameters.json @@ -48,7 +48,7 @@ export const migrateResourceToSupportOverride = async (resourceName: string) => const cliInputs = mapParametersJsonToCliInputs(parameters!); const cliInputsPath = path.join(authresourceDirPath, 'cli-inputs.json'); JSONUtilities.writeJson(cliInputsPath, cliInputs); - printer.success('Migration is Successful'); + printer.debug('Migration is Successful'); } catch (e) { printer.error('There was an error migrating your project.'); rollback(authresourceDirPath, backupAuthResourceFolder!); diff --git a/packages/amplify-category-storage/package.json b/packages/amplify-category-storage/package.json index 779c11e7578..6ff1b6d5f61 100644 --- a/packages/amplify-category-storage/package.json +++ b/packages/amplify-category-storage/package.json @@ -41,7 +41,8 @@ "lodash": "^4.17.21", "promise-sequential": "^1.1.1", "uuid": "^8.3.2", - "vm2": "^3.9.3" + "vm2": "^3.9.3", + "@aws-amplify/cli-extensibility-helper": "1.0.0" }, "devDependencies": { "aws-sdk": "^2.963.0", diff --git a/packages/amplify-category-storage/resources/overrides-resource/DynamoDB/override.ts b/packages/amplify-category-storage/resources/overrides-resource/DynamoDB/override.ts index b2de7ccdba9..9a5ebc4c991 100644 --- a/packages/amplify-category-storage/resources/overrides-resource/DynamoDB/override.ts +++ b/packages/amplify-category-storage/resources/overrides-resource/DynamoDB/override.ts @@ -1,3 +1,3 @@ -import { AmplifyDDBResourceTemplate } from '@aws-amplify/cli-overrides-helper'; +import { AmplifyDDBResourceTemplate } from '@aws-amplify/cli-extensibility-helper'; export function override(resources: AmplifyDDBResourceTemplate) {} diff --git a/packages/amplify-category-storage/resources/overrides-resource/DynamoDB/package.json b/packages/amplify-category-storage/resources/overrides-resource/DynamoDB/package.json index 7b484b7b809..1a0684e84b3 100644 --- a/packages/amplify-category-storage/resources/overrides-resource/DynamoDB/package.json +++ b/packages/amplify-category-storage/resources/overrides-resource/DynamoDB/package.json @@ -8,7 +8,7 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { - "@aws-amplify/cli-overrides-helper": "1.1.0-ext11.0" + "@aws-amplify/cli-extensibility-helper": "1.1.0-ext15.0" }, "devDependencies": { diff --git a/packages/amplify-category-storage/resources/overrides-resource/S3/override.ts b/packages/amplify-category-storage/resources/overrides-resource/S3/override.ts index c018e0819d3..9f3a08a1b16 100644 --- a/packages/amplify-category-storage/resources/overrides-resource/S3/override.ts +++ b/packages/amplify-category-storage/resources/overrides-resource/S3/override.ts @@ -1,3 +1,3 @@ -import { AmplifyS3ResourceTemplate } from '@aws-amplify/cli-overrides-helper'; +import { AmplifyS3ResourceTemplate } from '@aws-amplify/cli-extensibility-helper'; export function override(resources: AmplifyS3ResourceTemplate) {} diff --git a/packages/amplify-category-storage/resources/overrides-resource/S3/package.json b/packages/amplify-category-storage/resources/overrides-resource/S3/package.json index deef309eb16..ba1450aa702 100644 --- a/packages/amplify-category-storage/resources/overrides-resource/S3/package.json +++ b/packages/amplify-category-storage/resources/overrides-resource/S3/package.json @@ -8,7 +8,7 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { - "@aws-amplify/cli-overrides-helper": "1.1.0-ext11.0" + "@aws-amplify/cli-extensibility-helper": "1.1.0-ext15.0" }, "devDependencies": { "typescript": "^4.2.4" diff --git a/packages/amplify-category-storage/src/__tests__/provider-utils/awscloudformation/service-walkthroughs/dynamoDb-walkthrough.test.ts b/packages/amplify-category-storage/src/__tests__/provider-utils/awscloudformation/service-walkthroughs/dynamoDb-walkthrough.test.ts index d6af9e7020c..dee9a23a52b 100644 --- a/packages/amplify-category-storage/src/__tests__/provider-utils/awscloudformation/service-walkthroughs/dynamoDb-walkthrough.test.ts +++ b/packages/amplify-category-storage/src/__tests__/provider-utils/awscloudformation/service-walkthroughs/dynamoDb-walkthrough.test.ts @@ -27,6 +27,9 @@ describe('add ddb walkthrough tests', () => { }; }, }, + input: { + options: {}, + }, } as unknown as $TSContext; }); @@ -126,6 +129,9 @@ describe('update ddb walkthrough tests', () => { }; }, }, + input: { + options: {}, + }, } as unknown as $TSContext; }); diff --git a/packages/amplify-category-storage/src/__tests__/provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough.test.ts b/packages/amplify-category-storage/src/__tests__/provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough.test.ts index 077d085b71d..f285c72011a 100644 --- a/packages/amplify-category-storage/src/__tests__/provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough.test.ts +++ b/packages/amplify-category-storage/src/__tests__/provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough.test.ts @@ -42,19 +42,19 @@ describe('add s3 walkthrough tests', () => { }, }; }, - getUserPoolGroupList: ()=>{ + getUserPoolGroupList: () => { return []; }, // eslint-disable-next-line getResourceStatus: () => { return { allResources: S3MockDataBuilder.getMockGetAllResourcesNoExistingLambdas() }; }, //eslint-disable-line - copyBatch : jest.fn().mockReturnValue( new Promise((resolve, reject) => resolve(true) ) ), - updateamplifyMetaAfterResourceAdd : jest.fn().mockReturnValue( new Promise((resolve, reject) => resolve(true) ) ), + copyBatch: jest.fn().mockReturnValue(new Promise((resolve, reject) => resolve(true))), + updateamplifyMetaAfterResourceAdd: jest.fn().mockReturnValue(new Promise((resolve, reject) => resolve(true))), pathManager: { - getBackendDirPath: jest.fn().mockReturnValue("mockTargetDir") - } - } + getBackendDirPath: jest.fn().mockReturnValue('mockTargetDir'), + }, + }, } as unknown as $TSContext; }); @@ -63,11 +63,15 @@ describe('add s3 walkthrough tests', () => { }); it('addWalkthrough() simple-auth test', async () => { - jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation( async () => {return} ); + jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async () => { + return; + }); jest.spyOn(AmplifyS3ResourceStackTransform.prototype, 'transform').mockImplementation(() => Promise.resolve()); - jest.spyOn(s3AuthAPI, 'migrateAuthDependencyResource').mockReturnValue(new Promise((resolve, _reject)=>{ - process.nextTick(() => resolve(undefined)); - })); + jest.spyOn(s3AuthAPI, 'migrateAuthDependencyResource').mockReturnValue( + new Promise((resolve, _reject) => { + process.nextTick(() => resolve(undefined)); + }), + ); const mockDataBuilder = new S3MockDataBuilder(undefined); const expectedCLIInputsJSON: S3UserInputs = mockDataBuilder.getCLIInputs(); @@ -95,7 +99,9 @@ describe('add s3 walkthrough tests', () => { expect(S3InputState.prototype.saveCliInputPayload).toHaveBeenCalledWith(expectedCLIInputsJSON); }); it('addWalkthrough() simple-auth+guest test', async () => { - jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async ()=>{ return }); + jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async () => { + return; + }); jest.spyOn(AmplifyS3ResourceStackTransform.prototype, 'transform').mockImplementation(() => Promise.resolve()); const mockDataBuilder = new S3MockDataBuilder(undefined); @@ -112,7 +118,7 @@ describe('add s3 walkthrough tests', () => { .fn() .mockResolvedValueOnce(S3AccessType.AUTH_AND_GUEST) // who should have access .mockResolvedValueOnce([S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ, S3PermissionType.DELETE]) // What kind of permissions (Auth) - .mockResolvedValueOnce([S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ,]); // What kind of permissions (Guest) + .mockResolvedValueOnce([S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ]); // What kind of permissions (Guest) prompter.confirmContinue = jest.fn().mockReturnValueOnce(false); // Do you want to add a Lambda Trigger ? @@ -125,29 +131,30 @@ describe('add s3 walkthrough tests', () => { expect(S3InputState.prototype.saveCliInputPayload).toHaveBeenCalledWith(expectedCLIInputsJSON); }); it('addWalkthrough() simple-auth + trigger (new function) test', async () => { - jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async ()=>{ return }); + jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async () => { + return; + }); jest.spyOn(AmplifyS3ResourceStackTransform.prototype, 'transform').mockImplementation(() => Promise.resolve()); const mockDataBuilder = new S3MockDataBuilder(undefined); const expectedCLIInputsJSON: S3UserInputs = mockDataBuilder.addMockTriggerFunction(undefined).getCLIInputs(); - + //Simple Auth CLI walkthrough prompter.input = jest .fn() .mockReturnValueOnce(S3MockDataBuilder.mockResourceName) // Provide a friendly name .mockResolvedValueOnce(S3MockDataBuilder.mockBucketName) // Provide bucket name - .mockResolvedValueOnce(false); + .mockResolvedValueOnce(false); prompter.pick = jest .fn() .mockResolvedValueOnce(S3AccessType.AUTH_ONLY) // who should have access - .mockResolvedValueOnce([S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ, S3PermissionType.DELETE]) // What kind of permissions (Auth) - + .mockResolvedValueOnce([S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ, S3PermissionType.DELETE]); // What kind of permissions (Auth) prompter.yesOrNo = jest - .fn() - .mockReturnValueOnce(true) //Do you want to add a Lambda Trigger ? - .mockResolvedValueOnce(false); //Do you want to edit the lamdba function now? + .fn() + .mockReturnValueOnce(true) //Do you want to add a Lambda Trigger ? + .mockResolvedValueOnce(false); //Do you want to edit the lamdba function now? stateManager.getMeta = jest.fn().mockReturnValue(S3MockDataBuilder.mockAmplifyMeta); @@ -158,34 +165,38 @@ describe('add s3 walkthrough tests', () => { expect(S3InputState.prototype.saveCliInputPayload).toHaveBeenCalledWith(expectedCLIInputsJSON); }); it('addWalkthrough() simple-auth + trigger (existing function) test', async () => { - jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async ()=>{ return }); + jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async () => { + return; + }); jest.spyOn(AmplifyS3ResourceStackTransform.prototype, 'transform').mockImplementation(() => Promise.resolve()); //Add Existing Lambda functions in resource status mockContext.amplify.getResourceStatus = () => { return { allResources: S3MockDataBuilder.getMockGetAllResources2ExistingLambdas() }; - } + }; const mockDataBuilder = new S3MockDataBuilder(undefined); //Select the first existing function from the list presented above in allResources - const expectedCLIInputsJSON: S3UserInputs = mockDataBuilder.addMockTriggerFunction( S3MockDataBuilder.mockExistingFunctionName1 ).getCLIInputs(); + const expectedCLIInputsJSON: S3UserInputs = mockDataBuilder + .addMockTriggerFunction(S3MockDataBuilder.mockExistingFunctionName1) + .getCLIInputs(); //Simple Auth CLI walkthrough prompter.input = jest .fn() .mockReturnValueOnce(S3MockDataBuilder.mockResourceName) // Provide a friendly name .mockResolvedValueOnce(S3MockDataBuilder.mockBucketName) // Provide bucket name - .mockResolvedValueOnce(false); + .mockResolvedValueOnce(false); prompter.pick = jest .fn() .mockResolvedValueOnce(S3AccessType.AUTH_ONLY) // who should have access .mockResolvedValueOnce([S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ, S3PermissionType.DELETE]) // What kind of permissions (Auth) .mockResolvedValueOnce(S3TriggerFunctionType.EXISTING_FUNCTION) - .mockResolvedValueOnce(S3MockDataBuilder.mockExistingFunctionName1 ); //Selected the First Existing function from the list. + .mockResolvedValueOnce(S3MockDataBuilder.mockExistingFunctionName1); //Selected the First Existing function from the list. prompter.yesOrNo = jest - .fn() - .mockReturnValueOnce(true) //Do you want to add a Lambda Trigger ? - .mockResolvedValueOnce(false); //Do you want to edit the lamdba function now? + .fn() + .mockReturnValueOnce(true) //Do you want to add a Lambda Trigger ? + .mockResolvedValueOnce(false); //Do you want to edit the lamdba function now? stateManager.getMeta = jest.fn().mockReturnValue(S3MockDataBuilder.mockAmplifyMeta); @@ -195,7 +206,6 @@ describe('add s3 walkthrough tests', () => { expect(returnedResourcename).toEqual(S3MockDataBuilder.mockResourceName); expect(S3InputState.prototype.saveCliInputPayload).toHaveBeenCalledWith(expectedCLIInputsJSON); }); - }); describe('update s3 permission walkthrough tests', () => { @@ -215,13 +225,13 @@ describe('update s3 permission walkthrough tests', () => { }, amplifyMeta: { auth: S3MockDataBuilder.mockAuthMeta, - storage : { + storage: { [S3MockDataBuilder.mockResourceName]: { - "service": "S3", - "providerPlugin": "awscloudformation", - "dependsOn": [] - } - } + service: 'S3', + providerPlugin: 'awscloudformation', + dependsOn: [], + }, + }, }, }; }, @@ -229,12 +239,15 @@ describe('update s3 permission walkthrough tests', () => { getResourceStatus: () => { return { allResources: S3MockDataBuilder.getMockGetAllResourcesNoExistingLambdas() }; }, //eslint-disable-line - copyBatch : jest.fn().mockReturnValue( new Promise((resolve, reject) => resolve(true) ) ), - updateamplifyMetaAfterResourceAdd : jest.fn().mockReturnValue( new Promise((resolve, reject) => resolve(true) ) ), + copyBatch: jest.fn().mockReturnValue(new Promise((resolve, reject) => resolve(true))), + updateamplifyMetaAfterResourceAdd: jest.fn().mockReturnValue(new Promise((resolve, reject) => resolve(true))), pathManager: { - getBackendDirPath: jest.fn().mockReturnValue("mockTargetDir") - } - } + getBackendDirPath: jest.fn().mockReturnValue('mockTargetDir'), + }, + }, + input: { + options: {}, + }, } as unknown as $TSContext; }); afterEach(() => { @@ -247,12 +260,14 @@ describe('update s3 permission walkthrough tests', () => { const mockDataBuilder = new S3MockDataBuilder(undefined); const currentCLIInputs = mockDataBuilder.removeMockTriggerFunction().getCLIInputs(); jest.spyOn(S3InputState.prototype, 'cliInputFileExists').mockImplementation(() => true); //CLI Input exists - jest.spyOn(S3InputState.prototype, 'getUserInput').mockImplementation(()=> currentCLIInputs); //simple-auth - jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async ()=>{ return }); + jest.spyOn(S3InputState.prototype, 'getUserInput').mockImplementation(() => currentCLIInputs); //simple-auth + jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async () => { + return; + }); jest.spyOn(AmplifyS3ResourceStackTransform.prototype, 'transform').mockImplementation(() => Promise.resolve()); //**Set Auth permissions in Expected Output (without Delete permissions) - const expectedCLIInputsJSON: S3UserInputs = mockDataBuilder.removeAuthPermission( S3PermissionType.DELETE ).getCLIInputs(); + const expectedCLIInputsJSON: S3UserInputs = mockDataBuilder.removeAuthPermission(S3PermissionType.DELETE).getCLIInputs(); //Update CLI walkthrough (update auth permission) prompter.pick = jest @@ -261,7 +276,7 @@ describe('update s3 permission walkthrough tests', () => { .mockResolvedValueOnce([S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ]); /** Update Auth Permission in CLI */ prompter.confirmContinue = jest.fn().mockReturnValueOnce(false); // Do you want to add a Lambda Trigger ? - stateManager.getMeta = jest.fn().mockReturnValue( S3MockDataBuilder.mockAmplifyMetaForUpdateWalkthrough ); + stateManager.getMeta = jest.fn().mockReturnValue(S3MockDataBuilder.mockAmplifyMetaForUpdateWalkthrough); const returnedResourcename = await updateWalkthrough(mockContext); expect(returnedResourcename).toEqual(S3MockDataBuilder.mockResourceName); expect(S3InputState.prototype.saveCliInputPayload).toHaveBeenCalledWith(expectedCLIInputsJSON); @@ -271,15 +286,17 @@ describe('update s3 permission walkthrough tests', () => { const mockDataBuilder = new S3MockDataBuilder(undefined); const currentCLIInputs = mockDataBuilder.removeMockTriggerFunction().getCLIInputs(); jest.spyOn(S3InputState.prototype, 'cliInputFileExists').mockImplementation(() => true); //CLI Input exists - jest.spyOn(S3InputState.prototype, 'getUserInput').mockImplementation(()=> currentCLIInputs); //simple-auth - jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async ()=>{ return }); + jest.spyOn(S3InputState.prototype, 'getUserInput').mockImplementation(() => currentCLIInputs); //simple-auth + jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async () => { + return; + }); jest.spyOn(AmplifyS3ResourceStackTransform.prototype, 'transform').mockImplementation(() => Promise.resolve()); //**Set Auth permissions in Expected Output (without Delete permissions) const expectedCLIInputsJSON: S3UserInputs = mockDataBuilder - .removeAuthPermission(S3PermissionType.DELETE) - .addGuestAccess([S3PermissionType.READ]) - .getCLIInputs(); + .removeAuthPermission(S3PermissionType.DELETE) + .addGuestAccess([S3PermissionType.READ]) + .getCLIInputs(); //Update CLI walkthrough (update auth permission) prompter.pick = jest @@ -289,7 +306,7 @@ describe('update s3 permission walkthrough tests', () => { .mockResolvedValueOnce([S3PermissionType.READ]); /** Update Guest Permission in CLI */ prompter.confirmContinue = jest.fn().mockReturnValueOnce(false); // Do you want to add a Lambda Trigger ? - stateManager.getMeta = jest.fn().mockReturnValue( S3MockDataBuilder.mockAmplifyMetaForUpdateWalkthrough ); + stateManager.getMeta = jest.fn().mockReturnValue(S3MockDataBuilder.mockAmplifyMetaForUpdateWalkthrough); const returnedResourcename = await updateWalkthrough(mockContext); expect(returnedResourcename).toEqual(S3MockDataBuilder.mockResourceName); expect(S3InputState.prototype.saveCliInputPayload).toHaveBeenCalledWith(expectedCLIInputsJSON); @@ -299,27 +316,27 @@ describe('update s3 permission walkthrough tests', () => { const mockDataBuilder = new S3MockDataBuilder(undefined); //start with auth+guest permissions const currentCLIInputs = mockDataBuilder - .removeMockTriggerFunction() - .addGuestAccess(undefined) //default guest access permissions - .getCLIInputs(); + .removeMockTriggerFunction() + .addGuestAccess(undefined) //default guest access permissions + .getCLIInputs(); jest.spyOn(S3InputState.prototype, 'cliInputFileExists').mockImplementation(() => true); //CLI Input exists - jest.spyOn(S3InputState.prototype, 'getUserInput').mockImplementation(()=> currentCLIInputs); //simple-auth - jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async ()=>{ return }); + jest.spyOn(S3InputState.prototype, 'getUserInput').mockImplementation(() => currentCLIInputs); //simple-auth + jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async () => { + return; + }); jest.spyOn(AmplifyS3ResourceStackTransform.prototype, 'transform').mockImplementation(() => Promise.resolve()); //**Set Auth permissions in Expected Output (without Delete permissions) - const expectedCLIInputsJSON: S3UserInputs = mockDataBuilder - .removeGuestAccess() - .getCLIInputs(); + const expectedCLIInputsJSON: S3UserInputs = mockDataBuilder.removeGuestAccess().getCLIInputs(); //Update CLI walkthrough (update auth permission) prompter.pick = jest .fn() .mockResolvedValueOnce(S3AccessType.AUTH_ONLY) // who should have access - .mockResolvedValueOnce(mockDataBuilder.defaultAuthPerms) /** Update Auth Permission in CLI */ + .mockResolvedValueOnce(mockDataBuilder.defaultAuthPerms); /** Update Auth Permission in CLI */ prompter.confirmContinue = jest.fn().mockReturnValueOnce(false); // Do you want to add a Lambda Trigger ? - stateManager.getMeta = jest.fn().mockReturnValue( S3MockDataBuilder.mockAmplifyMetaForUpdateWalkthrough ); + stateManager.getMeta = jest.fn().mockReturnValue(S3MockDataBuilder.mockAmplifyMetaForUpdateWalkthrough); const returnedResourcename = await updateWalkthrough(mockContext); expect(returnedResourcename).toEqual(S3MockDataBuilder.mockResourceName); expect(S3InputState.prototype.saveCliInputPayload).toHaveBeenCalledWith(expectedCLIInputsJSON); @@ -331,33 +348,30 @@ describe('update s3 permission walkthrough tests', () => { it('updateWalkthrough() simple-auth + update add group(individual) permission ', async () => { const mockDataBuilder = new S3MockDataBuilder(undefined); //start with simple auth permissions - const currentCLIInputs = mockDataBuilder - .removeMockTriggerFunction() - .getCLIInputs(); + const currentCLIInputs = mockDataBuilder.removeMockTriggerFunction().getCLIInputs(); //Update Group list function in context - mockContext.amplify.getUserPoolGroupList = ()=>Object.keys( mockDataBuilder.mockGroupAccess ); + mockContext.amplify.getUserPoolGroupList = () => Object.keys(mockDataBuilder.mockGroupAccess); jest.spyOn(S3InputState.prototype, 'cliInputFileExists').mockImplementation(() => true); //CLI Input exists - jest.spyOn(S3InputState.prototype, 'getUserInput').mockImplementation(()=> currentCLIInputs); //simple-auth - jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async ()=>{ return }); + jest.spyOn(S3InputState.prototype, 'getUserInput').mockImplementation(() => currentCLIInputs); //simple-auth + jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async () => { + return; + }); jest.spyOn(AmplifyS3ResourceStackTransform.prototype, 'transform').mockImplementation(() => Promise.resolve()); //**Set Auth permissions in Expected Output (without Delete permissions) - const expectedCLIInputsJSON: S3UserInputs = mockDataBuilder - .removeAuthAccess() - .addGroupAccess() - .getCLIInputs(); + const expectedCLIInputsJSON: S3UserInputs = mockDataBuilder.removeAuthAccess().addGroupAccess().getCLIInputs(); //Update CLI walkthrough (update auth permission) prompter.pick = jest .fn() - .mockResolvedValueOnce( UserPermissionTypeOptions.INDIVIDUAL_GROUPS ) // Restrict Access By - .mockResolvedValueOnce( ['mockAdminGroup', 'mockGuestGroup'] ) //Select Groups - .mockResolvedValueOnce( [S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ, S3PermissionType.DELETE] ) //what kind of access do you want for the admin group - .mockResolvedValueOnce( [S3PermissionType.READ] ) //what kind of access fo you want for the guest group + .mockResolvedValueOnce(UserPermissionTypeOptions.INDIVIDUAL_GROUPS) // Restrict Access By + .mockResolvedValueOnce(['mockAdminGroup', 'mockGuestGroup']) //Select Groups + .mockResolvedValueOnce([S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ, S3PermissionType.DELETE]) //what kind of access do you want for the admin group + .mockResolvedValueOnce([S3PermissionType.READ]); //what kind of access fo you want for the guest group prompter.confirmContinue = jest.fn().mockReturnValueOnce(false); // Do you want to add a Lambda Trigger ? - stateManager.getMeta = jest.fn().mockReturnValue( S3MockDataBuilder.mockAmplifyMetaForUpdateWalkthrough ); + stateManager.getMeta = jest.fn().mockReturnValue(S3MockDataBuilder.mockAmplifyMetaForUpdateWalkthrough); const returnedResourcename = await updateWalkthrough(mockContext); expect(returnedResourcename).toEqual(S3MockDataBuilder.mockResourceName); expect(S3InputState.prototype.saveCliInputPayload).toHaveBeenCalledWith(expectedCLIInputsJSON); @@ -365,41 +379,37 @@ describe('update s3 permission walkthrough tests', () => { it('addWalkthrough() simple-auth + update add (both) group and auth+guest permission ', async () => { const mockDataBuilder = new S3MockDataBuilder(undefined); //start with simple auth permissions - const currentCLIInputs = mockDataBuilder - .removeMockTriggerFunction() - .getCLIInputs(); + const currentCLIInputs = mockDataBuilder.removeMockTriggerFunction().getCLIInputs(); //Update Group list function in context - mockContext.amplify.getUserPoolGroupList = ()=>Object.keys( mockDataBuilder.mockGroupAccess ); + mockContext.amplify.getUserPoolGroupList = () => Object.keys(mockDataBuilder.mockGroupAccess); jest.spyOn(S3InputState.prototype, 'cliInputFileExists').mockImplementation(() => true); //CLI Input exists - jest.spyOn(S3InputState.prototype, 'getUserInput').mockImplementation(()=> currentCLIInputs); //simple-auth - jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async ()=>{ return }); + jest.spyOn(S3InputState.prototype, 'getUserInput').mockImplementation(() => currentCLIInputs); //simple-auth + jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async () => { + return; + }); jest.spyOn(AmplifyS3ResourceStackTransform.prototype, 'transform').mockImplementation(() => Promise.resolve()); //** Add GuestAccess, GroupAccess - const expectedCLIInputsJSON: S3UserInputs = mockDataBuilder - .addGuestAccess(undefined) - .addGroupAccess() - .getCLIInputs(); + const expectedCLIInputsJSON: S3UserInputs = mockDataBuilder.addGuestAccess(undefined).addGroupAccess().getCLIInputs(); //Update CLI walkthrough (update auth permission) prompter.pick = jest .fn() - .mockResolvedValueOnce( UserPermissionTypeOptions.BOTH ) // Restrict Access By - .mockResolvedValueOnce( S3AccessType.AUTH_AND_GUEST ) // Restrict Access By - .mockResolvedValueOnce( [S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ, S3PermissionType.DELETE] ) //select Auth permissions - .mockResolvedValueOnce( [S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ] ) //select Guest permissions - .mockResolvedValueOnce( ['mockAdminGroup', 'mockGuestGroup'] ) //Select Groups - .mockResolvedValueOnce( [S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ, S3PermissionType.DELETE] ) //select admin group permissions - .mockResolvedValueOnce( [S3PermissionType.READ] ) //select guest group permissions + .mockResolvedValueOnce(UserPermissionTypeOptions.BOTH) // Restrict Access By + .mockResolvedValueOnce(S3AccessType.AUTH_AND_GUEST) // Restrict Access By + .mockResolvedValueOnce([S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ, S3PermissionType.DELETE]) //select Auth permissions + .mockResolvedValueOnce([S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ]) //select Guest permissions + .mockResolvedValueOnce(['mockAdminGroup', 'mockGuestGroup']) //Select Groups + .mockResolvedValueOnce([S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ, S3PermissionType.DELETE]) //select admin group permissions + .mockResolvedValueOnce([S3PermissionType.READ]); //select guest group permissions prompter.confirmContinue = jest.fn().mockReturnValueOnce(false); // Do you want to add a Lambda Trigger ? - stateManager.getMeta = jest.fn().mockReturnValue( S3MockDataBuilder.mockAmplifyMetaForUpdateWalkthrough ); + stateManager.getMeta = jest.fn().mockReturnValue(S3MockDataBuilder.mockAmplifyMetaForUpdateWalkthrough); const returnedResourcename = await updateWalkthrough(mockContext); expect(returnedResourcename).toEqual(S3MockDataBuilder.mockResourceName); expect(S3InputState.prototype.saveCliInputPayload).toHaveBeenCalledWith(expectedCLIInputsJSON); }); - }); describe('update s3 lambda-trigger walkthrough tests', () => { @@ -439,6 +449,9 @@ describe('update s3 lambda-trigger walkthrough tests', () => { getBackendDirPath: jest.fn().mockReturnValue('mockTargetDir'), }, }, + input: { + options: {}, + }, } as unknown as $TSContext; }); afterEach(() => { @@ -452,7 +465,9 @@ describe('update s3 lambda-trigger walkthrough tests', () => { const currentCLIInputs = mockDataBuilder.removeMockTriggerFunction().getCLIInputs(); jest.spyOn(S3InputState.prototype, 'cliInputFileExists').mockImplementation(() => true); //CLI Input exists jest.spyOn(S3InputState.prototype, 'getUserInput').mockImplementation(() => currentCLIInputs); //simple-auth - jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async ()=>{ return }); + jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async () => { + return; + }); jest.spyOn(AmplifyS3ResourceStackTransform.prototype, 'transform').mockImplementation(() => Promise.resolve()); //**Set Auth permissions in Expected Output (without Delete permissions) @@ -488,7 +503,9 @@ describe('update s3 lambda-trigger walkthrough tests', () => { const currentCLIInputs = existingDataBuilder.addMockTriggerFunction(undefined).getCLIInputs(); jest.spyOn(S3InputState.prototype, 'cliInputFileExists').mockImplementation(() => true); //CLI Input exists jest.spyOn(S3InputState.prototype, 'getUserInput').mockImplementation(() => currentCLIInputs); //simple-auth - jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async ()=>{ return }); + jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async () => { + return; + }); jest.spyOn(AmplifyS3ResourceStackTransform.prototype, 'transform').mockImplementation(() => Promise.resolve()); //**Set simple auth and remove triggerFunction @@ -499,7 +516,11 @@ describe('update s3 lambda-trigger walkthrough tests', () => { prompter.pick = jest .fn() .mockResolvedValueOnce(S3AccessType.AUTH_ONLY) // who should have access - .mockResolvedValueOnce([S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ, S3PermissionType.DELETE]) /** Update Auth Permission in CLI */ + .mockResolvedValueOnce([ + S3PermissionType.CREATE_AND_UPDATE, + S3PermissionType.READ, + S3PermissionType.DELETE, + ]) /** Update Auth Permission in CLI */ .mockResolvedValueOnce(S3CLITriggerUpdateMenuOptions.REMOVE); /** Select one of Update/Remove Skip*/ stateManager.getMeta = jest.fn().mockReturnValue(S3MockDataBuilder.mockAmplifyMetaForUpdateWalkthroughLambda); @@ -524,7 +545,9 @@ describe('update s3 lambda-trigger walkthrough tests', () => { jest.spyOn(S3InputState.prototype, 'cliInputFileExists').mockImplementation(() => true); //CLI Input exists jest.spyOn(S3InputState.prototype, 'getUserInput').mockImplementation(() => currentCLIInputs); //simple-auth - jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async ()=>{ return }); + jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async () => { + return; + }); jest.spyOn(AmplifyS3ResourceStackTransform.prototype, 'transform').mockImplementation(() => Promise.resolve()); //**Set simple-auth and set mockExistingFunctionName1 as the new trigger function @@ -537,7 +560,11 @@ describe('update s3 lambda-trigger walkthrough tests', () => { prompter.pick = jest .fn() .mockResolvedValueOnce(S3AccessType.AUTH_ONLY) // who should have access - .mockResolvedValueOnce([S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ, S3PermissionType.DELETE]) /** Update Auth Permission in CLI */ + .mockResolvedValueOnce([ + S3PermissionType.CREATE_AND_UPDATE, + S3PermissionType.READ, + S3PermissionType.DELETE, + ]) /** Update Auth Permission in CLI */ .mockResolvedValueOnce(S3CLITriggerUpdateMenuOptions.UPDATE) /** Select one of Update/Remove Skip*/ .mockResolvedValueOnce(S3TriggerFunctionType.EXISTING_FUNCTION) .mockResolvedValueOnce(S3MockDataBuilder.mockExistingFunctionName1); @@ -565,7 +592,9 @@ describe('update s3 lambda-trigger walkthrough tests', () => { jest.spyOn(S3InputState.prototype, 'cliInputFileExists').mockImplementation(() => true); //CLI Input exists jest.spyOn(S3InputState.prototype, 'getUserInput').mockImplementation(() => currentCLIInputs); //simple-auth - jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation((async ()=>{ return })); + jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async () => { + return; + }); jest.spyOn(AmplifyS3ResourceStackTransform.prototype, 'transform').mockImplementation(() => Promise.resolve()); //**Set simple-auth and set mockExistingFunctionName1 as the new trigger function @@ -578,7 +607,11 @@ describe('update s3 lambda-trigger walkthrough tests', () => { prompter.pick = jest .fn() .mockResolvedValueOnce(S3AccessType.AUTH_ONLY) // who should have access - .mockResolvedValueOnce([S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ, S3PermissionType.DELETE]) /** Update Auth Permission in CLI */ + .mockResolvedValueOnce([ + S3PermissionType.CREATE_AND_UPDATE, + S3PermissionType.READ, + S3PermissionType.DELETE, + ]) /** Update Auth Permission in CLI */ .mockResolvedValueOnce(S3CLITriggerUpdateMenuOptions.UPDATE) /** Select one of Update/Remove Skip*/ .mockResolvedValueOnce(S3TriggerFunctionType.NEW_FUNCTION); @@ -608,7 +641,9 @@ describe('update s3 lambda-trigger walkthrough tests', () => { jest.spyOn(S3InputState.prototype, 'cliInputFileExists').mockImplementation(() => true); //CLI Input exists jest.spyOn(S3InputState.prototype, 'getUserInput').mockImplementation(() => currentCLIInputs); //simple-auth - jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async ()=>{ return }); + jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async () => { + return; + }); jest.spyOn(AmplifyS3ResourceStackTransform.prototype, 'transform').mockImplementation(() => Promise.resolve()); //**Set simple-auth and set mockExistingFunctionName1 as the new trigger function @@ -621,7 +656,11 @@ describe('update s3 lambda-trigger walkthrough tests', () => { prompter.pick = jest .fn() .mockResolvedValueOnce(S3AccessType.AUTH_ONLY) // who should have access - .mockResolvedValueOnce([S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ, S3PermissionType.DELETE]) /** Update Auth Permission in CLI */ + .mockResolvedValueOnce([ + S3PermissionType.CREATE_AND_UPDATE, + S3PermissionType.READ, + S3PermissionType.DELETE, + ]) /** Update Auth Permission in CLI */ .mockResolvedValueOnce(S3CLITriggerUpdateMenuOptions.UPDATE) /** Select one of Update/Remove Skip*/ .mockResolvedValueOnce(S3TriggerFunctionType.NEW_FUNCTION); @@ -656,13 +695,13 @@ describe('migrate s3 and update s3 permission walkthrough tests', () => { }, amplifyMeta: { auth: S3MockDataBuilder.mockAuthMeta, - storage : { + storage: { [S3MockDataBuilder.mockResourceName]: { - "service": "S3", - "providerPlugin": "awscloudformation", - "dependsOn": [] - } - } + service: 'S3', + providerPlugin: 'awscloudformation', + dependsOn: [], + }, + }, }, }; }, @@ -670,12 +709,15 @@ describe('migrate s3 and update s3 permission walkthrough tests', () => { getResourceStatus: () => { return { allResources: S3MockDataBuilder.getMockGetAllResourcesNoExistingLambdas() }; }, //eslint-disable-line - copyBatch : jest.fn().mockReturnValue( new Promise((resolve, reject) => resolve(true) ) ), - updateamplifyMetaAfterResourceAdd : jest.fn().mockReturnValue( new Promise((resolve, reject) => resolve(true) ) ), + copyBatch: jest.fn().mockReturnValue(new Promise((resolve, reject) => resolve(true))), + updateamplifyMetaAfterResourceAdd: jest.fn().mockReturnValue(new Promise((resolve, reject) => resolve(true))), pathManager: { - getBackendDirPath: jest.fn().mockReturnValue("mockTargetDir") - } - } + getBackendDirPath: jest.fn().mockReturnValue('mockTargetDir'), + }, + }, + input: { + options: {}, + }, } as unknown as $TSContext; }); afterEach(() => { @@ -690,30 +732,33 @@ describe('migrate s3 and update s3 permission walkthrough tests', () => { const mockStorageParams = {}; //used only for userpools const mockCFN = {}; //currently not used - const oldParams : MigrationParams = { - parametersFilepath : "mockParamsfilePath", - cfnFilepath : "mockOldCFNFilepath", - storageParamsFilepath : "oldStorageParamsFilepath", + const oldParams: MigrationParams = { + parametersFilepath: 'mockParamsfilePath', + cfnFilepath: 'mockOldCFNFilepath', + storageParamsFilepath: 'oldStorageParamsFilepath', parameters: mockParamsJSON, cfn: mockCFN, - storageParams: mockStorageParams - } + storageParams: mockStorageParams, + }; const mockDataBuilder = new S3MockDataBuilder(undefined); const currentCLIInputs = mockDataBuilder.removeMockTriggerFunction().getCLIInputs(); jest.spyOn(S3InputState.prototype, 'migrate'); - jest.spyOn(S3InputState.prototype, 'getOldS3ParamsForMigration').mockImplementation(()=>oldParams); + jest.spyOn(S3InputState.prototype, 'getOldS3ParamsForMigration').mockImplementation(() => oldParams); jest.spyOn(S3InputState.prototype, 'cliInputFileExists').mockImplementation(() => false); //CLI Input doesnt exist - requires migration - jest.spyOn(S3InputState.prototype, 'getUserInput').mockImplementation(()=> currentCLIInputs); //simple-auth - jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async ()=>{ return }); + jest.spyOn(S3InputState.prototype, 'getUserInput').mockImplementation(() => currentCLIInputs); //simple-auth + jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(async () => { + return; + }); jest.spyOn(AmplifyS3ResourceStackTransform.prototype, 'transform').mockImplementation(() => Promise.resolve()); //**Set Auth permissions in Expected Output (without Delete permissions) - const expectedCLIInputsJSON: S3UserInputs = mockDataBuilder.removeAuthPermission( S3PermissionType.DELETE ).getCLIInputs(); + const expectedCLIInputsJSON: S3UserInputs = mockDataBuilder.removeAuthPermission(S3PermissionType.DELETE).getCLIInputs(); - prompter.confirmContinue = jest.fn() - .mockReturnValueOnce(true) // File migration required to continue. Do you want to continue ? - .mockReturnValueOnce(false); // Do you want to add a Lambda Trigger ? + prompter.confirmContinue = jest + .fn() + .mockReturnValueOnce(true) // File migration required to continue. Do you want to continue ? + .mockReturnValueOnce(false); // Do you want to add a Lambda Trigger ? //Update CLI walkthrough (update auth permission) prompter.pick = jest @@ -721,52 +766,42 @@ describe('migrate s3 and update s3 permission walkthrough tests', () => { .mockResolvedValueOnce(S3AccessType.AUTH_ONLY) // who should have access .mockResolvedValueOnce([S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ]); /** Update Auth Permission in CLI */ - // - stateManager.getMeta = jest.fn().mockReturnValue( S3MockDataBuilder.mockAmplifyMetaForUpdateWalkthrough ); + // + stateManager.getMeta = jest.fn().mockReturnValue(S3MockDataBuilder.mockAmplifyMetaForUpdateWalkthrough); const returnedResourcename = await updateWalkthrough(mockContext); expect(returnedResourcename).toEqual(S3MockDataBuilder.mockResourceName); expect(S3InputState.prototype.saveCliInputPayload).toHaveBeenCalledWith(expectedCLIInputsJSON); }); - }); - -function getMigrationMockParametersJSON() : $TSAny { +function getMigrationMockParametersJSON(): $TSAny { const mockParametersJSON = { - "bucketName": "migratefix2c53c1f2a55574207949d2bb7a88258a4", - "authPolicyName": "s3_amplify_81ce520f", - "unauthPolicyName": "s3_amplify_81ce520f", - "authRoleName": { - "Ref": "AuthRoleName" - }, - "unauthRoleName": { - "Ref": "UnauthRoleName" - }, - "selectedGuestPermissions": [ - "s3:GetObject", - "s3:ListBucket" - ], - "selectedAuthenticatedPermissions": [ - "s3:PutObject", - "s3:GetObject", - "s3:ListBucket", - "s3:DeleteObject" - ], - "s3PermissionsAuthenticatedPublic": "s3:PutObject,s3:GetObject,s3:DeleteObject", - "s3PublicPolicy": "Public_policy_217e732f", - "s3PermissionsAuthenticatedUploads": "s3:PutObject", - "s3UploadsPolicy": "Uploads_policy_217e732f", - "s3PermissionsAuthenticatedProtected": "s3:PutObject,s3:GetObject,s3:DeleteObject", - "s3ProtectedPolicy": "Protected_policy_217e732f", - "s3PermissionsAuthenticatedPrivate": "s3:PutObject,s3:GetObject,s3:DeleteObject", - "s3PrivatePolicy": "Private_policy_217e732f", - "AuthenticatedAllowList": "ALLOW", - "s3ReadPolicy": "read_policy_217e732f", - "s3PermissionsGuestPublic": "DISALLOW", - "s3PermissionsGuestUploads": "DISALLOW", - "GuestAllowList": "DISALLOW", - "triggerFunction": "NONE" - } + bucketName: 'migratefix2c53c1f2a55574207949d2bb7a88258a4', + authPolicyName: 's3_amplify_81ce520f', + unauthPolicyName: 's3_amplify_81ce520f', + authRoleName: { + Ref: 'AuthRoleName', + }, + unauthRoleName: { + Ref: 'UnauthRoleName', + }, + selectedGuestPermissions: ['s3:GetObject', 's3:ListBucket'], + selectedAuthenticatedPermissions: ['s3:PutObject', 's3:GetObject', 's3:ListBucket', 's3:DeleteObject'], + s3PermissionsAuthenticatedPublic: 's3:PutObject,s3:GetObject,s3:DeleteObject', + s3PublicPolicy: 'Public_policy_217e732f', + s3PermissionsAuthenticatedUploads: 's3:PutObject', + s3UploadsPolicy: 'Uploads_policy_217e732f', + s3PermissionsAuthenticatedProtected: 's3:PutObject,s3:GetObject,s3:DeleteObject', + s3ProtectedPolicy: 'Protected_policy_217e732f', + s3PermissionsAuthenticatedPrivate: 's3:PutObject,s3:GetObject,s3:DeleteObject', + s3PrivatePolicy: 'Private_policy_217e732f', + AuthenticatedAllowList: 'ALLOW', + s3ReadPolicy: 'read_policy_217e732f', + s3PermissionsGuestPublic: 'DISALLOW', + s3PermissionsGuestUploads: 'DISALLOW', + GuestAllowList: 'DISALLOW', + triggerFunction: 'NONE', + }; return mockParametersJSON; } @@ -808,37 +843,33 @@ class S3MockDataBuilder { auth: { mockAuthName: S3MockDataBuilder.mockAuthMeta, }, - storage : { + storage: { [S3MockDataBuilder.mockResourceName]: { - service : 'S3', + service: 'S3', providerPlugin: 'awscloudformation', - dependsOn: [] - } - } - } + dependsOn: [], + }, + }, + }; static mockAmplifyMetaForUpdateWalkthroughLambda = { auth: { mockAuthName: S3MockDataBuilder.mockAuthMeta, }, - storage : { + storage: { [S3MockDataBuilder.mockResourceName]: { - service : 'S3', + service: 'S3', providerPlugin: 'awscloudformation', dependsOn: [ { - category: "function", + category: 'function', resourceName: S3MockDataBuilder.mockFunctionName, - attributes: [ - "Name", - "Arn", - "LambdaExecutionRole" - ] - } - ] - } - } - } + attributes: ['Name', 'Arn', 'LambdaExecutionRole'], + }, + ], + }, + }, + }; mockGroupAccess = { mockAdminGroup: [S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ, S3PermissionType.DELETE], @@ -876,29 +907,24 @@ class S3MockDataBuilder { } } - static getMockGetAllResources2ExistingLambdas(){ + static getMockGetAllResources2ExistingLambdas() { return [ - { service: 'Cognito', - serviceType: 'managed' }, + { service: 'Cognito', serviceType: 'managed' }, - { - service : AmplifySupportedService.LAMBDA, - resourceName : S3MockDataBuilder.mockExistingFunctionName1 - }, - { - service : AmplifySupportedService.LAMBDA, - resourceName : S3MockDataBuilder.mockExistingFunctionName2 - } - ] + { + service: AmplifySupportedService.LAMBDA, + resourceName: S3MockDataBuilder.mockExistingFunctionName1, + }, + { + service: AmplifySupportedService.LAMBDA, + resourceName: S3MockDataBuilder.mockExistingFunctionName2, + }, + ]; } - static getMockGetAllResourcesNoExistingLambdas(){ - return [ - { service: 'Cognito', - serviceType: 'managed' }, - ] + static getMockGetAllResourcesNoExistingLambdas() { + return [{ service: 'Cognito', serviceType: 'managed' }]; } - addGuestAccess(guestAccess: Array | undefined): S3MockDataBuilder { this.cliInputs.storageAccess = S3AccessType.AUTH_AND_GUEST; if (guestAccess) { @@ -909,14 +935,14 @@ class S3MockDataBuilder { return this; } - removeGuestAccess() : S3MockDataBuilder { + removeGuestAccess(): S3MockDataBuilder { this.cliInputs.storageAccess = S3AccessType.AUTH_ONLY; this.cliInputs.guestAccess = []; return this; } - addMockTriggerFunction(customMockFunctionName : string | undefined): S3MockDataBuilder { - if (customMockFunctionName){ + addMockTriggerFunction(customMockFunctionName: string | undefined): S3MockDataBuilder { + if (customMockFunctionName) { this.cliInputs.triggerFunction = customMockFunctionName; } else { this.cliInputs.triggerFunction = S3MockDataBuilder.mockFunctionName; @@ -934,10 +960,10 @@ class S3MockDataBuilder { return this; } - removeAuthPermission( permissionToBeRemoved : S3PermissionType ): S3MockDataBuilder { - const newPermissions = this.defaultAuthPerms.filter( permission => permission !== permissionToBeRemoved ); + removeAuthPermission(permissionToBeRemoved: S3PermissionType): S3MockDataBuilder { + const newPermissions = this.defaultAuthPerms.filter(permission => permission !== permissionToBeRemoved); this.cliInputs.authAccess = newPermissions; - return this + return this; } addGroupAccess(): S3MockDataBuilder { diff --git a/packages/amplify-category-storage/src/index.ts b/packages/amplify-category-storage/src/index.ts index da35d1d6ad6..de6032d7614 100644 --- a/packages/amplify-category-storage/src/index.ts +++ b/packages/amplify-category-storage/src/index.ts @@ -12,6 +12,12 @@ import { categoryName } from './constants'; import { updateConfigOnEnvInit } from './provider-utils/awscloudformation'; import { DDBStackTransform } from './provider-utils/awscloudformation/cdk-stack-builder/ddb-stack-transform'; import { transformS3ResourceStack } from './provider-utils/awscloudformation/cdk-stack-builder/s3-stack-transform'; +import { getAllDefaults } from './provider-utils/awscloudformation/default-values/s3-defaults'; +import { + S3AccessType, + S3PermissionType, + S3UserInputs, +} from './provider-utils/awscloudformation/service-walkthrough-types/s3-user-input-types'; import { DynamoDBInputState } from './provider-utils/awscloudformation/service-walkthroughs/dynamoDB-input-state'; import { headlessAddStorage, @@ -20,13 +26,6 @@ import { headlessUpdateStorage, } from './provider-utils/awscloudformation/storage-configuration-helpers'; export { categoryName as category } from './constants'; -export { AmplifyDDBResourceTemplate, AmplifyS3ResourceTemplate } from './provider-utils/awscloudformation/cdk-stack-builder/types'; -import { getAllDefaults } from './provider-utils/awscloudformation/default-values/s3-defaults'; -import { - S3AccessType, - S3PermissionType, - S3UserInputs, -} from './provider-utils/awscloudformation/service-walkthrough-types/s3-user-input-types'; export { S3UserInputs, S3UserInputTriggerFunctionParams, @@ -37,9 +36,9 @@ export { s3CreateStorageResource, s3GetResourceName, s3GetUserInput, + s3RegisterAdminTrigger, s3RemoveAdminLambdaTrigger, s3RemoveStorageLambdaTrigger, - s3RegisterAdminTrigger, } from './provider-utils/awscloudformation/service-walkthroughs/s3-resource-api'; export async function s3GetBucketUserInputDefault(project: $TSAny, shortId: string, accessType: S3AccessType): Promise { diff --git a/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/ddb-stack-builder.ts b/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/ddb-stack-builder.ts index 44dad1f403a..a0162d89a42 100644 --- a/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/ddb-stack-builder.ts +++ b/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/ddb-stack-builder.ts @@ -1,7 +1,7 @@ import * as cdk from '@aws-cdk/core'; import * as ddb from '@aws-cdk/aws-dynamodb'; import { DynamoDBCLIInputs, DynamoDBCLIInputsKeyType, FieldType } from '../service-walkthrough-types/dynamoDB-user-input-types'; -import { AmplifyDDBResourceTemplate } from './types'; +import { AmplifyDDBResourceTemplate } from '@aws-amplify/cli-extensibility-helper'; const CFN_TEMPLATE_FORMAT_VERSION = '2010-09-09'; const ROOT_CFN_DESCRIPTION = 'DDB Resource for AWS Amplify CLI'; diff --git a/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/ddb-stack-transform.ts b/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/ddb-stack-transform.ts index 22ac57b02a0..28cb1fff6f6 100644 --- a/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/ddb-stack-transform.ts +++ b/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/ddb-stack-transform.ts @@ -1,15 +1,16 @@ -import { DynamoDBCLIInputs } from '../service-walkthrough-types/dynamoDB-user-input-types'; -import { DynamoDBInputState } from '../service-walkthroughs/dynamoDB-input-state'; -import { AmplifyDDBResourceStack } from './ddb-stack-builder'; -import { AmplifyDDBResourceInputParameters, AmplifyDDBResourceTemplate } from './types'; -import { App } from '@aws-cdk/core'; +import { AmplifyDDBResourceTemplate } from '@aws-amplify/cli-extensibility-helper'; import * as cdk from '@aws-cdk/core'; +import { App } from '@aws-cdk/core'; +import { $TSAny, buildOverrideDir, JSONUtilities, pathManager } from 'amplify-cli-core'; +import { formatter, printer } from 'amplify-prompts'; import * as fs from 'fs-extra'; -import { JSONUtilities, pathManager, buildOverrideDir, $TSAny } from 'amplify-cli-core'; +import os from 'os'; import * as path from 'path'; -import { formatter, printer } from 'amplify-prompts'; import * as vm from 'vm2'; -import os from 'os'; +import { DynamoDBCLIInputs } from '../service-walkthrough-types/dynamoDB-user-input-types'; +import { DynamoDBInputState } from '../service-walkthroughs/dynamoDB-input-state'; +import { AmplifyDDBResourceStack } from './ddb-stack-builder'; +import { AmplifyDDBResourceInputParameters } from './types'; export class DDBStackTransform { app: App; diff --git a/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/s3-stack-builder.ts b/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/s3-stack-builder.ts index b32990a9c57..6fffaf43412 100644 --- a/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/s3-stack-builder.ts +++ b/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/s3-stack-builder.ts @@ -1,27 +1,31 @@ -import * as cdk from '@aws-cdk/core'; -import * as s3Cdk from '@aws-cdk/aws-s3'; +import { AmplifyS3ResourceTemplate } from '@aws-amplify/cli-extensibility-helper'; import * as iamCdk from '@aws-cdk/aws-iam'; import * as lambdaCdk from '@aws-cdk/aws-lambda'; -import { - AmplifyResourceCfnStack, - AmplifyS3ResourceTemplate, - AmplifyCfnParamType, - AmplifyBuildParamsPermissions, - AmplifyS3ResourceInputParameters, -} from './types'; -import { S3UserInputs, defaultS3UserInputs, GroupAccessType, S3PermissionType, S3UserInputTriggerFunctionParams, S3TriggerPrefixTransform, S3TriggerPrefixType, S3TriggerEventType } from '../service-walkthrough-types/s3-user-input-types'; -import { $TSAny, $TSContext, $TSObject, AmplifyCategories } from 'amplify-cli-core'; +import * as s3Cdk from '@aws-cdk/aws-s3'; import { HttpMethods } from '@aws-cdk/aws-s3'; +import * as cdk from '@aws-cdk/core'; +import { $TSAny, $TSContext, $TSObject, AmplifyCategories } from 'amplify-cli-core'; +import { + defaultS3UserInputs, + GroupAccessType, + S3PermissionType, + S3TriggerEventType, + S3TriggerPrefixTransform, + S3TriggerPrefixType, + S3UserInputs, + S3UserInputTriggerFunctionParams, +} from '../service-walkthrough-types/s3-user-input-types'; import * as s3AuthAPI from '../service-walkthroughs/s3-auth-api'; import { S3CFNDependsOn, S3CFNPermissionType, S3InputState } from '../service-walkthroughs/s3-user-input-state'; +import { AmplifyBuildParamsPermissions, AmplifyCfnParamType, AmplifyResourceCfnStack, AmplifyS3ResourceInputParameters } from './types'; export class AmplifyS3ResourceCfnStack extends AmplifyResourceCfnStack implements AmplifyS3ResourceTemplate { id: string; scope: cdk.Construct; s3Bucket!: s3Cdk.CfnBucket; s3BucketName: string; - notificationConfiguration : s3Cdk.CfnBucket.NotificationConfigurationProperty = { - lambdaConfigurations : [] + notificationConfiguration: s3Cdk.CfnBucket.NotificationConfigurationProperty = { + lambdaConfigurations: [], }; triggerLambdaPermissions?: lambdaCdk.CfnPermission; adminTriggerLambdaPermissions?: lambdaCdk.CfnPermission; @@ -56,13 +60,13 @@ export class AmplifyS3ResourceCfnStack extends AmplifyResourceCfnStack implement this.s3BucketName = this.buildBucketName(); this.s3DependsOnResources = []; this.notificationConfiguration = { - lambdaConfigurations : [] - } + lambdaConfigurations: [], + }; } - private getGroupListFromProps(): Array|undefined { - const groupList = (this._props.groupAccess)? Object.keys(this._props.groupAccess) : []; - return groupList; + private getGroupListFromProps(): Array | undefined { + const groupList = this._props.groupAccess ? Object.keys(this._props.groupAccess) : []; + return groupList; } public getS3ResourceFriendlyName(): string { @@ -77,34 +81,37 @@ export class AmplifyS3ResourceCfnStack extends AmplifyResourceCfnStack implement return this.s3DependsOnResources; } - private _addNotificationsLambdaConfigurations( newLambdaConfigurations : s3Cdk.CfnBucket.LambdaConfigurationProperty[] ){ + private _addNotificationsLambdaConfigurations(newLambdaConfigurations: s3Cdk.CfnBucket.LambdaConfigurationProperty[]) { const existingLambdaConfigurations = (this.notificationConfiguration as any).lambdaConfigurations; this.notificationConfiguration = { - lambdaConfigurations : existingLambdaConfigurations.concat(newLambdaConfigurations) - } + lambdaConfigurations: existingLambdaConfigurations.concat(newLambdaConfigurations), + }; } /** * configure trigger policy to handle triggerFunction and adminTriggerFunction (predictions) */ - private configureTriggerPolicy(){ + private configureTriggerPolicy() { let s3TriggerPolicyDefinition = undefined; //6.1 Configure Trigger policy group if (this._props.triggerFunction && this._props.triggerFunction != 'NONE') { s3TriggerPolicyDefinition = this.createTriggerPolicyDefinition('S3TriggerBucketPolicy', this._props.triggerFunction); } //6.2 Configure Trigger policy group with adminTrigger - if (this._props.adminTriggerFunction?.triggerFunction && - this._props.adminTriggerFunction.triggerFunction != 'NONE' && - this._props.adminTriggerFunction.triggerFunction !== this._props.triggerFunction ) { + if ( + this._props.adminTriggerFunction?.triggerFunction && + this._props.adminTriggerFunction.triggerFunction != 'NONE' && + this._props.adminTriggerFunction.triggerFunction !== this._props.triggerFunction + ) { const adminTriggerFunctionName = this._props.adminTriggerFunction.triggerFunction; //create/update s3TriggerPolicyGroup with [predictions] adminLambda - s3TriggerPolicyDefinition = (s3TriggerPolicyDefinition)? this.addFunctionToTriggerPolicyDefinition(s3TriggerPolicyDefinition, adminTriggerFunctionName) - : this.createTriggerPolicyDefinition('S3TriggerBucketPolicy', adminTriggerFunctionName); + s3TriggerPolicyDefinition = s3TriggerPolicyDefinition + ? this.addFunctionToTriggerPolicyDefinition(s3TriggerPolicyDefinition, adminTriggerFunctionName) + : this.createTriggerPolicyDefinition('S3TriggerBucketPolicy', adminTriggerFunctionName); } //6.3 Configure Trigger policy if groups are configured - if (s3TriggerPolicyDefinition){ - this.s3TriggerPolicy = this.createTriggerPolicyFromPolicyDefinition( s3TriggerPolicyDefinition ); + if (s3TriggerPolicyDefinition) { + this.s3TriggerPolicy = this.createTriggerPolicyFromPolicyDefinition(s3TriggerPolicyDefinition); } } @@ -119,17 +126,19 @@ export class AmplifyS3ResourceCfnStack extends AmplifyResourceCfnStack implement this.s3Bucket.applyRemovalPolicy(cdk.RemovalPolicy.RETAIN); //2. Configure Notifications on the S3 bucket. if (this._props.triggerFunction && this._props.triggerFunction != 'NONE') { - const triggerLambdaFunctionParams : S3UserInputTriggerFunctionParams = { - category : AmplifyCategories.STORAGE, - tag : 'triggerFunction', - triggerFunction : this._props.triggerFunction, - permissions : [S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ, S3PermissionType.DELETE], - triggerEvents : [ S3TriggerEventType.OBJ_PUT_POST_COPY, S3TriggerEventType.OBJ_REMOVED ], - triggerPrefix : [ { prefix : 'protected/', prefixTransform : S3TriggerPrefixTransform.ATTACH_REGION }, - { prefix : 'private/', prefixTransform : S3TriggerPrefixTransform.ATTACH_REGION }, - { prefix : 'public/', prefixTransform : S3TriggerPrefixTransform.ATTACH_REGION } ] - } - const newLambdaConfigurations = this.buildLambdaConfigFromTriggerParams( triggerLambdaFunctionParams ); + const triggerLambdaFunctionParams: S3UserInputTriggerFunctionParams = { + category: AmplifyCategories.STORAGE, + tag: 'triggerFunction', + triggerFunction: this._props.triggerFunction, + permissions: [S3PermissionType.CREATE_AND_UPDATE, S3PermissionType.READ, S3PermissionType.DELETE], + triggerEvents: [S3TriggerEventType.OBJ_PUT_POST_COPY, S3TriggerEventType.OBJ_REMOVED], + triggerPrefix: [ + { prefix: 'protected/', prefixTransform: S3TriggerPrefixTransform.ATTACH_REGION }, + { prefix: 'private/', prefixTransform: S3TriggerPrefixTransform.ATTACH_REGION }, + { prefix: 'public/', prefixTransform: S3TriggerPrefixTransform.ATTACH_REGION }, + ], + }; + const newLambdaConfigurations = this.buildLambdaConfigFromTriggerParams(triggerLambdaFunctionParams); this._addNotificationsLambdaConfigurations(newLambdaConfigurations); this.triggerLambdaPermissions = this.createInvokeFunctionS3Permission('TriggerPermissions', this._props.triggerFunction); this.s3Bucket.addDependsOn(this.triggerLambdaPermissions as lambdaCdk.CfnPermission); @@ -140,13 +149,18 @@ export class AmplifyS3ResourceCfnStack extends AmplifyResourceCfnStack implement this.s3DependsOnResources.push(this.buildS3DependsOnFunctionCfn(this._props.triggerFunction as string)); } //3. Configure (Predictions category) Admin Trigger Notifications on Bucket - if ( this._props.adminTriggerFunction?.triggerFunction && - this._props.adminTriggerFunction.triggerFunction != 'NONE' && - this._props.adminTriggerFunction.triggerFunction != this._props.triggerFunction) { - const adminLambdaConfigurations = this.buildLambdaConfigFromTriggerParams( this._props.adminTriggerFunction ); + if ( + this._props.adminTriggerFunction?.triggerFunction && + this._props.adminTriggerFunction.triggerFunction != 'NONE' && + this._props.adminTriggerFunction.triggerFunction != this._props.triggerFunction + ) { + const adminLambdaConfigurations = this.buildLambdaConfigFromTriggerParams(this._props.adminTriggerFunction); this._addNotificationsLambdaConfigurations(adminLambdaConfigurations); - this.adminTriggerLambdaPermissions = this.createInvokeFunctionS3Permission('AdminTriggerPermissions', this._props.adminTriggerFunction.triggerFunction ); - this.s3Bucket.addDependsOn(this.adminTriggerLambdaPermissions ); + this.adminTriggerLambdaPermissions = this.createInvokeFunctionS3Permission( + 'AdminTriggerPermissions', + this._props.adminTriggerFunction.triggerFunction, + ); + this.s3Bucket.addDependsOn(this.adminTriggerLambdaPermissions); /** * Add Depends On: FUNCTION service @@ -156,12 +170,13 @@ export class AmplifyS3ResourceCfnStack extends AmplifyResourceCfnStack implement } //Apply all Notifications configurations on S3Bucket; - if (this.notificationConfiguration.lambdaConfigurations && - (this.notificationConfiguration.lambdaConfigurations as s3Cdk.CfnBucket.LambdaConfigurationProperty[]).length > 0 ) { - this.s3Bucket.notificationConfiguration = this.notificationConfiguration; + if ( + this.notificationConfiguration.lambdaConfigurations && + (this.notificationConfiguration.lambdaConfigurations as s3Cdk.CfnBucket.LambdaConfigurationProperty[]).length > 0 + ) { + this.s3Bucket.notificationConfiguration = this.notificationConfiguration; } - //4. Create IAM policies to control Cognito pool access to S3 bucket this.createAndSetIAMPolicies(); @@ -170,11 +185,7 @@ export class AmplifyS3ResourceCfnStack extends AmplifyResourceCfnStack implement if (groupList && groupList.length > 0) { const authResourceName: string = await s3AuthAPI.getAuthResourceARN(context); this.authResourceName = authResourceName; - this.s3GroupPolicyList = this.createS3AmplifyGroupPolicies( - authResourceName, - groupList, - this._props.groupAccess as GroupAccessType, - ); + this.s3GroupPolicyList = this.createS3AmplifyGroupPolicies(authResourceName, groupList, this._props.groupAccess as GroupAccessType); this.addGroupParams(authResourceName); @@ -191,12 +202,11 @@ export class AmplifyS3ResourceCfnStack extends AmplifyResourceCfnStack implement //6. Configure Trigger Policy for trigger function and adminTriggerFunction this.configureTriggerPolicy(); - } public addGroupParams(authResourceName: string): AmplifyS3CfnParameters | undefined { const groupList = this.getGroupListFromProps(); - if (groupList && groupList.length > 0 ) { + if (groupList && groupList.length > 0) { let s3CfnParams: Array = [ { params: [`auth${authResourceName}UserPoolId`], @@ -218,25 +228,21 @@ export class AmplifyS3ResourceCfnStack extends AmplifyResourceCfnStack implement return undefined; } - private createTriggerLambdaCFNParams( triggerParameterName: string, triggerFunction : string ){ + private createTriggerLambdaCFNParams(triggerParameterName: string, triggerFunction: string) { const triggerFunctionARN = `function${triggerFunction}Arn`; const triggerFunctionName = `function${triggerFunction}Name`; const triggerFunctionLambdaExecutionRole = `function${triggerFunction}LambdaExecutionRole`; const params = [triggerFunctionARN, triggerFunctionName, triggerFunctionLambdaExecutionRole]; - const s3CfnTriggerFunctionParams :any[] = params.map(param => ( - { - params: [param], - paramType: 'String', - default: param, - } - )) - s3CfnTriggerFunctionParams.push( - { - params: [triggerParameterName], - paramType: 'String', - } - ); - return s3CfnTriggerFunctionParams; + const s3CfnTriggerFunctionParams: any[] = params.map(param => ({ + params: [param], + paramType: 'String', + default: param, + })); + s3CfnTriggerFunctionParams.push({ + params: [triggerParameterName], + paramType: 'String', + }); + return s3CfnTriggerFunctionParams; } public addParameters() { @@ -270,15 +276,20 @@ export class AmplifyS3ResourceCfnStack extends AmplifyResourceCfnStack implement }, ]; if (this._props.triggerFunction && this._props.triggerFunction != 'NONE') { - const triggerFunctionCFNParams = this.createTriggerLambdaCFNParams( 'triggerFunction', this._props.triggerFunction ); - s3CfnParams = s3CfnParams.concat(triggerFunctionCFNParams) + const triggerFunctionCFNParams = this.createTriggerLambdaCFNParams('triggerFunction', this._props.triggerFunction); + s3CfnParams = s3CfnParams.concat(triggerFunctionCFNParams); } - if (this._props.adminTriggerFunction?.triggerFunction && - this._props.adminTriggerFunction.triggerFunction != 'NONE' && - this._props.adminTriggerFunction.triggerFunction != this._props.triggerFunction ){ - const adminTriggerFunctionCFNParams = this.createTriggerLambdaCFNParams( 'adminTriggerFunction', this._props.adminTriggerFunction.triggerFunction ); - s3CfnParams = s3CfnParams.concat(adminTriggerFunctionCFNParams) + if ( + this._props.adminTriggerFunction?.triggerFunction && + this._props.adminTriggerFunction.triggerFunction != 'NONE' && + this._props.adminTriggerFunction.triggerFunction != this._props.triggerFunction + ) { + const adminTriggerFunctionCFNParams = this.createTriggerLambdaCFNParams( + 'adminTriggerFunction', + this._props.adminTriggerFunction.triggerFunction, + ); + s3CfnParams = s3CfnParams.concat(adminTriggerFunctionCFNParams); } //insert into the stack @@ -355,9 +366,9 @@ export class AmplifyS3ResourceCfnStack extends AmplifyResourceCfnStack implement ); } - emptyNotificationsConfiguration(){ + emptyNotificationsConfiguration() { return { - lambdaConfigurations : [] + lambdaConfigurations: [], }; } @@ -404,25 +415,25 @@ export class AmplifyS3ResourceCfnStack extends AmplifyResourceCfnStack implement return lambdaConfigurations; } - filterRuleAppendRegionToLambdaTriggerPrefix( triggerPrefix: S3TriggerPrefixType ){ - const regionRef = cdk.Fn.ref('AWS::Region') + filterRuleAppendRegionToLambdaTriggerPrefix(triggerPrefix: S3TriggerPrefixType) { + const regionRef = cdk.Fn.ref('AWS::Region'); const filterRule = { - name :'prefix', - value: cdk.Fn.join('', [triggerPrefix.prefix, regionRef]) - }; + name: 'prefix', + value: cdk.Fn.join('', [triggerPrefix.prefix, regionRef]), + }; return filterRule; } - filterRulePlainStringLambdaTriggerPrefix( triggerPrefix: S3TriggerPrefixType ) { + filterRulePlainStringLambdaTriggerPrefix(triggerPrefix: S3TriggerPrefixType) { const filterRule = { - name :'prefix', - value: triggerPrefix.prefix - }; + name: 'prefix', + value: triggerPrefix.prefix, + }; return filterRule; } - buildTriggerPrefixRule(triggerPrefix : S3TriggerPrefixType ){ - if ( triggerPrefix.prefixTransform === S3TriggerPrefixTransform.ATTACH_REGION ){ + buildTriggerPrefixRule(triggerPrefix: S3TriggerPrefixType) { + if (triggerPrefix.prefixTransform === S3TriggerPrefixTransform.ATTACH_REGION) { const filterRule = this.filterRuleAppendRegionToLambdaTriggerPrefix(triggerPrefix); return filterRule; } else { @@ -431,26 +442,28 @@ export class AmplifyS3ResourceCfnStack extends AmplifyResourceCfnStack implement } } - buildLambdaConfigFromTriggerParams( functionParams:S3UserInputTriggerFunctionParams ):s3Cdk.CfnBucket.LambdaConfigurationProperty[] { - let lambdaConfigurations:s3Cdk.CfnBucket.LambdaConfigurationProperty[] = []; + buildLambdaConfigFromTriggerParams(functionParams: S3UserInputTriggerFunctionParams): s3Cdk.CfnBucket.LambdaConfigurationProperty[] { + let lambdaConfigurations: s3Cdk.CfnBucket.LambdaConfigurationProperty[] = []; const triggerFunctionArnRef = cdk.Fn.ref(`function${functionParams.triggerFunction}Arn`); - if( functionParams.permissions ){ - for( const triggerEvent of functionParams.triggerEvents ){ //S3ObjectCreate/Deleted - if (functionParams.triggerPrefix ){ //S3 folder to watch for triggers ( should be unqiue across trigger functions) - for ( const triggerPrefixDefinition of functionParams.triggerPrefix ){ - const lambdaConfig : $TSAny = { - event: triggerEvent, - function : triggerFunctionArnRef, - filter : { - s3Key: { - rules : [ this.buildTriggerPrefixRule( triggerPrefixDefinition ) ] //single rule - only single prefix supported - } - } - }; - lambdaConfigurations.push(lambdaConfig); - } + if (functionParams.permissions) { + for (const triggerEvent of functionParams.triggerEvents) { + //S3ObjectCreate/Deleted + if (functionParams.triggerPrefix) { + //S3 folder to watch for triggers ( should be unqiue across trigger functions) + for (const triggerPrefixDefinition of functionParams.triggerPrefix) { + const lambdaConfig: $TSAny = { + event: triggerEvent, + function: triggerFunctionArnRef, + filter: { + s3Key: { + rules: [this.buildTriggerPrefixRule(triggerPrefixDefinition)], //single rule - only single prefix supported + }, + }, + }; + lambdaConfigurations.push(lambdaConfig); } } + } } return lambdaConfigurations; } @@ -522,7 +535,7 @@ export class AmplifyS3ResourceCfnStack extends AmplifyResourceCfnStack implement /*************************************************************************************************** * Lambda Trigger Permissions : Allow S3 to invoke the trigger function ***************************************************************************************************/ - createInvokeFunctionS3Permission( logicalId : string, triggerFunctionName : string ): lambdaCdk.CfnPermission { + createInvokeFunctionS3Permission(logicalId: string, triggerFunctionName: string): lambdaCdk.CfnPermission { const sourceArn = cdk.Fn.join('', ['arn:aws:s3:::', this.buildBucketName()]); let resourceDefinition: lambdaCdk.CfnPermissionProps = { @@ -745,7 +758,7 @@ export class AmplifyS3ResourceCfnStack extends AmplifyResourceCfnStack implement * @param triggerFunctionName * @returns */ - private createTriggerPolicyDefinition( logicalId : string, triggerFunctionName : string ): IAmplifyPolicyDefinition{ + private createTriggerPolicyDefinition(logicalId: string, triggerFunctionName: string): IAmplifyPolicyDefinition { let policyDefinition: IAmplifyPolicyDefinition = { logicalId, isPolicyNameAbsolute: true, // set if policyName is not a reference @@ -765,23 +778,23 @@ export class AmplifyS3ResourceCfnStack extends AmplifyResourceCfnStack implement return policyDefinition; } - addFunctionToTriggerPolicyDefinition( policyDefinition :IAmplifyPolicyDefinition , functionName : string ){ - const newRoleRef = `function${functionName}LambdaExecutionRole`; - if ( policyDefinition.roleRefs && policyDefinition.roleRefs.includes(newRoleRef) ){ - return policyDefinition; - } - policyDefinition.roleRefs = (policyDefinition.roleRefs)?policyDefinition.roleRefs.concat([newRoleRef]): [newRoleRef]; - return policyDefinition; + addFunctionToTriggerPolicyDefinition(policyDefinition: IAmplifyPolicyDefinition, functionName: string) { + const newRoleRef = `function${functionName}LambdaExecutionRole`; + if (policyDefinition.roleRefs && policyDefinition.roleRefs.includes(newRoleRef)) { + return policyDefinition; + } + policyDefinition.roleRefs = policyDefinition.roleRefs ? policyDefinition.roleRefs.concat([newRoleRef]) : [newRoleRef]; + return policyDefinition; } //S3TriggerBucketPolicy - Policy to control trigger function access to S3 bucket - createTriggerPolicyFromPolicyDefinition( policyDefinition :IAmplifyPolicyDefinition ){ + createTriggerPolicyFromPolicyDefinition(policyDefinition: IAmplifyPolicyDefinition) { const policy: iamCdk.CfnPolicy = this.createIAMPolicy(policyDefinition, false /*action is array*/); return policy; } //S3TriggerBucketPolicy - Policy to control trigger function access to S3 bucket - createTriggerPolicy( logicalId: string, triggerFunctionName : string ): iamCdk.CfnPolicy { + createTriggerPolicy(logicalId: string, triggerFunctionName: string): iamCdk.CfnPolicy { let policyDefinition: IAmplifyPolicyDefinition = { logicalId, isPolicyNameAbsolute: true, // set if policyName is not a reference @@ -1046,4 +1059,3 @@ interface IAmplifyPolicyDefinition { type AmplifyS3Conditions = Record; type AmplifyS3CfnParameters = Record; - diff --git a/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/s3-stack-transform.ts b/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/s3-stack-transform.ts index 785c4d2bf09..804a5cb0dca 100644 --- a/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/s3-stack-transform.ts +++ b/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/s3-stack-transform.ts @@ -18,7 +18,8 @@ import os from 'os'; import { S3PermissionType, S3UserInputs } from '../service-walkthrough-types/s3-user-input-types'; import { canResourceBeTransformed, S3CFNDependsOn, S3CFNPermissionType, S3InputState } from '../service-walkthroughs/s3-user-input-state'; import { AmplifyS3ResourceCfnStack } from './s3-stack-builder'; -import { AmplifyBuildParamsPermissions, AmplifyCfnParamType, AmplifyS3ResourceInputParameters, AmplifyS3ResourceTemplate } from './types'; +import { AmplifyS3ResourceTemplate } from '@aws-amplify/cli-extensibility-helper'; +import { AmplifyBuildParamsPermissions, AmplifyCfnParamType, AmplifyS3ResourceInputParameters } from './types'; /** * Builds S3 resource stack, ingest overrides.ts and generates output-files. diff --git a/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/types.ts b/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/types.ts index e3a6b56a60e..b1a702958fd 100644 --- a/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/types.ts +++ b/packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/types.ts @@ -1,162 +1,129 @@ +import { AmplifyCDKL1 } from '@aws-amplify/cli-extensibility-helper'; import * as cdk from '@aws-cdk/core'; -import * as ddb from '@aws-cdk/aws-dynamodb'; -import * as s3Cdk from '@aws-cdk/aws-s3'; -import * as iamCdk from '@aws-cdk/aws-iam'; import { $TSObject } from 'amplify-cli-core'; -//CDK - L1 methods to store CFN gen related information -export interface AmplifyCDKL1 { - addCfnParameter(props: cdk.CfnParameterProps, logicalId: string): void; - addCfnOutput(props: cdk.CfnOutputProps, logicalId: string): void; - addCfnMapping(props: cdk.CfnMappingProps, logicalId: string): void; - addCfnCondition(props: cdk.CfnConditionProps, logicalId: string): void; - addCfnResource(props: cdk.CfnResourceProps, logicalId: string): void; -} - -export interface AmplifyDDBResourceTemplate extends AmplifyCDKL1{ - dynamoDBTable?: ddb.CfnTable; -} - export interface AmplifyDDBResourceInputParameters { - tableName: string, - partitionKeyName: string, - partitionKeyType: string, - sortKeyName?: string, - sortKeyType?: string -} - - -export interface AmplifyS3ResourceTemplate extends AmplifyCDKL1{ - s3Bucket?: s3Cdk.CfnBucket; - s3AuthPublicPolicy?: iamCdk.CfnPolicy - s3AuthProtectedPolicy?: iamCdk.CfnPolicy - s3AuthPrivatePolicy?: iamCdk.CfnPolicy - s3AuthUploadPolicy?: iamCdk.CfnPolicy - s3AuthReadPolicy?: iamCdk.CfnPolicy - s3GuestPublicPolicy?: iamCdk.CfnPolicy - s3GuestUploadPolicy?: iamCdk.CfnPolicy - s3GuestReadPolicy?: iamCdk.CfnPolicy + tableName: string; + partitionKeyName: string; + partitionKeyType: string; + sortKeyName?: string; + sortKeyType?: string; } export type AmplifyCfnParamType = { - params : Array - paramType : string - default? : string -} + params: Array; + paramType: string; + default?: string; +}; export interface AmplifyS3ResourceInputParameters { - bucketName? : string, - resourceName?: string, - policyUUID? : string, - authPolicyName? : string, - unauthPolicyName? : string, - authRoleName? : $TSObject, - unauthRoleName? : $TSObject, - s3PublicPolicy? : string, - s3PrivatePolicy? : string, //default:"NONE" - s3ProtectedPolicy? : string, - s3UploadsPolicy? : string, - s3ReadPolicy? : string, - s3PermissionsAuthenticatedPublic? : string, - s3PermissionsAuthenticatedProtected? : string, - s3PermissionsAuthenticatedPrivate? : string, - s3PermissionsAuthenticatedUploads? : string, - s3PermissionsGuestPublic? : string, - s3PermissionsGuestUploads? : string, - AuthenticatedAllowList? : string, - GuestAllowList? : string, - selectedGuestPermissions? : Array, - selectedAuthenticatedPermissions? : Array, - triggerFunction? : string, - adminTriggerFunction? : string, + bucketName?: string; + resourceName?: string; + policyUUID?: string; + authPolicyName?: string; + unauthPolicyName?: string; + authRoleName?: $TSObject; + unauthRoleName?: $TSObject; + s3PublicPolicy?: string; + s3PrivatePolicy?: string; //default:"NONE" + s3ProtectedPolicy?: string; + s3UploadsPolicy?: string; + s3ReadPolicy?: string; + s3PermissionsAuthenticatedPublic?: string; + s3PermissionsAuthenticatedProtected?: string; + s3PermissionsAuthenticatedPrivate?: string; + s3PermissionsAuthenticatedUploads?: string; + s3PermissionsGuestPublic?: string; + s3PermissionsGuestUploads?: string; + AuthenticatedAllowList?: string; + GuestAllowList?: string; + selectedGuestPermissions?: Array; + selectedAuthenticatedPermissions?: Array; + triggerFunction?: string; + adminTriggerFunction?: string; } //Base class for all storage resource stacks ( S3, DDB ) export class AmplifyResourceCfnStack extends cdk.Stack implements AmplifyCDKL1 { - - _cfnParameterMap: Map = new Map(); - constructor(scope: cdk.Construct, id: string ) { - super(scope, id, undefined); + _cfnParameterMap: Map = new Map(); + constructor(scope: cdk.Construct, id: string) { + super(scope, id, undefined); + } + + /** + * + * @param props :cdk.CfnOutputProps + * @param logicalId: : lodicalId of the Resource + */ + addCfnOutput(props: cdk.CfnOutputProps, logicalId: string): void { + try { + new cdk.CfnOutput(this, logicalId, props); + } catch (error) { + throw error; } - - /** - * - * @param props :cdk.CfnOutputProps - * @param logicalId: : lodicalId of the Resource - */ - addCfnOutput(props: cdk.CfnOutputProps, logicalId: string): void { - try { - new cdk.CfnOutput(this, logicalId, props); - } catch (error) { - throw error; - } + } + + /** + * + * @param props + * @param logicalId + */ + addCfnMapping(props: cdk.CfnMappingProps, logicalId: string): void { + try { + new cdk.CfnMapping(this, logicalId, props); + } catch (error) { + throw error; } - - /** - * - * @param props - * @param logicalId - */ - addCfnMapping(props: cdk.CfnMappingProps, logicalId: string): void { - try { - new cdk.CfnMapping(this, logicalId, props); - } catch (error) { - throw error; - } - } - - /** - * - * @param props - * @param logicalId - */ - addCfnCondition(props: cdk.CfnConditionProps, logicalId: string): void { - try { - new cdk.CfnCondition(this, logicalId, props); - } catch (error) { - throw error; - } + } + + /** + * + * @param props + * @param logicalId + */ + addCfnCondition(props: cdk.CfnConditionProps, logicalId: string): void { + try { + new cdk.CfnCondition(this, logicalId, props); + } catch (error) { + throw error; } - /** - * - * @param props - * @param logicalId - */ - addCfnResource(props: cdk.CfnResourceProps, logicalId: string): cdk.CfnResource { - try { - return new cdk.CfnResource(this, logicalId, props); - } catch (error) { - throw error; - } + } + /** + * + * @param props + * @param logicalId + */ + addCfnResource(props: cdk.CfnResourceProps, logicalId: string): cdk.CfnResource { + try { + return new cdk.CfnResource(this, logicalId, props); + } catch (error) { + throw error; } - /** - * - * @param props - * @param logicalId - */ - addCfnParameter(props: cdk.CfnParameterProps, logicalId: string): void { - try { - if (this._cfnParameterMap.has(logicalId)) { - throw new Error('logical Id already Exists'); - } - this._cfnParameterMap.set(logicalId, new cdk.CfnParameter(this, logicalId, props)); - } catch (error) { - throw error; + } + /** + * + * @param props + * @param logicalId + */ + addCfnParameter(props: cdk.CfnParameterProps, logicalId: string): void { + try { + if (this._cfnParameterMap.has(logicalId)) { + throw new Error('logical Id already Exists'); } + this._cfnParameterMap.set(logicalId, new cdk.CfnParameter(this, logicalId, props)); + } catch (error) { + throw error; } + } - //Generate convert cdk stack to cloudformation - public renderCloudFormationTemplate = (): string => { - return this._toCloudFormation() - }; - + //Generate convert cdk stack to cloudformation + public renderCloudFormationTemplate = (): string => { + return this._toCloudFormation(); + }; } //Types used in Build/Params.json export enum AmplifyBuildParamsPermissions { - ALLOW = 'ALLOW', - DISALLOW = 'DISALLOW' + ALLOW = 'ALLOW', + DISALLOW = 'DISALLOW', } - - - diff --git a/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/dynamoDb-walkthrough.ts b/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/dynamoDb-walkthrough.ts index c278bee32ab..37a77cba694 100644 --- a/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/dynamoDb-walkthrough.ts +++ b/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/dynamoDb-walkthrough.ts @@ -85,8 +85,9 @@ export async function updateWalkthrough(context: $TSContext) { // Check if we need to migrate to cli-inputs.json const cliInputsState = new DynamoDBInputState(resourceName); + const headlessMigrate = context.input.options?.yes || context.input.options?.forcePush || context.input.options?.headless; if (!cliInputsState.cliInputFileExists()) { - if (context.exeInfo?.forcePush || (await prompter.yesOrNo('File migration required to continue. Do you want to continue?', true))) { + if (headlessMigrate || (await prompter.yesOrNo('File migration required to continue. Do you want to continue?', true))) { cliInputsState.migrate(); const stackGenerator = new DDBStackTransform(resourceName); stackGenerator.transform(); diff --git a/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough.ts b/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough.ts index 719f202ec14..1f1e1a39a4a 100644 --- a/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough.ts +++ b/packages/amplify-category-storage/src/provider-utils/awscloudformation/service-walkthroughs/s3-walkthrough.ts @@ -133,8 +133,9 @@ export async function updateWalkthrough(context: $TSContext) { let cliInputsState = new S3InputState(storageResourceName, undefined); //Check if migration is required + const headlessMigrate = context.input.options?.yes || context.input.options?.forcePush || context.input.options?.headless; if (!cliInputsState.cliInputFileExists()) { - if (context.exeInfo?.forcePush || (await prompter.confirmContinue('File migration required to continue. Do you want to continue?'))) { + if (headlessMigrate || (await prompter.confirmContinue('File migration required to continue. Do you want to continue?'))) { //migrate auth and storage await cliInputsState.migrate(context); const stackGenerator = new AmplifyS3ResourceStackTransform(storageResourceName, context); @@ -438,10 +439,14 @@ function getS3ResourcesFromAmplifyMeta(amplifyMeta: $TSMeta): Record { +export async function createNewLambdaAndUpdateCFN( + context: $TSContext, + triggerFunctionName: string | undefined, + policyUUID: string | undefined, +): Promise { const targetDir = context.amplify.pathManager.getBackendDirPath(); - const newShortUUID = (policyUUID)?policyUUID: buildShortUUID(); - const newFunctionName = (triggerFunctionName)?triggerFunctionName:`S3Trigger${newShortUUID}`; + const newShortUUID = policyUUID ? policyUUID : buildShortUUID(); + const newFunctionName = triggerFunctionName ? triggerFunctionName : `S3Trigger${newShortUUID}`; const pluginDir = __dirname; const defaults = { functionName: `${newFunctionName}`, @@ -500,12 +505,11 @@ async function getExistingFunctionsForTrigger( excludeFunctionName: string | undefined, isInteractive: boolean, ): Promise> { - //Build the list of functions to be excluded ( existing-trigger, adminTrigger ) - let excludeFunctionList = (excludeFunctionName)?[excludeFunctionName]:[]; + let excludeFunctionList = excludeFunctionName ? [excludeFunctionName] : []; const adminTriggerFunction = await s3GetAdminTriggerFunctionName(context); - if(adminTriggerFunction && adminTriggerFunction != 'NONE'){ - excludeFunctionList.push(adminTriggerFunction) + if (adminTriggerFunction && adminTriggerFunction != 'NONE') { + excludeFunctionList.push(adminTriggerFunction); } let lambdaResourceNames: Array = await getLambdaFunctionList(context); @@ -573,7 +577,7 @@ function getCLITriggerStateEvent(triggerFlowType: S3CLITriggerFlow, existingTrig * @returns TriggerFunction name */ async function interactiveCreateNewLambdaAndUpdateCFN(context: $TSContext) { - const newTriggerFunction = await createNewLambdaAndUpdateCFN(context, undefined /*default function name*/, undefined /*unique shortid*/ ); + const newTriggerFunction = await createNewLambdaAndUpdateCFN(context, undefined /*default function name*/, undefined /*unique shortid*/); await askAndOpenFunctionEditor(context, newTriggerFunction); return newTriggerFunction; } diff --git a/packages/amplify-category-storage/tsconfig.json b/packages/amplify-category-storage/tsconfig.json index 67148798164..b6d8d07f066 100644 --- a/packages/amplify-category-storage/tsconfig.json +++ b/packages/amplify-category-storage/tsconfig.json @@ -15,6 +15,6 @@ { "path": "../amplify-headless-interface" }, { "path": "../amplify-prompts" }, { "path": "../amplify-util-import" }, - { "path": "../amplify-cli-overrides-helper" } + { "path": "../amplify-cli-extensibility-helper" } ] } diff --git a/packages/amplify-cli-overrides-helper/.npmignore b/packages/amplify-cli-extensibility-helper/.npmignore similarity index 100% rename from packages/amplify-cli-overrides-helper/.npmignore rename to packages/amplify-cli-extensibility-helper/.npmignore diff --git a/packages/amplify-cli-overrides-helper/CHANGELOG.md b/packages/amplify-cli-extensibility-helper/CHANGELOG.md similarity index 100% rename from packages/amplify-cli-overrides-helper/CHANGELOG.md rename to packages/amplify-cli-extensibility-helper/CHANGELOG.md diff --git a/packages/amplify-cli-overrides-helper/README.md b/packages/amplify-cli-extensibility-helper/README.md similarity index 100% rename from packages/amplify-cli-overrides-helper/README.md rename to packages/amplify-cli-extensibility-helper/README.md diff --git a/packages/amplify-cli-overrides-helper/package.json b/packages/amplify-cli-extensibility-helper/package.json similarity index 69% rename from packages/amplify-cli-overrides-helper/package.json rename to packages/amplify-cli-extensibility-helper/package.json index d08681d3c8e..3063afc1838 100644 --- a/packages/amplify-cli-overrides-helper/package.json +++ b/packages/amplify-cli-extensibility-helper/package.json @@ -1,11 +1,11 @@ { - "name": "@aws-amplify/cli-overrides-helper", + "name": "@aws-amplify/cli-extensibility-helper", "version": "1.0.0", - "description": "Amplify CLI Overrides Helper utility package", + "description": "Amplify CLI Extensibility Helper utility package", "repository": { "type": "git", "url": "https://github.com/aws-amplify/amplify-cli.git", - "directory": "packages/amplify-cli-overrides-helper" + "directory": "packages/amplify-cli-extensibility-helper" }, "author": "Amazon Web Services", "license": "Apache-2.0", @@ -28,8 +28,12 @@ }, "dependencies": { "amplify-prompts": "1.1.2", - "@aws-amplify/amplify-category-auth": "1.0.0", - "@aws-amplify/amplify-category-storage": "1.0.0", + "@aws-cdk/aws-s3": "~1.124.0", + "@aws-cdk/core": "~1.124.0", + "@aws-cdk/aws-dynamodb": "~1.124.0", + "@aws-cdk/aws-cognito": "~1.124.0", + "@aws-cdk/aws-lambda": "~1.124.0", + "@aws-cdk/aws-iam": "~1.124.0", "@aws-amplify/amplify-category-custom": "1.0.0", "amplify-cli-core": "1.31.1" }, diff --git a/packages/amplify-cli-overrides-helper/src/helpers/project-info.ts b/packages/amplify-cli-extensibility-helper/src/helpers/project-info.ts similarity index 100% rename from packages/amplify-cli-overrides-helper/src/helpers/project-info.ts rename to packages/amplify-cli-extensibility-helper/src/helpers/project-info.ts diff --git a/packages/amplify-cli-extensibility-helper/src/index.ts b/packages/amplify-cli-extensibility-helper/src/index.ts new file mode 100644 index 00000000000..29122f4335e --- /dev/null +++ b/packages/amplify-cli-extensibility-helper/src/index.ts @@ -0,0 +1,7 @@ +export { AmplifyRootStackTemplate } from './types/project/types'; +export { AmplifyAuthCognitoStackTemplate, AmplifyUserPoolGroupStackTemplate } from './types/auth/types'; +import { addCDKResourceDependency } from '@aws-amplify/amplify-category-custom'; +export { AmplifyDDBResourceTemplate, AmplifyS3ResourceTemplate, AmplifyCDKL1 } from './types/storage/types'; +import { getProjectInfo } from './helpers/project-info'; + +export { getProjectInfo, addCDKResourceDependency }; diff --git a/packages/amplify-cli-overrides-helper/src/types.ts b/packages/amplify-cli-extensibility-helper/src/types.ts similarity index 100% rename from packages/amplify-cli-overrides-helper/src/types.ts rename to packages/amplify-cli-extensibility-helper/src/types.ts diff --git a/packages/amplify-category-auth/src/provider-utils/awscloudformation/auth-stack-builder/types.ts b/packages/amplify-cli-extensibility-helper/src/types/auth/types.ts similarity index 100% rename from packages/amplify-category-auth/src/provider-utils/awscloudformation/auth-stack-builder/types.ts rename to packages/amplify-cli-extensibility-helper/src/types/auth/types.ts diff --git a/packages/amplify-provider-awscloudformation/src/root-stack-builder/types.ts b/packages/amplify-cli-extensibility-helper/src/types/project/types.ts similarity index 100% rename from packages/amplify-provider-awscloudformation/src/root-stack-builder/types.ts rename to packages/amplify-cli-extensibility-helper/src/types/project/types.ts diff --git a/packages/amplify-cli-extensibility-helper/src/types/storage/types.ts b/packages/amplify-cli-extensibility-helper/src/types/storage/types.ts new file mode 100644 index 00000000000..d40579ca434 --- /dev/null +++ b/packages/amplify-cli-extensibility-helper/src/types/storage/types.ts @@ -0,0 +1,35 @@ +import * as cdk from '@aws-cdk/core'; +import * as ddb from '@aws-cdk/aws-dynamodb'; +import * as s3Cdk from '@aws-cdk/aws-s3'; +import * as iamCdk from '@aws-cdk/aws-iam'; + +//CDK - L1 methods to store CFN gen related information +export interface AmplifyCDKL1 { + addCfnParameter(props: cdk.CfnParameterProps, logicalId: string): void; + addCfnOutput(props: cdk.CfnOutputProps, logicalId: string): void; + addCfnMapping(props: cdk.CfnMappingProps, logicalId: string): void; + addCfnCondition(props: cdk.CfnConditionProps, logicalId: string): void; + addCfnResource(props: cdk.CfnResourceProps, logicalId: string): void; +} + +export interface AmplifyDDBResourceTemplate extends AmplifyCDKL1 { + dynamoDBTable?: ddb.CfnTable; +} + +export interface AmplifyS3ResourceTemplate extends AmplifyCDKL1 { + s3Bucket?: s3Cdk.CfnBucket; + s3AuthPublicPolicy?: iamCdk.CfnPolicy; + s3AuthProtectedPolicy?: iamCdk.CfnPolicy; + s3AuthPrivatePolicy?: iamCdk.CfnPolicy; + s3AuthUploadPolicy?: iamCdk.CfnPolicy; + s3AuthReadPolicy?: iamCdk.CfnPolicy; + s3GuestPublicPolicy?: iamCdk.CfnPolicy; + s3GuestUploadPolicy?: iamCdk.CfnPolicy; + s3GuestReadPolicy?: iamCdk.CfnPolicy; +} + +//Types used in Build/Params.json +export enum AmplifyBuildParamsPermissions { + ALLOW = 'ALLOW', + DISALLOW = 'DISALLOW', +} diff --git a/packages/amplify-cli-overrides-helper/tsconfig.json b/packages/amplify-cli-extensibility-helper/tsconfig.json similarity index 100% rename from packages/amplify-cli-overrides-helper/tsconfig.json rename to packages/amplify-cli-extensibility-helper/tsconfig.json diff --git a/packages/amplify-cli-overrides-helper/src/index.ts b/packages/amplify-cli-overrides-helper/src/index.ts deleted file mode 100644 index 5e3f7905c0d..00000000000 --- a/packages/amplify-cli-overrides-helper/src/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -//import { AmplifyRootStackTemplate } from 'amplify-provider-awscloudformation'; -import { AmplifyAuthCognitoStackTemplate } from '@aws-amplify/amplify-category-auth'; -import { addCDKResourceDependency } from '@aws-amplify/amplify-category-custom'; -import { AmplifyDDBResourceTemplate, AmplifyS3ResourceTemplate } from '@aws-amplify/amplify-category-storage'; -import { getProjectInfo } from './helpers/project-info'; - -export { - getProjectInfo, - //AmplifyRootStackTemplate, - AmplifyAuthCognitoStackTemplate, - AmplifyDDBResourceTemplate, - AmplifyS3ResourceTemplate, - addCDKResourceDependency, -}; diff --git a/packages/amplify-provider-awscloudformation/package.json b/packages/amplify-provider-awscloudformation/package.json index 7b93091e2ef..6468303ef02 100644 --- a/packages/amplify-provider-awscloudformation/package.json +++ b/packages/amplify-provider-awscloudformation/package.json @@ -123,7 +123,8 @@ "proxy-agent": "^5.0.0", "rimraf": "^3.0.0", "vm2": "^3.9.3", - "xstate": "^4.14.0" + "xstate": "^4.14.0", + "@aws-amplify/cli-extensibility-helper": "1.0.0" }, "devDependencies": { "@types/columnify": "^1.5.0", diff --git a/packages/amplify-provider-awscloudformation/resources/overrides-resource/override.ts b/packages/amplify-provider-awscloudformation/resources/overrides-resource/override.ts index 2832816feaf..019ac34c490 100644 --- a/packages/amplify-provider-awscloudformation/resources/overrides-resource/override.ts +++ b/packages/amplify-provider-awscloudformation/resources/overrides-resource/override.ts @@ -1,3 +1,3 @@ -import { AmplifyRootStackTemplate } from '@aws-amplify/cli-overrides-helper'; +import { AmplifyRootStackTemplate } from '@aws-amplify/cli-extensibility-helper'; export function override(resources: AmplifyRootStackTemplate) {} diff --git a/packages/amplify-provider-awscloudformation/resources/overrides-resource/package.json b/packages/amplify-provider-awscloudformation/resources/overrides-resource/package.json index deef309eb16..ba1450aa702 100644 --- a/packages/amplify-provider-awscloudformation/resources/overrides-resource/package.json +++ b/packages/amplify-provider-awscloudformation/resources/overrides-resource/package.json @@ -8,7 +8,7 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { - "@aws-amplify/cli-overrides-helper": "1.1.0-ext11.0" + "@aws-amplify/cli-extensibility-helper": "1.1.0-ext15.0" }, "devDependencies": { "typescript": "^4.2.4" diff --git a/packages/amplify-provider-awscloudformation/src/index.ts b/packages/amplify-provider-awscloudformation/src/index.ts index 179ee7d364a..7c9c7770fd3 100644 --- a/packages/amplify-provider-awscloudformation/src/index.ts +++ b/packages/amplify-provider-awscloudformation/src/index.ts @@ -47,7 +47,6 @@ import { transformResourceWithOverrides } from './override-manager'; export { transformResourceWithOverrides } from './override-manager'; import { rootStackFileName } from './push-resources'; export { rootStackFileName } from './push-resources'; -export { AmplifyRootStackTemplate } from './root-stack-builder'; function init(context) { return initializer.run(context); @@ -67,7 +66,6 @@ function onInitSuccessful(context) { return initializer.onInitSuccessful(context); } - function exportResources(context, resourceList, exportType) { return resourceExport.run(context, resourceList, exportType); } @@ -76,7 +74,6 @@ function exportedStackResourcesUpdateMeta(context: $TSContext, stackName: string return exportUpdateMeta.run(context, stackName); } - function pushResources(context, resourceList) { return resourcePusher.run(context, resourceList); } diff --git a/packages/amplify-provider-awscloudformation/src/root-stack-builder/index.ts b/packages/amplify-provider-awscloudformation/src/root-stack-builder/index.ts index e6611d7b1ba..ab1f6cc6ebe 100644 --- a/packages/amplify-provider-awscloudformation/src/root-stack-builder/index.ts +++ b/packages/amplify-provider-awscloudformation/src/root-stack-builder/index.ts @@ -1,2 +1 @@ export { AmplifyRootStackTransform } from './root-stack-transform'; -export { AmplifyRootStackTemplate } from './types'; diff --git a/packages/amplify-provider-awscloudformation/src/root-stack-builder/root-stack-builder.ts b/packages/amplify-provider-awscloudformation/src/root-stack-builder/root-stack-builder.ts index ff38fbd5b90..77a571a6518 100644 --- a/packages/amplify-provider-awscloudformation/src/root-stack-builder/root-stack-builder.ts +++ b/packages/amplify-provider-awscloudformation/src/root-stack-builder/root-stack-builder.ts @@ -1,7 +1,7 @@ import * as cdk from '@aws-cdk/core'; import * as s3 from '@aws-cdk/aws-s3'; import * as iam from '@aws-cdk/aws-iam'; -import { AmplifyRootStackTemplate } from './types'; +import { AmplifyRootStackTemplate } from '@aws-amplify/cli-extensibility-helper'; import { IStackSynthesizer, ISynthesisSession } from '@aws-cdk/core'; const CFN_TEMPLATE_FORMAT_VERSION = '2010-09-09'; diff --git a/packages/amplify-provider-awscloudformation/src/root-stack-builder/root-stack-transform.ts b/packages/amplify-provider-awscloudformation/src/root-stack-builder/root-stack-transform.ts index 9453ac47cd5..146476424b4 100644 --- a/packages/amplify-provider-awscloudformation/src/root-stack-builder/root-stack-transform.ts +++ b/packages/amplify-provider-awscloudformation/src/root-stack-builder/root-stack-transform.ts @@ -1,15 +1,14 @@ -import { AmplifyRootStackTemplate } from './types'; -import { $TSContext, CFNTemplateFormat, Template, pathManager, writeCFNTemplate, buildOverrideDir, $TSAny } from 'amplify-cli-core'; -import { AmplifyRootStack, AmplifyRootStackOutputs } from './root-stack-builder'; -import { RootStackSythesizer } from './stack-synthesizer'; -import { App } from '@aws-cdk/core'; import * as cdk from '@aws-cdk/core'; -import * as path from 'path'; +import { App } from '@aws-cdk/core'; +import { $TSAny, $TSContext, buildOverrideDir, CFNTemplateFormat, pathManager, Template, writeCFNTemplate } from 'amplify-cli-core'; import * as amplifyPrinter from 'amplify-prompts'; +import { printer } from 'amplify-prompts'; import * as fs from 'fs-extra'; import os from 'os'; +import * as path from 'path'; import * as vm from 'vm2'; -import { printer } from 'amplify-prompts'; +import { AmplifyRootStack, AmplifyRootStackOutputs } from './root-stack-builder'; +import { RootStackSythesizer } from './stack-synthesizer'; export class AmplifyRootStackTransform { private app: App | undefined;