@proteinjs/user-server 1.16.1 → 1.18.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 +22 -0
- package/dist/generated/index.js +1 -1
- package/dist/generated/index.js.map +1 -1
- package/dist/src/routes/devLogin.d.ts +10 -0
- package/dist/src/routes/devLogin.d.ts.map +1 -1
- package/dist/src/routes/devLogin.js +28 -9
- package/dist/src/routes/devLogin.js.map +1 -1
- package/dist/src/services/Roles.d.ts +24 -1
- package/dist/src/services/Roles.d.ts.map +1 -1
- package/dist/src/services/Roles.js +92 -5
- package/dist/src/services/Roles.js.map +1 -1
- package/dist/src/services/UpdateUserInfo.d.ts +24 -1
- package/dist/src/services/UpdateUserInfo.d.ts.map +1 -1
- package/dist/src/services/UpdateUserInfo.js +79 -18
- package/dist/src/services/UpdateUserInfo.js.map +1 -1
- package/dist/test/DevLogin.test.js +13 -41
- package/dist/test/DevLogin.test.js.map +1 -1
- package/dist/test/DevLoginBootstrapAdmin.test.d.ts +2 -0
- package/dist/test/DevLoginBootstrapAdmin.test.d.ts.map +1 -0
- package/dist/test/DevLoginBootstrapAdmin.test.js +384 -0
- package/dist/test/DevLoginBootstrapAdmin.test.js.map +1 -0
- package/dist/test/MachineAccounts.integration.test.js.map +1 -1
- package/dist/test/Roles.integration.test.js +76 -0
- package/dist/test/Roles.integration.test.js.map +1 -1
- package/dist/test/UpdateUserInfoClearAvatarByAdmin.test.d.ts +2 -0
- package/dist/test/UpdateUserInfoClearAvatarByAdmin.test.d.ts.map +1 -0
- package/dist/test/UpdateUserInfoClearAvatarByAdmin.test.js +224 -0
- package/dist/test/UpdateUserInfoClearAvatarByAdmin.test.js.map +1 -0
- package/dist/test/UpdateUserInfoRefresh.test.d.ts +2 -0
- package/dist/test/UpdateUserInfoRefresh.test.d.ts.map +1 -0
- package/dist/test/UpdateUserInfoRefresh.test.js +99 -0
- package/dist/test/UpdateUserInfoRefresh.test.js.map +1 -0
- package/dist/test/devLoginHarness.d.ts +16 -0
- package/dist/test/devLoginHarness.d.ts.map +1 -0
- package/dist/test/devLoginHarness.js +79 -0
- package/dist/test/devLoginHarness.js.map +1 -0
- package/generated/index.ts +1 -1
- package/package.json +3 -3
- package/src/routes/devLogin.ts +17 -0
- package/src/services/Roles.ts +62 -5
- package/src/services/UpdateUserInfo.ts +68 -13
- package/test/DevLogin.test.ts +5 -36
- package/test/DevLoginBootstrapAdmin.test.ts +175 -0
- package/test/Roles.integration.test.ts +41 -0
- package/test/UpdateUserInfoClearAvatarByAdmin.test.ts +109 -0
- package/test/UpdateUserInfoRefresh.test.ts +40 -0
- package/test/devLoginHarness.ts +39 -0
|
@@ -0,0 +1,224 @@
|
|
|
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 sharp_1 = __importDefault(require("sharp"));
|
|
43
|
+
var db_1 = require("@proteinjs/db");
|
|
44
|
+
var db_file_1 = require("@proteinjs/db-file");
|
|
45
|
+
var reflection_1 = require("@proteinjs/reflection");
|
|
46
|
+
var user_1 = require("@proteinjs/user");
|
|
47
|
+
var UserServerTestEnvironment_1 = require("./UserServerTestEnvironment");
|
|
48
|
+
var UpdateUserInfo_1 = require("../src/services/UpdateUserInfo");
|
|
49
|
+
var testEnv = new UserServerTestEnvironment_1.UserServerTestEnvironment();
|
|
50
|
+
var getFileRow = function (fileId) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
51
|
+
switch (_a.label) {
|
|
52
|
+
case 0: return [4 /*yield*/, (0, user_1.getScopedDbAsSystem)().get(db_file_1.tables.File, { id: fileId })];
|
|
53
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
54
|
+
}
|
|
55
|
+
}); }); };
|
|
56
|
+
var userRow = function (id) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
57
|
+
switch (_a.label) {
|
|
58
|
+
case 0: return [4 /*yield*/, (0, db_1.getDbAsSystem)().get(user_1.tables.User, { id: id })];
|
|
59
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
60
|
+
}
|
|
61
|
+
}); }); };
|
|
62
|
+
/**
|
|
63
|
+
* Clearing SOMEONE ELSE'S avatar — the user-manager act behind the admin user surface.
|
|
64
|
+
*
|
|
65
|
+
* The service door is `allUsers` (every signed-in user manages their own profile through it), so
|
|
66
|
+
* the cross-user authorization is in-body and fail-closed: naming another person's id requires
|
|
67
|
+
* the `users` permission. Two invariants beyond the row write:
|
|
68
|
+
* - the ACTOR's session cache is never overwritten with the target's row (the mutation path
|
|
69
|
+
* refreshes the caller's cached user, and doing that for another person's row would leave the
|
|
70
|
+
* admin browsing as their target);
|
|
71
|
+
* - the target's own session cache is NOT refreshed — the write is to their row, and their next
|
|
72
|
+
* sign-in reads it.
|
|
73
|
+
* Outcomes asserted against a real Spanner emulator: rows, files, cached identity.
|
|
74
|
+
*/
|
|
75
|
+
describe('UpdateUserInfo — clearing another person avatar', function () {
|
|
76
|
+
var service = new UpdateUserInfo_1.UpdateUserInfo();
|
|
77
|
+
var admin;
|
|
78
|
+
var kevin;
|
|
79
|
+
beforeAll(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
80
|
+
return __generator(this, function (_a) {
|
|
81
|
+
switch (_a.label) {
|
|
82
|
+
case 0: return [4 /*yield*/, testEnv.beforeAll()];
|
|
83
|
+
case 1:
|
|
84
|
+
_a.sent();
|
|
85
|
+
// The in-body permission check resolves the CALLER through UserAuth — the same session-backed
|
|
86
|
+
// repo the services use (the environment seeds session storage but not this registration).
|
|
87
|
+
reflection_1.SourceRepository.get().objectCache['@proteinjs/user-auth/AuthenticatedUserRepo'] = [new user_1.UserRepo()];
|
|
88
|
+
return [2 /*return*/];
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}); });
|
|
92
|
+
afterAll(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
93
|
+
return __generator(this, function (_a) {
|
|
94
|
+
switch (_a.label) {
|
|
95
|
+
case 0: return [4 /*yield*/, testEnv.afterAll()];
|
|
96
|
+
case 1:
|
|
97
|
+
_a.sent();
|
|
98
|
+
return [2 /*return*/];
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}); });
|
|
102
|
+
beforeEach(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
103
|
+
return __generator(this, function (_a) {
|
|
104
|
+
switch (_a.label) {
|
|
105
|
+
case 0: return [4 /*yield*/, testEnv.createUser({ name: 'Ada Admin', email: "admin-".concat(Date.now(), "@test.local"), roles: ['admin'] })];
|
|
106
|
+
case 1:
|
|
107
|
+
admin = _a.sent();
|
|
108
|
+
return [4 /*yield*/, testEnv.createUser({ name: 'Kevin', email: "kevin-".concat(Date.now(), "@test.local") })];
|
|
109
|
+
case 2:
|
|
110
|
+
kevin = _a.sent();
|
|
111
|
+
testEnv.actAs(admin);
|
|
112
|
+
return [2 /*return*/];
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}); });
|
|
116
|
+
it("clears the target's avatar, returns the target's row, and leaves the actor's session alone", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
117
|
+
var updated, kevinRow;
|
|
118
|
+
return __generator(this, function (_a) {
|
|
119
|
+
switch (_a.label) {
|
|
120
|
+
case 0: return [4 /*yield*/, (0, db_1.getDbAsSystem)().update(user_1.tables.User, { id: kevin.id, avatarEmoji: '🦊' })];
|
|
121
|
+
case 1:
|
|
122
|
+
_a.sent();
|
|
123
|
+
return [4 /*yield*/, service.clearAvatar(kevin.id)];
|
|
124
|
+
case 2:
|
|
125
|
+
updated = _a.sent();
|
|
126
|
+
return [4 /*yield*/, userRow(kevin.id)];
|
|
127
|
+
case 3:
|
|
128
|
+
kevinRow = _a.sent();
|
|
129
|
+
expect(kevinRow.avatarEmoji).toBeFalsy();
|
|
130
|
+
expect(kevinRow.avatarFileId).toBeFalsy();
|
|
131
|
+
// The returned user is the target's row, password-less.
|
|
132
|
+
expect(updated.id).toBe(kevin.id);
|
|
133
|
+
expect(updated.name).toBe('Kevin');
|
|
134
|
+
expect(updated.password).toBeUndefined();
|
|
135
|
+
// The actor is still signed in as themselves — the session cache was not handed the target.
|
|
136
|
+
expect(new user_1.UserRepo().getUser().id).toBe(admin.id);
|
|
137
|
+
expect(new user_1.UserRepo().getUser().name).toBe('Ada Admin');
|
|
138
|
+
return [2 /*return*/];
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}); });
|
|
142
|
+
it("deletes the target's stored avatar photo", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
143
|
+
var png, withPhoto, _a, _b, _c;
|
|
144
|
+
return __generator(this, function (_d) {
|
|
145
|
+
switch (_d.label) {
|
|
146
|
+
case 0:
|
|
147
|
+
testEnv.actAs(kevin);
|
|
148
|
+
return [4 /*yield*/, (0, sharp_1.default)({ create: { width: 64, height: 64, channels: 3, background: { r: 4, g: 5, b: 6 } } })
|
|
149
|
+
.png()
|
|
150
|
+
.toBuffer()];
|
|
151
|
+
case 1:
|
|
152
|
+
png = _d.sent();
|
|
153
|
+
return [4 /*yield*/, service.updateAvatarPhoto(png.toString('base64'), 'image/png')];
|
|
154
|
+
case 2:
|
|
155
|
+
withPhoto = _d.sent();
|
|
156
|
+
_a = expect;
|
|
157
|
+
return [4 /*yield*/, getFileRow(withPhoto.avatarFileId)];
|
|
158
|
+
case 3:
|
|
159
|
+
_a.apply(void 0, [_d.sent()]).toBeTruthy();
|
|
160
|
+
testEnv.actAs(admin);
|
|
161
|
+
return [4 /*yield*/, service.clearAvatar(kevin.id)];
|
|
162
|
+
case 4:
|
|
163
|
+
_d.sent();
|
|
164
|
+
_b = expect;
|
|
165
|
+
return [4 /*yield*/, getFileRow(withPhoto.avatarFileId)];
|
|
166
|
+
case 5:
|
|
167
|
+
_b.apply(void 0, [_d.sent()]).toBeFalsy();
|
|
168
|
+
_c = expect;
|
|
169
|
+
return [4 /*yield*/, userRow(kevin.id)];
|
|
170
|
+
case 6:
|
|
171
|
+
_c.apply(void 0, [(_d.sent()).avatarFileId]).toBeFalsy();
|
|
172
|
+
return [2 /*return*/];
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}); });
|
|
176
|
+
it("refuses an actor without the users permission, and the target's avatar is untouched", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
177
|
+
var bystander, _a;
|
|
178
|
+
return __generator(this, function (_b) {
|
|
179
|
+
switch (_b.label) {
|
|
180
|
+
case 0: return [4 /*yield*/, testEnv.createUser({ name: 'Bystander', email: "bystander-".concat(Date.now(), "@test.local") })];
|
|
181
|
+
case 1:
|
|
182
|
+
bystander = _b.sent();
|
|
183
|
+
return [4 /*yield*/, (0, db_1.getDbAsSystem)().update(user_1.tables.User, { id: kevin.id, avatarEmoji: '🦊' })];
|
|
184
|
+
case 2:
|
|
185
|
+
_b.sent();
|
|
186
|
+
testEnv.actAs(bystander);
|
|
187
|
+
return [4 /*yield*/, expect(service.clearAvatar(kevin.id)).rejects.toThrow("Only a user manager can change another person's avatar.")];
|
|
188
|
+
case 3:
|
|
189
|
+
_b.sent();
|
|
190
|
+
_a = expect;
|
|
191
|
+
return [4 /*yield*/, userRow(kevin.id)];
|
|
192
|
+
case 4:
|
|
193
|
+
_a.apply(void 0, [(_b.sent()).avatarEmoji]).toBe('🦊');
|
|
194
|
+
return [2 /*return*/];
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
}); });
|
|
198
|
+
it('with no id it still clears the CALLER own avatar and refreshes their session (the existing contract)', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
199
|
+
var updated, _a;
|
|
200
|
+
return __generator(this, function (_b) {
|
|
201
|
+
switch (_b.label) {
|
|
202
|
+
case 0:
|
|
203
|
+
testEnv.actAs(kevin);
|
|
204
|
+
return [4 /*yield*/, service.updateAvatarEmoji('🦞')];
|
|
205
|
+
case 1:
|
|
206
|
+
_b.sent();
|
|
207
|
+
expect(new user_1.UserRepo().getUser().avatarEmoji).toBe('🦞');
|
|
208
|
+
return [4 /*yield*/, service.clearAvatar()];
|
|
209
|
+
case 2:
|
|
210
|
+
updated = _b.sent();
|
|
211
|
+
expect(updated.id).toBe(kevin.id);
|
|
212
|
+
expect(updated.avatarEmoji).toBeFalsy();
|
|
213
|
+
_a = expect;
|
|
214
|
+
return [4 /*yield*/, userRow(kevin.id)];
|
|
215
|
+
case 3:
|
|
216
|
+
_a.apply(void 0, [(_b.sent()).avatarEmoji]).toBeFalsy();
|
|
217
|
+
// Self path: the session cache is refreshed in the same stroke.
|
|
218
|
+
expect(new user_1.UserRepo().getUser().avatarEmoji).toBeFalsy();
|
|
219
|
+
return [2 /*return*/];
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}); });
|
|
223
|
+
});
|
|
224
|
+
//# sourceMappingURL=UpdateUserInfoClearAvatarByAdmin.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UpdateUserInfoClearAvatarByAdmin.test.js","sourceRoot":"","sources":["../../test/UpdateUserInfoClearAvatarByAdmin.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UpdateUserInfoRefresh.test.d.ts","sourceRoot":"","sources":["../../test/UpdateUserInfoRefresh.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,99 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
var db_1 = require("@proteinjs/db");
|
|
40
|
+
var user_1 = require("@proteinjs/user");
|
|
41
|
+
var UserServerTestEnvironment_1 = require("./UserServerTestEnvironment");
|
|
42
|
+
var UpdateUserInfo_1 = require("../src/services/UpdateUserInfo");
|
|
43
|
+
var testEnv = new UserServerTestEnvironment_1.UserServerTestEnvironment();
|
|
44
|
+
/**
|
|
45
|
+
* `refresh()` is the read-only half of the persist-and-refresh helper: no write, just the stored
|
|
46
|
+
* row pulled back into the session cache. It exists for changes this session did not make — an
|
|
47
|
+
* avatar set on the phone, a rename from another tab, an admin clearing an avatar — which
|
|
48
|
+
* otherwise stay invisible here until the next sign-in, because the cached user is only ever
|
|
49
|
+
* rewritten by this session's OWN mutations.
|
|
50
|
+
*/
|
|
51
|
+
describe('UpdateUserInfo.refresh — re-reads the stored row into the session cache', function () {
|
|
52
|
+
beforeAll(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
53
|
+
return __generator(this, function (_a) {
|
|
54
|
+
switch (_a.label) {
|
|
55
|
+
case 0: return [4 /*yield*/, testEnv.beforeAll()];
|
|
56
|
+
case 1:
|
|
57
|
+
_a.sent();
|
|
58
|
+
return [2 /*return*/];
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}); });
|
|
62
|
+
afterAll(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
63
|
+
return __generator(this, function (_a) {
|
|
64
|
+
switch (_a.label) {
|
|
65
|
+
case 0: return [4 /*yield*/, testEnv.afterAll()];
|
|
66
|
+
case 1:
|
|
67
|
+
_a.sent();
|
|
68
|
+
return [2 /*return*/];
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}); });
|
|
72
|
+
it('picks up a change made outside this session, and returns the row password-less', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
73
|
+
var user, updated;
|
|
74
|
+
return __generator(this, function (_a) {
|
|
75
|
+
switch (_a.label) {
|
|
76
|
+
case 0: return [4 /*yield*/, testEnv.createUser({ name: 'Two Devices', email: 'refresh@test.local' })];
|
|
77
|
+
case 1:
|
|
78
|
+
user = _a.sent();
|
|
79
|
+
testEnv.actAs(user);
|
|
80
|
+
// The other device's write: the row moves, this session's cached user does not.
|
|
81
|
+
return [4 /*yield*/, (0, db_1.getDbAsSystem)().update(user_1.tables.User, { avatarEmoji: '🦊' }, { id: user.id })];
|
|
82
|
+
case 2:
|
|
83
|
+
// The other device's write: the row moves, this session's cached user does not.
|
|
84
|
+
_a.sent();
|
|
85
|
+
expect(new user_1.UserRepo().getUser().avatarEmoji).toBeFalsy();
|
|
86
|
+
return [4 /*yield*/, new UpdateUserInfo_1.UpdateUserInfo().refresh()];
|
|
87
|
+
case 3:
|
|
88
|
+
updated = _a.sent();
|
|
89
|
+
expect(updated.id).toBe(user.id);
|
|
90
|
+
expect(updated.avatarEmoji).toBe('🦊');
|
|
91
|
+
expect(updated.password).toBeUndefined();
|
|
92
|
+
// The point of the call: the cached user carries it now, with no re-login.
|
|
93
|
+
expect(new user_1.UserRepo().getUser().avatarEmoji).toBe('🦊');
|
|
94
|
+
return [2 /*return*/];
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}); });
|
|
98
|
+
});
|
|
99
|
+
//# sourceMappingURL=UpdateUserInfoRefresh.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UpdateUserInfoRefresh.test.js","sourceRoot":"","sources":["../../test/UpdateUserInfoRefresh.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oCAA8C;AAC9C,wCAAmD;AACnD,yEAAwE;AACxE,iEAAgE;AAEhE,IAAM,OAAO,GAAG,IAAI,qDAAyB,EAAE,CAAC;AAEhD;;;;;;GAMG;AACH,QAAQ,CAAC,yEAAyE,EAAE;IAClF,SAAS,CAAC;;;wBACR,qBAAM,OAAO,CAAC,SAAS,EAAE,EAAA;;oBAAzB,SAAyB,CAAC;;;;SAC3B,CAAC,CAAC;IAEH,QAAQ,CAAC;;;wBACP,qBAAM,OAAO,CAAC,QAAQ,EAAE,EAAA;;oBAAxB,SAAwB,CAAC;;;;SAC1B,CAAC,CAAC;IAEH,EAAE,CAAC,gFAAgF,EAAE;;;;wBACtE,qBAAM,OAAO,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,EAAA;;oBAArF,IAAI,GAAG,SAA8E;oBAC3F,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAEpB,gFAAgF;oBAChF,qBAAM,IAAA,kBAAa,GAAE,CAAC,MAAM,CAAC,aAAM,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,EAAA;;oBADjF,gFAAgF;oBAChF,SAAiF,CAAC;oBAClF,MAAM,CAAC,IAAI,eAAQ,EAAE,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC,SAAS,EAAE,CAAC;oBAEzC,qBAAM,IAAI,+BAAc,EAAE,CAAC,OAAO,EAAE,EAAA;;oBAA9C,OAAO,GAAG,SAAoC;oBAEpD,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oBACjC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACvC,MAAM,CAAE,OAAe,CAAC,QAAQ,CAAC,CAAC,aAAa,EAAE,CAAC;oBAClD,2EAA2E;oBAC3E,MAAM,CAAC,IAAI,eAAQ,EAAE,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;;;;SACzD,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** What one `GET /dev/login` did, seen from outside: the session it minted (or not) and the response it sent. */
|
|
2
|
+
export type DevLoginOutcome = {
|
|
3
|
+
loggedInAs?: string;
|
|
4
|
+
sessionRegenerated: boolean;
|
|
5
|
+
sessionSaved: boolean;
|
|
6
|
+
status?: number;
|
|
7
|
+
body?: unknown;
|
|
8
|
+
redirect?: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Drives the devLogin route once over the REAL passport login machinery (see
|
|
12
|
+
* passportSessionHarness): the full session-establishment contract (regenerate → login → save)
|
|
13
|
+
* is pinned by SignupRoute.test.ts — the dev-door suites assert the door INHERITS it.
|
|
14
|
+
*/
|
|
15
|
+
export declare const invokeDevLogin: (query?: Record<string, unknown>) => Promise<DevLoginOutcome>;
|
|
16
|
+
//# sourceMappingURL=devLoginHarness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devLoginHarness.d.ts","sourceRoot":"","sources":["../../test/devLoginHarness.ts"],"names":[],"mappings":"AAGA,iHAAiH;AACjH,MAAM,MAAM,eAAe,GAAG;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,cAAc,WAAkB,OAAO,MAAM,EAAE,OAAO,CAAC,KAAG,QAAQ,eAAe,CAoB7F,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.invokeDevLogin = void 0;
|
|
40
|
+
var devLogin_1 = require("../src/routes/devLogin");
|
|
41
|
+
var passportSessionHarness_1 = require("./passportSessionHarness");
|
|
42
|
+
/**
|
|
43
|
+
* Drives the devLogin route once over the REAL passport login machinery (see
|
|
44
|
+
* passportSessionHarness): the full session-establishment contract (regenerate → login → save)
|
|
45
|
+
* is pinned by SignupRoute.test.ts — the dev-door suites assert the door INHERITS it.
|
|
46
|
+
*/
|
|
47
|
+
var invokeDevLogin = function (query) { return __awaiter(void 0, void 0, void 0, function () {
|
|
48
|
+
var _a, request, events, outcome, response;
|
|
49
|
+
var _b;
|
|
50
|
+
return __generator(this, function (_c) {
|
|
51
|
+
switch (_c.label) {
|
|
52
|
+
case 0: return [4 /*yield*/, (0, passportSessionHarness_1.createPassportRequest)({ query: query })];
|
|
53
|
+
case 1:
|
|
54
|
+
_a = _c.sent(), request = _a.request, events = _a.events;
|
|
55
|
+
outcome = { sessionRegenerated: false, sessionSaved: false };
|
|
56
|
+
response = {
|
|
57
|
+
status: function (code) {
|
|
58
|
+
outcome.status = code;
|
|
59
|
+
return this;
|
|
60
|
+
},
|
|
61
|
+
send: function (body) {
|
|
62
|
+
outcome.body = body;
|
|
63
|
+
},
|
|
64
|
+
redirect: function (path) {
|
|
65
|
+
outcome.redirect = path;
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
return [4 /*yield*/, devLogin_1.devLogin.onRequest(request, response)];
|
|
69
|
+
case 2:
|
|
70
|
+
_c.sent();
|
|
71
|
+
outcome.loggedInAs = (_b = request.session.passport) === null || _b === void 0 ? void 0 : _b.user;
|
|
72
|
+
outcome.sessionRegenerated = events.includes('regenerate');
|
|
73
|
+
outcome.sessionSaved = events.includes('save');
|
|
74
|
+
return [2 /*return*/, outcome];
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}); };
|
|
78
|
+
exports.invokeDevLogin = invokeDevLogin;
|
|
79
|
+
//# sourceMappingURL=devLoginHarness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devLoginHarness.js","sourceRoot":"","sources":["../../test/devLoginHarness.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,mDAAkD;AAClD,mEAAiE;AAYjE;;;;GAIG;AACI,IAAM,cAAc,GAAG,UAAO,KAA+B;;;;;oBACtC,qBAAM,IAAA,8CAAqB,EAAC,EAAE,KAAK,OAAA,EAAE,CAAC,EAAA;;gBAA5D,KAAsB,SAAsC,EAA1D,OAAO,aAAA,EAAE,MAAM,YAAA;gBACjB,OAAO,GAAoB,EAAE,kBAAkB,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;gBAC9E,QAAQ,GAAG;oBACf,MAAM,YAAC,IAAY;wBACjB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;wBACtB,OAAO,IAAI,CAAC;oBACd,CAAC;oBACD,IAAI,YAAC,IAAc;wBACjB,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;oBACtB,CAAC;oBACD,QAAQ,YAAC,IAAY;wBACnB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;oBAC1B,CAAC;iBACF,CAAC;gBACF,qBAAM,mBAAQ,CAAC,SAAS,CAAC,OAAgB,EAAE,QAAiB,CAAC,EAAA;;gBAA7D,SAA6D,CAAC;gBAC9D,OAAO,CAAC,UAAU,GAAG,MAAA,OAAO,CAAC,OAAO,CAAC,QAAQ,0CAAE,IAAI,CAAC;gBACpD,OAAO,CAAC,kBAAkB,GAAG,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;gBAC3D,OAAO,CAAC,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAC/C,sBAAO,OAAO,EAAC;;;KAChB,CAAC;AApBW,QAAA,cAAc,kBAoBzB"}
|