@proteinjs/user-server 1.6.0 → 1.8.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.
Files changed (114) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/generated/index.d.ts.map +1 -1
  3. package/dist/generated/index.js +9 -1
  4. package/dist/generated/index.js.map +1 -1
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +6 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/src/authentication/PasswordHasher.d.ts +45 -0
  10. package/dist/src/authentication/PasswordHasher.d.ts.map +1 -0
  11. package/dist/src/authentication/PasswordHasher.js +152 -0
  12. package/dist/src/authentication/PasswordHasher.js.map +1 -0
  13. package/dist/src/authentication/UserStatusTableWatcher.d.ts +19 -0
  14. package/dist/src/authentication/UserStatusTableWatcher.d.ts.map +1 -0
  15. package/dist/src/authentication/UserStatusTableWatcher.js +115 -0
  16. package/dist/src/authentication/UserStatusTableWatcher.js.map +1 -0
  17. package/dist/src/authentication/authenticate.d.ts.map +1 -1
  18. package/dist/src/authentication/authenticate.js +41 -13
  19. package/dist/src/authentication/authenticate.js.map +1 -1
  20. package/dist/src/authorization/userCache.d.ts.map +1 -1
  21. package/dist/src/authorization/userCache.js +27 -3
  22. package/dist/src/authorization/userCache.js.map +1 -1
  23. package/dist/src/emails/AccountDeletionEmailConfigs.d.ts +35 -0
  24. package/dist/src/emails/AccountDeletionEmailConfigs.d.ts.map +1 -0
  25. package/dist/src/emails/AccountDeletionEmailConfigs.js +36 -0
  26. package/dist/src/emails/AccountDeletionEmailConfigs.js.map +1 -0
  27. package/dist/src/emails/AccountDeletionEmails.d.ts +13 -0
  28. package/dist/src/emails/AccountDeletionEmails.d.ts.map +1 -0
  29. package/dist/src/emails/AccountDeletionEmails.js +98 -0
  30. package/dist/src/emails/AccountDeletionEmails.js.map +1 -0
  31. package/dist/src/routes/devLogin.d.ts +15 -5
  32. package/dist/src/routes/devLogin.d.ts.map +1 -1
  33. package/dist/src/routes/devLogin.js +52 -15
  34. package/dist/src/routes/devLogin.js.map +1 -1
  35. package/dist/src/routes/executePasswordReset.js +5 -3
  36. package/dist/src/routes/executePasswordReset.js.map +1 -1
  37. package/dist/src/routes/login.d.ts.map +1 -1
  38. package/dist/src/routes/login.js +26 -2
  39. package/dist/src/routes/login.js.map +1 -1
  40. package/dist/src/services/AccountDeletion.d.ts +52 -0
  41. package/dist/src/services/AccountDeletion.d.ts.map +1 -0
  42. package/dist/src/services/AccountDeletion.js +426 -0
  43. package/dist/src/services/AccountDeletion.js.map +1 -0
  44. package/dist/src/services/MachineCredentials.d.ts +21 -0
  45. package/dist/src/services/MachineCredentials.d.ts.map +1 -0
  46. package/dist/src/services/MachineCredentials.js +164 -0
  47. package/dist/src/services/MachineCredentials.js.map +1 -0
  48. package/dist/src/services/Roles.d.ts.map +1 -1
  49. package/dist/src/services/Roles.js +7 -0
  50. package/dist/src/services/Roles.js.map +1 -1
  51. package/dist/src/services/SetUserStatus.d.ts +18 -0
  52. package/dist/src/services/SetUserStatus.d.ts.map +1 -0
  53. package/dist/src/services/SetUserStatus.js +118 -0
  54. package/dist/src/services/SetUserStatus.js.map +1 -0
  55. package/dist/src/services/Signup.d.ts +16 -1
  56. package/dist/src/services/Signup.d.ts.map +1 -1
  57. package/dist/src/services/Signup.js +55 -16
  58. package/dist/src/services/Signup.js.map +1 -1
  59. package/dist/src/services/UpdateUserInfo.d.ts.map +1 -1
  60. package/dist/src/services/UpdateUserInfo.js +20 -17
  61. package/dist/src/services/UpdateUserInfo.js.map +1 -1
  62. package/dist/test/AccountDeletion.integration.test.d.ts +2 -0
  63. package/dist/test/AccountDeletion.integration.test.d.ts.map +1 -0
  64. package/dist/test/AccountDeletion.integration.test.js +710 -0
  65. package/dist/test/AccountDeletion.integration.test.js.map +1 -0
  66. package/dist/test/DevLogin.test.d.ts +2 -0
  67. package/dist/test/DevLogin.test.d.ts.map +1 -0
  68. package/dist/test/DevLogin.test.js +262 -0
  69. package/dist/test/DevLogin.test.js.map +1 -0
  70. package/dist/test/MachineAccounts.integration.test.d.ts +2 -0
  71. package/dist/test/MachineAccounts.integration.test.d.ts.map +1 -0
  72. package/dist/test/MachineAccounts.integration.test.js +597 -0
  73. package/dist/test/MachineAccounts.integration.test.js.map +1 -0
  74. package/dist/test/PasswordMigration.integration.test.d.ts +2 -0
  75. package/dist/test/PasswordMigration.integration.test.d.ts.map +1 -0
  76. package/dist/test/PasswordMigration.integration.test.js +332 -0
  77. package/dist/test/PasswordMigration.integration.test.js.map +1 -0
  78. package/dist/test/SetUserStatus.integration.test.d.ts +2 -0
  79. package/dist/test/SetUserStatus.integration.test.d.ts.map +1 -0
  80. package/dist/test/SetUserStatus.integration.test.js +266 -0
  81. package/dist/test/SetUserStatus.integration.test.js.map +1 -0
  82. package/dist/test/UserCacheMissingAccount.test.d.ts +2 -0
  83. package/dist/test/UserCacheMissingAccount.test.d.ts.map +1 -0
  84. package/dist/test/UserCacheMissingAccount.test.js +104 -0
  85. package/dist/test/UserCacheMissingAccount.test.js.map +1 -0
  86. package/dist/test/UserStatusGate.integration.test.d.ts +2 -0
  87. package/dist/test/UserStatusGate.integration.test.d.ts.map +1 -0
  88. package/dist/test/UserStatusGate.integration.test.js +162 -0
  89. package/dist/test/UserStatusGate.integration.test.js.map +1 -0
  90. package/generated/index.ts +9 -1
  91. package/index.ts +3 -0
  92. package/package.json +8 -6
  93. package/src/authentication/PasswordHasher.ts +87 -0
  94. package/src/authentication/UserStatusTableWatcher.ts +56 -0
  95. package/src/authentication/authenticate.ts +31 -6
  96. package/src/authorization/userCache.ts +25 -2
  97. package/src/emails/AccountDeletionEmailConfigs.ts +79 -0
  98. package/src/emails/AccountDeletionEmails.ts +39 -0
  99. package/src/routes/devLogin.ts +45 -7
  100. package/src/routes/executePasswordReset.ts +2 -2
  101. package/src/routes/login.ts +23 -0
  102. package/src/services/AccountDeletion.ts +291 -0
  103. package/src/services/MachineCredentials.ts +94 -0
  104. package/src/services/Roles.ts +10 -0
  105. package/src/services/SetUserStatus.ts +56 -0
  106. package/src/services/Signup.ts +43 -12
  107. package/src/services/UpdateUserInfo.ts +4 -5
  108. package/test/AccountDeletion.integration.test.ts +391 -0
  109. package/test/DevLogin.test.ts +160 -0
  110. package/test/MachineAccounts.integration.test.ts +312 -0
  111. package/test/PasswordMigration.integration.test.ts +132 -0
  112. package/test/SetUserStatus.integration.test.ts +120 -0
  113. package/test/UserCacheMissingAccount.test.ts +42 -0
  114. package/test/UserStatusGate.integration.test.ts +68 -0
