@seidor-cloud-produtos/orbit-backend-lib 2.0.110 → 2.0.111
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/dist/clean-arch/application/cache/cache.spec.d.ts +1 -0
- package/dist/clean-arch/application/cache/cache.spec.js +178 -0
- package/dist/clean-arch/application/consistency-event-dispatcher/consistency-event-dispatcher.d.ts +1 -1
- package/dist/clean-arch/application/logger/logger.spec.d.ts +1 -0
- package/dist/clean-arch/application/logger/logger.spec.js +204 -0
- package/dist/clean-arch/domain/entities/entity.spec.d.ts +1 -0
- package/dist/clean-arch/domain/entities/entity.spec.js +130 -0
- package/dist/clean-arch/domain/events/consistency-event/consistency-event.spec.d.ts +1 -0
- package/dist/clean-arch/domain/events/consistency-event/consistency-event.spec.js +91 -0
- package/dist/clean-arch/domain/value-objects/password.spec.d.ts +1 -0
- package/dist/clean-arch/domain/value-objects/password.spec.js +90 -0
- package/dist/clean-arch/infra/adapters/http-adapters.spec.d.ts +1 -0
- package/dist/clean-arch/infra/adapters/http-adapters.spec.js +318 -0
- package/dist/clean-arch/infra/authorizations/authorizer.spec.js +43 -0
- package/dist/clean-arch/infra/cache/cache-clients.spec.d.ts +1 -0
- package/dist/clean-arch/infra/cache/cache-clients.spec.js +161 -0
- package/dist/clean-arch/infra/cache/clients/node-cache.js +3 -2
- package/dist/clean-arch/infra/http/controller.spec.js +170 -51
- package/dist/clean-arch/infra/http/helpers.spec.d.ts +1 -0
- package/dist/clean-arch/infra/http/helpers.spec.js +136 -0
- package/dist/clean-arch/infra/http/net.spec.d.ts +1 -0
- package/dist/clean-arch/infra/http/net.spec.js +46 -0
- package/dist/clean-arch/infra/logger/logger-orbit.d.ts +2 -0
- package/dist/clean-arch/infra/logger/logger-orbit.spec.d.ts +1 -0
- package/dist/clean-arch/infra/logger/logger-orbit.spec.js +122 -0
- package/dist/clean-arch/infra/orbit-http-client/orbit-axios-client/orbit-axios-client.spec.d.ts +1 -0
- package/dist/clean-arch/infra/orbit-http-client/orbit-axios-client/orbit-axios-client.spec.js +143 -0
- package/dist/clean-arch/infra/orbit-notification-client/discord-client.spec.d.ts +1 -0
- package/dist/clean-arch/infra/orbit-notification-client/discord-client.spec.js +58 -0
- package/dist/clean-arch/infra/queue/queue-utils.spec.d.ts +1 -0
- package/dist/clean-arch/infra/queue/queue-utils.spec.js +170 -0
- package/dist/clean-arch/infra/queue/rabbitmq/amqp-lib.js +4 -4
- package/dist/clean-arch/infra/queue/rabbitmq/amqp-lib.spec.js +466 -89
- package/dist/clean-arch/infra/queue/rabbitmq/types.d.ts +1 -1
- package/dist/clean-arch/infra/scaledjob/amqp/runner.d.ts +0 -3
- package/dist/clean-arch/infra/scaledjob/amqp/runner.js +5 -6
- package/dist/clean-arch/infra/scaledjob/amqp/runner.spec.js +74 -84
- package/dist/clean-arch/infra/scaledjob/sqs/runner.spec.d.ts +1 -0
- package/dist/clean-arch/infra/scaledjob/sqs/runner.spec.js +150 -0
- package/dist/clean-arch/infra/tracing/start-tracing.d.ts +10 -0
- package/dist/clean-arch/infra/tracing/start-tracing.js +78 -0
- package/dist/clean-arch/infra/validations/zod/validation-zod.spec.js +23 -0
- package/dist/clean-arch/shared/pagination/get-take-and-skip.spec.d.ts +1 -0
- package/dist/clean-arch/shared/pagination/get-take-and-skip.spec.js +16 -0
- package/dist/coverage/block-navigation.d.ts +1 -0
- package/dist/coverage/block-navigation.js +72 -0
- package/dist/coverage/prettify.d.ts +0 -0
- package/dist/coverage/prettify.js +1009 -0
- package/dist/coverage/sorter.d.ts +1 -0
- package/dist/coverage/sorter.js +178 -0
- package/dist/frameworks/express/api-gateway/mapping-model.spec.js +58 -0
- package/dist/frameworks/express/authorizations/authorization-express.spec.js +9 -0
- package/dist/frameworks/express/middleware-express.spec.d.ts +1 -0
- package/dist/frameworks/express/middleware-express.spec.js +51 -0
- package/dist/frameworks/nest/nest.spec.d.ts +1 -0
- package/dist/frameworks/nest/nest.spec.js +122 -0
- package/dist/infra/http/api-gateway/mapping-model.spec.js +42 -0
- package/package.json +5 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare function addSorting(): void;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
var addSorting = (function () {
|
|
4
|
+
'use strict';
|
|
5
|
+
var cols,
|
|
6
|
+
currentSort = {
|
|
7
|
+
index: 0,
|
|
8
|
+
desc: false,
|
|
9
|
+
};
|
|
10
|
+
// returns the summary table element
|
|
11
|
+
function getTable() {
|
|
12
|
+
return document.querySelector('.coverage-summary');
|
|
13
|
+
}
|
|
14
|
+
// returns the thead element of the summary table
|
|
15
|
+
function getTableHeader() {
|
|
16
|
+
return getTable().querySelector('thead tr');
|
|
17
|
+
}
|
|
18
|
+
// returns the tbody element of the summary table
|
|
19
|
+
function getTableBody() {
|
|
20
|
+
return getTable().querySelector('tbody');
|
|
21
|
+
}
|
|
22
|
+
// returns the th element for nth column
|
|
23
|
+
function getNthColumn(n) {
|
|
24
|
+
return getTableHeader().querySelectorAll('th')[n];
|
|
25
|
+
}
|
|
26
|
+
function onFilterInput() {
|
|
27
|
+
const searchValue = document.getElementById('fileSearch').value;
|
|
28
|
+
const rows = document.getElementsByTagName('tbody')[0].children;
|
|
29
|
+
for (let i = 0; i < rows.length; i++) {
|
|
30
|
+
const row = rows[i];
|
|
31
|
+
if (row.textContent.toLowerCase().includes(searchValue.toLowerCase())) {
|
|
32
|
+
row.style.display = '';
|
|
33
|
+
} else {
|
|
34
|
+
row.style.display = 'none';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// loads the search box
|
|
39
|
+
function addSearchBox() {
|
|
40
|
+
var template = document.getElementById('filterTemplate');
|
|
41
|
+
var templateClone = template.content.cloneNode(true);
|
|
42
|
+
templateClone.getElementById('fileSearch').oninput = onFilterInput;
|
|
43
|
+
template.parentElement.appendChild(templateClone);
|
|
44
|
+
}
|
|
45
|
+
// loads all columns
|
|
46
|
+
function loadColumns() {
|
|
47
|
+
var colNodes = getTableHeader().querySelectorAll('th'),
|
|
48
|
+
colNode,
|
|
49
|
+
cols = [],
|
|
50
|
+
col,
|
|
51
|
+
i;
|
|
52
|
+
for (i = 0; i < colNodes.length; i += 1) {
|
|
53
|
+
colNode = colNodes[i];
|
|
54
|
+
col = {
|
|
55
|
+
key: colNode.getAttribute('data-col'),
|
|
56
|
+
sortable: !colNode.getAttribute('data-nosort'),
|
|
57
|
+
type: colNode.getAttribute('data-type') || 'string',
|
|
58
|
+
};
|
|
59
|
+
cols.push(col);
|
|
60
|
+
if (col.sortable) {
|
|
61
|
+
col.defaultDescSort = col.type === 'number';
|
|
62
|
+
colNode.innerHTML = colNode.innerHTML + '<span class="sorter"></span>';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return cols;
|
|
66
|
+
}
|
|
67
|
+
// attaches a data attribute to every tr element with an object
|
|
68
|
+
// of data values keyed by column name
|
|
69
|
+
function loadRowData(tableRow) {
|
|
70
|
+
var tableCols = tableRow.querySelectorAll('td'),
|
|
71
|
+
colNode,
|
|
72
|
+
col,
|
|
73
|
+
data = {},
|
|
74
|
+
i,
|
|
75
|
+
val;
|
|
76
|
+
for (i = 0; i < tableCols.length; i += 1) {
|
|
77
|
+
colNode = tableCols[i];
|
|
78
|
+
col = cols[i];
|
|
79
|
+
val = colNode.getAttribute('data-value');
|
|
80
|
+
if (col.type === 'number') {
|
|
81
|
+
val = Number(val);
|
|
82
|
+
}
|
|
83
|
+
data[col.key] = val;
|
|
84
|
+
}
|
|
85
|
+
return data;
|
|
86
|
+
}
|
|
87
|
+
// loads all row data
|
|
88
|
+
function loadData() {
|
|
89
|
+
var rows = getTableBody().querySelectorAll('tr'),
|
|
90
|
+
i;
|
|
91
|
+
for (i = 0; i < rows.length; i += 1) {
|
|
92
|
+
rows[i].data = loadRowData(rows[i]);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// sorts the table using the data for the ith column
|
|
96
|
+
function sortByIndex(index, desc) {
|
|
97
|
+
var key = cols[index].key,
|
|
98
|
+
sorter = function (a, b) {
|
|
99
|
+
a = a.data[key];
|
|
100
|
+
b = b.data[key];
|
|
101
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
102
|
+
},
|
|
103
|
+
finalSorter = sorter,
|
|
104
|
+
tableBody = document.querySelector('.coverage-summary tbody'),
|
|
105
|
+
rowNodes = tableBody.querySelectorAll('tr'),
|
|
106
|
+
rows = [],
|
|
107
|
+
i;
|
|
108
|
+
if (desc) {
|
|
109
|
+
finalSorter = function (a, b) {
|
|
110
|
+
return -1 * sorter(a, b);
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
for (i = 0; i < rowNodes.length; i += 1) {
|
|
114
|
+
rows.push(rowNodes[i]);
|
|
115
|
+
tableBody.removeChild(rowNodes[i]);
|
|
116
|
+
}
|
|
117
|
+
rows.sort(finalSorter);
|
|
118
|
+
for (i = 0; i < rows.length; i += 1) {
|
|
119
|
+
tableBody.appendChild(rows[i]);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// removes sort indicators for current column being sorted
|
|
123
|
+
function removeSortIndicators() {
|
|
124
|
+
var col = getNthColumn(currentSort.index),
|
|
125
|
+
cls = col.className;
|
|
126
|
+
cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, '');
|
|
127
|
+
col.className = cls;
|
|
128
|
+
}
|
|
129
|
+
// adds sort indicators for current column being sorted
|
|
130
|
+
function addSortIndicators() {
|
|
131
|
+
getNthColumn(currentSort.index).className += currentSort.desc
|
|
132
|
+
? ' sorted-desc'
|
|
133
|
+
: ' sorted';
|
|
134
|
+
}
|
|
135
|
+
// adds event listeners for all sorter widgets
|
|
136
|
+
function enableUI() {
|
|
137
|
+
var i,
|
|
138
|
+
el,
|
|
139
|
+
ithSorter = function ithSorter(i) {
|
|
140
|
+
var col = cols[i];
|
|
141
|
+
return function () {
|
|
142
|
+
var desc = col.defaultDescSort;
|
|
143
|
+
if (currentSort.index === i) {
|
|
144
|
+
desc = !currentSort.desc;
|
|
145
|
+
}
|
|
146
|
+
sortByIndex(i, desc);
|
|
147
|
+
removeSortIndicators();
|
|
148
|
+
currentSort.index = i;
|
|
149
|
+
currentSort.desc = desc;
|
|
150
|
+
addSortIndicators();
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
for (i = 0; i < cols.length; i += 1) {
|
|
154
|
+
if (cols[i].sortable) {
|
|
155
|
+
// add the click event handler on the th so users
|
|
156
|
+
// dont have to click on those tiny arrows
|
|
157
|
+
el = getNthColumn(i).querySelector('.sorter').parentElement;
|
|
158
|
+
if (el.addEventListener) {
|
|
159
|
+
el.addEventListener('click', ithSorter(i));
|
|
160
|
+
} else {
|
|
161
|
+
el.attachEvent('onclick', ithSorter(i));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// adds sorting functionality to the UI
|
|
167
|
+
return function () {
|
|
168
|
+
if (!getTable()) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
cols = loadColumns();
|
|
172
|
+
loadData();
|
|
173
|
+
addSearchBox();
|
|
174
|
+
addSortIndicators();
|
|
175
|
+
enableUI();
|
|
176
|
+
};
|
|
177
|
+
})();
|
|
178
|
+
window.addEventListener('load', addSorting);
|
|
@@ -40,6 +40,17 @@ describe('ExpressMappingModel', () => {
|
|
|
40
40
|
});
|
|
41
41
|
});
|
|
42
42
|
describe('setHeader', () => {
|
|
43
|
+
it('should ignore empty header keys', () => {
|
|
44
|
+
const instance = new mapping_model_2.ExpressMappingModel({
|
|
45
|
+
request: {
|
|
46
|
+
headers: { existing: 'existing_value' },
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
expect(instance['setHeader']('', 'new_value')).toBe(instance);
|
|
50
|
+
expect(instance['getHeaders']()).toStrictEqual({
|
|
51
|
+
existing: 'existing_value',
|
|
52
|
+
});
|
|
53
|
+
});
|
|
43
54
|
it('should set a existing header value', () => {
|
|
44
55
|
const result = new mapping_model_2.ExpressMappingModel({
|
|
45
56
|
request: {
|
|
@@ -136,4 +147,51 @@ describe('ExpressMappingModel', () => {
|
|
|
136
147
|
expect(result).toBe('next func');
|
|
137
148
|
});
|
|
138
149
|
});
|
|
150
|
+
describe('setBody', () => {
|
|
151
|
+
it('should replace the body with body-json when present', () => {
|
|
152
|
+
const instance = new mapping_model_2.ExpressMappingModel({
|
|
153
|
+
request: {
|
|
154
|
+
body: {
|
|
155
|
+
['body-json']: { id: '1' },
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
instance['setBody']();
|
|
160
|
+
expect(instance['getBody']()).toStrictEqual({ id: '1' });
|
|
161
|
+
});
|
|
162
|
+
it('should keep the original body when body-json is missing', () => {
|
|
163
|
+
const body = { id: '1' };
|
|
164
|
+
const instance = new mapping_model_2.ExpressMappingModel({
|
|
165
|
+
request: {
|
|
166
|
+
body,
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
instance['setBody']();
|
|
170
|
+
expect(instance['getBody']()).toBe(body);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
describe('setMethod', () => {
|
|
174
|
+
it('should override request method from header', () => {
|
|
175
|
+
const instance = new mapping_model_2.ExpressMappingModel({
|
|
176
|
+
request: {
|
|
177
|
+
method: 'POST',
|
|
178
|
+
headers: {
|
|
179
|
+
'x-http-method-override': 'PATCH',
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
instance['setMethod']();
|
|
184
|
+
expect(instance['controller'].request.method).toBe('PATCH');
|
|
185
|
+
});
|
|
186
|
+
it('should keep request method when override header is missing', () => {
|
|
187
|
+
const instance = new mapping_model_2.ExpressMappingModel({
|
|
188
|
+
request: {
|
|
189
|
+
method: 'POST',
|
|
190
|
+
headers: {},
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
instance['setMethod']();
|
|
194
|
+
expect(instance['controller'].request.method).toBe('POST');
|
|
195
|
+
});
|
|
196
|
+
});
|
|
139
197
|
});
|
|
@@ -36,6 +36,15 @@ describe('Express', () => {
|
|
|
36
36
|
const authorizations = await expressInstance['getAuthorizations']();
|
|
37
37
|
expect(authorizations).toEqual(['auth1', 'auth2']);
|
|
38
38
|
});
|
|
39
|
+
it('should get authorizations from auths header when needed', async () => {
|
|
40
|
+
request.headers = {
|
|
41
|
+
auths: '["auth1","auth2"]',
|
|
42
|
+
['X-Amzn-Requestid']: 'request-id',
|
|
43
|
+
};
|
|
44
|
+
const expressInstance = (await authorization_express_1.default.create(query, controllerMetaData));
|
|
45
|
+
expect(expressInstance['getAuthsHeader']()).toBe('["auth1","auth2"]');
|
|
46
|
+
expect(expressInstance.getRequestId()).toBe('request-id');
|
|
47
|
+
});
|
|
39
48
|
it('should call next function when authorized', async () => {
|
|
40
49
|
const expressInstance = await authorization_express_1.default.create(query, controllerMetaData);
|
|
41
50
|
expressInstance['handleAuthorized']();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const vitest_1 = require("vitest");
|
|
5
|
+
vitest_1.vi.mock('compression', () => ({
|
|
6
|
+
default: vitest_1.vi.fn(options => options),
|
|
7
|
+
}));
|
|
8
|
+
const compression_1 = tslib_1.__importDefault(require("compression"));
|
|
9
|
+
const mapping_model_1 = require("./api-gateway/mapping-model");
|
|
10
|
+
const middleware_express_1 = require("./api-gateway/middleware-express");
|
|
11
|
+
const authorization_express_1 = tslib_1.__importDefault(require("./authorizations/authorization-express"));
|
|
12
|
+
const middleware_express_2 = require("./authorizations/middleware-express");
|
|
13
|
+
const middleware_express_3 = require("./compression/middleware-express");
|
|
14
|
+
describe('Express middlewares', () => {
|
|
15
|
+
it('should map API Gateway requests through the mapping model', () => {
|
|
16
|
+
const parseSpy = vitest_1.vi
|
|
17
|
+
.spyOn(mapping_model_1.ExpressMappingModel.prototype, 'parse')
|
|
18
|
+
.mockReturnValue('mapped');
|
|
19
|
+
const request = {};
|
|
20
|
+
const response = {};
|
|
21
|
+
const next = vitest_1.vi.fn();
|
|
22
|
+
expect((0, middleware_express_1.mapRequestMiddleware)(request, response, next)).toBe('mapped');
|
|
23
|
+
expect(parseSpy).toHaveBeenCalledTimes(1);
|
|
24
|
+
});
|
|
25
|
+
it('should build the authorizer middleware and validate the request', async () => {
|
|
26
|
+
const validate = vitest_1.vi.fn().mockResolvedValue(true);
|
|
27
|
+
const createSpy = vitest_1.vi
|
|
28
|
+
.spyOn(authorization_express_1.default, 'create')
|
|
29
|
+
.mockResolvedValue({ validate });
|
|
30
|
+
const request = {};
|
|
31
|
+
const response = {};
|
|
32
|
+
const next = vitest_1.vi.fn();
|
|
33
|
+
const query = { $and: ['auth.read'] };
|
|
34
|
+
const middleware = (0, middleware_express_2.authorizer)(query);
|
|
35
|
+
await expect(middleware(request, response, next)).resolves.toBe(true);
|
|
36
|
+
expect(createSpy).toHaveBeenCalledWith(query, {
|
|
37
|
+
request,
|
|
38
|
+
response,
|
|
39
|
+
next,
|
|
40
|
+
});
|
|
41
|
+
expect(validate).toHaveBeenCalledTimes(1);
|
|
42
|
+
});
|
|
43
|
+
it('should create a compression middleware with the expected filter', () => {
|
|
44
|
+
expect(compression_1.default).toHaveBeenCalledWith({
|
|
45
|
+
filter: expect.any(Function),
|
|
46
|
+
});
|
|
47
|
+
const filter = middleware_express_3.compressionMiddleware.filter;
|
|
48
|
+
expect(filter({ headers: { 'accept-encoding': 'identity' } })).toBe(true);
|
|
49
|
+
expect(filter({ headers: { 'accept-encoding': 'gzip' } })).toBe(false);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const authorization_nest_1 = tslib_1.__importDefault(require("./authorizations/authorization-nest"));
|
|
5
|
+
const guard_nest_1 = tslib_1.__importDefault(require("./authorizations/guard-nest"));
|
|
6
|
+
const not_allowed_nest_1 = require("./authorizations/not-allowed-nest");
|
|
7
|
+
const orbit_error_1 = require("./errors/orbit-error");
|
|
8
|
+
const orbit_exception_filter_1 = require("./exception-filters/orbit-exception-filter");
|
|
9
|
+
describe('Nest integrations', () => {
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
vi.restoreAllMocks();
|
|
12
|
+
});
|
|
13
|
+
it('should expose orbit errors as HTTP exceptions', () => {
|
|
14
|
+
const error = new orbit_error_1.OrbitError('Forbidden', 403);
|
|
15
|
+
expect(error.getStatus()).toBe(403);
|
|
16
|
+
expect(error.message).toBe('Forbidden');
|
|
17
|
+
});
|
|
18
|
+
it('should expose the not allowed payload for Nest', () => {
|
|
19
|
+
const timestamp = new Date('2024-01-01T00:00:00.000Z');
|
|
20
|
+
const error = new not_allowed_nest_1.NestNotAllowedError({
|
|
21
|
+
status: 401,
|
|
22
|
+
body: {
|
|
23
|
+
code: 401,
|
|
24
|
+
message: 'Unauthorized',
|
|
25
|
+
timestamp,
|
|
26
|
+
errors: [
|
|
27
|
+
{
|
|
28
|
+
code_error: '401',
|
|
29
|
+
location: 'authorization',
|
|
30
|
+
msg: 'Unauthorized',
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
headers: {},
|
|
35
|
+
});
|
|
36
|
+
expect(error.getStatus()).toBe(403);
|
|
37
|
+
expect(error.getResponse()).toEqual({
|
|
38
|
+
code: 401,
|
|
39
|
+
message: 'Unauthorized',
|
|
40
|
+
timestamp,
|
|
41
|
+
errors: [
|
|
42
|
+
{
|
|
43
|
+
code_error: '401',
|
|
44
|
+
location: 'authorization',
|
|
45
|
+
msg: 'Unauthorized',
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
});
|
|
49
|
+
expect(error.message).toBe('Unauthorized');
|
|
50
|
+
});
|
|
51
|
+
it('should translate orbit errors in the exception filter', () => {
|
|
52
|
+
const response = {
|
|
53
|
+
status: vi.fn().mockReturnThis(),
|
|
54
|
+
json: vi.fn().mockReturnThis(),
|
|
55
|
+
};
|
|
56
|
+
const host = {
|
|
57
|
+
switchToHttp: () => ({
|
|
58
|
+
getResponse: () => response,
|
|
59
|
+
}),
|
|
60
|
+
};
|
|
61
|
+
const exception = new not_allowed_nest_1.NestNotAllowedError({
|
|
62
|
+
status: 403,
|
|
63
|
+
body: {
|
|
64
|
+
code: 403,
|
|
65
|
+
message: 'Forbidden',
|
|
66
|
+
timestamp: new Date('2024-01-01T00:00:00.000Z'),
|
|
67
|
+
errors: [],
|
|
68
|
+
},
|
|
69
|
+
headers: {},
|
|
70
|
+
});
|
|
71
|
+
const filter = new orbit_exception_filter_1.OrbitExceptionFilter();
|
|
72
|
+
filter.catch(exception, host);
|
|
73
|
+
expect(response.status).toHaveBeenCalledWith(403);
|
|
74
|
+
expect(response.json).toHaveBeenCalledWith(exception.getResponse());
|
|
75
|
+
});
|
|
76
|
+
it('should authorize or throw on Nest authorization wrappers', async () => {
|
|
77
|
+
const query = { $and: ['auth.read'] };
|
|
78
|
+
const request = {
|
|
79
|
+
headers: {
|
|
80
|
+
authorizations: '["auth.read"]',
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
const response = {};
|
|
84
|
+
const next = vi.fn();
|
|
85
|
+
const instance = (await authorization_nest_1.default.create(query, {
|
|
86
|
+
request,
|
|
87
|
+
response,
|
|
88
|
+
next,
|
|
89
|
+
}));
|
|
90
|
+
await expect(instance['handleAuthorized']()).resolves.toBe(true);
|
|
91
|
+
await expect(instance['unauthorize']({
|
|
92
|
+
status: 403,
|
|
93
|
+
body: {
|
|
94
|
+
code: 403,
|
|
95
|
+
message: 'Forbidden',
|
|
96
|
+
timestamp: new Date('2024-01-01T00:00:00.000Z'),
|
|
97
|
+
errors: [],
|
|
98
|
+
},
|
|
99
|
+
headers: {},
|
|
100
|
+
})).rejects.toBeInstanceOf(not_allowed_nest_1.NestNotAllowedError);
|
|
101
|
+
});
|
|
102
|
+
it('should validate requests through the Nest guard', async () => {
|
|
103
|
+
const validate = vi.fn().mockResolvedValue(true);
|
|
104
|
+
const createSpy = vi
|
|
105
|
+
.spyOn(authorization_nest_1.default, 'create')
|
|
106
|
+
.mockResolvedValue({ validate });
|
|
107
|
+
const request = {};
|
|
108
|
+
const response = {};
|
|
109
|
+
const next = vi.fn();
|
|
110
|
+
const guard = new guard_nest_1.default({ $or: ['auth.read'] });
|
|
111
|
+
const context = {
|
|
112
|
+
switchToHttp: () => ({
|
|
113
|
+
getRequest: () => request,
|
|
114
|
+
getResponse: () => response,
|
|
115
|
+
getNext: () => next,
|
|
116
|
+
}),
|
|
117
|
+
};
|
|
118
|
+
await expect(guard.canActivate(context)).resolves.toBe(true);
|
|
119
|
+
expect(createSpy).toHaveBeenCalledWith({ $or: ['auth.read'] }, { request, response, next });
|
|
120
|
+
expect(validate).toHaveBeenCalledTimes(1);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
@@ -132,5 +132,47 @@ describe('MappingModel', () => {
|
|
|
132
132
|
expect(instance['deleteParams'].mock.calls.length).toBe(1);
|
|
133
133
|
expect(instance['next'].mock.calls.length).toBe(1);
|
|
134
134
|
});
|
|
135
|
+
it('should create an empty context when it is missing', () => {
|
|
136
|
+
const instance = new MockMappingModel(undefined);
|
|
137
|
+
instance['getBody'] = vi.fn().mockReturnValue({
|
|
138
|
+
['api-gateway-params']: {
|
|
139
|
+
header: {},
|
|
140
|
+
querystring: {},
|
|
141
|
+
path: {},
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
instance['next'] = vi.fn().mockReturnValue('next func');
|
|
145
|
+
instance['setHeader'] = vi.fn().mockReturnThis();
|
|
146
|
+
instance['deleteParams'] = vi.fn().mockReturnThis();
|
|
147
|
+
expect(instance.parse()).toBe('next func');
|
|
148
|
+
expect(instance['setHeader'].mock.calls).toStrictEqual([
|
|
149
|
+
['authorizations', undefined],
|
|
150
|
+
['fiscalidsfromtenant', '[]'],
|
|
151
|
+
['accept-encoding', 'identity'],
|
|
152
|
+
]);
|
|
153
|
+
});
|
|
154
|
+
it('should map fiscal ids from tenant into headers', () => {
|
|
155
|
+
const instance = new MockMappingModel(undefined);
|
|
156
|
+
instance['getBody'] = vi.fn().mockReturnValue({
|
|
157
|
+
['api-gateway-params']: {
|
|
158
|
+
context: {
|
|
159
|
+
authorizations: ['test'],
|
|
160
|
+
fiscalIdsFromTenant: ['123', '456'],
|
|
161
|
+
},
|
|
162
|
+
header: {},
|
|
163
|
+
querystring: {},
|
|
164
|
+
path: {},
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
instance['next'] = vi.fn().mockReturnValue('next func');
|
|
168
|
+
instance['setHeader'] = vi.fn().mockReturnThis();
|
|
169
|
+
instance['deleteParams'] = vi.fn().mockReturnThis();
|
|
170
|
+
expect(instance.parse()).toBe('next func');
|
|
171
|
+
expect(instance['setHeader'].mock.calls).toStrictEqual([
|
|
172
|
+
['authorizations', ['test']],
|
|
173
|
+
['fiscalidsfromtenant', '["123","456"]'],
|
|
174
|
+
['accept-encoding', 'identity'],
|
|
175
|
+
]);
|
|
176
|
+
});
|
|
135
177
|
});
|
|
136
178
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seidor-cloud-produtos/orbit-backend-lib",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.111",
|
|
4
4
|
"description": "Internal lib for backend components",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -81,6 +81,10 @@
|
|
|
81
81
|
"@aws-sdk/client-sqs": "3.940.0",
|
|
82
82
|
"@fastify/cors": "8.3.0",
|
|
83
83
|
"@nestjs/common": "8.4.7",
|
|
84
|
+
"@opentelemetry/auto-instrumentations-node": "^0.69.0",
|
|
85
|
+
"@opentelemetry/resources": "^2.5.0",
|
|
86
|
+
"@opentelemetry/sdk-node": "^0.211.0",
|
|
87
|
+
"@opentelemetry/semantic-conventions": "^1.39.0",
|
|
84
88
|
"amqplib": "0.10.9",
|
|
85
89
|
"axios": "1.8.2",
|
|
86
90
|
"compression": "1.7.4",
|