@terreno/api 0.9.3 → 0.10.0
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/bunfig.unit.toml +3 -0
- package/dist/expressServer.js +3 -9
- package/dist/expressServer.test.js +4 -7
- package/dist/openApi.test.js +3 -0
- package/dist/openApiEtag.test.js +8 -0
- package/dist/permissions.middleware.test.d.ts +1 -0
- package/dist/permissions.middleware.test.js +341 -0
- package/dist/syncConsents.js +2 -2
- package/dist/tests/bunSetup.js +27 -22
- package/package.json +1 -1
- package/src/expressServer.test.ts +4 -11
- package/src/expressServer.ts +4 -8
- package/src/openApi.test.ts +5 -1
- package/src/openApiEtag.test.ts +11 -0
- package/src/permissions.middleware.test.ts +197 -0
- package/src/syncConsents.ts +1 -1
- package/src/tests/bunSetup.ts +14 -8
package/bunfig.unit.toml
ADDED
package/dist/expressServer.js
CHANGED
|
@@ -341,16 +341,10 @@ function setupServer(options) {
|
|
|
341
341
|
}
|
|
342
342
|
// Convenience method to execute cronjobs with an always-running server.
|
|
343
343
|
function cronjob(name, schedule, callback) {
|
|
344
|
-
var
|
|
345
|
-
|
|
346
|
-
_cronSchedule = "0 * * * *";
|
|
347
|
-
}
|
|
348
|
-
else if (schedule === "minutely") {
|
|
349
|
-
_cronSchedule = "* * * * *";
|
|
350
|
-
}
|
|
351
|
-
logger_1.logger.info("Adding cronjob ".concat(name, ", running at: ").concat(schedule));
|
|
344
|
+
var cronSchedule = schedule === "hourly" ? "0 * * * *" : schedule === "minutely" ? "* * * * *" : schedule;
|
|
345
|
+
logger_1.logger.info("Adding cronjob ".concat(name, ", running at: ").concat(cronSchedule));
|
|
352
346
|
try {
|
|
353
|
-
new cron_1.default.CronJob(
|
|
347
|
+
new cron_1.default.CronJob(cronSchedule, callback, null, true, "America/Chicago");
|
|
354
348
|
}
|
|
355
349
|
catch (error) {
|
|
356
350
|
throw new Error("Failed to create cronjob: ".concat(error));
|
|
@@ -383,16 +383,13 @@ var tests_1 = require("./tests");
|
|
|
383
383
|
var callback = function () { };
|
|
384
384
|
(0, bun_test_1.expect)(function () { return (0, expressServer_1.cronjob)("test-invalid", "invalid-cron", callback); }).toThrow("Failed to create cronjob");
|
|
385
385
|
});
|
|
386
|
-
|
|
387
|
-
// schedule to a cron expression but then use the original schedule string.
|
|
388
|
-
// This test documents that current (buggy) behavior.
|
|
389
|
-
(0, bun_test_1.it)("hourly alias fails due to bug in implementation", function () {
|
|
386
|
+
(0, bun_test_1.it)("accepts hourly alias", function () {
|
|
390
387
|
var callback = function () { };
|
|
391
|
-
(0, bun_test_1.expect)(function () { return (0, expressServer_1.cronjob)("test-hourly-alias", "hourly", callback); }).toThrow(
|
|
388
|
+
(0, bun_test_1.expect)(function () { return (0, expressServer_1.cronjob)("test-hourly-alias", "hourly", callback); }).not.toThrow();
|
|
392
389
|
});
|
|
393
|
-
(0, bun_test_1.it)("minutely alias
|
|
390
|
+
(0, bun_test_1.it)("accepts minutely alias", function () {
|
|
394
391
|
var callback = function () { };
|
|
395
|
-
(0, bun_test_1.expect)(function () { return (0, expressServer_1.cronjob)("test-minutely-alias", "minutely", callback); }).toThrow(
|
|
392
|
+
(0, bun_test_1.expect)(function () { return (0, expressServer_1.cronjob)("test-minutely-alias", "minutely", callback); }).not.toThrow();
|
|
396
393
|
});
|
|
397
394
|
});
|
|
398
395
|
(0, bun_test_1.describe)("createRouter routePathMiddleware", function () {
|
package/dist/openApi.test.js
CHANGED
|
@@ -74,6 +74,9 @@ var expressServer_1 = require("./expressServer");
|
|
|
74
74
|
var permissions_1 = require("./permissions");
|
|
75
75
|
var tests_1 = require("./tests");
|
|
76
76
|
function getMessageSummaryOpenApiMiddleware(options) {
|
|
77
|
+
if (!options.openApi) {
|
|
78
|
+
throw new Error("Expected openApi to be configured for test routes");
|
|
79
|
+
}
|
|
77
80
|
return options.openApi.path({
|
|
78
81
|
parameters: [
|
|
79
82
|
{
|
package/dist/openApiEtag.test.js
CHANGED
|
@@ -45,6 +45,14 @@ var buildResponse = function () {
|
|
|
45
45
|
(0, bun_test_1.expect)(next).toHaveBeenCalledTimes(1);
|
|
46
46
|
(0, bun_test_1.expect)(res.json).toBe(originalJson);
|
|
47
47
|
});
|
|
48
|
+
(0, bun_test_1.it)("skips GET requests for non-openapi.json paths", function () {
|
|
49
|
+
var req = buildRequest({ method: "GET", path: "/health" });
|
|
50
|
+
var _a = buildResponse(), res = _a.res, originalJson = _a.originalJson;
|
|
51
|
+
var next = (0, bun_test_1.mock)(function () { });
|
|
52
|
+
(0, openApiEtag_1.openApiEtagMiddleware)(req, res, next);
|
|
53
|
+
(0, bun_test_1.expect)(next).toHaveBeenCalledTimes(1);
|
|
54
|
+
(0, bun_test_1.expect)(res.json).toBe(originalJson);
|
|
55
|
+
});
|
|
48
56
|
(0, bun_test_1.it)("sets ETag and returns json body when no matching If-None-Match header is provided", function () {
|
|
49
57
|
var req = buildRequest();
|
|
50
58
|
var _a = buildResponse(), res = _a.res, originalJson = _a.originalJson, set = _a.set, status = _a.status, end = _a.end;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
20
|
+
}) : (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
o[k2] = m[k];
|
|
23
|
+
}));
|
|
24
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
25
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
26
|
+
}) : function(o, v) {
|
|
27
|
+
o["default"] = v;
|
|
28
|
+
});
|
|
29
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
30
|
+
var ownKeys = function(o) {
|
|
31
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
32
|
+
var ar = [];
|
|
33
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
34
|
+
return ar;
|
|
35
|
+
};
|
|
36
|
+
return ownKeys(o);
|
|
37
|
+
};
|
|
38
|
+
return function (mod) {
|
|
39
|
+
if (mod && mod.__esModule) return mod;
|
|
40
|
+
var result = {};
|
|
41
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
42
|
+
__setModuleDefault(result, mod);
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
45
|
+
})();
|
|
46
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
47
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
48
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
49
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
50
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
51
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
52
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
56
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
57
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
58
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
59
|
+
function step(op) {
|
|
60
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
61
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
62
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
63
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
64
|
+
switch (op[0]) {
|
|
65
|
+
case 0: case 1: t = op; break;
|
|
66
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
67
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
68
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
69
|
+
default:
|
|
70
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
71
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
72
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
73
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
74
|
+
if (t[2]) _.ops.pop();
|
|
75
|
+
_.trys.pop(); continue;
|
|
76
|
+
}
|
|
77
|
+
op = body.call(thisArg, _);
|
|
78
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
79
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
83
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
84
|
+
if (!m) return o;
|
|
85
|
+
var i = m.call(o), r, ar = [], e;
|
|
86
|
+
try {
|
|
87
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
88
|
+
}
|
|
89
|
+
catch (error) { e = { error: error }; }
|
|
90
|
+
finally {
|
|
91
|
+
try {
|
|
92
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
93
|
+
}
|
|
94
|
+
finally { if (e) throw e.error; }
|
|
95
|
+
}
|
|
96
|
+
return ar;
|
|
97
|
+
};
|
|
98
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
99
|
+
var bun_test_1 = require("bun:test");
|
|
100
|
+
var Sentry = __importStar(require("@sentry/bun"));
|
|
101
|
+
var errors_1 = require("./errors");
|
|
102
|
+
var permissions_1 = require("./permissions");
|
|
103
|
+
(0, bun_test_1.describe)("permissionMiddleware", function () {
|
|
104
|
+
var allPermissions = {
|
|
105
|
+
create: [permissions_1.Permissions.IsAny],
|
|
106
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
107
|
+
list: [permissions_1.Permissions.IsAny],
|
|
108
|
+
read: [permissions_1.Permissions.IsAny],
|
|
109
|
+
update: [permissions_1.Permissions.IsAny],
|
|
110
|
+
};
|
|
111
|
+
var buildReq = function (overrides) {
|
|
112
|
+
if (overrides === void 0) { overrides = {}; }
|
|
113
|
+
return __assign({ method: "GET", params: {}, user: { id: "user-1" } }, overrides);
|
|
114
|
+
};
|
|
115
|
+
(0, bun_test_1.it)("calls next immediately for OPTIONS requests", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
116
|
+
var model, middleware, next;
|
|
117
|
+
return __generator(this, function (_a) {
|
|
118
|
+
switch (_a.label) {
|
|
119
|
+
case 0:
|
|
120
|
+
model = {
|
|
121
|
+
collection: { findOne: (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
122
|
+
return [2 /*return*/, null];
|
|
123
|
+
}); }); }) },
|
|
124
|
+
findById: (0, bun_test_1.mock)(function () { return ({ exec: (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
125
|
+
return [2 /*return*/, null];
|
|
126
|
+
}); }); }) }); }),
|
|
127
|
+
modelName: "MockModel",
|
|
128
|
+
};
|
|
129
|
+
middleware = (0, permissions_1.permissionMiddleware)(model, { permissions: allPermissions });
|
|
130
|
+
next = (0, bun_test_1.mock)(function () { });
|
|
131
|
+
return [4 /*yield*/, middleware(buildReq({ method: "OPTIONS" }), {}, next)];
|
|
132
|
+
case 1:
|
|
133
|
+
_a.sent();
|
|
134
|
+
(0, bun_test_1.expect)(next).toHaveBeenCalledTimes(1);
|
|
135
|
+
(0, bun_test_1.expect)(next.mock.calls[0]).toEqual([]);
|
|
136
|
+
(0, bun_test_1.expect)(model.findById).toHaveBeenCalledTimes(0);
|
|
137
|
+
return [2 /*return*/];
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}); });
|
|
141
|
+
(0, bun_test_1.it)("returns APIError for unsupported HTTP methods", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
142
|
+
var model, middleware, next, _a, error;
|
|
143
|
+
return __generator(this, function (_b) {
|
|
144
|
+
switch (_b.label) {
|
|
145
|
+
case 0:
|
|
146
|
+
model = {
|
|
147
|
+
collection: { findOne: (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
148
|
+
return [2 /*return*/, null];
|
|
149
|
+
}); }); }) },
|
|
150
|
+
findById: (0, bun_test_1.mock)(function () { return ({ exec: (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
151
|
+
return [2 /*return*/, null];
|
|
152
|
+
}); }); }) }); }),
|
|
153
|
+
modelName: "MockModel",
|
|
154
|
+
};
|
|
155
|
+
middleware = (0, permissions_1.permissionMiddleware)(model, { permissions: allPermissions });
|
|
156
|
+
next = (0, bun_test_1.mock)(function () { });
|
|
157
|
+
return [4 /*yield*/, middleware(buildReq({ method: "TRACE" }), {}, next)];
|
|
158
|
+
case 1:
|
|
159
|
+
_b.sent();
|
|
160
|
+
(0, bun_test_1.expect)(next).toHaveBeenCalledTimes(1);
|
|
161
|
+
_a = __read(next.mock.calls[0], 1), error = _a[0];
|
|
162
|
+
(0, bun_test_1.expect)(error).toBeInstanceOf(errors_1.APIError);
|
|
163
|
+
(0, bun_test_1.expect)(error.status).toBe(405);
|
|
164
|
+
(0, bun_test_1.expect)(error.title).toContain("Method TRACE not allowed");
|
|
165
|
+
return [2 /*return*/];
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
}); });
|
|
169
|
+
(0, bun_test_1.it)("wraps query execution failures in a 500 APIError", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
170
|
+
var exec, model, middleware, next, _a, error;
|
|
171
|
+
return __generator(this, function (_b) {
|
|
172
|
+
switch (_b.label) {
|
|
173
|
+
case 0:
|
|
174
|
+
exec = (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
175
|
+
return __generator(this, function (_a) {
|
|
176
|
+
throw new Error("query failed");
|
|
177
|
+
});
|
|
178
|
+
}); });
|
|
179
|
+
model = {
|
|
180
|
+
collection: { findOne: (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
181
|
+
return [2 /*return*/, null];
|
|
182
|
+
}); }); }) },
|
|
183
|
+
findById: (0, bun_test_1.mock)(function () { return ({ exec: exec }); }),
|
|
184
|
+
modelName: "MockModel",
|
|
185
|
+
};
|
|
186
|
+
middleware = (0, permissions_1.permissionMiddleware)(model, { permissions: allPermissions });
|
|
187
|
+
next = (0, bun_test_1.mock)(function () { });
|
|
188
|
+
return [4 /*yield*/, middleware(buildReq({ method: "GET", params: { id: "507f1f77bcf86cd799439011" } }), {}, next)];
|
|
189
|
+
case 1:
|
|
190
|
+
_b.sent();
|
|
191
|
+
(0, bun_test_1.expect)(exec).toHaveBeenCalledTimes(1);
|
|
192
|
+
_a = __read(next.mock.calls[0], 1), error = _a[0];
|
|
193
|
+
(0, bun_test_1.expect)(error).toBeInstanceOf(errors_1.APIError);
|
|
194
|
+
(0, bun_test_1.expect)(error.status).toBe(500);
|
|
195
|
+
(0, bun_test_1.expect)(error.title).toContain("GET failed on 507f1f77bcf86cd799439011");
|
|
196
|
+
return [2 /*return*/];
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}); });
|
|
200
|
+
(0, bun_test_1.it)("captures sentry message when document does not exist", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
201
|
+
var captureMessageSpy, model, middleware, next, _a, error;
|
|
202
|
+
return __generator(this, function (_b) {
|
|
203
|
+
switch (_b.label) {
|
|
204
|
+
case 0:
|
|
205
|
+
captureMessageSpy = (0, bun_test_1.spyOn)(Sentry, "captureMessage");
|
|
206
|
+
model = {
|
|
207
|
+
collection: { findOne: (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
208
|
+
return [2 /*return*/, null];
|
|
209
|
+
}); }); }) },
|
|
210
|
+
findById: (0, bun_test_1.mock)(function () { return ({ exec: (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
211
|
+
return [2 /*return*/, null];
|
|
212
|
+
}); }); }) }); }),
|
|
213
|
+
modelName: "MockModel",
|
|
214
|
+
};
|
|
215
|
+
middleware = (0, permissions_1.permissionMiddleware)(model, { permissions: allPermissions });
|
|
216
|
+
next = (0, bun_test_1.mock)(function () { });
|
|
217
|
+
return [4 /*yield*/, middleware(buildReq({ method: "GET", params: { id: "507f1f77bcf86cd799439011" } }), {}, next)];
|
|
218
|
+
case 1:
|
|
219
|
+
_b.sent();
|
|
220
|
+
(0, bun_test_1.expect)(captureMessageSpy).toHaveBeenCalledWith("Document 507f1f77bcf86cd799439011 not found for model MockModel");
|
|
221
|
+
_a = __read(next.mock.calls[0], 1), error = _a[0];
|
|
222
|
+
(0, bun_test_1.expect)(error).toBeInstanceOf(errors_1.APIError);
|
|
223
|
+
(0, bun_test_1.expect)(error.status).toBe(404);
|
|
224
|
+
(0, bun_test_1.expect)(error.meta).toBeUndefined();
|
|
225
|
+
captureMessageSpy.mockRestore();
|
|
226
|
+
return [2 /*return*/];
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
}); });
|
|
230
|
+
(0, bun_test_1.it)("returns hidden reason metadata when document is deleted", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
231
|
+
var model, middleware, next, _a, error;
|
|
232
|
+
return __generator(this, function (_b) {
|
|
233
|
+
switch (_b.label) {
|
|
234
|
+
case 0:
|
|
235
|
+
model = {
|
|
236
|
+
collection: { findOne: (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
237
|
+
return [2 /*return*/, ({ deleted: true })];
|
|
238
|
+
}); }); }) },
|
|
239
|
+
findById: (0, bun_test_1.mock)(function () { return ({ exec: (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
240
|
+
return [2 /*return*/, null];
|
|
241
|
+
}); }); }) }); }),
|
|
242
|
+
modelName: "MockModel",
|
|
243
|
+
};
|
|
244
|
+
middleware = (0, permissions_1.permissionMiddleware)(model, { permissions: allPermissions });
|
|
245
|
+
next = (0, bun_test_1.mock)(function () { });
|
|
246
|
+
return [4 /*yield*/, middleware(buildReq({ method: "GET", params: { id: "507f1f77bcf86cd799439011" } }), {}, next)];
|
|
247
|
+
case 1:
|
|
248
|
+
_b.sent();
|
|
249
|
+
_a = __read(next.mock.calls[0], 1), error = _a[0];
|
|
250
|
+
(0, bun_test_1.expect)(error).toBeInstanceOf(errors_1.APIError);
|
|
251
|
+
(0, bun_test_1.expect)(error.status).toBe(404);
|
|
252
|
+
(0, bun_test_1.expect)(error.meta).toEqual({ deleted: "true" });
|
|
253
|
+
(0, bun_test_1.expect)(error.disableExternalErrorTracking).toBe(true);
|
|
254
|
+
return [2 /*return*/];
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
}); });
|
|
258
|
+
(0, bun_test_1.it)("returns hidden reason metadata when document is disabled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
259
|
+
var model, middleware, next, _a, error;
|
|
260
|
+
return __generator(this, function (_b) {
|
|
261
|
+
switch (_b.label) {
|
|
262
|
+
case 0:
|
|
263
|
+
model = {
|
|
264
|
+
collection: { findOne: (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
265
|
+
return [2 /*return*/, ({ disabled: true })];
|
|
266
|
+
}); }); }) },
|
|
267
|
+
findById: (0, bun_test_1.mock)(function () { return ({ exec: (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
268
|
+
return [2 /*return*/, null];
|
|
269
|
+
}); }); }) }); }),
|
|
270
|
+
modelName: "MockModel",
|
|
271
|
+
};
|
|
272
|
+
middleware = (0, permissions_1.permissionMiddleware)(model, { permissions: allPermissions });
|
|
273
|
+
next = (0, bun_test_1.mock)(function () { });
|
|
274
|
+
return [4 /*yield*/, middleware(buildReq({ method: "GET", params: { id: "507f1f77bcf86cd799439011" } }), {}, next)];
|
|
275
|
+
case 1:
|
|
276
|
+
_b.sent();
|
|
277
|
+
_a = __read(next.mock.calls[0], 1), error = _a[0];
|
|
278
|
+
(0, bun_test_1.expect)(error).toBeInstanceOf(errors_1.APIError);
|
|
279
|
+
(0, bun_test_1.expect)(error.status).toBe(404);
|
|
280
|
+
(0, bun_test_1.expect)(error.meta).toEqual({ disabled: "true" });
|
|
281
|
+
(0, bun_test_1.expect)(error.disableExternalErrorTracking).toBe(true);
|
|
282
|
+
return [2 /*return*/];
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
}); });
|
|
286
|
+
(0, bun_test_1.it)("returns hidden reason metadata when document is archived", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
287
|
+
var model, middleware, next, _a, error;
|
|
288
|
+
return __generator(this, function (_b) {
|
|
289
|
+
switch (_b.label) {
|
|
290
|
+
case 0:
|
|
291
|
+
model = {
|
|
292
|
+
collection: { findOne: (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
293
|
+
return [2 /*return*/, ({ archived: true })];
|
|
294
|
+
}); }); }) },
|
|
295
|
+
findById: (0, bun_test_1.mock)(function () { return ({ exec: (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
296
|
+
return [2 /*return*/, null];
|
|
297
|
+
}); }); }) }); }),
|
|
298
|
+
modelName: "MockModel",
|
|
299
|
+
};
|
|
300
|
+
middleware = (0, permissions_1.permissionMiddleware)(model, { permissions: allPermissions });
|
|
301
|
+
next = (0, bun_test_1.mock)(function () { });
|
|
302
|
+
return [4 /*yield*/, middleware(buildReq({ method: "GET", params: { id: "507f1f77bcf86cd799439011" } }), {}, next)];
|
|
303
|
+
case 1:
|
|
304
|
+
_b.sent();
|
|
305
|
+
_a = __read(next.mock.calls[0], 1), error = _a[0];
|
|
306
|
+
(0, bun_test_1.expect)(error).toBeInstanceOf(errors_1.APIError);
|
|
307
|
+
(0, bun_test_1.expect)(error.status).toBe(404);
|
|
308
|
+
(0, bun_test_1.expect)(error.meta).toEqual({ archived: "true" });
|
|
309
|
+
(0, bun_test_1.expect)(error.disableExternalErrorTracking).toBe(true);
|
|
310
|
+
return [2 /*return*/];
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
}); });
|
|
314
|
+
(0, bun_test_1.it)("returns plain not found when hidden document has no reason", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
315
|
+
var model, middleware, next, _a, error;
|
|
316
|
+
return __generator(this, function (_b) {
|
|
317
|
+
switch (_b.label) {
|
|
318
|
+
case 0:
|
|
319
|
+
model = {
|
|
320
|
+
collection: { findOne: (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
321
|
+
return [2 /*return*/, ({ foo: "bar" })];
|
|
322
|
+
}); }); }) },
|
|
323
|
+
findById: (0, bun_test_1.mock)(function () { return ({ exec: (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
324
|
+
return [2 /*return*/, null];
|
|
325
|
+
}); }); }) }); }),
|
|
326
|
+
modelName: "MockModel",
|
|
327
|
+
};
|
|
328
|
+
middleware = (0, permissions_1.permissionMiddleware)(model, { permissions: allPermissions });
|
|
329
|
+
next = (0, bun_test_1.mock)(function () { });
|
|
330
|
+
return [4 /*yield*/, middleware(buildReq({ method: "GET", params: { id: "507f1f77bcf86cd799439011" } }), {}, next)];
|
|
331
|
+
case 1:
|
|
332
|
+
_b.sent();
|
|
333
|
+
_a = __read(next.mock.calls[0], 1), error = _a[0];
|
|
334
|
+
(0, bun_test_1.expect)(error).toBeInstanceOf(errors_1.APIError);
|
|
335
|
+
(0, bun_test_1.expect)(error.status).toBe(404);
|
|
336
|
+
(0, bun_test_1.expect)(error.meta).toBeUndefined();
|
|
337
|
+
return [2 /*return*/];
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
}); });
|
|
341
|
+
});
|
package/dist/syncConsents.js
CHANGED
|
@@ -176,7 +176,7 @@ var syncConsents = function (definitions_1) {
|
|
|
176
176
|
args_1[_i - 1] = arguments[_i];
|
|
177
177
|
}
|
|
178
178
|
return __awaiter(void 0, __spreadArray([definitions_1], __read(args_1), false), void 0, function (definitions, options) {
|
|
179
|
-
var _a, deactivateRemoved, _b, dryRun, result, slugs, activeForms, activeBySlug, slugs_1, slugs_1_1, slug, def, existing, newVersion, e_1_1, activeBySlug_1, activeBySlug_1_1, _c, slug,
|
|
179
|
+
var _a, deactivateRemoved, _b, dryRun, result, slugs, activeForms, activeBySlug, slugs_1, slugs_1_1, slug, def, existing, newVersion, e_1_1, activeBySlug_1, activeBySlug_1_1, _c, slug, e_2_1, summary;
|
|
180
180
|
var e_1, _d, e_2, _e;
|
|
181
181
|
var _f, _g, _h, _j;
|
|
182
182
|
if (options === void 0) { options = {}; }
|
|
@@ -291,7 +291,7 @@ var syncConsents = function (definitions_1) {
|
|
|
291
291
|
_k.label = 16;
|
|
292
292
|
case 16:
|
|
293
293
|
if (!!activeBySlug_1_1.done) return [3 /*break*/, 20];
|
|
294
|
-
_c = __read(activeBySlug_1_1.value,
|
|
294
|
+
_c = __read(activeBySlug_1_1.value, 1), slug = _c[0];
|
|
295
295
|
if (!!definitions[slug]) return [3 /*break*/, 19];
|
|
296
296
|
logger_1.logger.info("syncConsents: deactivating \"".concat(slug, "\""), { dryRun: dryRun });
|
|
297
297
|
if (!!dryRun) return [3 /*break*/, 18];
|
package/dist/tests/bunSetup.js
CHANGED
|
@@ -70,30 +70,35 @@ var mongoose_1 = __importDefault(require("mongoose"));
|
|
|
70
70
|
var winston_1 = __importDefault(require("winston"));
|
|
71
71
|
var expressServer_1 = require("../expressServer");
|
|
72
72
|
var logger_1 = require("../logger");
|
|
73
|
+
var shouldConnectToTestDb = process.env.BUN_TEST_DISABLE_DB !== "true";
|
|
73
74
|
// Connect to MongoDB once for all tests
|
|
74
|
-
|
|
75
|
-
return
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
});
|
|
75
|
+
if (shouldConnectToTestDb) {
|
|
76
|
+
(0, bun_test_1.beforeAll)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
77
|
+
return __generator(this, function (_a) {
|
|
78
|
+
switch (_a.label) {
|
|
79
|
+
case 0: return [4 /*yield*/, mongoose_1.default
|
|
80
|
+
.connect("mongodb://127.0.0.1/terreno?&connectTimeoutMS=360000")
|
|
81
|
+
.catch(logger_1.logger.catch)];
|
|
82
|
+
case 1:
|
|
83
|
+
_a.sent();
|
|
84
|
+
return [2 /*return*/];
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}); });
|
|
88
|
+
}
|
|
86
89
|
// Close MongoDB connection after all tests
|
|
87
|
-
|
|
88
|
-
return
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
});
|
|
90
|
+
if (shouldConnectToTestDb) {
|
|
91
|
+
(0, bun_test_1.afterAll)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
92
|
+
return __generator(this, function (_a) {
|
|
93
|
+
switch (_a.label) {
|
|
94
|
+
case 0: return [4 /*yield*/, mongoose_1.default.connection.close()];
|
|
95
|
+
case 1:
|
|
96
|
+
_a.sent();
|
|
97
|
+
return [2 /*return*/];
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}); });
|
|
101
|
+
}
|
|
97
102
|
var logs = [];
|
|
98
103
|
var SHOW_ALL_LOGS = process.env.SHOW_ALL_TEST_LOGS === "true";
|
|
99
104
|
// Create a custom stream that captures logs
|
package/package.json
CHANGED
|
@@ -310,21 +310,14 @@ describe("expressServer", () => {
|
|
|
310
310
|
);
|
|
311
311
|
});
|
|
312
312
|
|
|
313
|
-
|
|
314
|
-
// schedule to a cron expression but then use the original schedule string.
|
|
315
|
-
// This test documents that current (buggy) behavior.
|
|
316
|
-
it("hourly alias fails due to bug in implementation", () => {
|
|
313
|
+
it("accepts hourly alias", () => {
|
|
317
314
|
const callback = () => {};
|
|
318
|
-
expect(() => cronjob("test-hourly-alias", "hourly", callback)).toThrow(
|
|
319
|
-
"Failed to create cronjob"
|
|
320
|
-
);
|
|
315
|
+
expect(() => cronjob("test-hourly-alias", "hourly", callback)).not.toThrow();
|
|
321
316
|
});
|
|
322
317
|
|
|
323
|
-
it("minutely alias
|
|
318
|
+
it("accepts minutely alias", () => {
|
|
324
319
|
const callback = () => {};
|
|
325
|
-
expect(() => cronjob("test-minutely-alias", "minutely", callback)).toThrow(
|
|
326
|
-
"Failed to create cronjob"
|
|
327
|
-
);
|
|
320
|
+
expect(() => cronjob("test-minutely-alias", "minutely", callback)).not.toThrow();
|
|
328
321
|
});
|
|
329
322
|
});
|
|
330
323
|
|
package/src/expressServer.ts
CHANGED
|
@@ -340,15 +340,11 @@ export function cronjob(
|
|
|
340
340
|
schedule: "hourly" | "minutely" | string,
|
|
341
341
|
callback: () => void
|
|
342
342
|
) {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
} else if (schedule === "minutely") {
|
|
347
|
-
_cronSchedule = "* * * * *";
|
|
348
|
-
}
|
|
349
|
-
logger.info(`Adding cronjob ${name}, running at: ${schedule}`);
|
|
343
|
+
const cronSchedule =
|
|
344
|
+
schedule === "hourly" ? "0 * * * *" : schedule === "minutely" ? "* * * * *" : schedule;
|
|
345
|
+
logger.info(`Adding cronjob ${name}, running at: ${cronSchedule}`);
|
|
350
346
|
try {
|
|
351
|
-
new cron.CronJob(
|
|
347
|
+
new cron.CronJob(cronSchedule, callback, null, true, "America/Chicago");
|
|
352
348
|
} catch (error) {
|
|
353
349
|
throw new Error(`Failed to create cronjob: ${error}`);
|
|
354
350
|
}
|
package/src/openApi.test.ts
CHANGED
|
@@ -11,7 +11,11 @@ import {Permissions} from "./permissions";
|
|
|
11
11
|
import {FoodModel, setupDb, UserModel} from "./tests";
|
|
12
12
|
|
|
13
13
|
function getMessageSummaryOpenApiMiddleware(options: Partial<ModelRouterOptions<any>>): any {
|
|
14
|
-
|
|
14
|
+
if (!options.openApi) {
|
|
15
|
+
throw new Error("Expected openApi to be configured for test routes");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return options.openApi.path({
|
|
15
19
|
parameters: [
|
|
16
20
|
{
|
|
17
21
|
in: "query",
|
package/src/openApiEtag.test.ts
CHANGED
|
@@ -61,6 +61,17 @@ describe("openApiEtagMiddleware", () => {
|
|
|
61
61
|
expect(res.json).toBe(originalJson);
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
+
it("skips GET requests for non-openapi.json paths", () => {
|
|
65
|
+
const req = buildRequest({method: "GET", path: "/health"});
|
|
66
|
+
const {res, originalJson} = buildResponse();
|
|
67
|
+
const next = mock(() => {}) as NextFunction;
|
|
68
|
+
|
|
69
|
+
openApiEtagMiddleware(req, res, next);
|
|
70
|
+
|
|
71
|
+
expect(next).toHaveBeenCalledTimes(1);
|
|
72
|
+
expect(res.json).toBe(originalJson);
|
|
73
|
+
});
|
|
74
|
+
|
|
64
75
|
it("sets ETag and returns json body when no matching If-None-Match header is provided", () => {
|
|
65
76
|
const req = buildRequest();
|
|
66
77
|
const {res, originalJson, set, status, end} = buildResponse();
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import {describe, expect, it, mock, spyOn} from "bun:test";
|
|
2
|
+
import * as Sentry from "@sentry/bun";
|
|
3
|
+
import type express from "express";
|
|
4
|
+
|
|
5
|
+
import {APIError} from "./errors";
|
|
6
|
+
import {Permissions, permissionMiddleware} from "./permissions";
|
|
7
|
+
|
|
8
|
+
describe("permissionMiddleware", () => {
|
|
9
|
+
const allPermissions = {
|
|
10
|
+
create: [Permissions.IsAny],
|
|
11
|
+
delete: [Permissions.IsAny],
|
|
12
|
+
list: [Permissions.IsAny],
|
|
13
|
+
read: [Permissions.IsAny],
|
|
14
|
+
update: [Permissions.IsAny],
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const buildReq = (overrides: Record<string, unknown> = {}): express.Request => {
|
|
18
|
+
return {
|
|
19
|
+
method: "GET",
|
|
20
|
+
params: {},
|
|
21
|
+
user: {id: "user-1"},
|
|
22
|
+
...overrides,
|
|
23
|
+
} as unknown as express.Request;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
it("calls next immediately for OPTIONS requests", async () => {
|
|
27
|
+
const model = {
|
|
28
|
+
collection: {findOne: mock(async () => null)},
|
|
29
|
+
findById: mock(() => ({exec: mock(async () => null)})),
|
|
30
|
+
modelName: "MockModel",
|
|
31
|
+
} as any;
|
|
32
|
+
const middleware = permissionMiddleware(model, {permissions: allPermissions});
|
|
33
|
+
const next = mock(() => {});
|
|
34
|
+
|
|
35
|
+
await middleware(buildReq({method: "OPTIONS"}), {} as express.Response, next as any);
|
|
36
|
+
|
|
37
|
+
expect(next).toHaveBeenCalledTimes(1);
|
|
38
|
+
expect((next as any).mock.calls[0]).toEqual([]);
|
|
39
|
+
expect(model.findById).toHaveBeenCalledTimes(0);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("returns APIError for unsupported HTTP methods", async () => {
|
|
43
|
+
const model = {
|
|
44
|
+
collection: {findOne: mock(async () => null)},
|
|
45
|
+
findById: mock(() => ({exec: mock(async () => null)})),
|
|
46
|
+
modelName: "MockModel",
|
|
47
|
+
} as any;
|
|
48
|
+
const middleware = permissionMiddleware(model, {permissions: allPermissions});
|
|
49
|
+
const next = mock(() => {});
|
|
50
|
+
|
|
51
|
+
await middleware(buildReq({method: "TRACE"}), {} as express.Response, next as any);
|
|
52
|
+
|
|
53
|
+
expect(next).toHaveBeenCalledTimes(1);
|
|
54
|
+
const [error] = (next as any).mock.calls[0];
|
|
55
|
+
expect(error).toBeInstanceOf(APIError);
|
|
56
|
+
expect(error.status).toBe(405);
|
|
57
|
+
expect(error.title).toContain("Method TRACE not allowed");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("wraps query execution failures in a 500 APIError", async () => {
|
|
61
|
+
const exec = mock(async () => {
|
|
62
|
+
throw new Error("query failed");
|
|
63
|
+
});
|
|
64
|
+
const model = {
|
|
65
|
+
collection: {findOne: mock(async () => null)},
|
|
66
|
+
findById: mock(() => ({exec})),
|
|
67
|
+
modelName: "MockModel",
|
|
68
|
+
} as any;
|
|
69
|
+
const middleware = permissionMiddleware(model, {permissions: allPermissions});
|
|
70
|
+
const next = mock(() => {});
|
|
71
|
+
|
|
72
|
+
await middleware(
|
|
73
|
+
buildReq({method: "GET", params: {id: "507f1f77bcf86cd799439011"}}),
|
|
74
|
+
{} as express.Response,
|
|
75
|
+
next as any
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
expect(exec).toHaveBeenCalledTimes(1);
|
|
79
|
+
const [error] = (next as any).mock.calls[0];
|
|
80
|
+
expect(error).toBeInstanceOf(APIError);
|
|
81
|
+
expect(error.status).toBe(500);
|
|
82
|
+
expect(error.title).toContain("GET failed on 507f1f77bcf86cd799439011");
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("captures sentry message when document does not exist", async () => {
|
|
86
|
+
const captureMessageSpy = spyOn(Sentry, "captureMessage");
|
|
87
|
+
const model = {
|
|
88
|
+
collection: {findOne: mock(async () => null)},
|
|
89
|
+
findById: mock(() => ({exec: mock(async () => null)})),
|
|
90
|
+
modelName: "MockModel",
|
|
91
|
+
} as any;
|
|
92
|
+
const middleware = permissionMiddleware(model, {permissions: allPermissions});
|
|
93
|
+
const next = mock(() => {});
|
|
94
|
+
|
|
95
|
+
await middleware(
|
|
96
|
+
buildReq({method: "GET", params: {id: "507f1f77bcf86cd799439011"}}),
|
|
97
|
+
{} as express.Response,
|
|
98
|
+
next as any
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
expect(captureMessageSpy).toHaveBeenCalledWith(
|
|
102
|
+
"Document 507f1f77bcf86cd799439011 not found for model MockModel"
|
|
103
|
+
);
|
|
104
|
+
const [error] = (next as any).mock.calls[0];
|
|
105
|
+
expect(error).toBeInstanceOf(APIError);
|
|
106
|
+
expect(error.status).toBe(404);
|
|
107
|
+
expect(error.meta).toBeUndefined();
|
|
108
|
+
captureMessageSpy.mockRestore();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("returns hidden reason metadata when document is deleted", async () => {
|
|
112
|
+
const model = {
|
|
113
|
+
collection: {findOne: mock(async () => ({deleted: true}))},
|
|
114
|
+
findById: mock(() => ({exec: mock(async () => null)})),
|
|
115
|
+
modelName: "MockModel",
|
|
116
|
+
} as any;
|
|
117
|
+
const middleware = permissionMiddleware(model, {permissions: allPermissions});
|
|
118
|
+
const next = mock(() => {});
|
|
119
|
+
|
|
120
|
+
await middleware(
|
|
121
|
+
buildReq({method: "GET", params: {id: "507f1f77bcf86cd799439011"}}),
|
|
122
|
+
{} as express.Response,
|
|
123
|
+
next as any
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
const [error] = (next as any).mock.calls[0];
|
|
127
|
+
expect(error).toBeInstanceOf(APIError);
|
|
128
|
+
expect(error.status).toBe(404);
|
|
129
|
+
expect(error.meta).toEqual({deleted: "true"});
|
|
130
|
+
expect(error.disableExternalErrorTracking).toBe(true);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("returns hidden reason metadata when document is disabled", async () => {
|
|
134
|
+
const model = {
|
|
135
|
+
collection: {findOne: mock(async () => ({disabled: true}))},
|
|
136
|
+
findById: mock(() => ({exec: mock(async () => null)})),
|
|
137
|
+
modelName: "MockModel",
|
|
138
|
+
} as any;
|
|
139
|
+
const middleware = permissionMiddleware(model, {permissions: allPermissions});
|
|
140
|
+
const next = mock(() => {});
|
|
141
|
+
|
|
142
|
+
await middleware(
|
|
143
|
+
buildReq({method: "GET", params: {id: "507f1f77bcf86cd799439011"}}),
|
|
144
|
+
{} as express.Response,
|
|
145
|
+
next as any
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
const [error] = (next as any).mock.calls[0];
|
|
149
|
+
expect(error).toBeInstanceOf(APIError);
|
|
150
|
+
expect(error.status).toBe(404);
|
|
151
|
+
expect(error.meta).toEqual({disabled: "true"});
|
|
152
|
+
expect(error.disableExternalErrorTracking).toBe(true);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("returns hidden reason metadata when document is archived", async () => {
|
|
156
|
+
const model = {
|
|
157
|
+
collection: {findOne: mock(async () => ({archived: true}))},
|
|
158
|
+
findById: mock(() => ({exec: mock(async () => null)})),
|
|
159
|
+
modelName: "MockModel",
|
|
160
|
+
} as any;
|
|
161
|
+
const middleware = permissionMiddleware(model, {permissions: allPermissions});
|
|
162
|
+
const next = mock(() => {});
|
|
163
|
+
|
|
164
|
+
await middleware(
|
|
165
|
+
buildReq({method: "GET", params: {id: "507f1f77bcf86cd799439011"}}),
|
|
166
|
+
{} as express.Response,
|
|
167
|
+
next as any
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
const [error] = (next as any).mock.calls[0];
|
|
171
|
+
expect(error).toBeInstanceOf(APIError);
|
|
172
|
+
expect(error.status).toBe(404);
|
|
173
|
+
expect(error.meta).toEqual({archived: "true"});
|
|
174
|
+
expect(error.disableExternalErrorTracking).toBe(true);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("returns plain not found when hidden document has no reason", async () => {
|
|
178
|
+
const model = {
|
|
179
|
+
collection: {findOne: mock(async () => ({foo: "bar"}))},
|
|
180
|
+
findById: mock(() => ({exec: mock(async () => null)})),
|
|
181
|
+
modelName: "MockModel",
|
|
182
|
+
} as any;
|
|
183
|
+
const middleware = permissionMiddleware(model, {permissions: allPermissions});
|
|
184
|
+
const next = mock(() => {});
|
|
185
|
+
|
|
186
|
+
await middleware(
|
|
187
|
+
buildReq({method: "GET", params: {id: "507f1f77bcf86cd799439011"}}),
|
|
188
|
+
{} as express.Response,
|
|
189
|
+
next as any
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
const [error] = (next as any).mock.calls[0];
|
|
193
|
+
expect(error).toBeInstanceOf(APIError);
|
|
194
|
+
expect(error.status).toBe(404);
|
|
195
|
+
expect(error.meta).toBeUndefined();
|
|
196
|
+
});
|
|
197
|
+
});
|
package/src/syncConsents.ts
CHANGED
|
@@ -237,7 +237,7 @@ export const syncConsents = async (
|
|
|
237
237
|
|
|
238
238
|
// Deactivate forms that are no longer in definitions
|
|
239
239
|
if (deactivateRemoved) {
|
|
240
|
-
for (const [slug
|
|
240
|
+
for (const [slug] of activeBySlug) {
|
|
241
241
|
if (!definitions[slug]) {
|
|
242
242
|
logger.info(`syncConsents: deactivating "${slug}"`, {dryRun});
|
|
243
243
|
if (!dryRun) {
|
package/src/tests/bunSetup.ts
CHANGED
|
@@ -6,17 +6,23 @@ import winston from "winston";
|
|
|
6
6
|
import {setupEnvironment} from "../expressServer";
|
|
7
7
|
import {logger, winstonLogger} from "../logger";
|
|
8
8
|
|
|
9
|
+
const shouldConnectToTestDb = process.env.BUN_TEST_DISABLE_DB !== "true";
|
|
10
|
+
|
|
9
11
|
// Connect to MongoDB once for all tests
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
if (shouldConnectToTestDb) {
|
|
13
|
+
beforeAll(async () => {
|
|
14
|
+
await mongoose
|
|
15
|
+
.connect("mongodb://127.0.0.1/terreno?&connectTimeoutMS=360000")
|
|
16
|
+
.catch(logger.catch);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
15
19
|
|
|
16
20
|
// Close MongoDB connection after all tests
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
if (shouldConnectToTestDb) {
|
|
22
|
+
afterAll(async () => {
|
|
23
|
+
await mongoose.connection.close();
|
|
24
|
+
});
|
|
25
|
+
}
|
|
20
26
|
|
|
21
27
|
let logs: string[] = [];
|
|
22
28
|
|