2021-03-29 19:58:11 +02:00
|
|
|
import getLogger from '../../test/fixtures/no-logger';
|
2021-05-02 20:58:02 +02:00
|
|
|
import { CLIENT } from '../types/permissions';
|
2021-04-22 15:04:08 +02:00
|
|
|
import { createTestConfig } from '../../test/config/test-config';
|
2021-04-22 23:40:52 +02:00
|
|
|
import ApiUser from '../types/api-user';
|
2021-09-15 20:28:10 +02:00
|
|
|
import { ALL, ApiTokenType } from '../types/models/api-token';
|
2022-06-17 09:00:13 +02:00
|
|
|
import apiTokenMiddleware, {
|
|
|
|
TOKEN_TYPE_ERROR_MESSAGE,
|
|
|
|
} from './api-token-middleware';
|
2024-01-17 14:33:03 +01:00
|
|
|
import { ApiTokenService } from '../services';
|
|
|
|
import { IUnleashConfig } from '../types';
|
2021-03-29 19:58:11 +02:00
|
|
|
|
2023-11-03 12:00:24 +01:00
|
|
|
let config: IUnleashConfig;
|
2021-03-29 19:58:11 +02:00
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
beforeEach(() => {
|
2023-11-03 12:00:24 +01:00
|
|
|
config = createTestConfig({
|
2021-03-29 19:58:11 +02:00
|
|
|
getLogger,
|
|
|
|
authentication: {
|
|
|
|
enableApiToken: true,
|
|
|
|
},
|
2023-11-03 12:00:24 +01:00
|
|
|
});
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should not do anything if request does not contain a authorization', async () => {
|
2021-03-29 19:58:11 +02:00
|
|
|
const apiTokenService = {
|
2021-05-28 11:10:24 +02:00
|
|
|
getUserForToken: jest.fn(),
|
2023-11-03 12:00:24 +01:00
|
|
|
} as unknown as ApiTokenService;
|
2021-03-29 19:58:11 +02:00
|
|
|
|
|
|
|
const func = apiTokenMiddleware(config, { apiTokenService });
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
const cb = jest.fn();
|
2021-03-29 19:58:11 +02:00
|
|
|
|
|
|
|
const req = {
|
2021-05-28 11:10:24 +02:00
|
|
|
header: jest.fn(),
|
2021-03-29 19:58:11 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
await func(req, undefined, cb);
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(req.header).toHaveBeenCalledTimes(1);
|
|
|
|
expect(cb).toHaveBeenCalledTimes(1);
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should not add user if unknown token', async () => {
|
2021-03-29 19:58:11 +02:00
|
|
|
const apiTokenService = {
|
2021-05-28 11:10:24 +02:00
|
|
|
getUserForToken: jest.fn(),
|
2023-11-03 12:00:24 +01:00
|
|
|
} as unknown as ApiTokenService;
|
2021-03-29 19:58:11 +02:00
|
|
|
|
|
|
|
const func = apiTokenMiddleware(config, { apiTokenService });
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
const cb = jest.fn();
|
2021-03-29 19:58:11 +02:00
|
|
|
|
|
|
|
const req = {
|
2021-05-28 11:10:24 +02:00
|
|
|
header: jest.fn().mockReturnValue('some-token'),
|
2021-03-29 19:58:11 +02:00
|
|
|
user: undefined,
|
|
|
|
};
|
|
|
|
|
|
|
|
await func(req, undefined, cb);
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(cb).toHaveBeenCalled();
|
|
|
|
expect(req.header).toHaveBeenCalled();
|
|
|
|
expect(req.user).toBeFalsy();
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
|
2022-09-29 07:53:29 +02:00
|
|
|
test('should not make database query when provided PAT format', async () => {
|
|
|
|
const apiTokenService = {
|
|
|
|
getUserForToken: jest.fn(),
|
2023-11-03 12:00:24 +01:00
|
|
|
} as unknown as ApiTokenService;
|
2022-09-29 07:53:29 +02:00
|
|
|
|
|
|
|
const func = apiTokenMiddleware(config, { apiTokenService });
|
|
|
|
|
|
|
|
const cb = jest.fn();
|
|
|
|
|
|
|
|
const req = {
|
|
|
|
header: jest.fn().mockReturnValue('user:asdkjsdhg3'),
|
|
|
|
user: undefined,
|
|
|
|
};
|
|
|
|
|
|
|
|
await func(req, undefined, cb);
|
|
|
|
|
|
|
|
expect(apiTokenService.getUserForToken).not.toHaveBeenCalled();
|
|
|
|
expect(req.header).toHaveBeenCalled();
|
|
|
|
expect(cb).toHaveBeenCalled();
|
|
|
|
expect(req.user).toBeFalsy();
|
|
|
|
});
|
|
|
|
|
2021-09-15 20:28:10 +02:00
|
|
|
test('should add user if known token', async () => {
|
2021-04-22 23:40:52 +02:00
|
|
|
const apiUser = new ApiUser({
|
2023-05-04 09:56:00 +02:00
|
|
|
tokenName: 'default',
|
2021-03-29 19:58:11 +02:00
|
|
|
permissions: [CLIENT],
|
2021-09-15 20:28:10 +02:00
|
|
|
project: ALL,
|
|
|
|
environment: ALL,
|
|
|
|
type: ApiTokenType.CLIENT,
|
2022-08-16 15:33:33 +02:00
|
|
|
secret: 'a',
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
const apiTokenService = {
|
2021-05-28 11:10:24 +02:00
|
|
|
getUserForToken: jest.fn().mockReturnValue(apiUser),
|
2023-11-03 12:00:24 +01:00
|
|
|
} as unknown as ApiTokenService;
|
2021-03-29 19:58:11 +02:00
|
|
|
|
|
|
|
const func = apiTokenMiddleware(config, { apiTokenService });
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
const cb = jest.fn();
|
2021-03-29 19:58:11 +02:00
|
|
|
|
|
|
|
const req = {
|
2021-05-28 11:10:24 +02:00
|
|
|
header: jest.fn().mockReturnValue('some-known-token'),
|
2021-03-29 19:58:11 +02:00
|
|
|
user: undefined,
|
2021-09-15 20:28:10 +02:00
|
|
|
path: '/api/client',
|
2021-03-29 19:58:11 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
await func(req, undefined, cb);
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(cb).toHaveBeenCalled();
|
|
|
|
expect(req.header).toHaveBeenCalled();
|
|
|
|
expect(req.user).toBe(apiUser);
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
|
2021-09-15 20:28:10 +02:00
|
|
|
test('should not add user if not /api/client', async () => {
|
2022-06-17 09:00:13 +02:00
|
|
|
expect.assertions(5);
|
|
|
|
|
2021-09-15 20:28:10 +02:00
|
|
|
const apiUser = new ApiUser({
|
2023-05-04 09:56:00 +02:00
|
|
|
tokenName: 'default',
|
2021-09-15 20:28:10 +02:00
|
|
|
permissions: [CLIENT],
|
|
|
|
project: ALL,
|
|
|
|
environment: ALL,
|
|
|
|
type: ApiTokenType.CLIENT,
|
2022-08-16 15:33:33 +02:00
|
|
|
secret: 'a',
|
2021-09-15 20:28:10 +02:00
|
|
|
});
|
2022-06-17 09:00:13 +02:00
|
|
|
|
2021-09-15 20:28:10 +02:00
|
|
|
const apiTokenService = {
|
|
|
|
getUserForToken: jest.fn().mockReturnValue(apiUser),
|
2023-11-03 12:00:24 +01:00
|
|
|
} as unknown as ApiTokenService;
|
2021-09-15 20:28:10 +02:00
|
|
|
|
|
|
|
const func = apiTokenMiddleware(config, { apiTokenService });
|
|
|
|
const cb = jest.fn();
|
|
|
|
|
|
|
|
const res = {
|
2022-06-17 09:00:13 +02:00
|
|
|
status: (code: unknown) => ({
|
|
|
|
send: (data: unknown) => {
|
|
|
|
expect(code).toEqual(403);
|
|
|
|
expect(data).toEqual({ message: TOKEN_TYPE_ERROR_MESSAGE });
|
|
|
|
},
|
|
|
|
}),
|
2021-09-15 20:28:10 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
const req = {
|
|
|
|
header: jest.fn().mockReturnValue('some-known-token'),
|
|
|
|
user: undefined,
|
|
|
|
path: '/api/admin',
|
|
|
|
};
|
|
|
|
|
|
|
|
await func(req, res, cb);
|
|
|
|
|
|
|
|
expect(cb).not.toHaveBeenCalled();
|
|
|
|
expect(req.header).toHaveBeenCalled();
|
|
|
|
expect(req.user).toBeUndefined();
|
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should not add user if disabled', async () => {
|
2021-04-22 23:40:52 +02:00
|
|
|
const apiUser = new ApiUser({
|
2023-05-04 09:56:00 +02:00
|
|
|
tokenName: 'default',
|
2021-03-29 19:58:11 +02:00
|
|
|
permissions: [CLIENT],
|
2021-09-15 20:28:10 +02:00
|
|
|
project: ALL,
|
|
|
|
environment: ALL,
|
|
|
|
type: ApiTokenType.CLIENT,
|
2022-08-16 15:33:33 +02:00
|
|
|
secret: 'a',
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
const apiTokenService = {
|
2021-05-28 11:10:24 +02:00
|
|
|
getUserForToken: jest.fn().mockReturnValue(apiUser),
|
2023-11-03 12:00:24 +01:00
|
|
|
} as unknown as ApiTokenService;
|
2021-03-29 19:58:11 +02:00
|
|
|
|
2021-04-22 15:04:08 +02:00
|
|
|
const disabledConfig = createTestConfig({
|
2021-03-29 19:58:11 +02:00
|
|
|
getLogger,
|
|
|
|
authentication: {
|
|
|
|
enableApiToken: false,
|
2021-04-09 13:46:53 +02:00
|
|
|
createAdminUser: false,
|
2021-03-29 19:58:11 +02:00
|
|
|
},
|
2021-04-22 10:07:10 +02:00
|
|
|
});
|
2021-03-29 19:58:11 +02:00
|
|
|
|
|
|
|
const func = apiTokenMiddleware(disabledConfig, { apiTokenService });
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
const cb = jest.fn();
|
2021-03-29 19:58:11 +02:00
|
|
|
|
|
|
|
const req = {
|
2021-05-28 11:10:24 +02:00
|
|
|
header: jest.fn().mockReturnValue('some-known-token'),
|
2021-03-29 19:58:11 +02:00
|
|
|
user: undefined,
|
|
|
|
};
|
|
|
|
|
2022-09-28 15:53:56 +02:00
|
|
|
const send = jest.fn();
|
|
|
|
const res = {
|
|
|
|
status: () => {
|
|
|
|
return {
|
|
|
|
send: send,
|
|
|
|
};
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
await func(req, res, cb);
|
2021-03-29 19:58:11 +02:00
|
|
|
|
2022-09-28 15:53:56 +02:00
|
|
|
expect(send).not.toHaveBeenCalled();
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(cb).toHaveBeenCalled();
|
|
|
|
expect(req.user).toBeFalsy();
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should call next if apiTokenService throws', async () => {
|
2021-03-29 19:58:11 +02:00
|
|
|
getLogger.setMuteError(true);
|
|
|
|
const apiTokenService = {
|
|
|
|
getUserForToken: () => {
|
|
|
|
throw new Error('hi there, i am stupid');
|
|
|
|
},
|
2023-11-03 12:00:24 +01:00
|
|
|
} as unknown as ApiTokenService;
|
2021-03-29 19:58:11 +02:00
|
|
|
|
|
|
|
const func = apiTokenMiddleware(config, { apiTokenService });
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
const cb = jest.fn();
|
2021-03-29 19:58:11 +02:00
|
|
|
|
|
|
|
const req = {
|
2021-05-28 11:10:24 +02:00
|
|
|
header: jest.fn().mockReturnValue('some-token'),
|
2021-03-29 19:58:11 +02:00
|
|
|
user: undefined,
|
|
|
|
};
|
|
|
|
|
|
|
|
await func(req, undefined, cb);
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(cb).toHaveBeenCalled();
|
2021-03-29 19:58:11 +02:00
|
|
|
getLogger.setMuteError(false);
|
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should call next if apiTokenService throws x2', async () => {
|
2021-09-15 20:28:10 +02:00
|
|
|
jest.spyOn(global.console, 'error').mockImplementation(() => jest.fn());
|
2021-03-29 19:58:11 +02:00
|
|
|
const apiTokenService = {
|
|
|
|
getUserForToken: () => {
|
|
|
|
throw new Error('hi there, i am stupid');
|
|
|
|
},
|
2023-11-03 12:00:24 +01:00
|
|
|
} as unknown as ApiTokenService;
|
2021-03-29 19:58:11 +02:00
|
|
|
|
|
|
|
const func = apiTokenMiddleware(config, { apiTokenService });
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
const cb = jest.fn();
|
2021-03-29 19:58:11 +02:00
|
|
|
|
|
|
|
const req = {
|
2021-05-28 11:10:24 +02:00
|
|
|
header: jest.fn().mockReturnValue('some-token'),
|
2021-03-29 19:58:11 +02:00
|
|
|
user: undefined,
|
|
|
|
};
|
|
|
|
|
|
|
|
await func(req, undefined, cb);
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(cb).toHaveBeenCalled();
|
2021-03-29 19:58:11 +02:00
|
|
|
});
|
2024-01-02 09:51:01 +01:00
|
|
|
|
|
|
|
test('should add user if client token and /edge/metrics', async () => {
|
|
|
|
const apiUser = new ApiUser({
|
|
|
|
tokenName: 'default',
|
|
|
|
permissions: [CLIENT],
|
|
|
|
project: ALL,
|
|
|
|
environment: ALL,
|
|
|
|
type: ApiTokenType.CLIENT,
|
|
|
|
secret: 'a',
|
|
|
|
});
|
|
|
|
const apiTokenService = {
|
|
|
|
getUserForToken: jest.fn().mockReturnValue(apiUser),
|
|
|
|
} as unknown as ApiTokenService;
|
|
|
|
|
|
|
|
const func = apiTokenMiddleware(config, { apiTokenService });
|
|
|
|
|
|
|
|
const cb = jest.fn();
|
|
|
|
|
|
|
|
const req = {
|
|
|
|
header: jest.fn().mockReturnValue('some-known-token'),
|
|
|
|
user: undefined,
|
|
|
|
path: '/edge/metrics',
|
|
|
|
method: 'POST',
|
|
|
|
};
|
|
|
|
|
|
|
|
await func(req, undefined, cb);
|
|
|
|
|
|
|
|
expect(cb).toHaveBeenCalled();
|
|
|
|
expect(req.header).toHaveBeenCalled();
|
|
|
|
expect(req.user).toBe(apiUser);
|
|
|
|
});
|