@@ -0,0 +1,98 @@
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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
29
+ 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;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
43
+ }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ exports.AccountDeletionEmails = void 0;
51
+ var email_server_1 = require("@proteinjs/email-server");
52
+ var AccountDeletionEmailConfigs_1 = require("./AccountDeletionEmailConfigs");
53
+ /**
54
+ * Thin sender for the two account-deletion emails: deletion-requested (at deactivation — the
55
+ * only cancel channel an account-takeover victim has) and the store-required completion
56
+ * confirmation (sent by the purge walker after the user row is gone). Content comes from the
57
+ * config factories beside this class; transport is the app's DefaultEmailConfigFactory SMTP
58
+ * config via EmailSender.
59
+ */
60
+ var AccountDeletionEmails = /** @class */ (function () {
61
+ function AccountDeletionEmails() {
62
+ }
63
+ AccountDeletionEmails.prototype.sendDeletionRequested = function (to, purgeAfter) {
64
+ return __awaiter(this, void 0, void 0, function () {
65
+ var config, _a, text, html;
66
+ return __generator(this, function (_b) {
67
+ switch (_b.label) {
68
+ case 0:
69
+ config = (0, AccountDeletionEmailConfigs_1.getDefaultAccountDeletionRequestedEmailConfigFactory)().getConfig();
70
+ _a = config.getEmailContent(purgeAfter), text = _a.text, html = _a.html;
71
+ return [4 /*yield*/, new email_server_1.EmailSender().sendEmail(__assign({ to: to, subject: 'Your account is scheduled for deletion', text: text, html: html }, config.options))];
72
+ case 1:
73
+ _b.sent();
74
+ return [2 /*return*/];
75
+ }
76
+ });
77
+ });
78
+ };
79
+ AccountDeletionEmails.prototype.sendAccountDeleted = function (to) {
80
+ return __awaiter(this, void 0, void 0, function () {
81
+ var config, _a, text, html;
82
+ return __generator(this, function (_b) {
83
+ switch (_b.label) {
84
+ case 0:
85
+ config = (0, AccountDeletionEmailConfigs_1.getDefaultAccountDeletedEmailConfigFactory)().getConfig();
86
+ _a = config.getEmailContent(), text = _a.text, html = _a.html;
87
+ return [4 /*yield*/, new email_server_1.EmailSender().sendEmail(__assign({ to: to, subject: 'Your account has been deleted', text: text, html: html }, config.options))];
88
+ case 1:
89
+ _b.sent();
90
+ return [2 /*return*/];
91
+ }
92
+ });
93
+ });
94
+ };
95
+ return AccountDeletionEmails;
96
+ }());
97
+ exports.AccountDeletionEmails = AccountDeletionEmails;
98
+ //# sourceMappingURL=AccountDeletionEmails.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AccountDeletionEmails.js","sourceRoot":"","sources":["../../../src/emails/AccountDeletionEmails.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,wDAAsD;AACtD,6EAGuC;AAEvC;;;;;;GAMG;AACH;IAAA;IAwBA,CAAC;IAvBO,qDAAqB,GAA3B,UAA4B,EAAU,EAAE,UAAkB;;;;;;wBAClD,MAAM,GAAG,IAAA,kFAAoD,GAAE,CAAC,SAAS,EAAE,CAAC;wBAC5E,KAAiB,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,EAAjD,IAAI,UAAA,EAAE,IAAI,UAAA,CAAwC;wBAC1D,qBAAM,IAAI,0BAAW,EAAE,CAAC,SAAS,YAC/B,EAAE,IAAA,EACF,OAAO,EAAE,wCAAwC,EACjD,IAAI,MAAA,EACJ,IAAI,MAAA,IACD,MAAM,CAAC,OAAO,EACjB,EAAA;;wBANF,SAME,CAAC;;;;;KACJ;IAEK,kDAAkB,GAAxB,UAAyB,EAAU;;;;;;wBAC3B,MAAM,GAAG,IAAA,wEAA0C,GAAE,CAAC,SAAS,EAAE,CAAC;wBAClE,KAAiB,MAAM,CAAC,eAAe,EAAE,EAAvC,IAAI,UAAA,EAAE,IAAI,UAAA,CAA8B;wBAChD,qBAAM,IAAI,0BAAW,EAAE,CAAC,SAAS,YAC/B,EAAE,IAAA,EACF,OAAO,EAAE,+BAA+B,EACxC,IAAI,MAAA,EACJ,IAAI,MAAA,IACD,MAAM,CAAC,OAAO,EACjB,EAAA;;wBANF,SAME,CAAC;;;;;KACJ;IACH,4BAAC;AAAD,CAAC,AAxBD,IAwBC;AAxBY,sDAAqB"}
@@ -1,13 +1,23 @@
1
1
  import { Route } from '@proteinjs/server-api';
