2021-03-29 19:58:11 +02:00
|
|
|
import dbInit from '../helpers/database-init';
|
|
|
|
import getLogger from '../../fixtures/no-logger';
|
|
|
|
import { ApiTokenService } from '../../../lib/services/api-token-service';
|
2021-04-22 15:04:08 +02:00
|
|
|
import { createTestConfig } from '../../config/test-config';
|
2021-09-15 20:28:10 +02:00
|
|
|
import { ApiTokenType, IApiToken } from '../../../lib/types/models/api-token';
|
2021-09-24 13:55:00 +02:00
|
|
|
import { DEFAULT_ENV } from '../../../lib/util/constants';
|
2021-11-02 15:13:46 +01:00
|
|
|
import { addDays, subDays } from 'date-fns';
|
2022-04-06 08:11:41 +02:00
|
|
|
import ProjectService from '../../../lib/services/project-service';
|
|
|
|
import FeatureToggleService from '../../../lib/services/feature-toggle-service';
|
|
|
|
import { AccessService } from '../../../lib/services/access-service';
|
2022-06-08 15:41:02 +02:00
|
|
|
import { SegmentService } from '../../../lib/services/segment-service';
|
2022-07-21 16:23:56 +02:00
|
|
|
import { GroupService } from '../../../lib/services/group-service';
|
2023-01-18 13:22:58 +01:00
|
|
|
import { FavoritesService } from '../../../lib/services';
|
2021-03-29 19:58:11 +02:00
|
|
|
|
|
|
|
let db;
|
|
|
|
let stores;
|
|
|
|
let apiTokenService: ApiTokenService;
|
2022-04-06 08:11:41 +02:00
|
|
|
let projectService: ProjectService;
|
2023-01-18 13:22:58 +01:00
|
|
|
let favoritesService: FavoritesService;
|
2021-03-29 19:58:11 +02:00
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
beforeAll(async () => {
|
2021-04-22 15:04:08 +02:00
|
|
|
const config = createTestConfig({
|
2021-04-22 10:07:10 +02:00
|
|
|
server: { baseUriPath: '/test' },
|
|
|
|
});
|
2021-04-09 13:46:53 +02:00
|
|
|
db = await dbInit('api_token_service_serial', getLogger);
|
2021-03-29 19:58:11 +02:00
|
|
|
stores = db.stores;
|
2022-07-21 16:23:56 +02:00
|
|
|
const groupService = new GroupService(stores, config);
|
|
|
|
const accessService = new AccessService(stores, config, groupService);
|
2022-06-08 15:41:02 +02:00
|
|
|
const featureToggleService = new FeatureToggleService(
|
|
|
|
stores,
|
|
|
|
config,
|
|
|
|
new SegmentService(stores, config),
|
2022-10-05 23:33:36 +02:00
|
|
|
accessService,
|
2022-06-08 15:41:02 +02:00
|
|
|
);
|
2022-04-06 08:11:41 +02:00
|
|
|
const project = {
|
|
|
|
id: 'test-project',
|
|
|
|
name: 'Test Project',
|
|
|
|
description: 'Fancy',
|
|
|
|
};
|
|
|
|
const user = await stores.userStore.insert({
|
|
|
|
name: 'Some Name',
|
|
|
|
email: 'test@getunleash.io',
|
|
|
|
});
|
2023-01-18 13:22:58 +01:00
|
|
|
favoritesService = new FavoritesService(stores, config);
|
2022-04-06 08:11:41 +02:00
|
|
|
projectService = new ProjectService(
|
|
|
|
stores,
|
|
|
|
config,
|
|
|
|
accessService,
|
|
|
|
featureToggleService,
|
2022-07-21 16:23:56 +02:00
|
|
|
groupService,
|
2023-01-18 13:22:58 +01:00
|
|
|
favoritesService,
|
2022-04-06 08:11:41 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
await projectService.createProject(project, user);
|
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
apiTokenService = new ApiTokenService(stores, config);
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
afterAll(async () => {
|
|
|
|
if (db) {
|
|
|
|
await db.destroy();
|
|
|
|
}
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
2021-05-28 11:10:24 +02:00
|
|
|
afterEach(async () => {
|
2021-03-29 19:58:11 +02:00
|
|
|
const tokens = await stores.apiTokenStore.getAll();
|
|
|
|
const deleteAll = tokens.map((t: IApiToken) =>
|
|
|
|
stores.apiTokenStore.delete(t.secret),
|
|
|
|
);
|
|
|
|
await Promise.all(deleteAll);
|
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should have empty list of tokens', async () => {
|
2021-03-29 19:58:11 +02:00
|
|
|
const allTokens = await apiTokenService.getAllTokens();
|
|
|
|
const activeTokens = await apiTokenService.getAllTokens();
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(allTokens.length).toBe(0);
|
|
|
|
expect(activeTokens.length).toBe(0);
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should create client token', async () => {
|
2021-09-15 20:28:10 +02:00
|
|
|
const token = await apiTokenService.createApiToken({
|
2021-03-29 19:58:11 +02:00
|
|
|
username: 'default-client',
|
|
|
|
type: ApiTokenType.CLIENT,
|
2021-09-15 20:28:10 +02:00
|
|
|
project: '*',
|
2021-09-24 13:55:00 +02:00
|
|
|
environment: DEFAULT_ENV,
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
const allTokens = await apiTokenService.getAllTokens();
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(allTokens.length).toBe(1);
|
|
|
|
expect(token.secret.length > 32).toBe(true);
|
|
|
|
expect(token.type).toBe(ApiTokenType.CLIENT);
|
|
|
|
expect(token.username).toBe('default-client');
|
|
|
|
expect(allTokens[0].secret).toBe(token.secret);
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should create admin token', async () => {
|
2021-09-15 20:28:10 +02:00
|
|
|
const token = await apiTokenService.createApiToken({
|
2021-03-29 19:58:11 +02:00
|
|
|
username: 'admin',
|
|
|
|
type: ApiTokenType.ADMIN,
|
2021-09-15 20:28:10 +02:00
|
|
|
project: '*',
|
|
|
|
environment: '*',
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(token.secret.length > 32).toBe(true);
|
|
|
|
expect(token.type).toBe(ApiTokenType.ADMIN);
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should set expiry of token', async () => {
|
2021-03-29 19:58:11 +02:00
|
|
|
const time = new Date('2022-01-01');
|
2021-09-15 20:28:10 +02:00
|
|
|
await apiTokenService.createApiToken({
|
2021-03-29 19:58:11 +02:00
|
|
|
username: 'default-client',
|
|
|
|
type: ApiTokenType.CLIENT,
|
|
|
|
expiresAt: time,
|
2021-09-15 20:28:10 +02:00
|
|
|
project: '*',
|
2021-09-24 13:55:00 +02:00
|
|
|
environment: DEFAULT_ENV,
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
const [token] = await apiTokenService.getAllTokens();
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(token.expiresAt).toEqual(time);
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should update expiry of token', async () => {
|
2021-03-29 19:58:11 +02:00
|
|
|
const time = new Date('2022-01-01');
|
|
|
|
const newTime = new Date('2023-01-01');
|
|
|
|
|
2022-11-28 10:56:34 +01:00
|
|
|
const token = await apiTokenService.createApiToken(
|
|
|
|
{
|
|
|
|
username: 'default-client',
|
|
|
|
type: ApiTokenType.CLIENT,
|
|
|
|
expiresAt: time,
|
|
|
|
project: '*',
|
|
|
|
environment: DEFAULT_ENV,
|
|
|
|
},
|
|
|
|
'tester',
|
|
|
|
);
|
2021-03-29 19:58:11 +02:00
|
|
|
|
2022-11-28 10:56:34 +01:00
|
|
|
await apiTokenService.updateExpiry(token.secret, newTime, 'tester');
|
2021-03-29 19:58:11 +02:00
|
|
|
|
|
|
|
const [updatedToken] = await apiTokenService.getAllTokens();
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(updatedToken.expiresAt).toEqual(newTime);
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should only return valid tokens', async () => {
|
2021-11-02 15:13:46 +01:00
|
|
|
const now = Date.now();
|
|
|
|
const yesterday = subDays(now, 1);
|
|
|
|
const tomorrow = addDays(now, 1);
|
2021-03-29 19:58:11 +02:00
|
|
|
|
2021-09-15 20:28:10 +02:00
|
|
|
await apiTokenService.createApiToken({
|
2021-03-29 19:58:11 +02:00
|
|
|
username: 'default-expired',
|
|
|
|
type: ApiTokenType.CLIENT,
|
2021-11-02 15:13:46 +01:00
|
|
|
expiresAt: yesterday,
|
2021-09-15 20:28:10 +02:00
|
|
|
project: '*',
|
2021-09-24 13:55:00 +02:00
|
|
|
environment: DEFAULT_ENV,
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
|
2021-09-15 20:28:10 +02:00
|
|
|
const activeToken = await apiTokenService.createApiToken({
|
2021-03-29 19:58:11 +02:00
|
|
|
username: 'default-valid',
|
|
|
|
type: ApiTokenType.CLIENT,
|
|
|
|
expiresAt: tomorrow,
|
2021-09-15 20:28:10 +02:00
|
|
|
project: '*',
|
2021-09-24 13:55:00 +02:00
|
|
|
environment: DEFAULT_ENV,
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
const tokens = await apiTokenService.getAllActiveTokens();
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(tokens.length).toBe(1);
|
|
|
|
expect(activeToken.secret).toBe(tokens[0].secret);
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
2022-04-06 08:11:41 +02:00
|
|
|
|
|
|
|
test('should create client token with project list', async () => {
|
|
|
|
const token = await apiTokenService.createApiToken({
|
|
|
|
username: 'default-client',
|
|
|
|
type: ApiTokenType.CLIENT,
|
|
|
|
projects: ['default', 'test-project'],
|
|
|
|
environment: DEFAULT_ENV,
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(token.secret.slice(0, 2)).toEqual('[]');
|
|
|
|
expect(token.projects).toStrictEqual(['default', 'test-project']);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should strip all other projects if ALL_PROJECTS is present', async () => {
|
|
|
|
const token = await apiTokenService.createApiToken({
|
|
|
|
username: 'default-client',
|
|
|
|
type: ApiTokenType.CLIENT,
|
|
|
|
projects: ['*', 'default'],
|
|
|
|
environment: DEFAULT_ENV,
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(token.projects).toStrictEqual(['*']);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should return user with multiple projects', async () => {
|
|
|
|
const now = Date.now();
|
|
|
|
const tomorrow = addDays(now, 1);
|
|
|
|
|
|
|
|
await apiTokenService.createApiToken({
|
|
|
|
username: 'default-valid',
|
|
|
|
type: ApiTokenType.CLIENT,
|
|
|
|
expiresAt: tomorrow,
|
|
|
|
projects: ['test-project', 'default'],
|
|
|
|
environment: DEFAULT_ENV,
|
|
|
|
});
|
|
|
|
|
|
|
|
await apiTokenService.createApiToken({
|
|
|
|
username: 'default-also-valid',
|
|
|
|
type: ApiTokenType.CLIENT,
|
|
|
|
expiresAt: tomorrow,
|
|
|
|
projects: ['test-project'],
|
|
|
|
environment: DEFAULT_ENV,
|
|
|
|
});
|
|
|
|
|
|
|
|
const tokens = await apiTokenService.getAllActiveTokens();
|
|
|
|
const multiProjectUser = await apiTokenService.getUserForToken(
|
|
|
|
tokens[0].secret,
|
|
|
|
);
|
|
|
|
const singleProjectUser = await apiTokenService.getUserForToken(
|
|
|
|
tokens[1].secret,
|
|
|
|
);
|
|
|
|
|
|
|
|
expect(multiProjectUser.projects).toStrictEqual([
|
|
|
|
'test-project',
|
|
|
|
'default',
|
|
|
|
]);
|
|
|
|
expect(singleProjectUser.projects).toStrictEqual(['test-project']);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should not partially create token if projects are invalid', async () => {
|
|
|
|
try {
|
|
|
|
await apiTokenService.createApiTokenWithProjects({
|
|
|
|
username: 'default-client',
|
|
|
|
type: ApiTokenType.CLIENT,
|
|
|
|
projects: ['non-existent-project'],
|
|
|
|
environment: DEFAULT_ENV,
|
|
|
|
});
|
|
|
|
} catch (e) {}
|
|
|
|
const allTokens = await apiTokenService.getAllTokens();
|
|
|
|
|
|
|
|
expect(allTokens.length).toBe(0);
|
|
|
|
});
|