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

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