PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 2.4.5
Fluent Support – Helpdesk & Customer Support Ticket System v2.4.5
2.4.5 2.4.0 2.3.2 2.3.1 2.3.0 2.2.1 2.2.0 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.4.0 1.4.1 1.4.2 1.4.5 1.4.6 1.4.7 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 All 69 releases
← All changes | app/Http/Controllers/AuthController.php +195 -101 1.10.5 → 2.4.5 View file →
@@ -4,9 +4,9 @@
4 4
5 5 use FluentSupport\App\Models\Meta;
6 6 use FluentSupport\App\Services\Helper;
7 7 use FluentSupport\Framework\Support\Arr;
8 -use FluentSupport\Framework\Request\Request;
8 +use FluentSupport\Framework\Http\Request\Request;
9 9 use FluentSupport\App\Hooks\Handlers\AuthHandler;
10 10 use FluentSupport\App\Hooks\Handlers\ReCaptchaHandler;
11 11 use FluentSupport\App\Hooks\Handlers\TwoFaHandler;
12 12 use FluentSupport\App\Hooks\Handlers\EmailVerificationHandler;
@@ -14,9 +14,11 @@
14 14
15 15 class AuthController extends Controller
16 16 {
17 17 /**
18 - * signUp method will create new user submitted data from sign up form
18 + * Two steps: the first submit emails a verification code, the second
19 + * verifies it and creates the user.
20 + *
19 21 * @param Request $request
20 22 * @return \WP_REST_Response
21 23 * @throws \FluentSupport\Framework\Validator\ValidationException
22 24 */
@@ -22,16 +24,22 @@
22 24 */
23 25 public function signup(Request $request)
24 26 {
25 27
26 - if(Helper::getAuthProvider() != 'fluent_support') {
28 + if(Helper::getAuthProvider() !== 'fluent_support') {
27 29 return $this->sendError([
28 30 'message' => __('You are not allowed to signup using this form', 'fluent-support')
29 31 ]);
30 32 }
31 33
32 - if (!wp_verify_nonce($request->get('_fsupport_signup_nonce'), 'fluent_support_signup_nonce')) {
34 + if (!Helper::isSignupEnabled()) {
33 35 return $this->sendError([
36 + 'message' => __('User registration is not enabled on this site.', 'fluent-support')
37 + ], 403);
38 + }
39 +
40 + if (!wp_verify_nonce($request->getSafe('_fsupport_signup_nonce', 'sanitize_text_field'), 'fluent_support_signup_nonce')) {
41 + return $this->sendError([
34 42 'message' => __('Security verification failed. Please try again', 'fluent-support')
35 43 ]);
36 44 }
37 45
@@ -56,11 +64,15 @@
56 64 * @param array $formData
57 65 */
58 66 do_action('fluent_support/before_signup_validation', $formData);
59 67
60 - $checkRecaptchaAvailability = $this->isRecaptchaApplicable('signup_form');
61 - if ($checkRecaptchaAvailability && !$formData['_email_verification_hash']) {
62 - $validateCaptcha = ReCaptchaHandler::validateRecaptcha($formData['g-recaptcha-response']);
68 + // The captcha was already passed on the first step, and the second step is
69 + // gated by the issued verification record below.
70 + $isVerificationStep = !empty($formData['_email_verification_token']);
71 +
72 + $checkRecaptchaAvailability = ReCaptchaHandler::isRecaptchaApplicable('signup_form');
73 + if ($checkRecaptchaAvailability && !$isVerificationStep) {
74 + $validateCaptcha = ReCaptchaHandler::validateRecaptcha($formData['g-recaptcha-response'] ?? '', null, null, 'signup');
63 75 if (!$validateCaptcha) {
64 76 return $this->response([
65 77 'message' => __('Your recaptcha is not verified', 'fluent-support')
66 78 ], 422);
@@ -68,9 +80,9 @@
68 80 }
69 81
70 82 $this->validate($formData, $rules, $messages);
71 83
72 - if (empty($formData['_email_verification_token'])) {
84 + if (!$isVerificationStep) {
73 85 $tokenHtml = EmailVerificationHandler::sendSignupEmailVerificationHtml($formData);
74 86
75 87 return $this->response([
76 88 'verification_html' => $tokenHtml
@@ -76,24 +88,46 @@
76 88 'verification_html' => $tokenHtml
77 89 ]);
78 90 } else {
79 91 $token = $formData['_email_verification_token'];
80 - $verificationHash = $formData['_email_verification_hash'];
92 + $verificationHash = $formData['_email_verification_hash'] ?? '';
81 93
82 - $logHash = Meta::where('object_type', 'fs_login_hashes',)
94 + $logHashMeta = Meta::where('object_type', 'fs_login_hashes',)
83 95 ->where('key', $verificationHash)
84 96 ->first();
85 - $logHash = Helper::safeUnserialize($logHash->value);
86 97
98 + if (!$logHashMeta) {
99 + wp_send_json([
100 + 'message' => __('Please provide a valid verification code that was sent to your email address', 'fluent-support')
101 + ], 422);
102 + }
103 +
104 + $logHash = Helper::safeUnserialize($logHashMeta->value);
105 +
87 106 if (!$logHash) {
88 107 wp_send_json([
89 - 'message' => __('Please provide a valid verification code that sent to your email address', 'fluent-support')
108 + 'message' => __('Please provide a valid verification code that was sent to your email address', 'fluent-support')
90 109 ], 422);
91 110 }
92 111
93 - // check if it got expired or not
94 - if ($logHash['used_count'] > 5 || strtotime($logHash['valid_till']) < current_time('timestamp')) {
112 + if (($logHash['status'] ?? '') !== 'issued') {
95 113 wp_send_json([
114 + 'message' => __('Your verification code has already been used. Please try again', 'fluent-support')
115 + ], 422);
116 + }
117 +
118 + // Old or malformed records have no bound email.
119 + if (empty($logHash['email'])) {
120 + wp_send_json([
121 + 'message' => __('Your verification code has expired. Please request a new one', 'fluent-support')
122 + ], 422);
123 + }
124 +
125 + // valid_till is written with gmdate(). Parse it as UTC explicitly, since a plugin
126 + // may have changed the PHP default timezone.
127 + $validTill = $logHash['valid_till'] ?? '';
128 + if (($logHash['used_count'] ?? 0) > 5 || ($validTill && strtotime($validTill . ' UTC') < current_time('timestamp'))) {
129 + wp_send_json([
96 130 'message' => __('Your verification code has been expired. Please try again', 'fluent-support')
97 131 ], 422);
98 132 }
99 133
@@ -104,18 +138,32 @@
104 138 'value' => maybe_serialize($logHash)
105 139 ]);
106 140
107 141 wp_send_json([
108 - 'message' => __('Please provide a valid verification code that sent to your email address', 'fluent-support')
142 + 'message' => __('Please provide a valid verification code that was sent to your email address', 'fluent-support')
109 143 ], 422);
110 144 }
111 145
112 - $logHash['used_count'] += 1;
113 - $logHash['status'] = 'used';
146 + // Consume atomically: the update only matches if the record is unchanged since
147 + // we read it, so two concurrent requests can't both succeed.
148 + $consumed = Meta::where('key', $logHash['login_hash'])
149 + ->where('object_type', 'fs_login_hashes')
150 + ->where('value', $logHashMeta->value)
151 + ->update([
152 + 'value' => maybe_serialize(array_merge($logHash, [
153 + 'used_count' => ($logHash['used_count'] ?? 0) + 1,
154 + 'status' => 'used',
155 + ]))
156 + ]);
114 157
115 - Meta::where('key', $logHash['login_hash'])->update([
116 - 'value' => maybe_serialize($logHash)
117 - ]);
158 + if (!$consumed) {
159 + wp_send_json([
160 + 'message' => __('Your verification code has already been used. Please try again', 'fluent-support')
161 + ], 422);
162 + }
163 +
164 + // Use the address the code was issued to, not the submitted one.
165 + $formData['email'] = $logHash['email'];
118 166 }
119 167
120 168 /*
121 169 * Action After validate user signup validation success
@@ -126,13 +174,13 @@
126 174 do_action('fluent_support/after_signup_validation', $formData);
127 175
128 176 $userId = $this->createUser($formData);
129 177
130 - if (is_wp_error($userId)) {
178 + if (!$userId) {
131 179 return $this->response(
132 180 apply_filters(
133 181 'fluent_support/signup_create_user_error',
134 - ['error' => $userId->get_error_message()]
182 + ['error' => __('Could not create your account. The username or email address may already be registered.', 'fluent-support')]
135 183 ), 423);
136 184 }
137 185
138 186 /*
@@ -138,9 +186,8 @@
138 186 /*
139 187 * Action After creating WP user from ticket sign up form
140 188 *
141 189 * @since v1.0.0
142 - * @param array $formData
143 190 */
144 191 do_action('fluent_support/after_creating_user');
145 192
146 193 $this->maybeUpdateUser($userId, $formData);
@@ -158,25 +205,30 @@
158 205 'message' => __('Successfully registered to the site.', 'fluent-support'),
159 206 'redirect' => Arr::get($formData, '__redirect_to', Helper::getPortalBaseUrl())
160 207 ]);
161 208
209 + // The browser navigates to this by script; keep it on this site.
210 + if (!empty($response['redirect'])) {
211 + $portalUrl = Helper::getPortalBaseUrl();
212 + $response['redirect'] = wp_validate_redirect(esc_url_raw($response['redirect']), $portalUrl) ?: $portalUrl;
213 + }
214 +
162 215 return $this->response($response);
163 216 }
164 217
165 218 /**
166 - * handleLogin method will perform login functionality and redirect
167 219 * @param Request $request
168 220 * @return \WP_REST_Response
169 221 */
170 222 public function handleLogin(Request $request)
171 223 {
172 - if(Helper::getAuthProvider() != 'fluent_support') {
224 + if(Helper::getAuthProvider() !== 'fluent_support') {
173 225 return $this->sendError([
174 226 'message' => __('You are not allowed to login using this form', 'fluent-support')
175 227 ]);
176 228 }
177 229
178 - if (!wp_verify_nonce($request->get('_support_login_nonce'), 'fsupport_login_nonce')) {
230 + if (!wp_verify_nonce($request->getSafe('_support_login_nonce', 'sanitize_text_field'), 'fsupport_login_nonce')) {
179 231 return $this->response([
180 232 'message' => __('Security verification failed', 'fluent-support')
181 233 ], 403);
182 234 }
@@ -182,11 +234,11 @@
182 234 }
183 235
184 236 $data = $request->all();
185 237
186 - $checkRecaptchaAvailability = $this->isRecaptchaApplicable('login_form');
238 + $checkRecaptchaAvailability = ReCaptchaHandler::isRecaptchaApplicable('login_form');
187 239 if ($checkRecaptchaAvailability) {
188 - $validateCaptcha = ReCaptchaHandler::validateRecaptcha($data['g-recaptcha-response']);
240 + $validateCaptcha = ReCaptchaHandler::validateRecaptcha($data['g-recaptcha-response'] ?? '', null, null, 'login');
189 241
190 242 if (!$validateCaptcha) {
191 243 return $this->response([
192 244 'message' => __('Your recaptcha is not verified', 'fluent-support')
@@ -199,15 +251,13 @@
199 251 'message' => __('Email and Password is required', 'fluent-support')
200 252 ], 403);
201 253 }
202 254 $redirectUrl = Helper::getPortalBaseUrl();
203 - if ($redirect = $request->get('redirect_to')) {
204 - if (filter_var($redirect, FILTER_VALIDATE_URL)) {
205 - $redirectUrl = sanitize_url($redirect);
206 - }
255 + if ($redirect = $request->getSafe('redirect_to', 'sanitize_text_field')) {
256 + $redirectUrl = wp_validate_redirect($redirect, $redirectUrl);
207 257 }
208 258
209 - if (get_current_user_id()) { // user already registered
259 + if (get_current_user_id()) { // already logged in
210 260 return $this->sendSuccess([
211 261 'redirect' => $redirectUrl
212 262 ]);
213 263 }
@@ -212,9 +262,9 @@
212 262 ]);
213 263 }
214 264
215 265 $email = sanitize_user($data['log']);
216 - $password = trim($data['pwd']);
266 + $password = trim($data['pwd'] ?? '');
217 267
218 268 if (is_email($email)) {
219 269 $user = get_user_by('email', $email);
220 270 } else {
@@ -220,12 +270,32 @@
220 270 } else {
221 271 $user = get_user_by('login', $email);
222 272 }
223 273
274 + // 5 attempts per account+IP, 20 per account.
275 + $ip = Helper::getIp();
276 + $ipKey = $user
277 + ? 'fs_login_ip_' . wp_hash($user->ID . '|' . $ip)
278 + : 'fs_login_ip_' . wp_hash(strtolower($email) . '|' . $ip);
279 + $accountKey = $user
280 + ? 'fs_login_act_' . wp_hash($user->ID)
281 + : 'fs_login_act_' . wp_hash(strtolower($email));
282 +
283 + $ipAttempts = get_transient($ipKey);
284 + $accountAttempts = get_transient($accountKey);
285 +
286 + if (($ipAttempts !== false && $ipAttempts >= 5) || ($accountAttempts !== false && $accountAttempts >= 20)) {
287 + return $this->sendError([
288 + 'message' => __('Too many login attempts. Please try again after 15 minutes.', 'fluent-support')
289 + ], 429);
290 + }
291 +
224 292 if (!$user) {
225 - $user = new \WP_Error('authentication_failed', __('<strong>Error</strong>: Invalid username, email address or incorrect password.', 'fluent-support'));
293 + $user = new \WP_Error('authentication_failed', __('Invalid username, email address or incorrect password.', 'fluent-support'));
226 294
227 295 do_action('wp_login_failed', $email, $user);
296 + $this->incrementLoginAttempts($ipKey);
297 + $this->incrementLoginAttempts($accountKey);
228 298
229 299 return $this->response([
230 300 'message' => __('Email or Password is not valid. Please try again', 'fluent-support')
231 301 ], 403);
@@ -232,9 +302,18 @@
232 302
233 303 }
234 304
235 305 $twoFactorEnabled = Helper::getBusinessSettings('enable_two_fa');
236 - if ('yes' == $twoFactorEnabled) {
306 + if ('yes' === $twoFactorEnabled) {
307 + if (!wp_check_password($password, $user->user_pass, $user->ID)) {
308 + $this->incrementLoginAttempts($ipKey);
309 + $this->incrementLoginAttempts($accountKey);
310 +
311 + return $this->response([
312 + 'message' => __('Invalid username, email address or incorrect password.', 'fluent-support')
313 + ], 403);
314 + }
315 +
237 316 (new TwoFaHandler)->maybe2FaRedirect($user);
238 317 }
239 318
240 319 if (apply_filters('fluent_support_use_native_login', true)) {
@@ -239,13 +318,19 @@
239 318
240 319 if (apply_filters('fluent_support_use_native_login', true)) {
241 320 $user = wp_signon();
242 321 if (is_wp_error($user)) {
322 + $this->incrementLoginAttempts($ipKey);
323 + $this->incrementLoginAttempts($accountKey);
243 324 return $this->response([
244 325 'message' => $user->get_error_message()
245 326 ], 403);
246 327 }
247 328
329 + $authIpKey = 'fs_login_ip_' . wp_hash($user->ID . '|' . $ip);
330 + $authAccountKey = 'fs_login_act_' . wp_hash($user->ID);
331 + delete_transient($authIpKey);
332 + delete_transient($authAccountKey);
248 333 return $this->sendSuccess([
249 334 'redirect' => $redirectUrl
250 335 ]);
251 336 }
@@ -250,8 +335,10 @@
250 335 ]);
251 336 }
252 337
253 338 if (wp_check_password($password, $user->user_pass, $user->ID)) {
339 + delete_transient($ipKey);
340 + delete_transient($accountKey);
254 341 $this->login($user->ID);
255 342 return $this->sendSuccess([
256 343 'redirect' => $redirectUrl
257 344 ]);
@@ -256,29 +343,24 @@
256 343 'redirect' => $redirectUrl
257 344 ]);
258 345 }
259 346
347 + $this->incrementLoginAttempts($ipKey);
348 + $this->incrementLoginAttempts($accountKey);
349 +
260 350 return $this->response([
261 - 'message' => __('<strong>Error</strong>: Invalid username, email address or incorrect password.', 'fluent-support')
351 + 'message' => __('Invalid username, email address or incorrect password.', 'fluent-support')
262 352 ], 403);
263 353 }
264 354
265 - public function isRecaptchaApplicable($formName)
355 + private function incrementLoginAttempts($rateLimitKey)
266 356 {
267 - $reCaptchaSettingsData = Meta::where('object_type', '_fs_recaptcha_settings')->first();
268 - if(!isset($reCaptchaSettingsData->value)){
269 - return false;
357 + $attempts = get_transient($rateLimitKey);
358 + if ($attempts === false) {
359 + set_transient($rateLimitKey, 1, 15 * MINUTE_IN_SECONDS);
360 + } else {
361 + set_transient($rateLimitKey, $attempts + 1, 15 * MINUTE_IN_SECONDS);
270 362 }
271 - $reCaptchaData = Helper::safeUnserialize($reCaptchaSettingsData->value, []);
272 - if(!isset($reCaptchaData['is_enabled']) || !isset($reCaptchaData['formContainingReCaptcha'])){
273 - return false;
274 - }
275 - $isEnabled = filter_var($reCaptchaData['is_enabled'], FILTER_VALIDATE_BOOLEAN);
276 - if (!$isEnabled) {
277 - return false;
278 - }
279 - $formContainingReCaptcha = $reCaptchaData['formContainingReCaptcha'];
280 - return 'yes' === $formContainingReCaptcha[$formName];
281 363 }
282 364
283 365 private function nativeLoginHandler($user, $info, $redirectUrl = '')
284 366 {
@@ -305,9 +387,9 @@
305 387 }
306 388
307 389 $user_signon = wp_signon($info, $secure_cookie);
308 390
309 - // Note: No sanitization needed here as we're only checking emptiness, not using the cookie value
391 + // Only checked for emptiness, so no sanitizing needed.
310 392 if (!is_wp_error($user_signon) && empty($_COOKIE[LOGGED_IN_COOKIE])) {
311 393 if (headers_sent()) {
312 394 return $this->response([
313 395 // translators: %1$s is the URL to WordPress cookies documentation, %2$s is the URL to WordPress support forums
@@ -346,9 +428,8 @@
346 428 ]);
347 429 }
348 430
349 431 /**
350 - * getRules method will prepare the rules for the input field
351 432 * @param array $fields
352 433 * @return mixed
353 434 */
354 435 protected function getRules($fields = [])
@@ -380,9 +461,9 @@
380 461
381 462 public function resetPassword(Request $request)
382 463 {
383 464
384 - if(Helper::getAuthProvider() != 'fluent_support') {
465 + if(Helper::getAuthProvider() !== 'fluent_support') {
385 466 return $this->sendError([
386 467 'message' => __('You are not allowed to reset password using this form', 'fluent-support')
387 468 ]);
388 469 }
@@ -388,22 +469,30 @@
388 469 }
389 470
390 471 $errors = new \WP_Error();
391 472
392 - if (!wp_verify_nonce($request->get('_fsupport_reset_pass_nonce'), 'fluent_support_reset_pass_nonce')) {
473 + if (!wp_verify_nonce($request->getSafe('_fsupport_reset_pass_nonce', 'sanitize_text_field'), 'fluent_support_reset_pass_nonce')) {
393 474 return $this->sendError([
394 475 'message' => __('Security verification failed. Please try again', 'fluent-support')
395 476 ]);
396 477 }
397 478
398 - $usernameOrEmail = trim(wp_unslash($request->get('user_login')));
479 + $usernameOrEmail = trim(wp_unslash($request->getSafe('user_login', 'sanitize_text_field')));
399 480
400 481 if (!$usernameOrEmail) {
401 482 return $this->sendError([
402 - 'message' => 'Username or email is required'
483 + 'message' => __('Username or email is required.', 'fluent-support')
403 484 ]);
404 485 }
405 486
487 + // Generous because of shared NAT IPs. Runs before the account lookup so probes for
488 + // missing accounts are throttled too, and a 429 reveals nothing about existence.
489 + if (Helper::hitRateLimit('fs_reset_pass_ip_' . wp_hash(Helper::getIp()), 20)) {
490 + return $this->sendError([
491 + 'message' => __('Too many password reset requests. Please try again after 15 minutes.', 'fluent-support')
492 + ], 429);
493 + }
494 +
406 495 $user_data = get_user_by('email', $usernameOrEmail);
407 496
408 497 if (!$user_data) {
409 498 $user_data = get_user_by('login', $usernameOrEmail);
@@ -409,11 +498,9 @@
409 498 $user_data = get_user_by('login', $usernameOrEmail);
410 499 }
411 500
412 501 if (!$user_data) {
413 - return $this->sendError([
414 - 'message' => __('Invalid username or email', 'fluent-support')
415 - ]);
502 + return $this->sendResetPassResponse();
416 503 }
417 504
418 505 $user_data = apply_filters('lostpassword_user_data', $user_data, $errors);
419 506
@@ -421,24 +508,17 @@
421 508
422 509 $errors = apply_filters('lostpassword_errors', $errors, $user_data);
423 510
424 511 if ($errors->has_errors()) {
425 - return $this->sendError([
426 - 'message' => $errors->get_error_message()
427 - ]);
512 + return $this->sendResetPassResponse();
428 513 }
429 514
430 515 if (!$user_data) {
431 - return $this->sendError([
432 - 'message' => __('<strong>Error</strong>: There is no account with that username or email address.', 'fluent-support')
433 - ]);
516 + return $this->sendResetPassResponse();
434 517 }
435 518
436 519 if (is_multisite() && !is_user_member_of_blog($user_data->ID, get_current_blog_id())) {
437 -
438 - return $this->sendError([
439 - 'message' => __('<strong>Error</strong>: Invalid username or email', 'fluent-support')
440 - ]);
520 + return $this->sendResetPassResponse();
441 521 }
442 522
443 523 // Redefining user_login ensures we return the right case in the email.
444 524 $user_login = $user_data->user_login;
@@ -446,21 +526,13 @@
446 526 do_action('retrieve_password', $user_login);
447 527
448 528 $allow = apply_filters('allow_password_reset', true, $user_data->ID);
449 529
450 - if (!$allow) {
451 - return $this->sendError([
452 - 'message' => __('Password reset is not allowed for this user', 'fluent-support')
453 - ]);
530 + if (!$allow || is_wp_error($allow)) {
531 + return $this->sendResetPassResponse();
454 532 }
455 533
456 - if (is_wp_error($allow)) {
457 - return $this->sendError([
458 - 'message' => $allow->get_error_message()
459 - ]);
460 - }
461 534
462 -
463 535 /*
464 536 * Filter reset password link text
465 537 *
466 538 * @since v1.5.7
@@ -468,8 +540,18 @@
468 540 */
469 541 // translators: %s is the site name
470 542 $linkText = apply_filters("fluent_support/reset_password_link", sprintf(__('Reset your password for %s', 'fluent-support'), get_bloginfo('name')));
471 543
544 + // get_password_reset_key() invalidates the previous link, so repeated requests could
545 + // block recovery. The owner already has a working link from the first send.
546 + $cooldownKey = 'fs_reset_pass_sent_' . wp_hash($user_data->ID);
547 +
548 + if (get_transient($cooldownKey)) {
549 + return $this->sendResetPassResponse();
550 + }
551 +
552 + set_transient($cooldownKey, 1, 5 * MINUTE_IN_SECONDS);
553 +
472 554 $resetUrl = add_query_arg([
473 555 'action' => 'rp',
474 556 'key' => get_password_reset_key($user_data),
475 557 'login' => rawurlencode($user_data->user_login)
@@ -507,15 +589,24 @@
507 589 $headers = array('Content-Type: text/html; charset=UTF-8');
508 590
509 591 wp_mail($user_data->user_email, $mailSubject, $message, $headers);
510 592
593 + return $this->sendResetPassResponse();
594 + }
595 +
596 + /**
597 + * Same response for every outcome, so the form can't confirm which accounts exist.
598 + *
599 + * @return mixed
600 + */
601 + protected function sendResetPassResponse()
602 + {
511 603 return $this->sendSuccess([
512 - 'message' => __('Please check your email for the reset link', 'fluent-support')
604 + 'message' => __('If an account matches that username or email, a password reset link has been sent. Please check your inbox, including the spam folder.', 'fluent-support')
513 605 ]);
514 606 }
515 607
516 608 /**
517 - * getMessages message will return the validation message regarding sign up or sign in
518 609 * @param array $rules
519 610 * @return mixed
520 611 */
521 612 protected function getMessages($rules = [])
@@ -530,11 +621,10 @@
530 621 return apply_filters('fluent_support/signup_validation_messages', [], $rules);
531 622 }
532 623
533 624 /**
534 - * createUser method will create new user
535 625 * @param array $formData
536 - * @return mixed
626 + * @return int|false
537 627 */
538 628 public function createUser($formData = [])
539 629 {
540 630 /*
@@ -553,9 +643,9 @@
553 643 */
554 644 $userName = apply_filters('fluent_support/signup_username', Arr::get($formData, 'username'));
555 645
556 646 if (empty($formData['password'])) {
557 - $password = wp_generate_password(8);
647 + $password = wp_generate_password(16, true, true);
558 648 } else {
559 649 $password = $formData['password'];
560 650 }
561 651
@@ -587,22 +677,29 @@
587 677
588 678 }
589 679
590 680 /**
591 - * maybeUpdateUser method will update user information if exists
592 - * @param $userId
593 - * @param $formData
681 + * Sets the name fields from first/last name, if given.
682 + *
683 + * @param int $userId
684 + * @param array $formData
594 685 */
595 686 public function maybeUpdateUser($userId, $formData)
596 687 {
597 - $name = trim(Arr::get($formData, 'first_name') . ' ' . Arr::get($formData, 'last_name'));
688 + if (!$userId) {
689 + return;
690 + }
598 691
692 + $firstName = Arr::get($formData, 'first_name', '');
693 + $lastName = Arr::get($formData, 'last_name', '');
694 + $name = trim($firstName . ' ' . $lastName);
695 +
599 696 $data = array_filter([
600 697 'ID' => $userId,
601 698 'user_nicename' => $name,
602 699 'display_name' => $name,
603 - 'first_name' => Arr::get($formData, 'first_name'),
604 - 'last_name' => Arr::get($formData, 'last_name'),
700 + 'first_name' => $firstName,
701 + 'last_name' => $lastName,
605 702 ]);
606 703
607 704 if ($name) {
608 705 /*
@@ -632,9 +729,9 @@
632 729 }
633 730 }
634 731
635 732 public function addUserMetaData($userId, $formData) {
636 - $customFieldsKey = apply_filters('fluent_support/custom_registration_form_fields_key', Helper::getBusinessSettings('custom_registration_form_field'));
733 + $customFieldsKey = Helper::getCustomRegistrationFieldKeys();
637 734
638 735 if (empty($customFieldsKey)) {
639 736 return;
640 737 }
@@ -639,18 +736,16 @@
639 736 return;
640 737 }
641 738
642 739 foreach ($customFieldsKey as $key) {
643 - if (isset($formData[$key])) {
644 - $fieldValue = $formData[$key];
645 - update_user_meta($userId, $key, $fieldValue);
740 + if (isset($formData[$key]) && is_scalar($formData[$key])) {
741 + update_user_meta($userId, $key, sanitize_text_field($formData[$key]));
646 742 }
647 743 }
648 744 }
649 745
650 746 /**
651 - * assignRole method will assign role to a given user id
652 - * @param $userId
747 + * @param int $userId
653 748 */
654 749 protected function assignRole($userId)
655 750 {
656 751 $user = new \WP_User($userId);
@@ -658,9 +753,9 @@
658 753 /*
659 754 * Action before assigning role to registered user
660 755 *
661 756 * @since v1.0.0
662 - * @param array $data
757 + * @param \WP_User $user
663 758 */
664 759 do_action('fluent_support/before_assigning_role', $user);
665 760 /*
666 761 * Filter user assignable role after signup
@@ -674,9 +769,9 @@
674 769 /*
675 770 * Action after assigning role to registered user
676 771 *
677 772 * @since v1.0.0
678 - * @param array $data
773 + * @param \WP_User $user
679 774 */
680 775 do_action('fluent_support/after_assigning_role', $user);
681 776 }
682 777
@@ -681,10 +776,9 @@
681 776 }
682 777
683 778
684 779 /**
685 - * login method will clear existing cookies and set new cookie for a given user id
686 - * @param $userId
780 + * @param int $userId
687 781 */
688 782 protected function login($userId)
689 783 {
690 784 /*