@steedos/accounts 3.0.13-beta.9 → 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.
- package/lib/core/index.js +177 -249
- package/lib/core/index.js.map +1 -1
- package/lib/database-mongo/index.js +1 -1
- package/lib/database-mongo/index.js.map +1 -1
- package/lib/database-mongo/mongo.js +760 -1278
- package/lib/database-mongo/mongo.js.map +1 -1
- package/lib/db.js +2 -2
- package/lib/db.js.map +1 -1
- package/lib/index.js +107 -143
- package/lib/index.js.map +1 -1
- package/lib/mail.js +36 -47
- package/lib/mail.js.map +1 -1
- package/lib/password/accounts-password.js +505 -763
- package/lib/password/accounts-password.js.map +1 -1
- package/lib/password/index.js +2 -2
- package/lib/password/index.js.map +1 -1
- package/lib/password/utils/encryption.js +10 -22
- package/lib/password/utils/encryption.js.map +1 -1
- package/lib/password/utils/is-email.js +2 -2
- package/lib/password/utils/is-email.js.map +1 -1
- package/lib/password/utils/user.js +3 -3
- package/lib/password/utils/user.js.map +1 -1
- package/lib/rest-express/endpoints/authorize.js +47 -54
- package/lib/rest-express/endpoints/authorize.js.map +1 -1
- package/lib/rest-express/endpoints/geetestV3/geetest-init.js +85 -131
- package/lib/rest-express/endpoints/geetestV3/geetest-init.js.map +1 -1
- package/lib/rest-express/endpoints/geetestV3/sdk/geetest_config.js +1 -1
- package/lib/rest-express/endpoints/geetestV3/sdk/geetest_config.js.map +1 -1
- package/lib/rest-express/endpoints/geetestV3/sdk/geetest_lib.js +112 -160
- package/lib/rest-express/endpoints/geetestV3/sdk/geetest_lib.js.map +1 -1
- package/lib/rest-express/endpoints/geetestV3/sdk/geetest_lib_result.js +8 -9
- package/lib/rest-express/endpoints/geetestV3/sdk/geetest_lib_result.js.map +1 -1
- package/lib/rest-express/endpoints/get-user.js +7 -12
- package/lib/rest-express/endpoints/get-user.js.map +1 -1
- package/lib/rest-express/endpoints/impersonate.js +14 -27
- package/lib/rest-express/endpoints/impersonate.js.map +1 -1
- package/lib/rest-express/endpoints/initServer.js +9 -13
- package/lib/rest-express/endpoints/initServer.js.map +1 -1
- package/lib/rest-express/endpoints/login.js +82 -104
- package/lib/rest-express/endpoints/login.js.map +1 -1
- package/lib/rest-express/endpoints/logout.js +68 -86
- package/lib/rest-express/endpoints/logout.js.map +1 -1
- package/lib/rest-express/endpoints/oauth/provider-callback.js +29 -37
- package/lib/rest-express/endpoints/oauth/provider-callback.js.map +1 -1
- package/lib/rest-express/endpoints/password/change-password.js +73 -102
- package/lib/rest-express/endpoints/password/change-password.js.map +1 -1
- package/lib/rest-express/endpoints/password/register.js +63 -95
- package/lib/rest-express/endpoints/password/register.js.map +1 -1
- package/lib/rest-express/endpoints/password/reset.js +27 -48
- package/lib/rest-express/endpoints/password/reset.js.map +1 -1
- package/lib/rest-express/endpoints/password/setSpaceUserPassword.js +112 -144
- package/lib/rest-express/endpoints/password/setSpaceUserPassword.js.map +1 -1
- package/lib/rest-express/endpoints/password/two-factor.js +39 -70
- package/lib/rest-express/endpoints/password/two-factor.js.map +1 -1
- package/lib/rest-express/endpoints/password/verify-email.js +34 -65
- package/lib/rest-express/endpoints/password/verify-email.js.map +1 -1
- package/lib/rest-express/endpoints/password/verify.js +45 -74
- package/lib/rest-express/endpoints/password/verify.js.map +1 -1
- package/lib/rest-express/endpoints/put-user-name.js +19 -32
- package/lib/rest-express/endpoints/put-user-name.js.map +1 -1
- package/lib/rest-express/endpoints/refresh-access-token.js +14 -27
- package/lib/rest-express/endpoints/refresh-access-token.js.map +1 -1
- package/lib/rest-express/endpoints/service-authenticate.js +55 -79
- package/lib/rest-express/endpoints/service-authenticate.js.map +1 -1
- package/lib/rest-express/endpoints/spaces.js +13 -30
- package/lib/rest-express/endpoints/spaces.js.map +1 -1
- package/lib/rest-express/endpoints/steedos/accept_invitation.js +28 -42
- package/lib/rest-express/endpoints/steedos/accept_invitation.js.map +1 -1
- package/lib/rest-express/endpoints/steedos/create-tenant.js +81 -102
- package/lib/rest-express/endpoints/steedos/create-tenant.js.map +1 -1
- package/lib/rest-express/endpoints/steedos/decline_invitation.js +28 -42
- package/lib/rest-express/endpoints/steedos/decline_invitation.js.map +1 -1
- package/lib/rest-express/endpoints/steedos/get-tenant.js +54 -67
- package/lib/rest-express/endpoints/steedos/get-tenant.js.map +1 -1
- package/lib/rest-express/endpoints/steedos/settings.js +110 -127
- package/lib/rest-express/endpoints/steedos/settings.js.map +1 -1
- package/lib/rest-express/endpoints/update-session.js +33 -48
- package/lib/rest-express/endpoints/update-session.js.map +1 -1
- package/lib/rest-express/express-middleware.js +57 -59
- package/lib/rest-express/express-middleware.js.map +1 -1
- package/lib/rest-express/index.js +1 -1
- package/lib/rest-express/index.js.map +1 -1
- package/lib/rest-express/user-loader.js +67 -86
- package/lib/rest-express/user-loader.js.map +1 -1
- package/lib/rest-express/utils/get-user-agent.js +2 -2
- package/lib/rest-express/utils/get-user-agent.js.map +1 -1
- package/lib/rest-express/utils/getClientIp.js +3 -3
- package/lib/rest-express/utils/getClientIp.js.map +1 -1
- package/lib/rest-express/utils/send-error.js +5 -7
- package/lib/rest-express/utils/send-error.js.map +1 -1
- package/lib/rest-express/utils/steedos-auth.js +21 -21
- package/lib/rest-express/utils/steedos-auth.js.map +1 -1
- package/lib/rest-express/utils/users.js +17 -30
- package/lib/rest-express/utils/users.js.map +1 -1
- package/lib/server/accounts-server.js +413 -574
- package/lib/server/accounts-server.js.map +1 -1
- package/lib/server/index.js +1 -1
- package/lib/server/index.js.map +1 -1
- package/lib/server/utils/email.js +19 -35
- package/lib/server/utils/email.js.map +1 -1
- package/lib/server/utils/get-first-user-email.js +3 -3
- package/lib/server/utils/get-first-user-email.js.map +1 -1
- package/lib/server/utils/tokens.js +14 -24
- package/lib/server/utils/tokens.js.map +1 -1
- package/lib/types/index.js +1 -1
- package/package.json +5 -5
- package/src/database-mongo/mongo.ts +6 -2
- package/src/password/accounts-password.ts +61 -0
- package/src/rest-express/endpoints/password/change-password.ts +1 -1
- package/src/rest-express/endpoints/password/setSpaceUserPassword.ts +5 -0
- package/src/rest-express/endpoints/service-authenticate.ts +2 -5
- 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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
|
21
|
+
validateEmail(email) {
|
|
23
22
|
return !(0, lodash_1.isEmpty)((0, lodash_1.trim)(email)) && (0, utils_1.isEmail)(email);
|
|
24
23
|
},
|
|
25
|
-
validatePassword
|
|
24
|
+
validatePassword(password) {
|
|
26
25
|
return !(0, lodash_1.isEmpty)(password);
|
|
27
26
|
},
|
|
28
|
-
validateUsername
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
class AccountsPassword {
|
|
47
|
+
serviceName = "password";
|
|
48
|
+
server;
|
|
49
|
+
options;
|
|
50
|
+
db;
|
|
51
|
+
constructor(options = {}) {
|
|
52
|
+
this.options = { ...defaultOptions, ...options };
|
|
52
53
|
}
|
|
53
|
-
|
|
54
|
+
setStore(store) {
|
|
54
55
|
this.db = store;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
79
|
+
}
|
|
80
|
+
findUserById(id) {
|
|
91
81
|
return this.db.findUserById(id);
|
|
92
|
-
}
|
|
93
|
-
|
|
82
|
+
}
|
|
83
|
+
findUserByUsername(username) {
|
|
94
84
|
return this.db.findUserByUsername(username);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
94
|
+
}
|
|
95
|
+
removeEmail(userId, email) {
|
|
113
96
|
return this.db.removeEmail(userId, email);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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
|
-
|
|
215
|
-
|
|
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
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
return
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
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
|
-
|
|
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
|
-
|
|
562
|
-
return
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
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
|
-
|
|
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
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
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
|
-
|
|
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
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
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
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
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
|
-
|
|
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
|