UNPKG

@aws-amplify/amplify-category-storage

Version:

amplify-cli storage plugin

440 lines • 21.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.S3InputState = exports.canResourceBeTransformed = exports.S3StorageParamsPermissionType = exports.S3CFNPermissionType = void 0; const lodash_1 = __importDefault(require("lodash")); const amplify_cli_core_1 = require("@aws-amplify/amplify-cli-core"); const amplify_prompts_1 = require("@aws-amplify/amplify-prompts"); const fs = __importStar(require("fs-extra")); const path = __importStar(require("path")); const s3_user_input_types_1 = require("../service-walkthrough-types/s3-user-input-types"); const s3_auth_api_1 = require("./s3-auth-api"); const s3_walkthrough_1 = require("./s3-walkthrough"); var S3CFNPermissionType; (function (S3CFNPermissionType) { S3CFNPermissionType["CREATE"] = "s3:PutObject"; S3CFNPermissionType["READ"] = "s3:GetObject"; S3CFNPermissionType["DELETE"] = "s3:DeleteObject"; S3CFNPermissionType["LIST"] = "s3:ListBucket"; })(S3CFNPermissionType = exports.S3CFNPermissionType || (exports.S3CFNPermissionType = {})); var S3StorageParamsPermissionType; (function (S3StorageParamsPermissionType) { S3StorageParamsPermissionType["CREATE_AND_UPDATE"] = "create/update"; S3StorageParamsPermissionType["READ"] = "read"; S3StorageParamsPermissionType["DELETE"] = "delete"; })(S3StorageParamsPermissionType = exports.S3StorageParamsPermissionType || (exports.S3StorageParamsPermissionType = {})); function canResourceBeTransformed(context, resourceName) { const resourceInputState = new S3InputState(context, resourceName, undefined); return resourceInputState.cliInputFileExists(); } exports.canResourceBeTransformed = canResourceBeTransformed; class S3InputState { constructor(context, resourceName, userInput) { this.context = context; this._category = amplify_cli_core_1.AmplifyCategories.STORAGE; this._service = amplify_cli_core_1.AmplifySupportedService.S3; const projectBackendDirPath = amplify_cli_core_1.pathManager.getBackendDirPath(); this._cliInputsFilePath = path.resolve(path.join(projectBackendDirPath, amplify_cli_core_1.AmplifyCategories.STORAGE, resourceName, 'cli-inputs.json')); this._resourceName = resourceName; this.buildFilePath = path.resolve(path.join(projectBackendDirPath, amplify_cli_core_1.AmplifyCategories.STORAGE, resourceName, 'build')); if (userInput) { this._inputPayload = userInput; } else { if (this.cliInputFileExists()) { this._inputPayload = this.getCliInputPayload(); } else { return; } } void this.isCLIInputsValid(this._inputPayload); } getOldS3ParamsForMigration() { const backendDir = amplify_cli_core_1.pathManager.getBackendDirPath(); const oldParametersFilepath = path.join(backendDir, amplify_cli_core_1.AmplifyCategories.STORAGE, this._resourceName, 'parameters.json'); const oldCFNFilepath = path.join(backendDir, amplify_cli_core_1.AmplifyCategories.STORAGE, this._resourceName, 's3-cloudformation-template.json'); const oldStorageParamsFilepath = path.join(backendDir, amplify_cli_core_1.AmplifyCategories.STORAGE, this._resourceName, `storage-params.json`); const oldParameters = amplify_cli_core_1.JSONUtilities.readJson(oldParametersFilepath, { throwIfNotExist: true }); const oldCFN = amplify_cli_core_1.JSONUtilities.readJson(oldCFNFilepath, { throwIfNotExist: true }); const oldStorageParams = amplify_cli_core_1.JSONUtilities.readJson(oldStorageParamsFilepath, { throwIfNotExist: false }) || {}; const oldParams = { parametersFilepath: oldParametersFilepath, cfnFilepath: oldCFNFilepath, storageParamsFilepath: oldStorageParamsFilepath, parameters: oldParameters, cfn: oldCFN, storageParams: oldStorageParams, }; return oldParams; } inferAuthPermissions(oldParams) { if (oldParams.selectedAuthenticatedPermissions && ((oldParams.s3PermissionsAuthenticatedPublic && oldParams.s3PermissionsAuthenticatedPublic != 'DISALLOW') || (oldParams.s3PermissionsAuthenticatedPrivate && oldParams.s3PermissionsAuthenticatedPrivate != 'DISALLOW') || (oldParams.s3PermissionsAuthenticatedProtected && oldParams.s3PermissionsAuthenticatedProtected != 'DISALLOW') || (oldParams.s3PermissionsAuthenticatedUploads && oldParams.s3PermissionsAuthenticatedUploads != 'DISALLOW'))) { return oldParams.selectedAuthenticatedPermissions; } else { return []; } } inferGuestPermissions(oldParams) { if (oldParams.selectedGuestPermissions && ((oldParams.s3PermissionsGuestPublic && oldParams.s3PermissionsGuestPublic != 'DISALLOW') || (oldParams.s3PermissionsGuestPrivate && oldParams.s3PermissionsGuestPrivate != 'DISALLOW') || (oldParams.s3PermissionsGuestProtected && oldParams.s3PermissionsGuestProtected != 'DISALLOW') || (oldParams.s3PermissionsGuestUploads && oldParams.s3PermissionsGuestUploads != 'DISALLOW'))) { return oldParams.selectedGuestPermissions; } else { return []; } } genInputParametersForMigration(oldS3Params) { var _a, _b; const oldParams = oldS3Params.parameters; const storageParams = oldS3Params.storageParams; const userInputs = { resourceName: this._resourceName, bucketName: oldParams.bucketName, policyUUID: (0, s3_walkthrough_1.buildShortUUID)(), storageAccess: s3_user_input_types_1.S3AccessType.AUTH_ONLY, guestAccess: [], authAccess: [], triggerFunction: 'NONE', groupAccess: undefined, }; const authPermissions = this.inferAuthPermissions(oldParams); const guestPermissions = this.inferGuestPermissions(oldParams); if (oldParams.triggerFunction) { userInputs.triggerFunction = oldParams.triggerFunction; } if (authPermissions && authPermissions.length > 0) { userInputs.authAccess = S3InputState.getInputPermissionsFromCfnPermissions(authPermissions); } else { userInputs.authAccess = []; } if (guestPermissions && guestPermissions.length > 0) { userInputs.guestAccess = S3InputState.getInputPermissionsFromCfnPermissions(guestPermissions); } else { userInputs.guestAccess = []; } if (((_a = userInputs.guestAccess) === null || _a === void 0 ? void 0 : _a.length) > 0) { userInputs.storageAccess = s3_user_input_types_1.S3AccessType.AUTH_AND_GUEST; } else { if (((_b = userInputs.authAccess) === null || _b === void 0 ? void 0 : _b.length) > 0) { userInputs.storageAccess = s3_user_input_types_1.S3AccessType.AUTH_ONLY; } } if (storageParams && Object.prototype.hasOwnProperty.call(storageParams, 'groupPermissionMap')) { userInputs.groupAccess = S3InputState.getPolicyMapFromStorageParamPolicyMap(storageParams.groupPermissionMap); } return userInputs; } removeOldS3ConfigFiles(migrationParams) { if (fs.existsSync(migrationParams.cfnFilepath)) { fs.removeSync(migrationParams.cfnFilepath); } if (fs.existsSync(migrationParams.parametersFilepath)) { fs.removeSync(migrationParams.parametersFilepath); } if (fs.existsSync(migrationParams.storageParamsFilepath)) { fs.removeSync(migrationParams.storageParamsFilepath); } } checkNeedsMigration() { const backendDir = amplify_cli_core_1.pathManager.getBackendDirPath(); const oldParametersFilepath = path.join(backendDir, amplify_cli_core_1.AmplifyCategories.STORAGE, this._resourceName, 'parameters.json'); const oldCFNFilepath = path.join(backendDir, amplify_cli_core_1.AmplifyCategories.STORAGE, this._resourceName, 's3-cloudformation-template.json'); return fs.existsSync(oldParametersFilepath) && fs.existsSync(oldCFNFilepath); } async migrate(context) { if (!this.checkNeedsMigration()) { return; } try { const authMigrationAccepted = await (0, s3_auth_api_1.migrateAuthDependencyResource)(context); if (!authMigrationAccepted) { (0, amplify_cli_core_1.exitOnNextTick)(0); } } catch (error) { amplify_prompts_1.printer.error(`Migration for Auth resource failed with error : ${error}`); throw error; } const oldS3Params = this.getOldS3ParamsForMigration(); const cliInputs = this.genInputParametersForMigration(oldS3Params); await this.saveCliInputPayload(cliInputs); this.removeOldS3ConfigFiles(oldS3Params); } cliInputFileExists() { return fs.existsSync(this._cliInputsFilePath); } checkPrefixExists(triggerPrefixList, prefix) { for (const triggerPrefix of triggerPrefixList) { if (triggerPrefix.prefix === prefix) { return true; } } return false; } _confirmLambdaTriggerPrefixUnique(triggerFunctionName, triggerPrefixList) { var _a; if ((_a = this._inputPayload) === null || _a === void 0 ? void 0 : _a.additionalTriggerFunctions) { for (const triggerParams of this._inputPayload.additionalTriggerFunctions) { if (triggerParams.triggerPrefix) { for (const configuredTriggerPrefix of triggerParams.triggerPrefix) { if (this.checkPrefixExists(triggerPrefixList, configuredTriggerPrefix.prefix) && triggerParams.triggerFunction !== triggerFunctionName) { throw new Error(`Error installing additional Lambda Trigger : trigger ${triggerParams.triggerFunction} already configured on prefix ${triggerParams.triggerPrefix}`); } } } } } return true; } addAdminLambdaTrigger(adminLambdaTrigger) { if (this._inputPayload) { this._inputPayload.adminTriggerFunction = adminLambdaTrigger; } else { throw new Error('Error : Admin Lambda Trigger cannot be installed because S3 resource CLI Input is not initialized.'); } } removeAdminLambdaTrigger() { if (this._inputPayload) { this._inputPayload.adminTriggerFunction = undefined; } else { throw new Error('Error : Admin Lambda Trigger cannot be installed because S3 resource CLI Input is not initialized.'); } } addAdditionalLambdaTrigger(triggerFunctionParams) { let additionalTriggerFunctions = []; if (!this._inputPayload) { throw new Error(`Error installing additional Lambda Trigger : Storage resource ${this._resourceName} not configured`); } if (triggerFunctionParams.triggerPrefix) { this._confirmLambdaTriggerPrefixUnique(triggerFunctionParams.triggerFunction, triggerFunctionParams.triggerPrefix); } if (this._inputPayload.additionalTriggerFunctions) { let functionExists = false; const existingTriggerFunctions = this._inputPayload.additionalTriggerFunctions; additionalTriggerFunctions = existingTriggerFunctions === null || existingTriggerFunctions === void 0 ? void 0 : existingTriggerFunctions.map((functionParams) => { if (functionParams.triggerPrefix === triggerFunctionParams.triggerPrefix && functionParams.triggerFunction === triggerFunctionParams.triggerFunction) { functionExists = true; return triggerFunctionParams; } else { return functionParams; } }); if (functionExists == false && additionalTriggerFunctions && additionalTriggerFunctions.length > 0) { additionalTriggerFunctions.push(triggerFunctionParams); } } else { additionalTriggerFunctions = [triggerFunctionParams]; } this._inputPayload.additionalTriggerFunctions = additionalTriggerFunctions; } getUserInput() { if (this._inputPayload) { return this._inputPayload; } else { try { this._inputPayload = this.getCliInputPayload(); } catch (e) { throw new Error('cli-inputs.json file missing from the resource directory'); } } return this._inputPayload; } async isCLIInputsValid(cliInputs) { if (!cliInputs) { cliInputs = this.getCliInputPayload(); } const schemaValidator = new amplify_cli_core_1.CLIInputSchemaValidator(this.context, this._service, this._category, 'S3UserInputs'); return await schemaValidator.validateInput(JSON.stringify(cliInputs)); } static getPermissionTypeFromCfnType(s3CFNPermissionType) { switch (s3CFNPermissionType) { case S3CFNPermissionType.CREATE: return s3_user_input_types_1.S3PermissionType.CREATE_AND_UPDATE; case S3CFNPermissionType.READ: case S3CFNPermissionType.LIST: return s3_user_input_types_1.S3PermissionType.READ; case S3CFNPermissionType.DELETE: return s3_user_input_types_1.S3PermissionType.DELETE; default: throw new Error(`Unknown CFN Type: ${s3CFNPermissionType}`); } } static getPermissionTypeFromStorageParamsType(s3StorageParamsPermissionType) { switch (s3StorageParamsPermissionType) { case S3StorageParamsPermissionType.CREATE_AND_UPDATE: return s3_user_input_types_1.S3PermissionType.CREATE_AND_UPDATE; case S3StorageParamsPermissionType.READ: return s3_user_input_types_1.S3PermissionType.READ; case S3StorageParamsPermissionType.DELETE: return s3_user_input_types_1.S3PermissionType.DELETE; default: throw new Error(`Unknown Storage Param Type: ${s3StorageParamsPermissionType}`); } } static getCfnTypesFromPermissionType(s3PermissionType) { switch (s3PermissionType) { case s3_user_input_types_1.S3PermissionType.CREATE_AND_UPDATE: return [S3CFNPermissionType.CREATE]; case s3_user_input_types_1.S3PermissionType.READ: return [S3CFNPermissionType.READ, S3CFNPermissionType.LIST]; case s3_user_input_types_1.S3PermissionType.DELETE: return [S3CFNPermissionType.DELETE]; default: throw new Error(`Unknown Permission Type: ${s3PermissionType}`); } } static getInputPermissionsFromCfnPermissions(selectedGuestPermissions) { if (selectedGuestPermissions && selectedGuestPermissions.length > 0) { const inputParams = selectedGuestPermissions.map(S3InputState.getPermissionTypeFromCfnType); return lodash_1.default.uniq(inputParams); } else { return []; } } static getInputPermissionsFromStorageParamPermissions(storageParamGroupPermissions) { if (storageParamGroupPermissions && storageParamGroupPermissions.length > 0) { return storageParamGroupPermissions.map(S3InputState.getPermissionTypeFromStorageParamsType); } else { return []; } } static getTriggerLambdaPermissionsFromInputPermission(triggerPermissions) { switch (triggerPermissions) { case s3_user_input_types_1.S3PermissionType.CREATE_AND_UPDATE: return s3_user_input_types_1.S3TriggerEventType.OBJ_PUT_POST_COPY; case s3_user_input_types_1.S3PermissionType.DELETE: return s3_user_input_types_1.S3TriggerEventType.OBJ_REMOVED; } throw new Error(`Unknown Trigger Lambda Permission Type ${triggerPermissions}`); } static getCfnPermissionsFromInputPermissions(selectedPermissions) { if (selectedPermissions && selectedPermissions.length > 0) { let selectedCfnPermissions = []; for (const selectedPermission of selectedPermissions) { selectedCfnPermissions = selectedCfnPermissions.concat(S3InputState.getCfnTypesFromPermissionType(selectedPermission)); } return selectedCfnPermissions; } else { return []; } } static getPolicyMapFromCfnPolicyMap(groupCFNPolicyMap) { if (groupCFNPolicyMap) { const result = {}; for (const groupName of Object.keys(groupCFNPolicyMap)) { result[groupName] = S3InputState.getInputPermissionsFromCfnPermissions(groupCFNPolicyMap[groupName]); } return result; } else { return undefined; } } static getPolicyMapFromStorageParamPolicyMap(groupStorageParamsPolicyMap) { if (groupStorageParamsPolicyMap) { const result = {}; for (const groupName of Object.keys(groupStorageParamsPolicyMap)) { result[groupName] = S3InputState.getInputPermissionsFromStorageParamPermissions(groupStorageParamsPolicyMap[groupName]); } return result; } else { return undefined; } } static getPolicyMapFromStorageParamsPolicyMap(groupStorageParamsPolicyMap) { if (groupStorageParamsPolicyMap) { const result = {}; for (const groupName of Object.keys(groupStorageParamsPolicyMap)) { result[groupName] = S3InputState.getInputPermissionsFromStorageParamPermissions(groupStorageParamsPolicyMap[groupName]); } return result; } else { return undefined; } } async updateInputPayload(props) { this._inputPayload = props.inputPayload; const schemaValidator = new amplify_cli_core_1.CLIInputSchemaValidator(this.context, this._service, this._category, 'S3UserInputs'); await schemaValidator.validateInput(JSON.stringify(this._inputPayload)); } static async getInstance(context, props) { if (!S3InputState.s3InputState) { S3InputState.s3InputState = new S3InputState(context, props.resourceName, props.inputPayload); } if (props.inputPayload) { await S3InputState.s3InputState.updateInputPayload(props); } return S3InputState.s3InputState; } getCliInputPayload() { let cliInputs; try { cliInputs = amplify_cli_core_1.JSONUtilities.readJson(this._cliInputsFilePath); } catch (e) { throw new Error('cli-inputs.json file missing from the resource directory'); } return cliInputs; } getCliMetadata() { return undefined; } async saveCliInputPayload(cliInputs) { await this.isCLIInputsValid(cliInputs); this._inputPayload = cliInputs; fs.ensureDirSync(path.join(amplify_cli_core_1.pathManager.getBackendDirPath(), this._category, this._resourceName)); amplify_cli_core_1.JSONUtilities.writeJson(this._cliInputsFilePath, cliInputs); } } exports.S3InputState = S3InputState; //# sourceMappingURL=s3-user-input-state.js.map