@proteinjs/user-server 1.0.33 → 1.0.34

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 CHANGED
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.0.34](https://github.com/proteinjs/user/compare/@proteinjs/user-server@1.0.33...@proteinjs/user-server@1.0.34) (2024-07-12)
7
+
8
+ **Note:** Version bump only for package @proteinjs/user-server
9
+
10
+
11
+
12
+
13
+
6
14
  ## [1.0.27](https://github.com/proteinjs/user/compare/@proteinjs/user-server@1.0.26...@proteinjs/user-server@1.0.27) (2024-06-27)
7
15
 
8
16
  **Note:** Version bump only for package @proteinjs/user-server
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Brent Bahry
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -3,6 +3,7 @@ import '@proteinjs/db';
3
3
  import '@proteinjs/reflection';
4
4
  import '@proteinjs/server-api';
5
5
  import '@proteinjs/user';
6
+ import '@proteinjs/email-server';
6
7
  import '@proteinjs/util';
7
8
  import 'crypto-js';
8
9
  import 'express-session';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../generated/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AAEpC,OAAO,eAAe,CAAC;AACvB,OAAO,uBAAuB,CAAC;AAC/B,OAAO,uBAAuB,CAAC;AAC/B,OAAO,iBAAiB,CAAC;AACzB,OAAO,iBAAiB,CAAC;AACzB,OAAO,WAAW,CAAC;AACnB,OAAO,iBAAiB,CAAC;AACzB,OAAO,QAAQ,CAAC;AA+BhB,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../generated/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AAEpC,OAAO,eAAe,CAAC;AACvB,OAAO,uBAAuB,CAAC;AAC/B,OAAO,uBAAuB,CAAC;AAC/B,OAAO,iBAAiB,CAAC;AACzB,OAAO,yBAAyB,CAAC;AACjC,OAAO,iBAAiB,CAAC;AACzB,OAAO,WAAW,CAAC;AACnB,OAAO,iBAAiB,CAAC;AACzB,OAAO,QAAQ,CAAC;AAqChB,cAAc,UAAU,CAAC"}
@@ -19,24 +19,31 @@ require("@proteinjs/db");
19
19
  require("@proteinjs/reflection");
20
20
  require("@proteinjs/server-api");
21
21
  require("@proteinjs/user");
22
+ require("@proteinjs/email-server");
22
23
  require("@proteinjs/util");
23
24
  require("crypto-js");
24
25
  require("express-session");
25
26
  require("moment");
26
27
  /** Generate Source Graph */
27
- var sourceGraph = "{\"options\":{\"directed\":true,\"multigraph\":false,\"compound\":false},\"nodes\":[{\"v\":\"@proteinjs/user-server/DbSessionStore\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"DbSessionStore\",\"filePath\":\"/Users/veronica/Repositories/n3xa-meta-repo/packages/proteinjs/packages/user/packages/server/src/authentication/DbSessionStore.ts\",\"qualifiedName\":\"@proteinjs/user-server/DbSessionStore\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"TWELVE_HOURS\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"get\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"set\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"touch\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"destroy\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"insertOrUpdate\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<void>\",\"filePath\":null,\"qualifiedName\":\"/Promise<void>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[{\"name\":\"sessionId\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"session\",\"type\":{\"packageName\":\"\",\"name\":\"Express.SessionData\",\"filePath\":null,\"qualifiedName\":\"/Express.SessionData\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"cb\",\"type\":{\"packageName\":\"\",\"name\":\"(error?: any) => void\",\"filePath\":null,\"qualifiedName\":\"/(error?: any) => void\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"sweep\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<void>\",\"filePath\":null,\"qualifiedName\":\"/Promise<void>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[],\"directParentClasses\":[{\"packageName\":\"express-session\",\"name\":\"Store\",\"filePath\":null,\"qualifiedName\":\"express-session/Store\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParentInterfaces\":[],\"directParentClasses\":[]}],\"sourceType\":2}},{\"v\":\"express-session/Store\"},{\"v\":\"@proteinjs/user-server/userCache\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"userCache\",\"filePath\":\"/Users/veronica/Repositories/n3xa-meta-repo/packages/proteinjs/packages/user/packages/server/src/authorization/userCache.ts\",\"qualifiedName\":\"@proteinjs/user-server/userCache\",\"type\":{\"packageName\":\"\",\"name\":\"SessionDataCache<User>\",\"filePath\":null,\"qualifiedName\":\"/SessionDataCache<User>\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionDataCache\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionDataCache\",\"typeParameters\":[\"@proteinjs/user/User\"],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/SessionDataCache\"},{\"v\":\"@proteinjs/user-server/createUser\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"createUser\",\"filePath\":\"/Users/veronica/Repositories/n3xa-meta-repo/packages/proteinjs/packages/user/packages/server/src/routes/createUser.ts\",\"qualifiedName\":\"@proteinjs/user-server/createUser\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/Route\"},{\"v\":\"@proteinjs/user-server/login\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"login\",\"filePath\":\"/Users/veronica/Repositories/n3xa-meta-repo/packages/proteinjs/packages/user/packages/server/src/routes/login.ts\",\"qualifiedName\":\"@proteinjs/user-server/login\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/user-server/logout\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"logout\",\"filePath\":\"/Users/veronica/Repositories/n3xa-meta-repo/packages/proteinjs/packages/user/packages/server/src/routes/logout.ts\",\"qualifiedName\":\"@proteinjs/user-server/logout\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}}],\"edges\":[{\"v\":\"@proteinjs/user-server/DbSessionStore\",\"w\":\"express-session/Store\",\"value\":\"extends class\"},{\"v\":\"@proteinjs/user-server/userCache\",\"w\":\"@proteinjs/server-api/SessionDataCache\",\"value\":\"has type\"},{\"v\":\"@proteinjs/user-server/createUser\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"},{\"v\":\"@proteinjs/user-server/login\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"},{\"v\":\"@proteinjs/user-server/logout\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"}]}";
28
+ var sourceGraph = "{\"options\":{\"directed\":true,\"multigraph\":false,\"compound\":false},\"nodes\":[{\"v\":\"@proteinjs/user-server/DbSessionStore\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"DbSessionStore\",\"filePath\":\"/home/runner/work/user/user/packages/server/src/authentication/DbSessionStore.ts\",\"qualifiedName\":\"@proteinjs/user-server/DbSessionStore\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"TWELVE_HOURS\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"get\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"set\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"touch\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"destroy\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"insertOrUpdate\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<void>\",\"filePath\":null,\"qualifiedName\":\"/Promise<void>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[{\"name\":\"sessionId\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"session\",\"type\":{\"packageName\":\"\",\"name\":\"Express.SessionData\",\"filePath\":null,\"qualifiedName\":\"/Express.SessionData\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"cb\",\"type\":{\"packageName\":\"\",\"name\":\"(error?: any) => void\",\"filePath\":null,\"qualifiedName\":\"/(error?: any) => void\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"sweep\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<void>\",\"filePath\":null,\"qualifiedName\":\"/Promise<void>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[],\"directParentClasses\":[{\"packageName\":\"express-session\",\"name\":\"Store\",\"filePath\":null,\"qualifiedName\":\"express-session/Store\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParentInterfaces\":[],\"directParentClasses\":[]}],\"sourceType\":2}},{\"v\":\"express-session/Store\"},{\"v\":\"@proteinjs/user-server/userCache\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"userCache\",\"filePath\":\"/home/runner/work/user/user/packages/server/src/authorization/userCache.ts\",\"qualifiedName\":\"@proteinjs/user-server/userCache\",\"type\":{\"packageName\":\"\",\"name\":\"SessionDataCache<User>\",\"filePath\":null,\"qualifiedName\":\"/SessionDataCache<User>\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionDataCache\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionDataCache\",\"typeParameters\":[\"@proteinjs/user/User\"],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/SessionDataCache\"},{\"v\":\"@proteinjs/user-server/createUser\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"createUser\",\"filePath\":\"/home/runner/work/user/user/packages/server/src/routes/createUser.ts\",\"qualifiedName\":\"@proteinjs/user-server/createUser\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/Route\"},{\"v\":\"@proteinjs/user-server/executePasswordReset\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"executePasswordReset\",\"filePath\":\"/home/runner/work/user/user/packages/server/src/routes/executePasswordReset.ts\",\"qualifiedName\":\"@proteinjs/user-server/executePasswordReset\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/user-server/initiatePasswordReset\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"initiatePasswordReset\",\"filePath\":\"/home/runner/work/user/user/packages/server/src/routes/initiatePasswordReset.ts\",\"qualifiedName\":\"@proteinjs/user-server/initiatePasswordReset\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/user-server/login\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"login\",\"filePath\":\"/home/runner/work/user/user/packages/server/src/routes/login.ts\",\"qualifiedName\":\"@proteinjs/user-server/login\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/user-server/logout\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"logout\",\"filePath\":\"/home/runner/work/user/user/packages/server/src/routes/logout.ts\",\"qualifiedName\":\"@proteinjs/user-server/logout\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/user-server/validateResetPasswordToken\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"validateResetPasswordToken\",\"filePath\":\"/home/runner/work/user/user/packages/server/src/routes/validateResetPasswordToken.ts\",\"qualifiedName\":\"@proteinjs/user-server/validateResetPasswordToken\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}}],\"edges\":[{\"v\":\"@proteinjs/user-server/DbSessionStore\",\"w\":\"express-session/Store\",\"value\":\"extends class\"},{\"v\":\"@proteinjs/user-server/userCache\",\"w\":\"@proteinjs/server-api/SessionDataCache\",\"value\":\"has type\"},{\"v\":\"@proteinjs/user-server/createUser\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"},{\"v\":\"@proteinjs/user-server/executePasswordReset\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"},{\"v\":\"@proteinjs/user-server/initiatePasswordReset\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"},{\"v\":\"@proteinjs/user-server/login\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"},{\"v\":\"@proteinjs/user-server/logout\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"},{\"v\":\"@proteinjs/user-server/validateResetPasswordToken\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"}]}";
28
29
  /** Generate Source Links */
