Skip to content

Commit

Permalink
Merge branch 'main' into docs/new-constraint-operators
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasheartman committed Mar 9, 2022
2 parents 5228151 + 3910e23 commit aafa200
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 24 deletions.
113 changes: 109 additions & 4 deletions src/lib/create-config.test.ts
Expand Up @@ -18,7 +18,7 @@ test('should create default config', async () => {
expect(config).toMatchSnapshot();
});

test('should add initApiToken from options', async () => {
test('should add initApiToken for admin token from options', async () => {
const token = {
environment: '*',
project: '*',
Expand Down Expand Up @@ -52,7 +52,41 @@ test('should add initApiToken from options', async () => {
);
});

test('should add initApiToken from env var', async () => {
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 () => {
process.env.INIT_ADMIN_API_TOKENS = '*:*.some-token1, *:*.some-token2';

const config = createConfig({
Expand Down Expand Up @@ -81,7 +115,7 @@ test('should add initApiToken from env var', async () => {
delete process.env.INIT_ADMIN_API_TOKENS;
});

test('should validate initApiToken from env var', async () => {
test('should validate initApiToken for admin token from env var', async () => {
process.env.INIT_ADMIN_API_TOKENS = 'invalidProject:*:some-token1';

expect(() => createConfig({})).toThrow(
Expand All @@ -91,8 +125,19 @@ test('should validate initApiToken from env var', async () => {
delete process.env.INIT_ADMIN_API_TOKENS;
});

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;
});

test('should merge initApiToken from options and env vars', async () => {
process.env.INIT_ADMIN_API_TOKENS = '*:*.some-token1, *:*.some-token2';
process.env.INIT_CLIENT_API_TOKENS = 'default:development.some-token1';
const token = {
environment: '*',
project: '*',
Expand All @@ -116,6 +161,66 @@ test('should merge initApiToken from options and env vars', async () => {
},
});

expect(config.authentication.initApiTokens).toHaveLength(3);
expect(config.authentication.initApiTokens).toHaveLength(4);
delete process.env.INIT_CLIENT_API_TOKENS;
delete process.env.INIT_ADMIN_API_TOKENS;
});

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);
});
50 changes: 31 additions & 19 deletions src/lib/create-config.ts
Expand Up @@ -182,27 +182,39 @@ const formatServerOptions = (
};
};

const loadInitApiTokens = () => {
if (process.env.INIT_ADMIN_API_TOKENS) {
const initApiTokens = process.env.INIT_ADMIN_API_TOKENS.split(/,\s?/);
const tokens = initApiTokens.map((secret) => {
const [project = '*', rest] = secret.split(':');
const [environment = '*'] = rest.split('.');
const token = {
createdAt: undefined,
project,
environment,
secret,
type: ApiTokenType.ADMIN,
username: 'admin',
};
validateApiToken(token);
return token;
});
return tokens;
} else {
const loadTokensFromString = (tokenString: String, tokenType: ApiTokenType) => {
if (!tokenString) {
return [];
}
const initApiTokens = tokenString.split(/,\s?/);
const tokens = initApiTokens.map((secret) => {
const [project = '*', rest] = secret.split(':');
const [environment = '*'] = rest.split('.');
const token = {
createdAt: undefined,
project,
environment,
secret,
type: tokenType,
username: 'admin',
};
validateApiToken(token);
return token;
});
return tokens;
};

const loadInitApiTokens = () => {
return [
...loadTokensFromString(
process.env.INIT_ADMIN_API_TOKENS,
ApiTokenType.ADMIN,
),
...loadTokensFromString(
process.env.INIT_CLIENT_API_TOKENS,
ApiTokenType.CLIENT,
),
];
};

export function createConfig(options: IUnleashOptions): IUnleashConfig {
Expand Down
2 changes: 1 addition & 1 deletion website/docs/deploy/configuring-unleash.md
Expand Up @@ -89,7 +89,7 @@ unleash.start(unleashOptions);
```
The tokens can be of any API token type. Note that _admin_ tokens **must** target all environments and projects (i.e. use `'*'` for `environments` and `project` and start the secret with `*:*.`).

You can also use the environment variable `INIT_ADMIN_API_TOKENS` to create API tokens on startup. This variable should be set to a comma-separated list of API tokens to initialize (for instance `*:*.some-random-string, *:*.some-other-token`). With the environment variable, all tokens will be created as admin tokens and Unleash will assign a username automatically.
You can also use the environment variables `INIT_ADMIN_API_TOKENS` or `INIT_CLIENT_API_TOKENS` to create API admin or client tokens on startup. Both variables require a comma-separated list of API tokens to initialize (for instance `*:*.some-random-string, *:*.some-other-token`). The tokens found in `INIT_ADMIN_API_TOKENS` and `INIT_CLIENT_API_TOKENS` will be created as admin and client tokens respectively and Unleash will assign a username automatically.
- **databaseUrl** - (_deprecated_) the postgres database url to connect to. Only used if _db_ object is not specified, and overrides the _db_ object and any environment variables that change parts of it (like `DATABASE_SSL`). Should include username/password. This value may also be set via the `DATABASE_URL` environment variable. Alternatively, if you would like to read the database url from a file, you may set the `DATABASE_URL_FILE` environment variable with the full file path. The contents of the file must be the database url exactly.
- **db** - The database configuration object taking the following properties:
- _user_ - the database username (`DATABASE_USERNAME`)
Expand Down

0 comments on commit aafa200

Please sign in to comment.