@6thbridge/utils 1.9.1 → 1.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/logger/logger.js +2 -1
- package/lib/logger/logger.js.map +1 -1
- package/lib/middlewares/common.d.ts +2 -1
- package/lib/middlewares/common.js +8 -1
- package/lib/middlewares/common.js.map +1 -1
- package/lib/middlewares/common.test.d.ts +1 -0
- package/lib/middlewares/common.test.js +500 -0
- package/lib/middlewares/common.test.js.map +1 -0
- package/lib/middlewares/express.d.ts +0 -1
- package/lib/middlewares/express.js +1 -15
- package/lib/middlewares/express.js.map +1 -1
- package/lib/middlewares/index.d.ts +1 -2
- package/lib/middlewares/index.js +1 -3
- package/lib/middlewares/index.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types/context.entity.js +1 -0
- package/lib/types/context.entity.js.map +1 -1
- package/lib/types/permission.d.ts +1 -1
- package/lib/utils/amount.js +6 -1
- package/lib/utils/amount.js.map +1 -1
- package/lib/utils/amount.test.js +25 -0
- package/lib/utils/amount.test.js.map +1 -1
- package/package.json +1 -1
- package/readme.md +7 -0
package/lib/logger/logger.js
CHANGED
package/lib/logger/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/logger/logger.ts"],"names":[],"mappings":";;;;;;AAAA,mCAAqD;AACrD,8CAAwC;AAGxC,sDAA8B;AAC9B,yCAAwC;AAExC,MAAa,WAAW;IAAxB;QACE,YAAO,GAAY,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,KAAK,CAAC;QAMjD,cAAS,GAAY,eAAe,CAAC;IAGvC,CAAC;CAAA;AAVD,kCAUC;AAED,MAAM,YAAY,GAAa;
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/logger/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,13 +6,14 @@ export declare const AUTHENTICATION_TYPES: {
|
|
|
6
6
|
CLIENT_ID: string;
|
|
7
7
|
CLIENT_SECRET: string;
|
|
8
8
|
JWT: string;
|
|
9
|
+
PARTNER: string;
|
|
9
10
|
};
|
|
10
11
|
export declare function emptyMiddleware(req: any, res: any, next: any): any;
|
|
11
12
|
export declare function unless(middlewareName: string, paths: string[], middleware: any): typeof emptyMiddleware;
|
|
12
13
|
export declare class CommonMiddleware {
|
|
13
14
|
static getPartnerRequestContext(req: express.Request): PFunctionResult<PartnerContextEntity>;
|
|
14
15
|
static processAuthorizationCheck(req: express.Request): PFunctionResult<ValidateUserAccessResponseDTO>;
|
|
15
|
-
static getRequestContext(req: express.Request, supportedAuthenticationType?: string[], permissions?: ResourcePermission[]): Promise<{
|
|
16
|
+
static getRequestContext(req: express.Request, supportedAuthenticationType?: string[], permissions?: ResourcePermission[]): Promise<import("../types").FunctionResult<PartnerContextEntity> | {
|
|
16
17
|
data: ContextEntity;
|
|
17
18
|
error?: undefined;
|
|
18
19
|
statusCode?: undefined;
|
|
@@ -27,6 +27,7 @@ exports.AUTHENTICATION_TYPES = {
|
|
|
27
27
|
CLIENT_ID: 'client-id',
|
|
28
28
|
CLIENT_SECRET: 'client-secret',
|
|
29
29
|
JWT: 'jwt',
|
|
30
|
+
PARTNER: 'partner',
|
|
30
31
|
};
|
|
31
32
|
function emptyMiddleware(req, res, next) {
|
|
32
33
|
logger_1.logger.out("Passing through an empty Middleware");
|
|
@@ -66,7 +67,10 @@ class CommonMiddleware {
|
|
|
66
67
|
const response = yield _axios.post('/internal/v1/partners/validate-api-key', { apiKey });
|
|
67
68
|
return { data: types_1.PartnerContextEntity.fromRequest(req, response.data.data) };
|
|
68
69
|
}
|
|
69
|
-
catch (
|
|
70
|
+
catch (ex) {
|
|
71
|
+
logger_1.logger.exception(ex, {
|
|
72
|
+
error: 'Failed to validate API key'
|
|
73
|
+
});
|
|
70
74
|
// Axios errors can contain the API key in their request configuration.
|
|
71
75
|
return failure;
|
|
72
76
|
}
|
|
@@ -130,6 +134,9 @@ class CommonMiddleware {
|
|
|
130
134
|
static getRequestContext(req, supportedAuthenticationType, permissions) {
|
|
131
135
|
return __awaiter(this, void 0, void 0, function* () {
|
|
132
136
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
137
|
+
if (supportedAuthenticationType === null || supportedAuthenticationType === void 0 ? void 0 : supportedAuthenticationType.includes(exports.AUTHENTICATION_TYPES.PARTNER)) {
|
|
138
|
+
return CommonMiddleware.getPartnerRequestContext(req);
|
|
139
|
+
}
|
|
133
140
|
try {
|
|
134
141
|
const requestSource = (req.headers["x-request-source"] || req.headers["source"]);
|
|
135
142
|
if (requestSource === types_1.INTERNAL_REQUEST_SOURCE) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/middlewares/common.ts"],"names":[],"mappings":";;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/middlewares/common.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const common_1 = require("./common");
|
|
13
|
+
const context_entity_1 = require("../types/context.entity");
|
|
14
|
+
const custom_exception_1 = require("../types/custom.exception");
|
|
15
|
+
const client_entity_1 = require("../types/client.entity");
|
|
16
|
+
const logger_1 = require("../logger");
|
|
17
|
+
const mockPost = jest.fn();
|
|
18
|
+
const mockResolveAxiosError = jest.fn();
|
|
19
|
+
jest.mock('../utils', () => ({
|
|
20
|
+
HttpUtil: {
|
|
21
|
+
getAxiosInstance: () => ({ post: (...args) => mockPost(...args) }),
|
|
22
|
+
resolveAxiosError: (...args) => mockResolveAxiosError(...args),
|
|
23
|
+
},
|
|
24
|
+
}));
|
|
25
|
+
jest.mock('../types', () => (Object.assign(Object.assign({}, jest.requireActual('../types/context.entity')), jest.requireActual('../types/custom.exception'))));
|
|
26
|
+
jest.mock('../logger', () => ({
|
|
27
|
+
logger: { out: jest.fn(), debug: jest.fn(), exception: jest.fn() },
|
|
28
|
+
}));
|
|
29
|
+
jest.mock('../logger/logger', () => ({
|
|
30
|
+
Logger: class {
|
|
31
|
+
constructor() {
|
|
32
|
+
this.setProps = jest.fn();
|
|
33
|
+
this.out = jest.fn();
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
}));
|
|
37
|
+
const partner = {
|
|
38
|
+
partnerId: 'partner-1',
|
|
39
|
+
name: 'Example Partner',
|
|
40
|
+
provider: 'example',
|
|
41
|
+
status: 'active',
|
|
42
|
+
};
|
|
43
|
+
const clientAuth = {
|
|
44
|
+
domain: 'example.com',
|
|
45
|
+
country: 'NG',
|
|
46
|
+
currency: 'NGN',
|
|
47
|
+
locale: 'en',
|
|
48
|
+
authenticationType: 'jwt',
|
|
49
|
+
requestClientId: 'request-client',
|
|
50
|
+
contextClientId: 'context-client',
|
|
51
|
+
requestClient: {
|
|
52
|
+
clientId: 'request-client',
|
|
53
|
+
name: 'Requester',
|
|
54
|
+
email: 'requester@example.com',
|
|
55
|
+
logo: '',
|
|
56
|
+
status: client_entity_1.ClientStatusOption.active,
|
|
57
|
+
parentClientId: '',
|
|
58
|
+
},
|
|
59
|
+
contextClient: {
|
|
60
|
+
clientId: 'context-client',
|
|
61
|
+
name: 'Context client',
|
|
62
|
+
email: 'client@example.com',
|
|
63
|
+
logo: '',
|
|
64
|
+
status: client_entity_1.ClientStatusOption.active,
|
|
65
|
+
parentClientId: 'request-client',
|
|
66
|
+
},
|
|
67
|
+
requestUserId: 'request-user',
|
|
68
|
+
contextUserId: 'context-user',
|
|
69
|
+
requestUser: {
|
|
70
|
+
userId: 'request-user',
|
|
71
|
+
clientId: 'request-client',
|
|
72
|
+
name: 'Requester',
|
|
73
|
+
email: 'requester@example.com',
|
|
74
|
+
firstName: 'Request',
|
|
75
|
+
lastName: 'User',
|
|
76
|
+
roleId: 'main',
|
|
77
|
+
},
|
|
78
|
+
contextUser: {
|
|
79
|
+
userId: 'context-user',
|
|
80
|
+
clientId: 'context-client',
|
|
81
|
+
name: 'Context user',
|
|
82
|
+
email: 'user@example.com',
|
|
83
|
+
firstName: 'Context',
|
|
84
|
+
lastName: 'User',
|
|
85
|
+
roleId: 'staff',
|
|
86
|
+
},
|
|
87
|
+
permissions: 'payments.read,payments.write',
|
|
88
|
+
};
|
|
89
|
+
const permissions = [
|
|
90
|
+
{ resource: 'payments', action: 'read' },
|
|
91
|
+
{ resource: 'payments', action: 'write' },
|
|
92
|
+
];
|
|
93
|
+
const forbidden = { statusCode: 403, errorCode: 'Forbidden', error: expect.any(String) };
|
|
94
|
+
const request = (overrides = {}) => (Object.assign({ headers: {}, body: {}, query: {}, params: {}, cookies: {}, path: '/v1/payments', originalUrl: '/v1/payments', method: 'GET', ip: '127.0.0.1' }, overrides));
|
|
95
|
+
function gatewayRequest(auth = {}, overrides = {}) {
|
|
96
|
+
return request(Object.assign(Object.assign({}, overrides), { headers: Object.assign({ 'x-request-source': 'api-gateway', 'x-authentication-data': JSON.stringify(Object.assign(Object.assign({}, clientAuth), auth)) }, overrides.headers) }));
|
|
97
|
+
}
|
|
98
|
+
beforeEach(() => {
|
|
99
|
+
jest.resetAllMocks();
|
|
100
|
+
mockResolveAxiosError.mockReturnValue({ message: 'HTTP request failed' });
|
|
101
|
+
});
|
|
102
|
+
afterEach(() => jest.restoreAllMocks());
|
|
103
|
+
describe('emptyMiddleware', () => {
|
|
104
|
+
it('passes control to next and returns its result', () => {
|
|
105
|
+
const next = jest.fn().mockReturnValue('next-result');
|
|
106
|
+
expect((0, common_1.emptyMiddleware)(request(), {}, next)).toBe('next-result');
|
|
107
|
+
expect(next).toHaveBeenCalledTimes(1);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
describe('unless', () => {
|
|
111
|
+
it('returns the empty middleware when no middleware is supplied', () => {
|
|
112
|
+
expect((0, common_1.unless)('auth', ['/public'], undefined)).toBe(common_1.emptyMiddleware);
|
|
113
|
+
});
|
|
114
|
+
it('returns the empty middleware when no exclusion paths are supplied', () => {
|
|
115
|
+
const middleware = jest.fn();
|
|
116
|
+
const next = jest.fn();
|
|
117
|
+
(0, common_1.unless)('auth', [], middleware)(request(), {}, next);
|
|
118
|
+
expect(middleware).not.toHaveBeenCalled();
|
|
119
|
+
expect(next).toHaveBeenCalledTimes(1);
|
|
120
|
+
});
|
|
121
|
+
it.each(['/public', '/public/', '/users/123', '/files/a/b'])('skips matching path %s', (path) => {
|
|
122
|
+
const middleware = jest.fn();
|
|
123
|
+
const next = jest.fn().mockReturnValue('skipped');
|
|
124
|
+
const wrapped = (0, common_1.unless)('auth', ['/public', '/users/:id', '/files/*segments'], middleware);
|
|
125
|
+
expect(wrapped(request({ path }), {}, next)).toBe('skipped');
|
|
126
|
+
expect(middleware).not.toHaveBeenCalled();
|
|
127
|
+
expect(next).toHaveBeenCalledTimes(1);
|
|
128
|
+
});
|
|
129
|
+
it.each(['/publication', '/users', '/users/123/orders'])('runs middleware on nonmatching path %s', (path) => {
|
|
130
|
+
const middleware = jest.fn().mockReturnValue('authenticated');
|
|
131
|
+
const req = request({ path });
|
|
132
|
+
const res = {};
|
|
133
|
+
const next = jest.fn();
|
|
134
|
+
expect((0, common_1.unless)('auth', ['/public', '/users/:id'], middleware)(req, res, next)).toBe('authenticated');
|
|
135
|
+
expect(middleware).toHaveBeenCalledWith(req, res, next);
|
|
136
|
+
expect(next).not.toHaveBeenCalled();
|
|
137
|
+
});
|
|
138
|
+
it('rejects invalid exclusion patterns when the wrapper is created', () => {
|
|
139
|
+
expect(() => (0, common_1.unless)('auth', ['/files/*'], jest.fn())).toThrow();
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
describe('CommonMiddleware.getPartnerRequestContext', () => {
|
|
143
|
+
it('uses validated partner data without another lookup, even when a key is present', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
144
|
+
const req = request({
|
|
145
|
+
headers: {
|
|
146
|
+
'x-partner-data': JSON.stringify(partner),
|
|
147
|
+
'x-partner-api-key': 'unused-key',
|
|
148
|
+
'x-request-source': 'api-gateway',
|
|
149
|
+
'x-request-id': 'request-1',
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
const result = yield common_1.CommonMiddleware.getPartnerRequestContext(req);
|
|
153
|
+
expect(result.error).toBeUndefined();
|
|
154
|
+
expect(result.data).toBeInstanceOf(context_entity_1.PartnerContextEntity);
|
|
155
|
+
expect(result.data).toMatchObject({
|
|
156
|
+
partner,
|
|
157
|
+
authenticationType: 'partner',
|
|
158
|
+
requestId: 'request-1',
|
|
159
|
+
request: req,
|
|
160
|
+
});
|
|
161
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
162
|
+
}));
|
|
163
|
+
it('validates a direct API key and builds the partner context', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
164
|
+
var _a;
|
|
165
|
+
mockPost.mockResolvedValue({ data: { data: partner } });
|
|
166
|
+
const result = yield common_1.CommonMiddleware.getPartnerRequestContext(request({
|
|
167
|
+
headers: { 'x-partner-api-key': 'partner-key' },
|
|
168
|
+
}));
|
|
169
|
+
expect(result.data).toBeInstanceOf(context_entity_1.PartnerContextEntity);
|
|
170
|
+
expect((_a = result.data) === null || _a === void 0 ? void 0 : _a.partner).toEqual(partner);
|
|
171
|
+
expect(mockPost).toHaveBeenCalledTimes(1);
|
|
172
|
+
expect(mockPost).toHaveBeenCalledWith('/internal/v1/partners/validate-api-key', {
|
|
173
|
+
apiKey: 'partner-key',
|
|
174
|
+
});
|
|
175
|
+
}));
|
|
176
|
+
it.each([undefined, '', ' ', ['one', 'two']])('rejects a missing or invalid API key: %j', (apiKey) => __awaiter(void 0, void 0, void 0, function* () {
|
|
177
|
+
const result = yield common_1.CommonMiddleware.getPartnerRequestContext(request({
|
|
178
|
+
headers: { 'x-partner-api-key': apiKey },
|
|
179
|
+
}));
|
|
180
|
+
expect(result).toEqual(forbidden);
|
|
181
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
182
|
+
}));
|
|
183
|
+
it.each([
|
|
184
|
+
'{invalid',
|
|
185
|
+
'',
|
|
186
|
+
'null',
|
|
187
|
+
'{}',
|
|
188
|
+
JSON.stringify(Object.assign(Object.assign({}, partner), { partnerId: ' ' })),
|
|
189
|
+
['one', 'two'],
|
|
190
|
+
])('rejects malformed partner data without falling back to a key: %j', (data) => __awaiter(void 0, void 0, void 0, function* () {
|
|
191
|
+
const result = yield common_1.CommonMiddleware.getPartnerRequestContext(request({
|
|
192
|
+
headers: { 'x-partner-data': data, 'x-partner-api-key': 'unused-key' },
|
|
193
|
+
}));
|
|
194
|
+
expect(result).toEqual(forbidden);
|
|
195
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
196
|
+
}));
|
|
197
|
+
it.each([undefined, {}, { data: {} }, { data: { data: Object.assign(Object.assign({}, partner), { provider: '' }) } }])('rejects malformed validation responses: %j', (response) => __awaiter(void 0, void 0, void 0, function* () {
|
|
198
|
+
mockPost.mockResolvedValue(response);
|
|
199
|
+
const result = yield common_1.CommonMiddleware.getPartnerRequestContext(request({
|
|
200
|
+
headers: { 'x-partner-api-key': 'partner-key' },
|
|
201
|
+
}));
|
|
202
|
+
expect(result).toEqual(forbidden);
|
|
203
|
+
}));
|
|
204
|
+
it('returns a generic forbidden response when validation fails', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
205
|
+
mockPost.mockRejectedValue(new Error('validation failed with partner-key'));
|
|
206
|
+
const result = yield common_1.CommonMiddleware.getPartnerRequestContext(request({
|
|
207
|
+
headers: { 'x-partner-api-key': 'partner-key' },
|
|
208
|
+
}));
|
|
209
|
+
expect(result).toEqual(forbidden);
|
|
210
|
+
expect(JSON.stringify(result)).not.toContain('partner-key');
|
|
211
|
+
}));
|
|
212
|
+
});
|
|
213
|
+
describe('CommonMiddleware.processAuthorizationCheck', () => {
|
|
214
|
+
beforeEach(() => mockPost.mockResolvedValue({ data: { data: clientAuth } }));
|
|
215
|
+
it('extracts the full authorization payload with header and body precedence', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
216
|
+
const result = yield common_1.CommonMiddleware.processAuthorizationCheck(request({
|
|
217
|
+
headers: {
|
|
218
|
+
origin: 'https://origin.example.com/path',
|
|
219
|
+
referer: 'https://referer.example.com/path',
|
|
220
|
+
'client-id': 'header-client',
|
|
221
|
+
'request-client-id': 'other-client',
|
|
222
|
+
secret: 'preferred-secret',
|
|
223
|
+
'client-secret': 'other-secret',
|
|
224
|
+
'context-client-id': 'header-context',
|
|
225
|
+
authorization: 'Bearer header-token',
|
|
226
|
+
'x-country-code': 'NG',
|
|
227
|
+
'x-currency-code': 'NGN',
|
|
228
|
+
},
|
|
229
|
+
cookies: { 'request-client-id': 'cookie-client', 'auth-token': 'cookie-token' },
|
|
230
|
+
body: { clientId: 'body-context', token: 'body-token' },
|
|
231
|
+
}));
|
|
232
|
+
expect(result).toEqual({ data: clientAuth });
|
|
233
|
+
expect(mockPost).toHaveBeenCalledWith('/v1/auths/validate-user-access', {
|
|
234
|
+
domain: 'origin.example.com',
|
|
235
|
+
secret: 'preferred-secret',
|
|
236
|
+
requestClientId: 'header-client',
|
|
237
|
+
contextClientId: 'body-context',
|
|
238
|
+
country: 'NG',
|
|
239
|
+
currency: 'NGN',
|
|
240
|
+
token: 'header-token',
|
|
241
|
+
});
|
|
242
|
+
}));
|
|
243
|
+
it('uses query.clientId ahead of body, context header, and request client', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
244
|
+
yield common_1.CommonMiddleware.processAuthorizationCheck(request({
|
|
245
|
+
headers: { 'client-id': 'request-client', 'context-client-id': 'header-context' },
|
|
246
|
+
body: { clientId: 'body-context' },
|
|
247
|
+
query: { clientId: 'query-context' },
|
|
248
|
+
}));
|
|
249
|
+
expect(mockPost).toHaveBeenCalledWith('/v1/auths/validate-user-access', expect.objectContaining({
|
|
250
|
+
requestClientId: 'request-client',
|
|
251
|
+
contextClientId: 'query-context',
|
|
252
|
+
}));
|
|
253
|
+
}));
|
|
254
|
+
it('uses referer, request-client-id, client-secret, context header, and body token fallbacks', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
255
|
+
yield common_1.CommonMiddleware.processAuthorizationCheck(request({
|
|
256
|
+
headers: {
|
|
257
|
+
referer: 'https://referer.example.com/path',
|
|
258
|
+
'request-client-id': 'request-client',
|
|
259
|
+
'client-secret': 'client-secret',
|
|
260
|
+
'context-client-id': 'header-context',
|
|
261
|
+
},
|
|
262
|
+
body: { token: 'Bearer body-token' },
|
|
263
|
+
}));
|
|
264
|
+
expect(mockPost).toHaveBeenCalledWith('/v1/auths/validate-user-access', expect.objectContaining({
|
|
265
|
+
domain: 'referer.example.com',
|
|
266
|
+
requestClientId: 'request-client',
|
|
267
|
+
contextClientId: 'header-context',
|
|
268
|
+
secret: 'client-secret',
|
|
269
|
+
token: 'body-token',
|
|
270
|
+
}));
|
|
271
|
+
}));
|
|
272
|
+
it('uses cookie client and token values when corresponding headers and body values are absent', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
273
|
+
yield common_1.CommonMiddleware.processAuthorizationCheck(request({
|
|
274
|
+
cookies: { 'request-client-id': 'cookie-client', 'auth-token': 'cookie-token' },
|
|
275
|
+
}));
|
|
276
|
+
expect(mockPost).toHaveBeenCalledWith('/v1/auths/validate-user-access', expect.objectContaining({
|
|
277
|
+
requestClientId: 'cookie-client',
|
|
278
|
+
contextClientId: 'cookie-client',
|
|
279
|
+
token: 'cookie-token',
|
|
280
|
+
}));
|
|
281
|
+
}));
|
|
282
|
+
it('allows domain-based validation without a client ID or cookies', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
283
|
+
yield common_1.CommonMiddleware.processAuthorizationCheck(request({
|
|
284
|
+
headers: { origin: 'https://origin.example.com' },
|
|
285
|
+
cookies: undefined,
|
|
286
|
+
}));
|
|
287
|
+
expect(mockPost).toHaveBeenCalledWith('/v1/auths/validate-user-access', expect.objectContaining({
|
|
288
|
+
domain: 'origin.example.com',
|
|
289
|
+
requestClientId: undefined,
|
|
290
|
+
token: '',
|
|
291
|
+
}));
|
|
292
|
+
}));
|
|
293
|
+
it.each([undefined, 'undefined'])('keeps the empty token when the supplied token is %j', (token) => __awaiter(void 0, void 0, void 0, function* () {
|
|
294
|
+
yield common_1.CommonMiddleware.processAuthorizationCheck(request({
|
|
295
|
+
headers: { 'client-id': 'request-client', authorization: token },
|
|
296
|
+
}));
|
|
297
|
+
expect(mockPost).toHaveBeenCalledWith('/v1/auths/validate-user-access', expect.objectContaining({ token: '' }));
|
|
298
|
+
}));
|
|
299
|
+
it('rejects missing domain and client identity before calling user-service', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
300
|
+
yield expect(common_1.CommonMiddleware.processAuthorizationCheck(request())).rejects.toMatchObject({
|
|
301
|
+
statusCode: 403,
|
|
302
|
+
errorCode: 'Forbidden',
|
|
303
|
+
message: expect.any(String),
|
|
304
|
+
});
|
|
305
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
306
|
+
}));
|
|
307
|
+
it('translates user-service errors to a forbidden CustomException', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
308
|
+
const error = new Error('connection failed');
|
|
309
|
+
mockPost.mockRejectedValue(error);
|
|
310
|
+
const result = common_1.CommonMiddleware.processAuthorizationCheck(request({ headers: { 'client-id': 'client-1' } }));
|
|
311
|
+
yield expect(result).rejects.toBeInstanceOf(custom_exception_1.CustomException);
|
|
312
|
+
yield expect(result).rejects.toMatchObject({
|
|
313
|
+
statusCode: 403,
|
|
314
|
+
errorCode: 'Forbidden',
|
|
315
|
+
message: expect.any(String),
|
|
316
|
+
});
|
|
317
|
+
expect(mockResolveAxiosError).toHaveBeenCalledWith(error);
|
|
318
|
+
expect(logger_1.logger.exception).toHaveBeenCalledWith(error, expect.objectContaining({
|
|
319
|
+
axiosError: { message: 'HTTP request failed' },
|
|
320
|
+
}));
|
|
321
|
+
}));
|
|
322
|
+
});
|
|
323
|
+
describe('CommonMiddleware.getRequestContext', () => {
|
|
324
|
+
it('selects partner authentication from route configuration and skips client permissions', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
325
|
+
const result = yield common_1.CommonMiddleware.getRequestContext(request({
|
|
326
|
+
headers: { 'x-partner-data': JSON.stringify(partner) },
|
|
327
|
+
}), ['partner'], permissions);
|
|
328
|
+
expect(result.data).toBeInstanceOf(context_entity_1.PartnerContextEntity);
|
|
329
|
+
expect(result.data).toMatchObject({ authenticationType: 'partner', partner });
|
|
330
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
331
|
+
}));
|
|
332
|
+
it('requires partner identity even when the request claims an internal source', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
333
|
+
const result = yield common_1.CommonMiddleware.getRequestContext(request({ headers: { source: 'internal' } }), ['partner']);
|
|
334
|
+
expect(result).toEqual(forbidden);
|
|
335
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
336
|
+
}));
|
|
337
|
+
it.each(['source', 'x-request-source'])('builds an internal context from %s without external validation', (sourceHeader) => __awaiter(void 0, void 0, void 0, function* () {
|
|
338
|
+
const result = yield common_1.CommonMiddleware.getRequestContext(request({
|
|
339
|
+
headers: {
|
|
340
|
+
[sourceHeader]: 'internal',
|
|
341
|
+
'request-client-id': 'internal-client',
|
|
342
|
+
'authentication-type': 'internal',
|
|
343
|
+
'x-request-id': 'internal-request',
|
|
344
|
+
},
|
|
345
|
+
}), ['jwt'], permissions);
|
|
346
|
+
expect(result.data).toBeInstanceOf(context_entity_1.ContextEntity);
|
|
347
|
+
expect(result.data).toMatchObject({
|
|
348
|
+
requestId: 'internal-request',
|
|
349
|
+
requestClientId: 'internal-client',
|
|
350
|
+
});
|
|
351
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
352
|
+
}));
|
|
353
|
+
it('gives x-request-source precedence over source', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
354
|
+
var _a, _b;
|
|
355
|
+
const result = yield common_1.CommonMiddleware.getRequestContext(gatewayRequest({}, { headers: { source: 'internal' } }), ['jwt']);
|
|
356
|
+
expect((_a = result.data) === null || _a === void 0 ? void 0 : _a.authenticationType).toBe('jwt');
|
|
357
|
+
expect((_b = result.data) === null || _b === void 0 ? void 0 : _b.requestClientId).toBe('request-client');
|
|
358
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
359
|
+
}));
|
|
360
|
+
it('builds a gateway context from authentication data, retaining header overrides', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
361
|
+
const req = gatewayRequest({}, {
|
|
362
|
+
headers: {
|
|
363
|
+
'x-request-id': 'request-1',
|
|
364
|
+
'x-country-code': 'CM',
|
|
365
|
+
'x-currency-code': 'XAF',
|
|
366
|
+
'x-locale-id': 'fr',
|
|
367
|
+
},
|
|
368
|
+
});
|
|
369
|
+
const result = yield common_1.CommonMiddleware.getRequestContext(req, ['jwt']);
|
|
370
|
+
expect(result.data).toMatchObject({
|
|
371
|
+
authenticationType: 'jwt',
|
|
372
|
+
requestClientId: 'request-client',
|
|
373
|
+
contextClientId: 'context-client',
|
|
374
|
+
requestUserId: 'request-user',
|
|
375
|
+
contextUserId: 'context-user',
|
|
376
|
+
requestClient: clientAuth.requestClient,
|
|
377
|
+
contextClient: clientAuth.contextClient,
|
|
378
|
+
requestUser: clientAuth.requestUser,
|
|
379
|
+
contextUser: clientAuth.contextUser,
|
|
380
|
+
permissions: ['payments.read', 'payments.write'],
|
|
381
|
+
requestId: 'request-1',
|
|
382
|
+
countryCode: 'CM',
|
|
383
|
+
currencyCode: 'XAF',
|
|
384
|
+
locale: 'fr',
|
|
385
|
+
request: req,
|
|
386
|
+
});
|
|
387
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
388
|
+
}));
|
|
389
|
+
it('validates direct requests and builds their context from the response', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
390
|
+
mockPost.mockResolvedValue({ data: { data: clientAuth } });
|
|
391
|
+
const result = yield common_1.CommonMiddleware.getRequestContext(request({
|
|
392
|
+
headers: { 'client-id': 'request-client', authorization: 'Bearer token' },
|
|
393
|
+
}), ['jwt']);
|
|
394
|
+
expect(result.data).toMatchObject({
|
|
395
|
+
authenticationType: 'jwt',
|
|
396
|
+
requestClientId: 'request-client',
|
|
397
|
+
});
|
|
398
|
+
expect(mockPost).toHaveBeenCalledTimes(1);
|
|
399
|
+
expect(mockPost).toHaveBeenCalledWith('/v1/auths/validate-user-access', expect.objectContaining({ token: 'token' }));
|
|
400
|
+
}));
|
|
401
|
+
it('uses the client flow when partner headers appear on a JWT route', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
402
|
+
var _a;
|
|
403
|
+
const result = yield common_1.CommonMiddleware.getRequestContext(gatewayRequest({}, {
|
|
404
|
+
headers: { 'x-partner-data': JSON.stringify(partner) },
|
|
405
|
+
}), ['jwt']);
|
|
406
|
+
expect((_a = result.data) === null || _a === void 0 ? void 0 : _a.authenticationType).toBe('jwt');
|
|
407
|
+
expect(result.data).not.toBeInstanceOf(context_entity_1.PartnerContextEntity);
|
|
408
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
409
|
+
}));
|
|
410
|
+
it.each([undefined, []])('does not restrict authentication types when configured with %j', (types) => __awaiter(void 0, void 0, void 0, function* () {
|
|
411
|
+
var _a;
|
|
412
|
+
const result = yield common_1.CommonMiddleware.getRequestContext(gatewayRequest(), types, permissions);
|
|
413
|
+
expect((_a = result.data) === null || _a === void 0 ? void 0 : _a.authenticationType).toBe('jwt');
|
|
414
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
415
|
+
}));
|
|
416
|
+
it.each(['client-id', 'client-secret'])('skips JWT permission validation for %s', (authenticationType) => __awaiter(void 0, void 0, void 0, function* () {
|
|
417
|
+
var _a;
|
|
418
|
+
const result = yield common_1.CommonMiddleware.getRequestContext(gatewayRequest({
|
|
419
|
+
authenticationType,
|
|
420
|
+
}), [authenticationType], permissions);
|
|
421
|
+
expect((_a = result.data) === null || _a === void 0 ? void 0 : _a.authenticationType).toBe(authenticationType);
|
|
422
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
423
|
+
}));
|
|
424
|
+
it.each([undefined, 'client-id'])('rejects missing or unsupported authentication type: %j', (authenticationType) => __awaiter(void 0, void 0, void 0, function* () {
|
|
425
|
+
const result = yield common_1.CommonMiddleware.getRequestContext(gatewayRequest({ authenticationType }), ['jwt']);
|
|
426
|
+
expect(result).toEqual(forbidden);
|
|
427
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
428
|
+
}));
|
|
429
|
+
it.each([undefined, []])('skips the permission lookup when JWT permissions are %j', (resourcePermissions) => __awaiter(void 0, void 0, void 0, function* () {
|
|
430
|
+
var _a;
|
|
431
|
+
const result = yield common_1.CommonMiddleware.getRequestContext(gatewayRequest(), ['jwt'], resourcePermissions);
|
|
432
|
+
expect((_a = result.data) === null || _a === void 0 ? void 0 : _a.authenticationType).toBe('jwt');
|
|
433
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
434
|
+
}));
|
|
435
|
+
it.each([false, true])('checks JWT resource permissions with enforceOwn=%s', (enforceOwn) => __awaiter(void 0, void 0, void 0, function* () {
|
|
436
|
+
var _a, _b, _c;
|
|
437
|
+
mockPost.mockResolvedValue({ data: { data: { enforceOwn } } });
|
|
438
|
+
const result = yield common_1.CommonMiddleware.getRequestContext(gatewayRequest({}, {
|
|
439
|
+
body: { userId: 'body-user' },
|
|
440
|
+
}), ['jwt'], permissions);
|
|
441
|
+
expect((_a = result.data) === null || _a === void 0 ? void 0 : _a.authenticationType).toBe('jwt');
|
|
442
|
+
expect(mockPost).toHaveBeenCalledWith('/v1/auths/validate-user-permission', {
|
|
443
|
+
ip: '127.0.0.1',
|
|
444
|
+
requestClientId: 'request-client',
|
|
445
|
+
contextClientId: 'request-client',
|
|
446
|
+
authenticationType: 'jwt',
|
|
447
|
+
supportedAuthenticationType: ['jwt'],
|
|
448
|
+
permission: permissions[0],
|
|
449
|
+
resourcePermissions: permissions,
|
|
450
|
+
requestUser: clientAuth.requestUser,
|
|
451
|
+
contextUser: clientAuth.contextUser,
|
|
452
|
+
permissions: clientAuth.permissions,
|
|
453
|
+
contextUserId: 'context-user',
|
|
454
|
+
requestUserId: 'request-user',
|
|
455
|
+
});
|
|
456
|
+
if (enforceOwn) {
|
|
457
|
+
expect((_b = result.data) === null || _b === void 0 ? void 0 : _b.logger.setProps).toHaveBeenCalledWith({ userId: 'body-user' });
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
expect((_c = result.data) === null || _c === void 0 ? void 0 : _c.logger.setProps).not.toHaveBeenCalled();
|
|
461
|
+
}
|
|
462
|
+
}));
|
|
463
|
+
it.each([undefined, '{invalid', 'null', '{}'])('rejects malformed gateway authentication data: %j', (data) => __awaiter(void 0, void 0, void 0, function* () {
|
|
464
|
+
const result = yield common_1.CommonMiddleware.getRequestContext(request({
|
|
465
|
+
headers: {
|
|
466
|
+
'x-request-source': 'api-gateway',
|
|
467
|
+
'x-authentication-data': data,
|
|
468
|
+
},
|
|
469
|
+
}), ['jwt']);
|
|
470
|
+
expect(result).toEqual(forbidden);
|
|
471
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
472
|
+
expect(logger_1.logger.exception).toHaveBeenCalled();
|
|
473
|
+
}));
|
|
474
|
+
it('rejects empty validation responses from direct authentication', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
475
|
+
mockPost.mockResolvedValue({ data: { data: undefined } });
|
|
476
|
+
const result = yield common_1.CommonMiddleware.getRequestContext(request({ headers: { 'client-id': 'client-1' } }), ['jwt']);
|
|
477
|
+
expect(result).toEqual(forbidden);
|
|
478
|
+
}));
|
|
479
|
+
it('propagates an authorization failure returned by the validation helper', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
480
|
+
jest.spyOn(common_1.CommonMiddleware, 'processAuthorizationCheck').mockResolvedValue({
|
|
481
|
+
error: 'Access denied',
|
|
482
|
+
statusCode: 403,
|
|
483
|
+
errorCode: 'Forbidden',
|
|
484
|
+
});
|
|
485
|
+
expect(yield common_1.CommonMiddleware.getRequestContext(request(), ['jwt'])).toEqual(forbidden);
|
|
486
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
487
|
+
}));
|
|
488
|
+
it('returns a forbidden result when direct authentication throws', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
489
|
+
mockPost.mockRejectedValue(new Error('connection failed'));
|
|
490
|
+
const result = yield common_1.CommonMiddleware.getRequestContext(request({ headers: { 'client-id': 'client-1' } }), ['jwt']);
|
|
491
|
+
expect(result).toEqual(forbidden);
|
|
492
|
+
}));
|
|
493
|
+
it('preserves the error message returned by permission validation', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
494
|
+
mockPost.mockRejectedValue({ response: { data: { error: 'Permission denied' } } });
|
|
495
|
+
const result = yield common_1.CommonMiddleware.getRequestContext(gatewayRequest(), ['jwt'], permissions);
|
|
496
|
+
expect(result).toEqual({ error: 'Permission denied', statusCode: 403, errorCode: 'Forbidden' });
|
|
497
|
+
expect(logger_1.logger.exception).toHaveBeenCalled();
|
|
498
|
+
}));
|
|
499
|
+
});
|
|
500
|
+
//# sourceMappingURL=common.test.js.map
|