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
18 changes: 11 additions & 7 deletions lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,20 +257,20 @@ function saveConfigFile(data) {
const validateCliOptions = (options) => {
const errors = [];

if (options.domain && !options.domain.trim()) {
if (options.domain && (typeof options.domain !== 'string' || !options.domain.trim())) {
errors.push('--domain cannot be empty');
}

if (options.token !== undefined && (typeof options.token !== 'string' || !options.token.trim())) {
errors.push('--token cannot be empty');
}

if (options.email && !options.email.trim()) {
if (options.email && (typeof options.email !== 'string' || !options.email.trim())) {
errors.push('--email cannot be empty');
}

if (options.apiPath) {
if (!options.apiPath.startsWith('/')) {
if (typeof options.apiPath !== 'string' || !options.apiPath.startsWith('/')) {
errors.push('--api-path must start with "/"');
} else {
// Validate API path format
Expand All @@ -282,16 +282,18 @@ const validateCliOptions = (options) => {
}
}

if (options.protocol && !['http', 'https'].includes(options.protocol.toLowerCase())) {
if (options.protocol && (typeof options.protocol !== 'string' || !['http', 'https'].includes(options.protocol.toLowerCase()))) {
errors.push('--protocol must be "http" or "https"');
}

if (options.authType && !AUTH_TYPES.includes(options.authType.toLowerCase())) {
if (options.authType && (typeof options.authType !== 'string' || !AUTH_TYPES.includes(options.authType.toLowerCase()))) {
errors.push('--auth-type must be "basic", "bearer", "mtls", or "cookie"');
}

// Check if basic auth is provided with email
const normAuthType = options.authType ? normalizeAuthType(options.authType, Boolean(options.email)) : null;
const normAuthType = (typeof options.authType === 'string' && options.authType)
? normalizeAuthType(options.authType, Boolean(options.email))
: null;
if (normAuthType === 'basic' && !options.email) {
errors.push('--email is required when using basic authentication (use your username for on-premise)');
}
Expand Down Expand Up @@ -512,7 +514,9 @@ async function initConfig(cliOptions = {}) {
protocol: cliOptions.protocol,
domain: cliOptions.domain,
apiPath: cliOptions.apiPath,
authType: cliOptions.authType ? cliOptions.authType.trim().toLowerCase() : undefined,
authType: (typeof cliOptions.authType === 'string' && cliOptions.authType)
? cliOptions.authType.trim().toLowerCase()
: cliOptions.authType,
email: cliOptions.email,
token: cliOptions.token,
cookie: cliOptions.cookie,
Expand Down
50 changes: 50 additions & 0 deletions tests/config.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -349,4 +349,54 @@ describe('initConfig CLI option validation', () => {
expect.stringMatching(/--token cannot be empty/)
);
});

test('non-string --domain surfaces a validation error instead of crashing', async () => {
await expect(initConfig({
domain: 12345,
token: 'valid-token',
authType: 'bearer',
})).rejects.toThrow('process.exit called');

expect(errorSpy).toHaveBeenCalledWith(
expect.stringMatching(/--domain cannot be empty/)
);
});

test('non-string --api-path surfaces a validation error instead of crashing', async () => {
await expect(initConfig({
domain: 'example.com',
apiPath: 12345,
token: 'valid-token',
authType: 'bearer',
})).rejects.toThrow('process.exit called');

expect(errorSpy).toHaveBeenCalledWith(
expect.stringMatching(/--api-path must start with/)
);
});

test('non-string --protocol surfaces a validation error instead of crashing', async () => {
await expect(initConfig({
domain: 'example.com',
protocol: 12345,
token: 'valid-token',
authType: 'bearer',
})).rejects.toThrow('process.exit called');

expect(errorSpy).toHaveBeenCalledWith(
expect.stringMatching(/--protocol must be/)
);
});

test('non-string --auth-type surfaces a validation error instead of crashing', async () => {
await expect(initConfig({
domain: 'example.com',
token: 'valid-token',
authType: 12345,
})).rejects.toThrow('process.exit called');

expect(errorSpy).toHaveBeenCalledWith(
expect.stringMatching(/--auth-type must be/)
);
});
});
Loading