PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 1.0.98
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v1.0.98
2.10.0 2.10.01 2.9.1 2.9.0 2.8.1 2.8.0 2.7.7 2.7.5 2.7.0 2.6.01 2.6.0 2.5.0 2.4.01 trunk 1.0.90 1.0.91 1.0.92 1.0.93 1.0.94 1.0.95 1.0.96 1.0.97 1.0.98 1.0.99 1.1.0 All 77 releases
fluent-community / Modules / Auth / AuthHelper.php

AuthHelper.php in FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses 1.0.98, at Modules/Auth/AuthHelper.php

347 lines 14.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCommunity\Modules\Auth;
4
5 use FluentCommunity\App\App;
6 use FluentCommunity\App\Services\Helper;
7 use FluentCommunity\App\Services\Libs\Mailer;
8 use FluentCommunity\Framework\Support\Arr;
9
10 class AuthHelper
11 {
12 public static function registerNewUser($user_login, $user_email, $user_pass = '', $extraData = [])
13 {
14 $errors = new \WP_Error();
15
16 $sanitized_user_login = sanitize_user($user_login);
17
18 $user_email = apply_filters('user_registration_email', $user_email);
19
20 // Check the username.
21 if ('' === $sanitized_user_login) {
22 $errors->add('empty_username', __('<strong>Error</strong>: Please enter a username.', 'fluent-community'));
23 } elseif (!validate_username($user_login)) {
24 $errors->add('invalid_username', __('<strong>Error</strong>: This username is invalid because it uses illegal characters. Please enter a valid username.', 'fluent-community'));
25 $sanitized_user_login = '';
26 } elseif (username_exists($sanitized_user_login)) {
27 $errors->add('username_exists', __('<strong>Error</strong>: This username is already registered. Please choose another one.', 'fluent-community'));
28 } else {
29 /** This filter is documented in wp-includes/user.php */
30 $illegal_user_logins = (array)apply_filters('illegal_user_logins', array());
31 if (in_array(strtolower($sanitized_user_login), array_map('strtolower', $illegal_user_logins), true)) {
32 $errors->add('invalid_username', __('<strong>Error</strong>: Sorry, that username is not allowed.', 'fluent-community'));
33 }
34 }
35
36 // Check the email address.
37 if ('' === $user_email) {
38 $errors->add('empty_email', __('<strong>Error</strong>: Please type your email address.', 'fluent-community'));
39 } elseif (!is_email($user_email)) {
40 $errors->add('invalid_email', __('<strong>Error</strong>: The email address is not correct.', 'fluent-community'));
41 $user_email = '';
42 } elseif (email_exists($user_email)) {
43 $errors->add(
44 'email_exists',
45 __('<strong>Error:</strong> This email address is already registered. Please login or try resetting your password.', 'fluent-community')
46 );
47 }
48
49 do_action('register_post', $sanitized_user_login, $user_email, $errors);
50
51 $errors = apply_filters('registration_errors', $errors, $sanitized_user_login, $user_email);
52
53 if ($errors->has_errors()) {
54 return $errors;
55 }
56
57 if (!$user_pass) {
58 $user_pass = wp_generate_password(8, false);
59 }
60
61 $data = [
62 'user_login' => wp_slash($sanitized_user_login),
63 'user_email' => wp_slash($user_email),
64 'user_pass' => $user_pass
65 ];
66
67 if (!empty($extraData['first_name'])) {
68 $data['first_name'] = sanitize_text_field($extraData['first_name']);
69 }
70
71 if (!empty($extraData['last_name'])) {
72 $data['last_name'] = sanitize_text_field($extraData['last_name']);
73 }
74
75 if (!empty($extraData['full_name']) && empty($extraData['first_name']) && empty($extraData['last_name'])) {
76 $extraData['full_name'] = sanitize_text_field($extraData['full_name']);
77 // extract the names
78 $fullNameArray = explode(' ', $extraData['full_name']);
79 $data['first_name'] = array_shift($fullNameArray);
80 if ($fullNameArray) {
81 $data['last_name'] = implode(' ', $fullNameArray);
82 } else {
83 $data['last_name'] = '';
84 }
85 }
86
87 if (!empty($extraData['description'])) {
88 $data['description'] = sanitize_textarea_field($extraData['description']);
89 }
90
91 if (!empty($extraData['user_url']) && filter_var($extraData['user_url'], FILTER_VALIDATE_URL)) {
92 $data['user_url'] = sanitize_url($extraData['user_url']);
93 }
94
95 if (!empty($extraData['role'])) {
96 $data['role'] = $extraData['role'];
97 }
98
99 $user_id = wp_insert_user($data);
100
101 if (!$user_id || is_wp_error($user_id)) {
102 $errors->add('registerfail', __('<strong>Error</strong>: Could not register you. Please contact the site admin!', 'fluent-community')
103 );
104 return $errors;
105 }
106
107 if (!empty($_COOKIE['wp_lang'])) {
108 $wp_lang = sanitize_text_field($_COOKIE['wp_lang']);
109 if (in_array($wp_lang, get_available_languages(), true)) {
110 update_user_meta($user_id, 'locale', $wp_lang); // Set user locale if defined on registration.
111 }
112 }
113
114 do_action('register_new_user', $user_id);
115
116 return $user_id;
117 }
118
119 public static function makeLogin($user)
120 {
121 wp_clear_auth_cookie();
122 wp_set_current_user($user->ID, $user->user_login);
123 wp_set_auth_cookie($user->ID, true, is_ssl());
124
125 $user = get_user_by('ID', $user->ID);
126
127 if ($user) {
128 do_action('wp_login', $user->user_login, $user);
129 }
130
131 return $user;
132 }
133
134 public static function isFluentAuthAvailable()
135 {
136 if (defined('FLUENT_AUTH_VERSION') && FLUENT_AUTH_VERSION) {
137 return (new \FluentAuth\App\Hooks\Handlers\CustomAuthHandler())->isEnabled();
138 }
139
140 return false;
141 }
142
143 public static function getFormFields($invitation = null)
144 {
145 $fields = apply_filters('fluent_communuty/auth/signup_fields', [
146 'full_name' => [
147 'label' => __('Full name', 'fluent-community'),
148 'placeholder' => __('Your first & last name', 'fluent-community'),
149 'type' => 'text',
150 'required' => true,
151 'value' => $invitation ? Arr::get($invitation->meta, 'invitee_name') : '',
152 'sanitize_callback' => 'sanitize_text_field'
153 ],
154 'email' => [
155 'type' => 'email',
156 'placeholder' => __('Your email address', 'fluent-community'),
157 'label' => __('Email Address', 'fluent-community'),
158 'required' => true,
159 'value' => $invitation ? $invitation->message : '',
160 'readonly' => !!$invitation,
161 'sanitize_callback' => 'sanitize_email'
162 ],
163 'username' => [
164 'type' => 'text',
165 'placeholder' => __('No space or special characters', 'fluent-community'),
166 'label' => __('Space username', 'fluent-community'),
167 'required' => true,
168 'sanitize_callback' => 'sanitize_user'
169 ],
170 'password' => [
171 'type' => 'password',
172 'placeholder' => __('Password', 'fluent-community'),
173 'label' => __('Account Password', 'fluent-community'),
174 'required' => true,
175 'sanitize_callback' => 'sanitize_text_field'
176 ],
177 'conf_password' => [
178 'type' => 'password',
179 'placeholder' => __('Password Confirmation', 'fluent-community'),
180 'label' => __('Re-type Account Password', 'fluent-community'),
181 'required' => true,
182 'sanitize_callback' => 'sanitize_text_field'
183 ],
184 'terms' => [
185 'type' => 'inline_checkbox',
186 'inline_label' => __('I agree to the terms and conditions', 'fluent-community'),
187 'required' => true
188 ]
189 ], $invitation);
190
191 if (!self::isPasswordConfRequired()) {
192 unset($fields['conf_password']);
193 }
194
195 return $fields;
196 }
197
198 public static function isPasswordConfRequired()
199 {
200 return apply_filters('fluent_community/autg/password_confirmation', true);
201 }
202
203 public static function isRegistrationEnabled()
204 {
205 return apply_filters('fluent_community/auth/registration_enabled', !!get_option('users_can_register'));
206 }
207
208 public static function isTwoFactorEnabled()
209 {
210 return apply_filters('fluent_community/auth/two_factor_enabled', true);
211 }
212
213 public static function get2FaRegistrationCodeForm($formData)
214 {
215 $generalSettings = Helper::generalSettings();
216 try {
217 $verifcationCode = str_pad(random_int(100123, 900987), 6, 0, STR_PAD_LEFT);
218 } catch (\Exception $e) {
219 $verifcationCode = str_pad(mt_rand(100123, 900987), 6, 0, STR_PAD_LEFT);
220 }
221
222 // Hash the code
223 $codeHash = wp_hash_password($verifcationCode);
224
225 // Create a token with the email and code hash
226 $data = [
227 'email' => $formData['email'],
228 'code_hash' => $codeHash,
229 'expires' => time() + 600 // 10 minutes expiry
230 ];
231 $token = base64_encode(json_encode($data));
232
233 // Sign the token
234 $signature = hash_hmac('sha256', $token, SECURE_AUTH_KEY);
235 $signedToken = $token . '.' . $signature;
236
237 $mailSubject = apply_filters("fluent_community/auth/signup_verification_mail_subject", sprintf(__('Your registration verification code for %s', 'fluent-community'), Arr::get($generalSettings, 'site_title')));
238
239 $pStart = '<p style="font-family: Arial, sans-serif; font-size: 16px; font-weight: normal; margin: 0; margin-bottom: 16px;">';
240
241 $message = $pStart . sprintf(__('Hello %s,', 'fluent-community'), Arr::get($formData, 'first_name')) . '</p>' .
242 $pStart . __('Thank you for registering with us! To complete the setup of your account, please enter the verification code below on the registration page.', 'fluent-community') . '</p>' .
243 $pStart . '<b>' . sprintf(__('Verification Code: %s', 'fluent-community'), $verifcationCode) . '</b></p>' .
244 '<br />' .
245 $pStart . __('This code is valid for 10 minutes and is meant to ensure the security of your account. If you did not initiate this request, please ignore this email.', 'fluent-community') . '</p>';
246
247 $message = apply_filters('fluent_community/auth/signup_verification_email_body', $message, $verifcationCode, $formData);
248
249 $generalSettings = Helper::generalSettings();
250 $message = (string)App::make('view')->make('email.template', [
251 'logo' => [
252 'url' => $generalSettings['logo'],
253 'alt' => $generalSettings['site_title']
254 ],
255 'bodyContent' => $message,
256 'pre_header' => __('Activate your account', 'fluent-community'),
257 'footerLines' => [
258 __('If you did not initiate this request, please ignore this email.', 'fluent-community'),
259 sprintf(__('This email has been sent from %1$s. Site: %2$s', 'fluent-community'), Arr::get($generalSettings, 'site_title'), site_url())
260 ]
261 ]);
262
263 $mailer = new Mailer($formData['email'], $mailSubject, $message);
264
265 if ($formData['first_name']) {
266 $toName = trim(Arr::get($formData, 'first_name') . ' ' . Arr::get($formData, 'last_name'));
267 $mailer = $mailer->to($formData['email'], $toName);
268 }
269
270 $mailer->send();
271
272 ob_start();
273 ?>
274 <div class="fls_signup_verification">
275 <input type="hidden" name="__two_fa_signed_token" value="<?php echo esc_attr($signedToken); ?>"/>
276 <p><?php echo esc_html(sprintf(__('A verification code has been sent to %s. Please provide the code below: ', 'fluent-community'), $formData['email'])) ?></p>
277 <div class="fcom_form-group fcom_field_vefication">
278 <div class="fcom_form_label">
279 <label for="fcom_field_vefication"><?php _e('Verification Code', 'fluent-community'); ?></label>
280 </div>
281 <div class="fs_input_wrap">
282 <input type="text" id="fcom_field_vefication"
283 placeholder="<?php _e('2FA Code', 'fluent-community'); ?>" name="_email_verification_code"
284 required/>
285 </div>
286 </div>
287 <div class="fcom_form-group">
288 <div class="fcom_form_input">
289 <button type="submit" class="fcom_btn fcom_btn_primary">
290 <?php _e('Complete Signup', 'fluent-community'); ?>
291 </button>
292 </div>
293 </div>
294 </div>
295
296 <?php
297 return ob_get_clean();
298 }
299
300 public static function validateVerificationCode($code, $verificationToken, $formData)
301 {
302 list($data, $signature) = explode('.', $verificationToken, 2);
303 $expectedSignature = hash_hmac('sha256', $data, SECURE_AUTH_KEY);
304
305 if (!hash_equals($expectedSignature, $signature)) {
306 return new \WP_Error('invalid_token', __('Invalid verification token. Please try again', 'fluent-community'));
307 }
308
309 $data = json_decode(base64_decode($data), true);
310 if ($data['expires'] < time()) {
311 return new \WP_Error('expired_token', __('Verification token has expired. Please try again.', 'fluent-community'));
312 }
313
314 if ($data['email'] !== $formData['email']) {
315 return new \WP_Error('invalid_email', __('Invalid email address. Please try again', 'fluent-community'));
316 }
317
318 if (!wp_check_password($code, $data['code_hash'])) {
319 return new \WP_Error('invalid_code', __('Invalid verification code. Please try again', 'fluent-community'));
320 }
321
322 return true;
323 }
324
325 public static function isAuthRateLimit()
326 {
327 if (apply_filters('fluent_community/auth/disable_rate_limit', false)) {
328 return true;
329 }
330
331 $transientKey = 'fluent_com_rate_limit_' . md5(Helper::getIp());
332 $rateLimit = get_transient($transientKey);
333
334 if (!$rateLimit) {
335 $rateLimit = 0;
336 }
337
338 if ($rateLimit >= 10) {
339 return new \WP_Error('rate_limit', __('Too many requests. Please try again later', 'fluent-community'));
340 }
341
342 $rateLimit = $rateLimit + 1;
343 set_transient($transientKey, $rateLimit, 300); // per 5 minutes
344 return true;
345 }
346 }
347