@steedos/accounts 3.0.13-beta.8 → 3.0.13

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 (112) hide show
  1. package/lib/core/index.js +177 -249
  2. package/lib/core/index.js.map +1 -1
  3. package/lib/database-mongo/index.js +1 -1
  4. package/lib/database-mongo/index.js.map +1 -1
  5. package/lib/database-mongo/mongo.js +760 -1278
  6. package/lib/database-mongo/mongo.js.map +1 -1
  7. package/lib/db.js +2 -2
  8. package/lib/db.js.map +1 -1
  9. package/lib/index.js +107 -143
  10. package/lib/index.js.map +1 -1
  11. package/lib/mail.js +36 -47
  12. package/lib/mail.js.map +1 -1
  13. package/lib/password/accounts-password.js +505 -763
  14. package/lib/password/accounts-password.js.map +1 -1
  15. package/lib/password/index.js +2 -2
  16. package/lib/password/index.js.map +1 -1
  17. package/lib/password/utils/encryption.js +10 -22
  18. package/lib/password/utils/encryption.js.map +1 -1
  19. package/lib/password/utils/is-email.js +2 -2
  20. package/lib/password/utils/is-email.js.map +1 -1
  21. package/lib/password/utils/user.js +3 -3
  22. package/lib/password/utils/user.js.map +1 -1
  23. package/lib/rest-express/endpoints/authorize.js +47 -54
  24. package/lib/rest-express/endpoints/authorize.js.map +1 -1
  25. package/lib/rest-express/endpoints/geetestV3/geetest-init.js +85 -131
  26. package/lib/rest-express/endpoints/geetestV3/geetest-init.js.map +1 -1
  27. package/lib/rest-express/endpoints/geetestV3/sdk/geetest_config.js +1 -1
  28. package/lib/rest-express/endpoints/geetestV3/sdk/geetest_config.js.map +1 -1
  29. package/lib/rest-express/endpoints/geetestV3/sdk/geetest_lib.js +112 -160
  30. package/lib/rest-express/endpoints/geetestV3/sdk/geetest_lib.js.map +1 -1
  31. package/lib/rest-express/endpoints/geetestV3/sdk/geetest_lib_result.js +8 -9
  32. package/lib/rest-express/endpoints/geetestV3/sdk/geetest_lib_result.js.map +1 -1
  33. package/lib/rest-express/endpoints/get-user.js +7 -12
  34. package/lib/rest-express/endpoints/get-user.js.map +1 -1
  35. package/lib/rest-express/endpoints/impersonate.js +14 -27
  36. package/lib/rest-express/endpoints/impersonate.js.map +1 -1
  37. package/lib/rest-express/endpoints/initServer.js +9 -13
  38. package/lib/rest-express/endpoints/initServer.js.map +1 -1
  39. package/lib/rest-express/endpoints/login.js +82 -104
  40. package/lib/rest-express/endpoints/login.js.map +1 -1
  41. package/lib/rest-express/endpoints/logout.js +68 -86
  42. package/lib/rest-express/endpoints/logout.js.map +1 -1
  43. package/lib/rest-express/endpoints/oauth/provider-callback.js +29 -37
  44. package/lib/rest-express/endpoints/oauth/provider-callback.js.map +1 -1
  45. package/lib/rest-express/endpoints/password/change-password.js +73 -102
  46. package/lib/rest-express/endpoints/password/change-password.js.map +1 -1
  47. package/lib/rest-express/endpoints/password/register.js +63 -95
  48. package/lib/rest-express/endpoints/password/register.js.map +1 -1
  49. package/lib/rest-express/endpoints/password/reset.js +27 -48
  50. package/lib/rest-express/endpoints/password/reset.js.map +1 -1
  51. package/lib/rest-express/endpoints/password/setSpaceUserPassword.js +112 -144
  52. package/lib/rest-express/endpoints/password/setSpaceUserPassword.js.map +1 -1
  53. package/lib/rest-express/endpoints/password/two-factor.js +39 -70
  54. package/lib/rest-express/endpoints/password/two-factor.js.map +1 -1
  55. package/lib/rest-express/endpoints/password/verify-email.js +34 -65
  56. package/lib/rest-express/endpoints/password/verify-email.js.map +1 -1
  57. package/lib/rest-express/endpoints/password/verify.js +45 -74
  58. package/lib/rest-express/endpoints/password/verify.js.map +1 -1
  59. package/lib/rest-express/endpoints/put-user-name.js +19 -32
  60. package/lib/rest-express/endpoints/put-user-name.js.map +1 -1
  61. package/lib/rest-express/endpoints/refresh-access-token.js +14 -27
  62. package/lib/rest-express/endpoints/refresh-access-token.js.map +1 -1
  63. package/lib/rest-express/endpoints/service-authenticate.js +55 -79
  64. package/lib/rest-express/endpoints/service-authenticate.js.map +1 -1
  65. package/lib/rest-express/endpoints/spaces.js +13 -30
  66. package/lib/rest-express/endpoints/spaces.js.map +1 -1
  67. package/lib/rest-express/endpoints/steedos/accept_invitation.js +28 -42
  68. package/lib/rest-express/endpoints/steedos/accept_invitation.js.map +1 -1
  69. package/lib/rest-express/endpoints/steedos/create-tenant.js +81 -102
  70. package/lib/rest-express/endpoints/steedos/create-tenant.js.map +1 -1
  71. package/lib/rest-express/endpoints/steedos/decline_invitation.js +28 -42
  72. package/lib/rest-express/endpoints/steedos/decline_invitation.js.map +1 -1
  73. package/lib/rest-express/endpoints/steedos/get-tenant.js +54 -67
  74. package/lib/rest-express/endpoints/steedos/get-tenant.js.map +1 -1
  75. package/lib/rest-express/endpoints/steedos/settings.js +110 -127
  76. package/lib/rest-express/endpoints/steedos/settings.js.map +1 -1
  77. package/lib/rest-express/endpoints/update-session.js +33 -48
  78. package/lib/rest-express/endpoints/update-session.js.map +1 -1
  79. package/lib/rest-express/express-middleware.js +57 -59
  80. package/lib/rest-express/express-middleware.js.map +1 -1
  81. package/lib/rest-express/index.js +1 -1
  82. package/lib/rest-express/index.js.map +1 -1
  83. package/lib/rest-express/user-loader.js +67 -86
  84. package/lib/rest-express/user-loader.js.map +1 -1
  85. package/lib/rest-express/utils/get-user-agent.js +2 -2
  86. package/lib/rest-express/utils/get-user-agent.js.map +1 -1
  87. package/lib/rest-express/utils/getClientIp.js +3 -3
  88. package/lib/rest-express/utils/getClientIp.js.map +1 -1
  89. package/lib/rest-express/utils/send-error.js +5 -7
  90. package/lib/rest-express/utils/send-error.js.map +1 -1
  91. package/lib/rest-express/utils/steedos-auth.js +21 -21
  92. package/lib/rest-express/utils/steedos-auth.js.map +1 -1
  93. package/lib/rest-express/utils/users.js +17 -30
  94. package/lib/rest-express/utils/users.js.map +1 -1
  95. package/lib/server/accounts-server.js +413 -574
  96. package/lib/server/accounts-server.js.map +1 -1
  97. package/lib/server/index.js +1 -1
  98. package/lib/server/index.js.map +1 -1
  99. package/lib/server/utils/email.js +19 -35
  100. package/lib/server/utils/email.js.map +1 -1
  101. package/lib/server/utils/get-first-user-email.js +3 -3
  102. package/lib/server/utils/get-first-user-email.js.map +1 -1
  103. package/lib/server/utils/tokens.js +14 -24
  104. package/lib/server/utils/tokens.js.map +1 -1
  105. package/lib/types/index.js +1 -1
  106. package/package.json +5 -5
  107. package/src/database-mongo/mongo.ts +6 -2
  108. package/src/password/accounts-password.ts +61 -0
  109. package/src/rest-express/endpoints/password/change-password.ts +1 -1
  110. package/src/rest-express/endpoints/password/setSpaceUserPassword.ts +5 -0
  111. package/src/rest-express/endpoints/service-authenticate.ts +2 -5
  112. package/src/types/types/user.ts +2 -0