29
30
  var DbSessionStore_1 = require("../src/authentication/DbSessionStore");
30
31
  var userCache_1 = require("../src/authorization/userCache");
31
32
  var createUser_1 = require("../src/routes/createUser");
33
+ var executePasswordReset_1 = require("../src/routes/executePasswordReset");
34
+ var initiatePasswordReset_1 = require("../src/routes/initiatePasswordReset");
32
35
  var login_1 = require("../src/routes/login");
33
36
  var logout_1 = require("../src/routes/logout");
37
+ var validateResetPasswordToken_1 = require("../src/routes/validateResetPasswordToken");
34
38
  var sourceLinks = {
35
39
  '@proteinjs/user-server/DbSessionStore': DbSessionStore_1.DbSessionStore,
36
40
  '@proteinjs/user-server/userCache': userCache_1.userCache,
37
41
  '@proteinjs/user-server/createUser': createUser_1.createUser,
42
+ '@proteinjs/user-server/executePasswordReset': executePasswordReset_1.executePasswordReset,
43
+ '@proteinjs/user-server/initiatePasswordReset': initiatePasswordReset_1.initiatePasswordReset,
38
44
  '@proteinjs/user-server/login': login_1.login,
39
45
  '@proteinjs/user-server/logout': logout_1.logout,
46
+ '@proteinjs/user-server/validateResetPasswordToken': validateResetPasswordToken_1.validateResetPasswordToken,
40
47
  };
41
48
  /** Load Source Graph and Links */
