diff --git a/src/cli/validation.test.ts b/src/cli/validation.test.ts new file mode 100644 index 0000000..26104a3 --- /dev/null +++ b/src/cli/validation.test.ts @@ -0,0 +1,17 @@ +import { validateIsPrefixedId } from "./validation.ts"; +import { assertEquals } from "std/testing/assert"; + +Deno.test("non-prefixed ids fail", () => { + const result = validateIsPrefixedId("abc"); + assertEquals(result, false); +}); + +Deno.test("prefixed ids pass", () => { + const result = validateIsPrefixedId("abc/123"); + assertEquals(result, true); +}); + +Deno.test("prefixed ids with paths pass", () => { + const result = validateIsPrefixedId("abc/123/xyz"); + assertEquals(result, true); +}); diff --git a/src/cli/validation.ts b/src/cli/validation.ts new file mode 100644 index 0000000..aa1ca6d --- /dev/null +++ b/src/cli/validation.ts @@ -0,0 +1,5 @@ +const prefixedId = /.+\/.+/; + +export function validateIsPrefixedId(id: string) { + return prefixedId.test(id); +} diff --git a/src/commands/compliance/new.command.ts b/src/commands/compliance/new.command.ts index 76bc9a8..0f2ae66 100644 --- a/src/commands/compliance/new.command.ts +++ b/src/commands/compliance/new.command.ts @@ -7,17 +7,33 @@ import { MarkdownDocument } from "../../model/MarkdownDocument.ts"; import { GlobalCommandOptions } from "../GlobalCommandOptions.ts"; import { ComplianceControl } from "../../compliance/ComplianceControl.ts"; import { TopLevelCommand } from "../TopLevelCommand.ts"; +import { validateIsPrefixedId } from "../../cli/validation.ts"; +import { ValidationError } from "x/cliffy/command"; +import { CLI } from "../../info.ts"; + +const idValidationMessage = + "Control ids must contain a prefix for a control framework path like 'framework/control'."; export function registerNewCmd(program: TopLevelCommand) { program .command("new [name]") - .description("generate a new compliance control") + .description( + `Gnerate a new compliance control with the specified id.\n${idValidationMessage}`, + ) + .example( + "create a new control", + `${CLI} compliance new iso27001/8.2-privileged-access-rights`, + ) .action( - async (opts: GlobalCommandOptions, module: string, name?: string) => { + async (opts: GlobalCommandOptions, control: string, name?: string) => { + if (!validateIsPrefixedId(control)) { + throw new ValidationError(idValidationMessage); + } + const kit = await CollieRepository.load(); const logger = new Logger(kit, opts); - const controlPath = kit.resolvePath("compliance", module + ".md"); + const controlPath = kit.resolvePath("compliance", control + ".md"); if (!name) { name = await Input.prompt({ message: `Choose a human-friendly name for this control`, diff --git a/src/commands/kit/new.command.ts b/src/commands/kit/new.command.ts index 21bdebc..05b3fa8 100644 --- a/src/commands/kit/new.command.ts +++ b/src/commands/kit/new.command.ts @@ -4,13 +4,24 @@ import { CollieRepository } from "../../model/CollieRepository.ts"; import { GlobalCommandOptions } from "../GlobalCommandOptions.ts"; import { TopLevelCommand } from "../TopLevelCommand.ts"; import { newKitDirectoryCreation } from "./kit-utilities.ts"; +import { ValidationError } from "x/cliffy/command"; +import { validateIsPrefixedId } from "../../cli/validation.ts"; + +const idValidationMessage = + "Kit module ids must contain a prefix for a platform like 'platform/module'"; export function registerNewCmd(program: TopLevelCommand) { program .command("new [name]") - .description("Generate a new kit module terraform template") + .description( + `Generate a new kit module terraform template.\n${idValidationMessage}`, + ) .action( async (opts: GlobalCommandOptions, module: string, name?: string) => { + if (!validateIsPrefixedId(module)) { + throw new ValidationError(idValidationMessage); + } + const collie = await CollieRepository.load(); const logger = new Logger(collie, opts);