PluginProbe
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent / 3.4.3
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent v3.4.3
3.5.4 3.5.3 3.5.2 3.5.1 3.4.9 3.5.0 3.4.8 3.4.7 trunk 2.3.1 3.3.6 3.3.7 3.3.8 3.3.9 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6
supportcandy / includes / class-wpsc-current-user.php

class-wpsc-current-user.php in SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent 3.4.3, at includes/class-wpsc-current-user.php

1,111 lines 33.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 exit; // Exit if accessed directly!
4 }
5
6 if ( ! class_exists( 'WPSC_Current_User' ) ) :
7
8 final class WPSC_Current_User {
9
10 /**
11 * Current user object to access
12 *
13 * @var WPSC_Current_User
14 */
15 public static $current_user;
16
17 /**
18 * Login type
19 *
20 * @var string
21 */
22 public static $login_type = '';
23
24 /**
25 * Guest login type
26 *
27 * @var string
28 */
29 public static $guest_login_type = '';
30
31 /**
32 * Current user WP object
33 *
34 * @var WP_User
35 */
36 public $user;
37
38 /**
39 * Check whether user is guest
40 *
41 * @var boolean
42 */
43 public $is_guest = false;
44
45 /**
46 * Check whether user is customer or not
47 *
48 * @var boolean
49 */
50 public $is_customer = false;
51
52 /**
53 * Customer object for current user
54 *
55 * @var WPSC_Customer
56 */
57 public $customer;
58
59 /**
60 * Check whether user is an agent or not
61 *
62 * @var boolean
63 */
64 public $is_agent = false;
65
66 /**
67 * Agent object for current user
68 *
69 * @var WPSC_Agent
70 */
71 public $agent;
72
73 /**
74 * Current user level. e.g. customer, agent or admin
75 *
76 * @var string
77 */
78 public $level;
79
80 /**
81 * Initialize this class
82 *
83 * @return void
84 */
85 public static function init() {
86
87 add_action( 'init', array( __CLASS__, 'load_current_user' ) );
88
89 // default login.
90 add_action( 'wp_ajax_nopriv_wpsc_default_login', array( __CLASS__, 'check_user_login' ) );
91
92 // default registration.
93 add_action( 'wp_ajax_nopriv_wpsc_get_default_registration', array( __CLASS__, 'get_user_registration' ) );
94 add_action( 'wp_ajax_nopriv_wpsc_check_user_availability', array( __CLASS__, 'check_user_availability' ) );
95 add_action( 'wp_ajax_nopriv_wpsc_authenticate_registration', array( __CLASS__, 'send_registration_otp' ) );
96 add_action( 'wp_ajax_nopriv_wpsc_confirm_registration', array( __CLASS__, 'register_user' ) );
97
98 // sign-in using otp.
99 add_action( 'wp_ajax_nopriv_wpsc_get_guest_sign_in', array( __CLASS__, 'get_guest_sign_in' ) );
100 add_action( 'wp_ajax_nopriv_wpsc_authenticate_guest_login', array( __CLASS__, 'get_guest_sign_in_auth' ) );
101 add_action( 'wp_ajax_nopriv_wpsc_confirm_guest_login', array( __CLASS__, 'confirm_guest_login' ) );
102
103 // user registration email template.
104 add_filter( 'wpsc_email_notification_page_sections', array( __CLASS__, 'registration_email_template_section' ) );
105
106 // guest login email template.
107 add_filter( 'wpsc_email_notification_page_sections', array( __CLASS__, 'guest_login_email_template_section' ) );
108 }
109
110 /**
111 * Initialize the object
112 *
113 * @param string $email - email address.
114 */
115 public function __construct( $email = '' ) {
116
117 $user = $email ? get_user_by( 'email', $email ) : new WP_User();
118 if ( $user === false ) {
119 $user = new WP_User();
120 }
121 $this->user = $user;
122
123 // is guest.
124 $this->is_guest = $this->user->ID ? false : true;
125
126 // Set customer object.
127 if ( $this->user->ID ) {
128
129 $this->is_customer = true;
130 $customer = WPSC_Customer::get_by_email( $this->user->user_email );
131 if ( $customer->id ) {
132 $this->customer = $customer;
133 } else {
134 $this->customer = WPSC_Customer::insert(
135 array(
136 'user' => $this->user->ID,
137 'name' => $this->user->display_name,
138 'email' => $this->user->user_email,
139 )
140 );
141 }
142 } elseif ( $email ) {
143
144 $this->is_customer = true;
145 $this->customer = WPSC_Customer::get_by_email( $email );
146 }
147
148 // Set agent object.
149 $agent = WPSC_Agent::get_by_user_id( $this->user->ID );
150 if ( $agent->id && $agent->is_active ) {
151 $this->is_agent = true;
152 $this->agent = $agent;
153 }
154
155 // set leval.
156 if ( WPSC_Functions::is_site_admin() ) {
157 $this->level = 'admin';
158 } elseif ( $this->is_agent ) {
159 $this->level = 'agent';
160 } elseif ( $this->is_customer ) {
161 $this->level = 'customer';
162 } else {
163 $this->level = 'none';
164 }
165 }
166
167 /**
168 * Load current wpsc user
169 *
170 * @return void
171 */
172 public static function load_current_user() {
173
174 global $current_user;
175
176 // wp logged-in user.
177 $email = $current_user && $current_user->ID ? $current_user->user_email : '';
178 if ( $email ) {
179 self::$current_user = new WPSC_Current_User( $email );
180 self::$login_type = 'registered';
181 return;
182 }
183
184 // guest login.
185 $gs = get_option( 'wpsc-gs-general' );
186
187 $login_auth = isset( $_COOKIE['wpsc_guest_login_auth'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['wpsc_guest_login_auth'] ) ) : '';
188 $login_auth = $login_auth ? json_decode( $login_auth ) : false;
189
190 if ( ! $login_auth ) {
191 self::$current_user = new WPSC_Current_User();
192 return;
193 }
194
195 $login_auth->email = $login_auth->email ? sanitize_email( $login_auth->email ) : '';
196 if ( ! $login_auth->email ) {
197 self::$current_user = new WPSC_Current_User();
198 return;
199 }
200
201 if ( $login_auth && self::validate_guest_login( $login_auth ) ) {
202 self::$current_user = new WPSC_Current_User( $login_auth->email );
203 return;
204 }
205
206 self::$current_user = new WPSC_Current_User();
207 }
208
209 /**
210 * Change current user
211 *
212 * @param string $email - email string.
213 *
214 * @return string
215 */
216 public static function change_current_user( $email ) {
217
218 $current_user = new WPSC_Current_User( $email );
219 self::$current_user = $current_user;
220 return self::$current_user;
221 }
222
223 /**
224 * Return ticket list filters for the user.
225 *
226 * @return array
227 */
228 public function get_tl_filters() {
229
230 $filters = array(
231 'default' => array(),
232 'saved' => array(),
233 );
234
235 // default filters.
236 $default_filters = get_option( $this->is_agent ? 'wpsc-atl-default-filters' : 'wpsc-ctl-default-filters' );
237 foreach ( $default_filters as $index => $filter ) {
238
239 // exclude if filter is not enabled.
240 if ( ! $filter['is_enable'] ) {
241 continue;
242 }
243
244 $filters['default'][ $index ] = $filter;
245 }
246
247 // saved filters.
248 $filters['saved'] = $this->get_saved_filters();
249
250 // return filters.
251 return $filters;
252 }
253
254 /**
255 * Return all saved filters for current user
256 *
257 * @return array
258 */
259 public function get_saved_filters() {
260
261 $saved_filters = ! $this->is_guest && $this->user->ID ? get_user_meta( $this->user->ID, get_current_blog_id() . '-wpsc-tl-saved-filters', true ) : array();
262 return $saved_filters ? $saved_filters : array();
263 }
264
265 /**
266 * Return attachment auth for URLs created in rest api
267 *
268 * @return string
269 */
270 public function get_attachment_auth() {
271
272 $now = new DateTime();
273 $diff = new DateInterval( 'PT1H' );
274
275 $auth = get_user_meta( $this->user->ID, get_current_blog_id() . '-wpsc-rest-attachment-auth', true );
276 if ( $auth ) {
277 $dt = new DateTime( $auth['date'] );
278 if ( $now < $dt->add( $diff ) ) {
279 return $auth['key'];
280 }
281 }
282
283 $auth = array(
284 'key' => WPSC_Functions::get_random_string( 12 ),
285 'date' => $now->format( 'Y-m-d H:i:s' ),
286 );
287 update_user_meta( $this->user->ID, get_current_blog_id() . '-wpsc-rest-attachment-auth', $auth );
288 return $auth['key'];
289 }
290
291 /**
292 * Get ticket list items
293 *
294 * @return array
295 */
296 public function get_tl_list_items() {
297
298 return $this->is_agent ? get_option( 'wpsc-atl-list-items' ) : get_option( 'wpsc-ctl-list-items' );
299 }
300
301 /**
302 * Get default orderby
303 *
304 * @return array
305 */
306 public function get_tl_default_settings() {
307
308 return $this->is_agent ? get_option( 'wpsc-tl-ms-agent-view' ) : get_option( 'wpsc-tl-ms-customer-view' );
309 }
310
311 /**
312 * Return system query for the current user for ticket list
313 *
314 * @param array $filters - filters.
315 * @return array
316 */
317 public function get_tl_system_query( $filters ) {
318
319 $current_user = self::$current_user;
320
321 $adv_setting = get_option( 'wpsc-ms-advanced-settings' );
322 if ( $adv_setting['public-mode'] && ! $current_user->is_agent ) {
323 return $filters;
324 }
325
326 $system_query = array( 'relation' => 'OR' );
327
328 $system_query[] = array(
329 'slug' => 'customer',
330 'compare' => '=',
331 'val' => $this->customer->id,
332 );
333
334 if ( $this->is_agent ) {
335
336 if ( $this->agent->has_cap( 'view-assigned-me' ) ) {
337 $system_query[] = array(
338 'slug' => 'assigned_agent',
339 'compare' => '=',
340 'val' => $this->agent->id,
341 );
342 }
343
344 if ( $this->agent->has_cap( 'view-unassigned' ) ) {
345 $system_query[] = array(
346 'slug' => 'assigned_agent',
347 'compare' => '=',
348 'val' => '',
349 );
350 }
351
352 if ( $this->agent->has_cap( 'view-assigned-others' ) ) {
353 $system_query[] = array(
354 'slug' => 'assigned_agent',
355 'compare' => 'NOT IN',
356 'val' => array( $this->agent->id, '' ),
357 );
358 }
359 }
360
361 return apply_filters( 'wpsc_tl_current_user_system_query', $system_query, $filters, $this );
362 }
363
364 /**
365 * Return system query for the current user for ticket list
366 *
367 * @param array $filters - filters.
368 * @return array
369 */
370 public function get_atl_system_query( $filters ) {
371
372 $system_query = array( 'relation' => 'OR' );
373
374 $system_query[] = array(
375 'slug' => 'customer',
376 'compare' => '=',
377 'val' => $this->customer->id,
378 );
379
380 if ( $this->is_agent ) {
381
382 if ( $this->agent->has_cap( 'at-assigned-me' ) ) {
383 $system_query[] = array(
384 'slug' => 'assigned_agent',
385 'compare' => '=',
386 'val' => $this->agent->id,
387 );
388 }
389
390 if ( $this->agent->has_cap( 'at-unassigned' ) ) {
391 $system_query[] = array(
392 'slug' => 'assigned_agent',
393 'compare' => '=',
394 'val' => '',
395 );
396 }
397
398 if ( $this->agent->has_cap( 'at-assigned-others' ) ) {
399 $system_query[] = array(
400 'slug' => 'assigned_agent',
401 'compare' => 'NOT IN',
402 'val' => array( $this->agent->id, '' ),
403 );
404 }
405 }
406
407 return apply_filters( 'wpsc_atl_current_user_system_query', $system_query, $filters, $this );
408 }
409
410 /**
411 * Check login for default login form
412 *
413 * @return void
414 */
415 public static function check_user_login() {
416
417 if ( check_ajax_referer( 'wpsc_default_login', '_ajax_nonce', false ) != 1 ) {
418 wp_send_json_error( 'Unauthorised request!', 401 );
419 }
420
421 WPSC_MS_Recaptcha::validate( 'submit_login' );
422
423 $username = isset( $_POST['username'] ) ? sanitize_text_field( wp_unslash( $_POST['username'] ) ) : '';
424 if ( ! $username ) {
425 wp_send_json_error( 'Bad request', 400 );
426 }
427
428 $password = isset( $_POST['password'] ) ? $_POST['password'] : ''; // phpcs:ignore
429 if ( ! $password ) {
430 wp_send_json_error( 'Bad request', 400 );
431 }
432
433 $remember_me = isset( $_POST['remember_me'] ) ? true : false;
434
435 $user = wp_signon(
436 array(
437 'user_login' => $username,
438 'user_password' => $password,
439 'remember' => $remember_me,
440 )
441 );
442
443 $success = is_wp_error( $user ) ? 0 : 1;
444 wp_send_json( array( 'success' => $success ) );
445 }
446
447 /**
448 * Get user registration
449 *
450 * @return void
451 */
452 public static function get_user_registration() {
453
454 $page_settings = get_option( 'wpsc-gs-page-settings' );
455 $recaptcha = get_option( 'wpsc-recaptcha-settings' );
456 $tc = get_option( 'wpsc-term-and-conditions' );
457 $gdpr = get_option( 'wpsc-gdpr-settings' );
458 if ( $page_settings['user-registration'] !== 'default' ) {
459 wp_send_json_error( __( 'Unauthorized', 'supportcandy' ), 401 );
460 }?>
461
462 <h2><?php esc_attr_e( 'Please sign up', 'supportcandy' ); ?></h2>
463 <form onsubmit="return false;" class="wpsc-login wpsc-authenticate-registration">
464 <input type="text" name="firstname" placeholder="<?php esc_attr_e( 'First Name', 'supportcandy' ); ?>" autocomplete="off"/>
465 <input type="text" name="lastname" placeholder="<?php esc_attr_e( 'Last Name', 'supportcandy' ); ?>" autocomplete="off"/>
466
467 <div style="margin: 0 0 5px !important;">
468 <input id="wpsc-username" type="text" name="username" style="margin-bottom: 0px !important;" placeholder="<?php esc_attr_e( 'Username', 'supportcandy' ); ?>" autocomplete="off"/>
469 <small id="wpsc-username-unavailable" style="color: #e84118;font-style:italic;display:none;"><?php esc_attr_e( 'Username is already taken!', 'supportcandy' ); ?></small>
470 <small id="wpsc-username-available" style="color: #4cd137;font-style:italic;display:none;"><?php esc_attr_e( 'Username is available!', 'supportcandy' ); ?></small>
471 <script>
472 jQuery('#wpsc-username').change(function(){
473 jQuery('#wpsc-username-available').hide();
474 jQuery('#wpsc-username-unavailable').hide();
475 var username = jQuery(this).val().trim();
476 const data = { action: 'wpsc_check_user_availability', type : 'username', username, _ajax_nonce: '<?php echo esc_attr( wp_create_nonce( 'wpsc_check_user_availability' ) ); ?>' };
477 jQuery.post(supportcandy.ajax_url, data, function (response) {
478 jQuery('input[name=is_username]').val(response.isAvailable);
479 if (response.isAvailable == 1) {
480 jQuery('#wpsc-username-unavailable').hide();
481 jQuery('#wpsc-username-available').show();
482 } else {
483 jQuery('#wpsc-username-available').hide();
484 jQuery('#wpsc-username-unavailable').show();
485 }
486 });
487 });
488 </script>
489 </div>
490
491 <div style="margin: 0 0 5px !important;">
492 <input id="wpsc-email" type="text" name="email_address" style="margin-bottom: 0px !important;" placeholder="<?php esc_attr_e( 'Email Address', 'supportcandy' ); ?>" autocomplete="off"/>
493 <small id="wpsc-email-unavailable" style="color: #e84118;font-style:italic;display:none;"><?php esc_attr_e( 'Email is already taken!', 'supportcandy' ); ?></small>
494 <small id="wpsc-email-available" style="color: #4cd137;font-style:italic;display:none;"><?php esc_attr_e( 'Email is available!', 'supportcandy' ); ?></small>
495 <script>
496 jQuery('#wpsc-email').change(function(){
497 console.log('email changed');
498 jQuery('#wpsc-email-available').hide();
499 jQuery('#wpsc-email-unavailable').hide();
500 var email = jQuery(this).val().trim();
501 const data = { action: 'wpsc_check_user_availability', type: 'email', email, _ajax_nonce: '<?php echo esc_attr( wp_create_nonce( 'wpsc_check_user_availability' ) ); ?>' };
502 jQuery.post(supportcandy.ajax_url, data, function (response) {
503 jQuery('input[name=is_email]').val(response.isAvailable);
504 if (response.isAvailable == 1) {
505 jQuery('#wpsc-email-unavailable').hide();
506 jQuery('#wpsc-email-available').show();
507 } else {
508 jQuery('#wpsc-email-available').hide();
509 jQuery('#wpsc-email-unavailable').show();
510 }
511 });
512 });
513 </script>
514 </div>
515 <input type="password" name="password" placeholder="<?php esc_attr_e( 'Password', 'supportcandy' ); ?>"/>
516 <input type="password" name="confirm_password" placeholder="<?php esc_attr_e( 'Confirm Password', 'supportcandy' ); ?>"/>
517 <?php
518
519 // recaptcha.
520 if ( $recaptcha['allow-recaptcha'] === 1 && $recaptcha['recaptcha-version'] == 2 && $recaptcha['recaptcha-site-key'] && $recaptcha['recaptcha-secret-key'] ) {
521 $unique_id = uniqid( 'wpsc_' );
522 ?>
523 <script src="https://www.google.com/recaptcha/api.js?onload=recaptchaCallback&render=explicit" async defer></script> <?php // phpcs:ignore ?>
524 <div id="<?php echo esc_attr( $unique_id ); ?>" data-sitekey="" style="margin-bottom: 5px;"></div>
525 <script>
526 var recaptchaCallback = function() {
527 var obj = jQuery('#<?php echo esc_attr( $unique_id ); ?>');
528 grecaptcha.render(obj.attr("id"), {
529 "sitekey" : "<?php echo esc_attr( $recaptcha['recaptcha-site-key'] ); ?>",
530 "callback" : function(token) {
531 obj.closest('form').find(".g-recaptcha-response").val(token);
532 }
533 });
534 }
535 </script>
536 <?php
537 }
538 if ( $recaptcha['allow-recaptcha'] === 1 && $recaptcha['recaptcha-version'] == 3 && $recaptcha['recaptcha-site-key'] && $recaptcha['recaptcha-secret-key'] ) {
539 ?>
540 <script src="https://www.google.com/recaptcha/api.js?render=<?php echo esc_attr( $recaptcha['recaptcha-site-key'] ); ?>"></script> <?php // phpcs:ignore ?>
541 <?php
542 }
543 do_action( 'wpsc_registration_form' );
544 ?>
545 <div class="wpsc-reg-user">
546 <?php
547 if ( $tc['allow-term-and-conditions-reg-user'] ) :
548 ?>
549 <div class="wpsc-tff term-and-conditions wpsc-xs-12 wpsc-sm-12 wpsc-md-12 wpsc-lg-12 required wpsc-visible" data-cft="term-and-conditions-reg-user">
550 <div class="checkbox-container">
551 <?php $unique_id = uniqid( 'wpsc_' ); ?>
552 <input name="wpsc-tandc-reg-user" id="<?php echo esc_attr( $unique_id ); ?>" type="checkbox" value="1"/>
553 <?php
554 $name = WPSC_Translations::get( 'wpsc-term-and-conditions-reg-user', stripslashes( $tc['tandc-text-reg-user'] ) );
555 ?>
556 <label for="<?php echo esc_attr( $unique_id ); ?>"><?php echo wp_kses_post( $name ); ?></label>
557 </div>
558 </div>
559 <?php
560 endif;
561
562 if ( $gdpr['allow-gdpr-reg-user'] ) {
563 ?>
564 <div class="wpsc-tff wpsc-gdpr wpsc-xs-12 wpsc-sm-12 wpsc-md-12 wpsc-lg-12 required wpsc-visible" data-cft="gdpr-reg-user">
565 <div class="checkbox-container">
566 <?php $unique_id = uniqid( 'wpsc_' ); ?>
567 <input name="wpsc-gdpr-reg-user" id="<?php echo esc_attr( $unique_id ); ?>" type="checkbox" value="1"/>
568 <?php
569 $name = WPSC_Translations::get( 'wpsc-gdpr-reg-user', stripslashes( $gdpr['gdpr-text-reg-user'] ) );
570 ?>
571 <label for="<?php echo esc_attr( $unique_id ); ?>"><?php echo wp_kses_post( $name ); ?></label>
572 </div>
573 </div>
574 <?php
575 }
576 ?>
577 <div>
578
579 <button class="wpsc-button normal primary" onclick="wpsc_set_default_registration(this)"><?php esc_attr_e( 'Sign Up', 'supportcandy' ); ?></button>
580 <button class="wpsc-button normal secondary" onclick="window.location.reload();"><?php esc_attr_e( 'Cancel', 'supportcandy' ); ?></button>
581 <input type="hidden" name="action" value="wpsc_authenticate_registration"/>
582 <input type="hidden" name="is_username" value="0"/>
583 <input type="hidden" name="is_email" value="0"/>
584 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_authenticate_registration' ) ); ?>">
585 </form>
586 <?php
587 wp_die();
588 }
589
590 /**
591 * Check username availability
592 *
593 * @return void
594 */
595 public static function check_user_availability() {
596
597 if ( check_ajax_referer( 'wpsc_check_user_availability', '_ajax_nonce', false ) != 1 ) {
598 wp_send_json_error( 'Unauthorised request!', 401 );
599 }
600
601 $page_settings = get_option( 'wpsc-gs-page-settings' );
602 if ( $page_settings['user-registration'] !== 'default' ) {
603 wp_send_json_error( __( 'Unauthorized', 'supportcandy' ), 401 );
604 }
605
606 $type = isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : '';
607 if ( in_array( $type, array( 'username', 'email' ) ) === false ) {
608 wp_send_json_error( 'Something went wrong', 400 );
609 }
610
611 if ( $type === 'username' ) {
612 $username = isset( $_POST['username'] ) ? sanitize_user( wp_unslash( $_POST['username'] ) ) : '';
613 if ( ! $username ) {
614 wp_send_json_error( 'Something went wrong', 400 );
615 }
616 } elseif ( $type === 'email' ) {
617 $email = isset( $_POST['email'] ) && filter_var( wp_unslash( $_POST['email'] ), FILTER_VALIDATE_EMAIL ) ? sanitize_email( wp_unslash( $_POST['email'] ) ) : '';
618 if ( ! $email ) {
619 wp_send_json_error( 'Something went wrong', 400 );
620 }
621 }
622 $flag = $type === 'username' ? self::is_username_available( $username ) : self::is_email_available( $email );
623
624 wp_send_json( array( 'isAvailable' => $flag ? 0 : 1 ) );
625 }
626
627 /**
628 * Send registration OTP for email authentication
629 *
630 * @return void
631 */
632 public static function send_registration_otp() {
633
634 if ( check_ajax_referer( 'wpsc_authenticate_registration', '_ajax_nonce', false ) != 1 ) {
635 wp_send_json_error( 'Unauthorised request!', 401 );
636 }
637 $page_settings = get_option( 'wpsc-gs-page-settings' );
638 if ( $page_settings['user-registration'] !== 'default' ) {
639 wp_send_json_error( __( 'Unauthorized', 'supportcandy' ), 401 );
640 }
641
642 WPSC_MS_Recaptcha::validate( 'submit_registration' );
643
644 $firstname = isset( $_POST['firstname'] ) ? sanitize_text_field( wp_unslash( $_POST['firstname'] ) ) : '';
645 if ( ! $firstname ) {
646 wp_send_json_error( 'Bad request', 400 );
647 }
648
649 $lastname = isset( $_POST['lastname'] ) ? sanitize_text_field( wp_unslash( $_POST['lastname'] ) ) : '';
650 if ( ! $lastname ) {
651 wp_send_json_error( 'Bad request', 400 );
652 }
653
654 $username = isset( $_POST['username'] ) ? sanitize_user( wp_unslash( $_POST['username'] ) ) : '';
655 if ( ! $username ) {
656 wp_send_json_error( 'Bad request', 400 );
657 }
658
659 if ( self::is_username_available( $username ) ) {
660 wp_send_json_error( 'Bad request', 400 );
661 }
662
663 $email_address = isset( $_POST['email_address'] ) && filter_var( wp_unslash( $_POST['email_address'] ), FILTER_VALIDATE_EMAIL ) ? sanitize_email( wp_unslash( $_POST['email_address'] ) ) : '';
664 if ( ! $email_address ) {
665 wp_send_json_error( 'Bad request', 400 );
666 }
667
668 if ( self::is_email_available( $email_address ) ) {
669 wp_send_json_error( 'Bad request', 400 );
670 }
671
672 $password = isset( $_POST['password'] ) ? wp_unslash( $_POST['password'] ) : ''; // phpcs:ignore
673 if ( ! $password ) {
674 wp_send_json_error( 'Bad request', 400 );
675 }
676
677 $data = array(
678 'firstname' => $firstname,
679 'lastname' => $lastname,
680 'username' => $username,
681 'email_address' => $email_address,
682 'password' => $password,
683 );
684
685 $data = apply_filters( 'wpsc_register_user_data', $data );
686
687 $otp = WPSC_Email_OTP::insert(
688 array(
689 'email' => $email_address,
690 'date_expiry' => ( new DateTime() )->add( new DateInterval( 'PT1H' ) )->format( 'Y-m-d H:i:s' ),
691 'data' => wp_json_encode( $data ),
692 )
693 );
694
695 // send email notification.
696 WPSC_EN_User_Reg_OTP::send_otp( $otp );
697 ?>
698
699 <h2><?php esc_attr_e( 'Please sign up', 'supportcandy' ); ?></h2>
700 <small style="margin: 0 0 5px;"><?php esc_attr_e( 'We have sent a one-time verification code to your email address.', 'supportcandy' ); ?></small>
701 <form onsubmit="return false;" class="wpsc-login wpsc-confirm-registration">
702 <input type="text" name="otp" autocomplete="off"/>
703 <button class="wpsc-button normal primary" onclick="wpsc_confirm_registration(this)"><?php esc_attr_e( 'Submit', 'supportcandy' ); ?></button>
704 <input type="hidden" name="action" value="wpsc_confirm_registration"/>
705 <input type="hidden" name="otp_id" value="<?php echo esc_attr( $otp->id ); ?>">
706 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_confirm_registration' ) ); ?>"/>
707 </form>
708 <?php
709 wp_die();
710 }
711
712 /**
713 * Checks whether username is available or not
714 *
715 * @param string $username - user name string.
716 * @return boolean
717 */
718 public static function is_username_available( $username ) {
719
720 $user = get_user_by( 'login', $username );
721 return $user ? true : false;
722 }
723
724 /**
725 * Checks whether email is available or not
726 *
727 * @param string $email - email string.
728 * @return boolean
729 */
730 public static function is_email_available( $email ) {
731
732 $user = get_user_by( 'email', $email );
733 return $user ? true : false;
734 }
735
736 /**
737 * Register user after OTP matched
738 *
739 * @return void
740 */
741 public static function register_user() {
742
743 if ( check_ajax_referer( 'wpsc_confirm_registration', '_ajax_nonce', false ) != 1 ) {
744 wp_send_json_error( 'Unauthorised request!', 401 );
745 }
746
747 $page_settings = get_option( 'wpsc-gs-page-settings' );
748 if ( $page_settings['user-registration'] !== 'default' ) {
749 wp_send_json_error( __( 'Unauthorized', 'supportcandy' ), 401 );
750 }
751
752 $verification_otp = isset( $_POST['otp'] ) ? sanitize_text_field( wp_unslash( $_POST['otp'] ) ) : '';
753 if ( ! $verification_otp ) {
754 wp_send_json_error( 'Bad request', 400 );
755 }
756
757 $id = isset( $_POST['otp_id'] ) ? intval( $_POST['otp_id'] ) : '';
758 if ( ! $id ) {
759 wp_send_json_error( 'Bad request', 400 );
760 }
761
762 $otp = new WPSC_Email_OTP( $id );
763 if ( ! $otp->id ) {
764 wp_send_json_error( 'Bad request', 400 );
765 }
766
767 if ( ! $otp->is_valid( $verification_otp ) ) {
768 wp_send_json( array( 'isSuccess' => 0 ) );
769 wp_die();
770 }
771
772 $data = json_decode( $otp->data );
773
774 // insert user.
775 $display_name = $data->firstname . ' ' . $data->lastname;
776 $user_id = wp_insert_user(
777 array(
778 'user_login' => $data->username,
779 'user_pass' => $data->password,
780 'user_email' => $data->email_address,
781 'first_name' => $data->firstname,
782 'last_name' => $data->lastname,
783 'display_name' => $display_name,
784 'role' => 'subscriber',
785 )
786 );
787 if ( is_wp_error( $user_id ) ) {
788 wp_send_json( array( 'isSuccess' => 0 ) );
789 wp_die();
790 }
791
792 $user = wp_signon(
793 array(
794 'user_login' => $data->username,
795 'user_password' => $data->password,
796 )
797 );
798 wp_new_user_notification( $user_id, null, 'admin' );
799 do_action( 'wpsc_after_user_registration', $user, $data );
800 wp_send_json( array( 'isSuccess' => 1 ) );
801 }
802
803 /**
804 * User registrstion OTP email template section
805 *
806 * @param array $sections - section name.
807 * @return array
808 */
809 public static function registration_email_template_section( $sections ) {
810
811 $sections['registration-otp'] = array(
812 'slug' => 'registration_otp',
813 'icon' => 'unlock',
814 'label' => esc_attr__( 'User Registration OTP', 'supportcandy' ),
815 'callback' => 'wpsc_get_en_user_reg_otp',
816 );
817 return $sections;
818 }
819
820 /**
821 * Get guest sign in screen
822 *
823 * @return void
824 */
825 public static function get_guest_sign_in() {
826
827 $gs = get_option( 'wpsc-gs-general' );
828 $page_settings = get_option( 'wpsc-gs-page-settings' );
829 if ( ! ( $page_settings['otp-login'] && in_array( 'guest', $gs['allow-create-ticket'] ) ) ) {
830 wp_send_json_error( 'Unauthorozed', 400 );
831 }
832 ?>
833
834 <h2><?php esc_attr_e( 'Please sign in', 'supportcandy' ); ?></h2>
835 <form onsubmit="return false;" class="wpsc-login authenticate-guest-login">
836 <input type="text" name="email_address" placeholder="<?php esc_attr_e( 'Email Address', 'supportcandy' ); ?>" autocomplete="off"/>
837 <button class="wpsc-button normal primary" onclick="wpsc_authenticate_guest_login(this)"><?php esc_attr_e( 'Sign In', 'supportcandy' ); ?></button>
838 <button class="wpsc-button normal secondary" onclick="window.location.reload();"><?php esc_attr_e( 'Cancel', 'supportcandy' ); ?></button>
839 <input type="hidden" name="action" value="wpsc_authenticate_guest_login"/>
840 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_authenticate_guest_login' ) ); ?>">
841 </form>
842 <?php
843 wp_die();
844 }
845
846 /**
847 * Get OTP screen
848 *
849 * @return void
850 */
851 public static function get_guest_sign_in_auth() {
852
853 if ( check_ajax_referer( 'wpsc_authenticate_guest_login', '_ajax_nonce', false ) != 1 ) {
854 wp_send_json_error( 'Unauthorised request!', 401 );
855 }
856 $gs = get_option( 'wpsc-gs-general' );
857 $page_settings = get_option( 'wpsc-gs-page-settings' );
858 if ( ! ( $page_settings['otp-login'] && in_array( 'guest', $gs['allow-create-ticket'] ) ) ) {
859 wp_send_json_error( 'Unauthorozed', 400 );
860 }
861
862 $email_address = isset( $_POST['email_address'] ) && filter_var( wp_unslash( $_POST['email_address'] ), FILTER_VALIDATE_EMAIL ) ? sanitize_text_field( wp_unslash( $_POST['email_address'] ) ) : '';
863 if ( ! $email_address ) {
864 wp_send_json_error( 'Bad request', 400 );
865 }
866
867 $customer = WPSC_Customer::get_by_email( $email_address );
868 if ( ! $customer->id ) {
869 esc_attr_e( 'Invalid email address!', 'supportcandy' );
870 wp_die();
871 }
872
873 $otp = WPSC_Email_OTP::insert(
874 array(
875 'email' => $email_address,
876 'date_expiry' => ( new DateTime() )->add( new DateInterval( 'P1D' ) )->format( 'Y-m-d H:i:s' ),
877 'data' => wp_json_encode(
878 array(
879 'email' => $email_address,
880 )
881 ),
882 )
883 );
884
885 // Send OTP for login.
886 WPSC_EN_Guest_Login_OTP::send_otp( $otp );
887 ?>
888
889 <h2><?php esc_attr_e( 'Please sign in', 'supportcandy' ); ?></h2>
890 <small style="margin: 0 0 5px;"><?php esc_attr_e( 'We have sent a one-time verification code to your email address.', 'supportcandy' ); ?></small>
891 <form onsubmit="return false;" class="wpsc-login wpsc-confirm-guest-login">
892 <input type="text" name="otp" autocomplete="off"/>
893 <button class="wpsc-button normal primary" onclick="wpsc_confirm_guest_login(this)"><?php esc_attr_e( 'Submit', 'supportcandy' ); ?></button>
894 <input type="hidden" name="action" value="wpsc_confirm_guest_login"/>
895 <input type="hidden" name="otp_id" value="<?php echo esc_attr( $otp->id ); ?>">
896 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_confirm_guest_login' ) ); ?>">
897 </form>
898 <?php
899 wp_die();
900 }
901
902 /**
903 * Confirm guest login
904 *
905 * @return void
906 */
907 public static function confirm_guest_login() {
908
909 // Add rate limiting.
910 $ip_address = WPSC_DF_IP_Address::get_current_user_ip();
911 $attempt_key = 'wpsc_otp_attempts_' . md5( $ip_address );
912 $attempts = get_transient( $attempt_key );
913 $attempts = $attempts ? $attempts : 1;
914
915 if ( $attempts >= 5 ) {
916 wp_send_json_error( 'Too many attempts. Please try again later.', 429 );
917 }
918
919 if ( check_ajax_referer( 'wpsc_confirm_guest_login', '_ajax_nonce', false ) != 1 ) {
920 wp_send_json_error( 'Unauthorised request!', 401 );
921 }
922
923 $gs = get_option( 'wpsc-gs-general' );
924 $page_settings = get_option( 'wpsc-gs-page-settings' );
925 if ( ! ( $page_settings['otp-login'] && in_array( 'guest', $gs['allow-create-ticket'] ) ) ) {
926 wp_send_json_error( 'Unauthorozed', 400 );
927 }
928
929 $verification_otp = isset( $_POST['otp'] ) ? sanitize_text_field( wp_unslash( $_POST['otp'] ) ) : '';
930 if ( ! $verification_otp ) {
931 wp_send_json_error( 'Bad request', 400 );
932 }
933
934 $id = isset( $_POST['otp_id'] ) ? intval( $_POST['otp_id'] ) : '';
935 if ( ! $id ) {
936 wp_send_json_error( 'Bad request', 400 );
937 }
938
939 $otp = new WPSC_Email_OTP( $id );
940 if ( ! $otp->id ) {
941 wp_send_json_error( 'Bad request', 400 );
942 }
943
944 if ( ! $otp->is_valid( $verification_otp ) ) {
945
946 // Increment attempt counter.
947 ++$attempts;
948 set_transient( $attempt_key, $attempts, 300 ); // 5 minute lockout.
949
950 // Add per-OTP attempt tracking.
951 $otp_attempt_key = 'wpsc_otp_' . $id . '_attempts';
952 $otp_attempts = get_transient( $otp_attempt_key );
953 $otp_attempts = $otp_attempts ? $otp_attempts + 1 : 1;
954 set_transient( $otp_attempt_key, $otp_attempts, 600 );
955
956 if ( $otp_attempts >= 3 ) {
957 WPSC_Email_OTP::destroy( $otp );
958 wp_send_json_error( 'OTP has been invalidated due to too many failed attempts', 403 );
959 }
960
961 wp_send_json( array( 'isSuccess' => 0 ) );
962 wp_die();
963 }
964
965 $data = json_decode( $otp->data, true );
966 $data['auth_token'] = WPSC_Functions::get_random_string( 100 );
967 $data['auth_type'] = 'login';
968 $otp->data = wp_json_encode( $data );
969 $otp->save();
970
971 // Clear rate limiting on success.
972 delete_transient( $attempt_key );
973
974 // add customer record if not set.
975 $customer = WPSC_Customer::get_by_email( $data['email'] );
976 if ( ! $customer->id ) {
977 $user = get_user_by( 'email', $data['email'] );
978 if ( $user ) {
979
980 WPSC_Customer::insert(
981 array(
982 'user' => $user->ID,
983 'name' => $user->display_name,
984 'email' => $user->user_email,
985 )
986 );
987
988 } else {
989
990 WPSC_Customer::insert(
991 array(
992 'user' => 0,
993 'name' => $data['name'],
994 'email' => $data['email'],
995 )
996 );
997 }
998 }
999
1000 $auth = array(
1001 'email' => $otp->email,
1002 'token' => $data['auth_token'],
1003 );
1004
1005 setcookie( 'wpsc_guest_login_auth', wp_json_encode( $auth ), $otp->date_expiry->getTimestamp(), '/' );
1006
1007 wp_send_json( array( 'isSuccess' => 1 ) );
1008 }
1009
1010 /**
1011 * Validate login auth token
1012 *
1013 * @param object $login_auth - login auth details.
1014 * @return boolean
1015 */
1016 public static function validate_guest_login( $login_auth ) {
1017
1018 $gs = get_option( 'wpsc-gs-general' );
1019 $page_settings = get_option( 'wpsc-gs-page-settings' );
1020
1021 $results = WPSC_Email_OTP::find(
1022 array(
1023 'meta_query' => array(
1024 'relation' => 'AND',
1025 array(
1026 'slug' => 'email',
1027 'compare' => '=',
1028 'val' => $login_auth->email,
1029 ),
1030 ),
1031 )
1032 )['results'];
1033
1034 if ( ! $results ) {
1035 return false;
1036 }
1037
1038 $otp = $results[0];
1039 if ( ! $otp->id ) {
1040 return false;
1041 }
1042
1043 $now = new DateTime();
1044 $data = json_decode( $otp->data );
1045
1046 if (
1047 isset( $data->auth_type ) &&
1048 ( ( $data->auth_type == 'login' && $page_settings['otp-login'] && in_array( 'guest', $gs['allow-create-ticket'] ) ) || $data->auth_type == 'open-ticket' ) &&
1049 ( $otp->date_expiry > $now && $data->auth_token == $login_auth->token )
1050 ) {
1051 self::$login_type = 'guest';
1052 self::$guest_login_type = $data->auth_type;
1053 return true;
1054 }
1055
1056 return false;
1057 }
1058
1059 /**
1060 * Add guest login email template
1061 *
1062 * @param array $sections - section name.
1063 * @return array
1064 */
1065 public static function guest_login_email_template_section( $sections ) {
1066
1067 $sections['guest-login-otp'] = array(
1068 'slug' => 'guest_login_otp',
1069 'icon' => 'unlock',
1070 'label' => esc_attr__( 'Guest Login OTP', 'supportcandy' ),
1071 'callback' => 'wpsc_get_en_guest_login_otp',
1072 );
1073 return $sections;
1074 }
1075
1076 /**
1077 * Logout current user
1078 *
1079 * @return void
1080 */
1081 public function logout() {
1082
1083 global $current_user;
1084
1085 $otp = WPSC_Email_OTP::find(
1086 array(
1087 'meta_query' => array(
1088 'relation' => 'AND',
1089 array(
1090 'slug' => 'email',
1091 'compare' => '=',
1092 'val' => $this->customer->email,
1093 ),
1094 ),
1095 )
1096 )['results'];
1097
1098 if ( $otp ) :
1099 WPSC_Email_OTP::destroy( $otp[0] );
1100 @setcookie( 'wpsc_guest_login_auth', '', time(), '/' ); //phpcs:ignore
1101 endif;
1102
1103 if ( $current_user->ID ) {
1104 wp_logout();
1105 }
1106 }
1107 }
1108 endif;
1109
1110 WPSC_Current_User::init();
1111