42
49
  var reflection_1 = require("@proteinjs/reflection");
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../generated/index.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;;;;;;;;;;;;;;AAEpC,yBAAuB;AACvB,iCAA+B;AAC/B,iCAA+B;AAC/B,2BAAyB;AACzB,2BAAyB;AACzB,qBAAmB;AACnB,2BAAyB;AACzB,kBAAgB;AAGhB,4BAA4B;AAE5B,IAAM,WAAW,GAAG,6qMAA6qM,CAAC;AAGlsM,4BAA4B;AAE5B,uEAAsE;AACtE,4DAA2D;AAC3D,uDAAsD;AACtD,6CAA4C;AAC5C,+CAA8C;AAE9C,IAAM,WAAW,GAAG;IACnB,uCAAuC,EAAE,+BAAc;IACvD,kCAAkC,EAAE,qBAAS;IAC7C,mCAAmC,EAAE,uBAAU;IAC/C,8BAA8B,EAAE,aAAK;IACrC,+BAA+B,EAAE,eAAM;CACvC,CAAC;AAGF,kCAAkC;AAElC,oDAAyD;AACzD,6BAAgB,CAAC,KAAK,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AAGjD,2CAAyB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../generated/index.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;;;;;;;;;;;;;;AAEpC,yBAAuB;AACvB,iCAA+B;AAC/B,iCAA+B;AAC/B,2BAAyB;AACzB,mCAAiC;AACjC,2BAAyB;AACzB,qBAAmB;AACnB,2BAAyB;AACzB,kBAAgB;AAGhB,4BAA4B;AAE5B,IAAM,WAAW,GAAG,u6QAAu6Q,CAAC;AAG57Q,4BAA4B;AAE5B,uEAAsE;AACtE,4DAA2D;AAC3D,uDAAsD;AACtD,2EAA0E;AAC1E,6EAA4E;AAC5E,6CAA4C;AAC5C,+CAA8C;AAC9C,uFAAsF;AAEtF,IAAM,WAAW,GAAG;IACnB,uCAAuC,EAAE,+BAAc;IACvD,kCAAkC,EAAE,qBAAS;IAC7C,mCAAmC,EAAE,uBAAU;IAC/C,6CAA6C,EAAE,2CAAoB;IACnE,8CAA8C,EAAE,6CAAqB;IACrE,8BAA8B,EAAE,aAAK;IACrC,+BAA+B,EAAE,eAAM;IACvC,mDAAmD,EAAE,uDAA0B;CAC/E,CAAC;AAGF,kCAAkC;AAElC,oDAAyD;AACzD,6BAAgB,CAAC,KAAK,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AAGjD,2CAAyB"}
@@ -0,0 +1,14 @@
1
+ import { Route } from '@proteinjs/server-api';
2
+ /**
3
+ * Route handler for executing a password reset.
4
+ *
5
+ * This function handles the process of resetting a user's password using a provided reset token.
6
+ * It verifies the token, checks its expiration, and updates the user's password if everything is valid.
7
+ *
8
+ * @bodyParam {string} token - The password reset token.
9
+ * @bodyParam {string} newPassword - The new password for the user.
10
+ *
11
+ * @throws {Error} If there's an issue with the database operations or if the token is invalid or expired.
12
+ */
13
+ export declare const executePasswordReset: Route;
14
+ //# sourceMappingURL=executePasswordReset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executePasswordReset.d.ts","sourceRoot":"","sources":["../../../src/routes/executePasswordReset.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAO9C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,EAAE,KAqClC,CAAC"}
@@ -0,0 +1,101 @@
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
+ exports.executePasswordReset = void 0;
43
+ var db_1 = require("@proteinjs/db");
44
+ var user_1 = require("@proteinjs/user");
45
+ var util_1 = require("@proteinjs/util");
46
+ var moment_1 = __importDefault(require("moment"));
47
+ var sha256_1 = __importDefault(require("crypto-js/sha256"));
48
+ /**
49
+ * Route handler for executing a password reset.
50
+ *
51
+ * This function handles the process of resetting a user's password using a provided reset token.
52
+ * It verifies the token, checks its expiration, and updates the user's password if everything is valid.
53
+ *
54
+ * @bodyParam {string} token - The password reset token.
55
+ * @bodyParam {string} newPassword - The new password for the user.
56
+ *
57
+ * @throws {Error} If there's an issue with the database operations or if the token is invalid or expired.
58
+ */
59
+ exports.executePasswordReset = {
60
+ path: user_1.routes.executePasswordReset.path,
61
+ method: user_1.routes.executePasswordReset.method,
62
+ onRequest: function (request, response) { return __awaiter(void 0, void 0, void 0, function () {
63
+ var logger, _a, token, newPassword, db, user, currentTime, tokenExpiration, hashedPassword;
64
+ return __generator(this, function (_b) {
65
+ switch (_b.label) {
66
+ case 0:
67
+ logger = new util_1.Logger('executePasswordReset');
68
+ _a = request.body, token = _a.token, newPassword = _a.newPassword;
69
+ db = (0, db_1.getDbAsSystem)();
70
+ return [4 /*yield*/, db.get(user_1.tables.User, { passwordResetToken: token })];
71
+ case 1:
72
+ user = _b.sent();
73
+ if (!user) {
74
+ logger.info("Invalid reset token used: ".concat(token));
75
+ response.status(400).send({ error: 'Invalid or expired reset token' });
76
+ return [2 /*return*/];
77
+ }
78
+ currentTime = (0, moment_1.default)();
79
+ tokenExpiration = (0, moment_1.default)(user.passwordResetTokenExpiration);
80
+ if (currentTime.isAfter(tokenExpiration)) {
81
+ logger.info("Expired reset token used for user: ".concat(user.email));
82
+ response.status(400).send({ error: 'Reset token has expired' });
83
+ return [2 /*return*/];
84
+ }
85
+ hashedPassword = (0, sha256_1.default)(newPassword).toString();
86
+ return [4 /*yield*/, db.update(user_1.tables.User, {
87
+ id: user.id,
88
+ password: hashedPassword,
89
+ passwordResetToken: null,
90
+ passwordResetTokenExpiration: null,
91
+ })];
92
+ case 2:
93
+ _b.sent();
94
+ logger.info("Password successfully reset for user: ".concat(user.email));
95
+ response.send({ message: 'Password has been successfully reset' });
96
+ return [2 /*return*/];
97
+ }
98
+ });
99
+ }); },
100
+ };
101
+ //# sourceMappingURL=executePasswordReset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executePasswordReset.js","sourceRoot":"","sources":["../../../src/routes/executePasswordReset.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,oCAA8C;AAC9C,wCAAiD;AACjD,wCAAyC;AACzC,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,aAAM,CAAC,sBAAsB,CAAC,CAAC;oBAC5C,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,oCAA6B,KAAK,CAAE,CAAC,CAAC;wBAClD,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,6CAAsC,IAAI,CAAC,KAAK,CAAE,CAAC,CAAC;wBAChE,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,gDAAyC,IAAI,CAAC,KAAK,CAAE,CAAC,CAAC;oBACnE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,sCAAsC,EAAE,CAAC,CAAC;;;;SACpE;CACF,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { Route } from '@proteinjs/server-api';
2
+ /**
3
+ * Route for initiating a password reset process.
4
+ *
5
+ * This route handles the process of generating a password reset token,
6
+ * sending a reset email to the user, and storing the token and expiration of the token in the database.
7
+ *
8
+ * Requires an implementation of `DefaultPasswordResetEmailConfigFactory` to build the password reset email with.
9
+ *
10
+ * @bodyParam {string} email - The email address of the user requesting a password reset.
11
+ * @bodyParam {string} resetPath - The path to the password reset page in the client application.
12
+ * This will be combined with the generated token to create the reset link that is emailed to the user.
13
+ *
14
+ * @throws {Error} If there's an issue with sending the email or updating the database.
15
+ */
16
+ export declare const initiatePasswordReset: Route;
17
+ //# sourceMappingURL=initiatePasswordReset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initiatePasswordReset.d.ts","sourceRoot":"","sources":["../../../src/routes/initiatePasswordReset.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAW9C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAgEnC,CAAC"}
@@ -0,0 +1,134 @@
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
+ exports.initiatePasswordReset = void 0;
43
+ var db_1 = require("@proteinjs/db");
44
+ var user_1 = require("@proteinjs/user");
45
+ var util_1 = require("@proteinjs/util");
46
+ var moment_1 = __importDefault(require("moment"));
47
+ var email_server_1 = require("@proteinjs/email-server");
48
+ var crypto_js_1 = require("crypto-js");
49
+ /**
50
+ * Route for initiating a password reset process.
51
+ *
52
+ * This route handles the process of generating a password reset token,
53
+ * sending a reset email to the user, and storing the token and expiration of the token in the database.
54
+ *
55
+ * Requires an implementation of `DefaultPasswordResetEmailConfigFactory` to build the password reset email with.
56
+ *
57
+ * @bodyParam {string} email - The email address of the user requesting a password reset.
58
+ * @bodyParam {string} resetPath - The path to the password reset page in the client application.
59
+ * This will be combined with the generated token to create the reset link that is emailed to the user.
60
+ *
61
+ * @throws {Error} If there's an issue with sending the email or updating the database.
62
+ */
63
+ exports.initiatePasswordReset = {
64
+ path: user_1.routes.initiatePasswordReset.path,
65
+ method: user_1.routes.initiatePasswordReset.method,
66
+ onRequest: function (request, response) { return __awaiter(void 0, void 0, void 0, function () {
67
+ var logger, _a, email, resetPath, db, genericResponse, user, currentTime, tokenAge, emailSender, defaultConfigFactory, passwordResetToken, passwordResetTokenExpiration, config, _b, text, html, error_1;
68
+ var _c;
69
+ return __generator(this, function (_d) {
70
+ switch (_d.label) {
71
+ case 0:
72
+ logger = new util_1.Logger('initiatePasswordReset');
73
+ _a = request.body, email = _a.email, resetPath = _a.resetPath;
74
+ db = (0, db_1.getDbAsSystem)();
75
+ genericResponse = { message: 'If an account with that email exists, we have sent a password reset link.' };
76
+ return [4 /*yield*/, db.get(user_1.tables.User, { email: email })];
77
+ case 1:
78
+ user = _d.sent();
79
+ if (!user) {
80
+ logger.info("Password reset requested for non-existent user: ".concat(email));
81
+ // Don't reveal that the user doesn't exist
82
+ response.send(genericResponse);
83
+ return [2 /*return*/];
84
+ }
85
+ currentTime = (0, moment_1.default)();
86
+ if (user.passwordResetToken && user.passwordResetTokenExpiration) {
87
+ tokenAge = currentTime.diff((0, moment_1.default)(user.passwordResetTokenExpiration), 'minutes');
88
+ if (tokenAge < -55) {
89
+ // Token is less than 5 minutes old
90
+ logger.info("Password reset requested too soon for user: ".concat(email));
91
+ response.send(genericResponse);
92
+ return [2 /*return*/];
93
+ }
94
+ }
95
+ emailSender = new email_server_1.EmailSender();
96
+ defaultConfigFactory = (0, email_server_1.getDefaultPasswordResetEmailConfigFactory)();
97
+ if (!defaultConfigFactory) {
98
+ throw new Error("Unable to find a @proteinjs/email-server/DefaultPasswordResetEmailConfigFactory implementation when initiating password reset.");
99
+ }
100
+ passwordResetToken = crypto_js_1.lib.WordArray.random(32).toString();
101
+ passwordResetTokenExpiration = (0, moment_1.default)().add(1, 'hour');
102
+ _d.label = 2;
103
+ case 2:
104
+ _d.trys.push([2, 5, , 6]);
105
+ config = defaultConfigFactory.getConfig();
106
+ _b = config.getEmailContent("".concat(resetPath, "?token=").concat(passwordResetToken)), text = _b.text, html = _b.html;
107
+ // Send email containing a reset link
108
+ return [4 /*yield*/, emailSender.sendEmail({
109
+ to: user.email,
110
+ subject: ((_c = config.options) === null || _c === void 0 ? void 0 : _c.subject) || 'Reset Password',
111
+ text: text,
112
+ html: html,
113
+ })];
114
+ case 3:
115
+ // Send email containing a reset link
116
+ _d.sent();
117
+ // If email is sent successfully, save reset token to user record
118
+ return [4 /*yield*/, db.update(user_1.tables.User, { id: user.id, passwordResetToken: passwordResetToken, passwordResetTokenExpiration: passwordResetTokenExpiration })];
119
+ case 4:
120
+ // If email is sent successfully, save reset token to user record
121
+ _d.sent();
122
+ response.send(genericResponse);
123
+ return [3 /*break*/, 6];
124
+ case 5:
125
+ error_1 = _d.sent();
126
+ logger.error("Failed to send password reset email to: ".concat(email), error_1);
127
+ response.status(500).send({ error: 'Failed to send password reset email. Please try again later.' });
128
+ return [3 /*break*/, 6];
129
+ case 6: return [2 /*return*/];
130
+ }
131
+ });
132
+ }); },
133
+ };
134
+ //# sourceMappingURL=initiatePasswordReset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initiatePasswordReset.js","sourceRoot":"","sources":["../../../src/routes/initiatePasswordReset.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,oCAA8C;AAC9C,wCAAiD;AACjD,wCAAyC;AACzC,kDAA4B;AAC5B,wDAGiC;AACjC,uCAAgC;AAEhC;;;;;;;;;;;;;GAaG;AACU,QAAA,qBAAqB,GAAU;IAC1C,IAAI,EAAE,aAAM,CAAC,qBAAqB,CAAC,IAAI;IACvC,MAAM,EAAE,aAAM,CAAC,qBAAqB,CAAC,MAAM;IAC3C,SAAS,EAAE,UAAO,OAAO,EAAE,QAAQ;;;;;;oBAC3B,MAAM,GAAG,IAAI,aAAM,CAAC,uBAAuB,CAAC,CAAC;oBAC7C,KAAuB,OAAO,CAAC,IAAI,EAAjC,KAAK,WAAA,EAAE,SAAS,eAAA,CAAkB;oBACpC,EAAE,GAAG,IAAA,kBAAa,GAAE,CAAC;oBAErB,eAAe,GAAG,EAAE,OAAO,EAAE,2EAA2E,EAAE,CAAC;oBAGpG,qBAAM,EAAE,CAAC,GAAG,CAAC,aAAM,CAAC,IAAI,EAAE,EAAE,KAAK,OAAA,EAAE,CAAC,EAAA;;oBAA3C,IAAI,GAAG,SAAoC;oBACjD,IAAI,CAAC,IAAI,EAAE;wBACT,MAAM,CAAC,IAAI,CAAC,0DAAmD,KAAK,CAAE,CAAC,CAAC;wBACxE,2CAA2C;wBAC3C,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;wBAC/B,sBAAO;qBACR;oBAGK,WAAW,GAAG,IAAA,gBAAM,GAAE,CAAC;oBAC7B,IAAI,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,4BAA4B,EAAE;wBAC1D,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,IAAA,gBAAM,EAAC,IAAI,CAAC,4BAA4B,CAAC,EAAE,SAAS,CAAC,CAAC;wBACxF,IAAI,QAAQ,GAAG,CAAC,EAAE,EAAE;4BAClB,mCAAmC;4BACnC,MAAM,CAAC,IAAI,CAAC,sDAA+C,KAAK,CAAE,CAAC,CAAC;4BACpE,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;4BAC/B,sBAAO;yBACR;qBACF;oBAEK,WAAW,GAAG,IAAI,0BAAW,EAAE,CAAC;oBAEhC,oBAAoB,GAAG,IAAA,wDAAuB,GAAE,CAAC;oBACvD,IAAI,CAAC,oBAAoB,EAAE;wBACzB,MAAM,IAAI,KAAK,CACb,gIAAgI,CACjI,CAAC;qBACH;oBAGK,kBAAkB,GAAG,eAAG,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;oBACzD,4BAA4B,GAAG,IAAA,gBAAM,GAAE,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;;;;oBAGrD,MAAM,GAAG,oBAAoB,CAAC,SAAS,EAAE,CAAC;oBAC1C,KAAiB,MAAM,CAAC,eAAe,CAAC,UAAG,SAAS,oBAAU,kBAAkB,CAAE,CAAC,EAAjF,IAAI,UAAA,EAAE,IAAI,UAAA,CAAwE;oBAE1F,qCAAqC;oBACrC,qBAAM,WAAW,CAAC,SAAS,CAAC;4BAC1B,EAAE,EAAE,IAAI,CAAC,KAAK;4BACd,OAAO,EAAE,CAAA,MAAA,MAAM,CAAC,OAAO,0CAAE,OAAO,KAAI,gBAAgB;4BACpD,IAAI,MAAA;4BACJ,IAAI,MAAA;yBACL,CAAC,EAAA;;oBANF,qCAAqC;oBACrC,SAKE,CAAC;oBAEH,iEAAiE;oBACjE,qBAAM,EAAE,CAAC,MAAM,CAAC,aAAM,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,kBAAkB,oBAAA,EAAE,4BAA4B,8BAAA,EAAE,CAAC,EAAA;;oBAD/F,iEAAiE;oBACjE,SAA+F,CAAC;oBAChG,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;;;;oBAE/B,MAAM,CAAC,KAAK,CAAC,kDAA2C,KAAK,CAAE,EAAE,OAAK,CAAC,CAAC;oBACxE,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,8DAA8D,EAAE,CAAC,CAAC;;;;;SAExG;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Route } from '@proteinjs/server-api';
2
+ export declare const validateResetPasswordToken: Route;
3
+ //# sourceMappingURL=validateResetPasswordToken.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateResetPasswordToken.d.ts","sourceRoot":"","sources":["../../../src/routes/validateResetPasswordToken.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAM9C,eAAO,MAAM,0BAA0B,EAAE,KAgCxC,CAAC"}
@@ -0,0 +1,83 @@
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
+ exports.validateResetPasswordToken = void 0;
43
+ var db_1 = require("@proteinjs/db");
44
+ var user_1 = require("@proteinjs/user");
45
+ var util_1 = require("@proteinjs/util");
46
+ var moment_1 = __importDefault(require("moment"));
47
+ exports.validateResetPasswordToken = {
48
+ path: user_1.routes.validateResetToken.path,
49
+ method: user_1.routes.validateResetToken.method,
50
+ onRequest: function (request, response) { return __awaiter(void 0, void 0, void 0, function () {
51
+ var logger, token, db, user, currentTime, tokenExpiration;
52
+ return __generator(this, function (_a) {
53
+ switch (_a.label) {
54
+ case 0:
55
+ logger = new util_1.Logger('validateResetToken');
56
+ token = request.query.token;
57
+ db = (0, db_1.getDbAsSystem)();
58
+ if (!token) {
59
+ response.status(400).send({ isValid: false, message: 'No token provided' });
60
+ return [2 /*return*/];
61
+ }
62
+ return [4 /*yield*/, db.get(user_1.tables.User, { passwordResetToken: token })];
63
+ case 1:
64
+ user = _a.sent();
65
+ if (!user) {
66
+ logger.info("Invalid reset token used: ".concat(token));
67
+ response.status(200).send({ isValid: false, message: 'Invalid token' });
68
+ return [2 /*return*/];
69
+ }
70
+ currentTime = (0, moment_1.default)();
71
+ tokenExpiration = (0, moment_1.default)(user.passwordResetTokenExpiration);
72
+ if (currentTime.isAfter(tokenExpiration)) {
73
+ logger.info("Expired reset token used for user: ".concat(user.email));
74
+ response.status(200).send({ isValid: false, message: 'Token has expired' });
75
+ return [2 /*return*/];
76
+ }
77
+ response.status(200).send({ isValid: true });
78
+ return [2 /*return*/];
79
+ }
80
+ });
81
+ }); },
82
+ };
83
+ //# sourceMappingURL=validateResetPasswordToken.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateResetPasswordToken.js","sourceRoot":"","sources":["../../../src/routes/validateResetPasswordToken.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,oCAA8C;AAC9C,wCAAiD;AACjD,wCAAyC;AACzC,kDAA4B;AAEf,QAAA,0BAA0B,GAAU;IAC/C,IAAI,EAAE,aAAM,CAAC,kBAAkB,CAAC,IAAI;IACpC,MAAM,EAAE,aAAM,CAAC,kBAAkB,CAAC,MAAM;IACxC,SAAS,EAAE,UAAO,OAAO,EAAE,QAAQ;;;;;oBAC3B,MAAM,GAAG,IAAI,aAAM,CAAC,oBAAoB,CAAC,CAAC;oBACxC,KAAK,GAAK,OAAO,CAAC,KAAK,MAAlB,CAAmB;oBAC1B,EAAE,GAAG,IAAA,kBAAa,GAAE,CAAC;oBAE3B,IAAI,CAAC,KAAK,EAAE;wBACV,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC;wBAC5E,sBAAO;qBACR;oBAGY,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,oCAA6B,KAAK,CAAE,CAAC,CAAC;wBAClD,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC;wBACxE,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,6CAAsC,IAAI,CAAC,KAAK,CAAE,CAAC,CAAC;wBAChE,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC;wBAC5E,sBAAO;qBACR;oBAED,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;;;;SAC9C;CACF,CAAC"}
@@ -4,38 +4,42 @@ import '@proteinjs/db';
4
4
  import '@proteinjs/reflection';
