diff --git a/src/commands/config/cmd-config-auto.test.mts b/src/commands/config/cmd-config-auto.test.mts index cba878eac..177d1a828 100644 --- a/src/commands/config/cmd-config-auto.test.mts +++ b/src/commands/config/cmd-config-auto.test.mts @@ -32,6 +32,7 @@ describe('socket config auto', async () => { - apiToken -- The API token required to access most API endpoints - defaultOrg -- The default org slug to use; 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 + - skipAskToPersistDefaultOrg -- This flag prevents the CLI from asking you to persist the org slug when you selected one interactively - org -- Alias for defaultOrg For certain keys it will request the value from server, for others it will @@ -44,6 +45,7 @@ describe('socket config auto', async () => { - apiToken -- The API token required to access most API endpoints - defaultOrg -- The default org slug to use; 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 + - skipAskToPersistDefaultOrg -- This flag prevents the CLI from asking you to persist the org slug when you selected one interactively - org -- Alias for defaultOrg Examples diff --git a/src/commands/config/cmd-config-get.test.mts b/src/commands/config/cmd-config-get.test.mts index 4c78cbe3f..2deae0169 100644 --- a/src/commands/config/cmd-config-get.test.mts +++ b/src/commands/config/cmd-config-get.test.mts @@ -34,6 +34,7 @@ describe('socket config get', async () => { - apiToken -- The API token required to access most API endpoints - defaultOrg -- The default org slug to use; 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 + - skipAskToPersistDefaultOrg -- This flag prevents the CLI from asking you to persist the org slug when you selected one interactively - org -- Alias for defaultOrg Examples diff --git a/src/commands/config/cmd-config-set.test.mts b/src/commands/config/cmd-config-set.test.mts index a9e36a255..12a01aa6f 100644 --- a/src/commands/config/cmd-config-set.test.mts +++ b/src/commands/config/cmd-config-set.test.mts @@ -41,6 +41,7 @@ describe('socket config get', async () => { - apiToken -- The API token required to access most API endpoints - defaultOrg -- The default org slug to use; 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 + - skipAskToPersistDefaultOrg -- This flag prevents the CLI from asking you to persist the org slug when you selected one interactively - org -- Alias for defaultOrg Examples diff --git a/src/commands/config/cmd-config-unset.test.mts b/src/commands/config/cmd-config-unset.test.mts index 93c86716c..69f35537c 100644 --- a/src/commands/config/cmd-config-unset.test.mts +++ b/src/commands/config/cmd-config-unset.test.mts @@ -35,6 +35,7 @@ describe('socket config unset', async () => { - apiToken -- The API token required to access most API endpoints - defaultOrg -- The default org slug to use; 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 + - skipAskToPersistDefaultOrg -- This flag prevents the CLI from asking you to persist the org slug when you selected one interactively - org -- Alias for defaultOrg Examples diff --git a/src/commands/repository/output-list-repos.mts b/src/commands/repository/output-list-repos.mts index 9355a3230..0eb631746 100644 --- a/src/commands/repository/output-list-repos.mts +++ b/src/commands/repository/output-list-repos.mts @@ -67,7 +67,9 @@ export async function outputListRepos( logger.info( `This is page ${page}. Server indicated there are more results available on page ${nextPage}...`, ) - logger.info(`(Hint: you can use \`socket repos list --page ${nextPage}\`)`) + logger.info( + `(Hint: you can use \`socket repository list --page ${nextPage}\`)`, + ) } else if (perPage === Infinity) { logger.info(`This should be the entire list available on the server.`) } else { diff --git a/src/commands/scan/cmd-scan-create.mts b/src/commands/scan/cmd-scan-create.mts index 11b394cb8..783b0f737 100644 --- a/src/commands/scan/cmd-scan-create.mts +++ b/src/commands/scan/cmd-scan-create.mts @@ -3,7 +3,7 @@ import path from 'node:path' import { logger } from '@socketsecurity/registry/lib/logger' import { handleCreateNewScan } from './handle-create-new-scan.mts' -import { outputCreateNewScan } from './output-create-new-scan.mjs' +import { outputCreateNewScan } from './output-create-new-scan.mts' import { suggestOrgSlug } from './suggest-org-slug.mts' import { suggestTarget } from './suggest_target.mts' import constants from '../../constants.mts' diff --git a/src/commands/scan/cmd-scan-github.mts b/src/commands/scan/cmd-scan-github.mts index 70299f638..3b9e602c3 100644 --- a/src/commands/scan/cmd-scan-github.mts +++ b/src/commands/scan/cmd-scan-github.mts @@ -3,7 +3,7 @@ import path from 'node:path' import { logger } from '@socketsecurity/registry/lib/logger' import { handleCreateGithubScan } from './handle-create-github-scan.mts' -import { outputScanGithub } from './output-scan-github.mjs' +import { outputScanGithub } from './output-scan-github.mts' import { suggestOrgSlug } from './suggest-org-slug.mts' import constants from '../../constants.mts' import { commonFlags, outputFlags } from '../../flags.mts' diff --git a/src/commands/scan/suggest-to-persist-orgslug.mts b/src/commands/scan/suggest-to-persist-orgslug.mts new file mode 100644 index 000000000..d4235cc3c --- /dev/null +++ b/src/commands/scan/suggest-to-persist-orgslug.mts @@ -0,0 +1,54 @@ +import { logger } from '@socketsecurity/registry/lib/logger' +import { select } from '@socketsecurity/registry/lib/prompts' + +import { getConfigValue, updateConfigValue } from '../../utils/config.mts' + +export async function suggestToPersistOrgSlug(orgSlug: string): Promise { + const skipAsk = getConfigValue('skipAskToPersistDefaultOrg') + if (!skipAsk.ok || skipAsk.data) { + // Don't ask to store it when disabled before, or when reading config fails. + return + } + + const result = await select({ + message: `Would you like to use this org (${orgSlug}) as the default org for future calls?`, + choices: [ + { + name: 'Yes', + value: 'yes', + description: 'Stores it in your config', + }, + { + name: 'No', + value: 'no', + description: 'Do not persist this org as default org', + }, + { + name: "No and don't ask again", + value: 'sush', + description: + 'Do not store as default org and do not ask again to persist it', + }, + ], + }) + if (result === 'yes') { + const updateResult = updateConfigValue('defaultOrg', orgSlug) + if (updateResult.ok) { + logger.success('Updated default org config to:', orgSlug) + } else { + logger.fail( + '(Non blocking) Failed to update default org in config:', + updateResult.cause, + ) + } + } else if (result === 'sush') { + const updateResult = updateConfigValue('skipAskToPersistDefaultOrg', true) + if (updateResult.ok) { + logger.info('Default org not changed. Will not ask to persist again.') + } else { + logger.fail( + `(Non blocking) Failed to store preference; will ask to persist again next time. Reason: ${updateResult.cause}`, + ) + } + } +} diff --git a/src/utils/config.mts b/src/utils/config.mts index 51bf3a046..43c1a0b48 100644 --- a/src/utils/config.mts +++ b/src/utils/config.mts @@ -20,6 +20,7 @@ export interface LocalConfig { apiToken?: string | null | undefined defaultOrg?: string enforcedOrgs?: string[] | readonly string[] | null | undefined + skipAskToPersistDefaultOrg?: boolean org?: string // convenience alias for defaultOrg } @@ -37,6 +38,10 @@ export const supportedConfigKeys: Map = new Map([ 'enforcedOrgs', 'Orgs in this list have their security policies enforced on this machine', ], + [ + 'skipAskToPersistDefaultOrg', + 'This flag prevents the CLI from asking you to persist the org slug when you selected one interactively', + ], ['org', 'Alias for defaultOrg'], ]) @@ -206,19 +211,35 @@ export function overrideConfigApiToken(apiToken: unknown) { let _pendingSave = false export function updateConfigValue( - key: keyof LocalConfig, + configKey: keyof LocalConfig, value: LocalConfig[Key], ): CResult { const localConfig = getConfigValues() - const keyResult = normalizeConfigKey(key) + const keyResult = normalizeConfigKey(configKey) if (!keyResult.ok) { return keyResult } - localConfig[keyResult.data as Key] = value + const key: Key = keyResult.data as Key + let wasDeleted = value === undefined // implicitly when serializing + if (key === 'skipAskToPersistDefaultOrg') { + if (value === 'true' || value === 'false') { + localConfig['skipAskToPersistDefaultOrg'] = value === 'true' + } else { + delete localConfig['skipAskToPersistDefaultOrg'] + wasDeleted = true + } + } else { + if (value === 'undefined' || value === 'true' || value === 'false') { + logger.warn( + `Note: The value is set to "${value}", as a string (!). Use \`socket config unset\` to reset a key.`, + ) + } + localConfig[key] = value + } if (_readOnlyConfig) { return { ok: true, - message: `Config key '${keyResult.data}' was updated`, + message: `Config key '${key}' was ${wasDeleted ? 'deleted' : `updated`}`, data: 'Change applied but not persisted; current config is overridden through env var or flag', } } @@ -240,7 +261,7 @@ export function updateConfigValue( return { ok: true, - message: `Config key '${keyResult.data}' was updated`, + message: `Config key '${key}' was ${wasDeleted ? 'deleted' : `updated`}`, data: undefined, } } diff --git a/src/utils/determine-org-slug.mts b/src/utils/determine-org-slug.mts index 7dbe34199..cdb50a53b 100644 --- a/src/utils/determine-org-slug.mts +++ b/src/utils/determine-org-slug.mts @@ -2,6 +2,7 @@ import { logger } from '@socketsecurity/registry/lib/logger' import { getConfigValueOrUndef } from './config.mts' import { suggestOrgSlug } from '../commands/scan/suggest-org-slug.mts' +import { suggestToPersistOrgSlug } from '../commands/scan/suggest-to-persist-orgslug.mts' export async function determineOrgSlug( orgFlag: string, @@ -55,6 +56,10 @@ export async function determineOrgSlug( logger.fail('Skipping auto-discovery of org in dry-run mode') } else { orgSlug = (await suggestOrgSlug()) || '' + + if (orgSlug) { + await suggestToPersistOrgSlug(orgSlug) + } } }