2
2
  /**
3
- * DEV-ONLY session bootstrap: `GET /dev/login` establishes a session for the account named by
4
- * `DEV_AUTO_LOGIN_EMAIL` — no credentials involved — so automated dev-loop testing (agent-driven
5
- * browsers) can self-serve a session instead of stalling on the login form every time a cookie
6
- * is lost.
3
+ * DEV-ONLY session bootstrap: `GET /dev/login` establishes a session — no credentials involved —
4
+ * so automated dev-loop testing (agent-driven browsers) can self-serve a session instead of
5
+ * stalling on the login form. `?email=<addr>` selects the session's account so parallel
6
+ * verification can fan out over distinct users; absent, the `DEV_AUTO_LOGIN_EMAIL` account is
7
+ * used as before.
7
8
  *
8
9
  * Double-gated, acts only when BOTH hold; otherwise the path answers 404 as if unregistered:
9
10
  * 1. `process.env.DEVELOPMENT` — the dev-server switch, never set in prod images.
10
- * 2. `DEV_AUTO_LOGIN_EMAIL` — explicit per-launch opt-in naming exactly one account.
11
+ * 2. `DEV_AUTO_LOGIN_EMAIL` — explicit per-launch opt-in naming the default account.
12
+ *
13
+ * Domain rail: `?email` must share `DEV_AUTO_LOGIN_EMAIL`'s domain — even a dev server must not
14
+ * mint sessions (much less accounts) for arbitrary domains; anything else answers 400.
15
+ *
16
+ * A missing account is created through the normal signup creation path (`Signup.createAccount`)
17
+ * as a normal test user — password `test`, matching the seeded test-account convention, so
18
+ * interactive login works for the same identity. Composes with userCache's missing-account→guest
19
+ * seam: that covers sessions whose account was deleted AFTER minting; this ensures dev-minted
20
+ * sessions reference a real account from the start.
11
21
  */
12
22
  export declare const devLogin: Route;
13
23
  //# sourceMappingURL=devLogin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"devLogin.d.ts","sourceRoot":"","sources":["../../../src/routes/devLogin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAK9C;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ,EAAE,KAmBtB,CAAC"}
