Skip to content

Commit

Permalink
refactor: block creating token for disabled environment (#1464)
Browse files Browse the repository at this point in the history
* refactor: block creating token for disabled environment

Co-authored-by: olav <mail@olav.io>

* refactore: remove unused deps

Co-authored-by: olav <mail@olav.io>
  • Loading branch information
ykhedher and olav committed Mar 24, 2022
1 parent b76be29 commit d11d0e7
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 2 deletions.
4 changes: 3 additions & 1 deletion src/lib/services/api-token-service.test.ts
Expand Up @@ -3,6 +3,7 @@ import { createTestConfig } from '../../test/config/test-config';
import { IUnleashConfig } from '../server-impl';
import { ApiTokenType } from '../types/models/api-token';
import FakeApiTokenStore from '../../test/fixtures/fake-api-token-store';
import FakeEnvironmentStore from '../../test/fixtures/fake-environment-store';

test('Should init api token', async () => {
const token = {
Expand All @@ -19,11 +20,12 @@ test('Should init api token', async () => {
},
});
const apiTokenStore = new FakeApiTokenStore();
const environmentStore = new FakeEnvironmentStore();
const insertCalled = new Promise((resolve) => {
apiTokenStore.on('insert', resolve);
});

new ApiTokenService({ apiTokenStore }, config);
new ApiTokenService({ apiTokenStore, environmentStore }, config);

await insertCalled;

Expand Down
13 changes: 12 additions & 1 deletion src/lib/services/api-token-service.ts
Expand Up @@ -9,26 +9,34 @@ import {
IApiToken,
IApiTokenCreate,
validateApiToken,
validateApiTokenEnvironment,
} from '../types/models/api-token';
import { IApiTokenStore } from '../types/stores/api-token-store';
import { FOREIGN_KEY_VIOLATION } from '../error/db-error';
import BadDataError from '../error/bad-data-error';
import { minutesToMilliseconds } from 'date-fns';
import { IEnvironmentStore } from 'lib/types/stores/environment-store';

export class ApiTokenService {
private store: IApiTokenStore;

private environmentStore: IEnvironmentStore;

private logger: Logger;

private timer: NodeJS.Timeout;

private activeTokens: IApiToken[] = [];

constructor(
{ apiTokenStore }: Pick<IUnleashStores, 'apiTokenStore'>,
{
apiTokenStore,
environmentStore,
}: Pick<IUnleashStores, 'apiTokenStore' | 'environmentStore'>,
config: Pick<IUnleashConfig, 'getLogger' | 'authentication'>,
) {
this.store = apiTokenStore;
this.environmentStore = environmentStore;
this.logger = config.getLogger('/services/api-token-service.ts');
this.fetchActiveTokens();
this.timer = setInterval(
Expand Down Expand Up @@ -105,6 +113,9 @@ export class ApiTokenService {
): Promise<IApiToken> {
validateApiToken(newToken);

const environments = await this.environmentStore.getAll();
validateApiTokenEnvironment(newToken, environments);

const secret = this.generateSecretKey(newToken);
const createNewToken = { ...newToken, secret };
return this.insertNewApiToken(createNewToken);
Expand Down
24 changes: 24 additions & 0 deletions src/lib/types/models/api-token.ts
@@ -1,4 +1,5 @@
import BadDataError from '../../error/bad-data-error';
import { IEnvironment } from '../model';

export const ALL = '*';

Expand Down Expand Up @@ -46,3 +47,26 @@ export const validateApiToken = ({
);
}
};

export const validateApiTokenEnvironment = (
{ environment }: Pick<IApiTokenCreate, 'environment'>,
environments: IEnvironment[],
): void => {
if (environment === ALL) {
return;
}

const selectedEnvironment = environments.find(
(env) => env.name === environment,
);

if (!selectedEnvironment) {
throw new BadDataError(`Environment=${environment} does not exist`);
}

if (!selectedEnvironment.enabled) {
throw new BadDataError(
'Client token cannot be scoped to disabled environments',
);
}
};
18 changes: 18 additions & 0 deletions src/test/e2e/api/admin/api-token.e2e.test.ts
Expand Up @@ -331,3 +331,21 @@ test('client tokens cannot span all environments', async () => {
.set('Content-Type', 'application/json')
.expect(400);
});

test('should not create token for disabled environment', async () => {
await db.stores.environmentStore.create({
name: 'disabledEnvironment',
type: 'production',
enabled: false,
});
return app.request
.post('/api/admin/api-tokens')
.send({
username: 'default',
type: 'client',
project: 'default',
environment: 'disabledEnvironment',
})
.set('Content-Type', 'application/json')
.expect(400);
});

0 comments on commit d11d0e7

Please sign in to comment.