@proteinjs/user-server 1.20.1 → 1.21.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/CHANGELOG.md +19 -0
- package/dist/generated/index.js +1 -1
- package/dist/generated/index.js.map +1 -1
- package/dist/src/services/Signup.d.ts +14 -0
- package/dist/src/services/Signup.d.ts.map +1 -1
- package/dist/src/services/Signup.js +102 -27
- package/dist/src/services/Signup.js.map +1 -1
- package/dist/test/SignupResendInvite.integration.test.d.ts +2 -0
- package/dist/test/SignupResendInvite.integration.test.d.ts.map +1 -0
- package/dist/test/SignupResendInvite.integration.test.js +235 -0
- package/dist/test/SignupResendInvite.integration.test.js.map +1 -0
- package/generated/index.ts +1 -1
- package/package.json +4 -4
- package/src/services/Signup.ts +71 -21
- package/test/SignupResendInvite.integration.test.ts +163 -0
|
@@ -82,7 +82,7 @@ var Signup = /** @class */ (function () {
|
|
|
82
82
|
// previously evaluated the check WITHOUT returning it, which made sendInvite/revokeInvite
|
|
83
83
|
// effectively public — any caller (even logged out) could mint themselves a valid signup
|
|
84
84
|
// token and bypass invite-only signup.
|
|
85
|
-
if (methodName === 'sendInvite' || methodName === 'revokeInvite') {
|
|
85
|
+
if (methodName === 'sendInvite' || methodName === 'resendInvite' || methodName === 'revokeInvite') {
|
|
86
86
|
return user_1.UserAuth.hasPermission(user_1.USER_PERMISSIONS.users);
|
|
87
87
|
}
|
|
88
88
|
return true;
|
|
@@ -155,40 +155,33 @@ var Signup = /** @class */ (function () {
|
|
|
155
155
|
});
|
|
156
156
|
};
|
|
157
157
|
Signup.prototype.sendInvite = function (email) {
|
|
158
|
-
var _a;
|
|
159
158
|
return __awaiter(this, void 0, void 0, function () {
|
|
160
|
-
var logger, caseInsensitiveEmail, db, userRecord,
|
|
161
|
-
return __generator(this, function (
|
|
162
|
-
switch (
|
|
159
|
+
var logger, caseInsensitiveEmail, db, userRecord, config, _a, token, tokenExpiresAt, invite, userId, error_1;
|
|
160
|
+
return __generator(this, function (_b) {
|
|
161
|
+
switch (_b.label) {
|
|
163
162
|
case 0:
|
|
164
163
|
logger = new logger_1.Logger({ name: 'Signup.sendInvite' });
|
|
165
164
|
caseInsensitiveEmail = email.toLowerCase();
|
|
166
|
-
|
|
165
|
+
_b.label = 1;
|
|
167
166
|
case 1:
|
|
168
|
-
|
|
167
|
+
_b.trys.push([1, 9, , 10]);
|
|
169
168
|
db = (0, db_1.getDbAsSystem)();
|
|
170
169
|
return [4 /*yield*/, db.get(user_1.tables.User, { email: caseInsensitiveEmail })];
|
|
171
170
|
case 2:
|
|
172
|
-
userRecord =
|
|
171
|
+
userRecord = _b.sent();
|
|
173
172
|
if (userRecord) {
|
|
174
173
|
return [2 /*return*/, { sent: false, error: 'User already exists with that email.' }];
|
|
175
174
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (!defaultConfigFactory) {
|
|
179
|
-
throw new Error("Unable to find a @proteinjs/email-server/DefaultInviteEmailConfigFactory implementation when sending invite.");
|
|
180
|
-
}
|
|
181
|
-
config = defaultConfigFactory.getConfig();
|
|
182
|
-
token = crypto_js_1.lib.WordArray.random(32).toString();
|
|
183
|
-
tokenExpiresAt = (0, moment_1.default)().add(exports.INVITE_TOKEN_TTL_DAYS, 'days');
|
|
175
|
+
config = this.inviteEmailConfig();
|
|
176
|
+
_a = this.mintInviteToken(), token = _a.token, tokenExpiresAt = _a.tokenExpiresAt;
|
|
184
177
|
return [4 /*yield*/, db.get(user_1.tables.Invite, { email: caseInsensitiveEmail })];
|
|
185
178
|
case 3:
|
|
186
|
-
invite =
|
|
179
|
+
invite = _b.sent();
|
|
187
180
|
if (!invite) return [3 /*break*/, 5];
|
|
188
181
|
invite = __assign(__assign({}, invite), { token: token, tokenExpiresAt: tokenExpiresAt });
|
|
189
182
|
return [4 /*yield*/, db.update(user_1.tables.Invite, invite)];
|
|
190
183
|
case 4:
|
|
191
|
-
|
|
184
|
+
_b.sent();
|
|
192
185
|
return [3 /*break*/, 7];
|
|
193
186
|
case 5:
|
|
194
187
|
userId = new user_1.UserRepo().getUser().id;
|
|
@@ -199,16 +192,14 @@ var Signup = /** @class */ (function () {
|
|
|
199
192
|
invitedBy: new db_1.Reference(user_1.tables.User.name, userId),
|
|
200
193
|
})];
|
|
201
194
|
case 6:
|
|
202
|
-
invite =
|
|
203
|
-
|
|
204
|
-
case 7:
|
|
205
|
-
_b = config.getEmailContent("".concat(user_1.uiRoutes.auth.signup, "?token=").concat(token)), text = _b.text, html = _b.html;
|
|
206
|
-
return [4 /*yield*/, emailSender.sendEmail(__assign({ to: caseInsensitiveEmail, subject: ((_a = config.options) === null || _a === void 0 ? void 0 : _a.subject) || "You're Invited", text: text, html: html }, config.options))];
|
|
195
|
+
invite = _b.sent();
|
|
196
|
+
_b.label = 7;
|
|
197
|
+
case 7: return [4 /*yield*/, this.emailInvite(caseInsensitiveEmail, token, config)];
|
|
207
198
|
case 8:
|
|
208
|
-
|
|
199
|
+
_b.sent();
|
|
209
200
|
return [2 /*return*/, { sent: true }];
|
|
210
201
|
case 9:
|
|
211
|
-
error_1 =
|
|
202
|
+
error_1 = _b.sent();
|
|
212
203
|
logger.error({ message: 'Error sending invite', obj: { email: caseInsensitiveEmail }, error: error_1 });
|
|
213
204
|
return [2 /*return*/, {
|
|
214
205
|
sent: false,
|
|
@@ -219,6 +210,58 @@ var Signup = /** @class */ (function () {
|
|
|
219
210
|
});
|
|
220
211
|
});
|
|
221
212
|
};
|
|
213
|
+
/**
|
|
214
|
+
* Re-sends a standing invite: the token in the earlier email stops working, a fresh token with
|
|
215
|
+
* a fresh expiry takes its place on the same row (never a second row), and the invite email goes
|
|
216
|
+
* out again through the same config. Refused when no invite stands for the address — there is
|
|
217
|
+
* nothing to re-send — and when the address already has an account (the invite was used).
|
|
218
|
+
* The inviter stays whoever sent it first.
|
|
219
|
+
*/
|
|
220
|
+
Signup.prototype.resendInvite = function (email) {
|
|
221
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
222
|
+
var logger, caseInsensitiveEmail, db, userRecord, invite, config, _a, token, tokenExpiresAt, error_2;
|
|
223
|
+
return __generator(this, function (_b) {
|
|
224
|
+
switch (_b.label) {
|
|
225
|
+
case 0:
|
|
226
|
+
logger = new logger_1.Logger({ name: 'Signup.resendInvite' });
|
|
227
|
+
caseInsensitiveEmail = email.toLowerCase();
|
|
228
|
+
_b.label = 1;
|
|
229
|
+
case 1:
|
|
230
|
+
_b.trys.push([1, 6, , 7]);
|
|
231
|
+
db = (0, db_1.getDbAsSystem)();
|
|
232
|
+
return [4 /*yield*/, db.get(user_1.tables.User, { email: caseInsensitiveEmail })];
|
|
233
|
+
case 2:
|
|
234
|
+
userRecord = _b.sent();
|
|
235
|
+
if (userRecord) {
|
|
236
|
+
return [2 /*return*/, { sent: false, error: 'User already exists with that email.' }];
|
|
237
|
+
}
|
|
238
|
+
return [4 /*yield*/, db.get(user_1.tables.Invite, { email: caseInsensitiveEmail })];
|
|
239
|
+
case 3:
|
|
240
|
+
invite = _b.sent();
|
|
241
|
+
if (!invite) {
|
|
242
|
+
return [2 /*return*/, { sent: false, error: 'No invite exists for that email.' }];
|
|
243
|
+
}
|
|
244
|
+
config = this.inviteEmailConfig();
|
|
245
|
+
_a = this.mintInviteToken(), token = _a.token, tokenExpiresAt = _a.tokenExpiresAt;
|
|
246
|
+
return [4 /*yield*/, db.update(user_1.tables.Invite, __assign(__assign({}, invite), { token: token, tokenExpiresAt: tokenExpiresAt }))];
|
|
247
|
+
case 4:
|
|
248
|
+
_b.sent();
|
|
249
|
+
return [4 /*yield*/, this.emailInvite(caseInsensitiveEmail, token, config)];
|
|
250
|
+
case 5:
|
|
251
|
+
_b.sent();
|
|
252
|
+
return [2 /*return*/, { sent: true }];
|
|
253
|
+
case 6:
|
|
254
|
+
error_2 = _b.sent();
|
|
255
|
+
logger.error({ message: 'Error re-sending invite', obj: { email: caseInsensitiveEmail }, error: error_2 });
|
|
256
|
+
return [2 /*return*/, {
|
|
257
|
+
sent: false,
|
|
258
|
+
error: 'Error occurred.',
|
|
259
|
+
}];
|
|
260
|
+
case 7: return [2 /*return*/];
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
};
|
|
222
265
|
Signup.prototype.revokeInvite = function (email) {
|
|
223
266
|
return __awaiter(this, void 0, void 0, function () {
|
|
224
267
|
var db;
|
|
@@ -243,7 +286,7 @@ var Signup = /** @class */ (function () {
|
|
|
243
286
|
*/
|
|
244
287
|
Signup.prototype.initializeSignup = function (inviteToken) {
|
|
245
288
|
return __awaiter(this, void 0, void 0, function () {
|
|
246
|
-
var config, isInviteOnly, lookup,
|
|
289
|
+
var config, isInviteOnly, lookup, error_3;
|
|
247
290
|
return __generator(this, function (_a) {
|
|
248
291
|
switch (_a.label) {
|
|
249
292
|
case 0:
|
|
@@ -286,7 +329,7 @@ var Signup = /** @class */ (function () {
|
|
|
286
329
|
isInviteOnly: isInviteOnly,
|
|
287
330
|
}];
|
|
288
331
|
case 3:
|
|
289
|
-
|
|
332
|
+
error_3 = _a.sent();
|
|
290
333
|
return [2 /*return*/, {
|
|
291
334
|
isReady: false,
|
|
292
335
|
error: 'Initializing sign up failed.',
|
|
@@ -360,6 +403,38 @@ var Signup = /** @class */ (function () {
|
|
|
360
403
|
});
|
|
361
404
|
});
|
|
362
405
|
};
|
|
406
|
+
/** The invite email content factory the consumer registers; its absence is a misconfiguration, said aloud. */
|
|
407
|
+
Signup.prototype.inviteEmailConfig = function () {
|
|
408
|
+
var defaultConfigFactory = (0, email_server_1.getDefaultInviteEmailConfigFactory)();
|
|
409
|
+
if (!defaultConfigFactory) {
|
|
410
|
+
throw new Error("Unable to find a @proteinjs/email-server/DefaultInviteEmailConfigFactory implementation when sending invite.");
|
|
411
|
+
}
|
|
412
|
+
return defaultConfigFactory.getConfig();
|
|
413
|
+
};
|
|
414
|
+
/** A fresh redeemable token with its expiry from the TTL knob — the one minting path for send and re-send. */
|
|
415
|
+
Signup.prototype.mintInviteToken = function () {
|
|
416
|
+
return {
|
|
417
|
+
token: crypto_js_1.lib.WordArray.random(32).toString(),
|
|
418
|
+
tokenExpiresAt: (0, moment_1.default)().add(exports.INVITE_TOKEN_TTL_DAYS, 'days'),
|
|
419
|
+
};
|
|
420
|
+
};
|
|
421
|
+
/** The invite email itself — the signup link carrying `token`, rendered by the consumer's config. */
|
|
422
|
+
Signup.prototype.emailInvite = function (email, token, config) {
|
|
423
|
+
var _a;
|
|
424
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
425
|
+
var _b, text, html;
|
|
426
|
+
return __generator(this, function (_c) {
|
|
427
|
+
switch (_c.label) {
|
|
428
|
+
case 0:
|
|
429
|
+
_b = config.getEmailContent("".concat(user_1.uiRoutes.auth.signup, "?token=").concat(token)), text = _b.text, html = _b.html;
|
|
430
|
+
return [4 /*yield*/, new email_server_1.EmailSender().sendEmail(__assign({ to: email, subject: ((_a = config.options) === null || _a === void 0 ? void 0 : _a.subject) || "You're Invited", text: text, html: html }, config.options))];
|
|
431
|
+
case 1:
|
|
432
|
+
_c.sent();
|
|
433
|
+
return [2 /*return*/];
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
};
|
|
363
438
|
return Signup;
|
|
364
439
|
}());
|
|
365
440
|
exports.Signup = Signup;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Signup.js","sourceRoot":"","sources":["../../../src/services/Signup.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oCAAyD;AACzD,wCAYyB;AACzB,kDAA4B;AAC5B,uCAAgC;AAChC,4CAA2C;AAC3C,
|
|
1
|
+
{"version":3,"file":"Signup.js","sourceRoot":"","sources":["../../../src/services/Signup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SignupResendInvite.integration.test.d.ts","sourceRoot":"","sources":["../../test/SignupResendInvite.integration.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
+
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;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
+
};
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
var moment_1 = __importDefault(require("moment"));
|
|
43
|
+
/**
|
|
44
|
+
* Re-sending an invite (`SignupService.resendInvite`), against the emulator — outcomes on the row
|
|
45
|
+
* and on the transport fake, never call counts alone:
|
|
46
|
+
*
|
|
47
|
+
* - the token in the earlier email stops resolving, the fresh one resolves to the SAME invite;
|
|
48
|
+
* - the row count for the address stays one, its expiry re-stamped from the TTL knob, its inviter kept;
|
|
49
|
+
* - exactly one email goes out for the re-send, to the address, carrying the fresh signup link;
|
|
50
|
+
* - an address with no standing invite is refused: nothing written, nothing sent;
|
|
51
|
+
* - an address that already has an account is refused the same way (the invite was used).
|
|
52
|
+
*
|
|
53
|
+
* The email transport is stubbed at the module boundary (the SignupInvite.test.ts pattern) — SMTP
|
|
54
|
+
* is an external transport; the config fake echoes the signup path so the link can be asserted.
|
|
55
|
+
* The service door (`serviceMetadata.auth`) is pinned here too: re-send rides the 'users' permission
|
|
56
|
+
* exactly like send and revoke — the earlier gap that left invite minting public must not reopen.
|
|
57
|
+
*/
|
|
58
|
+
var sendEmail = jest.fn();
|
|
59
|
+
jest.mock('@proteinjs/email-server', function () { return ({
|
|
60
|
+
EmailSender: jest.fn().mockImplementation(function () { return ({ sendEmail: sendEmail }); }),
|
|
61
|
+
getDefaultInviteEmailConfigFactory: function () { return ({
|
|
62
|
+
getConfig: function () { return ({
|
|
63
|
+
options: { subject: 'Your invite' },
|
|
64
|
+
getEmailContent: function (signupPathWithToken) { return ({
|
|
65
|
+
text: "Accept: /".concat(signupPathWithToken),
|
|
66
|
+
html: "<a href=\"/".concat(signupPathWithToken, "\">Accept</a>"),
|
|
67
|
+
}); },
|
|
68
|
+
}); },
|
|
69
|
+
}); },
|
|
70
|
+
getDefaultSignupConfirmationEmailConfigFactory: function () { return ({
|
|
71
|
+
getConfig: function () { return ({ getNewUserEmailContent: function () { return ({ text: 'welcome', html: '<p>welcome</p>' }); } }); },
|
|
72
|
+
}); },
|
|
73
|
+
}); });
|
|
74
|
+
var db_1 = require("@proteinjs/db");
|
|
75
|
+
var reflection_1 = require("@proteinjs/reflection");
|
|
76
|
+
var user_1 = require("@proteinjs/user");
|
|
77
|
+
var Signup_1 = require("../src/services/Signup");
|
|
78
|
+
var UserServerTestEnvironment_1 = require("./UserServerTestEnvironment");
|
|
79
|
+
var TIMEOUT = 60000;
|
|
80
|
+
/** Tolerance for the clock advancing between the stamp and the assertion. */
|
|
81
|
+
var CLOCK_SKEW_TOLERANCE_SECONDS = 60;
|
|
82
|
+
var inviteRows = function (email) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
83
|
+
switch (_a.label) {
|
|
84
|
+
case 0: return [4 /*yield*/, (0, db_1.getDbAsSystem)().query(user_1.tables.Invite, { email: email })];
|
|
85
|
+
case 1: return [2 /*return*/, (_a.sent())];
|
|
86
|
+
}
|
|
87
|
+
}); }); };
|
|
88
|
+
/** The re-send's own transport call: the one addressed to `email` after the earlier `before` calls. */
|
|
89
|
+
var emailsTo = function (email) {
|
|
90
|
+
return sendEmail.mock.calls.map(function (_a) {
|
|
91
|
+
var message = _a[0];
|
|
92
|
+
return message;
|
|
93
|
+
}).filter(function (message) { return message.to === email; });
|
|
94
|
+
};
|
|
95
|
+
describe('SignupService.resendInvite — against the emulator', function () {
|
|
96
|
+
var env = new UserServerTestEnvironment_1.UserServerTestEnvironment();
|
|
97
|
+
var inviter;
|
|
98
|
+
beforeAll(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
99
|
+
return __generator(this, function (_a) {
|
|
100
|
+
switch (_a.label) {
|
|
101
|
+
case 0: return [4 /*yield*/, env.beforeAll()];
|
|
102
|
+
case 1:
|
|
103
|
+
_a.sent();
|
|
104
|
+
// The invite-mode factory the token lookup consults (`initializeSignup`) — seeded like the
|
|
105
|
+
// environment seeds its own loadables (the suites load src, never the generated source
|
|
106
|
+
// graph, so an unseeded lookup has no graph to walk); invite-optional, the library default.
|
|
107
|
+
reflection_1.SourceRepository.get().objectCache['@proteinjs/user-server/DefaultInviteConfigFactory'] = [{ getConfig: function () { return ({ isInviteOnly: false }); } }];
|
|
108
|
+
return [4 /*yield*/, env.createUser({ name: 'Inviter', email: 'inviter@example.com', roles: ['admin'] })];
|
|
109
|
+
case 2:
|
|
110
|
+
inviter = _a.sent();
|
|
111
|
+
env.actAs(inviter);
|
|
112
|
+
return [2 /*return*/];
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}); }, TIMEOUT);
|
|
116
|
+
afterAll(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
117
|
+
return __generator(this, function (_a) {
|
|
118
|
+
switch (_a.label) {
|
|
119
|
+
case 0: return [4 /*yield*/, env.afterAll()];
|
|
120
|
+
case 1:
|
|
121
|
+
_a.sent();
|
|
122
|
+
return [2 /*return*/];
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}); }, TIMEOUT);
|
|
126
|
+
beforeEach(function () {
|
|
127
|
+
sendEmail.mockClear();
|
|
128
|
+
});
|
|
129
|
+
it('retires the earlier token, mints a fresh one on the SAME row, and emails the fresh link exactly once', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
130
|
+
var email, sent, standing, earlierToken, earlierExpiry, resent, rows, refreshed, earlier, fresh, messages, resend;
|
|
131
|
+
var _a, _b;
|
|
132
|
+
return __generator(this, function (_c) {
|
|
133
|
+
switch (_c.label) {
|
|
134
|
+
case 0:
|
|
135
|
+
email = 'guest@example.com';
|
|
136
|
+
return [4 /*yield*/, new Signup_1.Signup().sendInvite(email)];
|
|
137
|
+
case 1:
|
|
138
|
+
sent = _c.sent();
|
|
139
|
+
expect(sent).toEqual({ sent: true });
|
|
140
|
+
return [4 /*yield*/, inviteRows(email)];
|
|
141
|
+
case 2:
|
|
142
|
+
standing = (_c.sent())[0];
|
|
143
|
+
earlierToken = standing.token;
|
|
144
|
+
earlierExpiry = (0, moment_1.default)(standing.tokenExpiresAt);
|
|
145
|
+
expect(emailsTo(email)).toHaveLength(1);
|
|
146
|
+
return [4 /*yield*/, new Signup_1.Signup().resendInvite('Guest@Example.com')];
|
|
147
|
+
case 3:
|
|
148
|
+
resent = _c.sent();
|
|
149
|
+
expect(resent).toEqual({ sent: true });
|
|
150
|
+
return [4 /*yield*/, inviteRows(email)];
|
|
151
|
+
case 4:
|
|
152
|
+
rows = _c.sent();
|
|
153
|
+
expect(rows).toHaveLength(1);
|
|
154
|
+
refreshed = rows[0];
|
|
155
|
+
expect(refreshed.id).toBe(standing.id);
|
|
156
|
+
expect(refreshed.token).not.toBe(earlierToken);
|
|
157
|
+
expect((_a = refreshed.invitedBy) === null || _a === void 0 ? void 0 : _a._id).toBe(inviter.id);
|
|
158
|
+
// The expiry is re-stamped from the knob (fresh window), never left at the earlier stamp.
|
|
159
|
+
expect((0, moment_1.default)(refreshed.tokenExpiresAt).isSameOrAfter(earlierExpiry)).toBe(true);
|
|
160
|
+
expect(Math.abs((0, moment_1.default)(refreshed.tokenExpiresAt).diff((0, moment_1.default)().add(Signup_1.INVITE_TOKEN_TTL_DAYS, 'days'), 'seconds'))).toBeLessThan(CLOCK_SKEW_TOLERANCE_SECONDS);
|
|
161
|
+
return [4 /*yield*/, new Signup_1.Signup().initializeSignup(earlierToken)];
|
|
162
|
+
case 5:
|
|
163
|
+
earlier = _c.sent();
|
|
164
|
+
expect(earlier.isReady).toBe(false);
|
|
165
|
+
expect(earlier.error).toMatch(/no longer valid/i);
|
|
166
|
+
return [4 /*yield*/, new Signup_1.Signup().initializeSignup(refreshed.token)];
|
|
167
|
+
case 6:
|
|
168
|
+
fresh = _c.sent();
|
|
169
|
+
expect(fresh.isReady).toBe(true);
|
|
170
|
+
expect((_b = fresh.invite) === null || _b === void 0 ? void 0 : _b.email).toBe(email);
|
|
171
|
+
messages = emailsTo(email);
|
|
172
|
+
expect(messages).toHaveLength(2);
|
|
173
|
+
resend = messages[1];
|
|
174
|
+
expect(resend.subject).toBe('Your invite');
|
|
175
|
+
expect(resend.text).toContain("signup?token=".concat(refreshed.token));
|
|
176
|
+
expect(resend.html).toContain("signup?token=".concat(refreshed.token));
|
|
177
|
+
expect(resend.text).not.toContain(earlierToken);
|
|
178
|
+
return [2 /*return*/];
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}); }, TIMEOUT);
|
|
182
|
+
it('refuses an address with no standing invite — nothing written, nothing sent', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
183
|
+
var email, response, _a;
|
|
184
|
+
return __generator(this, function (_b) {
|
|
185
|
+
switch (_b.label) {
|
|
186
|
+
case 0:
|
|
187
|
+
email = 'nobody@example.com';
|
|
188
|
+
return [4 /*yield*/, new Signup_1.Signup().resendInvite(email)];
|
|
189
|
+
case 1:
|
|
190
|
+
response = _b.sent();
|
|
191
|
+
expect(response.sent).toBe(false);
|
|
192
|
+
expect(response.error).toMatch(/no invite/i);
|
|
193
|
+
_a = expect;
|
|
194
|
+
return [4 /*yield*/, inviteRows(email)];
|
|
195
|
+
case 2:
|
|
196
|
+
_a.apply(void 0, [_b.sent()]).toHaveLength(0);
|
|
197
|
+
expect(emailsTo(email)).toHaveLength(0);
|
|
198
|
+
return [2 /*return*/];
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}); }, TIMEOUT);
|
|
202
|
+
it('refuses an address that already has an account — the invite was used', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
203
|
+
var email, response;
|
|
204
|
+
return __generator(this, function (_a) {
|
|
205
|
+
switch (_a.label) {
|
|
206
|
+
case 0:
|
|
207
|
+
email = 'member@example.com';
|
|
208
|
+
return [4 /*yield*/, env.createUser({ name: 'Member', email: email })];
|
|
209
|
+
case 1:
|
|
210
|
+
_a.sent();
|
|
211
|
+
return [4 /*yield*/, new Signup_1.Signup().resendInvite(email)];
|
|
212
|
+
case 2:
|
|
213
|
+
response = _a.sent();
|
|
214
|
+
expect(response.sent).toBe(false);
|
|
215
|
+
expect(response.error).toMatch(/already exists/i);
|
|
216
|
+
expect(emailsTo(email)).toHaveLength(0);
|
|
217
|
+
return [2 /*return*/];
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
}); }, TIMEOUT);
|
|
221
|
+
it('rides the users-permission door like send and revoke (never public)', function () {
|
|
222
|
+
var hasPermission = jest.spyOn(user_1.UserAuth, 'hasPermission');
|
|
223
|
+
try {
|
|
224
|
+
hasPermission.mockReturnValue(false);
|
|
225
|
+
expect(new Signup_1.Signup().serviceMetadata.auth.canAccess('resendInvite', ['x@example.com'])).toBe(false);
|
|
226
|
+
hasPermission.mockReturnValue(true);
|
|
227
|
+
expect(new Signup_1.Signup().serviceMetadata.auth.canAccess('resendInvite', ['x@example.com'])).toBe(true);
|
|
228
|
+
expect(hasPermission).toHaveBeenCalledWith(user_1.USER_PERMISSIONS.users);
|
|
229
|
+
}
|
|
230
|
+
finally {
|
|
231
|
+
hasPermission.mockRestore();
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
//# sourceMappingURL=SignupResendInvite.integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SignupResendInvite.integration.test.js","sourceRoot":"","sources":["../../test/SignupResendInvite.integration.test.ts"],"names":[],"mappings":"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"}
|