Skip to content
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
64 changes: 64 additions & 0 deletions src/application/template/action/createApiKeyAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {Action, ActionError} from '@/application/template/action/action';
import {ActionContext} from '@/application/template/action/context';
import {ApplicationApi, GeneratedApiKey} from '@/application/api/application';
import {ApiKeyPermission} from '@/application/model/application';
import {ConfigurationManager} from '@/application/project/configuration/manager/configurationManager';
import {ErrorReason} from '@/application/error';

export type CreateApiKeyOptions = {
keyName: string,
environment: 'development' | 'production',
permissions: ApiKeyPermission[],
result: string,
};

export type Configuration = {
applicationApi: ApplicationApi,
configurationManager: ConfigurationManager,
};

export class CreateApiKeyAction implements Action<CreateApiKeyOptions> {
private readonly configurationManager: ConfigurationManager;

private readonly api: ApplicationApi;

public constructor({configurationManager, applicationApi}: Configuration) {
this.configurationManager = configurationManager;
this.api = applicationApi;
}

public async execute(options: CreateApiKeyOptions, context: ActionContext): Promise<void> {
const {output} = context;
const configuration = await this.configurationManager.load();

const applicationSlug = options.environment === 'production'
? configuration.applications.production
: configuration.applications.development;

if (applicationSlug === undefined) {
throw new ActionError('The project has no application configured for the selected environment.', {
reason: ErrorReason.PRECONDITION,
});
}

const notifier = output?.notify('Creating API key');

let apiKey: GeneratedApiKey;

try {
apiKey = await this.api.createApiKey({
organizationSlug: configuration.organization,
workspaceSlug: configuration.workspace,
applicationSlug: applicationSlug,
name: options.keyName,
permissions: options.permissions,
});
} catch (error) {
throw ActionError.fromCause(error);
} finally {
notifier?.stop();
}

context.set(options.result, apiKey.secret);
}
}
11 changes: 11 additions & 0 deletions src/infrastructure/application/cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,10 @@ import {ResolveImportAction} from '@/application/template/action/resolveImportAc
import {
ResolveImportOptionsValidator,
} from '@/infrastructure/application/validation/actions/resolveImportOptionsValidator';
import {CreateApiKeyAction} from '@/application/template/action/createApiKeyAction';
import {
CreateApiKeyOptionsValidator,
} from '@/infrastructure/application/validation/actions/createApiKeyOptionsValidator';

export type Configuration = {
program: Program,
Expand Down Expand Up @@ -1353,6 +1357,13 @@ export class Cli {
}),
validator: new AddComponentOptionsValidator(),
}),
'create-api-key': new ValidatedAction({
action: new CreateApiKeyAction({
applicationApi: this.getApplicationApi(),
configurationManager: this.getConfigurationManager(),
}),
validator: new CreateApiKeyOptionsValidator(),
}),
'create-resource': new ValidatedAction({
action: new CreateResourceAction({
configurationManager: this.getConfigurationManager(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {z, ZodType, ZodTypeDef} from 'zod';
import {ActionOptionsValidator} from '@/infrastructure/application/validation/actions/actionOptionsValidator';
import {CreateApiKeyOptions} from '@/application/template/action/createApiKeyAction';
import {ApiKeyPermission} from '@/application/model/application';

const schema: ZodType<CreateApiKeyOptions, ZodTypeDef, any> = z.strictObject({
keyName: z.string().min(1),
environment: z.enum(['development', 'production']),
permissions: z.array(
z.enum(
ApiKeyPermission.all()
.flatMap(
value => [
value.toUpperCase(),
value.toLowerCase(),
],
) as [string, ...string[]],
).transform<ApiKeyPermission>(ApiKeyPermission.fromValue),
).min(1),
result: z.string().min(1),
});

export class CreateApiKeyOptionsValidator extends ActionOptionsValidator<CreateApiKeyOptions> {
public constructor() {
super(schema);
}
}