5
5
  import '@proteinjs/server-api';
6
6
  import '@proteinjs/user';
7
+ import '@proteinjs/email-server';
7
8
  import '@proteinjs/util';
8
9
  import 'crypto-js';
9
10
  import 'express-session';
10
11
  import 'moment';
11
12
 
12
-
13
13
  /** Generate Source Graph */
14
14
 
15
- const sourceGraph = "{\"options\":{\"directed\":true,\"multigraph\":false,\"compound\":false},\"nodes\":[{\"v\":\"@proteinjs/user-server/DbSessionStore\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"DbSessionStore\",\"filePath\":\"/Users/veronica/Repositories/n3xa-meta-repo/packages/proteinjs/packages/user/packages/server/src/authentication/DbSessionStore.ts\",\"qualifiedName\":\"@proteinjs/user-server/DbSessionStore\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"TWELVE_HOURS\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"get\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"set\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"touch\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"destroy\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"insertOrUpdate\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<void>\",\"filePath\":null,\"qualifiedName\":\"/Promise<void>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[{\"name\":\"sessionId\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"session\",\"type\":{\"packageName\":\"\",\"name\":\"Express.SessionData\",\"filePath\":null,\"qualifiedName\":\"/Express.SessionData\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"cb\",\"type\":{\"packageName\":\"\",\"name\":\"(error?: any) => void\",\"filePath\":null,\"qualifiedName\":\"/(error?: any) => void\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"sweep\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<void>\",\"filePath\":null,\"qualifiedName\":\"/Promise<void>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[],\"directParentClasses\":[{\"packageName\":\"express-session\",\"name\":\"Store\",\"filePath\":null,\"qualifiedName\":\"express-session/Store\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParentInterfaces\":[],\"directParentClasses\":[]}],\"sourceType\":2}},{\"v\":\"express-session/Store\"},{\"v\":\"@proteinjs/user-server/userCache\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"userCache\",\"filePath\":\"/Users/veronica/Repositories/n3xa-meta-repo/packages/proteinjs/packages/user/packages/server/src/authorization/userCache.ts\",\"qualifiedName\":\"@proteinjs/user-server/userCache\",\"type\":{\"packageName\":\"\",\"name\":\"SessionDataCache<User>\",\"filePath\":null,\"qualifiedName\":\"/SessionDataCache<User>\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionDataCache\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionDataCache\",\"typeParameters\":[\"@proteinjs/user/User\"],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/SessionDataCache\"},{\"v\":\"@proteinjs/user-server/createUser\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"createUser\",\"filePath\":\"/Users/veronica/Repositories/n3xa-meta-repo/packages/proteinjs/packages/user/packages/server/src/routes/createUser.ts\",\"qualifiedName\":\"@proteinjs/user-server/createUser\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/Route\"},{\"v\":\"@proteinjs/user-server/login\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"login\",\"filePath\":\"/Users/veronica/Repositories/n3xa-meta-repo/packages/proteinjs/packages/user/packages/server/src/routes/login.ts\",\"qualifiedName\":\"@proteinjs/user-server/login\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/user-server/logout\",\"value\":{\"packageName\":\"@proteinjs/user-server\",\"name\":\"logout\",\"filePath\":\"/Users/veronica/Repositories/n3xa-meta-repo/packages/proteinjs/packages/user/packages/server/src/routes/logout.ts\",\"qualifiedName\":\"@proteinjs/user-server/logout\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}}],\"edges\":[{\"v\":\"@proteinjs/user-server/DbSessionStore\",\"w\":\"express-session/Store\",\"value\":\"extends class\"},{\"v\":\"@proteinjs/user-server/userCache\",\"w\":\"@proteinjs/server-api/SessionDataCache\",\"value\":\"has type\"},{\"v\":\"@proteinjs/user-server/createUser\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"},{\"v\":\"@proteinjs/user-server/login\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"},{\"v\":\"@proteinjs/user-server/logout\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"}]}";
16
-
15
+ const sourceGraph =
16
+ '{"options":{"directed":true,"multigraph":false,"compound":false},"nodes":[{"v":"@proteinjs/user-server/DbSessionStore","value":{"packageName":"@proteinjs/user-server","name":"DbSessionStore","filePath":"/home/runner/work/user/user/packages/server/src/authentication/DbSessionStore.ts","qualifiedName":"@proteinjs/user-server/DbSessionStore","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"TWELVE_HOURS","type":null,"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"get","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"set","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"touch","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"destroy","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[{"name":"insertOrUpdate","returnType":{"packageName":"","name":"Promise<void>","filePath":null,"qualifiedName":"/Promise<void>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[{"name":"sessionId","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null}},{"name":"session","type":{"packageName":"","name":"Express.SessionData","filePath":null,"qualifiedName":"/Express.SessionData","typeParameters":null,"directParents":null}},{"name":"cb","type":{"packageName":"","name":"(error?: any) => void","filePath":null,"qualifiedName":"/(error?: any) => void","typeParameters":null,"directParents":null}}]},{"name":"sweep","returnType":{"packageName":"","name":"Promise<void>","filePath":null,"qualifiedName":"/Promise<void>","typeParameters":null,"directParents":null},"isAsync":true,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]}],"typeParameters":[],"directParentInterfaces":[],"directParentClasses":[{"packageName":"express-session","name":"Store","filePath":null,"qualifiedName":"express-session/Store","isAbstract":false,"isStatic":false,"visibility":"public","properties":[],"methods":[],"typeParameters":[],"directParentInterfaces":[],"directParentClasses":[]}],"sourceType":2}},{"v":"express-session/Store"},{"v":"@proteinjs/user-server/userCache","value":{"packageName":"@proteinjs/user-server","name":"userCache","filePath":"/home/runner/work/user/user/packages/server/src/authorization/userCache.ts","qualifiedName":"@proteinjs/user-server/userCache","type":{"packageName":"","name":"SessionDataCache<User>","filePath":null,"qualifiedName":"/SessionDataCache<User>","typeParameters":[],"directParents":[{"packageName":"@proteinjs/server-api","name":"SessionDataCache","filePath":null,"qualifiedName":"@proteinjs/server-api/SessionDataCache","typeParameters":["@proteinjs/user/User"],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/server-api/SessionDataCache"},{"v":"@proteinjs/user-server/createUser","value":{"packageName":"@proteinjs/user-server","name":"createUser","filePath":"/home/runner/work/user/user/packages/server/src/routes/createUser.ts","qualifiedName":"@proteinjs/user-server/createUser","type":{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":[{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/server-api/Route"},{"v":"@proteinjs/user-server/executePasswordReset","value":{"packageName":"@proteinjs/user-server","name":"executePasswordReset","filePath":"/home/runner/work/user/user/packages/server/src/routes/executePasswordReset.ts","qualifiedName":"@proteinjs/user-server/executePasswordReset","type":{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":[{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/user-server/initiatePasswordReset","value":{"packageName":"@proteinjs/user-server","name":"initiatePasswordReset","filePath":"/home/runner/work/user/user/packages/server/src/routes/initiatePasswordReset.ts","qualifiedName":"@proteinjs/user-server/initiatePasswordReset","type":{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":[{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/user-server/login","value":{"packageName":"@proteinjs/user-server","name":"login","filePath":"/home/runner/work/user/user/packages/server/src/routes/login.ts","qualifiedName":"@proteinjs/user-server/login","type":{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":[{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/user-server/logout","value":{"packageName":"@proteinjs/user-server","name":"logout","filePath":"/home/runner/work/user/user/packages/server/src/routes/logout.ts","qualifiedName":"@proteinjs/user-server/logout","type":{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":[{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/user-server/validateResetPasswordToken","value":{"packageName":"@proteinjs/user-server","name":"validateResetPasswordToken","filePath":"/home/runner/work/user/user/packages/server/src/routes/validateResetPasswordToken.ts","qualifiedName":"@proteinjs/user-server/validateResetPasswordToken","type":{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":[{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}}],"edges":[{"v":"@proteinjs/user-server/DbSessionStore","w":"express-session/Store","value":"extends class"},{"v":"@proteinjs/user-server/userCache","w":"@proteinjs/server-api/SessionDataCache","value":"has type"},{"v":"@proteinjs/user-server/createUser","w":"@proteinjs/server-api/Route","value":"has type"},{"v":"@proteinjs/user-server/executePasswordReset","w":"@proteinjs/server-api/Route","value":"has type"},{"v":"@proteinjs/user-server/initiatePasswordReset","w":"@proteinjs/server-api/Route","value":"has type"},{"v":"@proteinjs/user-server/login","w":"@proteinjs/server-api/Route","value":"has type"},{"v":"@proteinjs/user-server/logout","w":"@proteinjs/server-api/Route","value":"has type"},{"v":"@proteinjs/user-server/validateResetPasswordToken","w":"@proteinjs/server-api/Route","value":"has type"}]}';
17
17
 