@@ -1,17 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- var tslib_1 = require("tslib");
4
- var lodash_1 = require("lodash");
5
- var server_1 = require("../server");
6
- var utils_1 = require("./utils");
7
- var errors_1 = require("./errors");
8
- var objectql_1 = require("@steedos/objectql");
9
- var EFFECTIVE_TIME = 10;
10
- var CODE_LENGTH = 6;
11
- var MAX_FAILURE_COUNT = 10;
12
- var _ = require("underscore");
13
- var moment = require("moment");
14
- var defaultOptions = {
3
+ const lodash_1 = require("lodash");
4
+ const server_1 = require("../server");
5
+ const utils_1 = require("./utils");
6
+ const errors_1 = require("./errors");
7
+ const objectql_1 = require("@steedos/objectql");
8
+ const EFFECTIVE_TIME = 10;
9
+ const CODE_LENGTH = 6;
10
+ const MAX_FAILURE_COUNT = 10;
11
+ const _ = require("underscore");
12
+ const moment = require("moment");
13
+ const defaultOptions = {
15
14
  verifyEmailTokenExpiration: 259200000,
16
15
  passwordResetTokenExpiration: 259200000,
17
16
  passwordEnrollTokenExpiration: 2592000000,
@@ -19,24 +18,24 @@ var defaultOptions = {
19
18
  returnTokensAfterResetPassword: false,
20
19
  invalidateAllSessionsAfterPasswordReset: true,
21
20
  invalidateAllSessionsAfterPasswordChanged: false,
22
- validateEmail: function (email) {
21
+ validateEmail(email) {
23
22
  return !(0, lodash_1.isEmpty)((0, lodash_1.trim)(email)) && (0, utils_1.isEmail)(email);
24
23
  },
25
- validatePassword: function (password) {
24
+ validatePassword(password) {
26
25
  return !(0, lodash_1.isEmpty)(password);
27
26
  },
28
- validateUsername: function (username) {
29
- var usernameRegex = /^[a-zA-Z][a-zA-Z0-9]*$/;
30
- var isValid = username && !(0, lodash_1.isEmpty)((0, lodash_1.trim)(username)) && usernameRegex.test(username);
27
+ validateUsername(username) {
28
+ const usernameRegex = /^[a-zA-Z][a-zA-Z0-9]*$/;
29
+ const isValid = username && !(0, lodash_1.isEmpty)((0, lodash_1.trim)(username)) && usernameRegex.test(username);
31
30
  return Boolean(isValid);
32
31
  },
33
32
  errors: errors_1.errors,
34
33
  sendVerificationEmailAfterSignup: false,
35
34
  };
36
- var getPathFragmentPrefix = function () {
37
- var config = (0, objectql_1.getSteedosConfig)().email;
38
- var defaultPathPrefix = "accounts/a/#";
39
- var pathFragmentPrefix = config && config.pathFragmentPrefix
35
+ const getPathFragmentPrefix = function () {
36
+ const config = (0, objectql_1.getSteedosConfig)().email;
37
+ const defaultPathPrefix = "accounts/a/#";
38
+ let pathFragmentPrefix = config && config.pathFragmentPrefix
40
39
  ? config.pathFragmentPrefix
41
40
  : defaultPathPrefix;
42
41
  if (pathFragmentPrefix && !/\/$/.test(pathFragmentPrefix)) {
@@ -44,732 +43,492 @@ var getPathFragmentPrefix = function () {
44
43
  }
45
44
  return pathFragmentPrefix;
46
45
  };
47
- var AccountsPassword = (function () {
48
- function AccountsPassword(options) {
49
- if (options === void 0) { options = {}; }
50
- this.serviceName = "password";
51
- this.options = tslib_1.__assign(tslib_1.__assign({}, defaultOptions), options);
46
+ class AccountsPassword {
47
+ serviceName = "password";
48
+ server;
49
+ options;
50
+ db;
51
+ constructor(options = {}) {
52
+ this.options = { ...defaultOptions, ...options };
52
53
  }
53
- AccountsPassword.prototype.setStore = function (store) {
54
+ setStore(store) {
54
55
  this.db = store;
55
- };
56
- AccountsPassword.prototype.authenticate = function (params) {
57
- return tslib_1.__awaiter(this, void 0, void 0, function () {
58
- var user, password, token, locale, passwordUnencrypted, isHashPassword, foundUser;
59
- return tslib_1.__generator(this, function (_a) {
60
- switch (_a.label) {
61
- case 0:
62
- user = params.user, password = params.password, token = params.token, locale = params.locale;
63
- passwordUnencrypted = params["password-unencrypted"];
64
- isHashPassword = true;
65
- if (passwordUnencrypted && !password) {
66
- password = passwordUnencrypted;
67
- isHashPassword = false;
68
- }
69
- if (!(user && token)) return [3, 2];
70
- return [4, this.codeAuthenticator(user, token, locale)];
71
- case 1: return [2, _a.sent()];
72
- case 2:
73
- if (!user || !password) {
74
- throw new Error(this.options.errors.unrecognizedOptionsForLogin);
75
- }
76
- if ((!(0, lodash_1.isString)(user) && !(0, lodash_1.isPlainObject)(user)) || !(0, lodash_1.isString)(password)) {
77
- throw new Error(this.options.errors.matchFailed);
78
- }
79
- return [4, this.passwordAuthenticator(user, password, isHashPassword)];
80
- case 3:
81
- foundUser = _a.sent();
82
- return [2, foundUser];
83
- }
84
- });
85
- });
86
- };
87
- AccountsPassword.prototype.findUserByEmail = function (email) {
56
+ }
57
+ async authenticate(params) {
58
+ let { user, password, token, locale } = params;
59
+ const passwordUnencrypted = params["password-unencrypted"];
60
+ let isHashPassword = true;
61
+ if (passwordUnencrypted && !password) {
62
+ password = passwordUnencrypted;
63
+ isHashPassword = false;
64
+ }
65
+ if (user && token) {
66
+ return await this.codeAuthenticator(user, token, locale);
67
+ }
68
+ if (!user || !password) {
69
+ throw new Error(this.options.errors.unrecognizedOptionsForLogin);
70
+ }
71
+ if ((!(0, lodash_1.isString)(user) && !(0, lodash_1.isPlainObject)(user)) || !(0, lodash_1.isString)(password)) {
72
+ throw new Error(this.options.errors.matchFailed);
73
+ }
74
+ const foundUser = await this.passwordAuthenticator(user, password, isHashPassword);
75
+ return foundUser;
76
+ }
77
+ findUserByEmail(email) {
88
78
  return this.db.findUserByEmail(email);
89
- };
90
- AccountsPassword.prototype.findUserById = function (id) {
79
+ }
80
+ findUserById(id) {
91
81
  return this.db.findUserById(id);
92
- };
93
- AccountsPassword.prototype.findUserByUsername = function (username) {
82
+ }
83
+ findUserByUsername(username) {
94
84
  return this.db.findUserByUsername(username);
95
- };
96
- AccountsPassword.prototype.getInviteInfo = function (id) {
97
- return tslib_1.__awaiter(this, void 0, void 0, function () {
98
- return tslib_1.__generator(this, function (_a) {
99
- switch (_a.label) {
100
- case 0: return [4, this.db.getInviteInfo(id)];
101
- case 1: return [2, _a.sent()];
102
- }
103
- });
104
- });
105
- };
106
- AccountsPassword.prototype.addEmail = function (userId, newEmail, verified) {
85
+ }
86
+ async getInviteInfo(id) {
87
+ return await this.db.getInviteInfo(id);
88
+ }
89
+ addEmail(userId, newEmail, verified) {
107
90
  if (!this.options.validateEmail(newEmail)) {
108
91
  throw new Error(this.options.errors.invalidEmail);
109
92
  }
110
93
  return this.db.addEmail(userId, newEmail, verified);
111
- };
112
- AccountsPassword.prototype.removeEmail = function (userId, email) {
94
+ }
95
+ removeEmail(userId, email) {
113
96
  return this.db.removeEmail(userId, email);
114
- };
115
- AccountsPassword.prototype.verifyEmail = function (token) {
116
- return tslib_1.__awaiter(this, void 0, void 0, function () {
117
- var user, verificationTokens, tokenRecord, emailRecord;
118
- return tslib_1.__generator(this, function (_a) {
119
- switch (_a.label) {
120
- case 0:
121
- if (!token || !(0, lodash_1.isString)(token)) {
122
- throw new Error(this.options.errors.invalidToken);
123
- }
124
- return [4, this.db.findUserByEmailVerificationToken(token)];
125
- case 1:
126
- user = _a.sent();
127
- if (!user) {
128
- throw new Error(this.options.errors.verifyEmailLinkExpired);
129
- }
130
- verificationTokens = (0, utils_1.getUserVerificationTokens)(user);
131
- tokenRecord = (0, lodash_1.find)(verificationTokens, function (t) { return t.token === token; });
132
- if (!tokenRecord ||
133
- this.isTokenExpired(tokenRecord, this.options.verifyEmailTokenExpiration)) {
134
- throw new Error(this.options.errors.verifyEmailLinkExpired);
135
- }
136
- emailRecord = (0, lodash_1.find)(user.emails, function (e) { return e.address === tokenRecord.address; });
137
- if (!emailRecord) {
138
- throw new Error(this.options.errors.verifyEmailLinkUnknownAddress);
139
- }
140
- return [4, this.db.verifyEmail(user.id, emailRecord.address)];
141
- case 2:
142
- _a.sent();
143
- return [2];
144
- }
145
- });
97
+ }
98
+ async verifyEmail(token) {
99
+ if (!token || !(0, lodash_1.isString)(token)) {
100
+ throw new Error(this.options.errors.invalidToken);
101
+ }
102
+ const user = await this.db.findUserByEmailVerificationToken(token);
103
+ if (!user) {
104
+ throw new Error(this.options.errors.verifyEmailLinkExpired);
105
+ }
106
+ const verificationTokens = (0, utils_1.getUserVerificationTokens)(user);
107
+ const tokenRecord = (0, lodash_1.find)(verificationTokens, (t) => t.token === token);
108
+ if (!tokenRecord ||
109
+ this.isTokenExpired(tokenRecord, this.options.verifyEmailTokenExpiration)) {
110
+ throw new Error(this.options.errors.verifyEmailLinkExpired);
111
+ }
112
+ const emailRecord = (0, lodash_1.find)(user.emails, (e) => e.address === tokenRecord.address);
113
+ if (!emailRecord) {
114
+ throw new Error(this.options.errors.verifyEmailLinkUnknownAddress);
115
+ }
116
+ await this.db.verifyEmail(user.id, emailRecord.address);
117
+ }
118
+ async resetPassword(token, newPassword, infos) {
119
+ if (!token || !(0, lodash_1.isString)(token)) {
120
+ throw new Error(this.options.errors.invalidToken);
121
+ }
122
+ if (!newPassword || !(0, lodash_1.isString)(newPassword)) {
123
+ throw new Error(this.options.errors.invalidNewPassword);
124
+ }
125
+ const user = await this.db.findUserByResetPasswordToken(token);
126
+ if (!user) {
127
+ throw new Error(this.options.errors.resetPasswordLinkExpired);
128
+ }
129
+ const resetTokens = (0, utils_1.getUserResetTokens)(user);
130
+ const resetTokenRecord = (0, lodash_1.find)(resetTokens, (t) => t.token === token);
131
+ if (!resetTokenRecord ||
132
+ this.isTokenExpired(resetTokenRecord, resetTokenRecord.reason === "enroll"
133
+ ? this.options.passwordEnrollTokenExpiration
134
+ : this.options.passwordResetTokenExpiration)) {
135
+ throw new Error(this.options.errors.resetPasswordLinkExpired);
136
+ }
137
+ const emails = user.emails || [];
138
+ if (!(0, lodash_1.includes)(emails.map((email) => email.address), resetTokenRecord.address)) {
139
+ throw new Error(this.options.errors.resetPasswordLinkUnknownAddress);
140
+ }
141
+ const password = await this.hashAndBcryptPassword(newPassword);
142
+ await this.db.setResetPassword(user.id, resetTokenRecord.address, password, token);
143
+ this.server.getHooks().emit(server_1.ServerHooks.ResetPasswordSuccess, user);
144
+ if (resetTokenRecord.reason === "enroll") {
145
+ await this.db.verifyEmail(user.id, resetTokenRecord.address);
146
+ }
147
+ if (this.options.invalidateAllSessionsAfterPasswordReset) {
148
+ await this.db.invalidateAllSessions(user.id);
149
+ }
150
+ if (this.options.notifyUserAfterPasswordChanged) {
151
+ const address = user.emails && user.emails[0].address;
152
+ if (address) {
153
+ const passwordChangedMail = this.server.prepareMail(address, "", this.server.sanitizeUser(user), "", this.server.options.emailTemplates.passwordChanged, this.server.options.emailTemplates.from);
154
+ await this.server.options.sendMail(passwordChangedMail);
155
+ }
156
+ }
157
+ if (this.options.returnTokensAfterResetPassword) {
158
+ return this.server.loginWithUser(user, infos);
159
+ }
160
+ return null;
161
+ }
162
+ async getUserProfile(userId) {
163
+ const spaceId = (0, objectql_1.getSteedosConfig)().tenant._id;
164
+ let password_history = 3;
165
+ let max_login_attempts = 10;
166
+ let lockout_interval = 15;
167
+ let enable_MFA = false;
168
+ let logout_other_clients = false;
169
+ let login_expiration_in_days = null;
170
+ let phone_logout_other_clients = false;
171
+ let phone_login_expiration_in_days = null;
172
+ const spaceUsers = await (0, objectql_1.getObject)("space_users").find({
173
+ filters: `(user eq '${userId}') and (space eq '${spaceId}')`,
146
174
  });
147
- };
148
- AccountsPassword.prototype.resetPassword = function (token, newPassword, infos) {
149
- return tslib_1.__awaiter(this, void 0, void 0, function () {
150
- var user, resetTokens, resetTokenRecord, emails, password, address, passwordChangedMail;
151
- return tslib_1.__generator(this, function (_a) {
152
- switch (_a.label) {
153
- case 0:
154
- if (!token || !(0, lodash_1.isString)(token)) {
155
- throw new Error(this.options.errors.invalidToken);
156
- }
157
- if (!newPassword || !(0, lodash_1.isString)(newPassword)) {
158
- throw new Error(this.options.errors.invalidNewPassword);
159
- }
160
- return [4, this.db.findUserByResetPasswordToken(token)];
161
- case 1:
162
- user = _a.sent();
163
- if (!user) {
164
- throw new Error(this.options.errors.resetPasswordLinkExpired);
165
- }
166
- resetTokens = (0, utils_1.getUserResetTokens)(user);
167
- resetTokenRecord = (0, lodash_1.find)(resetTokens, function (t) { return t.token === token; });
168
- if (!resetTokenRecord ||
169
- this.isTokenExpired(resetTokenRecord, resetTokenRecord.reason === "enroll"
170
- ? this.options.passwordEnrollTokenExpiration
171
- : this.options.passwordResetTokenExpiration)) {
172
- throw new Error(this.options.errors.resetPasswordLinkExpired);
173
- }
174
- emails = user.emails || [];
175
- if (!(0, lodash_1.includes)(emails.map(function (email) { return email.address; }), resetTokenRecord.address)) {
176
- throw new Error(this.options.errors.resetPasswordLinkUnknownAddress);
177
- }
178
- return [4, this.hashAndBcryptPassword(newPassword)];
179
- case 2:
180
- password = _a.sent();
181
- return [4, this.db.setResetPassword(user.id, resetTokenRecord.address, password, token)];
182
- case 3:
183
- _a.sent();
184
- this.server.getHooks().emit(server_1.ServerHooks.ResetPasswordSuccess, user);
185
- if (!(resetTokenRecord.reason === "enroll")) return [3, 5];
186
- return [4, this.db.verifyEmail(user.id, resetTokenRecord.address)];
187
- case 4:
188
- _a.sent();
189
- _a.label = 5;
190
- case 5:
191
- if (!this.options.invalidateAllSessionsAfterPasswordReset) return [3, 7];
192
- return [4, this.db.invalidateAllSessions(user.id)];
193
- case 6:
194
- _a.sent();
195
- _a.label = 7;
196
- case 7:
197
- if (!this.options.notifyUserAfterPasswordChanged) return [3, 9];
198
- address = user.emails && user.emails[0].address;
199
- if (!address) return [3, 9];
200
- passwordChangedMail = this.server.prepareMail(address, "", this.server.sanitizeUser(user), "", this.server.options.emailTemplates.passwordChanged, this.server.options.emailTemplates.from);
201
- return [4, this.server.options.sendMail(passwordChangedMail)];
202
- case 8:
203
- _a.sent();
204
- _a.label = 9;
205
- case 9:
206
- if (this.options.returnTokensAfterResetPassword) {
207
- return [2, this.server.loginWithUser(user, infos)];
208
- }
209
- return [2, null];
210
- }
175
+ if (spaceUsers.length > 0) {
176
+ const spaceUser = spaceUsers[0];
177
+ const profiles = await (0, objectql_1.getObject)("permission_set").find({
178
+ filters: `(name eq '${spaceUser.profile}') and (type eq 'profile') and (space eq '${spaceId}')`,
211
179
  });
212
- });
213
- };
214
- AccountsPassword.prototype.getUserProfile = function (userId) {
215
- return tslib_1.__awaiter(this, void 0, void 0, function () {
216
- var spaceId, password_history, max_login_attempts, lockout_interval, enable_MFA, logout_other_clients, login_expiration_in_days, phone_logout_other_clients, phone_login_expiration_in_days, spaceUsers, spaceUser, profiles, userProfile;
217
- return tslib_1.__generator(this, function (_a) {
218
- switch (_a.label) {
219
- case 0:
220
- spaceId = (0, objectql_1.getSteedosConfig)().tenant._id;
221
- password_history = 3;
222
- max_login_attempts = 10;
223
- lockout_interval = 15;
224
- enable_MFA = false;
225
- logout_other_clients = false;
226
- login_expiration_in_days = null;
227
- phone_logout_other_clients = false;
228
- phone_login_expiration_in_days = null;
229
- return [4, (0, objectql_1.getObject)("space_users").find({
230
- filters: "(user eq '".concat(userId, "') and (space eq '").concat(spaceId, "')"),
231
- })];
232
- case 1:
233
- spaceUsers = _a.sent();
234
- if (!(spaceUsers.length > 0)) return [3, 3];
235
- spaceUser = spaceUsers[0];
236
- return [4, (0, objectql_1.getObject)("permission_set").find({
237
- filters: "(name eq '".concat(spaceUser.profile, "') and (type eq 'profile') and (space eq '").concat(spaceId, "')"),
238
- })];
239
- case 2:
240
- profiles = _a.sent();
241
- if (profiles.length > 0) {
242
- userProfile = profiles[0];
243
- if (_.has(userProfile, "password_history")) {
244
- password_history = Number(userProfile.password_history);
245
- }
246
- if (_.has(userProfile, "max_login_attempts")) {
247
- max_login_attempts = Number(userProfile.max_login_attempts);
248
- }
249
- if (_.has(userProfile, "lockout_interval")) {
250
- lockout_interval = Number(userProfile.lockout_interval);
251
- }
252
- if (_.has(userProfile, "enable_MFA")) {
253
- enable_MFA = userProfile.enable_MFA;
254
- }
255
- if (_.has(userProfile, "logout_other_clients")) {
256
- logout_other_clients = userProfile.logout_other_clients;
257
- }
258
- if (_.has(userProfile, "login_expiration_in_days")) {
259
- login_expiration_in_days = userProfile.login_expiration_in_days;
260
- }
261
- if (_.has(userProfile, "phone_logout_other_clients")) {
262
- phone_logout_other_clients = userProfile.phone_logout_other_clients;
263
- }
264
- if (_.has(userProfile, "phone_login_expiration_in_days")) {
265
- phone_login_expiration_in_days =
266
- userProfile.phone_login_expiration_in_days;
267
- }
268
- }
269
- _a.label = 3;
270
- case 3: return [2, Object.assign({
271
- space: spaceId,
272
- password_history: password_history,
273
- max_login_attempts: max_login_attempts,
274
- lockout_interval: lockout_interval,
275
- logout_other_clients: logout_other_clients,
276
- enable_MFA: enable_MFA,
277
- login_expiration_in_days: login_expiration_in_days,
278
- phone_logout_other_clients: phone_logout_other_clients,
279
- phone_login_expiration_in_days: phone_login_expiration_in_days,
280
- })];
180
+ if (profiles.length > 0) {
181
+ const userProfile = profiles[0];
182
+ if (_.has(userProfile, "password_history")) {
183
+ password_history = Number(userProfile.password_history);
281
184
  }
282
- });
283
- });
284
- };
285
- AccountsPassword.prototype.setPassword = function (userId, newPassword) {
286
- return tslib_1.__awaiter(this, void 0, void 0, function () {
287
- var password;
288
- return tslib_1.__generator(this, function (_a) {
289
- switch (_a.label) {
290
- case 0: return [4, (0, utils_1.bcryptPassword)(newPassword)];
291
- case 1:
292
- password = _a.sent();
293
- return [2, this.db.setPassword(userId, password)];
185
+ if (_.has(userProfile, "max_login_attempts")) {
186
+ max_login_attempts = Number(userProfile.max_login_attempts);
294
187
  }
295
- });
296
- });
297
- };
298
- AccountsPassword.prototype.changePassword = function (userId, oldPassword, newPassword) {
299
- return tslib_1.__awaiter(this, void 0, void 0, function () {
300
- var user, saas, passwordHistory, userProfile, validPasswordHistory, _i, validPasswordHistory_1, item, verify, password, address, passwordChangedMail;
301
- return tslib_1.__generator(this, function (_a) {
302
- switch (_a.label) {
303
- case 0:
304
- if (!this.options.validatePassword(newPassword)) {
305
- throw new Error(this.options.errors.invalidPassword);
306
- }
307
- return [4, this.passwordAuthenticator({ id: userId }, oldPassword)];
308
- case 1:
309
- user = _a.sent();
310
- saas = (0, objectql_1.getSteedosConfig)().tenant.saas;
311
- if (!!saas) return [3, 6];
312
- passwordHistory = user.services.password_history || [];
313
- return [4, this.getUserProfile(userId)];
314
- case 2:
315
- userProfile = _a.sent();
316
- validPasswordHistory = _.last(passwordHistory, userProfile.password_history);
317
- _i = 0, validPasswordHistory_1 = validPasswordHistory;
318
- _a.label = 3;
319
- case 3:
320
- if (!(_i < validPasswordHistory_1.length)) return [3, 6];
321
- item = validPasswordHistory_1[_i];
322
- return [4, (0, utils_1.verifyPassword)(newPassword, item)];
323
- case 4:
324
- verify = _a.sent();
325
- if (verify) {
326
- throw new Error("最近 " + userProfile.password_history + " 次密码不能相同");
327
- }
328
- _a.label = 5;
329
- case 5:
330
- _i++;
331
- return [3, 3];
332
- case 6: return [4, (0, utils_1.bcryptPassword)(newPassword)];
333
- case 7:
334
- password = _a.sent();
335
- return [4, this.db.setPassword(userId, password)];
336
- case 8:
337
- _a.sent();
338
- this.server.getHooks().emit(server_1.ServerHooks.ChangePasswordSuccess, user);
339
- if (!this.options.invalidateAllSessionsAfterPasswordChanged) return [3, 10];
340
- return [4, this.db.invalidateAllSessions(user.id)];
341
- case 9:
342
- _a.sent();
343
- _a.label = 10;
344
- case 10:
345
- if (!this.options.notifyUserAfterPasswordChanged) return [3, 12];
346
- address = user.emails && user.emails[0].address;
347
- if (!address) return [3, 12];
348
- passwordChangedMail = this.server.prepareMail(address, "", this.server.sanitizeUser(user), "", this.server.options.emailTemplates.passwordChanged, this.server.options.emailTemplates.from);
349
- return [4, this.server.options.sendMail(passwordChangedMail)];
350
- case 11:
351
- _a.sent();
352
- _a.label = 12;
353
- case 12: return [2];
188
+ if (_.has(userProfile, "lockout_interval")) {
189
+ lockout_interval = Number(userProfile.lockout_interval);
354
190
  }
355
- });
356
- });
357
- };
358
- AccountsPassword.prototype.sendVerificationEmail = function (address) {
359
- return tslib_1.__awaiter(this, void 0, void 0, function () {
360
- var user, code, token, resetPasswordMail;
361
- return tslib_1.__generator(this, function (_a) {
362
- switch (_a.label) {
363
- case 0:
364
- if (!address || !(0, lodash_1.isString)(address)) {
365
- throw new Error(this.options.errors.invalidEmail);
366
- }
367
- return [4, this.db.findUserByEmail(address)];
368
- case 1:
369
- user = _a.sent();
370
- if (!user) {
371
- if (this.server.options.ambiguousErrorMessages) {
372
- return [2];
373
- }
374
- throw new Error(this.options.errors.userNotFound);
375
- }
376
- if (user.email_verified)
377
- return [2];
378
- code = (0, server_1.generateRandomCode)();
379
- token = (0, server_1.generateRandomToken)();
380
- return [4, this.db.addEmailVerificationToken(user.id, address, token, code)];
381
- case 2:
382
- _a.sent();
383
- resetPasswordMail = this.server.prepareMail(address, code, this.server.sanitizeUser(user), getPathFragmentPrefix() + "verify-email", this.server.options.emailTemplates.verifyEmail, this.server.options.emailTemplates.from);
384
- return [4, this.server.options.sendMail(resetPasswordMail)];
385
- case 3:
386
- _a.sent();
387
- return [2];
191
+ if (_.has(userProfile, "enable_MFA")) {
192
+ enable_MFA = userProfile.enable_MFA;
388
193
  }
389
- });
390
- });
391
- };
392
- AccountsPassword.prototype.sendResetPasswordEmail = function (address) {
393
- return tslib_1.__awaiter(this, void 0, void 0, function () {
394
- var user, token, resetPasswordMail;
395
- return tslib_1.__generator(this, function (_a) {
396
- switch (_a.label) {
397
- case 0:
398
- if (!address || !(0, lodash_1.isString)(address)) {
399
- throw new Error(this.options.errors.invalidEmail);
400
- }
401
- return [4, this.db.findUserByEmail(address)];
402
- case 1:
403
- user = _a.sent();
404
- if (!user) {
405
- if (this.server.options.ambiguousErrorMessages) {
406
- return [2];
407
- }
408
- throw new Error(this.options.errors.userNotFound);
409
- }
410
- token = (0, server_1.generateRandomToken)();
411
- return [4, this.db.addResetPasswordToken(user.id, address, token, "reset")];
412
- case 2:
413
- _a.sent();
414
- resetPasswordMail = this.server.prepareMail(address, token, this.server.sanitizeUser(user), getPathFragmentPrefix() + "reset-password", this.server.options.emailTemplates.resetPassword, this.server.options.emailTemplates.from);
415
- return [4, this.server.options.sendMail(resetPasswordMail)];
416
- case 3:
417
- _a.sent();
418
- return [2];
194
+ if (_.has(userProfile, "logout_other_clients")) {
195
+ logout_other_clients = userProfile.logout_other_clients;
419
196
  }
420
- });
421
- });
422
- };
423
- AccountsPassword.prototype.sendEnrollmentEmail = function (address) {
424
- return tslib_1.__awaiter(this, void 0, void 0, function () {
425
- var user, token, enrollmentMail;
426
- return tslib_1.__generator(this, function (_a) {
427
- switch (_a.label) {
428
- case 0:
429
- if (!address || !(0, lodash_1.isString)(address)) {
430
- throw new Error(this.options.errors.invalidEmail);
431
- }
432
- return [4, this.db.findUserByEmail(address)];
433
- case 1:
434
- user = _a.sent();
435
- if (!user) {
436
- throw new Error(this.options.errors.userNotFound);
437
- }
438
- token = (0, server_1.generateRandomToken)();
439
- return [4, this.db.addResetPasswordToken(user.id, address, token, "enroll")];
440
- case 2:
441
- _a.sent();
442
- enrollmentMail = this.server.prepareMail(address, token, this.server.sanitizeUser(user), getPathFragmentPrefix() + "enroll-account", this.server.options.emailTemplates.enrollAccount, this.server.options.emailTemplates.from);
443
- return [4, this.server.options.sendMail(enrollmentMail)];
444
- case 3:
445
- _a.sent();
446
- return [2];
197
+ if (_.has(userProfile, "login_expiration_in_days")) {
198
+ login_expiration_in_days = userProfile.login_expiration_in_days;
447
199
  }
448
- });
200
+ if (_.has(userProfile, "phone_logout_other_clients")) {
201
+ phone_logout_other_clients = userProfile.phone_logout_other_clients;
202
+ }
203
+ if (_.has(userProfile, "phone_login_expiration_in_days")) {
204
+ phone_login_expiration_in_days =
205
+ userProfile.phone_login_expiration_in_days;
206
+ }
207
+ }
208
+ }
209
+ return Object.assign({
210
+ space: spaceId,
211
+ password_history: password_history,
212
+ max_login_attempts: max_login_attempts,
213
+ lockout_interval: lockout_interval,
214
+ logout_other_clients,
215
+ enable_MFA,
216
+ login_expiration_in_days,
217
+ phone_logout_other_clients,
218
+ phone_login_expiration_in_days,
449
219
  });
450
- };
451
- AccountsPassword.prototype.createUser = function (user) {
452
- return tslib_1.__awaiter(this, void 0, void 0, function () {
453
- var _a, _b, _c, _d, r, userId_1, e_1;
454
- var _this = this;
455
- return tslib_1.__generator(this, function (_e) {
456
- switch (_e.label) {
457
- case 0:
458
- if (!user.email && !user.mobile) {
459
- throw new Error(this.options.errors.emailOrMobileRequired);
460
- }
461
- if (user.username && !this.options.validateUsername(user.username)) {
462
- throw new Error(this.options.errors.invalidUsername);
463
- }
464
- if (user.email && !this.options.validateEmail(user.email)) {
465
- throw new Error(this.options.errors.invalidEmail);
466
- }
467
- _a = user.mobile;
468
- if (!_a) return [3, 2];
469
- return [4, this.db.findUserByMobile(user.mobile)];
470
- case 1:
471
- _a = (_e.sent());
472
- _e.label = 2;
473
- case 2:
474
- if (_a) {
475
- throw new Error(this.options.errors.mobileAlreadyExists);
476
- }
477
- _b = user.username;
478
- if (!_b) return [3, 4];
479
- return [4, this.db.findUserByUsername(user.username)];
480
- case 3:
481
- _b = (_e.sent());
482
- _e.label = 4;
483
- case 4:
484
- if (_b) {
485
- throw new Error(this.options.errors.usernameAlreadyExists);
486
- }
487
- _c = user.email;
488
- if (!_c) return [3, 6];
489
- return [4, this.db.findUserByEmail(user.email)];
490
- case 5:
491
- _c = (_e.sent());
492
- _e.label = 6;
493
- case 6:
494
- if (_c) {
495
- throw new Error(this.options.errors.emailAlreadyExists);
496
- }
497
- if (!user.password && !user.verifyCode) {
498
- throw new Error(this.options.errors.invalidVerifyParam);
499
- }
500
- if (!user.password) return [3, 9];
501
- if (!this.options.validatePassword(user.password)) {
502
- throw new Error(this.options.errors.invalidPassword);
503
- }
504
- _d = user;
505
- return [4, (0, utils_1.bcryptPassword)(user.password)];
506
- case 7: return [4, _e.sent()];
507
- case 8:
508
- _d.password = _e.sent();
509
- _e.label = 9;
510
- case 9:
511
- if (!user.verifyCode) return [3, 11];
512
- return [4, this.db.checkVerificationCode(user, user.verifyCode)];
513
- case 10:
514
- r = _e.sent();
515
- if (!r) {
516
- throw new Error(this.options.errors.invalidVerifyCode);
517
- }
518
- delete user.verifyCode;
519
- if (user.email)
520
- user.email_verified = true;
521
- if (user.mobile)
522
- user.mobile_verified = true;
523
- _e.label = 11;
524
- case 11:
525
- _e.trys.push([11, 13, , 15]);
526
- return [4, this.db.createUser(user)];
527
- case 12:
528
- userId_1 = _e.sent();
529
- (0, lodash_1.defer)(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
530
- var userRecord;
531
- return tslib_1.__generator(this, function (_a) {
532
- switch (_a.label) {
533
- case 0:
534
- if (this.options.sendVerificationEmailAfterSignup &&
535
- user.email &&
536
- !user.email_verified)
537
- this.sendVerificationEmail(user.email);
538
- return [4, this.db.findUserById(userId_1)];
539
- case 1:
540
- userRecord = (_a.sent());
541
- this.server.getHooks().emit(server_1.ServerHooks.CreateUserSuccess, userRecord);
542
- return [2];
543
- }
544
- });
545
- }); });
546
- return [2, userId_1];
547
- case 13:
548
- e_1 = _e.sent();
549
- return [4, this.server.getHooks().emit(server_1.ServerHooks.CreateUserError, user)];
550
- case 14:
551
- _e.sent();
552
- throw e_1;
553
- case 15: return [2];
220
+ }
221
+ async checkPasswordExpiry(userId) {
222
+ const config = (0, objectql_1.getSteedosConfig)();
223
+ const tenant = config?.tenant;
224
+ if (!tenant || !tenant._id) {
225
+ return;
226
+ }
227
+ const spaceId = tenant._id;
228
+ const spaces = await (0, objectql_1.getObject)("spaces").find({
229
+ filters: [['_id', '=', spaceId]],
230
+ fields: ['password_expiry_days']
231
+ });
232
+ if (!spaces || spaces.length === 0) {
233
+ return;
234
+ }
235
+ const space = spaces[0];
236
+ const passwordExpiryDays = space.password_expiry_days;
237
+ if (!passwordExpiryDays || passwordExpiryDays <= 0) {
238
+ return;
239
+ }
240
+ const user = await this.db.findUserById(userId);
241
+ const passwordModifiedAt = user.password_modified_at;
242
+ if (!passwordModifiedAt) {
243
+ return;
244
+ }
245
+ const daysSinceModified = moment().diff(moment(passwordModifiedAt), 'days');
246
+ if (daysSinceModified >= passwordExpiryDays) {
247
+ await this.db.updateUser(userId, {
248
+ $set: { password_expired: true }
249
+ });
250
+ }
251
+ }
252
+ async setPassword(userId, newPassword) {
253
+ const password = await (0, utils_1.bcryptPassword)(newPassword);
254
+ return this.db.setPassword(userId, password);
255
+ }
256
+ async changePassword(userId, oldPassword, newPassword) {
257
+ if (!this.options.validatePassword(newPassword)) {
258
+ throw new Error(this.options.errors.invalidPassword);
259
+ }
260
+ const user = await this.passwordAuthenticator({ id: userId }, oldPassword);
261
+ const saas = (0, objectql_1.getSteedosConfig)().tenant.saas;
262
+ if (!saas) {
263
+ const passwordHistory = user.services.password_history || [];
264
+ const userProfile = await this.getUserProfile(userId);
265
+ const validPasswordHistory = _.last(passwordHistory, userProfile.password_history);
266
+ for (const item of validPasswordHistory) {
267
+ var verify = await (0, utils_1.verifyPassword)(newPassword, item);
268
+ if (verify) {
269
+ throw new Error("最近 " + userProfile.password_history + " 次密码不能相同");
554
270
  }
271
+ }
272
+ }
273
+ const password = await (0, utils_1.bcryptPassword)(newPassword);
274
+ await this.db.setPassword(userId, password);
275
+ this.server.getHooks().emit(server_1.ServerHooks.ChangePasswordSuccess, user);
276
+ if (this.options.invalidateAllSessionsAfterPasswordChanged) {
277
+ await this.db.invalidateAllSessions(user.id);
278
+ }
279
+ if (this.options.notifyUserAfterPasswordChanged) {
280
+ const address = user.emails && user.emails[0].address;
281
+ if (address) {
282
+ const passwordChangedMail = this.server.prepareMail(address, "", this.server.sanitizeUser(user), "", this.server.options.emailTemplates.passwordChanged, this.server.options.emailTemplates.from);
283
+ await this.server.options.sendMail(passwordChangedMail);
284
+ }
285
+ }
286
+ }
287
+ async sendVerificationEmail(address) {
288
+ if (!address || !(0, lodash_1.isString)(address)) {
289
+ throw new Error(this.options.errors.invalidEmail);
290
+ }
291
+ const user = await this.db.findUserByEmail(address);
292
+ if (!user) {
293
+ if (this.server.options.ambiguousErrorMessages) {
294
+ return;
295
+ }
296
+ throw new Error(this.options.errors.userNotFound);
297
+ }
298
+ if (user.email_verified)
299
+ return;
300
+ const code = (0, server_1.generateRandomCode)();
301
+ const token = (0, server_1.generateRandomToken)();
302
+ await this.db.addEmailVerificationToken(user.id, address, token, code);
303
+ const resetPasswordMail = this.server.prepareMail(address, code, this.server.sanitizeUser(user), getPathFragmentPrefix() + "verify-email", this.server.options.emailTemplates.verifyEmail, this.server.options.emailTemplates.from);
304
+ await this.server.options.sendMail(resetPasswordMail);
305
+ }
306
+ async sendResetPasswordEmail(address) {
307
+ if (!address || !(0, lodash_1.isString)(address)) {
308
+ throw new Error(this.options.errors.invalidEmail);
309
+ }
310
+ const user = await this.db.findUserByEmail(address);
311
+ if (!user) {
312
+ if (this.server.options.ambiguousErrorMessages) {
313
+ return;
314
+ }
315
+ throw new Error(this.options.errors.userNotFound);
316
+ }
317
+ const token = (0, server_1.generateRandomToken)();
318
+ await this.db.addResetPasswordToken(user.id, address, token, "reset");
319
+ const resetPasswordMail = this.server.prepareMail(address, token, this.server.sanitizeUser(user), getPathFragmentPrefix() + "reset-password", this.server.options.emailTemplates.resetPassword, this.server.options.emailTemplates.from);
320
+ await this.server.options.sendMail(resetPasswordMail);
321
+ }
322
+ async sendEnrollmentEmail(address) {
323
+ if (!address || !(0, lodash_1.isString)(address)) {
324
+ throw new Error(this.options.errors.invalidEmail);
325
+ }
326
+ const user = await this.db.findUserByEmail(address);
327
+ if (!user) {
328
+ throw new Error(this.options.errors.userNotFound);
329
+ }
330
+ const token = (0, server_1.generateRandomToken)();
331
+ await this.db.addResetPasswordToken(user.id, address, token, "enroll");
332
+ const enrollmentMail = this.server.prepareMail(address, token, this.server.sanitizeUser(user), getPathFragmentPrefix() + "enroll-account", this.server.options.emailTemplates.enrollAccount, this.server.options.emailTemplates.from);
333
+ await this.server.options.sendMail(enrollmentMail);
334
+ }
335
+ async createUser(user) {
336
+ if (!user.email && !user.mobile) {
337
+ throw new Error(this.options.errors.emailOrMobileRequired);
338
+ }
339
+ if (user.username && !this.options.validateUsername(user.username)) {
340
+ throw new Error(this.options.errors.invalidUsername);
341
+ }
342
+ if (user.email && !this.options.validateEmail(user.email)) {
343
+ throw new Error(this.options.errors.invalidEmail);
344
+ }
345
+ if (user.mobile && (await this.db.findUserByMobile(user.mobile))) {
346
+ throw new Error(this.options.errors.mobileAlreadyExists);
347
+ }
348
+ if (user.username && (await this.db.findUserByUsername(user.username))) {
349
+ throw new Error(this.options.errors.usernameAlreadyExists);
350
+ }
351
+ if (user.email && (await this.db.findUserByEmail(user.email))) {
352
+ throw new Error(this.options.errors.emailAlreadyExists);
353
+ }
354
+ if (!user.password && !user.verifyCode) {
355
+ throw new Error(this.options.errors.invalidVerifyParam);
356
+ }
357
+ if (user.password) {
358
+ if (!this.options.validatePassword(user.password)) {
359
+ throw new Error(this.options.errors.invalidPassword);
360
+ }
361
+ user.password = await await (0, utils_1.bcryptPassword)(user.password);
362
+ }
363
+ if (user.verifyCode) {
364
+ const r = await this.db.checkVerificationCode(user, user.verifyCode);
365
+ if (!r) {
366
+ throw new Error(this.options.errors.invalidVerifyCode);
367
+ }
368
+ delete user.verifyCode;
369
+ if (user.email)
370
+ user.email_verified = true;
371
+ if (user.mobile)
372
+ user.mobile_verified = true;
373
+ }
374
+ try {
375
+ const userId = await this.db.createUser(user);
376
+ (0, lodash_1.defer)(async () => {
377
+ if (this.options.sendVerificationEmailAfterSignup &&
378
+ user.email &&
379
+ !user.email_verified)
380
+ this.sendVerificationEmail(user.email);
381
+ const userRecord = (await this.db.findUserById(userId));
382
+ this.server.getHooks().emit(server_1.ServerHooks.CreateUserSuccess, userRecord);
555
383
  });
556
- });
557
- };
558
- AccountsPassword.prototype.isTokenExpired = function (tokenRecord, expiryDate) {
384
+ return userId;
385
+ }
386
+ catch (e) {
387
+ await this.server.getHooks().emit(server_1.ServerHooks.CreateUserError, user);
388
+ throw e;
389
+ }
390
+ }
391
+ isTokenExpired(tokenRecord, expiryDate) {
559
392
  return Number(tokenRecord.when) + expiryDate < Date.now();
560
- };
561
- AccountsPassword.prototype.verifyUserPasswordByEmail = function (email, password) {
562
- return tslib_1.__awaiter(this, void 0, void 0, function () {
563
- return tslib_1.__generator(this, function (_a) {
564
- switch (_a.label) {
565
- case 0: return [4, this.passwordAuthenticator({ email: email }, password)];
566
- case 1: return [2, _a.sent()];
393
+ }
394
+ async verifyUserPasswordByEmail(email, password) {
395
+ return await this.passwordAuthenticator({ email: email }, password);
396
+ }
397
+ async foundUser(user) {
398
+ const { username, email, id, mobile } = typeof user == "string"
399
+ ? this.toMobileAndEmail({ user })
400
+ : this.toMobileAndEmail({ ...user });
401
+ let foundUser = null;
402
+ if (id) {
403
+ foundUser = await this.db.findUserById(id);
404
+ }
405
+ else if (username) {
406
+ foundUser = await this.db.findUserByUsername(username);
407
+ }
408
+ else if (mobile) {
409
+ foundUser = await this.db.findUserByMobile(mobile);
410
+ }
411
+ else if (email) {
412
+ foundUser = await this.db.findUserByEmail(email);
413
+ }
414
+ return foundUser;
415
+ }
416
+ async passwordAuthenticator(user, password, isHashPassword = true) {
417
+ const { username, email, id, mobile } = typeof user == "string"
418
+ ? this.toMobileAndEmail({ user })
419
+ : this.toMobileAndEmail({ ...user });
420
+ let foundUser = null;
421
+ if (id) {
422
+ foundUser = await this.db.findUserById(id);
423
+ }
424
+ else if (username) {
425
+ foundUser = await this.db.findUserByUsername(username);
426
+ }
427
+ else if (mobile) {
428
+ foundUser = await this.db.findUserByMobile(mobile);
429
+ }
430
+ else if (email) {
431
+ foundUser = await this.db.findUserByEmail(email);
432
+ }
433
+ if (!foundUser) {
434
+ throw new Error(this.server.options.ambiguousErrorMessages
435
+ ? this.options.errors.invalidCredentials
436
+ : this.options.errors.userNotFound);
437
+ }
438
+ const hash = await this.db.findPasswordHash(foundUser.id);
439
+ if (!hash) {
440
+ throw new Error(this.options.errors.noPasswordSet);
441
+ }
442
+ const saas = (0, objectql_1.getSteedosConfig)().tenant.saas;
443
+ if (!saas) {
444
+ const locked = foundUser.lockout;
445
+ const login_failed_lockout_time = foundUser.login_failed_lockout_time;
446
+ if (locked) {
447
+ if (!login_failed_lockout_time) {
448
+ throw new Error("账户已锁定,请联系管理员");
567
449
  }
568
- });
569
- });
570
- };
571
- AccountsPassword.prototype.foundUser = function (user) {
572
- return tslib_1.__awaiter(this, void 0, void 0, function () {
573
- var _a, username, email, id, mobile, foundUser;
574
- return tslib_1.__generator(this, function (_b) {
575
- switch (_b.label) {
576
- case 0:
577
- _a = typeof user == "string"
578
- ? this.toMobileAndEmail({ user: user })
579
- : this.toMobileAndEmail(tslib_1.__assign({}, user)), username = _a.username, email = _a.email, id = _a.id, mobile = _a.mobile;
580
- foundUser = null;
581
- if (!id) return [3, 2];
582
- return [4, this.db.findUserById(id)];
583
- case 1:
584
- foundUser = _b.sent();
585
- return [3, 8];
586
- case 2:
587
- if (!username) return [3, 4];
588
- return [4, this.db.findUserByUsername(username)];
589
- case 3:
590
- foundUser = _b.sent();
591
- return [3, 8];
592
- case 4:
593
- if (!mobile) return [3, 6];
594
- return [4, this.db.findUserByMobile(mobile)];
595
- case 5:
596
- foundUser = _b.sent();
597
- return [3, 8];
598
- case 6:
599
- if (!email) return [3, 8];
600
- return [4, this.db.findUserByEmail(email)];
601
- case 7:
602
- foundUser = _b.sent();
603
- _b.label = 8;
604
- case 8: return [2, foundUser];
450
+ else {
451
+ if (moment(login_failed_lockout_time).isAfter(new Date())) {
452
+ throw new Error("账户已锁定,请联系管理员");
453
+ }
605
454
  }
606
- });
607
- });
608
- };
609
- AccountsPassword.prototype.passwordAuthenticator = function (user_1, password_1) {
610
- return tslib_1.__awaiter(this, arguments, void 0, function (user, password, isHashPassword) {
611
- var _a, username, email, id, mobile, foundUser, hash, saas, locked, login_failed_lockout_time, hashAlgorithm, pass, isPasswordValid, userProfile, login_failed_lockout_time, user_2, lockout_interval, login_failed_lockout_time_1;
612
- if (isHashPassword === void 0) { isHashPassword = true; }
613
- return tslib_1.__generator(this, function (_b) {
614
- switch (_b.label) {
615
- case 0:
616
- _a = typeof user == "string"
617
- ? this.toMobileAndEmail({ user: user })
618
- : this.toMobileAndEmail(tslib_1.__assign({}, user)), username = _a.username, email = _a.email, id = _a.id, mobile = _a.mobile;
619
- foundUser = null;
620
- if (!id) return [3, 2];
621
- return [4, this.db.findUserById(id)];
622
- case 1:
623
- foundUser = _b.sent();
624
- return [3, 8];
625
- case 2:
626
- if (!username) return [3, 4];
627
- return [4, this.db.findUserByUsername(username)];
628
- case 3:
629
- foundUser = _b.sent();
630
- return [3, 8];
631
- case 4:
632
- if (!mobile) return [3, 6];
633
- return [4, this.db.findUserByMobile(mobile)];
634
- case 5:
635
- foundUser = _b.sent();
636
- return [3, 8];
637
- case 6:
638
- if (!email) return [3, 8];
639
- return [4, this.db.findUserByEmail(email)];
640
- case 7:
641
- foundUser = _b.sent();
642
- _b.label = 8;
643
- case 8:
644
- if (!foundUser) {
645
- throw new Error(this.server.options.ambiguousErrorMessages
646
- ? this.options.errors.invalidCredentials
647
- : this.options.errors.userNotFound);
648
- }
649
- return [4, this.db.findPasswordHash(foundUser.id)];
650
- case 9:
651
- hash = _b.sent();
652
- if (!hash) {
653
- throw new Error(this.options.errors.noPasswordSet);
654
- }
655
- saas = (0, objectql_1.getSteedosConfig)().tenant.saas;
656
- if (!saas) {
657
- locked = foundUser.lockout;
658
- login_failed_lockout_time = foundUser.login_failed_lockout_time;
659
- if (locked) {
660
- if (!login_failed_lockout_time) {
661
- throw new Error("账户已锁定,请联系管理员");
662
- }
663
- else {
664
- if (moment(login_failed_lockout_time).isAfter(new Date())) {
665
- throw new Error("账户已锁定,请联系管理员");
666
- }
667
- }
668
- }
669
- }
670
- hashAlgorithm = this.options.passwordHashAlgorithm;
671
- pass = null;
672
- if (isHashPassword) {
673
- pass = password;
674
- }
675
- else {
676
- pass = hashAlgorithm ? (0, utils_1.hashPassword)(password, hashAlgorithm) : password;
677
- }
678
- return [4, (0, utils_1.verifyPassword)(pass, hash)];
679
- case 10:
680
- isPasswordValid = _b.sent();
681
- if (!!isPasswordValid) return [3, 19];
682
- if (!!saas) return [3, 18];
683
- return [4, this.getUserProfile(foundUser.id)];
684
- case 11:
685
- userProfile = _b.sent();
686
- login_failed_lockout_time = foundUser.login_failed_lockout_time;
687
- if (!(userProfile.lockout_interval != 0 &&
688
- moment(login_failed_lockout_time).isBefore(new Date()))) return [3, 13];
689
- return [4, this.db.updateUser(foundUser.id, {
690
- $set: { login_failed_number: 1 },
691
- })];
692
- case 12:
693
- _b.sent();
694
- return [3, 15];
695
- case 13: return [4, this.db.updateUser(foundUser.id, {
696
- $inc: { login_failed_number: 1 },
697
- })];
698
- case 14:
699
- _b.sent();
700
- _b.label = 15;
701
- case 15: return [4, this.db.findUserById(foundUser.id)];
702
- case 16:
703
- user_2 = _b.sent();
704
- if (!(user_2.login_failed_number >= userProfile.max_login_attempts)) return [3, 18];
705
- lockout_interval = userProfile.lockout_interval;
706
- login_failed_lockout_time_1 = null;
707
- if (lockout_interval === 0) {
708
- login_failed_lockout_time_1 = null;
709
- }
710
- else {
711
- login_failed_lockout_time_1 = new Date(moment().add(userProfile.lockout_interval, "m"));
712
- }
713
- return [4, this.db.updateUser(foundUser.id, {
714
- $set: {
715
- lockout: true,
716
- login_failed_lockout_time: login_failed_lockout_time_1,
717
- },
718
- })];
719
- case 17:
720
- _b.sent();
721
- _b.label = 18;
722
- case 18: throw new Error(this.server.options.ambiguousErrorMessages
723
- ? this.options.errors.invalidCredentials
724
- : this.options.errors.incorrectPassword);
725
- case 19: return [4, this.db.updateUser(foundUser.id, {
726
- $set: { lockout: false, login_failed_number: 0 },
727
- $unset: { login_failed_lockout_time: 1 },
728
- })];
729
- case 20:
730
- _b.sent();
731
- _b.label = 21;
732
- case 21: return [2, foundUser];
455
+ }
456
+ }
457
+ const hashAlgorithm = this.options.passwordHashAlgorithm;
458
+ let pass = null;
459
+ if (isHashPassword) {
460
+ pass = password;
461
+ }
462
+ else {
463
+ pass = hashAlgorithm ? (0, utils_1.hashPassword)(password, hashAlgorithm) : password;
464
+ }
465
+ const isPasswordValid = await (0, utils_1.verifyPassword)(pass, hash);
466
+ if (!isPasswordValid) {
467
+ if (!saas) {
468
+ const userProfile = await this.getUserProfile(foundUser.id);
469
+ const login_failed_lockout_time = foundUser.login_failed_lockout_time;
470
+ if (userProfile.lockout_interval != 0 &&
471
+ moment(login_failed_lockout_time).isBefore(new Date())) {
472
+ await this.db.updateUser(foundUser.id, {
473
+ $set: { login_failed_number: 1 },
474
+ });
733
475
  }
734
- });
735
- });
736
- };
737
- AccountsPassword.prototype.codeAuthenticator = function (user, token, locale) {
738
- return tslib_1.__awaiter(this, void 0, void 0, function () {
739
- var _a, username, email, mobile, id, foundUser;
740
- return tslib_1.__generator(this, function (_b) {
741
- switch (_b.label) {
742
- case 0:
743
- _a = (0, lodash_1.isString)(user)
744
- ? this.toMobileAndEmail({ user: user })
745
- : this.toMobileAndEmail(tslib_1.__assign({}, user)), username = _a.username, email = _a.email, mobile = _a.mobile, id = _a.id;
746
- return [4, this.db.findUserByVerificationCode({ email: email, mobile: mobile }, token)];
747
- case 1:
748
- foundUser = _b.sent();
749
- if (!foundUser) {
750
- throw new Error(this.server.options.ambiguousErrorMessages
751
- ? this.options.errors.invalidCode
752
- : this.options.errors.userNotFound);
753
- }
754
- return [2, foundUser];
476
+ else {
477
+ await this.db.updateUser(foundUser.id, {
478
+ $inc: { login_failed_number: 1 },
479
+ });
755
480
  }
481
+ const user = await this.db.findUserById(foundUser.id);
482
+ if (user.login_failed_number >= userProfile.max_login_attempts) {
483
+ let lockout_interval = userProfile.lockout_interval;
484
+ let login_failed_lockout_time = null;
485
+ if (lockout_interval === 0) {
486
+ login_failed_lockout_time = null;
487
+ }
488
+ else {
489
+ login_failed_lockout_time = new Date(moment().add(userProfile.lockout_interval, "m"));
490
+ }
491
+ await this.db.updateUser(foundUser.id, {
492
+ $set: {
493
+ lockout: true,
494
+ login_failed_lockout_time: login_failed_lockout_time,
495
+ },
496
+ });
497
+ }
498
+ }
499
+ throw new Error(this.server.options.ambiguousErrorMessages
500
+ ? this.options.errors.invalidCredentials
501
+ : this.options.errors.incorrectPassword);
502
+ }
503
+ else {
504
+ await this.db.updateUser(foundUser.id, {
505
+ $set: { lockout: false, login_failed_number: 0 },
506
+ $unset: { login_failed_lockout_time: 1 },
756
507
  });
757
- });
758
- };
759
- AccountsPassword.prototype.hashAndBcryptPassword = function (password) {
760
- return tslib_1.__awaiter(this, void 0, void 0, function () {
761
- var hashAlgorithm, hashedPassword;
762
- return tslib_1.__generator(this, function (_a) {
763
- hashAlgorithm = this.options.passwordHashAlgorithm;
764
- hashedPassword = hashAlgorithm
765
- ? (0, utils_1.hashPassword)(password, hashAlgorithm)
766
- : password;
767
- return [2, (0, utils_1.bcryptPassword)(hashedPassword)];
768
- });
769
- });
770
- };
771
- AccountsPassword.prototype.toMobileAndEmail = function (_a) {
772
- var user = _a.user, username = _a.username, email = _a.email, mobile = _a.mobile, id = _a.id;
508
+ }
509
+ await this.checkPasswordExpiry(foundUser.id);
510
+ return foundUser;
511
+ }
512
+ async codeAuthenticator(user, token, locale) {
513
+ const { username, email, mobile, id } = (0, lodash_1.isString)(user)
514
+ ? this.toMobileAndEmail({ user })
515
+ : this.toMobileAndEmail({ ...user });
516
+ let foundUser = await this.db.findUserByVerificationCode({ email: email, mobile: mobile }, token);
517
+ if (!foundUser) {
518
+ throw new Error(this.server.options.ambiguousErrorMessages
519
+ ? this.options.errors.invalidCode
520
+ : this.options.errors.userNotFound);
521
+ }
522
+ return foundUser;
523
+ }
524
+ async hashAndBcryptPassword(password) {
525
+ const hashAlgorithm = this.options.passwordHashAlgorithm;
526
+ const hashedPassword = hashAlgorithm
527
+ ? (0, utils_1.hashPassword)(password, hashAlgorithm)
528
+ : password;
529
+ return (0, utils_1.bcryptPassword)(hashedPassword);
530
+ }
531
+ toMobileAndEmail({ user, username, email, mobile, id }) {
773
532
  if (user && !username && !email && !mobile) {
774
533
  if ((0, utils_1.isEmail)(user)) {
775
534
  email = user;
@@ -778,49 +537,32 @@ var AccountsPassword = (function () {
778
537
  mobile = user;
779
538
  }
780
539
  }
781
- return { username: username, email: email, mobile: mobile, id: id };
782
- };
783
- AccountsPassword.prototype.sendVerificationCode = function (user) {
784
- return tslib_1.__awaiter(this, void 0, void 0, function () {
785
- var code, result, verificationCodeMail, result, sms;
786
- return tslib_1.__generator(this, function (_a) {
787
- switch (_a.label) {
788
- case 0:
789
- code = (0, server_1.generateRandomCode)();
790
- if (!user.email) return [3, 3];
791
- return [4, this.db.addVerificationCode(user, code, {
792
- MAX_FAILURE_COUNT: MAX_FAILURE_COUNT,
793
- EFFECTIVE_TIME: EFFECTIVE_TIME,
794
- })];
795
- case 1:
796
- result = _a.sent();
797
- verificationCodeMail = this.server.prepareMail(user.email, result.code, null, getPathFragmentPrefix() + "verify-email", this.server.options.emailTemplates.verificationCode, this.server.options.emailTemplates.from);
798
- return [4, this.server.options.sendMail(verificationCodeMail)];
799
- case 2:
800
- _a.sent();
801
- return [2, result.owner];
802
- case 3:
803
- if (!user.mobile) return [3, 6];
804
- return [4, this.db.addVerificationCode(user, code, {
805
- MAX_FAILURE_COUNT: MAX_FAILURE_COUNT,
806
- EFFECTIVE_TIME: EFFECTIVE_TIME,
807
- })];
808
- case 4:
809
- result = _a.sent();
810
- sms = {
811
- mobile: user.mobile,
812
- message: "\u60A8\u7684\u9A8C\u8BC1\u7801\u4E3A\uFF1A".concat(result.code, "\uFF0C\u8BE5\u9A8C\u8BC1\u7801").concat(EFFECTIVE_TIME, "\u5206\u949F\u5185\u6709\u6548\uFF0C\u8BF7\u52FF\u6CC4\u6F0F\u4E8E\u4ED6\u4EBA\uFF01"),
813
- };
814
- return [4, this.server.options.sendSMS(sms)];
815
- case 5:
816
- _a.sent();
817
- return [2, result.owner];
818
- case 6: return [2];
819
- }
540
+ return { username, email, mobile, id };
541
+ }
542
+ async sendVerificationCode(user) {
543
+ const code = (0, server_1.generateRandomCode)();
544
+ if (user.email) {
545
+ const result = await this.db.addVerificationCode(user, code, {
546
+ MAX_FAILURE_COUNT,
547
+ EFFECTIVE_TIME,
820
548
  });
821
- });
822
- };
823
- return AccountsPassword;
824
- }());
549
+ const verificationCodeMail = this.server.prepareMail(user.email, result.code, null, getPathFragmentPrefix() + "verify-email", this.server.options.emailTemplates.verificationCode, this.server.options.emailTemplates.from);
550
+ await this.server.options.sendMail(verificationCodeMail);
551
+ return result.owner;
552
+ }
553
+ else if (user.mobile) {
554
+ const result = await this.db.addVerificationCode(user, code, {
555
+ MAX_FAILURE_COUNT,
556
+ EFFECTIVE_TIME,
557
+ });
558
+ const sms = {
559
+ mobile: user.mobile,
560
+ message: `您的验证码为:${result.code},该验证码${EFFECTIVE_TIME}分钟内有效,请勿泄漏于他人!`,
561
+ };
562
+ await this.server.options.sendSMS(sms);
563
+ return result.owner;
564
+ }
565
+ }
566
+ }
825
567
  exports.default = AccountsPassword;
826
568
  //# sourceMappingURL=accounts-password.js.map