mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-04 00:18:01 +01:00
refactor: block creating token for disabled environment (#1464)
* 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>
This commit is contained in:
parent
b76be29e59
commit
d11d0e712b
@ -3,6 +3,7 @@ import { createTestConfig } from '../../test/config/test-config';
|
|||||||
import { IUnleashConfig } from '../server-impl';
|
import { IUnleashConfig } from '../server-impl';
|
||||||
import { ApiTokenType } from '../types/models/api-token';
|
import { ApiTokenType } from '../types/models/api-token';
|
||||||
import FakeApiTokenStore from '../../test/fixtures/fake-api-token-store';
|
import FakeApiTokenStore from '../../test/fixtures/fake-api-token-store';
|
||||||
|
import FakeEnvironmentStore from '../../test/fixtures/fake-environment-store';
|
||||||
|
|
||||||
test('Should init api token', async () => {
|
test('Should init api token', async () => {
|
||||||
const token = {
|
const token = {
|
||||||
@ -19,11 +20,12 @@ test('Should init api token', async () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const apiTokenStore = new FakeApiTokenStore();
|
const apiTokenStore = new FakeApiTokenStore();
|
||||||
|
const environmentStore = new FakeEnvironmentStore();
|
||||||
const insertCalled = new Promise((resolve) => {
|
const insertCalled = new Promise((resolve) => {
|
||||||
apiTokenStore.on('insert', resolve);
|
apiTokenStore.on('insert', resolve);
|
||||||
});
|
});
|
||||||
|
|
||||||
new ApiTokenService({ apiTokenStore }, config);
|
new ApiTokenService({ apiTokenStore, environmentStore }, config);
|
||||||
|
|
||||||
await insertCalled;
|
await insertCalled;
|
||||||
|
|
||||||
|
@ -9,15 +9,19 @@ import {
|
|||||||
IApiToken,
|
IApiToken,
|
||||||
IApiTokenCreate,
|
IApiTokenCreate,
|
||||||
validateApiToken,
|
validateApiToken,
|
||||||
|
validateApiTokenEnvironment,
|
||||||
} from '../types/models/api-token';
|
} from '../types/models/api-token';
|
||||||
import { IApiTokenStore } from '../types/stores/api-token-store';
|
import { IApiTokenStore } from '../types/stores/api-token-store';
|
||||||
import { FOREIGN_KEY_VIOLATION } from '../error/db-error';
|
import { FOREIGN_KEY_VIOLATION } from '../error/db-error';
|
||||||
import BadDataError from '../error/bad-data-error';
|
import BadDataError from '../error/bad-data-error';
|
||||||
import { minutesToMilliseconds } from 'date-fns';
|
import { minutesToMilliseconds } from 'date-fns';
|
||||||
|
import { IEnvironmentStore } from 'lib/types/stores/environment-store';
|
||||||
|
|
||||||
export class ApiTokenService {
|
export class ApiTokenService {
|
||||||
private store: IApiTokenStore;
|
private store: IApiTokenStore;
|
||||||
|
|
||||||
|
private environmentStore: IEnvironmentStore;
|
||||||
|
|
||||||
private logger: Logger;
|
private logger: Logger;
|
||||||
|
|
||||||
private timer: NodeJS.Timeout;
|
private timer: NodeJS.Timeout;
|
||||||
@ -25,10 +29,14 @@ export class ApiTokenService {
|
|||||||
private activeTokens: IApiToken[] = [];
|
private activeTokens: IApiToken[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
{ apiTokenStore }: Pick<IUnleashStores, 'apiTokenStore'>,
|
{
|
||||||
|
apiTokenStore,
|
||||||
|
environmentStore,
|
||||||
|
}: Pick<IUnleashStores, 'apiTokenStore' | 'environmentStore'>,
|
||||||
config: Pick<IUnleashConfig, 'getLogger' | 'authentication'>,
|
config: Pick<IUnleashConfig, 'getLogger' | 'authentication'>,
|
||||||
) {
|
) {
|
||||||
this.store = apiTokenStore;
|
this.store = apiTokenStore;
|
||||||
|
this.environmentStore = environmentStore;
|
||||||
this.logger = config.getLogger('/services/api-token-service.ts');
|
this.logger = config.getLogger('/services/api-token-service.ts');
|
||||||
this.fetchActiveTokens();
|
this.fetchActiveTokens();
|
||||||
this.timer = setInterval(
|
this.timer = setInterval(
|
||||||
@ -105,6 +113,9 @@ export class ApiTokenService {
|
|||||||
): Promise<IApiToken> {
|
): Promise<IApiToken> {
|
||||||
validateApiToken(newToken);
|
validateApiToken(newToken);
|
||||||
|
|
||||||
|
const environments = await this.environmentStore.getAll();
|
||||||
|
validateApiTokenEnvironment(newToken, environments);
|
||||||
|
|
||||||
const secret = this.generateSecretKey(newToken);
|
const secret = this.generateSecretKey(newToken);
|
||||||
const createNewToken = { ...newToken, secret };
|
const createNewToken = { ...newToken, secret };
|
||||||
return this.insertNewApiToken(createNewToken);
|
return this.insertNewApiToken(createNewToken);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import BadDataError from '../../error/bad-data-error';
|
import BadDataError from '../../error/bad-data-error';
|
||||||
|
import { IEnvironment } from '../model';
|
||||||
|
|
||||||
export const ALL = '*';
|
export const ALL = '*';
|
||||||
|
|
||||||
@ -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',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -331,3 +331,21 @@ test('client tokens cannot span all environments', async () => {
|
|||||||
.set('Content-Type', 'application/json')
|
.set('Content-Type', 'application/json')
|
||||||
.expect(400);
|
.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);
|
||||||
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user