18
18
  /** Generate Source Links */
19
19
 
20
20
  import { DbSessionStore } from '../src/authentication/DbSessionStore';
21
21
  import { userCache } from '../src/authorization/userCache';
22
22
  import { createUser } from '../src/routes/createUser';
23
+ import { executePasswordReset } from '../src/routes/executePasswordReset';
24
+ import { initiatePasswordReset } from '../src/routes/initiatePasswordReset';
23
25
  import { login } from '../src/routes/login';
24
26
  import { logout } from '../src/routes/logout';
27
+ import { validateResetPasswordToken } from '../src/routes/validateResetPasswordToken';
25
28
 
26
29
  const sourceLinks = {
27
- '@proteinjs/user-server/DbSessionStore': DbSessionStore,
28
- '@proteinjs/user-server/userCache': userCache,
29
- '@proteinjs/user-server/createUser': createUser,
30
- '@proteinjs/user-server/login': login,
31
- '@proteinjs/user-server/logout': logout,
30
+ '@proteinjs/user-server/DbSessionStore': DbSessionStore,
31
+ '@proteinjs/user-server/userCache': userCache,
32
+ '@proteinjs/user-server/createUser': createUser,
33
+ '@proteinjs/user-server/executePasswordReset': executePasswordReset,
34
+ '@proteinjs/user-server/initiatePasswordReset': initiatePasswordReset,
35
+ '@proteinjs/user-server/login': login,
36
+ '@proteinjs/user-server/logout': logout,
37
+ '@proteinjs/user-server/validateResetPasswordToken': validateResetPasswordToken,
32
38
  };
