PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 3.0.1
Defender Security – Malware Scanner, Login Security & Firewall v3.0.1
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / src / controller / notification.php

notification.php in Defender Security – Malware Scanner, Login Security & Firewall 3.0.1, at src/controller/notification.php

832 lines 20.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WP_Defender\Controller;
4
5 use Calotes\Component\Request;
6 use Calotes\Component\Response;
7 use Calotes\Helper\HTTP;
8 use WP_Defender\Component\Config\Config_Hub_Helper;
9 use WP_Defender\Controller;
10 use WP_Defender\Traits\Formats;
11 use WP_Defender\Traits\User;
12 use WP_Defender\Model\Notification as Model_Notification;
13
14 class Notification extends Controller {
15 use User, Formats;
16
17 public $slug = 'wdf-notification';
18
19 /**
20 * @var \WP_Defender\Component\Notification
21 */
22 protected $service;
23
24 public function __construct() {
25 $this->register_page(
26 esc_html__( 'Notifications', 'wpdef' ),
27 $this->slug,
28 array(
29 &$this,
30 'main_view',
31 ),
32 $this->parent_slug
33 );
34 $this->register_routes();
35 $this->service = wd_di()->get( \WP_Defender\Component\Notification::class );
36 add_action( 'defender_enqueue_assets', array( &$this, 'enqueue_assets' ) );
37 // We use custom ajax endpoint here as the nonce would fail with other user.
38 add_action( 'wp_ajax_defender_listen_user_subscribe', array( &$this, 'verify_subscriber' ) );
39 add_action( 'wp_ajax_nopriv_defender_listen_user_subscribe', array( &$this, 'verify_subscriber' ) );
40 add_action( 'wp_ajax_defender_listen_user_unsubscribe', array( &$this, 'unsubscribe_and_send_email' ) );
41 add_action( 'wp_ajax_nopriv_defender_listen_user_unsubscribe', array( &$this, 'unsubscribe_and_send_email' ) );
42 add_action( 'defender_notify', array( &$this, 'send_notify' ), 10, 2 );
43 // We will schedule the time to send reports.
44 if ( ! wp_next_scheduled( 'wdf_maybe_send_report' ) ) {
45 $timestamp = gmmktime( gmdate( 'H' ), 0, 0 );
46 wp_schedule_event( $timestamp, 'thirty_minutes', 'wdf_maybe_send_report' );
47 }
48 add_action( 'wdf_maybe_send_report', array( &$this, 'report_sender' ) );
49 add_action( 'admin_notices', array( &$this, 'show_actions_with_subscription' ) );
50 }
51
52 /**
53 * For users who have subscribed or unsubscribed confirmation.
54 *
55 * @return null
56 */
57 public function show_actions_with_subscription() {
58 if ( ! defined( 'IS_PROFILE_PAGE' ) || false === constant( 'IS_PROFILE_PAGE' ) ) {
59 return null;
60 }
61 $slug = isset( $_GET['slug'] ) ? sanitize_text_field( $_GET['slug'] ) : false;
62 if ( empty( $slug ) ) {
63 return null;
64 }
65 $m = $this->service->find_module_by_slug( $slug );
66 if ( ! is_object( $m ) ) {
67 return null;
68 }
69 $context = isset( $_GET['context'] ) ? sanitize_text_field( $_GET['context'] ) : false;
70 if ( 'subscribed' === $context ) {
71 $unsubscribe_link = $this->service->create_unsubscribe_url( $m->slug, $this->get_current_user_email() );
72 $strings = sprintf(
73 /* translators: %s - module title, %s - unsubscribed link */
74 __( 'You are now subscribed to receive <strong>%1$s</strong>. Made a mistake? <a href="%2$s">Unsubscribe</a>', 'wpdef' ),
75 $m->title,
76 $unsubscribe_link
77 );
78 } elseif ( 'unsubscribe' === $context ) {
79 $strings = sprintf(
80 /* translators: %s - module title */
81 __( 'You are now unsubscribed from <strong>%s</strong>.', 'wpdef' ),
82 $m->title
83 );
84 } else {
85 return null;
86 }
87 ?>
88 <div class="notice notice-success" style="position:relative;">
89 <p><?php echo $strings; ?></p>
90 <a href="<?php echo get_edit_profile_url(); ?>" class="notice-dismiss" style="text-decoration: none">
91 <span class="screen-reader-text"><?php _e( 'Dismiss this notice.', 'wpdef' ); ?></span>
92 </a>
93 </div>
94 <?php
95 }
96
97 /**
98 * Trigger report check signals.
99 */
100 public function report_sender() {
101 $this->service->maybe_dispatch_report();
102 }
103
104 public function main_view() {
105 $this->render( 'main' );
106 }
107
108 /**
109 * Dispatch notification.
110 *
111 * @param string $slug
112 * @param object $args
113 */
114 public function send_notify( $slug, $args ) {
115 $this->service->dispatch_notification( $slug, $args );
116 }
117
118 /**
119 * @param Request $request
120 *
121 * @defender_route
122 * @return Response
123 */
124 public function validate_email( Request $request ) {
125 $data = $request->get_data(
126 array(
127 'email' => array(
128 'type' => 'string',
129 'sanitize' => 'sanitize_text_field',
130 ),
131 )
132 );
133 $email = $data['email'] ?? false;
134 if ( filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
135 return new Response(
136 true,
137 array(
138 'error' => false,
139 'avatar' => get_avatar_url( $data['email'] ),
140 )
141 );
142 } else {
143 return new Response(
144 false,
145 array(
146 'error' => __( 'Invalid email address.', 'wpdef' ),
147 )
148 );
149 }
150 }
151
152 /**
153 * Unsubscribe process.
154 */
155 public function unsubscribe_and_send_email() {
156 $slug = HTTP::get( 'slug', '' );
157 $hash = HTTP::get( 'hash', '' );
158 $slug = sanitize_text_field( $slug );
159 if ( empty( $slug ) || empty( $hash ) ) {
160 wp_die( __( 'You shall not pass.', 'wpdef' ) );
161 }
162 $m = $this->service->find_module_by_slug( $slug );
163 if ( ! is_object( $m ) ) {
164 wp_die( __( 'You shall not pass.', 'wpdef' ) );
165 }
166 $inhouse = false;
167 foreach ( $m->in_house_recipients as &$recipient ) {
168 $email = $recipient['email'];
169 if ( hash_equals( $hash, hash( 'sha256', $email . AUTH_SALT ) ) ) {
170 if ( ! is_user_logged_in() ) {
171 auth_redirect();
172 }
173 if ( $email !== $this->get_current_user_email() ) {
174 wp_die( __( 'Invalid request.', 'wpdef' ) );
175 }
176 $recipient['status'] = Model_Notification::USER_SUBSCRIBE_CANCELED;
177 $m->save();
178 $inhouse = true;
179 // Send email.
180 $this->service->send_unsubscribe_email( $m, $email, $inhouse, $recipient['name'] );
181 break;
182 }
183 }
184
185 if ( false === $inhouse ) {
186 // No match on in-house, check the outhouse list.
187 foreach ( $m->out_house_recipients as &$recipient ) {
188 $email = $recipient['email'];
189 if ( hash_equals( $hash, hash( 'sha256', $email . AUTH_SALT ) ) ) {
190 $recipient['status'] = Model_Notification::USER_SUBSCRIBE_CANCELED;
191 $m->save();
192 $this->service->send_unsubscribe_email( $m, $email, $inhouse, $recipient['name'] );
193 }
194 }
195 }
196 if ( $inhouse ) {
197 wp_redirect(
198 add_query_arg(
199 array(
200 'slug' => $slug,
201 'context' => 'unsubscribe',
202 ),
203 get_edit_profile_url()
204 )
205 );
206 } else {
207 wp_redirect( get_home_url() );
208 }
209 exit;
210 }
211
212 /**
213 * An endpoint for saving single config from frontend.
214 *
215 * @param Request $request
216 *
217 * @defender_route
218 * @return Response
219 */
220 public function save( Request $request ) {
221 $raw_data = $request->get_data();
222 $slug = sanitize_textarea_field( $raw_data['slug'] );
223 $model = $this->service->find_module_by_slug( $slug );
224
225 if ( ! is_object( $model ) ) {
226 // Should never be here.
227 die;
228 }
229 $data = $request->get_data_by_model( $model );
230 $model->import( $data );
231 $model->status = Model_Notification::STATUS_ACTIVE;
232 if ( $model->validate() ) {
233 if ( 0 === $model->last_sent ) {
234 // This means that the notification or report never sent, we will use the moment that it get activate.
235 $model->last_sent = time();
236 }
237 $model->save();
238 $this->service->send_subscription_confirm_email(
239 $model
240 );
241 Config_Hub_Helper::set_clear_active_flag();
242
243 return new Response(
244 true,
245 array_merge(
246 array(
247 'message' => __(
248 'You have activated the notification successfully. Note, recipients will need to confirm their subscriptions to begin receiving notifications.',
249 'wpdef'
250 ),
251 ),
252 $this->data_frontend()
253 )
254 );
255 }
256
257 return new Response(
258 false,
259 array(
260 'message' => $model->get_formatted_errors(),
261 )
262 );
263 }
264
265 /**
266 * @param Request $request
267 *
268 * @defender_route
269 * @return Response
270 */
271 public function save_bulk( Request $request ) {
272 $data = $request->get_data(
273 array(
274 'reports' => array(
275 'type' => 'array',
276 'sanitize' => 'sanitize_textarea_field',
277 ),
278 'notifications' => array(
279 'type' => 'array',
280 'sanitize' => 'sanitize_textarea_field',
281 ),
282 )
283 );
284 $this->save_reports( $data['reports'] );
285 $this->save_notifications( $data['notifications'] );
286 Config_Hub_Helper::set_clear_active_flag();
287
288 return new Response(
289 true,
290 array_merge(
291 $this->data_frontend(),
292 array(
293 'message' => __(
294 'Your settings have been updated successfully. Any new recipients will receive an email to confirm their subscription.',
295 'wpdef'
296 ),
297 )
298 )
299 );
300 }
301
302 /**
303 * Process bulk reports saving.
304 *
305 * @param array $data
306 */
307 private function save_reports( $data ) {
308 foreach ( $data['configs'] as $datum ) {
309 $slug = $datum['slug'];
310 $model = $this->service->find_module_by_slug( $slug );
311 if ( ! is_object( $model ) ) {
312 continue;
313 }
314
315 $import = array(
316 // Bulk saving must always enabled.
317 'status' => Model_Notification::STATUS_ACTIVE,
318 'configs' => $datum,
319 'in_house_recipients' => $data['in_house_recipients'],
320 'out_house_recipients' => $data['out_house_recipients'],
321 );
322 // @since 2.7.0.
323 if ( 'malware-report' !== $slug ) {
324 $import['frequency'] = $data['frequency'];
325 $import['day_n'] = $data['day_n'];
326 $import['day'] = $data['day'];
327 $import['time'] = $data['time'];
328 }
329 foreach ( $import['out_house_recipients'] as $key => $val ) {
330 if ( ! filter_var( $val['email'], FILTER_VALIDATE_EMAIL ) ) {
331 unset( $import['out_house_recipients'][ $key ] );
332 }
333 }
334 $model->import( $import );
335 if ( $model->validate() ) {
336 $model->save();
337 $this->service->send_subscription_confirm_email(
338 $model
339 );
340 }
341 }
342 }
343
344 /**
345 * @param array $data
346 *
347 * @throws \DI\DependencyException
348 * @throws \DI\NotFoundException
349 * @throws \ReflectionException
350 */
351 private function save_notifications( $data ) {
352 foreach ( $data['configs'] as $datum ) {
353 $slug = $datum['slug'];
354 $model = $this->service->find_module_by_slug( $slug );
355 if ( ! is_object( $model ) ) {
356 continue;
357 }
358 $import = array(
359 'status' => Model_Notification::STATUS_ACTIVE,
360 'configs' => $datum,
361 'in_house_recipients' => $data['in_house_recipients'],
362 'out_house_recipients' => $data['out_house_recipients'],
363 );
364 foreach ( $import['out_house_recipients'] as $key => $val ) {
365 if ( ! filter_var( $val['email'], FILTER_VALIDATE_EMAIL ) ) {
366 unset( $import['out_house_recipients'][ $key ] );
367 }
368 }
369 $model->import( $import );
370 if ( $model->validate() ) {
371 $model->save();
372 $this->service->send_subscription_confirm_email(
373 $model
374 );
375 }
376 }
377 }
378
379 /**
380 * Bulk activate.
381 *
382 * @param Request $request
383 *
384 * @defender_route
385 * @return Response
386 * @throws \Exception
387 */
388 public function bulk_activate( Request $request ) {
389 $data = $request->get_data(
390 array(
391 'slugs' => array(
392 'type' => 'array',
393 'sanitize' => 'sanitize_text_field',
394 ),
395 )
396 );
397 $slugs = $data['slugs'];
398 if ( empty( $slugs ) ) {
399 return new Response( false, array() );
400 }
401
402 foreach ( $slugs as $slug ) {
403 $model = $this->service->find_module_by_slug( $slug );
404 if ( is_object( $model ) ) {
405 $model->status = Model_Notification::STATUS_ACTIVE;
406 if ( 0 === $model->last_sent ) {
407 // This means that the notification or report never sent, we will use the moment that it get activate.
408 $model->last_sent = time();
409 }
410 $model->save();
411 }
412 }
413
414 return new Response(
415 true,
416 array_merge(
417 array(
418 'message' => 'You have activated the notification successfully. Note, recipients will need to confirm their subscriptions to begin receiving notifications.',
419 ),
420 $this->data_frontend()
421 )
422 );
423 }
424
425 /**
426 * @param Request $request
427 *
428 * @defender_route
429 * @return Response
430 */
431 public function bulk_deactivate( Request $request ) {
432 $data = $request->get_data(
433 array(
434 'slugs' => array(
435 'type' => 'array',
436 'sanitize' => 'sanitize_text_field',
437 ),
438 )
439 );
440 $slugs = $data['slugs'];
441 if ( empty( $slugs ) ) {
442 return new Response( false, array() );
443 }
444
445 foreach ( $slugs as $slug ) {
446 $model = $this->service->find_module_by_slug( $slug );
447 if ( is_object( $model ) ) {
448 $model->status = Model_Notification::STATUS_DISABLED;
449 $model->save();
450 }
451 }
452
453 return new Response(
454 true,
455 array_merge(
456 array(
457 'message' => __( 'You have deactivated the notifications successfully.', 'wpdef' ),
458 ),
459 $this->data_frontend()
460 )
461 );
462 }
463
464 /**
465 * @param Request $request
466 *
467 * @defender_route
468 * @return Response
469 */
470 public function disable( Request $request ) {
471 $data = $request->get_data(
472 array(
473 'slug' => array(
474 'type' => 'string',
475 'sanitize' => 'sanitize_text_field',
476 ),
477 )
478 );
479
480 $slug = $data['slug'];
481 $model = $this->service->find_module_by_slug( $slug );
482 if ( ! is_object( $model ) ) {
483 // Should never be here.
484 die;
485 }
486 $model->status = Model_Notification::STATUS_DISABLED;
487 $model->save();
488
489 return new Response(
490 true,
491 array_merge(
492 $this->data_frontend(),
493 array(
494 'message' => __( 'You have deactivated the notification successfully.', 'wpdef' ),
495 )
496 )
497 );
498 }
499
500 /**
501 * This is a receiver to process subscribe confirmation from email.
502 */
503 public function verify_subscriber() {
504 $hash = HTTP::get( 'hash', false );
505 $slug = HTTP::get( 'uid', false );
506 $inhouse = HTTP::get( 'inhouse', 0 );
507 if ( $inhouse && ! is_user_logged_in() ) {
508 // This is in-house, so we need to redirect.
509 auth_redirect();
510 }
511 if ( false === $hash || false === $slug ) {
512 wp_die( __( 'You shall not pass.', 'wpdef' ) );
513 }
514 $m = $this->service->find_module_by_slug( $slug );
515 if ( ! is_object( $m ) ) {
516 wp_die( __( 'You shall not pass.', 'wpdef' ) );
517 }
518 if ( $inhouse ) {
519 $processed = false;
520 foreach ( $m->in_house_recipients as &$recipient ) {
521 if ( Model_Notification::USER_SUBSCRIBED === $recipient['status'] ) {
522 continue;
523 }
524
525 $email = $recipient['email'];
526 $name = $recipient['name'];
527 if ( hash_equals( $hash, hash( 'sha256', $email . AUTH_SALT ) )
528 && $email === $this->get_current_user_email() ) {
529 $recipient['status'] = Model_Notification::USER_SUBSCRIBED;
530 $this->service->send_subscribed_email( $email, $m, $name );
531 $processed = true;
532 }
533 }
534 } else {
535 foreach ( $m->out_house_recipients as &$recipient ) {
536 if ( Model_Notification::USER_SUBSCRIBED === $recipient['status'] ) {
537 continue;
538 }
539
540 $email = $recipient['email'];
541 $name = $recipient['name'];
542 if ( hash_equals( $hash, hash( 'sha256', $email . AUTH_SALT ) ) ) {
543 $recipient['status'] = Model_Notification::USER_SUBSCRIBED;
544 $this->service->send_subscribed_email( $email, $m, $name );
545 }
546 }
547 }
548 $m->save();
549 if ( $inhouse ) {
550 if ( $processed ) {
551 wp_redirect(
552 add_query_arg(
553 array(
554 'slug' => $m->slug,
555 'context' => 'subscribed',
556 ),
557 get_edit_profile_url()
558 )
559 );
560 } else {
561 wp_redirect( home_url() );
562 }
563 } else {
564 wp_redirect( home_url() );
565 }
566 exit;
567 }
568
569 /**
570 * Enqueue assets & output data.
571 */
572 public function enqueue_assets() {
573 if ( ! $this->is_page_active() ) {
574 return;
575 }
576 wp_localize_script(
577 'def-notification',
578 'notification',
579 array_merge( $this->data_frontend(), $this->dump_routes_and_nonces() )
580 );
581 wp_enqueue_script( 'def-momentjs', defender_asset_url( '/assets/js/vendor/moment/moment.min.js' ) );
582 wp_enqueue_script( 'def-notification' );
583 $this->enqueue_main_assets();
584 wp_enqueue_style(
585 'def-select2',
586 defender_asset_url( '/assets/css/select2.min.css' )
587 );
588 }
589
590 /**
591 * An endpoint for fetching users pool.
592 *
593 * @param Request $request Request data.
594 *
595 * @defender_route
596 */
597 public function get_users( Request $request ) {
598 $data = $request->get_data(
599 array(
600 'paged' => array(
601 'type' => 'int',
602 'sanitize' => 'sanitize_text_field',
603 ),
604 'search' => array(
605 'type' => 'string',
606 'sanitize' => 'sanitize_text_field',
607 ),
608 'exclude' => array(
609 'type' => 'array',
610 ),
611 'module' => array(
612 'type' => 'string',
613 'sanitize' => 'sanitize_text_field',
614 ),
615 'user_role_filter' => array(
616 'type' => 'string',
617 'sanitize' => 'sanitize_text_field',
618 ),
619 'user_sort' => array(
620 'type' => 'string',
621 'sanitize' => 'sanitize_text_field',
622 ),
623 )
624 );
625 $paged = 1;
626 $exclude = $data['exclude'] ?? array();
627 $username = $data['search'] ?? '';
628 $slug = $data['module'] ?? null;
629 $role = '';
630
631 if (
632 isset( $data['user_role_filter'] ) &&
633 'all' !== $data['user_role_filter']
634 ) {
635 $role = $data['user_role_filter'];
636 }
637
638 $order_by = 'ID';
639 $order = 'DESC';
640 if ( isset( $data['user_sort'] ) ) {
641 switch ( $data['user_sort'] ) {
642 case 'recent':
643 $order_by = 'registered';
644 $order = 'DESC';
645 break;
646 case 'alpha_asc':
647 $order_by = 'display_name';
648 $order = 'ASC';
649 break;
650 case 'alpha_desc':
651 default:
652 $order_by = 'display_name';
653 $order = 'DESC';
654 break;
655 }
656 }
657
658 if ( strlen( $username ) ) {
659 $username = "*$username*";
660 }
661
662 $users = $this->service->get_users_pool(
663 $exclude,
664 $role,
665 $username,
666 $order_by,
667 $order,
668 10,
669 $paged
670 );
671
672 if ( ! is_null( $slug ) ) {
673 $notification = $this->service->find_module_by_slug( $slug );
674 if ( is_object( $notification ) ) {
675 foreach ( $notification->in_house_recipients as $recipient ) {
676 foreach ( $users as &$user ) {
677 if ( $user['email'] === $recipient['email'] ) {
678 $user['status'] = $recipient['status'];
679 }
680 }
681 }
682 }
683 }
684
685 wp_send_json_success( $users );
686 }
687
688 public function remove_settings() {
689 foreach ( $this->service->get_modules_as_objects() as $module ) {
690 $module->delete();
691 }
692 }
693
694 public function remove_data() {}
695
696 public function to_array() {}
697
698 /**
699 * All the variables that we will show on frontend, both in the main page, or dashboard widget.
700 *
701 * @return array
702 */
703 public function data_frontend() {
704 return array(
705 'notifications' => $this->service->get_modules(),
706 'inactive_notifications' => $this->service->get_inactive_modules(),
707 'active_count' => $this->service->count_active(),
708 'next_run' => $this->service->get_next_run(),
709 'misc' => array(
710 'days_of_week' => $this->get_days_of_week(),
711 'times_of_day' => $this->get_times(),
712 'timezone_text' => sprintf(
713 /* translators: %s - timezone, %s - time */
714 __(
715 'Your timezone is set to <strong>%1$s</strong>, so your current time is <strong>%2$s</strong>.',
716 'wpdef'
717 ),
718 wp_timezone_string(),
719 date( 'H:i', current_time( 'timestamp' ) )// phpcs:ignore
720 ),
721 'default_recipient' => $this->get_default_recipient(),
722 ),
723 );
724 }
725
726 /**
727 * Import the data of other source into this, it can be when HUB trigger the import, or user apply a preset.
728 *
729 * @param array $data
730 */
731 public function import_data( $data ) {}
732
733 /**
734 * @return array
735 */
736 public function export_strings() {
737 $modules = wd_di()->get( Notification::class )->service->get_modules_as_objects();
738 $strings = array();
739 foreach ( $modules as $module ) {
740 /* translators: %s - module title, %s - module status */
741 $string = __( '%1$s: %2$s', 'wpdef' );
742 if ( 'notification' === $module->type ) {
743 $string = sprintf(
744 $string,
745 $module->title,
746 Model_Notification::STATUS_ACTIVE === $module->status ? __( 'Enabled', 'wpdef' ) : __( 'Disabled', 'wpdef' )
747 );
748 } else {
749 $string = sprintf(
750 $string,
751 $module->title,
752 Model_Notification::STATUS_ACTIVE === $module->status ? $module->to_string() : __( 'Disabled', 'wpdef' )
753 );
754 }
755 $strings[] = $string;
756 }
757
758 return $strings;
759 }
760
761 /**
762 * Resend invite email.
763 *
764 * @param Request $request
765 *
766 * @defender_route
767 * @return Response
768 */
769 public function resend_invite_email( Request $request ) {
770 $data = $request->get_data(
771 array(
772 'slug' => array(
773 'type' => 'string',
774 'sanitize' => 'sanitize_textarea_field',
775 ),
776 'email' => array(
777 'type' => 'string',
778 'sanitize' => 'sanitize_text_field',
779 ),
780 'id' => array(
781 'type' => 'integer',
782 ),
783 'name' => array(
784 'type' => 'string',
785 'sanitize' => 'sanitize_text_field',
786 ),
787 )
788 );
789
790 $model = $this->service->find_module_by_slug( $data['slug'] );
791
792 if ( ! is_object( $model ) ) {
793 return new Response( false, [
794 'message' => __( 'Module not found.', 'wpdef' ),
795 ] );
796 }
797
798 $subscriber = array(
799 'email' => $data['email'],
800 'name' => $data['name'],
801 );
802
803 if ( ! empty( $data['id'] ) ) {
804 $subscriber['id'] = $data['id'];
805 }
806
807 // Resend invite email now.
808 $sent = $this->service->send_email( $subscriber, $model );
809
810 if ( $sent ) {
811 return new Response( true, [
812 'message' => __( 'Invitation sent successfully.', 'wpdef' ),
813 ] );
814 }
815
816 return new Response( false, [
817 'message' => __( 'Sorry! We could not send the invitation, Please try again later.', 'wpdef' ),
818 ] );
819 }
820
821 /**
822 * Get user roles with count.
823 *
824 * @defender_route
825 */
826 public function get_user_roles() {
827 $user_roles = $this->service->get_user_roles();
828
829 wp_send_json_success( $user_roles );
830 }
831 }
832