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
36 changes: 36 additions & 0 deletions src/commands/analytics/cmd-analytics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,42 @@ describe('socket analytics', async () => {
cmdit(
['analytics', '--dry-run', '--config', '{}'],
'should require args with just dry-run',
async cmd => {
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd)
expect(stdout).toMatchInlineSnapshot(`""`)
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
"
_____ _ _ /---------------
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
|_____|___|___|_,_|___|_|.dev | Command: \`socket analytics\`, cwd: <redacted>

\\x1b[31m\\xd7\\x1b[39m \\x1b[41m\\x1b[1m\\x1b[37m Input error: \\x1b[39m\\x1b[22m\\x1b[49m \\x1b[1mPlease review the input requirements and try again\\x1b[22m:

- Scope must be "repo" or "org" (\\x1b[32mok\\x1b[39m)

- The time filter must either be 7, 30 or 90 (\\x1b[32mok\\x1b[39m)

- You need to be logged in to use this command. See \`socket login\`. (\\x1b[31mmissing API token\\x1b[39m)"
`)

expect(code, 'dry-run should exit with code 2 if missing input').toBe(2)
}
)

cmdit(
[
'analytics',
'boo',
'--scope',
'org',
'--repo',
'bar',
'--dry-run',
'--config',
'{"apiToken":"anything"}'
],
'should require args with just dry-run',
async cmd => {
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd)
expect(stdout).toMatchInlineSnapshot(`"[DryRun]: Bailing now"`)
Expand Down
90 changes: 61 additions & 29 deletions src/commands/analytics/cmd-analytics.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { stripIndents } from 'common-tags'
import colors from 'yoctocolors-cjs'
import assert from 'node:assert'

import { logger } from '@socketsecurity/registry/lib/logger'

import { displayAnalytics } from './display-analytics'
import constants from '../../constants'
import { commonFlags, outputFlags } from '../../flags'
import { handleBadInput } from '../../utils/handle-bad-input'
import { meowOrExit } from '../../utils/meow-with-subcommands'
import { getFlagListOutput } from '../../utils/output-formatting'
import { getDefaultToken } from '../../utils/sdk'

import type { CliCommandConfig } from '../../utils/meow-with-subcommands'

Expand Down Expand Up @@ -84,34 +85,54 @@ async function run(

const { file, json, markdown, repo, scope, time } = cli.flags

const badScope = scope !== 'org' && scope !== 'repo'
const badTime = time !== 7 && time !== 30 && time !== 90
const badRepo = scope === 'repo' && !repo
const badFile = file !== '-' && !json && !markdown
const badFlags = json && markdown
const apiToken = getDefaultToken()

if (badScope || badTime || badRepo || badFile || badFlags) {
// 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:

- Scope must be "repo" or "org" ${badScope ? colors.red('(bad!)') : colors.green('(ok)')}

- The time filter must either be 7, 30 or 90 ${badTime ? colors.red('(bad!)') : colors.green('(ok)')}

${scope === 'repo' ? `- Repository name using --repo when scope is "repo" ${badRepo ? colors.red('(bad!)') : colors.green('(ok)')}` : ''}

${badFlags ? `- The \`--json\` and \`--markdown\` flags can not be used at the same time ${badFlags ? colors.red('(bad!)') : colors.green('(ok)')}` : ''}

${badFile ? `- The \`--file\` flag is only valid when using \`--json\` or \`--markdown\` ${badFile ? colors.red('(bad!)') : colors.green('(ok)')}` : ''}
`
.split('\n')
.filter(s => !!s.trim())
.join('\n')
)
const wasBadInput = handleBadInput(
{
test: scope === 'org' || scope === 'repo',
message: 'Scope must be "repo" or "org"',
pass: 'ok',
fail: 'bad'
},
{
test: time === 7 || time === 30 || time === 90,
message: 'The time filter must either be 7, 30 or 90',
pass: 'ok',
fail: 'bad'
},
{
nook: true,
test: scope === 'org' || repo,
message: 'When scope=repo, repo name should be set through --repo',
pass: 'ok',
fail: 'missing'
},
{
nook: true,
test: file === '-' || json || markdown,
message:
'The `--file` flag is only valid when using `--json` or `--markdown`',
pass: 'ok',
fail: 'bad'
},
{
nook: true,
test: !json || !markdown,
message:
'The `--json` and `--markdown` flags can not be used at the same time',
pass: 'ok',
fail: 'bad'
},
{
nook: true,
test: apiToken,
message:
'You need to be logged in to use this command. See `socket login`.',
pass: 'ok',
fail: 'missing API token'
}
)
if (wasBadInput) {
return
}

Expand All @@ -120,6 +141,9 @@ async function run(
return
}

assert(assertScope(scope))
assert(assertTime(time))

return await displayAnalytics({
scope,
time,
Expand All @@ -128,3 +152,11 @@ async function run(
filePath: String(file || '')
})
}

function assertScope(scope: unknown): scope is 'org' | 'repo' {
return scope === 'org' || scope === 'repo'
}

function assertTime(time: unknown): time is 7 | 30 | 90 {
return time === 7 || time === 30 || time === 90
}
12 changes: 10 additions & 2 deletions src/commands/audit-log/cmd-audit-log.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,23 @@ describe('socket audit-log', async () => {

\\x1b[31m\\xd7\\x1b[39m \\x1b[41m\\x1b[1m\\x1b[37m Input error: \\x1b[39m\\x1b[22m\\x1b[49m \\x1b[1mPlease review the input requirements and try again\\x1b[22m:

- Org name should be the first arg (\\x1b[31mmissing\\x1b[39m)"
- Org name should be the first arg (\\x1b[31mmissing\\x1b[39m)

- You need to be logged in to use this command. See \`socket login\`. (\\x1b[31mmissing API token\\x1b[39m)"
`)

expect(code, 'dry-run should exit with code 2 if missing input').toBe(2)
}
)