33
39
 
34
-
35
40
  /** Load Source Graph and Links */
36
41
 
37
42
  import { SourceRepository } from '@proteinjs/reflection';
38
43
  SourceRepository.merge(sourceGraph, sourceLinks);
39
44
 
40
-
41
- export * from '../index';
45
+ export * from '../index';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proteinjs/user-server",
3
- "version": "1.0.33",
3
+ "version": "1.0.34",
4
4
  "description": "User server components",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -22,9 +22,10 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "@proteinjs/db": "1.3.1",
25
+ "@proteinjs/email-server": "1.0.3",
25
26
  "@proteinjs/reflection": "1.1.6",
26
27
  "@proteinjs/server-api": "1.3.3",
27
- "@proteinjs/user": "^1.0.33",
28
+ "@proteinjs/user": "^1.0.34",
28
29
  "@proteinjs/util": "1.2.0",
29
30
  "crypto-js": "4.0.0",
30
31
  "express-session": "1.17.1",
@@ -43,5 +44,6 @@
43
44
  "typescript": "5.2.2"
44
45
  },
45
46
  "main": "./dist/generated/index.js",
46
- "types": "./dist/generated/index.d.ts"
47
- }
47
+ "types": "./dist/generated/index.d.ts",
48
+ "gitHead": "392402662a3066f07526c715703f2b381c899ed3"
49
+ }
@@ -0,0 +1,56 @@
1
+ import { Route } from '@proteinjs/server-api';
2
+ import { getDbAsSystem } from '@proteinjs/db';
3
+ import { routes, tables } from '@proteinjs/user';
4
+ import { Logger } from '@proteinjs/util';
5
+ import moment from 'moment';
6
+ import sha256 from 'crypto-js/sha256';
7
+
8
+ /**
9
+ * Route handler for executing a password reset.
10
+ *
11
+ * This function handles the process of resetting a user's password using a provided reset token.
12
+ * It verifies the token, checks its expiration, and updates the user's password if everything is valid.
13
+ *
14
+ * @bodyParam {string} token - The password reset token.
15
+ * @bodyParam {string} newPassword - The new password for the user.
16
+ *
17
+ * @throws {Error} If there's an issue with the database operations or if the token is invalid or expired.
18
+ */
19
+ export const executePasswordReset: Route = {
20
+ path: routes.executePasswordReset.path,
21
+ method: routes.executePasswordReset.method,
22
+ onRequest: async (request, response): Promise<void> => {
23
+ const logger = new Logger('executePasswordReset');
24
+ const { token, newPassword } = request.body;
25
+ const db = getDbAsSystem();
26
+
27
+ // Find user with the given reset token
28
+ const user = await db.get(tables.User, { passwordResetToken: token });
29
+ if (!user) {
30
+ logger.info(`Invalid reset token used: ${token}`);
31
+ response.status(400).send({ error: 'Invalid or expired reset token' });
32
+ return;
33
+ }
34
+
35
+ // Check if token is expired
36
+ const currentTime = moment();
37
+ const tokenExpiration = moment(user.passwordResetTokenExpiration);
38
+ if (currentTime.isAfter(tokenExpiration)) {
39
+ logger.info(`Expired reset token used for user: ${user.email}`);
40
+ response.status(400).send({ error: 'Reset token has expired' });
41
+ return;
42
+ }
43
+
44
+ // Update user's password
45
+ const hashedPassword = sha256(newPassword).toString();
46
+ await db.update(tables.User, {
47
+ id: user.id,
48
+ password: hashedPassword,
49
+ passwordResetToken: null,
50
+ passwordResetTokenExpiration: null,
51
+ });
52
+
53
+ logger.info(`Password successfully reset for user: ${user.email}`);
54
+ response.send({ message: 'Password has been successfully reset' });
55
+ },
56
+ };
@@ -0,0 +1,90 @@
1
+ import { Route } from '@proteinjs/server-api';
2
+ import { getDbAsSystem } from '@proteinjs/db';
3
+ import { routes, tables } from '@proteinjs/user';
4
+ import { Logger } from '@proteinjs/util';
5
+ import moment from 'moment';
6
+ import {
7
+ EmailSender,
8
+ getDefaultPasswordResetEmailConfigFactory as getDefaultConfigFactory,
9
+ } from '@proteinjs/email-server';
10
+ import { lib } from 'crypto-js';
11
+
12
+ /**
13
+ * Route for initiating a password reset process.
14
+ *
15
+ * This route handles the process of generating a password reset token,
16
+ * sending a reset email to the user, and storing the token and expiration of the token in the database.
17
+ *
18
+ * Requires an implementation of `DefaultPasswordResetEmailConfigFactory` to build the password reset email with.
19
+ *
20
+ * @bodyParam {string} email - The email address of the user requesting a password reset.
21
+ * @bodyParam {string} resetPath - The path to the password reset page in the client application.
22
+ * This will be combined with the generated token to create the reset link that is emailed to the user.
23
+ *
24
+ * @throws {Error} If there's an issue with sending the email or updating the database.
25
+ */
26
+ export const initiatePasswordReset: Route = {
27
+ path: routes.initiatePasswordReset.path,
28
+ method: routes.initiatePasswordReset.method,
29
+ onRequest: async (request, response): Promise<void> => {
30
+ const logger = new Logger('initiatePasswordReset');
31
+ const { email, resetPath } = request.body;
32
+ const db = getDbAsSystem();
33
+
34
+ const genericResponse = { message: 'If an account with that email exists, we have sent a password reset link.' };
35
+
36
+ // Check if user exists
37
+ const user = await db.get(tables.User, { email });
38
+ if (!user) {
39
+ logger.info(`Password reset requested for non-existent user: ${email}`);
40
+ // Don't reveal that the user doesn't exist
41
+ response.send(genericResponse);
42
+ return;
43
+ }
44
+
45
+ // Check if there's an existing token and it's less than 5 minutes old
46
+ const currentTime = moment();
47
+ if (user.passwordResetToken && user.passwordResetTokenExpiration) {
48
+ const tokenAge = currentTime.diff(moment(user.passwordResetTokenExpiration), 'minutes');
49
+ if (tokenAge < -55) {
50
+ // Token is less than 5 minutes old
51
+ logger.info(`Password reset requested too soon for user: ${email}`);
52
+ response.send(genericResponse);
53
+ return;
54
+ }
55
+ }
56
+
57
+ const emailSender = new EmailSender();
58
+
59
+ const defaultConfigFactory = getDefaultConfigFactory();
60
+ if (!defaultConfigFactory) {
61
+ throw new Error(
62
+ `Unable to find a @proteinjs/email-server/DefaultPasswordResetEmailConfigFactory implementation when initiating password reset.`
63
+ );
64
+ }
65
+
66
+ // Generate reset token
67
+ const passwordResetToken = lib.WordArray.random(32).toString();
68
+ const passwordResetTokenExpiration = moment().add(1, 'hour');
69
+
70
+ try {
71
+ const config = defaultConfigFactory.getConfig();
72
+ const { text, html } = config.getEmailContent(`${resetPath}?token=${passwordResetToken}`);
73
+
74
+ // Send email containing a reset link
75
+ await emailSender.sendEmail({
76
+ to: user.email,
77
+ subject: config.options?.subject || 'Reset Password',
78
+ text,
79
+ html,
80
+ });
81
+
82
+ // If email is sent successfully, save reset token to user record
83
+ await db.update(tables.User, { id: user.id, passwordResetToken, passwordResetTokenExpiration });
84
+ response.send(genericResponse);
85
+ } catch (error: any) {
86
+ logger.error(`Failed to send password reset email to: ${email}`, error);
87
+ response.status(500).send({ error: 'Failed to send password reset email. Please try again later.' });
88
+ }
89
+ },
90
+ };
@@ -0,0 +1,39 @@
1
+ import { Route } from '@proteinjs/server-api';
2
+ import { getDbAsSystem } from '@proteinjs/db';
3
+ import { routes, tables } from '@proteinjs/user';
4
+ import { Logger } from '@proteinjs/util';
5
+ import moment from 'moment';
6
+
7
+ export const validateResetPasswordToken: Route = {
8
+ path: routes.validateResetToken.path,
9
+ method: routes.validateResetToken.method,
10
+ onRequest: async (request, response): Promise<void> => {
11
+ const logger = new Logger('validateResetToken');
12
+ const { token } = request.query;
13
+ const db = getDbAsSystem();
14
+
15
+ if (!token) {
16
+ response.status(400).send({ isValid: false, message: 'No token provided' });
17
+ return;
18
+ }
19
+
20
+ // Find user with the given reset token
21
+ const user = await db.get(tables.User, { passwordResetToken: token });
22
+ if (!user) {
23
+ logger.info(`Invalid reset token used: ${token}`);
24
+ response.status(200).send({ isValid: false, message: 'Invalid token' });
25
+ return;
26
+ }
27
+
28
+ // Check if token is expired
29
+ const currentTime = moment();
30
+ const tokenExpiration = moment(user.passwordResetTokenExpiration);
31
+ if (currentTime.isAfter(tokenExpiration)) {
32
+ logger.info(`Expired reset token used for user: ${user.email}`);
33
+ response.status(200).send({ isValid: false, message: 'Token has expired' });
34
+ return;
35
+ }
36
+
37
+ response.status(200).send({ isValid: true });
38
+ },
39
+ };