Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(api): allow ${env} reference in custom-roles.json #804

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 27 additions & 22 deletions packages/amplify-category-api/src/graphql-transformer/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import * as path from 'path';
import { DeploymentResources } from '@aws-amplify/graphql-transformer-interfaces';
import { TransformerProjectConfig } from '@aws-amplify/graphql-transformer-core';
import rimraf from 'rimraf';
import { $TSContext, AmplifyCategories, CloudformationProviderFacade, JSONUtilities, pathManager, stateManager } from 'amplify-cli-core';
import {
$TSContext, AmplifyCategories, CloudformationProviderFacade, JSONUtilities, pathManager, stateManager,
} from 'amplify-cli-core';
import { CloudFormation, Fn } from 'cloudform';
import { ResourceConstants } from 'graphql-transformer-common';
import { pullAllBy, find } from 'lodash';
Expand Down Expand Up @@ -37,7 +39,7 @@ export const getAdminRoles = async (ctx: $TSContext, apiResourceName: string | u
return [];
}

//admin ui roles
// admin ui roles
try {
const amplifyMeta = stateManager.getMeta();
const appId = amplifyMeta?.providers?.[PROVIDER_NAME]?.AmplifyAppId;
Expand Down Expand Up @@ -66,7 +68,10 @@ export const getAdminRoles = async (ctx: $TSContext, apiResourceName: string | u
if (fs.existsSync(customRoleFile)) {
const customRoleConfig = JSONUtilities.readJson<CustomRolesConfig>(customRoleFile);
if (customRoleConfig && customRoleConfig.adminRoleNames) {
adminRoles.push(...customRoleConfig.adminRoleNames);
const adminRoleNames = customRoleConfig.adminRoleNames
// eslint-disable-next-line no-template-curly-in-string
.map((r) => (r.includes('${env}') ? r.replace('${env}', currentEnv) : r));
adminRoles.push(...adminRoleNames);
}
}
}
Expand All @@ -81,9 +86,9 @@ export function mergeUserConfigWithTransformOutput(
const userFunctions = userConfig.functions || {};
const userResolvers = userConfig.resolvers || {};
const userPipelineFunctions = userConfig.pipelineFunctions || {};
const functions = transformOutput.functions;
const resolvers = transformOutput.resolvers;
const pipelineFunctions = transformOutput.pipelineFunctions;
const { functions } = transformOutput;
const { resolvers } = transformOutput;
const { pipelineFunctions } = transformOutput;

if (!opts?.disableFunctionOverrides) {
for (const userFunction of Object.keys(userFunctions)) {
Expand All @@ -96,8 +101,8 @@ export function mergeUserConfigWithTransformOutput(

if (pipelineFunctionKeys.length > 0) {
printer.warn(
' You are using the "pipelineFunctions" directory for overridden and custom resolvers. ' +
'Please use the "resolvers" directory as "pipelineFunctions" will be deprecated.\n',
' You are using the "pipelineFunctions" directory for overridden and custom resolvers. '
+ 'Please use the "resolvers" directory as "pipelineFunctions" will be deprecated.\n',
);
}

Expand Down Expand Up @@ -149,7 +154,7 @@ function overrideUserDefinedStacks(userConfig: TransformerProjectConfig, transfo

customStackParams[ResourceConstants.PARAMETERS.AppSyncApiId] = Fn.GetAtt(ResourceConstants.RESOURCES.GraphQLAPILogicalID, 'ApiId');

let updatedParameters = rootStack.Parameters;
const updatedParameters = rootStack.Parameters;

for (const userStack of Object.keys(userStacks)) {
if (stacks[userStack]) {
Expand Down Expand Up @@ -203,16 +208,16 @@ export async function writeDeploymentToDisk(
context: $TSContext,
deployment: DeploymentResources,
directory: string,
rootStackFileName: string = 'rootStack.json',
rootStackFileName = 'rootStack.json',
buildParameters: Object,
) {
fs.ensureDirSync(directory);
// Delete the last deployments resources except for tsconfig if present
emptyBuildDirPreserveTsconfig(directory);

// Write the schema to disk
const schema = deployment.schema;
const fullSchemaPath = path.normalize(directory + `/schema.graphql`);
const { schema } = deployment;
const fullSchemaPath = path.normalize(`${directory}/schema.graphql`);
fs.writeFileSync(fullSchemaPath, schema);

// Setup the directories if they do not exist.
Expand All @@ -222,15 +227,15 @@ export async function writeDeploymentToDisk(
const resolverFileNames = Object.keys(deployment.resolvers);
const resolverRootPath = resolverDirectoryPath(directory);
for (const resolverFileName of resolverFileNames) {
const fullResolverPath = path.normalize(resolverRootPath + '/' + resolverFileName);
const fullResolverPath = path.normalize(`${resolverRootPath}/${resolverFileName}`);
fs.writeFileSync(fullResolverPath, deployment.resolvers[resolverFileName]);
}

// Write pipeline resolvers to disk
const pipelineFunctions = Object.keys(deployment.pipelineFunctions);
const pipelineFunctionRootPath = pipelineFunctionDirectoryPath(directory);
for (const functionFileName of pipelineFunctions) {
const fullTemplatePath = path.normalize(pipelineFunctionRootPath + '/' + functionFileName);
const fullTemplatePath = path.normalize(`${pipelineFunctionRootPath}/${functionFileName}`);
fs.writeFileSync(fullTemplatePath, deployment.pipelineFunctions[functionFileName]);
}

Expand All @@ -244,7 +249,7 @@ export async function writeDeploymentToDisk(
}
const fullFileName = fileNameParts.join('.');
throwIfNotJSONExt(fullFileName);
const fullStackPath = path.normalize(stackRootPath + '/' + fullFileName);
const fullStackPath = path.normalize(`${stackRootPath}/${fullFileName}`);
let stackContent = deployment.stacks[stackFileName];
if (typeof stackContent === 'string') {
stackContent = JSON.parse(stackContent);
Expand All @@ -255,17 +260,17 @@ export async function writeDeploymentToDisk(

// Write any functions to disk
const functionNames = Object.keys(deployment.functions);
const functionRootPath = path.normalize(directory + `/functions`);
const functionRootPath = path.normalize(`${directory}/functions`);
if (!fs.existsSync(functionRootPath)) {
fs.mkdirSync(functionRootPath);
}
for (const functionName of functionNames) {
const fullFunctionPath = path.normalize(functionRootPath + '/' + functionName);
const fullFunctionPath = path.normalize(`${functionRootPath}/${functionName}`);
const zipContents = fs.readFileSync(deployment.functions[functionName]);
fs.writeFileSync(fullFunctionPath, zipContents);
}
const rootStack = deployment.rootStack;
const rootStackPath = path.normalize(directory + `/${rootStackFileName}`);
const { rootStack } = deployment;
const rootStackPath = path.normalize(`${directory}/${rootStackFileName}`);
const rootStackString = JSON.stringify(rootStack, null, 4);
fs.writeFileSync(rootStackPath, rootStackString);

Expand All @@ -291,11 +296,11 @@ function pipelineFunctionDirectoryPath(rootPath: string) {
}

function resolverDirectoryPath(rootPath: string) {
return path.normalize(rootPath + `/resolvers`);
return path.normalize(`${rootPath}/resolvers`);
}

function stacksDirectoryPath(rootPath: string) {
return path.normalize(rootPath + `/stacks`);
return path.normalize(`${rootPath}/stacks`);
}

function throwIfNotJSONExt(stackFile: string) {
Expand All @@ -310,7 +315,7 @@ function throwIfNotJSONExt(stackFile: string) {

const emptyBuildDirPreserveTsconfig = (directory: string) => {
const files = fs.readdirSync(directory);
files.forEach(file => {
files.forEach((file) => {
const fileDir = path.join(directory, file);
if (fs.lstatSync(fileDir).isDirectory()) {
rimraf.sync(fileDir);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ $util.qr($ctx.stash.put(\\"hasAuth\\", true))
#set( $isAuthorized = false )
#set( $allowedFields = [] )
#if( $util.authType() == \\"IAM Authorization\\" )
#set( $adminRoles = [\\"myAdminRoleName\\"] )
#set( $adminRoles = [\\"myAdminRoleName\\",\\"myEnvFunction-fill\\"] )
#foreach( $adminRole in $adminRoles )
#if( $ctx.identity.userArn.contains($adminRole) && $ctx.identity.userArn != $ctx.stash.authRole && $ctx.identity.userArn != $ctx.stash.unauthRole )
#return($util.toJson({}))
Expand Down Expand Up @@ -175,7 +175,7 @@ $util.qr($ctx.stash.put(\\"hasAuth\\", true))
#set( $isAuthorized = false )
#set( $allowedFields = [] )
#if( $util.authType() == \\"IAM Authorization\\" )
#set( $adminRoles = [\\"myAdminRoleName\\"] )
#set( $adminRoles = [\\"myAdminRoleName\\",\\"myEnvFunction-fill\\"] )
#foreach( $adminRole in $adminRoles )
#if( $ctx.identity.userArn.contains($adminRole) && $ctx.identity.userArn != $ctx.stash.authRole && $ctx.identity.userArn != $ctx.stash.unauthRole )
#return($util.toJson({}))
Expand Down
10 changes: 6 additions & 4 deletions packages/amplify-e2e-tests/src/__tests__/api_10.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ describe('amplify add api (GraphQL)', () => {

it('init a project and add custom iam roles - local test with gql v2', async () => {
const name = 'customadminroles';
await initJSProjectWithProfile(projRoot, { name });
const envName = 'fill'
await initJSProjectWithProfile(projRoot, { name, envName });
await addApi(projRoot, { transformerVersion: 2, IAM: {}, 'Amazon Cognito User Pool': {} });
updateApiSchema(projRoot, name, 'cognito_simple_model.graphql');
await apiGqlCompile(projRoot);
Expand All @@ -95,7 +96,7 @@ describe('amplify add api (GraphQL)', () => {
expect(beforeAdminConfig).toMatchSnapshot();

const customRolesConfig = {
adminRoleNames: ['myAdminRoleName'],
adminRoleNames: ['myAdminRoleName', 'myEnvFunction-${env}'],
};
setCustomRolesConfig(projRoot, name, customRolesConfig);
await apiGqlCompile(projRoot);
Expand All @@ -106,7 +107,8 @@ describe('amplify add api (GraphQL)', () => {

it('init a project and add custom iam roles - local test with gql v2 w/ identity claim feature flag disabled', async () => {
const name = 'customadminroles';
await initJSProjectWithProfile(projRoot, { name });
const envName = 'fill'
await initJSProjectWithProfile(projRoot, { name, envName });
await addFeatureFlag(projRoot, 'graphqltransformer', 'useSubUsernameForDefaultIdentityClaim', false);
await addApi(projRoot, { transformerVersion: 2, IAM: {}, 'Amazon Cognito User Pool': {} });
updateApiSchema(projRoot, name, 'cognito_simple_model.graphql');
Expand All @@ -125,7 +127,7 @@ describe('amplify add api (GraphQL)', () => {
expect(beforeAdminConfig).toMatchSnapshot();

const customRolesConfig = {
adminRoleNames: ['myAdminRoleName'],
adminRoleNames: ['myAdminRoleName', 'myEnvFunction-${env}'],
};
setCustomRolesConfig(projRoot, name, customRolesConfig);
await apiGqlCompile(projRoot);
Expand Down