cmdit(
['audit-log', 'fakeorg', '--dry-run', '--config', '{}'],
[
'audit-log',
'fakeorg',
'--dry-run',
'--config',
'{"apiToken":"anything"}'
],
'should require args with just dry-run',
async cmd => {
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd)
Expand Down
33 changes: 27 additions & 6 deletions src/commands/audit-log/cmd-audit-log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { getConfigValue } from '../../utils/config'
import { handleBadInput } from '../../utils/handle-bad-input'
import { meowOrExit } from '../../utils/meow-with-subcommands'
import { getFlagListOutput } from '../../utils/output-formatting'
import { getDefaultToken } from '../../utils/sdk'

import type { CliCommandConfig } from '../../utils/meow-with-subcommands'

Expand Down Expand Up @@ -77,12 +78,32 @@ async function run(
const defaultOrgSlug = getConfigValue('defaultOrg')
const orgSlug = defaultOrgSlug || cli.input[0] || ''

const wasBadInput = handleBadInput({
test: orgSlug,
message: 'Org name should be the first arg',
pass: 'ok',
fail: 'missing'
})
const apiToken = getDefaultToken()

const wasBadInput = handleBadInput(
{
test: orgSlug,
message: 'Org name should be the first arg',
pass: 'ok',
fail: 'missing'
},
{
nook: true,
test: apiToken,
message:
'You need to be logged in to use this command. See `socket login`.',
pass: 'ok',
fail: 'missing API token'
},
{
nook: true,
test: !json || !markdown,
message:
'The `--json` and `--markdown` flags can not be used at the same time',
pass: 'ok',
fail: 'bad'
}
)
if (wasBadInput) {
return
}
Expand Down
36 changes: 2 additions & 34 deletions src/commands/audit-log/fetch-audit-log.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import constants from '../../constants'
import { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'
import { AuthError } from '../../utils/errors'
import { getDefaultToken, setupSdk } from '../../utils/sdk'
import { setupSdk } from '../../utils/sdk'

import type { SocketSdkReturnType } from '@socketsecurity/sdk'

Expand All @@ -18,44 +17,13 @@ export async function fetchAuditLog({
perPage: number
logType: string
}): Promise<SocketSdkReturnType<'getAuditLogEvents'>['data'] | void> {
const apiToken = getDefaultToken()
if (!apiToken) {
throw new AuthError(
'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'
)
}

return await fetchAuditLogWithToken(apiToken, {
logType,
orgSlug,
outputKind,
page,
perPage
})
}
const sockSdk = await setupSdk()

export async function fetchAuditLogWithToken(
apiToken: string,
{
logType,
orgSlug,
outputKind,
page,
perPage
}: {
outputKind: 'json' | 'markdown' | 'print'
orgSlug: string
page: number
perPage: number
logType: string
}
): Promise<SocketSdkReturnType<'getAuditLogEvents'>['data'] | void> {
// Lazily access constants.spinner.
const { spinner } = constants

spinner.start(`Looking up audit log for ${orgSlug}`)

const sockSdk = await setupSdk(apiToken)
const result = await handleApiCall(
sockSdk.getAuditLogEvents(orgSlug, {
// I'm not sure this is used at all.
Expand Down
2 changes: 1 addition & 1 deletion src/commands/cdxgen/cmd-cdxgen.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ describe('socket cdxgen', async () => {

// cdxgen does not support --dry-run
// cmdit(
// ['cdxgen', '--help', '--config', '{}'],
// ['cdxgen', '--help', '--config', '{"apiToken":"anything"}'],
// 'should require args with just dry-run',
// async cmd => {
// const { code, stderr, stdout } = await invokeNpm(entryPath, cmd)
Expand Down
22 changes: 16 additions & 6 deletions src/commands/config/cmd-config-auto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,22 @@ async function run(
const { json, markdown } = cli.flags
const [key = ''] = cli.input

const wasBadInput = handleBadInput({
test: supportedConfigKeys.has(key as keyof LocalConfig) && key !== 'test',
message: 'Config key should be the first arg',
pass: 'ok',
fail: key ? 'invalid config key' : 'missing'
})
const wasBadInput = handleBadInput(
{
test: supportedConfigKeys.has(key as keyof LocalConfig) && key !== 'test',
message: 'Config key should be the first arg',
pass: 'ok',
fail: key ? 'invalid config key' : 'missing'
},
{
nook: true,
test: !json || !markdown,
message:
'The `--json` and `--markdown` flags can not be used at the same time',
pass: 'ok',
fail: 'bad'
}
)
if (wasBadInput) {
return
}
Expand Down
9 changes: 8 additions & 1 deletion src/commands/config/cmd-config-get.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,14 @@ describe('socket config get', async () => {
)

cmdit(
['config', 'test', 'test', '--dry-run', '--config', '{}'],
[
'config',
'test',
'test',
'--dry-run',
'--config',
'{"apiToken":"anything"}'
],
'should require args with just dry-run',
async cmd => {
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd)
Expand Down
22 changes: 16 additions & 6 deletions src/commands/config/cmd-config-get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,22 @@ async function run(
const { json, markdown } = cli.flags
const [key = ''] = cli.input

const wasBadInput = handleBadInput({
test: supportedConfigKeys.has(key as keyof LocalConfig) || key === 'test',
message: 'Config key should be the first arg',
pass: 'ok',
fail: key ? 'invalid config key' : 'missing'
})
const wasBadInput = handleBadInput(
{
test: supportedConfigKeys.has(key as keyof LocalConfig) || key === 'test',
message: 'Config key should be the first arg',
pass: 'ok',
fail: key ? 'invalid config key' : 'missing'
},
{
nook: true,
test: !json || !markdown,
message:
'The `--json` and `--markdown` flags can not be used at the same time',
pass: 'ok',
fail: 'bad'
}
)
if (wasBadInput) {
return
}
Expand Down
2 changes: 1 addition & 1 deletion src/commands/config/cmd-config-list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ describe('socket config get', async () => {
)

cmdit(
['config', 'list', '--dry-run', '--config', '{}'],
['config', 'list', '--dry-run', '--config', '{"apiToken":"anything"}'],
'should require args with just dry-run',
async cmd => {
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd)
Expand Down
Loading