Skip to content

Commit

Permalink
feat(api): allow ${env} reference in custom-roles.json
Browse files Browse the repository at this point in the history
  • Loading branch information
joekiller committed Sep 16, 2022
1 parent 37665f2 commit d11e788
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 30 deletions.
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 @@ -2,7 +2,9 @@ import fs from 'fs-extra';
import * as path from 'path';
import { TransformerProjectConfig, DeploymentResources } 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 @@ -36,7 +38,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 @@ -65,7 +67,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 @@ -80,9 +85,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 @@ -95,8 +100,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 @@ -148,7 +153,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 @@ -202,7 +207,7 @@ export async function writeDeploymentToDisk(
context: $TSContext,
deployment: DeploymentResources,
directory: string,
rootStackFileName: string = 'rootStack.json',
rootStackFileName = 'rootStack.json',
buildParameters: Object,
minify = false,
) {
Expand All @@ -211,8 +216,8 @@ export async function writeDeploymentToDisk(
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 = minify ? JSON.stringify(rootStack) : 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 @@ -59,7 +59,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 @@ -166,7 +166,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
14 changes: 8 additions & 6 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,18 +96,19 @@ describe('amplify add api (GraphQL)', () => {
expect(beforeAdminConfig).toMatchSnapshot();

const customRolesConfig = {
adminRoleNames: ['myAdminRoleName'],
adminRoleNames: ['myAdminRoleName', 'myEnvFunction-${env}'],
};
setCustomRolesConfig(projRoot, name, customRolesConfig);
await apiGqlCompile(projRoot);
await apiGqlCompile(projRoot, true);
const afterAdminConfig = readFileSync(createResolver).toString();
expect(afterAdminConfig).toMatchSnapshot();
expect(beforeAdminConfig).not.toEqual(afterAdminConfig);
});

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,10 +127,10 @@ describe('amplify add api (GraphQL)', () => {
expect(beforeAdminConfig).toMatchSnapshot();

const customRolesConfig = {
adminRoleNames: ['myAdminRoleName'],
adminRoleNames: ['myAdminRoleName', 'myEnvFunction-${env}'],
};
setCustomRolesConfig(projRoot, name, customRolesConfig);
await apiGqlCompile(projRoot);
await apiGqlCompile(projRoot, true);
const afterAdminConfig = readFileSync(createResolver).toString();
expect(afterAdminConfig).toMatchSnapshot();
expect(beforeAdminConfig).not.toEqual(afterAdminConfig);
Expand Down

0 comments on commit d11e788

Please sign in to comment.