Skip to content

Commit

Permalink
(fix) Call Auth migration from S3 migration for all auth resources in…
Browse files Browse the repository at this point in the history
… S3 (aws-amplify#8511)

* (fix) Call Auth migration from S3 migration for all auth resources used by S3

* (fix) use invokePluginMethod instead of direct category calls

* (fix) unit-test for s3 migration

Co-authored-by: Sachin Panemangalore <[email protected]>
  • Loading branch information
sachscode and Sachin Panemangalore committed Nov 10, 2021
1 parent a5a1c12 commit 9bea739
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 18 deletions.
10 changes: 8 additions & 2 deletions packages/amplify-category-auth/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ const {
} = require('./provider-utils/awscloudformation/utils/auth-sms-workflow-helper');
const { AuthInputState } = require('./provider-utils/awscloudformation/auth-inputs-manager/auth-input-state');
const { printer } = require('amplify-prompts');
const { checkAuthResourceMigration } = require('./provider-utils/awscloudformation/utils/migrate-override-resource');
const { privateKeys } = require('./provider-utils/awscloudformation/constants');
const { checkAuthResourceMigration } = require('./provider-utils/awscloudformation/utils/check-for-auth-migration');

// this function is being kept for temporary compatability.
async function add(context, skipNextSteps = false) {
Expand Down Expand Up @@ -82,6 +82,10 @@ function canResourceBeTransformed(resourceName) {
return resourceInputState.cliInputFileExists();
}

async function migrateAuthResource( context, resourceName ){
await checkAuthResourceMigration( context, resourceName );
}

async function externalAuthEnable(context, externalCategory, resourceName, requirements) {
const { amplify } = context;
const serviceMetadata = getSupportedServices.supportedServices;
Expand All @@ -103,7 +107,7 @@ async function externalAuthEnable(context, externalCategory, resourceName, requi
}
currentAuthName = await getAuthResourceName(context);
// check for migration when auth has been enabled
checkAuthResourceMigration(context, currentAuthName);
await checkAuthResourceMigration(context, currentAuthName);
const cliState = new AuthInputState(currentAuthName);
currentAuthParams = await cliState.loadResourceParameters(context, cliState.getCLIInputPayload());

Expand Down Expand Up @@ -496,6 +500,7 @@ async function isSMSWorkflowEnabled(context, resourceName) {

module.exports = {
externalAuthEnable,
migrateAuthResource,
checkRequirements,
add,
migrate,
Expand All @@ -517,4 +522,5 @@ module.exports = {
AmplifyUserPoolGroupTransform,
transformCategoryStack,
AmplifyAuthCognitoStackTemplate,

};
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import {
S3TriggerFunctionType,
S3UserInputs,
} from '../../../../provider-utils/awscloudformation/service-walkthrough-types/s3-user-input-types';
import * as s3AuthAPI from '../../../../provider-utils/awscloudformation/service-walkthroughs/s3-auth-api';
import { S3CLITriggerUpdateMenuOptions, UserPermissionTypeOptions } from '../../../../provider-utils/awscloudformation/service-walkthroughs/s3-questions';

jest.mock('amplify-cli-core');
jest.mock('amplify-prompts');
jest.mock('../../../../provider-utils/awscloudformation/service-walkthroughs/s3-user-input-state');
jest.mock('../../../../provider-utils/awscloudformation/cdk-stack-builder/s3-stack-transform');
jest.mock('../../../../provider-utils/awscloudformation/service-walkthroughs/s3-auth-api');
jest.mock('uuid');

describe('add s3 walkthrough tests', () => {
Expand Down Expand Up @@ -61,6 +63,9 @@ describe('add s3 walkthrough tests', () => {
it('addWalkthrough() simple-auth test', async () => {
jest.spyOn(S3InputState.prototype, 'saveCliInputPayload').mockImplementation(() => true);
jest.spyOn(AmplifyS3ResourceStackTransform.prototype, 'transform').mockImplementation(() => Promise.resolve());
jest.spyOn(s3AuthAPI, 'migrateAuthDependencyResource').mockReturnValue(new Promise((resolve, _reject)=>{
process.nextTick(() => resolve(undefined));
}));

const mockDataBuilder = new S3MockDataBuilder(undefined);
const expectedCLIInputsJSON: S3UserInputs = mockDataBuilder.getCLIInputs();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ export const run = async (context: $TSContext) => {
}
} else if (amplifyMeta[categoryName][selectedResourceName].service === AmplifySupportedService.S3 ) {
// S3 migration logic goes in here
const resourceInputState = new S3InputState(selectedResourceName, undefined);
if (!resourceInputState.cliInputFileExists()) {
const s3ResourceInputState = new S3InputState(selectedResourceName, undefined);
if (!s3ResourceInputState.cliInputFileExists()) {
if (await prompter.yesOrNo('File migration required to continue. Do you want to continue?', true)) {
resourceInputState.migrate();
await s3ResourceInputState.migrate(context); //migrate auth and storage config resources
const stackGenerator = new AmplifyS3ResourceStackTransform(selectedResourceName, context);
stackGenerator.transform( CLISubCommandType.MIGRATE );
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { $TSAny, $TSContext } from "amplify-cli-core";
import { S3UserInputs } from "../service-walkthrough-types/s3-user-input-types";
import { S3InputState } from "./s3-user-input-state";
import { $TSAny, $TSContext} from "amplify-cli-core";
import { printer } from "amplify-prompts";
import { AmplifyCategories } from "amplify-cli-core";

/* This file contains all functions interacting with AUTH category */

//UPSTREAM API: function to be called from Storage to fetch or update Auth resources

/**
* Get the name of the Auth resource used by S3
* @param context used to fetch all auth resources used by storage(S3)
* @returns Name of the auth resource used by S3
*/
export async function getAuthResourceARN( context : $TSContext ) : Promise<string> {
let authResources = (await context.amplify.getResourceStatus('auth')).allResources;
authResources = authResources.filter((resource: $TSAny) => resource.service === 'Cognito');
Expand All @@ -13,3 +19,19 @@ export async function getAuthResourceARN( context : $TSContext ) : Promise<stri
}
return authResources[0].resourceName as string;
}
/**
* Migrate all Auth resources used by Storage(S3) for Override feature.
* @param context - used to fetch auth resources and to migrate auth resources for override-feature.
*/
export async function migrateAuthDependencyResource( context : $TSContext ) {
const authResourceName = await getAuthResourceARN(context);
try {
await context.amplify.invokePluginMethod(context,
AmplifyCategories.AUTH, undefined,
'migrateAuthResource',
[context, authResourceName ]);
} catch (error) {
printer.error(error as string);
throw error;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { ResourceDoesNotExistError, ResourceAlreadyExistsError, $TSContext } from 'amplify-cli-core';
import { ResourceDoesNotExistError,
ResourceAlreadyExistsError,
$TSContext,
ConfigurationError} from 'amplify-cli-core';

import { printer } from 'amplify-prompts';

export async function printErrorNoResourcesToUpdate( context : $TSContext ){
Expand All @@ -12,3 +16,9 @@ export async function printErrorAlreadyCreated( context : $TSContext ){
printer.warn(errMessage);
await context.usageData.emitError(new ResourceAlreadyExistsError(errMessage));
}

export async function printErrorAuthResourceMigrationFailed( context : $TSContext ){
const errMessage = 'Auth migration has failed';
printer.warn(errMessage);
await context.usageData.emitError(new ConfigurationError(errMessage));
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { S3AccessType, S3PermissionType, S3UserInputs, GroupAccessType } from '../service-walkthrough-types/s3-user-input-types';
import { $TSObject, AmplifyCategories, AmplifySupportedService } from 'amplify-cli-core';
import { $TSContext, $TSObject, AmplifyCategories, AmplifySupportedService } from 'amplify-cli-core';
import { JSONUtilities, pathManager } from 'amplify-cli-core';
import { CLIInputSchemaValidator } from 'amplify-cli-core';
import * as fs from 'fs-extra';
import * as path from 'path';
import { buildShortUUID } from './s3-walkthrough';
import { migrateAuthDependencyResource } from './s3-auth-api';
import { printer } from "amplify-prompts";


type ResourcRefType = {
Expand Down Expand Up @@ -186,7 +188,13 @@ export class S3InputState {
}
}

public migrate(){
public async migrate(context : $TSContext ){
try {
await migrateAuthDependencyResource(context);
} catch( error ) {
printer.error(`Migration for Auth resource failed with error : ${error as string}`)
throw error;
}
const oldS3Params : MigrationParams = this.getOldS3ParamsForMigration();
const cliInputs : S3UserInputs = this.genInputParametersForMigration( oldS3Params );
this.saveCliInputPayload(cliInputs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ import {
askAndOpenFunctionEditor,
S3CLITriggerUpdateMenuOptions,
} from './s3-questions';
import { printErrorAlreadyCreated, printErrorNoResourcesToUpdate } from './s3-errors';
import { printErrorAlreadyCreated, printErrorAuthResourceMigrationFailed, printErrorNoResourcesToUpdate } from './s3-errors';
import { getAllDefaults } from '../default-values/s3-defaults';

import { migrateAuthDependencyResource } from './s3-auth-api';
module.exports = {
addWalkthrough /* Add walkthrough for S3 resource */,
updateWalkthrough /* Update walkthrough for S3 resource */,
migrate: migrateCategory /* Migrate function to migrate from non-cdk to cdk implementation */,
migrate: migrateStorageCategory /* Migrate function to migrate from non-cdk to cdk implementation */,
getIAMPolicies /* Utility function to get IAM policies - cloudformation from actions */,
};

Expand All @@ -53,6 +53,14 @@ export async function addWalkthrough(context: $TSContext, defaultValuesFilename:
const { amplify } = context;
const amplifyMeta = stateManager.getMeta();

//Migrate auth category if required
try {
await migrateAuthDependencyResource(context)
} catch ( error ){
await printErrorAuthResourceMigrationFailed(context);
exitOnNextTick(0);
}

//First ask customers to configure Auth on the S3 resource, invoke auth workflow
await askAndInvokeAuthWorkflow(context);
const resourceName = await getS3ResourceNameFromMeta(amplifyMeta);
Expand Down Expand Up @@ -109,7 +117,7 @@ export async function addWalkthrough(context: $TSContext, defaultValuesFilename:
* @param context
* @returns resourceName
*/
export async function updateWalkthrough(context: $TSAny) {
export async function updateWalkthrough(context: $TSContext) {
const amplifyMeta = stateManager.getMeta();
const resourceName: string | undefined = await getS3ResourceNameFromMeta(amplifyMeta);
if (resourceName === undefined) {
Expand All @@ -127,7 +135,8 @@ export async function updateWalkthrough(context: $TSAny) {
//Check if migration is required
if (!cliInputsState.cliInputFileExists()) {
if (context.exeInfo?.forcePush || (await prompter.confirmContinue('File migration required to continue. Do you want to continue?'))) {
cliInputsState.migrate();
//migrate auth and storage
await cliInputsState.migrate( context );
const stackGenerator = new AmplifyS3ResourceStackTransform(resourceName, context);
await stackGenerator.transform(CLISubCommandType.UPDATE); //generates cloudformation
} else {
Expand Down Expand Up @@ -182,11 +191,11 @@ export async function updateWalkthrough(context: $TSAny) {
* @param context
* @param resourceName
*/
export async function migrateCategory(context: $TSAny, resourceName: $TSAny): Promise<string | undefined> {
export async function migrateStorageCategory(context: $TSContext, resourceName: string): Promise<string | undefined> {
let cliInputsState = new S3InputState(resourceName, undefined);
//Check if migration is required
if (!cliInputsState.cliInputFileExists()) {
cliInputsState.migrate();
await cliInputsState.migrate( context );
const stackGenerator = new AmplifyS3ResourceStackTransform(resourceName, context);
await stackGenerator.transform(CLISubCommandType.MIGRATE);
return stackGenerator.getCFN();
Expand Down

0 comments on commit 9bea739

Please sign in to comment.