@joystick.js/node-canary 0.0.0-canary.7 → 0.0.0-canary.71
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/_package.json +2 -1
- package/dist/app/accounts/createMetadataTableColumns.js +12 -0
- package/dist/app/accounts/deleteUser.js +7 -0
- package/dist/app/accounts/generateSession.js +2 -4
- package/dist/app/accounts/getBrowserSafeUser.js +2 -1
- package/dist/app/accounts/hasLoginTokenExpired.js +1 -2
- package/dist/app/accounts/index.js +2 -0
- package/dist/app/accounts/signup.js +30 -4
- package/dist/app/databases/mongodb/index.js +1 -1
- package/dist/app/databases/mongodb/queries/accounts.js +7 -0
- package/dist/app/databases/postgresql/queries/accounts.js +3 -0
- package/dist/app/databases/stringToSnakeCase.js +6 -0
- package/dist/app/getBrowserSafeRequest.js +3 -2
- package/dist/app/index.js +66 -12
- package/dist/app/middleware/getTranslations.js +64 -0
- package/dist/app/middleware/index.js +4 -5
- package/dist/app/middleware/render.js +11 -68
- package/dist/app/sanitizeAPIResponse.js +1 -6
- package/dist/app/validateSession.js +3 -0
- package/dist/email/templates/reset-password.js +0 -1
- package/dist/index.js +7 -2
- package/dist/lib/escapeHTML.js +9 -0
- package/dist/lib/escapeKeyValuePair.js +13 -0
- package/dist/lib/getBuildPath.js +1 -1
- package/dist/lib/getSSLCertificates.js +1 -1
- package/dist/lib/importFile.js +7 -0
- package/dist/lib/log.js +0 -3
- package/dist/lib/nodeUrlPolyfills.js +7 -14
- package/dist/ssr/getAPIForDataFunctions.js +33 -0
- package/dist/ssr/getDataFromComponent.js +14 -0
- package/dist/ssr/index.js +5 -41
- package/package.json +2 -1
- package/dist/app/accounts/roles/index.test.js +0 -123
- package/dist/app/index.test.js +0 -575
- package/dist/app/middleware/sanitizeQueryParameters.js +0 -16
- package/dist/email/send.test.js +0 -37
package/dist/app/index.test.js
DELETED
|
@@ -1,575 +0,0 @@
|
|
|
1
|
-
import { afterAll, afterEach, beforeAll, expect, jest, test } from "@jest/globals";
|
|
2
|
-
import { mockRequest, mockResponse } from "jest-mock-req-res";
|
|
3
|
-
import { killPortProcess } from "kill-port-process";
|
|
4
|
-
import assertRoutesDoNotExistInRegexes from "../tests/lib/assertRoutesDoNotExistInRegexes";
|
|
5
|
-
import assertRoutesExistInRegexes from "../tests/lib/assertRoutesExistInRegexes";
|
|
6
|
-
import setAppSettingsForTest from "../tests/lib/setAppSettingsForTest";
|
|
7
|
-
import startTestDatabase from "../tests/lib/databases/start";
|
|
8
|
-
import stopTestDatabase from "../tests/lib/databases/stop";
|
|
9
|
-
import getRouteRegexes from "../tests/lib/getRouteRegexes";
|
|
10
|
-
jest.mock("../../node_modules/crypto-extra", () => {
|
|
11
|
-
return {
|
|
12
|
-
randomString: () => "abc1234"
|
|
13
|
-
};
|
|
14
|
-
});
|
|
15
|
-
jest.mock("../../node_modules/bcrypt", () => {
|
|
16
|
-
return {
|
|
17
|
-
hashSync: () => "hashed$password",
|
|
18
|
-
compareSync: () => {
|
|
19
|
-
return true;
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
});
|
|
23
|
-
jest.mock("../../node_modules/dayjs", () => {
|
|
24
|
-
const _dayjs = jest.requireActual("../../node_modules/dayjs");
|
|
25
|
-
const _utc = jest.requireActual("../../node_modules/dayjs/plugin/utc");
|
|
26
|
-
_dayjs.extend(_utc);
|
|
27
|
-
return () => _dayjs("2022-01-01T00:00:00.000Z");
|
|
28
|
-
});
|
|
29
|
-
const nodemailer = {
|
|
30
|
-
smtp: {
|
|
31
|
-
sendMail: jest.fn()
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
jest.mock("../../node_modules/nodemailer", () => {
|
|
35
|
-
return {
|
|
36
|
-
createTransport: jest.fn(() => {
|
|
37
|
-
return {
|
|
38
|
-
sendMail: nodemailer.smtp.sendMail
|
|
39
|
-
};
|
|
40
|
-
})
|
|
41
|
-
};
|
|
42
|
-
});
|
|
43
|
-
jest.mock("../../node_modules/@joystick.js/ui/dist/component/generateId.js", () => {
|
|
44
|
-
return "component1234";
|
|
45
|
-
});
|
|
46
|
-
setAppSettingsForTest({
|
|
47
|
-
"config": {
|
|
48
|
-
"databases": [
|
|
49
|
-
{
|
|
50
|
-
"provider": "mongodb",
|
|
51
|
-
"users": true,
|
|
52
|
-
"options": {}
|
|
53
|
-
}
|
|
54
|
-
],
|
|
55
|
-
"i18n": {
|
|
56
|
-
"defaultLanguage": "en-US"
|
|
57
|
-
},
|
|
58
|
-
"middleware": {},
|
|
59
|
-
"email": {
|
|
60
|
-
"from": "app@test.com",
|
|
61
|
-
"smtp": {
|
|
62
|
-
"host": "fake.email.com",
|
|
63
|
-
"port": 587,
|
|
64
|
-
"username": "test",
|
|
65
|
-
"password": "password"
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
"global": {},
|
|
70
|
-
"public": {},
|
|
71
|
-
"private": {}
|
|
72
|
-
});
|
|
73
|
-
const dayjs = (await import("dayjs")).default;
|
|
74
|
-
const app = (await import("./index")).default;
|
|
75
|
-
const generateId = (await import("../lib/generateId")).default;
|
|
76
|
-
global.joystick = {
|
|
77
|
-
settings: {
|
|
78
|
-
config: {
|
|
79
|
-
databases: [{
|
|
80
|
-
"provider": "mongodb",
|
|
81
|
-
"users": true,
|
|
82
|
-
"options": {}
|
|
83
|
-
}]
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
describe("index.js", () => {
|
|
88
|
-
beforeAll(async () => {
|
|
89
|
-
process.env.PORT = 3600;
|
|
90
|
-
await startTestDatabase("mongodb");
|
|
91
|
-
});
|
|
92
|
-
afterEach(async () => {
|
|
93
|
-
await killPortProcess(process.env.PORT);
|
|
94
|
-
});
|
|
95
|
-
afterAll(async () => {
|
|
96
|
-
await stopTestDatabase();
|
|
97
|
-
});
|
|
98
|
-
test("registers render-related routes", async () => {
|
|
99
|
-
const instance = await app({});
|
|
100
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
101
|
-
instance.server.close();
|
|
102
|
-
}
|
|
103
|
-
if (instance?.app?._router) {
|
|
104
|
-
const routeRegexes = getRouteRegexes(instance.app._router.stack);
|
|
105
|
-
assertRoutesExistInRegexes(routeRegexes, [
|
|
106
|
-
"/_joystick/heartbeat",
|
|
107
|
-
"/_joystick/utils/process.js",
|
|
108
|
-
"/_joystick/index.client.js",
|
|
109
|
-
"/_joystick/index.css",
|
|
110
|
-
"/_joystick/ui",
|
|
111
|
-
"/_joystick/hmr/client.js"
|
|
112
|
-
]);
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
test("registers accounts-related routes", async () => {
|
|
116
|
-
const instance = await app({});
|
|
117
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
118
|
-
instance.server.close();
|
|
119
|
-
}
|
|
120
|
-
if (instance?.app?._router) {
|
|
121
|
-
const routeRegexes = getRouteRegexes(instance.app._router.stack);
|
|
122
|
-
assertRoutesExistInRegexes(routeRegexes, [
|
|
123
|
-
"/api/_accounts/login",
|
|
124
|
-
"/api/_accounts/logout",
|
|
125
|
-
"/api/_accounts/signup",
|
|
126
|
-
"/api/_accounts/recover-password",
|
|
127
|
-
"/api/_accounts/reset-password"
|
|
128
|
-
]);
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
test("registers getter routes", async () => {
|
|
132
|
-
const instance = await app({
|
|
133
|
-
api: {
|
|
134
|
-
getters: {
|
|
135
|
-
posts: {
|
|
136
|
-
input: {},
|
|
137
|
-
get: () => {
|
|
138
|
-
}
|
|
139
|
-
},
|
|
140
|
-
post: {
|
|
141
|
-
input: {},
|
|
142
|
-
get: () => {
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
149
|
-
instance.server.close();
|
|
150
|
-
}
|
|
151
|
-
if (instance?.app?._router) {
|
|
152
|
-
const routeRegexes = getRouteRegexes(instance.app._router.stack);
|
|
153
|
-
assertRoutesExistInRegexes(routeRegexes, [
|
|
154
|
-
"/api/_getters/posts",
|
|
155
|
-
"/api/_getters/post"
|
|
156
|
-
]);
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
test("registers setter routes", async () => {
|
|
160
|
-
const instance = await app({
|
|
161
|
-
api: {
|
|
162
|
-
setters: {
|
|
163
|
-
createPost: {
|
|
164
|
-
input: {},
|
|
165
|
-
set: () => {
|
|
166
|
-
}
|
|
167
|
-
},
|
|
168
|
-
updatePost: {
|
|
169
|
-
input: {},
|
|
170
|
-
set: () => {
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
177
|
-
instance.server.close();
|
|
178
|
-
}
|
|
179
|
-
if (instance?.app?._router) {
|
|
180
|
-
const routeRegexes = getRouteRegexes(instance.app._router.stack);
|
|
181
|
-
assertRoutesExistInRegexes(routeRegexes, [
|
|
182
|
-
"/api/_setters/createPost",
|
|
183
|
-
"/api/_setters/updatePost"
|
|
184
|
-
]);
|
|
185
|
-
}
|
|
186
|
-
});
|
|
187
|
-
test("registers custom routes if passed as function", async () => {
|
|
188
|
-
const instance = await app({
|
|
189
|
-
routes: {
|
|
190
|
-
"/latest": () => {
|
|
191
|
-
},
|
|
192
|
-
"/profile/:_id": () => {
|
|
193
|
-
},
|
|
194
|
-
"/category/:category/posts": () => {
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
if (instance?.app?._router) {
|
|
199
|
-
const routeRegexes = getRouteRegexes(instance.app._router.stack);
|
|
200
|
-
assertRoutesExistInRegexes(routeRegexes, [
|
|
201
|
-
"/latest",
|
|
202
|
-
"/profile/123",
|
|
203
|
-
"/category/tutorials/posts"
|
|
204
|
-
]);
|
|
205
|
-
}
|
|
206
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
207
|
-
instance.server.close();
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
test("does not register custom routes if passed as function not set to a function", async () => {
|
|
211
|
-
const instance = await app({
|
|
212
|
-
routes: {
|
|
213
|
-
"/latest": "function",
|
|
214
|
-
"/profile/:_id": "function",
|
|
215
|
-
"/category/:category/posts": "function"
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
if (instance?.app?._router) {
|
|
219
|
-
const routeRegexes = getRouteRegexes(instance.app._router.stack);
|
|
220
|
-
assertRoutesDoNotExistInRegexes(routeRegexes, [
|
|
221
|
-
"/latest",
|
|
222
|
-
"/profile/123",
|
|
223
|
-
"/category/tutorials/posts"
|
|
224
|
-
]);
|
|
225
|
-
}
|
|
226
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
227
|
-
instance.server.close();
|
|
228
|
-
}
|
|
229
|
-
});
|
|
230
|
-
test("registers custom routes if passed as an object", async () => {
|
|
231
|
-
const instance = await app({
|
|
232
|
-
routes: {
|
|
233
|
-
"/latest": {
|
|
234
|
-
method: "GET",
|
|
235
|
-
handler: () => {
|
|
236
|
-
}
|
|
237
|
-
},
|
|
238
|
-
"/profile/:_id": {
|
|
239
|
-
method: "POST",
|
|
240
|
-
handler: () => {
|
|
241
|
-
}
|
|
242
|
-
},
|
|
243
|
-
"/category/:category/posts": {
|
|
244
|
-
method: "PUT",
|
|
245
|
-
handler: () => {
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
251
|
-
instance.server.close();
|
|
252
|
-
}
|
|
253
|
-
if (instance?.app?._router) {
|
|
254
|
-
const routeRegexes = getRouteRegexes(instance.app._router.stack);
|
|
255
|
-
assertRoutesExistInRegexes(routeRegexes, [
|
|
256
|
-
"/latest",
|
|
257
|
-
"/profile/123",
|
|
258
|
-
"/category/tutorials/posts"
|
|
259
|
-
]);
|
|
260
|
-
}
|
|
261
|
-
});
|
|
262
|
-
test("does not register custom routes if passed as an object without a valid method", async () => {
|
|
263
|
-
const instance = await app({
|
|
264
|
-
routes: {
|
|
265
|
-
"/latest": {
|
|
266
|
-
method: "CAT"
|
|
267
|
-
},
|
|
268
|
-
"/profile/:_id": {
|
|
269
|
-
handler: () => {
|
|
270
|
-
}
|
|
271
|
-
},
|
|
272
|
-
"/category/:category/posts": {
|
|
273
|
-
method: "PUT",
|
|
274
|
-
handler: () => {
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
});
|
|
279
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
280
|
-
instance.server.close();
|
|
281
|
-
}
|
|
282
|
-
if (instance?.app?._router) {
|
|
283
|
-
const routeRegexes = getRouteRegexes(instance.app._router.stack);
|
|
284
|
-
assertRoutesDoNotExistInRegexes(routeRegexes, [
|
|
285
|
-
"/latest",
|
|
286
|
-
"/profile/123"
|
|
287
|
-
]);
|
|
288
|
-
assertRoutesExistInRegexes(routeRegexes, [
|
|
289
|
-
"/category/tutorials/posts"
|
|
290
|
-
]);
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
test("does not register custom routes if passed as an object without a handler function", async () => {
|
|
294
|
-
const instance = await app({
|
|
295
|
-
routes: {
|
|
296
|
-
"/latest": {
|
|
297
|
-
method: "GET"
|
|
298
|
-
},
|
|
299
|
-
"/profile/:_id": {
|
|
300
|
-
method: "POST"
|
|
301
|
-
},
|
|
302
|
-
"/category/:category/posts": {
|
|
303
|
-
method: "PUT"
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
});
|
|
307
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
308
|
-
instance.server.close();
|
|
309
|
-
}
|
|
310
|
-
if (instance?.app?._router) {
|
|
311
|
-
const routeRegexes = getRouteRegexes(instance.app._router.stack);
|
|
312
|
-
assertRoutesDoNotExistInRegexes(routeRegexes, [
|
|
313
|
-
"/latest",
|
|
314
|
-
"/profile/123",
|
|
315
|
-
"/category/tutorials/posts"
|
|
316
|
-
]);
|
|
317
|
-
}
|
|
318
|
-
});
|
|
319
|
-
test("sets build errors on process", async () => {
|
|
320
|
-
const instance = await app({});
|
|
321
|
-
const testMessage = { id: generateId() };
|
|
322
|
-
process.emit("message", JSON.stringify(testMessage));
|
|
323
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
324
|
-
instance.server.close();
|
|
325
|
-
}
|
|
326
|
-
expect(process.BUILD_ERROR).toEqual(testMessage);
|
|
327
|
-
});
|
|
328
|
-
test("if callback function is assigned to function-based route, it is called as expected", async () => {
|
|
329
|
-
const instance = await app({
|
|
330
|
-
routes: {
|
|
331
|
-
"/test": (req2, res2) => {
|
|
332
|
-
res2.status(200).send("Called as expected.");
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
});
|
|
336
|
-
const route = instance?.app?._router?.stack.find((stackItem) => {
|
|
337
|
-
return stackItem?.route?.path === "/test";
|
|
338
|
-
});
|
|
339
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
340
|
-
instance.server.close();
|
|
341
|
-
}
|
|
342
|
-
const req = mockRequest();
|
|
343
|
-
const res = mockResponse();
|
|
344
|
-
const handler = route?.route?.stack[0] && route?.route?.stack[0].handle;
|
|
345
|
-
if (handler) {
|
|
346
|
-
await handler(req, res, () => {
|
|
347
|
-
});
|
|
348
|
-
expect(res.status).toHaveBeenCalledWith(200);
|
|
349
|
-
expect(res.send).toHaveBeenCalledWith("Called as expected.");
|
|
350
|
-
}
|
|
351
|
-
});
|
|
352
|
-
test("if callback function is assigned to an object-based route, it is called as expected", async () => {
|
|
353
|
-
const instance = await app({
|
|
354
|
-
routes: {
|
|
355
|
-
"/test": {
|
|
356
|
-
method: "GET",
|
|
357
|
-
handler: (req2, res2) => {
|
|
358
|
-
res2.status(200).send("Called as expected.");
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
});
|
|
363
|
-
const route = instance?.app?._router?.stack.find((stackItem) => {
|
|
364
|
-
return stackItem?.route?.path === "/test";
|
|
365
|
-
});
|
|
366
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
367
|
-
instance.server.close();
|
|
368
|
-
}
|
|
369
|
-
const req = mockRequest();
|
|
370
|
-
const res = mockResponse();
|
|
371
|
-
const handler = route?.route?.stack[0] && route?.route?.stack[0].handle;
|
|
372
|
-
if (handler) {
|
|
373
|
-
await handler(req, res, () => {
|
|
374
|
-
});
|
|
375
|
-
expect(res.status).toHaveBeenCalledWith(200);
|
|
376
|
-
expect(res.send).toHaveBeenCalledWith("Called as expected.");
|
|
377
|
-
}
|
|
378
|
-
});
|
|
379
|
-
test("verify that a /_accounts/authenticated request will return true if passed a valid cookie", async () => {
|
|
380
|
-
const instance = await app({});
|
|
381
|
-
const route = instance?.app?._router?.stack.find((stackItem) => {
|
|
382
|
-
return stackItem?.route?.path === "/api/_accounts/authenticated";
|
|
383
|
-
});
|
|
384
|
-
const req = mockRequest({
|
|
385
|
-
cookies: {
|
|
386
|
-
joystickLoginToken: "testToken123",
|
|
387
|
-
joystickLoginTokenExpiresAt: dayjs().add(1, "minute").format()
|
|
388
|
-
}
|
|
389
|
-
});
|
|
390
|
-
const res = mockResponse();
|
|
391
|
-
const handler = route?.route?.stack[0] && route?.route?.stack[0].handle;
|
|
392
|
-
if (handler) {
|
|
393
|
-
await handler(req, res, () => {
|
|
394
|
-
});
|
|
395
|
-
expect(res.status).toHaveBeenCalledWith(200);
|
|
396
|
-
expect(res.send).toHaveBeenCalledWith('{"status":200,"authenticated":true}');
|
|
397
|
-
}
|
|
398
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
399
|
-
instance.server.close();
|
|
400
|
-
}
|
|
401
|
-
});
|
|
402
|
-
test("verify that a /_accounts/authenticated request will return false if passed an invalid cookie", async () => {
|
|
403
|
-
const instance = await app({});
|
|
404
|
-
const route = instance?.app?._router?.stack.find((stackItem) => {
|
|
405
|
-
return stackItem?.route?.path === "/api/_accounts/authenticated";
|
|
406
|
-
});
|
|
407
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
408
|
-
instance.server.close();
|
|
409
|
-
}
|
|
410
|
-
const req = mockRequest({
|
|
411
|
-
cookies: {
|
|
412
|
-
joystickLoginToken: "testToken123",
|
|
413
|
-
joystickLoginTokenExpiresAt: jest.requireActual("../../node_modules/dayjs")().subtract(1, "minute").format()
|
|
414
|
-
}
|
|
415
|
-
});
|
|
416
|
-
const res = mockResponse();
|
|
417
|
-
const handler = route?.route?.stack[0] && route?.route?.stack[0].handle;
|
|
418
|
-
if (handler) {
|
|
419
|
-
await handler(req, res, () => {
|
|
420
|
-
});
|
|
421
|
-
expect(res.status).toHaveBeenCalledWith(401);
|
|
422
|
-
expect(res.send).toHaveBeenCalledWith('{"status":401,"authenticated":false}');
|
|
423
|
-
}
|
|
424
|
-
});
|
|
425
|
-
test("verify that a /_accounts/signup request will set a cookie and return a user if passed a valid signup request", async () => {
|
|
426
|
-
const instance = await app({});
|
|
427
|
-
const route = instance?.app?._router?.stack.find((stackItem) => {
|
|
428
|
-
return stackItem?.route?.path === "/api/_accounts/signup";
|
|
429
|
-
});
|
|
430
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
431
|
-
instance.server.close();
|
|
432
|
-
}
|
|
433
|
-
const req = mockRequest({
|
|
434
|
-
body: {
|
|
435
|
-
emailAddress: "test@test.com",
|
|
436
|
-
password: "password",
|
|
437
|
-
metadata: {}
|
|
438
|
-
}
|
|
439
|
-
});
|
|
440
|
-
const res = mockResponse();
|
|
441
|
-
const handler = route?.route?.stack[0] && route?.route?.stack[0].handle;
|
|
442
|
-
if (handler) {
|
|
443
|
-
await handler(req, res, () => {
|
|
444
|
-
});
|
|
445
|
-
expect(res.cookie).toHaveBeenCalledWith("joystickLoginToken", "abc1234", { secure: true, httpOnly: true, expires: dayjs().toDate() });
|
|
446
|
-
expect(res.cookie).toHaveBeenCalledWith("joystickLoginTokenExpiresAt", "2022-01-31T00:00:00Z", { secure: true, httpOnly: true, expires: dayjs().toDate() });
|
|
447
|
-
expect(res.status).toHaveBeenCalledWith(200);
|
|
448
|
-
expect(res.send).toHaveBeenCalledWith('{"_id":"abc1234","password":"hashed$password","emailAddress":"test@test.com"}');
|
|
449
|
-
}
|
|
450
|
-
});
|
|
451
|
-
test("verify that a /_accounts/login request will set a cookie and return a user if passed a valid login request", async () => {
|
|
452
|
-
const instance = await app({});
|
|
453
|
-
const route = instance?.app?._router?.stack.find((stackItem) => {
|
|
454
|
-
return stackItem?.route?.path === "/api/_accounts/login";
|
|
455
|
-
});
|
|
456
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
457
|
-
instance.server.close();
|
|
458
|
-
}
|
|
459
|
-
const req = mockRequest({
|
|
460
|
-
body: {
|
|
461
|
-
emailAddress: "test@test.com",
|
|
462
|
-
password: "password"
|
|
463
|
-
}
|
|
464
|
-
});
|
|
465
|
-
const res = mockResponse();
|
|
466
|
-
const handler = route?.route?.stack[0] && route?.route?.stack[0].handle;
|
|
467
|
-
if (handler) {
|
|
468
|
-
await handler(req, res, () => {
|
|
469
|
-
});
|
|
470
|
-
expect(res.cookie).toHaveBeenCalledWith("joystickLoginToken", "abc1234", { secure: true, httpOnly: true, expires: dayjs().toDate() });
|
|
471
|
-
expect(res.cookie).toHaveBeenCalledWith("joystickLoginTokenExpiresAt", "2022-01-31T00:00:00Z", { secure: true, httpOnly: true, expires: dayjs().toDate() });
|
|
472
|
-
expect(res.status).toHaveBeenCalledWith(200);
|
|
473
|
-
expect(res.send).toHaveBeenCalledWith('{"_id":"abc1234","emailAddress":"test@test.com"}');
|
|
474
|
-
}
|
|
475
|
-
});
|
|
476
|
-
test("verify that a /_accounts/logout request deletes the cookie", async () => {
|
|
477
|
-
const instance = await app({});
|
|
478
|
-
const loginRoute = instance?.app?._router?.stack.find((stackItem) => {
|
|
479
|
-
return stackItem?.route?.path === "/api/_accounts/login";
|
|
480
|
-
});
|
|
481
|
-
const logoutRoute = instance?.app?._router?.stack.find((stackItem) => {
|
|
482
|
-
return stackItem?.route?.path === "/api/_accounts/logout";
|
|
483
|
-
});
|
|
484
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
485
|
-
instance.server.close();
|
|
486
|
-
}
|
|
487
|
-
const loginRequest = mockRequest({
|
|
488
|
-
body: {
|
|
489
|
-
emailAddress: "test@test.com",
|
|
490
|
-
password: "password"
|
|
491
|
-
}
|
|
492
|
-
});
|
|
493
|
-
const loginResponse = mockResponse();
|
|
494
|
-
const loginHandler = loginRoute?.route?.stack[0] && loginRoute?.route?.stack[0].handle;
|
|
495
|
-
const logoutRequest = mockRequest();
|
|
496
|
-
const logoutResponse = mockResponse();
|
|
497
|
-
const logoutHandler = logoutRoute?.route?.stack[0] && logoutRoute?.route?.stack[0].handle;
|
|
498
|
-
if (loginHandler && logoutHandler) {
|
|
499
|
-
await loginHandler(loginRequest, loginResponse, () => {
|
|
500
|
-
});
|
|
501
|
-
await logoutHandler(logoutRequest, logoutResponse, () => {
|
|
502
|
-
});
|
|
503
|
-
expect(loginResponse.cookie).toHaveBeenCalledWith("joystickLoginToken", "abc1234", { secure: true, httpOnly: true, expires: dayjs().toDate() });
|
|
504
|
-
expect(loginResponse.cookie).toHaveBeenCalledWith("joystickLoginTokenExpiresAt", "2022-01-31T00:00:00Z", { secure: true, httpOnly: true, expires: dayjs().toDate() });
|
|
505
|
-
expect(logoutResponse.cookie).toHaveBeenCalledWith("joystickLoginToken", null, { secure: true, httpOnly: true, expires: dayjs().toDate() });
|
|
506
|
-
expect(logoutResponse.cookie).toHaveBeenCalledWith("joystickLoginTokenExpiresAt", null, { secure: true, httpOnly: true, expires: dayjs().toDate() });
|
|
507
|
-
}
|
|
508
|
-
});
|
|
509
|
-
test("verify that a /_accounts/recover-password request attempts to send an email", async () => {
|
|
510
|
-
const instance = await app({});
|
|
511
|
-
const route = instance?.app?._router?.stack.find((stackItem) => {
|
|
512
|
-
return stackItem?.route?.path === "/api/_accounts/recover-password";
|
|
513
|
-
});
|
|
514
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
515
|
-
instance.server.close();
|
|
516
|
-
}
|
|
517
|
-
const req = mockRequest({
|
|
518
|
-
body: {
|
|
519
|
-
emailAddress: "test@test.com"
|
|
520
|
-
}
|
|
521
|
-
});
|
|
522
|
-
const res = mockResponse();
|
|
523
|
-
const handler = route?.route?.stack[0] && route?.route?.stack[0].handle;
|
|
524
|
-
if (handler) {
|
|
525
|
-
await handler(req, res, () => {
|
|
526
|
-
});
|
|
527
|
-
expect(nodemailer.smtp.sendMail).toHaveBeenCalledWith({
|
|
528
|
-
from: "app@test.com",
|
|
529
|
-
to: "test@test.com",
|
|
530
|
-
subject: "Reset Your Password",
|
|
531
|
-
html: `<!doctype html>
|
|
532
|
-
<html class="no-js" lang="en">
|
|
533
|
-
<head>
|
|
534
|
-
<meta charset="utf-8">
|
|
535
|
-
<title>Joystick</title>
|
|
536
|
-
|
|
537
|
-
</head>
|
|
538
|
-
<body style="color: #000; font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; font-size: 16px; line-height: 24px;">
|
|
539
|
-
<div id="email"><div js-c="testComponent1234">
|
|
540
|
-
<p>A password reset was requested for this email address (test@test.com). If you requested this reset, click the link below to reset your password:</p>
|
|
541
|
-
<p><a href="http://localhost:3600/reset-password/abc1234">Reset Password</a></p>
|
|
542
|
-
</div></div>
|
|
543
|
-
</body>
|
|
544
|
-
</html>
|
|
545
|
-
`,
|
|
546
|
-
text: "A password reset was requested for this email address (test@test.com). If you\nrequested this reset, click the link below to reset your password:\n\nReset Password [http://localhost:3600/reset-password/abc1234]"
|
|
547
|
-
});
|
|
548
|
-
}
|
|
549
|
-
});
|
|
550
|
-
test("verify that a /_accounts/reset-password request sets a cookie and returns the user", async () => {
|
|
551
|
-
const instance = await app({});
|
|
552
|
-
const route = instance?.app?._router?.stack.find((stackItem) => {
|
|
553
|
-
return stackItem?.route?.path === "/api/_accounts/reset-password";
|
|
554
|
-
});
|
|
555
|
-
if (instance?.server?.close && typeof instance.server.close === "function") {
|
|
556
|
-
instance.server.close();
|
|
557
|
-
}
|
|
558
|
-
const req = mockRequest({
|
|
559
|
-
body: {
|
|
560
|
-
token: "abc1234",
|
|
561
|
-
password: "test@test.com"
|
|
562
|
-
}
|
|
563
|
-
});
|
|
564
|
-
const res = mockResponse();
|
|
565
|
-
const handler = route?.route?.stack[0] && route?.route?.stack[0].handle;
|
|
566
|
-
if (handler) {
|
|
567
|
-
await handler(req, res, () => {
|
|
568
|
-
});
|
|
569
|
-
expect(res.cookie).toHaveBeenCalledWith("joystickLoginToken", "abc1234", { secure: true, httpOnly: true, expires: dayjs().toDate() });
|
|
570
|
-
expect(res.cookie).toHaveBeenCalledWith("joystickLoginTokenExpiresAt", "2022-01-31T00:00:00Z", { secure: true, httpOnly: true, expires: dayjs().toDate() });
|
|
571
|
-
expect(res.status).toHaveBeenCalledWith(200);
|
|
572
|
-
expect(res.send).toHaveBeenCalledWith('{"_id":"abc1234","password":"hashed$password","emailAddress":"test@test.com","sessions":[{"token":"abc1234","tokenExpiresAt":"2022-01-31T00:00:00Z"}],"passwordResetTokens":[]}');
|
|
573
|
-
}
|
|
574
|
-
});
|
|
575
|
-
});
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
var sanitizeQueryParameters_default = (req, res, next) => {
|
|
2
|
-
const queryParameters = Object.entries(req?.query);
|
|
3
|
-
const htmlRegex = new RegExp(/<(?:"[^"]*"['"]*|'[^']*'['"]*|[^'">])+>/g);
|
|
4
|
-
for (let i = 0; i < queryParameters?.length; i += 1) {
|
|
5
|
-
const [key, value] = queryParameters[i];
|
|
6
|
-
const keyHTMLMatches = key?.match(htmlRegex);
|
|
7
|
-
const valueHTMLMatches = value?.match(htmlRegex);
|
|
8
|
-
if (keyHTMLMatches?.length > 0 || valueHTMLMatches?.length > 0) {
|
|
9
|
-
delete req.query[key];
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
next();
|
|
13
|
-
};
|
|
14
|
-
export {
|
|
15
|
-
sanitizeQueryParameters_default as default
|
|
16
|
-
};
|
package/dist/email/send.test.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { jest } from "@jest/globals";
|
|
2
|
-
import chalk from "chalk";
|
|
3
|
-
import send from "./send";
|
|
4
|
-
import setAppSettingsForTest from "../tests/lib/setAppSettingsForTest";
|
|
5
|
-
setAppSettingsForTest({
|
|
6
|
-
"config": {
|
|
7
|
-
"databases": [
|
|
8
|
-
{
|
|
9
|
-
"provider": "mongodb",
|
|
10
|
-
"users": true,
|
|
11
|
-
"options": {}
|
|
12
|
-
}
|
|
13
|
-
],
|
|
14
|
-
"i18n": {
|
|
15
|
-
"defaultLanguage": "en-US"
|
|
16
|
-
},
|
|
17
|
-
"middleware": {},
|
|
18
|
-
"email": {
|
|
19
|
-
"from": "app@test.com",
|
|
20
|
-
"smtp": {}
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
"global": {},
|
|
24
|
-
"public": {},
|
|
25
|
-
"private": {}
|
|
26
|
-
});
|
|
27
|
-
console.warn = jest.fn();
|
|
28
|
-
describe("send.js", () => {
|
|
29
|
-
test("console.warns an error when bad smtp settings are passed", async () => {
|
|
30
|
-
const result = await send({ template: "test", props: {} });
|
|
31
|
-
expect(result).toBe(null);
|
|
32
|
-
expect(console.warn.mock.calls).toEqual([
|
|
33
|
-
[chalk.redBright("Invalid SMTP settings: config.smtp not defined in settings.test.js")],
|
|
34
|
-
[chalk.redBright("Cannot send email, invalid SMTP settings.")]
|
|
35
|
-
]);
|
|
36
|
-
});
|
|
37
|
-
});
|