From 6475f9bde11bfe47f673ba5571654e32e56465e2 Mon Sep 17 00:00:00 2001 From: Peter van der Zee Date: Tue, 25 Mar 2025 12:14:48 +0100 Subject: [PATCH 1/2] [socket config auto] Add defaultOrg config option --- src/commands/audit-log/cmd-audit-log.ts | 6 +- src/commands/config/cmd-config-auto.ts | 91 +++++++++++++++++++ src/commands/config/cmd-config-get.test.ts | 1 + src/commands/config/cmd-config-list.test.ts | 1 + src/commands/config/cmd-config-set.test.ts | 1 + src/commands/config/cmd-config-unset.test.ts | 1 + src/commands/config/cmd-config.test.ts | 1 + src/commands/config/cmd-config.ts | 6 +- src/commands/config/handle-config-auto.ts | 16 ++++ src/commands/config/output-config-auto.ts | 30 ++++++ .../diff-scan/cmd-diff-scan-get.test.ts | 13 +-- src/commands/diff-scan/cmd-diff-scan-get.ts | 13 +-- .../cmd-organization-policy-security.ts | 6 +- src/commands/repos/cmd-repos-del.ts | 12 ++- src/commands/repos/cmd-repos-list.ts | 7 +- src/commands/repos/cmd-repos-update.ts | 9 +- src/commands/repos/cmd-repos-view.ts | 16 ++-- src/commands/scan/cmd-scan-create.ts | 8 +- src/commands/scan/cmd-scan-del.test.ts | 2 +- src/commands/scan/cmd-scan-del.ts | 9 +- src/commands/scan/cmd-scan-list.ts | 4 +- src/commands/scan/cmd-scan-metadata.test.ts | 2 +- src/commands/scan/cmd-scan-metadata.ts | 9 +- src/commands/scan/cmd-scan-report.test.ts | 2 +- src/commands/scan/cmd-scan-report.ts | 10 +- src/commands/scan/cmd-scan-view.test.ts | 2 +- src/commands/scan/cmd-scan-view.ts | 10 +- src/commands/scan/cmd-scan.test.ts | 2 +- src/commands/scan/cmd-scan.ts | 2 +- src/utils/config.ts | 6 +- 30 files changed, 238 insertions(+), 60 deletions(-) create mode 100644 src/commands/config/cmd-config-auto.ts create mode 100644 src/commands/config/handle-config-auto.ts create mode 100644 src/commands/config/output-config-auto.ts diff --git a/src/commands/audit-log/cmd-audit-log.ts b/src/commands/audit-log/cmd-audit-log.ts index 356568b19..b585611b4 100644 --- a/src/commands/audit-log/cmd-audit-log.ts +++ b/src/commands/audit-log/cmd-audit-log.ts @@ -6,6 +6,7 @@ import { logger } from '@socketsecurity/registry/lib/logger' import { handleAuditLog } from './handle-audit-log' import constants from '../../constants' import { commonFlags, outputFlags } from '../../flags' +import { getConfigValue } from '../../utils/config' import { meowOrExit } from '../../utils/meow-with-subcommands' import { getFlagListOutput } from '../../utils/output-formatting' @@ -73,9 +74,10 @@ async function run( }) const { json, markdown, page, perPage, type } = cli.flags - const logType = String(type || '') - const [orgSlug = ''] = cli.input + + const defaultOrgSlug = getConfigValue('defaultOrg') + const orgSlug = defaultOrgSlug || cli.input[0] || '' if (!orgSlug) { // Use exit status of 2 to indicate incorrect usage, generally invalid diff --git a/src/commands/config/cmd-config-auto.ts b/src/commands/config/cmd-config-auto.ts new file mode 100644 index 000000000..35a794a42 --- /dev/null +++ b/src/commands/config/cmd-config-auto.ts @@ -0,0 +1,91 @@ +import { stripIndents } from 'common-tags' +import colors from 'yoctocolors-cjs' + +import { logger } from '@socketsecurity/registry/lib/logger' + +import { handleConfigAuto } from './handle-config-auto' +import constants from '../../constants' +import { commonFlags, outputFlags } from '../../flags' +import { supportedConfigKeys } from '../../utils/config' +import { meowOrExit } from '../../utils/meow-with-subcommands' +import { getFlagListOutput } from '../../utils/output-formatting' + +import type { LocalConfig } from '../../utils/config' +import type { CliCommandConfig } from '../../utils/meow-with-subcommands' + +const { DRY_RUN_BAIL_TEXT } = constants + +const config: CliCommandConfig = { + commandName: 'auto', + description: 'Automatically discover and set the correct value config item', + hidden: false, + flags: { + ...commonFlags, + ...outputFlags + }, + help: (command, config) => ` + Usage + $ ${command} + + Options + ${getFlagListOutput(config.flags, 6)} + + Attempt to automatically discover the correct value for a certain config key. + + For certain keys it will request the value from server, for others it will + reset the value to the default. For some keys this has no effect. + + Keys: + +${Array.from(supportedConfigKeys.entries()) + .map(([key, desc]) => ` - ${key} -- ${desc}`) + .join('\n')} + + Examples + $ ${command} auto defaultOrg + ` +} + +export const cmdConfigAuto = { + description: config.description, + hidden: config.hidden, + run +} + +async function run( + argv: string[] | readonly string[], + importMeta: ImportMeta, + { parentName }: { parentName: string } +): Promise { + const cli = meowOrExit({ + argv, + config, + importMeta, + parentName + }) + + const { json, markdown } = cli.flags + const [key = ''] = cli.input + + if (!supportedConfigKeys.has(key as keyof LocalConfig) && key !== 'test') { + // Use exit status of 2 to indicate incorrect usage, generally invalid + // options or missing arguments. + // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html + process.exitCode = 2 + logger.fail(stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields: + + - Config key should be the first arg ${!key ? colors.red('(missing!)') : !supportedConfigKeys.has(key as any) ? colors.red('(invalid config key!)') : colors.green('(ok)')} + `) + return + } + + if (cli.flags['dryRun']) { + logger.log(DRY_RUN_BAIL_TEXT) + return + } + + await handleConfigAuto({ + key: key as keyof LocalConfig, + outputKind: json ? 'json' : markdown ? 'markdown' : 'text' + }) +} diff --git a/src/commands/config/cmd-config-get.test.ts b/src/commands/config/cmd-config-get.test.ts index 5924f8960..df73ba7e7 100644 --- a/src/commands/config/cmd-config-get.test.ts +++ b/src/commands/config/cmd-config-get.test.ts @@ -31,6 +31,7 @@ describe('socket config get', async () => { - apiBaseUrl -- Base URL of the API endpoint - apiToken -- The API token required to access most API endpoints - apiProxy -- A proxy through which to access the API + - defaultOrg -- The default org slug to use when appropriate; usually the org your API token has access to. When set, all orgSlug arguments are implied to be this value. - enforcedOrgs -- Orgs in this list have their security policies enforced on this machine Examples diff --git a/src/commands/config/cmd-config-list.test.ts b/src/commands/config/cmd-config-list.test.ts index c42a1a7d6..0a2b209cd 100644 --- a/src/commands/config/cmd-config-list.test.ts +++ b/src/commands/config/cmd-config-list.test.ts @@ -32,6 +32,7 @@ describe('socket config get', async () => { - apiBaseUrl -- Base URL of the API endpoint - apiToken -- The API token required to access most API endpoints - apiProxy -- A proxy through which to access the API + - defaultOrg -- The default org slug to use when appropriate; usually the org your API token has access to. When set, all orgSlug arguments are implied to be this value. - enforcedOrgs -- Orgs in this list have their security policies enforced on this machine Examples diff --git a/src/commands/config/cmd-config-set.test.ts b/src/commands/config/cmd-config-set.test.ts index e6764039a..5a7b528b3 100644 --- a/src/commands/config/cmd-config-set.test.ts +++ b/src/commands/config/cmd-config-set.test.ts @@ -36,6 +36,7 @@ describe('socket config get', async () => { - apiBaseUrl -- Base URL of the API endpoint - apiToken -- The API token required to access most API endpoints - apiProxy -- A proxy through which to access the API + - defaultOrg -- The default org slug to use when appropriate; usually the org your API token has access to. When set, all orgSlug arguments are implied to be this value. - enforcedOrgs -- Orgs in this list have their security policies enforced on this machine Examples diff --git a/src/commands/config/cmd-config-unset.test.ts b/src/commands/config/cmd-config-unset.test.ts index 6cc259859..fcdda57d5 100644 --- a/src/commands/config/cmd-config-unset.test.ts +++ b/src/commands/config/cmd-config-unset.test.ts @@ -31,6 +31,7 @@ describe('socket config unset', async () => { - apiBaseUrl -- Base URL of the API endpoint - apiToken -- The API token required to access most API endpoints - apiProxy -- A proxy through which to access the API + - defaultOrg -- The default org slug to use when appropriate; usually the org your API token has access to. When set, all orgSlug arguments are implied to be this value. - enforcedOrgs -- Orgs in this list have their security policies enforced on this machine Examples diff --git a/src/commands/config/cmd-config.test.ts b/src/commands/config/cmd-config.test.ts index cdd00227b..812e44625 100644 --- a/src/commands/config/cmd-config.test.ts +++ b/src/commands/config/cmd-config.test.ts @@ -21,6 +21,7 @@ describe('socket config', async () => { $ socket config Commands + auto Automatically discover and set the correct value config item get Get the value of a local CLI config item list Show all local CLI config items and their values set Update the value of a local CLI config item diff --git a/src/commands/config/cmd-config.ts b/src/commands/config/cmd-config.ts index 61b607279..802cbbcfc 100644 --- a/src/commands/config/cmd-config.ts +++ b/src/commands/config/cmd-config.ts @@ -1,3 +1,4 @@ +import { cmdConfigAuto } from './cmd-config-auto' import { cmdConfigGet } from './cmd-config-get' import { cmdConfigList } from './cmd-config-list' import { cmdConfigSet } from './cmd-config-set' @@ -14,10 +15,11 @@ export const cmdConfig: CliSubcommand = { async run(argv, importMeta, { parentName }) { await meowWithSubcommands( { - unset: cmdConfigUnset, + auto: cmdConfigAuto, get: cmdConfigGet, list: cmdConfigList, - set: cmdConfigSet + set: cmdConfigSet, + unset: cmdConfigUnset }, { argv, diff --git a/src/commands/config/handle-config-auto.ts b/src/commands/config/handle-config-auto.ts new file mode 100644 index 000000000..3db7d4db6 --- /dev/null +++ b/src/commands/config/handle-config-auto.ts @@ -0,0 +1,16 @@ +import { outputConfigGet } from './output-config-get' +import { getConfigValue } from '../../utils/config' + +import type { LocalConfig } from '../../utils/config' + +export async function handleConfigAuto({ + key, + outputKind +}: { + key: keyof LocalConfig + outputKind: 'json' | 'markdown' | 'text' +}) { + const value = getConfigValue(key) + + await outputConfigGet(key, value, outputKind) +} diff --git a/src/commands/config/output-config-auto.ts b/src/commands/config/output-config-auto.ts new file mode 100644 index 000000000..02d132d26 --- /dev/null +++ b/src/commands/config/output-config-auto.ts @@ -0,0 +1,30 @@ +import { logger } from '@socketsecurity/registry/lib/logger' + +import { LocalConfig } from '../../utils/config' + +export async function outputConfigAuto( + key: keyof LocalConfig, + success: boolean, + value: unknown, + message: string, + outputKind: 'json' | 'markdown' | 'text' +) { + if (outputKind === 'json') { + logger.log(JSON.stringify({ success, message, result: { key, value } })) + } else if (outputKind === 'markdown') { + logger.log(`# Auto discover config value`) + logger.log('') + logger.log( + `Attempted to automatically discover the value for config key: "${key}"` + ) + logger.log('') + if (success) { + logger.log(`The discovered value is: "${value}"`) + } else { + logger.log(`The discovery failed: ${message}`) + } + logger.log('') + } else { + logger.log(`${key}: ${value}`) + } +} diff --git a/src/commands/diff-scan/cmd-diff-scan-get.test.ts b/src/commands/diff-scan/cmd-diff-scan-get.test.ts index d59fd6ea2..a49ec9cfa 100644 --- a/src/commands/diff-scan/cmd-diff-scan-get.test.ts +++ b/src/commands/diff-scan/cmd-diff-scan-get.test.ts @@ -25,8 +25,8 @@ describe('socket diff-scan get', async () => { best stored to disk to be further analyzed by other tools. Options - --after The full scan ID of the head scan - --before The full scan ID of the base scan + --after The scan ID of the head scan + --before The scan ID of the base scan --depth Max depth of JSON to display before truncating, use zero for no limit (without --json/--file) --dryRun Do input validation for a command and exit 0 when input is ok --file Path to a local file where the output should be saved. Use \`-\` to force stdout. @@ -66,12 +66,9 @@ describe('socket diff-scan get', async () => { \\x1b[31m\\xd7\\x1b[39m \\x1b[41m\\x1b[37mInput error\\x1b[39m\\x1b[49m: Please provide the required fields: - - Specify a before and after full scan ID \\x1b[31m(missing before and after!)\\x1b[39m - - - To get full scans IDs, you can run the command "socket scan list ". - The args are expecting a full \`aaa0aa0a-aaaa-0000-0a0a-0000000a00a0\` ID. - - - Org name as the first argument \\x1b[31m(missing!)\\x1b[39m" + - Specify a before and after scan ID \\x1b[31m(missing before and after!)\\x1b[39m + - To get scans IDs, you can run the command "socket scan list ". + The args are expecting a full \`aaa0aa0a-aaaa-0000-0a0a-0000000a00a0\` ID." `) expect(code, 'dry-run should exit with code 2 if missing input').toBe(2) diff --git a/src/commands/diff-scan/cmd-diff-scan-get.ts b/src/commands/diff-scan/cmd-diff-scan-get.ts index c3ad6d44d..e6248b5fc 100644 --- a/src/commands/diff-scan/cmd-diff-scan-get.ts +++ b/src/commands/diff-scan/cmd-diff-scan-get.ts @@ -5,6 +5,7 @@ import { logger } from '@socketsecurity/registry/lib/logger' import { handleDiffScan } from './handle-diff-scan' import constants from '../../constants' import { commonFlags } from '../../flags' +import { getConfigValue } from '../../utils/config' import { meowOrExit } from '../../utils/meow-with-subcommands' import { getFlagListOutput } from '../../utils/output-formatting' @@ -22,13 +23,13 @@ const config: CliCommandConfig = { type: 'string', shortFlag: 'a', default: '', - description: 'The full scan ID of the head scan' + description: 'The scan ID of the head scan' }, before: { type: 'string', shortFlag: 'b', default: '', - description: 'The full scan ID of the base scan' + description: 'The scan ID of the base scan' }, depth: { type: 'number', @@ -87,7 +88,8 @@ async function run( const { after, before, depth, file, json, markdown } = cli.flags - const [orgSlug = ''] = cli.input + const defaultOrgSlug = getConfigValue('defaultOrg') + const orgSlug = defaultOrgSlug || cli.input[0] || '' if (!before || !after || cli.input.length < 1) { // Use exit status of 2 to indicate incorrect usage, generally invalid @@ -95,10 +97,9 @@ async function run( // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html process.exitCode = 2 logger.fail(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n - - Specify a before and after full scan ID ${!before && !after ? colors.red('(missing before and after!)') : !before ? colors.red('(missing before!)') : !after ? colors.red('(missing after!)') : colors.green('(ok)')}\n - - To get full scans IDs, you can run the command "socket scan list ". + - Specify a before and after scan ID ${!before && !after ? colors.red('(missing before and after!)') : !before ? colors.red('(missing before!)') : !after ? colors.red('(missing after!)') : colors.green('(ok)')}\n - To get scans IDs, you can run the command "socket scan list ". The args are expecting a full \`aaa0aa0a-aaaa-0000-0a0a-0000000a00a0\` ID.\n - - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n`) + ${defaultOrgSlug ? `- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n` : ''}`) return } diff --git a/src/commands/organization/cmd-organization-policy-security.ts b/src/commands/organization/cmd-organization-policy-security.ts index 0d7998507..3ac31f004 100644 --- a/src/commands/organization/cmd-organization-policy-security.ts +++ b/src/commands/organization/cmd-organization-policy-security.ts @@ -6,6 +6,7 @@ import { logger } from '@socketsecurity/registry/lib/logger' import { handleSecurityPolicy } from './handle-security-policy' import constants from '../../constants' import { commonFlags, outputFlags } from '../../flags' +import { getConfigValue } from '../../utils/config' import { meowOrExit } from '../../utils/meow-with-subcommands' import { getFlagListOutput } from '../../utils/output-formatting' @@ -59,7 +60,8 @@ async function run( const json = Boolean(cli.flags['json']) const markdown = Boolean(cli.flags['markdown']) - const [orgSlug = ''] = cli.input + const defaultOrgSlug = getConfigValue('defaultOrg') + const orgSlug = defaultOrgSlug || cli.input[0] || '' if (!orgSlug || (json && markdown)) { // Use exit status of 2 to indicate incorrect usage, generally invalid @@ -69,7 +71,7 @@ async function run( logger.fail(stripIndents` ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields: - - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')} + ${defaultOrgSlug ? '' : `- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}`} - The json and markdown flags cannot be both set ${json && markdown ? colors.red('(pick one!)') : colors.green('(ok)')} `) return diff --git a/src/commands/repos/cmd-repos-del.ts b/src/commands/repos/cmd-repos-del.ts index 46f50c70d..14dab7d4b 100644 --- a/src/commands/repos/cmd-repos-del.ts +++ b/src/commands/repos/cmd-repos-del.ts @@ -6,6 +6,7 @@ import { logger } from '@socketsecurity/registry/lib/logger' import { handleDeleteRepo } from './handle-delete-repo' import constants from '../../constants' import { commonFlags } from '../../flags' +import { getConfigValue } from '../../utils/config' import { meowOrExit } from '../../utils/meow-with-subcommands' import { getFlagListOutput } from '../../utils/output-formatting' @@ -50,7 +51,9 @@ async function run( parentName }) - const [orgSlug = '', repoName = ''] = cli.input + const defaultOrgSlug = getConfigValue('defaultOrg') + const orgSlug = defaultOrgSlug || cli.input[0] || '' + const repoName = (defaultOrgSlug ? cli.input[0] : cli.input[1]) || '' if (!orgSlug || !repoName) { // Use exit status of 2 to indicate incorrect usage, generally invalid @@ -59,11 +62,10 @@ async function run( process.exitCode = 2 logger.fail(stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields: - - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')} + ${defaultOrgSlug ? '' : `- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}`} - - Repository name as the second argument ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')} - - - At least one TARGET (e.g. \`.\` or \`./package.json\``) + - A repository name argument ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')} + `) return } diff --git a/src/commands/repos/cmd-repos-list.ts b/src/commands/repos/cmd-repos-list.ts index 5cc573e21..8f5fc8cff 100644 --- a/src/commands/repos/cmd-repos-list.ts +++ b/src/commands/repos/cmd-repos-list.ts @@ -6,6 +6,7 @@ import { logger } from '@socketsecurity/registry/lib/logger' import { handleListRepos } from './handle-list-repos' import constants from '../../constants' import { commonFlags, outputFlags } from '../../flags' +import { getConfigValue } from '../../utils/config' import { meowOrExit } from '../../utils/meow-with-subcommands' import { getFlagListOutput } from '../../utils/output-formatting' @@ -74,7 +75,8 @@ async function run( parentName }) - const [orgSlug = ''] = cli.input + const defaultOrgSlug = getConfigValue('defaultOrg') + const orgSlug = defaultOrgSlug || cli.input[0] || '' if (!orgSlug) { // Use exit status of 2 to indicate incorrect usage, generally invalid @@ -84,8 +86,7 @@ async function run( logger.fail(stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields: - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')} - - - At least one TARGET (e.g. \`.\` or \`./package.json\``) + `) return } diff --git a/src/commands/repos/cmd-repos-update.ts b/src/commands/repos/cmd-repos-update.ts index 7460894a7..b5cd1ac4e 100644 --- a/src/commands/repos/cmd-repos-update.ts +++ b/src/commands/repos/cmd-repos-update.ts @@ -6,6 +6,7 @@ import { logger } from '@socketsecurity/registry/lib/logger' import { handleUpdateRepo } from './handle-update-repo' import constants from '../../constants' import { commonFlags } from '../../flags' +import { getConfigValue } from '../../utils/config' import { meowOrExit } from '../../utils/meow-with-subcommands' import { getFlagListOutput } from '../../utils/output-formatting' @@ -81,7 +82,8 @@ async function run( }) const repoName = cli.flags['repoName'] - const [orgSlug = ''] = cli.input + const defaultOrgSlug = getConfigValue('defaultOrg') + const orgSlug = defaultOrgSlug || cli.input[0] || '' if (!repoName || typeof repoName !== 'string' || !orgSlug) { // Use exit status of 2 to indicate incorrect usage, generally invalid @@ -90,11 +92,10 @@ async function run( process.exitCode = 2 logger.fail(stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields: - - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')} + ${defaultOrgSlug ? '' : `- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}`} - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')} - - - At least one TARGET (e.g. \`.\` or \`./package.json\``) + `) return } diff --git a/src/commands/repos/cmd-repos-view.ts b/src/commands/repos/cmd-repos-view.ts index f0833c160..f690ffe09 100644 --- a/src/commands/repos/cmd-repos-view.ts +++ b/src/commands/repos/cmd-repos-view.ts @@ -6,6 +6,7 @@ import { logger } from '@socketsecurity/registry/lib/logger' import { handleViewRepo } from './handle-view-repo' import constants from '../../constants' import { commonFlags, outputFlags } from '../../flags' +import { getConfigValue } from '../../utils/config' import { meowOrExit } from '../../utils/meow-with-subcommands' import { getFlagListOutput } from '../../utils/output-formatting' @@ -58,7 +59,8 @@ async function run( const { json, markdown, repoName } = cli.flags - const [orgSlug = ''] = cli.input + const defaultOrgSlug = getConfigValue('defaultOrg') + const orgSlug = defaultOrgSlug || cli.input[0] || '' if (!repoName || typeof repoName !== 'string' || !orgSlug) { // Use exit status of 2 to indicate incorrect usage, generally invalid @@ -69,11 +71,13 @@ async function run( stripIndents` ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields: - - Org name as the first argument ${ - !orgSlug ? colors.red('(missing!)') : colors.green('(ok)') - } - - - Repository name using --repoName ${ + ${ + defaultOrgSlug + ? '' + : `- Org name as the first argument ${ + !orgSlug ? colors.red('(missing!)') : colors.green('(ok)') + }\n` + }- Repository name using --repoName ${ !repoName ? colors.red('(missing!)') : typeof repoName !== 'string' diff --git a/src/commands/scan/cmd-scan-create.ts b/src/commands/scan/cmd-scan-create.ts index 64d27dabc..2cc291849 100644 --- a/src/commands/scan/cmd-scan-create.ts +++ b/src/commands/scan/cmd-scan-create.ts @@ -11,6 +11,7 @@ import { suggestRepoSlug } from './suggest-repo-slug' import { suggestBranchSlug } from './suggest_branch_slug' import { suggestTarget } from './suggest_target' import constants from '../../constants' +import { getConfigValue } from '../../utils/config' import { meowOrExit } from '../../utils/meow-with-subcommands' import { getFlagListOutput } from '../../utils/output-formatting' import { getDefaultToken } from '../../utils/sdk' @@ -147,12 +148,15 @@ async function run( }) const { cwd: cwdOverride, dryRun } = cli.flags + const defaultOrgSlug = getConfigValue('defaultOrg') + let orgSlug = defaultOrgSlug || cli.input[0] || '' + let targets = cli.input.slice(defaultOrgSlug ? 0 : 1) + const cwd = cwdOverride && cwdOverride !== 'process.cwd()' ? String(cwdOverride) : process.cwd() let { branch: branchName, repo: repoName } = cli.flags - let [orgSlug = '', ...targets] = cli.input // We're going to need an api token to suggest data because those suggestions // must come from data we already know. Don't error on missing api token yet. @@ -217,7 +221,7 @@ async function run( logger.fail(stripIndents` ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields: - - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')} + ${defaultOrgSlug ? '' : `- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}`} - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')} diff --git a/src/commands/scan/cmd-scan-del.test.ts b/src/commands/scan/cmd-scan-del.test.ts index 155304a3f..725cb20a9 100644 --- a/src/commands/scan/cmd-scan-del.test.ts +++ b/src/commands/scan/cmd-scan-del.test.ts @@ -61,7 +61,7 @@ describe('socket scan del', async () => { - Org name as the first argument \\x1b[31m(missing!)\\x1b[39m - - Full Scan ID to delete as second argument \\x1b[31m(missing!)\\x1b[39m" + - Scan ID to delete \\x1b[31m(missing!)\\x1b[39m" `) expect(code, 'dry-run should exit with code 2 if missing input').toBe(2) diff --git a/src/commands/scan/cmd-scan-del.ts b/src/commands/scan/cmd-scan-del.ts index 4dfd5569a..d3c2b947b 100644 --- a/src/commands/scan/cmd-scan-del.ts +++ b/src/commands/scan/cmd-scan-del.ts @@ -6,6 +6,7 @@ import { logger } from '@socketsecurity/registry/lib/logger' import { handleDeleteScan } from './handle-delete-scan' import constants from '../../constants' import { commonFlags, outputFlags } from '../../flags' +import { getConfigValue } from '../../utils/config' import { meowOrExit } from '../../utils/meow-with-subcommands' import { getFlagListOutput } from '../../utils/output-formatting' @@ -51,7 +52,9 @@ async function run( parentName }) - const [orgSlug = '', scanId = ''] = cli.input + const defaultOrgSlug = getConfigValue('defaultOrg') + const orgSlug = defaultOrgSlug || cli.input[0] || '' + const scanId = (defaultOrgSlug ? cli.input[0] : cli.input[1]) || '' if (!orgSlug || !scanId) { // Use exit status of 2 to indicate incorrect usage, generally invalid @@ -61,9 +64,9 @@ async function run( logger.fail( stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields: - - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')} + ${defaultOrgSlug ? '' : `- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}`} - - Full Scan ID to delete as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}` + - Scan ID to delete ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}` ) return } diff --git a/src/commands/scan/cmd-scan-list.ts b/src/commands/scan/cmd-scan-list.ts index 38f2003a7..a104877bd 100644 --- a/src/commands/scan/cmd-scan-list.ts +++ b/src/commands/scan/cmd-scan-list.ts @@ -6,6 +6,7 @@ import { logger } from '@socketsecurity/registry/lib/logger' import { handleListScans } from './handle-list-scans' import constants from '../../constants' import { commonFlags, outputFlags } from '../../flags' +import { getConfigValue } from '../../utils/config' import { meowOrExit } from '../../utils/meow-with-subcommands' import { getFlagListOutput } from '../../utils/output-formatting' @@ -91,7 +92,8 @@ async function run( parentName }) - const orgSlug = cli.input[0] + const defaultOrgSlug = getConfigValue('defaultOrg') + const orgSlug = defaultOrgSlug || cli.input[0] || '' if (!orgSlug) { // Use exit status of 2 to indicate incorrect usage, generally invalid diff --git a/src/commands/scan/cmd-scan-metadata.test.ts b/src/commands/scan/cmd-scan-metadata.test.ts index e5028e524..da1a8d70f 100644 --- a/src/commands/scan/cmd-scan-metadata.test.ts +++ b/src/commands/scan/cmd-scan-metadata.test.ts @@ -61,7 +61,7 @@ describe('socket scan metadata', async () => { - Org name as the first argument \\x1b[31m(missing!)\\x1b[39m - - Full Scan ID to inspect as second argument \\x1b[31m(missing!)\\x1b[39m" + - Scan ID to inspect as second argument \\x1b[31m(missing!)\\x1b[39m" `) expect(code, 'dry-run should exit with code 2 if missing input').toBe(2) diff --git a/src/commands/scan/cmd-scan-metadata.ts b/src/commands/scan/cmd-scan-metadata.ts index 0b9237184..e453213eb 100644 --- a/src/commands/scan/cmd-scan-metadata.ts +++ b/src/commands/scan/cmd-scan-metadata.ts @@ -6,6 +6,7 @@ import { logger } from '@socketsecurity/registry/lib/logger' import { handleOrgScanMetadata } from './handle-scan-metadata' import constants from '../../constants' import { commonFlags, outputFlags } from '../../flags' +import { getConfigValue } from '../../utils/config' import { meowOrExit } from '../../utils/meow-with-subcommands' import { getFlagListOutput } from '../../utils/output-formatting' @@ -54,7 +55,9 @@ async function run( parentName }) - const [orgSlug = '', scanId = ''] = cli.input + const defaultOrgSlug = getConfigValue('defaultOrg') + const orgSlug = defaultOrgSlug || cli.input[0] || '' + const scanId = (defaultOrgSlug ? cli.input[0] : cli.input[1]) || '' if (!orgSlug || !scanId) { // Use exit status of 2 to indicate incorrect usage, generally invalid @@ -64,9 +67,9 @@ async function run( logger.fail( stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields: - - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')} + ${defaultOrgSlug ? '' : `- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}`} - - Full Scan ID to inspect as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}` + - Scan ID to inspect as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}` ) return } diff --git a/src/commands/scan/cmd-scan-report.test.ts b/src/commands/scan/cmd-scan-report.test.ts index eaa080ad0..8e533c27a 100644 --- a/src/commands/scan/cmd-scan-report.test.ts +++ b/src/commands/scan/cmd-scan-report.test.ts @@ -81,7 +81,7 @@ describe('socket scan report', async () => { - Org name as the first argument \\x1b[31m(missing!)\\x1b[39m - - Full Scan ID to fetch as second argument \\x1b[31m(missing!)\\x1b[39m + - Scan ID to fetch \\x1b[31m(missing!)\\x1b[39m - Not both the --json and --markdown flags \\x1b[32m(ok)\\x1b[39m" `) diff --git a/src/commands/scan/cmd-scan-report.ts b/src/commands/scan/cmd-scan-report.ts index fabee68ec..33df82ea2 100644 --- a/src/commands/scan/cmd-scan-report.ts +++ b/src/commands/scan/cmd-scan-report.ts @@ -6,6 +6,7 @@ import { logger } from '@socketsecurity/registry/lib/logger' import { handleScanReport } from './handle-scan-report' import constants from '../../constants' import { commonFlags, outputFlags } from '../../flags' +import { getConfigValue } from '../../utils/config' import { meowOrExit } from '../../utils/meow-with-subcommands' import { getFlagListOutput } from '../../utils/output-formatting' @@ -105,7 +106,10 @@ async function run( security } = cli.flags - const [orgSlug = '', scanId = '', file = '-'] = cli.input + const defaultOrgSlug = getConfigValue('defaultOrg') + const orgSlug = defaultOrgSlug || cli.input[0] || '' + const scanId = (defaultOrgSlug ? cli.input[0] : cli.input[1]) || '' + const file = (defaultOrgSlug ? cli.input[1] : cli.input[2]) || '-' if ( !orgSlug || @@ -121,9 +125,9 @@ async function run( stripIndents` ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields: - - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')} + ${defaultOrgSlug ? '' : `- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}`} - - Full Scan ID to fetch as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')} + - Scan ID to fetch ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')} - Not both the --json and --markdown flags ${json && markdown ? colors.red('(pick one!)') : colors.green('(ok)')} ` diff --git a/src/commands/scan/cmd-scan-view.test.ts b/src/commands/scan/cmd-scan-view.test.ts index ac23935e7..ea077983b 100644 --- a/src/commands/scan/cmd-scan-view.test.ts +++ b/src/commands/scan/cmd-scan-view.test.ts @@ -63,7 +63,7 @@ describe('socket scan view', async () => { - Org name as the first argument \\x1b[31m(missing!)\\x1b[39m - - Full Scan ID to fetch as second argument \\x1b[31m(missing!)\\x1b[39m" + - Scan ID to fetch as second argument \\x1b[31m(missing!)\\x1b[39m" `) expect(code, 'dry-run should exit with code 2 if missing input').toBe(2) diff --git a/src/commands/scan/cmd-scan-view.ts b/src/commands/scan/cmd-scan-view.ts index 67fc91836..bd191d95b 100644 --- a/src/commands/scan/cmd-scan-view.ts +++ b/src/commands/scan/cmd-scan-view.ts @@ -7,6 +7,7 @@ import { handleScanView } from './handle-scan-view' import { streamScan } from './streamScan' import constants from '../../constants' import { commonFlags, outputFlags } from '../../flags' +import { getConfigValue } from '../../utils/config' import { meowOrExit } from '../../utils/meow-with-subcommands' import { getFlagListOutput } from '../../utils/output-formatting' @@ -57,7 +58,10 @@ async function run( parentName }) - const [orgSlug = '', scanId = '', file = '-'] = cli.input + const defaultOrgSlug = getConfigValue('defaultOrg') + const orgSlug = defaultOrgSlug || cli.input[0] || '' + const scanId = (defaultOrgSlug ? cli.input[0] : cli.input[1]) || '' + const file = (defaultOrgSlug ? cli.input[1] : cli.input[2]) || '-' if (!orgSlug || !scanId) { // Use exit status of 2 to indicate incorrect usage, generally invalid @@ -68,9 +72,9 @@ async function run( stripIndents` ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields: - - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')} + ${defaultOrgSlug ? '' : `- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}`} - - Full Scan ID to fetch as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')} + - Scan ID to fetch as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')} ` ) return diff --git a/src/commands/scan/cmd-scan.test.ts b/src/commands/scan/cmd-scan.test.ts index b15500872..f0d5983d3 100644 --- a/src/commands/scan/cmd-scan.test.ts +++ b/src/commands/scan/cmd-scan.test.ts @@ -15,7 +15,7 @@ describe('socket scan', async () => { const { code, stderr, stdout } = await invokeNpm(entryPath, cmd) expect(stdout).toMatchInlineSnapshot( ` - "Full Scan related commands + "Scan related commands Usage $ socket scan diff --git a/src/commands/scan/cmd-scan.ts b/src/commands/scan/cmd-scan.ts index 2443182c2..b9103bf3f 100644 --- a/src/commands/scan/cmd-scan.ts +++ b/src/commands/scan/cmd-scan.ts @@ -8,7 +8,7 @@ import { meowWithSubcommands } from '../../utils/meow-with-subcommands' import type { CliSubcommand } from '../../utils/meow-with-subcommands' -const description = 'Full Scan related commands' +const description = 'Scan related commands' export const cmdScan: CliSubcommand = { description, diff --git a/src/utils/config.ts b/src/utils/config.ts index e5a67e66e..de2d9f9cf 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -22,7 +22,7 @@ export interface LocalConfig { test?: unknown } -// Default app data folder env var on Win +// Dugefault app data folder env var on Win const LOCALAPPDATA = 'LOCALAPPDATA' // Default app data folder env var on Mac/Linux const XDG_DATA_HOME = 'XDG_DATA_HOME' @@ -32,6 +32,10 @@ export const supportedConfigKeys: Map = new Map([ ['apiBaseUrl', 'Base URL of the API endpoint'], ['apiToken', 'The API token required to access most API endpoints'], ['apiProxy', 'A proxy through which to access the API'], + [ + 'defaultOrg', + 'The default org slug to use when appropriate; usually the org your API token has access to. When set, all orgSlug arguments are implied to be this value.' + ], [ 'enforcedOrgs', 'Orgs in this list have their security policies enforced on this machine' From b6ac3d06b4bf18513df63e641d75882294a401e0 Mon Sep 17 00:00:00 2001 From: Peter van der Zee Date: Tue, 25 Mar 2025 13:33:11 +0100 Subject: [PATCH 2/2] Auto-discover and ask to update the defaultOrg and enforcedOrgs config keys --- src/commands/config/cmd-config-get.test.ts | 2 +- src/commands/config/cmd-config-list.test.ts | 2 +- src/commands/config/cmd-config-set.test.ts | 2 +- src/commands/config/cmd-config-unset.test.ts | 2 +- src/commands/config/discover-config-value.ts | 174 ++++++++++++++++++ src/commands/config/handle-config-auto.ts | 8 +- src/commands/config/output-config-auto.ts | 76 +++++++- .../cmd-organization-policy-security.test.ts | 18 +- src/utils/config.ts | 4 +- 9 files changed, 264 insertions(+), 24 deletions(-) create mode 100644 src/commands/config/discover-config-value.ts diff --git a/src/commands/config/cmd-config-get.test.ts b/src/commands/config/cmd-config-get.test.ts index df73ba7e7..af30a2a3a 100644 --- a/src/commands/config/cmd-config-get.test.ts +++ b/src/commands/config/cmd-config-get.test.ts @@ -29,8 +29,8 @@ describe('socket config get', async () => { Keys: - apiBaseUrl -- Base URL of the API endpoint - - apiToken -- The API token required to access most API endpoints - apiProxy -- A proxy through which to access the API + - apiToken -- The API token required to access most API endpoints - defaultOrg -- The default org slug to use when appropriate; usually the org your API token has access to. When set, all orgSlug arguments are implied to be this value. - enforcedOrgs -- Orgs in this list have their security policies enforced on this machine diff --git a/src/commands/config/cmd-config-list.test.ts b/src/commands/config/cmd-config-list.test.ts index 0a2b209cd..6fcafb375 100644 --- a/src/commands/config/cmd-config-list.test.ts +++ b/src/commands/config/cmd-config-list.test.ts @@ -30,8 +30,8 @@ describe('socket config get', async () => { Keys: - apiBaseUrl -- Base URL of the API endpoint - - apiToken -- The API token required to access most API endpoints - apiProxy -- A proxy through which to access the API + - apiToken -- The API token required to access most API endpoints - defaultOrg -- The default org slug to use when appropriate; usually the org your API token has access to. When set, all orgSlug arguments are implied to be this value. - enforcedOrgs -- Orgs in this list have their security policies enforced on this machine diff --git a/src/commands/config/cmd-config-set.test.ts b/src/commands/config/cmd-config-set.test.ts index 5a7b528b3..4e2e49bdf 100644 --- a/src/commands/config/cmd-config-set.test.ts +++ b/src/commands/config/cmd-config-set.test.ts @@ -34,8 +34,8 @@ describe('socket config get', async () => { Keys: - apiBaseUrl -- Base URL of the API endpoint - - apiToken -- The API token required to access most API endpoints - apiProxy -- A proxy through which to access the API + - apiToken -- The API token required to access most API endpoints - defaultOrg -- The default org slug to use when appropriate; usually the org your API token has access to. When set, all orgSlug arguments are implied to be this value. - enforcedOrgs -- Orgs in this list have their security policies enforced on this machine diff --git a/src/commands/config/cmd-config-unset.test.ts b/src/commands/config/cmd-config-unset.test.ts index fcdda57d5..8ea6118a9 100644 --- a/src/commands/config/cmd-config-unset.test.ts +++ b/src/commands/config/cmd-config-unset.test.ts @@ -29,8 +29,8 @@ describe('socket config unset', async () => { Keys: - apiBaseUrl -- Base URL of the API endpoint - - apiToken -- The API token required to access most API endpoints - apiProxy -- A proxy through which to access the API + - apiToken -- The API token required to access most API endpoints - defaultOrg -- The default org slug to use when appropriate; usually the org your API token has access to. When set, all orgSlug arguments are implied to be this value. - enforcedOrgs -- Orgs in this list have their security policies enforced on this machine diff --git a/src/commands/config/discover-config-value.ts b/src/commands/config/discover-config-value.ts new file mode 100644 index 000000000..666c1ca10 --- /dev/null +++ b/src/commands/config/discover-config-value.ts @@ -0,0 +1,174 @@ +import { handleApiCall } from '../../utils/api' +import { supportedConfigKeys } from '../../utils/config' +import { getDefaultToken, setupSdk } from '../../utils/sdk' + +import type { LocalConfig } from '../../utils/config' + +export async function discoverConfigValue( + key: string +): Promise<{ success: boolean; value: unknown; message: string }> { + // This will have to be a specific implementation per key because certain + // keys should request information from particular API endpoints while + // others should simply return their default value, like endpoint URL. + + if (!supportedConfigKeys.has(key as keyof LocalConfig)) { + return { + success: false, + value: undefined, + message: 'Requested key is not a valid config key.' + } + } + + if (key === 'apiBaseUrl') { + // Return the default value + return { + success: false, + value: undefined, + message: + "If you're unsure about the base endpoint URL then simply unset it." + } + } + + if (key === 'apiProxy') { + // I don't think we can auto-discover this with any order of reliability..? + return { + success: false, + value: undefined, + message: + 'When uncertain, unset this key. Otherwise ask your network administrator.' + } + } + + if (key === 'apiToken') { + return { + success: false, + value: undefined, + message: + 'You can find/create your API token in your Socket dashboard > settings > API tokens.\nYou should then use `socket login` to login instead of this command.' + } + } + + if (key === 'defaultOrg') { + const apiToken = getDefaultToken() + if (!apiToken) { + return { + success: false, + value: undefined, + message: + 'No API token set, must have a token to resolve its default org.' + } + } + + const org = await getDefaultOrgFromToken() + if (!org?.length) { + return { + success: false, + value: undefined, + message: + 'Was unable to determine default org for the current API token.' + } + } + + if (Array.isArray(org)) { + return { + success: true, + value: org, + message: 'These are the orgs that the current API token can access.' + } + } + + return { + success: true, + value: org, + message: 'This is the org that belongs to the current API token.' + } + } + + if (key === 'enforcedOrgs') { + const apiToken = getDefaultToken() + if (!apiToken) { + return { + success: false, + value: undefined, + message: + 'No API token set, must have a token to resolve orgs to enforce.' + } + } + + const orgs = await getEnforceableOrgsFromToken() + if (!orgs?.length) { + return { + success: false, + value: undefined, + message: + 'Was unable to determine any orgs to enforce for the current API token.' + } + } + + return { + success: true, + value: orgs, + message: 'These are the orgs whose security policy you can enforce.' + } + } + + if (key === 'test') { + return { + success: false, + value: undefined, + message: '' + } + } + + // Mostly to please TS, because we're not telling it `key` is keyof LocalConfig + return { + success: false, + value: undefined, + message: 'unreachable?' + } +} + +async function getDefaultOrgFromToken(): Promise< + string[] | string | undefined +> { + const sockSdk = await setupSdk() + const result = await handleApiCall( + sockSdk.getOrganizations(), + 'looking up organizations' + ) + + if (result.success) { + const arr = Array.from(Object.values(result.data.organizations)).map( + ({ slug }) => slug + ) + if (arr.length === 0) { + return undefined + } + if (arr.length === 1) { + return arr[0] + } + return arr + } + + return undefined +} + +async function getEnforceableOrgsFromToken(): Promise { + const sockSdk = await setupSdk() + const result = await handleApiCall( + sockSdk.getOrganizations(), + 'looking up organizations' + ) + + if (result.success) { + const arr = Array.from(Object.values(result.data.organizations)).map( + ({ slug }) => slug + ) + if (arr.length === 0) { + return undefined + } + return arr + } + + return undefined +} diff --git a/src/commands/config/handle-config-auto.ts b/src/commands/config/handle-config-auto.ts index 3db7d4db6..b459e576f 100644 --- a/src/commands/config/handle-config-auto.ts +++ b/src/commands/config/handle-config-auto.ts @@ -1,5 +1,5 @@ -import { outputConfigGet } from './output-config-get' -import { getConfigValue } from '../../utils/config' +import { discoverConfigValue } from './discover-config-value' +import { outputConfigAuto } from './output-config-auto' import type { LocalConfig } from '../../utils/config' @@ -10,7 +10,7 @@ export async function handleConfigAuto({ key: keyof LocalConfig outputKind: 'json' | 'markdown' | 'text' }) { - const value = getConfigValue(key) + const result = await discoverConfigValue(key) - await outputConfigGet(key, value, outputKind) + await outputConfigAuto(key, result, outputKind) } diff --git a/src/commands/config/output-config-auto.ts b/src/commands/config/output-config-auto.ts index 02d132d26..697831964 100644 --- a/src/commands/config/output-config-auto.ts +++ b/src/commands/config/output-config-auto.ts @@ -1,12 +1,19 @@ import { logger } from '@socketsecurity/registry/lib/logger' +import { select } from '@socketsecurity/registry/lib/prompts' -import { LocalConfig } from '../../utils/config' +import { LocalConfig, updateConfigValue } from '../../utils/config' export async function outputConfigAuto( key: keyof LocalConfig, - success: boolean, - value: unknown, - message: string, + { + message, + success, + value + }: { + success: boolean + value: unknown + message: string + }, outputKind: 'json' | 'markdown' | 'text' ) { if (outputKind === 'json') { @@ -20,11 +27,70 @@ export async function outputConfigAuto( logger.log('') if (success) { logger.log(`The discovered value is: "${value}"`) + if (message) { + logger.log('') + logger.log(message) + } } else { logger.log(`The discovery failed: ${message}`) } logger.log('') } else { - logger.log(`${key}: ${value}`) + if (message) { + logger.log(message) + logger.log('') + } + logger.log(`- ${key}: ${value}`) + logger.log('') + + if (success) { + if (key === 'defaultOrg') { + const proceed = await select({ + message: + 'Would you like to update the default org in local config to this value?', + choices: (Array.isArray(value) ? value : [value]) + .map(slug => ({ + name: 'Yes [' + slug + ']', + value: slug, + description: `Use "${slug}" as the default organization` + })) + .concat({ + name: 'No', + value: '', + description: 'Do not use any of these organizations' + }) + }) + if (proceed) { + logger.log( + `OK. Setting defaultOrg to "${proceed}".\nYou should no longer need to add the org to commands that normally require it.` + ) + updateConfigValue('defaultOrg', proceed) + } else { + logger.log('OK. No changes made.') + } + } else if (key === 'enforcedOrgs') { + const proceed = await select({ + message: + 'Would you like to update the enforced orgs in local config to this value?', + choices: (Array.isArray(value) ? value : [value]) + .map(slug => ({ + name: 'Yes [' + slug + ']', + value: slug, + description: `Enforce the security policy of "${slug}" on this machine` + })) + .concat({ + name: 'No', + value: '', + description: 'Do not use any of these organizations' + }) + }) + if (proceed) { + logger.log(`OK. Setting enforcedOrgs key to "${proceed}".`) + updateConfigValue('defaultOrg', proceed) + } else { + logger.log('OK. No changes made.') + } + } + } } } diff --git a/src/commands/organization/cmd-organization-policy-security.test.ts b/src/commands/organization/cmd-organization-policy-security.test.ts index bc1e78d5b..922c60004 100644 --- a/src/commands/organization/cmd-organization-policy-security.test.ts +++ b/src/commands/organization/cmd-organization-policy-security.test.ts @@ -60,17 +60,17 @@ describe('socket organization list', async () => { const { code, stderr, stdout } = await invokeNpm(entryPath, cmd) expect(stdout).toMatchInlineSnapshot(`""`) expect(`\n ${stderr}`).toMatchInlineSnapshot(` - " - _____ _ _ /--------------- - | __|___ ___| |_ ___| |_ | Socket.dev CLI ver - |__ | . | _| '_| -_| _| | Node: , API token set: - |_____|___|___|_,_|___|_|.dev | Command: \`socket organization policy security\`, cwd: + " + _____ _ _ /--------------- + | __|___ ___| |_ ___| |_ | Socket.dev CLI ver + |__ | . | _| '_| -_| _| | Node: , API token set: + |_____|___|___|_,_|___|_|.dev | Command: \`socket organization policy security\`, cwd: - \\x1b[31m\\xd7\\x1b[39m \\x1b[41m\\x1b[37mInput error\\x1b[39m\\x1b[49m: Please provide the required fields: + \\x1b[31m\\xd7\\x1b[39m \\x1b[41m\\x1b[37mInput error\\x1b[39m\\x1b[49m: Please provide the required fields: - - Org name as the first argument \\x1b[31m(missing!)\\x1b[39m - - The json and markdown flags cannot be both set \\x1b[32m(ok)\\x1b[39m" - `) + - Org name as the first argument \\x1b[31m(missing!)\\x1b[39m + - The json and markdown flags cannot be both set \\x1b[32m(ok)\\x1b[39m" + `) expect(code, 'dry-run should exit with code 2 if input bad').toBe(2) } diff --git a/src/utils/config.ts b/src/utils/config.ts index de2d9f9cf..3d25daf78 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -22,7 +22,7 @@ export interface LocalConfig { test?: unknown } -// Dugefault app data folder env var on Win +// Default app data folder env var on Win const LOCALAPPDATA = 'LOCALAPPDATA' // Default app data folder env var on Mac/Linux const XDG_DATA_HOME = 'XDG_DATA_HOME' @@ -30,8 +30,8 @@ const SOCKET_APP_DIR = 'socket/settings' // It used to be settings... export const supportedConfigKeys: Map = new Map([ ['apiBaseUrl', 'Base URL of the API endpoint'], - ['apiToken', 'The API token required to access most API endpoints'], ['apiProxy', 'A proxy through which to access the API'], + ['apiToken', 'The API token required to access most API endpoints'], [ 'defaultOrg', 'The default org slug to use when appropriate; usually the org your API token has access to. When set, all orgSlug arguments are implied to be this value.'