PluginProbe
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent / 3.5.1
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent v3.5.1
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.5.1, at includes/class-wpsc-current-user.php

1,251 lines 37.0 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 * Return customer object by WordPress user ID.
169 *
170 * @param int $user_id - WordPress user ID.
171 * @return WPSC_Customer
172 */
173 public static function get_customer_by_user_id( $user_id ) {
174
175 $user_id = absint( $user_id );
176 if ( ! $user_id ) {
177 return new WPSC_Customer();
178 }
179
180 return WPSC_Customer::get_by_user_id( $user_id );
181 }
182
183 /**
184 * Load current wpsc user
185 *
186 * @return void
187 */
188 public static function load_current_user() {
189
190 global $current_user;
191
192 // wp logged-in user.
193 $email = $current_user && $current_user->ID ? $current_user->user_email : '';
194 if ( $email ) {
195 self::$current_user = new WPSC_Current_User( $email );
196 self::$login_type = 'registered';
197 return;
198 }
199
200 // guest login.
201 $gs = get_option( 'wpsc-gs-general' );
202
203 $login_auth = isset( $_COOKIE['wpsc_guest_login_auth'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['wpsc_guest_login_auth'] ) ) : '';
204 $login_auth = $login_auth ? json_decode( $login_auth ) : false;
205
206 if ( ! $login_auth ) {
207 self::$current_user = new WPSC_Current_User();
208 return;
209 }
210
211 $login_auth->email = $login_auth->email ? sanitize_email( $login_auth->email ) : '';
212 if ( ! $login_auth->email ) {
213 self::$current_user = new WPSC_Current_User();
214 return;
215 }
216
217 if ( $login_auth && self::validate_guest_login( $login_auth ) ) {
218 self::$current_user = new WPSC_Current_User( $login_auth->email );
219 return;
220 }
221
222 self::$current_user = new WPSC_Current_User();
223 }
224
225 /**
226 * Change current user
227 *
228 * @param string $email - email string.
229 *
230 * @return string
231 */
232 public static function change_current_user( $email ) {
233
234 $current_user = new WPSC_Current_User( $email );
235 self::$current_user = $current_user;
236 return self::$current_user;
237 }
238
239 /**
240 * Return ticket list filters for the user.
241 *
242 * @return array
243 */
244 public function get_tl_filters() {
245
246 $filters = array(
247 'default' => array(),
248 'saved' => array(),
249 );
250
251 // default filters.
252 $default_filters = get_option( $this->is_agent ? 'wpsc-atl-default-filters' : 'wpsc-ctl-default-filters' );
253 foreach ( $default_filters as $index => $filter ) {
254
255 // exclude if current user does not have access to deleted filter.
256 if ( $index === 'deleted' && ! $this->agent->has_cap( 'dtt-access' ) ) {
257 continue;
258 }
259
260 // exclude if filter is not enabled.
261 if ( ! $filter['is_enable'] ) {
262 continue;
263 }
264
265 $filters['default'][ $index ] = $filter;
266 }
267
268 // saved filters.
269 $filters['saved'] = $this->get_saved_filters();
270
271 // return filters.
272 return $filters;
273 }
274
275 /**
276 * Return all saved filters for current user
277 *
278 * @return array
279 */
280 public function get_saved_filters() {
281
282 $saved_filters = ! $this->is_guest && $this->user->ID ? get_user_meta( $this->user->ID, get_current_blog_id() . '-wpsc-tl-saved-filters', true ) : array();
283 return $saved_filters ? $saved_filters : array();
284 }
285
286 /**
287 * Return attachment auth for URLs created in rest api
288 *
289 * @return string
290 */
291 public function get_attachment_auth() {
292
293 $now = new DateTime();
294 $diff = new DateInterval( 'PT1H' );
295
296 $auth = get_user_meta( $this->user->ID, get_current_blog_id() . '-wpsc-rest-attachment-auth', true );
297 if ( $auth ) {
298 $dt = new DateTime( $auth['date'] );
299 if ( $now < $dt->add( $diff ) ) {
300 return $auth['key'];
301 }
302 }
303
304 $auth = array(
305 'key' => WPSC_Functions::get_random_string( 12 ),
306 'date' => $now->format( 'Y-m-d H:i:s' ),
307 );
308 update_user_meta( $this->user->ID, get_current_blog_id() . '-wpsc-rest-attachment-auth', $auth );
309 return $auth['key'];
310 }
311
312 /**
313 * Get ticket list items
314 *
315 * @return array
316 */
317 public function get_tl_list_items() {
318
319 return $this->is_agent ? get_option( 'wpsc-atl-list-items' ) : get_option( 'wpsc-ctl-list-items' );
320 }
321
322 /**
323 * Get default orderby
324 *
325 * @return array
326 */
327 public function get_tl_default_settings() {
328
329 return $this->is_agent ? get_option( 'wpsc-tl-ms-agent-view' ) : get_option( 'wpsc-tl-ms-customer-view' );
330 }
331
332 /**
333 * Return system query for the current user for ticket list
334 *
335 * @param array $filters - filters.
336 * @return array
337 */
338 public function get_tl_system_query( $filters ) {
339
340 $current_user = self::$current_user;
341
342 $adv_setting = get_option( 'wpsc-ms-advanced-settings' );
343 if ( $adv_setting['public-mode'] && ! $current_user->is_agent ) {
344 return $filters;
345 }
346
347 $system_query = array( 'relation' => 'OR' );
348
349 $system_query[] = array(
350 'slug' => 'customer',
351 'compare' => '=',
352 'val' => $this->customer->id,
353 );
354
355 if ( $this->is_agent ) {
356
357 if ( $this->agent->has_cap( 'view-assigned-me' ) ) {
358 $system_query[] = array(
359 'slug' => 'assigned_agent',
360 'compare' => '=',
361 'val' => $this->agent->id,
362 );
363 }
364
365 if ( $this->agent->has_cap( 'view-unassigned' ) ) {
366 $system_query[] = array(
367 'slug' => 'assigned_agent',
368 'compare' => '=',
369 'val' => '',
370 );
371 }
372
373 if ( $this->agent->has_cap( 'view-assigned-others' ) ) {
374 $system_query[] = array(
375 'slug' => 'assigned_agent',
376 'compare' => 'NOT IN',
377 'val' => array( $this->agent->id, '' ),
378 );
379 }
380 }
381
382 return apply_filters( 'wpsc_tl_current_user_system_query', $system_query, $filters, $this );
383 }
384
385 /**
386 * Return system query for the current user for ticket list
387 *
388 * @param array $filters - filters.
389 * @return array
390 */
391 public function get_atl_system_query( $filters ) {
392
393 $system_query = array( 'relation' => 'OR' );
394
395 $system_query[] = array(
396 'slug' => 'customer',
397 'compare' => '=',
398 'val' => $this->customer->id,
399 );
400
401 if ( $this->is_agent ) {
402
403 if ( $this->agent->has_cap( 'at-assigned-me' ) ) {
404 $system_query[] = array(
405 'slug' => 'assigned_agent',
406 'compare' => '=',
407 'val' => $this->agent->id,
408 );
409 }
410
411 if ( $this->agent->has_cap( 'at-unassigned' ) ) {
412 $system_query[] = array(
413 'slug' => 'assigned_agent',
414 'compare' => '=',
415 'val' => '',
416 );
417 }
418
419 if ( $this->agent->has_cap( 'at-assigned-others' ) ) {
420 $system_query[] = array(
421 'slug' => 'assigned_agent',
422 'compare' => 'NOT IN',
423 'val' => array( $this->agent->id, '' ),
424 );
425 }
426 }
427
428 return apply_filters( 'wpsc_atl_current_user_system_query', $system_query, $filters, $this );
429 }
430
431 /**
432 * Check login for default login form
433 *
434 * @return void
435 */
436 public static function check_user_login() {
437
438 if ( check_ajax_referer( 'wpsc_default_login', '_ajax_nonce', false ) != 1 ) {
439 wp_send_json_error( 'Unauthorized request!', 401 );
440 }
441
442 WPSC_MS_Recaptcha::validate( 'submit_login' );
443
444 $username = isset( $_POST['username'] ) ? sanitize_text_field( wp_unslash( $_POST['username'] ) ) : '';
445 if ( ! $username ) {
446 wp_send_json_error( 'Bad request', 400 );
447 }
448
449 $password = isset( $_POST['password'] ) ? $_POST['password'] : ''; // phpcs:ignore
450 if ( ! $password ) {
451 wp_send_json_error( 'Bad request', 400 );
452 }
453
454 $remember_me = isset( $_POST['remember_me'] ) ? true : false;
455
456 $user = wp_signon(
457 array(
458 'user_login' => $username,
459 'user_password' => $password,
460 'remember' => $remember_me,
461 )
462 );
463
464 if ( is_wp_error( $user ) ) {
465
466 $auth_errors = array(
467 'incorrect_password',
468 'invalid_username',
469 'empty_username',
470 'empty_password',
471 );
472 $code = $user->get_error_code();
473 if ( in_array( $code, $auth_errors, true ) ) {
474
475 wp_send_json_error(
476 array(
477 'code' => 'invalid_login',
478 'message' => __( 'Invalid username or password.', 'supportcandy' ),
479 ),
480 401
481 );
482 }
483
484 wp_send_json_error(
485 array(
486 'code' => $code,
487 'message' => wp_strip_all_tags( $user->get_error_message() ),
488 ),
489 400
490 );
491 }
492 wp_send_json_success();
493 }
494
495 /**
496 * Get user registration
497 *
498 * @return void
499 */
500 public static function get_user_registration() {
501
502 $page_settings = get_option( 'wpsc-gs-page-settings' );
503 $recaptcha = get_option( 'wpsc-recaptcha-settings' );
504 $tc = get_option( 'wpsc-term-and-conditions' );
505 $gdpr = get_option( 'wpsc-gdpr-settings' );
506 if ( $page_settings['user-registration'] !== 'default' ) {
507 wp_send_json_error( __( 'Unauthorized', 'supportcandy' ), 401 );
508 }?>
509
510 <h2><?php esc_attr_e( 'Please sign up', 'supportcandy' ); ?></h2>
511 <form onsubmit="return false;" class="wpsc-login wpsc-authenticate-registration">
512 <input type="text" name="firstname" placeholder="<?php esc_attr_e( 'First Name', 'supportcandy' ); ?>" autocomplete="off"/>
513 <input type="text" name="lastname" placeholder="<?php esc_attr_e( 'Last Name', 'supportcandy' ); ?>" autocomplete="off"/>
514
515 <div style="margin: 0 0 5px !important;">
516 <input id="wpsc-username" type="text" name="username" style="margin-bottom: 0px !important;" placeholder="<?php esc_attr_e( 'Username', 'supportcandy' ); ?>" autocomplete="off"/>
517 <small id="wpsc-username-unavailable" style="color: #e84118;font-style:italic;display:none;"><?php esc_attr_e( 'Username is already taken!', 'supportcandy' ); ?></small>
518 <small id="wpsc-username-available" style="color: #4cd137;font-style:italic;display:none;"><?php esc_attr_e( 'Username is available!', 'supportcandy' ); ?></small>
519 <script>
520 jQuery('#wpsc-username').change(function(){
521 jQuery('#wpsc-username-available').hide();
522 jQuery('#wpsc-username-unavailable').hide();
523 var username = jQuery(this).val().trim();
524 const data = { action: 'wpsc_check_user_availability', type : 'username', username, _ajax_nonce: '<?php echo esc_attr( wp_create_nonce( 'wpsc_check_user_availability' ) ); ?>' };
525 jQuery.post(supportcandy.ajax_url, data, function (response) {
526 jQuery('input[name=is_username]').val(response.isAvailable);
527 if (response.isAvailable == 1) {
528 jQuery('#wpsc-username-unavailable').hide();
529 jQuery('#wpsc-username-available').show();
530 } else {
531 jQuery('#wpsc-username-available').hide();
532 jQuery('#wpsc-username-unavailable').show();
533 }
534 });
535 });
536 </script>
537 </div>
538
539 <div style="margin: 0 0 5px !important;">
540 <input id="wpsc-email" type="text" name="email_address" style="margin-bottom: 0px !important;" placeholder="<?php esc_attr_e( 'Email Address', 'supportcandy' ); ?>" autocomplete="off"/>
541 <small id="wpsc-email-unavailable" style="color: #e84118;font-style:italic;display:none;"><?php esc_attr_e( 'Email is already taken or not allowed!', 'supportcandy' ); ?></small>
542 <small id="wpsc-email-available" style="color: #4cd137;font-style:italic;display:none;"><?php esc_attr_e( 'Email is available!', 'supportcandy' ); ?></small>
543 <script>
544 jQuery('#wpsc-email').change(function(){
545 jQuery('#wpsc-email-available').hide();
546 jQuery('#wpsc-email-unavailable').hide();
547 var email = jQuery(this).val().trim();
548 const data = { action: 'wpsc_check_user_availability', type: 'email', email, _ajax_nonce: '<?php echo esc_attr( wp_create_nonce( 'wpsc_check_user_availability' ) ); ?>' };
549 jQuery.post(supportcandy.ajax_url, data, function (response) {
550 jQuery('input[name=is_email]').val(response.isAvailable);
551 if (response.isAvailable == 1) {
552 jQuery('#wpsc-email-unavailable').hide();
553 jQuery('#wpsc-email-available').show();
554 } else {
555 jQuery('#wpsc-email-available').hide();
556 jQuery('#wpsc-email-unavailable').show();
557 }
558 });
559 });
560 </script>
561 </div>
562 <input type="password" name="password" placeholder="<?php esc_attr_e( 'Password', 'supportcandy' ); ?>"/>
563 <input type="password" name="confirm_password" placeholder="<?php esc_attr_e( 'Confirm Password', 'supportcandy' ); ?>"/>
564 <?php
565
566 // recaptcha.
567 if ( $recaptcha['captcha-provider'] === 'google-recaptcha' && $recaptcha['recaptcha-version'] == 2 && $recaptcha['recaptcha-site-key'] && $recaptcha['recaptcha-secret-key'] ) {
568 $unique_id = uniqid( 'wpsc_' );
569 ?>
570 <script src="https://www.google.com/recaptcha/api.js?onload=recaptchaCallback&render=explicit" async defer></script> <?php // phpcs:ignore ?>
571 <div id="<?php echo esc_attr( $unique_id ); ?>" data-sitekey="" style="margin-bottom: 5px;"></div>
572 <script>
573 var recaptchaCallback = function() {
574 var obj = jQuery('#<?php echo esc_attr( $unique_id ); ?>');
575 grecaptcha.render(obj.attr("id"), {
576 "sitekey" : "<?php echo esc_attr( $recaptcha['recaptcha-site-key'] ); ?>",
577 "callback" : function(token) {
578 obj.closest('form').find(".g-recaptcha-response").val(token);
579 }
580 });
581 }
582 </script>
583 <?php
584 }
585 if ( $recaptcha['captcha-provider'] === 'google-recaptcha' && $recaptcha['recaptcha-version'] == 3 && $recaptcha['recaptcha-site-key'] && $recaptcha['recaptcha-secret-key'] ) {
586 ?>
587 <script src="https://www.google.com/recaptcha/api.js?render=<?php echo esc_attr( $recaptcha['recaptcha-site-key'] ); ?>"></script> <?php // phpcs:ignore ?>
588 <?php
589 }
590 if ( $recaptcha['captcha-provider'] === 'cloudflare-turnstile' && $recaptcha['cloudflare-site-key'] && $recaptcha['cloudflare-secret-key'] ) {
591 ?>
592 <script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script> <?php // phpcs:ignore ?>
593 <div class="wpsc-tff turnstile wpsc-xs-12 wpsc-sm-12 wpsc-md-12 wpsc-lg-12 required wpsc-visible" data-cft="turnstile">
594 <div class="cf-turnstile" data-sitekey="<?php echo esc_attr( $recaptcha['cloudflare-site-key'] ); ?>"></div>
595 </div>
596 <script>
597 jQuery(document).ready(function() {
598
599 function wpscInitTurnstileWidgets() {
600
601 if (
602 typeof window.turnstile === 'undefined' ||
603 typeof window.turnstile.render !== 'function'
604 ) {
605 return false;
606 }
607
608 jQuery('.cf-turnstile').each(function() {
609
610 var widget = jQuery(this);
611
612 if (
613 widget.find('input[name="cf-turnstile-response"]').length ||
614 widget.find('iframe').length ||
615 widget.attr('data-wpsc-rendered') === '1'
616 ) {
617
618 widget.attr('data-wpsc-rendered', '1');
619
620 return;
621 }
622
623 window.turnstile.render(
624 this,
625 {
626 sitekey: widget.data('sitekey')
627 }
628 );
629
630 widget.attr('data-wpsc-rendered', '1');
631 });
632
633 return true;
634 }
635
636 if (wpscInitTurnstileWidgets()) {
637 return;
638 }
639
640 var attempts = 0;
641
642 var timer = setInterval(
643 function() {
644
645 attempts++;
646
647 if (
648 wpscInitTurnstileWidgets() ||
649 attempts > 50
650 ) {
651
652 clearInterval(timer);
653 }
654
655 },
656 100
657 );
658
659 });
660 </script>
661 <?php
662 }
663 do_action( 'wpsc_registration_form' );
664 ?>
665 <div class="wpsc-reg-user">
666 <?php
667 if ( $tc['allow-term-and-conditions-reg-user'] ) :
668 ?>
669 <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">
670 <div class="checkbox-container">
671 <?php $unique_id = uniqid( 'wpsc_' ); ?>
672 <input name="wpsc-tandc-reg-user" id="<?php echo esc_attr( $unique_id ); ?>" type="checkbox" value="1"/>
673 <?php
674 $name = WPSC_Translations::get( 'wpsc-term-and-conditions-reg-user', stripslashes( $tc['tandc-text-reg-user'] ) );
675 ?>
676 <label for="<?php echo esc_attr( $unique_id ); ?>"><?php echo wp_kses_post( $name ); ?></label>
677 </div>
678 </div>
679 <?php
680 endif;
681
682 if ( $gdpr['allow-gdpr-reg-user'] ) {
683 ?>
684 <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">
685 <div class="checkbox-container">
686 <?php $unique_id = uniqid( 'wpsc_' ); ?>
687 <input name="wpsc-gdpr-reg-user" id="<?php echo esc_attr( $unique_id ); ?>" type="checkbox" value="1"/>
688 <?php
689 $name = WPSC_Translations::get( 'wpsc-gdpr-reg-user', stripslashes( $gdpr['gdpr-text-reg-user'] ) );
690 ?>
691 <label for="<?php echo esc_attr( $unique_id ); ?>"><?php echo wp_kses_post( $name ); ?></label>
692 </div>
693 </div>
694 <?php
695 }
696 ?>
697 </div>
698
699 <button class="wpsc-button normal primary" onclick="wpsc_set_default_registration(this)"><?php esc_attr_e( 'Sign Up', 'supportcandy' ); ?></button>
700 <button class="wpsc-button normal secondary" onclick="window.location.reload();"><?php esc_attr_e( 'Cancel', 'supportcandy' ); ?></button>
701 <input type="hidden" name="action" value="wpsc_authenticate_registration"/>
702 <input type="hidden" name="is_username" value="0"/>
703 <input type="hidden" name="is_email" value="0"/>
704 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_authenticate_registration' ) ); ?>">
705 </form>
706 <?php
707 wp_die();
708 }
709
710 /**
711 * Check username availability
712 *
713 * @return void
714 */
715 public static function check_user_availability() {
716
717 if ( check_ajax_referer( 'wpsc_check_user_availability', '_ajax_nonce', false ) != 1 ) {
718 wp_send_json_error( 'Unauthorized request!', 401 );
719 }
720
721 $page_settings = get_option( 'wpsc-gs-page-settings' );
722 if ( $page_settings['user-registration'] !== 'default' ) {
723 wp_send_json_error( __( 'Unauthorized', 'supportcandy' ), 401 );
724 }
725
726 $type = isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : '';
727 if ( in_array( $type, array( 'username', 'email' ) ) === false ) {
728 wp_send_json_error( 'Something went wrong', 400 );
729 }
730
731 if ( $type === 'username' ) {
732 $username = isset( $_POST['username'] ) ? sanitize_user( wp_unslash( $_POST['username'] ) ) : '';
733 if ( ! $username ) {
734 wp_send_json_error( 'Something went wrong', 400 );
735 }
736 } elseif ( $type === 'email' ) {
737 $email = isset( $_POST['email'] ) && filter_var( wp_unslash( $_POST['email'] ), FILTER_VALIDATE_EMAIL ) ? sanitize_email( wp_unslash( $_POST['email'] ) ) : '';
738 if ( ! $email ) {
739 wp_send_json_error( 'Something went wrong', 400 );
740 }
741 }
742 $flag = $type === 'username' ? self::is_username_available( $username ) : self::is_email_available( $email );
743
744 wp_send_json( array( 'isAvailable' => $flag ? 0 : 1 ) );
745 }
746
747 /**
748 * Send registration OTP for email authentication
749 *
750 * @return void
751 */
752 public static function send_registration_otp() {
753
754 if ( check_ajax_referer( 'wpsc_authenticate_registration', '_ajax_nonce', false ) != 1 ) {
755 wp_send_json_error( 'Unauthorized request!', 401 );
756 }
757 $page_settings = get_option( 'wpsc-gs-page-settings' );
758 if ( $page_settings['user-registration'] !== 'default' ) {
759 wp_send_json_error( __( 'Unauthorized', 'supportcandy' ), 401 );
760 }
761
762 WPSC_MS_Recaptcha::validate( 'submit_registration' );
763
764 $firstname = isset( $_POST['firstname'] ) ? sanitize_text_field( wp_unslash( $_POST['firstname'] ) ) : '';
765 if ( ! $firstname ) {
766 wp_send_json_error( 'Bad request', 400 );
767 }
768
769 $lastname = isset( $_POST['lastname'] ) ? sanitize_text_field( wp_unslash( $_POST['lastname'] ) ) : '';
770 if ( ! $lastname ) {
771 wp_send_json_error( 'Bad request', 400 );
772 }
773
774 $username = isset( $_POST['username'] ) ? sanitize_user( wp_unslash( $_POST['username'] ) ) : '';
775 if ( ! $username ) {
776 wp_send_json_error( 'Bad request', 400 );
777 }
778
779 if ( self::is_username_available( $username ) ) {
780 wp_send_json_error( 'Bad request', 400 );
781 }
782
783 $email_address = isset( $_POST['email_address'] ) && filter_var( wp_unslash( $_POST['email_address'] ), FILTER_VALIDATE_EMAIL ) ? sanitize_email( wp_unslash( $_POST['email_address'] ) ) : '';
784 if ( ! $email_address ) {
785 wp_send_json_error( 'Bad request', 400 );
786 }
787
788 if ( self::is_email_available( $email_address ) ) {
789 wp_send_json_error( 'Bad request', 400 );
790 }
791
792 $password = isset( $_POST['password'] ) ? wp_unslash( $_POST['password'] ) : ''; // phpcs:ignore
793 if ( ! $password ) {
794 wp_send_json_error( 'Bad request', 400 );
795 }
796
797 $data = array(
798 'firstname' => $firstname,
799 'lastname' => $lastname,
800 'username' => $username,
801 'email_address' => $email_address,
802 'password' => $password,
803 );
804
805 $data = apply_filters( 'wpsc_register_user_data', $data );
806
807 $otp = WPSC_Email_OTP::insert(
808 array(
809 'email' => $email_address,
810 'date_expiry' => ( new DateTime() )->add( new DateInterval( 'PT1H' ) )->format( 'Y-m-d H:i:s' ),
811 'data' => wp_json_encode( $data ),
812 )
813 );
814
815 // send email notification.
816 WPSC_EN_User_Reg_OTP::send_otp( $otp );
817 ?>
818
819 <h2><?php esc_attr_e( 'Please sign up', 'supportcandy' ); ?></h2>
820 <small style="margin: 0 0 5px;"><?php esc_attr_e( 'We have sent a one-time verification code to your email address.', 'supportcandy' ); ?></small>
821 <form onsubmit="return false;" class="wpsc-login wpsc-confirm-registration">
822 <input type="text" name="otp" autocomplete="off"/>
823 <button class="wpsc-button normal primary" onclick="wpsc_confirm_registration(this)"><?php esc_attr_e( 'Submit', 'supportcandy' ); ?></button>
824 <input type="hidden" name="action" value="wpsc_confirm_registration"/>
825 <input type="hidden" name="otp_id" value="<?php echo esc_attr( $otp->id ); ?>">
826 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_confirm_registration' ) ); ?>"/>
827 </form>
828 <?php
829 wp_die();
830 }
831
832 /**
833 * Checks whether username is available or not
834 *
835 * @param string $username - user name string.
836 * @return boolean
837 */
838 public static function is_username_available( $username ) {
839
840 $user = get_user_by( 'login', $username );
841 return $user ? true : false;
842 }
843
844 /**
845 * Checks whether email is available or not
846 *
847 * @param string $email - email string.
848 * @return boolean
849 */
850 public static function is_email_available( $email ) {
851
852 $user = get_user_by( 'email', $email );
853
854 // check allowed email domains.
855 $allowed_domains = apply_filters( 'wpsc_registration_allowed_email_domains', array() );
856 $domain = substr( strrchr( $email, '@' ), 1 );
857 if ( $allowed_domains && ! in_array( $domain, $allowed_domains, true ) ) {
858 return true;
859 }
860 return $user ? true : false;
861 }
862
863 /**
864 * Register user after OTP matched
865 *
866 * @return void
867 */
868 public static function register_user() {
869
870 if ( check_ajax_referer( 'wpsc_confirm_registration', '_ajax_nonce', false ) != 1 ) {
871 wp_send_json_error( 'Unauthorized request!', 401 );
872 }
873
874 $page_settings = get_option( 'wpsc-gs-page-settings' );
875 if ( $page_settings['user-registration'] !== 'default' ) {
876 wp_send_json_error( __( 'Unauthorized', 'supportcandy' ), 401 );
877 }
878
879 $verification_otp = isset( $_POST['otp'] ) ? sanitize_text_field( wp_unslash( $_POST['otp'] ) ) : '';
880 if ( ! $verification_otp ) {
881 wp_send_json_error( 'Bad request', 400 );
882 }
883
884 $id = isset( $_POST['otp_id'] ) ? intval( $_POST['otp_id'] ) : '';
885 if ( ! $id ) {
886 wp_send_json_error( 'Bad request', 400 );
887 }
888
889 $otp = new WPSC_Email_OTP( $id );
890 if ( ! $otp->id ) {
891 wp_send_json_error( 'Bad request', 400 );
892 }
893
894 if ( ! $otp->is_valid( $verification_otp ) ) {
895 wp_send_json( array( 'isSuccess' => 0 ) );
896 wp_die();
897 }
898
899 $data = json_decode( $otp->data );
900
901 // check allowed email domains.
902 $allowed_domains = apply_filters( 'wpsc_registration_allowed_email_domains', array() );
903 $domain = substr( strrchr( $data->email_address, '@' ), 1 );
904 if ( $allowed_domains && ! in_array( $domain, $allowed_domains, true ) ) {
905 wp_send_json_error(
906 array(
907 'isSuccess' => 0,
908 'message' => __( 'Email domain is not allowed.', 'supportcandy' ),
909 ),
910 403
911 );
912 }
913
914 // insert user.
915 $display_name = $data->firstname . ' ' . $data->lastname;
916 $user_id = wp_insert_user(
917 array(
918 'user_login' => $data->username,
919 'user_pass' => $data->password,
920 'user_email' => $data->email_address,
921 'first_name' => $data->firstname,
922 'last_name' => $data->lastname,
923 'display_name' => $display_name,
924 'role' => 'subscriber',
925 )
926 );
927 if ( is_wp_error( $user_id ) ) {
928 wp_send_json( array( 'isSuccess' => 0 ) );
929 wp_die();
930 }
931
932 $user = wp_signon(
933 array(
934 'user_login' => $data->username,
935 'user_password' => $data->password,
936 )
937 );
938 wp_new_user_notification( $user_id, null, 'admin' );
939 do_action( 'wpsc_after_user_registration', $user, $data );
940 wp_send_json( array( 'isSuccess' => 1 ) );
941 }
942
943 /**
944 * User registrstion OTP email template section
945 *
946 * @param array $sections - section name.
947 * @return array
948 */
949 public static function registration_email_template_section( $sections ) {
950
951 $sections['registration-otp'] = array(
952 'slug' => 'registration_otp',
953 'icon' => 'unlock',
954 'label' => esc_attr__( 'User Registration OTP', 'supportcandy' ),
955 'callback' => 'wpsc_get_en_user_reg_otp',
956 );
957 return $sections;
958 }
959
960 /**
961 * Get guest sign in screen
962 *
963 * @return void
964 */
965 public static function get_guest_sign_in() {
966
967 $gs = get_option( 'wpsc-gs-general' );
968 $page_settings = get_option( 'wpsc-gs-page-settings' );
969 if ( ! ( $page_settings['otp-login'] && in_array( 'guest', $gs['allow-create-ticket'] ) ) ) {
970 wp_send_json_error( 'Unauthorozed', 400 );
971 }
972 ?>
973
974 <h2><?php esc_attr_e( 'Please sign in', 'supportcandy' ); ?></h2>
975 <form onsubmit="return false;" class="wpsc-login authenticate-guest-login">
976 <input type="text" name="email_address" placeholder="<?php esc_attr_e( 'Email Address', 'supportcandy' ); ?>" autocomplete="off"/>
977 <button class="wpsc-button normal primary" onclick="wpsc_authenticate_guest_login(this)"><?php esc_attr_e( 'Sign In', 'supportcandy' ); ?></button>
978 <button class="wpsc-button normal secondary" onclick="window.location.reload();"><?php esc_attr_e( 'Cancel', 'supportcandy' ); ?></button>
979 <input type="hidden" name="action" value="wpsc_authenticate_guest_login"/>
980 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_authenticate_guest_login' ) ); ?>">
981 </form>
982 <?php
983 wp_die();
984 }
985
986 /**
987 * Get OTP screen
988 *
989 * @return void
990 */
991 public static function get_guest_sign_in_auth() {
992
993 if ( check_ajax_referer( 'wpsc_authenticate_guest_login', '_ajax_nonce', false ) != 1 ) {
994 wp_send_json_error( 'Unauthorized request!', 401 );
995 }
996 $gs = get_option( 'wpsc-gs-general' );
997 $page_settings = get_option( 'wpsc-gs-page-settings' );
998 if ( ! ( $page_settings['otp-login'] && in_array( 'guest', $gs['allow-create-ticket'] ) ) ) {
999 wp_send_json_error( 'Unauthorozed', 400 );
1000 }
1001
1002 $email_address = isset( $_POST['email_address'] ) && filter_var( wp_unslash( $_POST['email_address'] ), FILTER_VALIDATE_EMAIL ) ? sanitize_text_field( wp_unslash( $_POST['email_address'] ) ) : '';
1003 if ( ! $email_address ) {
1004 wp_send_json_error( 'Bad request', 400 );
1005 }
1006
1007 $customer = WPSC_Customer::get_by_email( $email_address );
1008 if ( ! $customer->id ) {
1009 esc_attr_e( 'Invalid email address!', 'supportcandy' );
1010 wp_die();
1011 }
1012
1013 $otp = WPSC_Email_OTP::insert(
1014 array(
1015 'email' => $email_address,
1016 'date_expiry' => ( new DateTime() )->add( new DateInterval( 'P1D' ) )->format( 'Y-m-d H:i:s' ),
1017 'data' => wp_json_encode(
1018 array(
1019 'email' => $email_address,
1020 )
1021 ),
1022 )
1023 );
1024
1025 // Send OTP for login.
1026 WPSC_EN_Guest_Login_OTP::send_otp( $otp );
1027 ?>
1028
1029 <h2><?php esc_attr_e( 'Please sign in', 'supportcandy' ); ?></h2>
1030 <small style="margin: 0 0 5px;"><?php esc_attr_e( 'We have sent a one-time verification code to your email address.', 'supportcandy' ); ?></small>
1031 <form onsubmit="return false;" class="wpsc-login wpsc-confirm-guest-login">
1032 <input type="text" name="otp" autocomplete="off"/>
1033 <button class="wpsc-button normal primary" onclick="wpsc_confirm_guest_login(this)"><?php esc_attr_e( 'Submit', 'supportcandy' ); ?></button>
1034 <input type="hidden" name="action" value="wpsc_confirm_guest_login"/>
1035 <input type="hidden" name="otp_id" value="<?php echo esc_attr( $otp->id ); ?>">
1036 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_confirm_guest_login' ) ); ?>">
1037 </form>
1038 <?php
1039 wp_die();
1040 }
1041
1042 /**
1043 * Confirm guest login
1044 *
1045 * @return void
1046 */
1047 public static function confirm_guest_login() {
1048
1049 // Add rate limiting.
1050 $ip_address = WPSC_DF_IP_Address::get_current_user_ip();
1051 $attempt_key = 'wpsc_otp_attempts_' . md5( $ip_address );
1052 $attempts = get_transient( $attempt_key );
1053 $attempts = $attempts ? $attempts : 1;
1054
1055 if ( $attempts >= 5 ) {
1056 wp_send_json_error( 'Too many attempts. Please try again later.', 429 );
1057 }
1058
1059 if ( check_ajax_referer( 'wpsc_confirm_guest_login', '_ajax_nonce', false ) != 1 ) {
1060 wp_send_json_error( 'Unauthorized request!', 401 );
1061 }
1062
1063 $gs = get_option( 'wpsc-gs-general' );
1064 $page_settings = get_option( 'wpsc-gs-page-settings' );
1065 if ( ! ( $page_settings['otp-login'] && in_array( 'guest', $gs['allow-create-ticket'] ) ) ) {
1066 wp_send_json_error( 'Unauthorozed', 400 );
1067 }
1068
1069 $verification_otp = isset( $_POST['otp'] ) ? sanitize_text_field( wp_unslash( $_POST['otp'] ) ) : '';
1070 if ( ! $verification_otp ) {
1071 wp_send_json_error( 'Bad request', 400 );
1072 }
1073
1074 $id = isset( $_POST['otp_id'] ) ? intval( $_POST['otp_id'] ) : '';
1075 if ( ! $id ) {
1076 wp_send_json_error( 'Bad request', 400 );
1077 }
1078
1079 $otp = new WPSC_Email_OTP( $id );
1080 if ( ! $otp->id ) {
1081 wp_send_json_error( 'Bad request', 400 );
1082 }
1083
1084 if ( ! $otp->is_valid( $verification_otp ) ) {
1085
1086 // Increment attempt counter.
1087 ++$attempts;
1088 set_transient( $attempt_key, $attempts, 300 ); // 5 minute lockout.
1089
1090 // Add per-OTP attempt tracking.
1091 $otp_attempt_key = 'wpsc_otp_' . $id . '_attempts';
1092 $otp_attempts = get_transient( $otp_attempt_key );
1093 $otp_attempts = $otp_attempts ? $otp_attempts + 1 : 1;
1094 set_transient( $otp_attempt_key, $otp_attempts, 600 );
1095
1096 if ( $otp_attempts >= 3 ) {
1097 WPSC_Email_OTP::destroy( $otp );
1098 wp_send_json_error( 'OTP has been invalidated due to too many failed attempts', 403 );
1099 }
1100
1101 wp_send_json( array( 'isSuccess' => 0 ) );
1102 wp_die();
1103 }
1104
1105 $data = json_decode( $otp->data, true );
1106 $data['auth_token'] = WPSC_Functions::get_random_string( 100 );
1107 $data['auth_type'] = 'login';
1108 $otp->data = wp_json_encode( $data );
1109 $otp->save();
1110
1111 // Clear rate limiting on success.
1112 delete_transient( $attempt_key );
1113
1114 // add customer record if not set.
1115 $customer = WPSC_Customer::get_by_email( $data['email'] );
1116 if ( ! $customer->id ) {
1117 $user = get_user_by( 'email', $data['email'] );
1118 if ( $user ) {
1119
1120 WPSC_Customer::insert(
1121 array(
1122 'user' => $user->ID,
1123 'name' => $user->display_name,
1124 'email' => $user->user_email,
1125 )
1126 );
1127
1128 } else {
1129
1130 WPSC_Customer::insert(
1131 array(
1132 'user' => 0,
1133 'name' => $data['name'],
1134 'email' => $data['email'],
1135 )
1136 );
1137 }
1138 }
1139
1140 $auth = array(
1141 'email' => $otp->email,
1142 'token' => $data['auth_token'],
1143 );
1144
1145 setcookie( 'wpsc_guest_login_auth', wp_json_encode( $auth ), $otp->date_expiry->getTimestamp(), '/' );
1146
1147 wp_send_json( array( 'isSuccess' => 1 ) );
1148 }
1149
1150 /**
1151 * Validate login auth token
1152 *
1153 * @param object $login_auth - login auth details.
1154 * @return boolean
1155 */
1156 public static function validate_guest_login( $login_auth ) {
1157
1158 $gs = get_option( 'wpsc-gs-general' );
1159 $page_settings = get_option( 'wpsc-gs-page-settings' );
1160
1161 $results = WPSC_Email_OTP::find(
1162 array(
1163 'meta_query' => array(
1164 'relation' => 'AND',
1165 array(
1166 'slug' => 'email',
1167 'compare' => '=',
1168 'val' => $login_auth->email,
1169 ),
1170 ),
1171 )
1172 )['results'];
1173
1174 if ( ! $results ) {
1175 return false;
1176 }
1177
1178 $otp = $results[0];
1179 if ( ! $otp->id ) {
1180 return false;
1181 }
1182
1183 $now = new DateTime();
1184 $data = json_decode( $otp->data );
1185
1186 if (
1187 isset( $data->auth_type ) &&
1188 ( ( $data->auth_type == 'login' && $page_settings['otp-login'] && in_array( 'guest', $gs['allow-create-ticket'] ) ) || $data->auth_type == 'open-ticket' ) &&
1189 ( $otp->date_expiry > $now && $data->auth_token == $login_auth->token )
1190 ) {
1191 self::$login_type = 'guest';
1192 self::$guest_login_type = $data->auth_type;
1193 return true;
1194 }
1195
1196 return false;
1197 }
1198
1199 /**
1200 * Add guest login email template
1201 *
1202 * @param array $sections - section name.
1203 * @return array
1204 */
1205 public static function guest_login_email_template_section( $sections ) {
1206
1207 $sections['guest-login-otp'] = array(
1208 'slug' => 'guest_login_otp',
1209 'icon' => 'unlock',
1210 'label' => esc_attr__( 'Guest Login OTP', 'supportcandy' ),
1211 'callback' => 'wpsc_get_en_guest_login_otp',
1212 );
1213 return $sections;
1214 }
1215
1216 /**
1217 * Logout current user
1218 *
1219 * @return void
1220 */
1221 public function logout() {
1222
1223 global $current_user;
1224
1225 $otp = WPSC_Email_OTP::find(
1226 array(
1227 'meta_query' => array(
1228 'relation' => 'AND',
1229 array(
1230 'slug' => 'email',
1231 'compare' => '=',
1232 'val' => $this->customer->email,
1233 ),
1234 ),
1235 )
1236 )['results'];
1237
1238 if ( $otp ) :
1239 WPSC_Email_OTP::destroy( $otp[0] );
1240 @setcookie( 'wpsc_guest_login_auth', '', time(), '/' ); //phpcs:ignore
1241 endif;
1242
1243 if ( $current_user->ID ) {
1244 wp_logout();
1245 }
1246 }
1247 }
1248 endif;
1249
1250 WPSC_Current_User::init();
1251