Skip to content

Commit

Permalink
Merge pull request #4449 from snyk/feat/add-context-to-app-create
Browse files Browse the repository at this point in the history
feat: add context flag to Snyk App create command
  • Loading branch information
jgresty authored Mar 6, 2023
2 parents c979bd9 + a483033 commit ed26e75
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/cli/commands/apps/create-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export async function createApp(
snykAppName: name,
snykAppRedirectUris: redirectUris,
snykAppScopes: scopes,
context,
} = data;
const payload = {
method: 'POST',
Expand All @@ -38,6 +39,7 @@ export async function createApp(
name,
redirect_uris: redirectUris,
scopes,
context,
},
qs: {
version: '2022-03-11~experimental',
Expand Down
12 changes: 9 additions & 3 deletions src/lib/apps/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const SNYK_APP_REDIRECT_URIS = 'snykAppRedirectUris';
export const SNYK_APP_SCOPES = 'snykAppScopes';
export const SNYK_APP_CLIENT_ID = 'snykAppClientId';
export const SNYK_APP_ORG_ID = 'snykAppOrgId';
export const SNYK_APP_CONTEXT = 'context';
export const SNYK_APP_DEBUG = 'snyk:apps';

export enum EValidSubCommands {
Expand All @@ -22,12 +23,13 @@ export const AppsErrorMessages = {
nameRequired: `Option '--name' is required! For interactive mode, please use '--interactive' or '-i' flag. For more information please run the help command 'snyk apps --help' or 'snyk apps -h'.`,
redirectUrisRequired: `Option '--redirect-uris' is required! For interactive mode, please use '--interactive' or '-i' flag. For more information please run the help command 'snyk apps --help' or 'snyk apps -h'.`,
scopesRequired: `Option '--scopes' is required! For interactive mode, please use '--interactive' or '-i' flag. For more information please run the help command 'snyk apps --help' or 'snyk apps -h'.`,
invalidContext: `Option '--context' must be either 'tenant' or 'user'! For interactive mode, please use '--interactive' or '-i' flag. For more information please run the help command 'snyk apps --help' or 'snyk apps -h'.`,
useExperimental: `\n${chalk.redBright(
"All 'apps' commands are only accessible behind the '--experimental' flag.",
)}\n
The behaviour can change at any time, without prior notice.
)}\n
The behaviour can change at any time, without prior notice.
You are kindly advised to use all the commands with caution.
${chalk.bold('Usage')}
${chalk.italic('snyk apps <COMMAND> --experimental')}\n`,
};
Expand All @@ -54,4 +56,8 @@ export const CreateAppPromptData = {
message:
'Please provide the org id under which you want to create your Snyk App: ',
},
SNYK_APP_CONTEXT: {
name: SNYK_APP_CONTEXT,
message: 'Which context will your app operate under: ',
},
};
10 changes: 10 additions & 0 deletions src/lib/apps/create-app/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
AppContext,
AppsErrorMessages,
createAppPrompts,
ICreateAppRequest,
Expand All @@ -7,6 +8,7 @@ import {
SNYK_APP_REDIRECT_URIS,
SNYK_APP_SCOPES,
SNYK_APP_ORG_ID,
SNYK_APP_CONTEXT,
validateUUID,
validateAllURL,
} from '..';
Expand Down Expand Up @@ -37,6 +39,11 @@ export function createAppDataScriptable(
);
} else if (!options.scopes) {
throw new ValidationError(AppsErrorMessages.scopesRequired);
} else if (
options.context != null &&
!(options.context == 'user' || options.context == 'tenant')
) {
throw new ValidationError(AppsErrorMessages.invalidContext);
} else {
return {
orgId: options.org,
Expand All @@ -45,6 +52,7 @@ export function createAppDataScriptable(
.replace(/\s+/g, '')
.split(','),
snykAppScopes: options.scopes.replace(/\s+/g, '').split(','),
context: options.context,
};
}
}
Expand All @@ -63,11 +71,13 @@ export async function createAppDataInteractive(): Promise<ICreateAppRequest> {
',',
) as string[];
const orgId = answers[SNYK_APP_ORG_ID].trim() as string;
const context = answers[SNYK_APP_CONTEXT].trim() as AppContext;
// POST: to create an app
return {
orgId,
snykAppName,
snykAppRedirectUris,
snykAppScopes,
context,
};
}
7 changes: 7 additions & 0 deletions src/lib/apps/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,11 @@ export const createAppPrompts = [
message: CreateAppPromptData.SNYK_APP_ORG_ID.message,
validate: validateUUID,
},
{
name: CreateAppPromptData.SNYK_APP_CONTEXT.name,
type: 'select',
message: CreateAppPromptData.SNYK_APP_CONTEXT.message,
choices: ['tenant', 'user'],
initial: 'tenant',
},
];
4 changes: 4 additions & 0 deletions src/lib/apps/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export type AppContext = 'tenant' | 'user';

export interface IGetAppsURLOpts {
orgId?: string;
clientId?: string;
Expand Down Expand Up @@ -48,11 +50,13 @@ export interface ICreateAppOptions extends IGenerateAppsOptions {
name?: string;
redirectUris?: string;
scopes?: string;
context?: AppContext;
}

export interface ICreateAppRequest {
orgId: string;
snykAppName: string;
snykAppRedirectUris: string[];
snykAppScopes: string[];
context?: AppContext;
}
14 changes: 14 additions & 0 deletions test/jest/acceptance/snyk-apps/create-app.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ describe('snyk-apps: create app', () => {
await expect(cli).toDisplay('Please provide the org id under which');
await cli.answer(testData.orgId);

await expect(cli).toDisplay('Which context will your app operate under');
await cli.answer('');

// Assert
await expect(cli).toDisplay('Snyk App created successfully!');
await expect(cli).toDisplay(testData.appName);
Expand Down Expand Up @@ -247,6 +250,17 @@ describe('snyk-apps: create app', () => {
await expect(cli).toExitWith(2);
});

it('throws an error when an invalid context is provided', async () => {
cli = await startSnykCLI(
`apps create --org=${testData.orgId} --name=${testData.appName} --redirect-uris=${testData.redirectURIs} --scopes=${testData.scopes} --context=foobar --experimental`,
{ env },
);
await expect(cli).toDisplay(
"Option '--context' must be either 'tenant' or 'user'! For interactive mode, please use '--interactive' or '-i' flag. For more information please run the help command 'snyk apps --help' or 'snyk apps -h'.",
);
await expect(cli).toExitWith(2);
});

it('should create app with user provided data', async () => {
cli = await startSnykCLI(
`apps create --org=${testData.orgId} --name=${testData.appName} --redirect-uris=${testData.redirectURIs} --scopes=${testData.scopes} --experimental`,
Expand Down

0 comments on commit ed26e75

Please sign in to comment.