1
+ {"version":3,"file":"devLogin.d.ts","sourceRoot":"","sources":["../../../src/routes/devLogin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAU9C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,QAAQ,EAAE,KA0CtB,CAAC"}
@@ -38,45 +38,82 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.devLogin = void 0;
40
40
  var logger_1 = require("@proteinjs/logger");
41
+ var Signup_1 = require("../services/Signup");
41
42
  var logger = new logger_1.Logger({ name: 'devLogin' });
43
+ /** Lowercased domain of an email address (the whole string when there is no `@`, which can never
44
+ * equal a real env domain — so malformed params fall out at the domain rail). */
45
+ var emailDomain = function (address) { return address.slice(address.lastIndexOf('@') + 1).toLowerCase(); };
42
46
  /**
43
- * DEV-ONLY session bootstrap: `GET /dev/login` establishes a session for the account named by
44
- * `DEV_AUTO_LOGIN_EMAIL` — no credentials involved — so automated dev-loop testing (agent-driven
45
- * browsers) can self-serve a session instead of stalling on the login form every time a cookie
46
- * is lost.
47
+ * DEV-ONLY session bootstrap: `GET /dev/login` establishes a session — no credentials involved —
48
+ * so automated dev-loop testing (agent-driven browsers) can self-serve a session instead of
49
+ * stalling on the login form. `?email=<addr>` selects the session's account so parallel
50
+ * verification can fan out over distinct users; absent, the `DEV_AUTO_LOGIN_EMAIL` account is
51
+ * used as before.
47
52
  *
48
53
  * Double-gated, acts only when BOTH hold; otherwise the path answers 404 as if unregistered:
49
54
  * 1. `process.env.DEVELOPMENT` — the dev-server switch, never set in prod images.
50
- * 2. `DEV_AUTO_LOGIN_EMAIL` — explicit per-launch opt-in naming exactly one account.
55
+ * 2. `DEV_AUTO_LOGIN_EMAIL` — explicit per-launch opt-in naming the default account.
56
+ *
57
+ * Domain rail: `?email` must share `DEV_AUTO_LOGIN_EMAIL`'s domain — even a dev server must not
58
+ * mint sessions (much less accounts) for arbitrary domains; anything else answers 400.
59
+ *
60
+ * A missing account is created through the normal signup creation path (`Signup.createAccount`)
61
+ * as a normal test user — password `test`, matching the seeded test-account convention, so
62
+ * interactive login works for the same identity. Composes with userCache's missing-account→guest
63
+ * seam: that covers sessions whose account was deleted AFTER minting; this ensures dev-minted
64
+ * sessions reference a real account from the start.
51
65
  */
52
66
  exports.devLogin = {
53
67
  path: '/dev/login',
54
68
  method: 'get',
55
69
  onRequest: function (request, response) { return __awaiter(void 0, void 0, void 0, function () {
56
- var email;
57
- var _a;
58
- return __generator(this, function (_b) {
59
- switch (_b.label) {
70
+ var envEmail, email, emailParam, requested, creation;
71
+ var _a, _b;
72
+ return __generator(this, function (_c) {
73
+ switch (_c.label) {
60
74
  case 0:
61
- email = ((_a = process.env.DEV_AUTO_LOGIN_EMAIL) !== null && _a !== void 0 ? _a : '').trim();
62
- if (!process.env.DEVELOPMENT || !email) {
75
+ envEmail = ((_a = process.env.DEV_AUTO_LOGIN_EMAIL) !== null && _a !== void 0 ? _a : '').trim();
76
+ if (!process.env.DEVELOPMENT || !envEmail) {
63
77
  response.status(404).send();
64
78
  return [2 /*return*/];
65
79
  }
66
- return [4 /*yield*/, new Promise(function (resolve) { return request.login(email, resolve); })];
80
+ email = envEmail;
81
+ emailParam = (_b = request.query) === null || _b === void 0 ? void 0 : _b.email;
82
+ if (emailParam !== undefined) {
83
+ requested = typeof emailParam === 'string' ? emailParam.trim() : '';
84
+ if (emailDomain(requested) !== emailDomain(envEmail)) {
85
+ response.status(400).send("/dev/login only accepts accounts on the @".concat(emailDomain(envEmail), " domain"));
86
+ return [2 /*return*/];
87
+ }
88
+ email = requested;
89
+ }
90
+ email = email.toLowerCase();
91
+ return [4 /*yield*/, new Signup_1.Signup().createAccount({
92
+ name: email.slice(0, email.indexOf('@')),
93
+ email: email,
94
+ password: 'test',
95
+ emailVerified: false,
96
+ invitedBy: null,
97
+ })];
67
98
  case 1:
68
- _b.sent();
99
+ creation = _c.sent();
100
+ if (creation === 'created') {
101
+ logger.info({ message: 'Dev auto-login created missing test account', obj: { email: email } });
102
+ }
103
+ return [4 /*yield*/, new Promise(function (resolve) { return request.login(email, resolve); })];
104
+ case 2:
105
+ _c.sent();
69
106
  // Explicit save before redirecting: with a DB-backed session store, save-on-response-end
70
107
  // races the redirected GET / — the follow-up request can read the session row before the
71
108
  // write commits and render the login page (observed: first /dev/login load lands on /login,
72
109
  // second succeeds). Awaiting the store write closes the race.
73
110
  return [4 /*yield*/, new Promise(function (resolve) { return request.session.save(resolve); })];
74
- case 2:
111
+ case 3:
75
112
  // Explicit save before redirecting: with a DB-backed session store, save-on-response-end
76
113
  // races the redirected GET / — the follow-up request can read the session row before the
77
114
  // write commits and render the login page (observed: first /dev/login load lands on /login,
78
115
  // second succeeds). Awaiting the store write closes the race.
79
- _b.sent();
116
+ _c.sent();
80
117
  logger.info({ message: 'Dev auto-login session established', obj: { email: email } });
81
118
  response.redirect('/');
82
119
  return [2 /*return*/];
@@ -1 +1 @@
1
- {"version":3,"file":"devLogin.js","sourceRoot":"","sources":["../../../src/routes/devLogin.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,4CAA2C;AAE3C,IAAM,MAAM,GAAG,IAAI,eAAM,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;AAEhD;;;;;;;;;GASG;AACU,QAAA,QAAQ,GAAU;IAC7B,IAAI,EAAE,YAAY;IAClB,MAAM,EAAE,KAAK;IACb,SAAS,EAAE,UAAO,OAAY,EAAE,QAAQ;;;;;;oBAChC,KAAK,GAAG,CAAC,MAAA,OAAO,CAAC,GAAG,CAAC,oBAAoB,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;oBAC9D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,KAAK,EAAE;wBACtC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;wBAC5B,sBAAO;qBACR;oBAED,qBAAM,IAAI,OAAO,CAAC,UAAC,OAAO,IAAK,OAAA,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,EAA7B,CAA6B,CAAC,EAAA;;oBAA7D,SAA6D,CAAC;oBAC9D,yFAAyF;oBACzF,yFAAyF;oBACzF,4FAA4F;oBAC5F,8DAA8D;oBAC9D,qBAAM,IAAI,OAAO,CAAC,UAAC,OAAO,IAAK,OAAA,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAA7B,CAA6B,CAAC,EAAA;;oBAJ7D,yFAAyF;oBACzF,yFAAyF;oBACzF,4FAA4F;oBAC5F,8DAA8D;oBAC9D,SAA6D,CAAC;oBAC9D,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,oCAAoC,EAAE,GAAG,EAAE,EAAE,KAAK,OAAA,EAAE,EAAE,CAAC,CAAC;oBAC/E,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;;;;SACxB;CACF,CAAC"}
1
+ {"version":3,"file":"devLogin.js","sourceRoot":"","sources":["../../../src/routes/devLogin.ts"],"names":[],"mappings":"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"}
@@ -44,7 +44,7 @@ var db_1 = require("@proteinjs/db");
44
44
  var user_1 = require("@proteinjs/user");
45
45
  var logger_1 = require("@proteinjs/logger");
46
46
  var moment_1 = __importDefault(require("moment"));
47
- var sha256_1 = __importDefault(require("crypto-js/sha256"));
47
+ var PasswordHasher_1 = require("../authentication/PasswordHasher");
48
48
  /**
49
49
  * Route handler for executing a password reset.
50
50
  *
@@ -82,14 +82,16 @@ exports.executePasswordReset = {
82
82
  response.status(400).send({ error: 'Reset token has expired' });
83
83
  return [2 /*return*/];
84
84
  }
85
- hashedPassword = (0, sha256_1.default)(newPassword).toString();
85
+ return [4 /*yield*/, new PasswordHasher_1.PasswordHasher().hash(newPassword)];
86
+ case 2:
87
+ hashedPassword = _b.sent();
86
88
  return [4 /*yield*/, db.update(user_1.tables.User, {
87
89
  id: user.id,
88
90
  password: hashedPassword,
89
91
  passwordResetToken: null,
90
92
  passwordResetTokenExpiration: null,
91
93
  })];
92
- case 2:
94
+ case 3:
93
95
  _b.sent();
94
96
  logger.info({ message: "Password successfully reset", obj: { email: user.email } });
95
97
  response.send({ message: 'Password has been successfully reset' });
@@ -1 +1 @@
1
- {"version":3,"file":"executePasswordReset.js","sourceRoot":"","sources":["../../../src/routes/executePasswordReset.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,oCAA8C;AAC9C,wCAAiD;AACjD,4CAA2C;AAC3C,kDAA4B;AAC5B,4DAAsC;AAEtC;;;;;;;;;;GAUG;AACU,QAAA,oBAAoB,GAAU;IACzC,IAAI,EAAE,aAAM,CAAC,oBAAoB,CAAC,IAAI;IACtC,MAAM,EAAE,aAAM,CAAC,oBAAoB,CAAC,MAAM;IAC1C,SAAS,EAAE,UAAO,OAAO,EAAE,QAAQ;;;;;oBAC3B,MAAM,GAAG,IAAI,eAAM,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,CAAC,CAAC;oBACtD,KAAyB,OAAO,CAAC,IAAI,EAAnC,KAAK,WAAA,EAAE,WAAW,iBAAA,CAAkB;oBACtC,EAAE,GAAG,IAAA,kBAAa,GAAE,CAAC;oBAGd,qBAAM,EAAE,CAAC,GAAG,CAAC,aAAM,CAAC,IAAI,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,EAAA;;oBAA/D,IAAI,GAAG,SAAwD;oBACrE,IAAI,CAAC,IAAI,EAAE;wBACT,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,0BAA0B,EAAE,GAAG,EAAE,EAAE,KAAK,OAAA,EAAE,EAAE,CAAC,CAAC;wBACrE,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gCAAgC,EAAE,CAAC,CAAC;wBACvE,sBAAO;qBACR;oBAGK,WAAW,GAAG,IAAA,gBAAM,GAAE,CAAC;oBACvB,eAAe,GAAG,IAAA,gBAAM,EAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;oBAClE,IAAI,WAAW,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE;wBACxC,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,0BAA0B,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;wBACjF,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC,CAAC;wBAChE,sBAAO;qBACR;oBAGK,cAAc,GAAG,IAAA,gBAAM,EAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,CAAC;oBACtD,qBAAM,EAAE,CAAC,MAAM,CAAC,aAAM,CAAC,IAAI,EAAE;4BAC3B,EAAE,EAAE,IAAI,CAAC,EAAE;4BACX,QAAQ,EAAE,cAAc;4BACxB,kBAAkB,EAAE,IAAI;4BACxB,4BAA4B,EAAE,IAAI;yBACnC,CAAC,EAAA;;oBALF,SAKE,CAAC;oBAEH,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,6BAA6B,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBACpF,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,sCAAsC,EAAE,CAAC,CAAC;;;;SACpE;CACF,CAAC"}
1
+ {"version":3,"file":"executePasswordReset.js","sourceRoot":"","sources":["../../../src/routes/executePasswordReset.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,oCAA8C;AAC9C,wCAAiD;AACjD,4CAA2C;AAC3C,kDAA4B;AAC5B,mEAAkE;AAElE;;;;;;;;;;GAUG;AACU,QAAA,oBAAoB,GAAU;IACzC,IAAI,EAAE,aAAM,CAAC,oBAAoB,CAAC,IAAI;IACtC,MAAM,EAAE,aAAM,CAAC,oBAAoB,CAAC,MAAM;IAC1C,SAAS,EAAE,UAAO,OAAO,EAAE,QAAQ;;;;;oBAC3B,MAAM,GAAG,IAAI,eAAM,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,CAAC,CAAC;oBACtD,KAAyB,OAAO,CAAC,IAAI,EAAnC,KAAK,WAAA,EAAE,WAAW,iBAAA,CAAkB;oBACtC,EAAE,GAAG,IAAA,kBAAa,GAAE,CAAC;oBAGd,qBAAM,EAAE,CAAC,GAAG,CAAC,aAAM,CAAC,IAAI,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,EAAA;;oBAA/D,IAAI,GAAG,SAAwD;oBACrE,IAAI,CAAC,IAAI,EAAE;wBACT,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,0BAA0B,EAAE,GAAG,EAAE,EAAE,KAAK,OAAA,EAAE,EAAE,CAAC,CAAC;wBACrE,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gCAAgC,EAAE,CAAC,CAAC;wBACvE,sBAAO;qBACR;oBAGK,WAAW,GAAG,IAAA,gBAAM,GAAE,CAAC;oBACvB,eAAe,GAAG,IAAA,gBAAM,EAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;oBAClE,IAAI,WAAW,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE;wBACxC,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,0BAA0B,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;wBACjF,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC,CAAC;wBAChE,sBAAO;qBACR;oBAGsB,qBAAM,IAAI,+BAAc,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,EAAA;;oBAA7D,cAAc,GAAG,SAA4C;oBACnE,qBAAM,EAAE,CAAC,MAAM,CAAC,aAAM,CAAC,IAAI,EAAE;4BAC3B,EAAE,EAAE,IAAI,CAAC,EAAE;4BACX,QAAQ,EAAE,cAAc;4BACxB,kBAAkB,EAAE,IAAI;4BACxB,4BAA4B,EAAE,IAAI;yBACnC,CAAC,EAAA;;oBALF,SAKE,CAAC;oBAEH,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,6BAA6B,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBACpF,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,sCAAsC,EAAE,CAAC,CAAC;;;;SACpE;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/routes/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAI9C,eAAO,MAAM,KAAK,EAAE,KAwBnB,CAAC"}
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/routes/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAK9C,eAAO,MAAM,KAAK,EAAE,KA8CnB,CAAC"}
@@ -39,11 +39,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.login = void 0;
40
40
  var user_1 = require("@proteinjs/user");
41
41
  var authenticate_1 = require("../authentication/authenticate");
42
+ var AccountDeletion_1 = require("../services/AccountDeletion");
42
43
  exports.login = {
43
44
  path: user_1.routes.login.path,
44
45
  method: user_1.routes.login.method,
45
46
  onRequest: function (request, response) { return __awaiter(void 0, void 0, void 0, function () {
46
- var credentials, error, result;
47
+ var credentials, error, result, outcome, error_1, error;
47
48
  return __generator(this, function (_a) {
48
49
  switch (_a.label) {
49
50
  case 0:
@@ -62,10 +63,33 @@ exports.login = {
62
63
  response.send({ error: result });
63
64
  return [2 /*return*/];
64
65
  }
66
+ _a.label = 2;
67
+ case 2:
68
+ _a.trys.push([2, 4, , 5]);
69
+ return [4 /*yield*/, new AccountDeletion_1.AccountDeletion().cancelPendingDeletion(credentials.email)];
70
+ case 3:
71
+ outcome = _a.sent();
72
+ return [3 /*break*/, 5];
73
+ case 4:
74
+ error_1 = _a.sent();
75
+ // Security boundary: the login response never carries internal error detail — an
76
+ // attacker probing emails must learn nothing from failure shapes (founder ruling
77
+ // 2026-08-18 after a watcher error surfaced verbatim in the login form). The real
78
+ // error stays loud in the server log.
79
+ console.error('cancelPendingDeletion failed during login', error_1);
80
+ response.send({ error: 'Unable to log in right now. Please try again.' });
81
+ return [2 /*return*/];
82
+ case 5:
83
+ if (outcome === 'purging') {
84
+ error = 'This account is being deleted and can no longer be restored.';
85
+ console.error(error);
86
+ response.send({ error: error });
87
+ return [2 /*return*/];
88
+ }
65
89
  return [4 /*yield*/, new Promise(function (resolve, reject) {
66
90
  request.login(credentials.email, resolve);
67
91
  })];
68
- case 2:
92
+ case 6:
69
93
  _a.sent();
70
94
  response.send({});
71
95
  return [2 /*return*/];
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/routes/login.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,wCAAyC;AACzC,+DAA8D;AAEjD,QAAA,KAAK,GAAU;IAC1B,IAAI,EAAE,aAAM,CAAC,KAAK,CAAC,IAAI;IACvB,MAAM,EAAE,aAAM,CAAC,KAAK,CAAC,MAAM;IAC3B,SAAS,EAAE,UAAO,OAAY,EAAE,QAAQ;;;;;oBAChC,WAAW,GAAwC,OAAO,CAAC,IAAI,CAAC;oBACtE,IAAI,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE;wBACzC,KAAK,GAAG,oCAAoC,CAAC;wBACnD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;wBACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,OAAA,EAAE,CAAC,CAAC;wBACzB,sBAAO;qBACR;oBAEc,qBAAM,IAAA,2BAAY,EAAC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,EAAA;;oBAApE,MAAM,GAAG,SAA2D;oBAC1E,IAAI,MAAM,KAAK,IAAI,EAAE;wBACnB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;wBACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;wBACjC,sBAAO;qBACR;oBAED,qBAAM,IAAI,OAAO,CAAC,UAAC,OAAO,EAAE,MAAM;4BAChC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;wBAC5C,CAAC,CAAC,EAAA;;oBAFF,SAEE,CAAC;oBACH,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;;;;SACnB;CACF,CAAC"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/routes/login.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,wCAAyC;AACzC,+DAA8D;AAC9D,+DAA8D;AAEjD,QAAA,KAAK,GAAU;IAC1B,IAAI,EAAE,aAAM,CAAC,KAAK,CAAC,IAAI;IACvB,MAAM,EAAE,aAAM,CAAC,KAAK,CAAC,MAAM;IAC3B,SAAS,EAAE,UAAO,OAAY,EAAE,QAAQ;;;;;oBAChC,WAAW,GAAwC,OAAO,CAAC,IAAI,CAAC;oBACtE,IAAI,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE;wBACzC,KAAK,GAAG,oCAAoC,CAAC;wBACnD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;wBACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,OAAA,EAAE,CAAC,CAAC;wBACzB,sBAAO;qBACR;oBAEc,qBAAM,IAAA,2BAAY,EAAC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,EAAA;;oBAApE,MAAM,GAAG,SAA2D;oBAC1E,IAAI,MAAM,KAAK,IAAI,EAAE;wBACnB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;wBACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;wBACjC,sBAAO;qBACR;;;;oBAOW,qBAAM,IAAI,iCAAe,EAAE,CAAC,qBAAqB,CAAC,WAAW,CAAC,KAAK,CAAC,EAAA;;oBAA9E,OAAO,GAAG,SAAoE,CAAC;;;;oBAE/E,iFAAiF;oBACjF,iFAAiF;oBACjF,kFAAkF;oBAClF,sCAAsC;oBACtC,OAAO,CAAC,KAAK,CAAC,2CAA2C,EAAE,OAAK,CAAC,CAAC;oBAClE,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,+CAA+C,EAAE,CAAC,CAAC;oBAC1E,sBAAO;;oBAET,IAAI,OAAO,KAAK,SAAS,EAAE;wBACnB,KAAK,GAAG,8DAA8D,CAAC;wBAC7E,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;wBACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,OAAA,EAAE,CAAC,CAAC;wBACzB,sBAAO;qBACR;oBAED,qBAAM,IAAI,OAAO,CAAC,UAAC,OAAO,EAAE,MAAM;4BAChC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;wBAC5C,CAAC,CAAC,EAAA;;oBAFF,SAEE,CAAC;oBACH,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;;;;SACnB;CACF,CAAC"}
@@ -0,0 +1,52 @@
1
+ import { Moment } from 'moment';
2
+ import { Service } from '@proteinjs/service';
3
+ import { AccountDeletionService } from '@proteinjs/user';
4
+ /**
5
+ * Deactivation ("gone right away") + cancel-by-login — the synchronous half of archive-then-purge.
6
+ * The purge walker (flow-server) owns erasure after the grace window; this service owns entering
7
+ * and leaving the deactivated state, driven by the `account_deletion` manifest row.
8
+ *
9
+ * Deliberately NOT deactivation's job: the user's own content_reference/content_seen/pins/
10
+ * notifications — all scoped to the locked-out user, invisible behind the auth gate, purged by
11
+ * the walker. Leaving them preserves watermarks and pins exactly for cancel-restore.
12
+ */
13
+ export declare class AccountDeletion implements AccountDeletionService {
14
+ /** Any authenticated user — the call acts only on the session user (re-auth inside). */
15
+ serviceMetadata: Service['serviceMetadata'];
16
+ private logger;
17
+ /**
18
+ * §3.3 — seven steps, each idempotent; a re-call after a partial failure resumes from the
19
+ * stored manifest. The caller's sessions die last, so the response is the last authenticated
20
+ * exchange.
21
+ */
22
+ requestDeletion(password: string): Promise<{
23
+ purgeAfter: Moment;
24
+ }>;
25
+ /**
26
+ * §3.4 — logging back in IS the cancel (called by the login route after `authenticate`
27
+ * passes, BEFORE `request.login`). Not RPC-reachable: it is deliberately absent from the
28
+ * AccountDeletionService interface, so the service router never exposes it.
29
+ */
30
+ cancelPendingDeletion(email: string): Promise<'not-pending' | 'restored' | 'purging'>;
31
+ /** Verify the caller's password against their own account row; throws with nothing written. */
32
+ private reauthenticateSessionUser;
33
+ /**
34
+ * §3.3 step 3: enumerate grants in both directions and persist the manifest row — phase
35
+ * 'grace', full grant set, owned-resource snapshot — before any mutation.
36
+ */
37
+ private createDeletionManifest;
38
+ /** Revoke grants by manifest id, in chunks of 100. Already-deleted ids no-op. */
39
+ private deleteGrantsById;
40
+ /** §3.4 step 3: per entry, get by (principal, resource, accessLevel) → insert if missing. */
41
+ private restoreManifestGrants;
42
+ private toManifestGrant;
43
+ /** A grant reference's id, loudly — the manifest must never be built from corrupt grants. */
44
+ private referenceId;
45
+ /**
46
+ * Grace window in days (ACCOUNT_DELETION_GRACE_DAYS, default 30). Fractional values are
47
+ * honored so dev verification can shorten the window to minutes.
48
+ */
49
+ private gracePeriodDays;
50
+ private chunk;
51
+ }
52
+ //# sourceMappingURL=AccountDeletion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AccountDeletion.d.ts","sourceRoot":"","sources":["../../../src/services/AccountDeletion.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGxC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAGL,sBAAsB,EAKvB,MAAM,iBAAiB,CAAC;AASzB;;;;;;;;GAQG;AACH,qBAAa,eAAgB,YAAW,sBAAsB;IAC5D,wFAAwF;IACjF,eAAe,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAIhD;IACF,OAAO,CAAC,MAAM,CAA+C;IAE7D;;;;OAIG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAsDxE;;;;OAIG;IACG,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,UAAU,GAAG,SAAS,CAAC;IA0C3F,+FAA+F;YACjF,yBAAyB;IAoBvC;;;OAGG;YACW,sBAAsB;IA6CpC,iFAAiF;YACnE,gBAAgB;IAS9B,6FAA6F;YAC/E,qBAAqB;IAsBnC,OAAO,CAAC,eAAe;IAUvB,6FAA6F;IAC7F,OAAO,CAAC,WAAW;IAOnB;;;OAGG;IACH,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,KAAK;CAOd"}