PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.0.0
WP 2FA – Two-factor authentication for WordPress v2.0.0
1.7.1 2.0.0 2.0.1 2.1.0 2.2.0 2.2.1 2.3.0 2.4.0 2.4.1 2.4.2 2.5.0 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.8.0 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0 3.0.1 3.1.0 3.1.1 3.1.1.2 trunk 1.2.0 1.3.0 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.1 1.6.2 1.7.0
wp-2fa / includes / classes / Admin / SettingsPage.php
wp-2fa / includes / classes / Admin Last commit date
Controllers 4 years ago SettingsPages 4 years ago Views 4 years ago HelpContactUs.php 4 years ago PremiumFeatures.php 4 years ago SettingsPage.php 4 years ago SetupWizard.php 4 years ago User.php 4 years ago UserListing.php 4 years ago UserNotices.php 4 years ago UserProfile.php 4 years ago UserRegistered.php 4 years ago index.php 5 years ago
SettingsPage.php
652 lines
1 <?php // phpcs:ignore
2
3 namespace WP2FA\Admin;
4
5 use \WP2FA\WP2FA as WP2FA;
6 use WP2FA\Utils\UserUtils;
7 use WP2FA\Utils\SettingsUtils;
8 use WP2FA\Admin\Controllers\Settings;
9 use WP2FA\Admin\Views\Settings_Page_Render;
10 use WP2FA\Admin\SettingsPages\{
11 Settings_Page_Policies,
12 Settings_Page_General,
13 Settings_Page_White_Label,
14 Settings_Page_Email
15 };
16
17 /**
18 * SettingsPage - Class for handling settings
19 */
20 class SettingsPage {
21
22 const TOP_MENU_SLUG = 'wp-2fa-policies';
23
24 /**
25 * Holds the status of the backupcodes functionality
26 *
27 * @var bool[]
28 */
29 private static $backupCodesEnabled = array();
30
31 /**
32 * Create admin menu entry and settings page
33 */
34 public function create_settings_admin_menu() {
35 // Create admin menu item.
36 add_menu_page(
37 esc_html__( 'WP 2FA', 'wp-2fa' ),
38 esc_html__( 'WP 2FA', 'wp-2fa' ),
39 'manage_options',
40 self::TOP_MENU_SLUG,
41 null,
42 "data:image/svg+xml;base64,".base64_encode(file_get_contents(WP_2FA_PATH . 'dist/images/wp-2fa-white-icon20x28.svg')),
43 81
44 );
45
46 $settings_policies = new Settings_Page_Policies();
47 $settings_general = new Settings_Page_General();
48 $settings_white_label = new Settings_Page_White_Label();
49 $settings_email = new Settings_Page_Email();
50 $settings_render = new Settings_Page_Render();
51
52 add_submenu_page(
53 self::TOP_MENU_SLUG,
54 esc_html__( '2FA Policies', 'wp-2fa' ),
55 esc_html__( '2FA Policies', 'wp-2fa' ),
56 'manage_options',
57 self::TOP_MENU_SLUG,
58 array( $settings_policies, 'render' ),
59 1
60 );
61
62 add_submenu_page(
63 self::TOP_MENU_SLUG,
64 esc_html__( 'WP 2FA Settings', 'wp-2fa' ),
65 esc_html__( 'Settings', 'wp-2fa' ),
66 'manage_options',
67 'wp-2fa-settings',
68 array( $settings_render, 'render' ),
69 2
70 );
71
72 // Register our policy settings.
73 register_setting(
74 WP_2FA_POLICY_SETTINGS_NAME,
75 WP_2FA_POLICY_SETTINGS_NAME,
76 array( $settings_policies, 'validate_and_sanitize' )
77 );
78
79 // Register our white label settings.
80 register_setting(
81 WP_2FA_WHITE_LABEL_SETTINGS_NAME,
82 WP_2FA_WHITE_LABEL_SETTINGS_NAME,
83 array( $settings_white_label, 'validate_and_sanitize' )
84 );
85
86 // Register our settings page.
87 register_setting(
88 WP_2FA_SETTINGS_NAME,
89 WP_2FA_SETTINGS_NAME,
90 array( $settings_general, 'validate_and_sanitize' )
91 );
92
93 register_setting(
94 WP_2FA_EMAIL_SETTINGS_NAME,
95 WP_2FA_EMAIL_SETTINGS_NAME,
96 array( $settings_email, 'validate_and_sanitize' )
97 );
98
99 do_action( 'wp_2fa_after_admin_menu_created', self::TOP_MENU_SLUG, false);
100 }
101
102 /**
103 * Create admin menu entry and settings page
104 */
105 public function create_settings_admin_menu_multisite() {
106 // Create admin menu item.
107 add_menu_page(
108 esc_html__( 'WP 2FA Settings', 'wp-2fa' ),
109 esc_html__( 'WP 2FA', 'wp-2fa' ),
110 'manage_options',
111 self::TOP_MENU_SLUG,
112 null,
113 "data:image/svg+xml;base64,".base64_encode(file_get_contents(WP_2FA_PATH . 'dist/images/wp-2fa-white-icon20x28.svg')),
114 81
115 );
116
117 $settings_policies = new Settings_Page_Policies();
118 add_submenu_page(
119 self::TOP_MENU_SLUG,
120 esc_html__( '2FA Policies', 'wp-2fa' ),
121 esc_html__( '2FA Policies', 'wp-2fa' ),
122 'manage_options',
123 self::TOP_MENU_SLUG,
124 array( $settings_policies, 'render' ),
125 1
126 );
127
128 $settings_render = new Settings_Page_Render();
129 add_submenu_page(
130 self::TOP_MENU_SLUG,
131 esc_html__( 'WP 2FA Settings', 'wp-2fa' ),
132 esc_html__( 'Settings', 'wp-2fa' ),
133 'manage_options',
134 'wp-2fa-settings',
135 array( $settings_render, 'render' ),
136 2
137 );
138
139 do_action( 'wp_2fa_after_admin_menu_created', self::TOP_MENU_SLUG, true);
140 }
141
142 /**
143 * Get all users
144 */
145 public function get_all_users() {
146 // Die if user does not have permission to view.
147 if ( ! current_user_can( 'manage_options' ) ) {
148 die( 'Access Denied.' );
149 }
150 // Filter $_GET array for security.
151 $get_array = filter_input_array( INPUT_GET );
152
153 // Die if nonce verification failed.
154 if ( ! wp_verify_nonce( sanitize_text_field( $get_array['wp_2fa_nonce'] ), 'wp-2fa-settings-nonce' ) ) {
155 die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) );
156 }
157
158 $users_args = array(
159 'fields' => array( 'ID', 'user_login' ),
160 );
161 if ( WP2FA::is_this_multisite() ) {
162 $users_args['blog_id'] = 0;
163 }
164 $users_data = UserUtils::get_all_user_ids_and_login_names( 'query', $users_args );
165
166 // Create final array which we will fill in below.
167 $users = [];
168
169 foreach ( $users_data as $user ) {
170 if ( strpos( $user['user_login'], $get_array['term'] ) !== false ) {
171 array_push( $users, [
172 'value' => $user['user_login'],
173 'label' => $user['user_login']
174 ]);
175 }
176 }
177
178 echo wp_json_encode( $users );
179 exit;
180 }
181
182 /**
183 * Get all network sites
184 */
185 public function get_all_network_sites() {
186 // Die if user does not have permission to view.
187 if ( ! current_user_can( 'manage_options' ) ) {
188 die( 'Access Denied.' );
189 }
190 // Filter $_GET array for security.
191 $get_array = filter_input_array( INPUT_GET );
192 // Die if nonce verification failed.
193 if ( ! wp_verify_nonce( sanitize_text_field( $get_array['wp_2fa_nonce'] ), 'wp-2fa-settings-nonce' ) ) {
194 die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) );
195 }
196 // Fetch sites.
197 $sites_found = array();
198
199 foreach ( get_sites() as $site ) {
200 $subsite_id = get_object_vars( $site )['blog_id'];
201 $subsite_name = get_blog_details( $subsite_id )->blogname;
202 $site_details = '';
203 $site_details[ $subsite_id ] = $subsite_name;
204 if ( false !== stripos( $subsite_name, $get_array['term'] ) ) {
205 array_push( $sites_found, [
206 'label' => $subsite_id,
207 'value' => $subsite_name
208 ]);
209 }
210 }
211 echo wp_json_encode( $sites_found );
212 exit;
213 }
214
215 /**
216 * Unlock users accounts if they have overrun grace period
217 *
218 * @param int $user_id User ID.
219 */
220 public function unlock_account( $user_id ) {
221 // Die if user does not have permission to view.
222 if ( ! current_user_can( 'manage_options' ) ) {
223 die( 'Access Denied.' );
224 }
225
226 $grace_period = WP2FA::get_wp2fa_setting( 'grace-period' );
227 $grace_period_denominator = WP2FA::get_wp2fa_setting( 'grace-period-denominator' );
228 $create_a_string = $grace_period . ' ' . $grace_period_denominator;
229 // Turn that string into a time.
230 $grace_expiry = strtotime( $create_a_string );
231
232 // Filter $_GET array for security.
233 $get_array = filter_input_array( INPUT_GET );
234 $nonce = sanitize_text_field( $get_array['wp_2fa_nonce'] );
235
236 // Die if nonce verification failed.
237 if ( ! wp_verify_nonce( $nonce, 'wp-2fa-unlock-account-nonce' ) ) {
238 die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) );
239 }
240
241 if ( isset( $get_array['user_id'] ) ) {
242 global $wpdb;
243 $wpdb->query(
244 $wpdb->prepare(
245 "
246 DELETE FROM $wpdb->usermeta
247 WHERE user_id = %d
248 AND meta_key IN ( %s, %s )
249 ",
250 [
251 intval( $get_array['user_id'] ),
252 WP_2FA_PREFIX . 'user_grace_period_expired',
253 WP_2FA_PREFIX . 'locked_account_notification',
254 ]
255 )
256 );
257 update_user_meta( intval( $get_array['user_id'] ), WP_2FA_PREFIX . 'grace_period_expiry', $grace_expiry );
258 $this->send_account_unlocked_email( intval( $get_array['user_id'] ) );
259 add_action( 'admin_notices', array( $this, 'user_unlocked_notice' ) );
260 }
261 }
262
263 /**
264 * Remove user 2fa config
265 *
266 * @param int $user_id User ID.
267 */
268 public function remove_user_2fa( $user_id ) {
269 // Filter $_GET array for security.
270 $get_array = filter_input_array( INPUT_GET );
271 $nonce = sanitize_text_field( $get_array['wp_2fa_nonce'] );
272
273 if ( ! wp_verify_nonce( $nonce, 'wp-2fa-remove-user-2fa-nonce' ) ) {
274 die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) );
275 }
276
277 if ( isset( $get_array['user_id'] ) ) {
278 $user_id = intval( $get_array['user_id'] );
279 global $wpdb;
280 $wpdb->query(
281 $wpdb->prepare(
282 "DELETE FROM $wpdb->usermeta
283 WHERE user_id = %d
284 AND meta_key LIKE %s",
285 [
286 $user_id,
287 'wp_2fa_%'
288 ]
289 )
290 );
291
292 $is_needed = User::is_enforced( $user_id );
293
294 if ( $is_needed ) {
295 if ( 'do-not-enforce' !== WP2FA::get_wp2fa_setting( 'enforcement-policy' ) ) {
296 // Turn inputs into a useable string.
297 $create_a_string = WP2FA::get_wp2fa_setting( 'grace-period' ) . ' ' . WP2FA::get_wp2fa_setting( 'grace-period-denominator' );
298 // Turn that string into a time.
299 $grace_expiry = strtotime( $create_a_string );
300 update_user_meta( $user_id, WP_2FA_PREFIX . 'grace_period_expiry', $grace_expiry );
301 update_user_meta( $user_id, WP_2FA_PREFIX . 'update_nag_dismissed', true );
302 }
303 $grace_policy = WP2FA::get_wp2fa_setting( 'grace-policy' );
304 if ( 'no-grace-period' === $grace_policy ) {
305 update_user_meta( $user_id, WP_2FA_PREFIX . 'user_enforced_instantly', true );
306 // Set this to a known older value so its already expired.
307 update_user_meta( $user_id, WP_2FA_PREFIX . 'grace_period_expiry', '1609502400' );
308 // Get sessions for user with ID $user_id.
309 $sessions = \WP_Session_Tokens::get_instance( $user_id );
310 // Log them out.
311 $sessions->destroy_all();
312 }
313 }
314 if ( isset( $get_array['admin_reset'] ) ) {
315 add_action( 'admin_notices', array( $this, 'admin_deleted_2fa_notice' ) );
316 } else {
317 add_action( 'admin_notices', array( $this, 'user_deleted_2fa_notice' ) );
318 }
319 }
320 }
321
322 /**
323 * Send account unlocked notification via email.
324 *
325 * @param int $user_id user ID.
326 *
327 * @return boolean
328 */
329 public static function send_account_unlocked_email( $user_id ) {
330 // Bail if the user has not enabled this email.
331 if ( 'enable_account_unlocked_email' !== WP2FA::get_wp2fa_email_templates( 'send_account_unlocked_email' ) ) {
332 return false;
333 }
334
335 // Grab user data.
336 $user = get_userdata( $user_id );
337 // Grab user email.
338 $email = $user->user_email;
339 // Setup the email contents.
340 $subject = wp_strip_all_tags( WP2FA::replace_email_strings( WP2FA::get_wp2fa_email_templates( 'user_account_unlocked_email_subject' ) ) );
341 $message = wpautop( WP2FA::replace_email_strings( WP2FA::get_wp2fa_email_templates( 'user_account_unlocked_email_body' ), $user_id ) );
342
343 self::send_email($email, $subject, $message);
344 }
345
346 /**
347 * Hide settings menu item
348 */
349 public function hide_settings() {
350 $user = wp_get_current_user();
351
352 // Check we have a user before doing anything else.
353 if ( is_a( $user, '\WP_User' ) ) {
354 $user_id = (int) $user->ID;
355 if ( ! empty( WP2FA::get_wp2fa_setting( '2fa_settings_last_updated_by' ) ) ) {
356 $main_user = (int) WP2FA::get_wp2fa_setting( '2fa_settings_last_updated_by' );
357 } else {
358 $main_user = '';
359 }
360 if ( ! empty( WP2FA::get_wp2fa_general_setting( 'limit_access' ) ) && $user->ID !== $main_user ) {
361 // Remove admin menu item.
362 remove_submenu_page( 'options-general.php', 'wp-2fa-policies' );
363 }
364 }
365 }
366
367 /**
368 * Add unlock user link to user actions.
369 *
370 * @param array $links Default row content.
371 *
372 * @return array
373 * @throws \Freemius_Exception
374 */
375 public function add_plugin_action_links( $links ) {
376 // add link to the external free trial page in free version and also in premium version if license is not active.
377 if ( ! function_exists( 'wp2fa_freemius' ) || ! wp2fa_freemius()->has_active_valid_license() ) {
378 $trial_link = 'https://wp2fa.io/get-wp-2fa-premium-trial/?utm_source=plugin&utm_medium=referral&utm_campaign=WP2FA';
379 $links = array_merge(
380 array(
381 '<a style="font-weight:bold" href="' . $trial_link . '" target="_blank">' . __( 'Free 14-day Premium Trial', 'wp-2fa' ) . '</a>',
382 ),
383 $links
384 );
385 }
386
387 // add link to the plugin settings page.
388 $url = Settings::get_settings_page_link();
389 $links = array_merge(
390 array(
391 '<a href="' . esc_url( $url ) . '">' . esc_html__( 'Configure 2FA Settings', 'wp-2fa' ) . '</a>',
392 ),
393 $links
394 );
395
396 return $links;
397 }
398
399 /**
400 * User unlocked notice.
401 */
402 public function user_unlocked_notice() {
403 ?>
404 <div class="notice notice-success is-dismissible">
405 <p><?php esc_html_e( 'User account successfully unlocked. User can login again.', 'wp-2fa' ); ?></p>
406 <button type="button" class="notice-dismiss">
407 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
408 </button>
409 </div>
410 <?php
411 }
412
413 /**
414 * User deleted 2FA settings notification
415 */
416 public function user_deleted_2fa_notice() {
417 ?>
418 <div class="notice notice-success is-dismissible">
419 <p><?php esc_html_e( 'Your 2FA settings have been removed.', 'wp-2fa' ); ?></p>
420 <button type="button" class="notice-dismiss">
421 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
422 </button>
423 </div>
424 <?php
425 }
426
427 /**
428 * Admin deleted user 2FA settings notification
429 */
430 public function admin_deleted_2fa_notice() {
431 ?>
432 <div class="notice notice-success is-dismissible">
433 <p><?php esc_html_e( 'User 2FA settings have been removed.', 'wp-2fa' ); ?></p>
434 <button type="button" class="notice-dismiss">
435 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
436 </button>
437 </div>
438 <?php
439 }
440
441 public function update_wp2fa_network_options() {
442
443 $settings_policies = new Settings_Page_Policies();
444
445 $settings_policies->update_wp2fa_network_options();
446
447 $settings_general = new Settings_Page_General();
448
449 $settings_general->update_wp2fa_network_options();
450
451 $settings_white_label = new Settings_Page_White_Label();
452
453 $settings_white_label->update_wp2fa_network_options();
454 }
455
456 /**
457 * Handle saving email options to the network main site options.
458 */
459 public function update_wp2fa_network_email_options() {
460 $settings_email = new Settings_Page_Email();
461
462 $settings_email->update_wp2fa_network_options();
463 }
464
465 /**
466 * These are used instead of add_settings_error which in a network site. Used to show if settings have been updated or failed.
467 */
468 public function settings_saved_network_admin_notice() {
469 if ( isset( $_GET['wp_2fa_network_settings_updated'] ) && $_GET['wp_2fa_network_settings_updated'] == 'true' ) :
470 ?>
471 <div class="notice notice-success is-dismissible">
472 <p><?php esc_html_e( '2FA Settings Updated', 'wp-2fa' ); ?></p>
473 <button type="button" class="notice-dismiss">
474 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
475 </button>
476 </div>
477 <?php
478 endif;
479 if ( isset( $_GET['wp_2fa_network_settings_updated'] ) && $_GET['wp_2fa_network_settings_updated'] == 'false' ) :
480 ?>
481 <div class="notice notice-error is-dismissible">
482 <p><?php esc_html_e( 'Please ensure both custom email address and display name are provided.', 'wp-2fa' ); ?></p>
483 <button type="button" class="notice-dismiss">
484 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
485 </button>
486 </div>
487 <?php
488 endif;
489 if ( isset( $_GET['wp_2fa_network_settings_error'] ) ) :
490 ?>
491 <div class="notice notice-error is-dismissible">
492 <p><?php echo urldecode_deep( $_GET['wp_2fa_network_settings_error'] ); ?></p>
493 <button type="button" class="notice-dismiss">
494 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
495 </button>
496 </div>
497 <?php
498 endif;
499 }
500
501 /**
502 * These are used instead of add_settings_error which in a network site. Used to show if settings have been updated or failed.
503 *
504 * @return void
505 *
506 * @since 2.0.0
507 */
508 public function settings_saved_admin_notice() {
509 if ( isset( $_GET['settings-updated'] ) && 'true' === $_GET['settings-updated'] ) :
510 $wp_settings_errors = get_settings_errors();
511
512 if ( count( $wp_settings_errors ) ) {
513 foreach ( $wp_settings_errors as $error ) {
514 ?>
515 <div class="notice notice-<?php echo \esc_attr( $error['type'] ); ?> is-dismissible">
516 <p><?php echo \esc_html( $error['message'] ); ?></p>
517 <button type="button" class="notice-dismiss">
518 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
519 </button>
520 </div>
521 <?php
522 }
523 } else {
524 ?>
525 <div class="notice notice-success is-dismissible">
526 <p><?php esc_html_e( '2FA Settings Updated', 'wp-2fa' ); ?></p>
527 <button type="button" class="notice-dismiss">
528 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
529 </button>
530 </div>
531 <?php
532 }
533 endif;
534 if ( isset( $_GET['settings-updated'] ) && 'false' === $_GET['settings-updated'] ) :
535 ?>
536 <div class="notice notice-error is-dismissible">
537 <p><?php esc_html_e( 'Please ensure both custom email address and display name are provided.', 'wp-2fa' ); ?></p>
538 <button type="button" class="notice-dismiss">
539 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
540 </button>
541 </div>
542 <?php
543 endif;
544 if ( isset( $_GET['settings_error'] ) ) :
545 ?>
546 <div class="notice notice-error is-dismissible">
547 <p><?php echo urldecode_deep( $_GET['settings_error'] ); ?></p>
548 <button type="button" class="notice-dismiss">
549 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
550 </button>
551 </div>
552 <?php
553 endif;
554 }
555
556 /**
557 * Add our custom state to our created page.
558 */
559 public function add_display_post_states( $post_states, $post ) {
560 if ( ! empty( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) ) ) {
561 if ( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) === $post->ID ) {
562 $post_states['wp_2fa_page_for_user'] = __( 'WP 2FA User Page', 'wp-2fa' );
563 }
564 }
565
566 return $post_states;
567 }
568
569 /**
570 * Handles sending of an email. It sets necessary header such as content type and custom from email address and name.
571 *
572 * @param string $recipient_email Email address to send message to.
573 * @param string $subject Email subject.
574 * @param string $message Message contents.
575 *
576 * @return bool Whether the email contents were sent successfully.
577 */
578 public static function send_email( $recipient_email, $subject, $message ) {
579
580 // Specify our desired headers.
581 $headers = 'Content-type: text/html;charset=utf-8' . "\r\n";
582
583 if ( 'use-custom-email' === WP2FA::get_wp2fa_email_templates( 'email_from_setting' ) ) {
584 $headers .= 'From: ' . WP2FA::get_wp2fa_email_templates( 'custom_from_display_name' ) . ' <' . WP2FA::get_wp2fa_email_templates( 'custom_from_email_address' ) . '>' . "\r\n";
585 } else {
586 $headers .= 'From: ' . get_bloginfo( 'name' ) . ' <' . get_bloginfo('admin_email') . '>' . "\r\n";
587 }
588
589 // Fire our email.
590 return wp_mail( $recipient_email, $subject, $message, $headers );
591
592 }
593
594 /**
595 * Turns user roles data in any form and shape to an array of strings.
596 *
597 * @param mixed $value User role names (slugs) as raw value.
598 *
599 * @return string[] List of user role names (slugs).
600 */
601 public static function extract_roles_from_input( $value ) {
602 if ( is_array( $value ) ) {
603 return $value;
604 }
605
606 if ( is_string( $value ) && ! empty( $value ) ) {
607 return explode( ',', $value );
608 }
609
610 return [];
611 }
612
613 /**
614 * Determine if any BG processes are currently running.
615 *
616 * @return int|false Number of jobs.
617 */
618 public function get_current_number_of_active_bg_processes() {
619 global $wpdb;
620
621 $bg_jobs = $wpdb->get_results(
622 "SELECT option_value FROM $wpdb->options
623 WHERE option_name LIKE '%_2fa_bg_%'"
624 );
625
626 return count( $bg_jobs );
627 }
628
629 /**
630 * Checks if the backup codes option is globally enabled
631 *
632 * @param string $role - The role name.
633 *
634 * @return bool
635 */
636 public static function are_backup_codes_enabled( string $role = 'global' ) {
637
638 if ( ! isset( self::$backupCodesEnabled[ $role ] ) ) {
639 self::$backupCodesEnabled[ $role ] = false;
640
641 if ( 'global' === $role ) {
642 $setting_value = Settings::get_role_or_default_setting( 'backup_codes_enabled' );
643 } else {
644 $setting_value = Settings::get_role_or_default_setting( 'backup_codes_enabled', 'current', $role );
645 }
646 self::$backupCodesEnabled[ $role ] = SettingsUtils::string_to_bool( $setting_value );
647 }
648
649 return self::$backupCodesEnabled[ $role ];
650 }
651 }
652