2021-10-13 20:52:44 +02:00
|
|
|
import { createConfig } from './create-config';
|
2022-01-05 10:00:59 +01:00
|
|
|
import { ApiTokenType } from './types/models/api-token';
|
2021-10-13 20:52:44 +02:00
|
|
|
|
|
|
|
test('should create default config', async () => {
|
|
|
|
const config = createConfig({
|
|
|
|
db: {
|
|
|
|
host: 'localhost',
|
|
|
|
port: 4242,
|
|
|
|
user: 'unleash',
|
|
|
|
password: 'password',
|
|
|
|
database: 'unleash_db',
|
|
|
|
},
|
|
|
|
server: {
|
|
|
|
port: 4242,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(config).toMatchSnapshot();
|
|
|
|
});
|
2022-01-05 10:00:59 +01:00
|
|
|
|
2022-03-02 12:44:46 +01:00
|
|
|
test('should add initApiToken for admin token from options', async () => {
|
2022-01-05 10:00:59 +01:00
|
|
|
const token = {
|
|
|
|
environment: '*',
|
|
|
|
project: '*',
|
2022-01-05 10:40:22 +01:00
|
|
|
secret: '*:*.some-random-string',
|
2022-01-05 10:00:59 +01:00
|
|
|
type: ApiTokenType.ADMIN,
|
|
|
|
username: 'admin',
|
|
|
|
};
|
|
|
|
const config = createConfig({
|
|
|
|
db: {
|
|
|
|
host: 'localhost',
|
|
|
|
port: 4242,
|
|
|
|
user: 'unleash',
|
|
|
|
password: 'password',
|
|
|
|
database: 'unleash_db',
|
|
|
|
},
|
|
|
|
server: {
|
|
|
|
port: 4242,
|
|
|
|
},
|
|
|
|
authentication: {
|
|
|
|
initApiTokens: [token],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(config.authentication.initApiTokens).toHaveLength(1);
|
|
|
|
expect(config.authentication.initApiTokens[0].environment).toBe(
|
|
|
|
token.environment,
|
|
|
|
);
|
|
|
|
expect(config.authentication.initApiTokens[0].project).toBe(token.project);
|
|
|
|
expect(config.authentication.initApiTokens[0].type).toBe(
|
|
|
|
ApiTokenType.ADMIN,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2022-03-02 12:44:46 +01:00
|
|
|
test('should add initApiToken for client token from options', async () => {
|
|
|
|
const token = {
|
|
|
|
environment: 'development',
|
|
|
|
project: 'default',
|
|
|
|
secret: 'default:development.some-random-string',
|
|
|
|
type: ApiTokenType.CLIENT,
|
|
|
|
username: 'admin',
|
|
|
|
};
|
|
|
|
const config = createConfig({
|
|
|
|
db: {
|
|
|
|
host: 'localhost',
|
|
|
|
port: 4242,
|
|
|
|
user: 'unleash',
|
|
|
|
password: 'password',
|
|
|
|
database: 'unleash_db',
|
|
|
|
},
|
|
|
|
server: {
|
|
|
|
port: 4242,
|
|
|
|
},
|
|
|
|
authentication: {
|
|
|
|
initApiTokens: [token],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(config.authentication.initApiTokens).toHaveLength(1);
|
|
|
|
expect(config.authentication.initApiTokens[0].environment).toBe(
|
|
|
|
token.environment,
|
|
|
|
);
|
|
|
|
expect(config.authentication.initApiTokens[0].project).toBe(token.project);
|
|
|
|
expect(config.authentication.initApiTokens[0].type).toBe(
|
|
|
|
ApiTokenType.CLIENT,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should add initApiToken for admin token from env var', async () => {
|
2022-01-05 10:40:22 +01:00
|
|
|
process.env.INIT_ADMIN_API_TOKENS = '*:*.some-token1, *:*.some-token2';
|
2022-01-05 10:00:59 +01:00
|
|
|
|
|
|
|
const config = createConfig({
|
|
|
|
db: {
|
|
|
|
host: 'localhost',
|
|
|
|
port: 4242,
|
|
|
|
user: 'unleash',
|
|
|
|
password: 'password',
|
|
|
|
database: 'unleash_db',
|
|
|
|
},
|
|
|
|
server: {
|
|
|
|
port: 4242,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(config.authentication.initApiTokens).toHaveLength(2);
|
|
|
|
expect(config.authentication.initApiTokens[0].environment).toBe('*');
|
|
|
|
expect(config.authentication.initApiTokens[0].project).toBe('*');
|
|
|
|
expect(config.authentication.initApiTokens[0].type).toBe(
|
|
|
|
ApiTokenType.ADMIN,
|
|
|
|
);
|
|
|
|
expect(config.authentication.initApiTokens[1].secret).toBe(
|
2022-01-05 10:40:22 +01:00
|
|
|
'*:*.some-token2',
|
2022-01-05 10:00:59 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
delete process.env.INIT_ADMIN_API_TOKENS;
|
|
|
|
});
|
|
|
|
|
2022-03-02 12:44:46 +01:00
|
|
|
test('should validate initApiToken for admin token from env var', async () => {
|
2022-01-05 10:00:59 +01:00
|
|
|
process.env.INIT_ADMIN_API_TOKENS = 'invalidProject:*:some-token1';
|
|
|
|
|
|
|
|
expect(() => createConfig({})).toThrow(
|
|
|
|
'Admin token cannot be scoped to single project',
|
|
|
|
);
|
|
|
|
|
|
|
|
delete process.env.INIT_ADMIN_API_TOKENS;
|
|
|
|
});
|
|
|
|
|
2022-03-02 12:44:46 +01:00
|
|
|
test('should validate initApiToken for client token from env var', async () => {
|
|
|
|
process.env.INIT_CLIENT_API_TOKENS = '*:*:some-token1';
|
|
|
|
|
|
|
|
expect(() => createConfig({})).toThrow(
|
|
|
|
'Client token cannot be scoped to all environments',
|
|
|
|
);
|
|
|
|
|
|
|
|
delete process.env.INIT_CLIENT_API_TOKENS;
|
|
|
|
});
|
|
|
|
|
2022-01-05 10:00:59 +01:00
|
|
|
test('should merge initApiToken from options and env vars', async () => {
|
2022-01-05 10:40:22 +01:00
|
|
|
process.env.INIT_ADMIN_API_TOKENS = '*:*.some-token1, *:*.some-token2';
|
2022-03-02 12:44:46 +01:00
|
|
|
process.env.INIT_CLIENT_API_TOKENS = 'default:development.some-token1';
|
2022-01-05 10:00:59 +01:00
|
|
|
const token = {
|
|
|
|
environment: '*',
|
|
|
|
project: '*',
|
2022-01-05 10:40:22 +01:00
|
|
|
secret: '*:*.some-random-string',
|
2022-01-05 10:00:59 +01:00
|
|
|
type: ApiTokenType.ADMIN,
|
|
|
|
username: 'admin',
|
|
|
|
};
|
|
|
|
const config = createConfig({
|
|
|
|
db: {
|
|
|
|
host: 'localhost',
|
|
|
|
port: 4242,
|
|
|
|
user: 'unleash',
|
|
|
|
password: 'password',
|
|
|
|
database: 'unleash_db',
|
|
|
|
},
|
|
|
|
server: {
|
|
|
|
port: 4242,
|
|
|
|
},
|
|
|
|
authentication: {
|
|
|
|
initApiTokens: [token],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2022-03-02 12:44:46 +01:00
|
|
|
expect(config.authentication.initApiTokens).toHaveLength(4);
|
|
|
|
delete process.env.INIT_CLIENT_API_TOKENS;
|
2022-01-05 10:00:59 +01:00
|
|
|
delete process.env.INIT_ADMIN_API_TOKENS;
|
|
|
|
});
|
2022-03-02 12:44:46 +01:00
|
|
|
|
|
|
|
test('should add initApiToken for client token from env var', async () => {
|
|
|
|
process.env.INIT_CLIENT_API_TOKENS =
|
|
|
|
'default:development.some-token1, default:development.some-token2';
|
|
|
|
|
|
|
|
const config = createConfig({
|
|
|
|
db: {
|
|
|
|
host: 'localhost',
|
|
|
|
port: 4242,
|
|
|
|
user: 'unleash',
|
|
|
|
password: 'password',
|
|
|
|
database: 'unleash_db',
|
|
|
|
},
|
|
|
|
server: {
|
|
|
|
port: 4242,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(config.authentication.initApiTokens).toHaveLength(2);
|
|
|
|
expect(config.authentication.initApiTokens[0].environment).toBe(
|
|
|
|
'development',
|
|
|
|
);
|
|
|
|
expect(config.authentication.initApiTokens[0].project).toBe('default');
|
|
|
|
expect(config.authentication.initApiTokens[0].type).toBe(
|
|
|
|
ApiTokenType.CLIENT,
|
|
|
|
);
|
|
|
|
expect(config.authentication.initApiTokens[0].secret).toBe(
|
|
|
|
'default:development.some-token1',
|
|
|
|
);
|
|
|
|
|
|
|
|
delete process.env.INIT_CLIENT_API_TOKENS;
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should handle cases where no env var specified for tokens', async () => {
|
|
|
|
const token = {
|
|
|
|
environment: '*',
|
|
|
|
project: '*',
|
|
|
|
secret: '*:*.some-random-string',
|
|
|
|
type: ApiTokenType.ADMIN,
|
|
|
|
username: 'admin',
|
|
|
|
};
|
|
|
|
const config = createConfig({
|
|
|
|
db: {
|
|
|
|
host: 'localhost',
|
|
|
|
port: 4242,
|
|
|
|
user: 'unleash',
|
|
|
|
password: 'password',
|
|
|
|
database: 'unleash_db',
|
|
|
|
},
|
|
|
|
server: {
|
|
|
|
port: 4242,
|
|
|
|
},
|
|
|
|
authentication: {
|
|
|
|
initApiTokens: [token],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(config.authentication.initApiTokens).toHaveLength(1);
|
|
|
|
});
|
2022-03-11 10:16:58 +01:00
|
|
|
|
|
|
|
test('should load environment overrides from env var', async () => {
|
|
|
|
process.env.ENABLED_ENVIRONMENTS = 'default,production';
|
|
|
|
|
|
|
|
const config = createConfig({
|
|
|
|
db: {
|
|
|
|
host: 'localhost',
|
|
|
|
port: 4242,
|
|
|
|
user: 'unleash',
|
|
|
|
password: 'password',
|
|
|
|
database: 'unleash_db',
|
|
|
|
},
|
|
|
|
server: {
|
|
|
|
port: 4242,
|
|
|
|
},
|
|
|
|
authentication: {
|
|
|
|
initApiTokens: [],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(config.environmentEnableOverrides).toHaveLength(2);
|
|
|
|
expect(config.environmentEnableOverrides).toContain('production');
|
|
|
|
delete process.env.ENABLED_ENVIRONMENTS;
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should yield an empty list when no environment overrides are specified', async () => {
|
|
|
|
const config = createConfig({
|
|
|
|
db: {
|
|
|
|
host: 'localhost',
|
|
|
|
port: 4242,
|
|
|
|
user: 'unleash',
|
|
|
|
password: 'password',
|
|
|
|
database: 'unleash_db',
|
|
|
|
},
|
|
|
|
server: {
|
|
|
|
port: 4242,
|
|
|
|
},
|
|
|
|
authentication: {
|
|
|
|
initApiTokens: [],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(config.environmentEnableOverrides).toStrictEqual([]);
|
|
|
|
});
|
2022-05-31 11:32:15 +02:00
|
|
|
|
|
|
|
test('should yield all empty lists when no additionalCspAllowedDomains are set', async () => {
|
|
|
|
const config = createConfig({});
|
|
|
|
expect(config.additionalCspAllowedDomains).toBeDefined();
|
|
|
|
expect(config.additionalCspAllowedDomains.defaultSrc).toStrictEqual([]);
|
|
|
|
expect(config.additionalCspAllowedDomains.fontSrc).toStrictEqual([]);
|
|
|
|
expect(config.additionalCspAllowedDomains.styleSrc).toStrictEqual([]);
|
|
|
|
expect(config.additionalCspAllowedDomains.scriptSrc).toStrictEqual([]);
|
|
|
|
expect(config.additionalCspAllowedDomains.imgSrc).toStrictEqual([]);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('If additionalCspAllowedDomains is set in config map, passes through', async () => {
|
|
|
|
const config = createConfig({
|
|
|
|
additionalCspAllowedDomains: {
|
|
|
|
defaultSrc: ['googlefonts.com'],
|
|
|
|
fontSrc: [],
|
|
|
|
styleSrc: [],
|
|
|
|
scriptSrc: [],
|
|
|
|
imgSrc: [],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
expect(config.additionalCspAllowedDomains).toBeDefined();
|
|
|
|
expect(config.additionalCspAllowedDomains.defaultSrc).toStrictEqual([
|
|
|
|
'googlefonts.com',
|
|
|
|
]);
|
|
|
|
expect(config.additionalCspAllowedDomains.fontSrc).toStrictEqual([]);
|
|
|
|
expect(config.additionalCspAllowedDomains.styleSrc).toStrictEqual([]);
|
|
|
|
expect(config.additionalCspAllowedDomains.scriptSrc).toStrictEqual([]);
|
|
|
|
expect(config.additionalCspAllowedDomains.imgSrc).toStrictEqual([]);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('Can set partial additionalCspDomains', () => {
|
|
|
|
const config = createConfig({
|
|
|
|
additionalCspAllowedDomains: {
|
|
|
|
defaultSrc: ['googlefonts.com'],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
expect(config.additionalCspAllowedDomains).toBeDefined();
|
|
|
|
expect(config.additionalCspAllowedDomains.defaultSrc).toStrictEqual([
|
|
|
|
'googlefonts.com',
|
|
|
|
]);
|
|
|
|
expect(config.additionalCspAllowedDomains.fontSrc).toStrictEqual([]);
|
|
|
|
expect(config.additionalCspAllowedDomains.styleSrc).toStrictEqual([]);
|
|
|
|
expect(config.additionalCspAllowedDomains.scriptSrc).toStrictEqual([]);
|
|
|
|
expect(config.additionalCspAllowedDomains.imgSrc).toStrictEqual([]);
|
|
|
|
});
|
|
|
|
|
|
|
|
test.each([
|
|
|
|
['CSP_ALLOWED_DEFAULT', 'googlefonts.com', 'defaultSrc'],
|
|
|
|
['CSP_ALLOWED_FONT', 'googlefonts.com', 'fontSrc'],
|
|
|
|
['CSP_ALLOWED_STYLE', 'googlefonts.com', 'styleSrc'],
|
|
|
|
['CSP_ALLOWED_SCRIPT', 'googlefonts.com', 'scriptSrc'],
|
|
|
|
['CSP_ALLOWED_IMG', 'googlefonts.com', 'imgSrc'],
|
|
|
|
])(
|
|
|
|
'When %s is set to %s. %s should include passed in domain',
|
|
|
|
(env, domain, key) => {
|
|
|
|
process.env[env] = domain;
|
|
|
|
const config = createConfig({});
|
|
|
|
expect(config.additionalCspAllowedDomains[key][0]).toBe(domain);
|
|
|
|
Object.keys(config.additionalCspAllowedDomains)
|
|
|
|
.filter((objKey) => objKey !== key)
|
|
|
|
.forEach((otherKey) => {
|
|
|
|
expect(
|
|
|
|
config.additionalCspAllowedDomains[otherKey],
|
|
|
|
).toStrictEqual([]);
|
|
|
|
});
|
|
|
|
delete process.env[env];
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
test('When multiple CSP environment variables are set, respects them all', () => {
|
|
|
|
process.env.CSP_ALLOWED_DEFAULT = 'googlefonts.com';
|
|
|
|
process.env.CSP_ALLOWED_IMG = 'googlefonts.com';
|
|
|
|
process.env.CSP_ALLOWED_SCRIPT = 'plausible.getunleash.io';
|
|
|
|
const config = createConfig({});
|
|
|
|
expect(config.additionalCspAllowedDomains.imgSrc).toStrictEqual([
|
|
|
|
'googlefonts.com',
|
|
|
|
]);
|
|
|
|
expect(config.additionalCspAllowedDomains.defaultSrc).toStrictEqual([
|
|
|
|
'googlefonts.com',
|
|
|
|
]);
|
|
|
|
expect(config.additionalCspAllowedDomains.scriptSrc).toStrictEqual([
|
|
|
|
'plausible.getunleash.io',
|
|
|
|
]);
|
|
|
|
delete process.env.CSP_ALLOWED_DEFAULT;
|
|
|
|
delete process.env.CSP_ALLOWED_IMG;
|
|
|
|
delete process.env.CSP_ALLOWED_SCRIPT;
|
|
|
|
});
|
|
|
|
|
|
|
|
test('Supports multiple domains comma separated in environment variables', () => {
|
|
|
|
process.env.CSP_ALLOWED_SCRIPT = 'plausible.getunleash.io,googlefonts.com';
|
|
|
|
const config = createConfig({});
|
|
|
|
expect(config.additionalCspAllowedDomains.scriptSrc).toStrictEqual([
|
|
|
|
'plausible.getunleash.io',
|
|
|
|
'googlefonts.com',
|
|
|
|
]);
|
|
|
|
});
|
2022-06-08 09:43:37 +02:00
|
|
|
|
|
|
|
test('Should enable client feature caching with .6 seconds max age by default', () => {
|
|
|
|
const config = createConfig({});
|
|
|
|
expect(config.clientFeatureCaching.enabled).toBe(true);
|
|
|
|
expect(config.clientFeatureCaching.maxAge).toBe(600);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('Should use overrides from options for client feature caching', () => {
|
|
|
|
const config = createConfig({
|
|
|
|
clientFeatureCaching: {
|
|
|
|
enabled: false,
|
|
|
|
maxAge: 120,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
expect(config.clientFeatureCaching.enabled).toBe(false);
|
|
|
|
expect(config.clientFeatureCaching.maxAge).toBe(120);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('Should be able to set client features caching using environment variables', () => {
|
|
|
|
process.env.CLIENT_FEATURE_CACHING_ENABLED = 'false';
|
|
|
|
process.env.CLIENT_FEATURE_CACHING_MAXAGE = '120';
|
|
|
|
const config = createConfig({});
|
|
|
|
expect(config.clientFeatureCaching.enabled).toBe(false);
|
|
|
|
expect(config.clientFeatureCaching.maxAge).toBe(120);
|
|
|
|
delete process.env.CLIENT_FEATURE_CACHING_ENABLED;
|
|
|
|
delete process.env.CLIENT_FEATURE_CACHING_MAXAGE;
|
|
|
|
});
|
|
|
|
|
|
|
|
test('Environment variables for client features caching takes priority over options', () => {
|
|
|
|
process.env.CLIENT_FEATURE_CACHING_MAXAGE = '120';
|
|
|
|
const config = createConfig({
|
|
|
|
clientFeatureCaching: {
|
|
|
|
maxAge: 180,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
expect(config.clientFeatureCaching.enabled).toBe(true);
|
|
|
|
expect(config.clientFeatureCaching.maxAge).toBe(120);
|
|
|
|
});
|
2022-08-26 09:09:48 +02:00
|
|
|
|
|
|
|
test('Environment variables for frontend CORS origins takes priority over options', async () => {
|
|
|
|
const create = (frontendApiOrigins?): string[] => {
|
|
|
|
return createConfig({
|
|
|
|
frontendApiOrigins,
|
|
|
|
}).frontendApiOrigins;
|
|
|
|
};
|
|
|
|
|
|
|
|
expect(create()).toEqual(['*']);
|
|
|
|
expect(create([])).toEqual([]);
|
|
|
|
expect(create(['*'])).toEqual(['*']);
|
|
|
|
expect(create(['https://example.com'])).toEqual(['https://example.com']);
|
|
|
|
expect(() => create(['a'])).toThrow('Invalid origin: a');
|
|
|
|
|
|
|
|
process.env.UNLEASH_FRONTEND_API_ORIGINS = '';
|
|
|
|
expect(create()).toEqual([]);
|
|
|
|
process.env.UNLEASH_FRONTEND_API_ORIGINS = '*';
|
|
|
|
expect(create()).toEqual(['*']);
|
|
|
|
process.env.UNLEASH_FRONTEND_API_ORIGINS = 'https://example.com, *';
|
|
|
|
expect(create()).toEqual(['https://example.com', '*']);
|
|
|
|
process.env.UNLEASH_FRONTEND_API_ORIGINS = 'b';
|
|
|
|
expect(() => create(['a'])).toThrow('Invalid origin: b');
|
|
|
|
delete process.env.UNLEASH_FRONTEND_API_ORIGINS;
|
|
|
|
expect(create()).toEqual(['*']);
|
|
|
|
});
|
2022-11-08 15:29:14 +01:00
|
|
|
|
|
|
|
test('baseUriPath defaults to the empty string', async () => {
|
|
|
|
let config = createConfig({});
|
|
|
|
expect(config.server.baseUriPath).toBe('');
|
|
|
|
});
|
|
|
|
test('BASE_URI_PATH defined in env is passed through', async () => {
|
|
|
|
process.env.BASE_URI_PATH = '/demo';
|
|
|
|
let config = createConfig({});
|
|
|
|
expect(config.server.baseUriPath).toBe('/demo');
|
|
|
|
delete process.env.BASE_URI_PATH;
|
|
|
|
});
|
|
|
|
|
|
|
|
test('environment variable takes precedence over configured variable', async () => {
|
|
|
|
process.env.BASE_URI_PATH = '/demo';
|
|
|
|
let config = createConfig({
|
|
|
|
server: {
|
|
|
|
baseUriPath: '/other',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
expect(config.server.baseUriPath).toBe('/demo');
|
|
|
|
delete process.env.BASE_URI_PATH;
|
|
|
|
});
|
|
|
|
|
|
|
|
test.each(['demo', '/demo', '/demo/'])(
|
|
|
|
'Trailing and leading slashes gets normalized for base path %s',
|
|
|
|
async (path) => {
|
|
|
|
let config = createConfig({
|
|
|
|
server: {
|
|
|
|
baseUriPath: path,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
expect(config.server.baseUriPath).toBe('/demo');
|
|
|
|
},
|
|
|
|
);
|