PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.2.1
WP 2FA – Two-factor authentication for WordPress v2.2.1
4.1.0 4.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 / class-setup-wizard.php
wp-2fa / includes / classes / Admin Last commit date
Controllers 4 years ago Helpers 4 years ago SettingsPages 4 years ago Views 4 years ago class-help-contact-us.php 4 years ago class-premium-features.php 4 years ago class-settings-page.php 4 years ago class-settingspage.php 4 years ago class-setup-wizard.php 4 years ago class-user-listing.php 4 years ago class-user-notices.php 4 years ago class-user-profile.php 4 years ago class-user-registered.php 4 years ago class-user.php 4 years ago index.php 5 years ago
class-setup-wizard.php
652 lines
1 <?php
2 /**
3 * Setup wizard rendering class.
4 *
5 * @package wp2fa
6 * @subpackage setup
7 * @copyright 2021 WP White Security
8 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
9 * @link https://wordpress.org/plugins/wp-2fa/
10 */
11
12 namespace WP2FA\Admin;
13
14 use \WP2FA\WP2FA as WP2FA;
15 use \WP2FA\Utils\User_Utils as User_Utils;
16 use \WP2FA\Utils\Generate_Modal as Generate_Modal;
17 use \WP2FA\Core as Core;
18 use \WP2FA\Authenticator\Authentication as Authentication;
19 use \WP2FA\Admin\Settings_Page as Settings_Page;
20 use WP2FA\Utils\Settings_Utils as Settings_Utils;
21 use WP2FA\Admin\Views\Wizard_Steps;
22 use WP2FA\Admin\Views\First_Time_Wizard_Steps;
23 use WP2FA\Admin\SettingsPages\Settings_Page_Policies;
24 use WP2FA\Admin\Helpers\WP_Helper;
25 use WP2FA\Admin\Helpers\User_Helper;
26 use WP2FA\Admin\Controllers\Settings;
27
28 /**
29 * Our class for creating a step by step wizard for easy configuration.
30 */
31 class Setup_Wizard {
32
33 /**
34 * Wizard Steps
35 *
36 * @var array
37 */
38 private $wizard_steps;
39
40 /**
41 * Current Step
42 *
43 * @var string
44 */
45 private $current_step;
46
47 /**
48 * Method: Constructor.
49 */
50 public function __construct() { }
51
52 /**
53 * Add setup admin page. This is empty on purpose.
54 */
55 public function admin_menus() {
56 add_dashboard_page( '', '', 'read', 'wp-2fa-setup', '' );
57 }
58
59 /**
60 * Adding menus for multisite install
61 *
62 * @return void
63 *
64 * @since 2.2.0
65 */
66 public function network_admin_menus() {
67 add_dashboard_page( 'index.php', '', 'read', 'wp-2fa-setup', '' );
68 }
69
70 /**
71 * Setup Page Start.
72 *
73 * @SuppressWarnings(PHPMD.ExitExpression)
74 */
75 public function setup_page() {
76
77 // Get page argument from $_GET array.
78 $page = ( isset( $_GET['page'] ) ) ? \sanitize_text_field( \wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore
79 if ( empty( $page ) || 'wp-2fa-setup' !== $page ) {
80 return;
81 }
82
83 // Clear out any old notices.
84 $user = wp_get_current_user();
85
86 // First lets check if any options have been saved.
87 $settings_saved = true;
88 $settings = WP2FA::get_wp2fa_setting();
89 if ( empty( $settings ) || ! isset( $settings ) ) {
90 $settings_saved = false;
91 }
92
93 /**
94 * Wizard Steps.
95 */
96 $get_array = filter_input_array( INPUT_GET );
97 if ( isset( $get_array['wizard_type'] ) ) {
98 $wizard_type = sanitize_text_field( $get_array['wizard_type'] );
99 } else {
100 $wizard_type = 'default';
101 }
102
103 $is_user_forced_to_setup = User_Helper::get_user_enforced_instantly( $user );
104 if ( ! empty( $is_user_forced_to_setup ) ) {
105 add_filter( 'wp_2fa_wizard_default_steps', array( $this, 'wp_2fa_add_intro_step' ) );
106 }
107
108 $user_type = User_Utils::determine_user_2fa_status( $user );
109
110 $wizard_steps = array(
111 'welcome' => array(
112 'name' => esc_html__( 'Welcome', 'wp-2fa' ),
113 'content' => array( $this, 'wp_2fa_step_welcome' ),
114 'wizard_type' => 'welcome_wizard',
115 ),
116 'settings_configuration' => array(
117 'name' => esc_html__( 'Select 2FA Methods', 'wp-2fa' ),
118 'content' => array( $this, 'wp_2fa_step_global_2fa_methods' ),
119 'save' => array( $this, 'wp_2fa_step_global_2fa_methods_save' ),
120 'wizard_type' => 'welcome_wizard',
121 ),
122 'finish' => array(
123 'name' => esc_html__( 'Setup Finish', 'wp-2fa' ),
124 'content' => array( $this, 'wp_2fa_step_finish' ),
125 'save' => array( $this, 'wp_2fa_step_finish_save' ),
126 'wizard_type' => 'welcome_wizard',
127 ),
128 );
129
130 // Admin user setting up fresh install of 2FA plugin.
131 if ( in_array( 'can_manage_options', $user_type, true ) && ! $settings_saved ) {
132 unset( $wizard_steps['user_choose_2fa_method'] );
133 unset( $wizard_steps['reconfigure_method'] );
134 }
135
136 // We will use this setting to determine if defaults have already been saved to the DB.
137 $have_defaults_been_applied = Settings_Utils::get_option( 'default_settings_applied', false );
138 // If we have settings, but they are the defaults, then we want to consider the settings to be unsaved at this point.
139 if ( in_array( 'can_manage_options', $user_type, true ) && $settings_saved && $have_defaults_been_applied ) {
140 $settings_saved = false;
141 }
142
143 // Ensure user has minimum capabitlies needed to be here.
144 if ( in_array( 'can_read', $user_type, true ) && $settings_saved ) {
145
146 switch ( $wizard_type ) {
147 case 'user_2fa_config':
148 $wizard_steps = array_intersect_key( $wizard_steps, array_flip( array( 'user_choose_2fa_method', 'setup_method', 'finish', 'backup_codes' ) ) );
149 break;
150
151 case 'backup_codes_config':
152 $wizard_steps = array_intersect_key( $wizard_steps, array_flip( array( 'backup_codes' ) ) );
153 break;
154
155 case 'user_reconfigure_config':
156 $wizard_steps = array_intersect_key( $wizard_steps, array_flip( array( 'reconfigure_method' ) ) );
157 break;
158
159 default:
160 $wizard_steps = array_intersect_key( $wizard_steps, array_flip( array( 'choose_2fa_method', 'setup_method', 'finish', 'backup_codes', 'reconfigure_method' ) ) );
161 }
162
163 // Remove 1st step if only one method is available.
164 if ( empty( WP2FA::get_wp2fa_setting( 'enable_totp' ) ) || empty( WP2FA::get_wp2fa_setting( 'enable_email' ) ) ) {
165 unset( $wizard_steps['choose_2fa_method'] );
166 }
167
168 // If the user has codes setup already, no need to add the slide.
169 if ( ! in_array( 'user_needs_to_setup_backup_codes', $user_type, true ) && 'backup_codes_config' !== $wizard_type ) {
170 unset( $wizard_steps['backup_codes'] );
171 }
172 }
173
174 /**
175 * Filter: `Wizard Default Steps`
176 *
177 * WSAL filter to filter wizard steps before they are displayed.
178 *
179 * @param array $wizard_steps – Wizard Steps.
180 */
181 $this->wizard_steps = apply_filters( WP_2FA_PREFIX . 'wizard_default_steps', $wizard_steps );
182
183 // Set current step.
184 $current_step = ( isset( $_GET['current-step'] ) ) ? \sanitize_text_field( \wp_unslash( $_GET['current-step'] ) ) : ''; // phpcs:ignore
185 $this->current_step = ! empty( $current_step ) ? $current_step : current( array_keys( $this->wizard_steps ) );
186
187 if ( 'backup_codes' === $this->current_step && ! Settings_Page::are_backup_codes_enabled( User_Helper::get_user_role( $user ) ) ) {
188
189 $redirect_to_finish = add_query_arg(
190 array(
191 'current-step' => 'finish',
192 'all-set' => 1,
193 )
194 );
195 wp_safe_redirect( esc_url_raw( $redirect_to_finish ) );
196 }
197
198 /**
199 * Enqueue Scripts.
200 */
201 wp_enqueue_style(
202 'wp_2fa_setup_wizard',
203 Core\style_url( 'setup-wizard', 'admin' ),
204 array( 'select2' ),
205 WP_2FA_VERSION
206 );
207
208 wp_enqueue_style(
209 'wp_2fa_admin-style',
210 Core\style_url( 'admin-style', 'admin' ),
211 array(),
212 WP_2FA_VERSION
213 );
214
215 \WP2FA\Core\enqueue_select2_scripts();
216
217 if ( \WP2FA\Admin\Helpers\WP_Helper::is_multisite() ) {
218 \WP2FA\Core\enqueue_multi_select_scripts();
219 }
220
221 wp_enqueue_script(
222 'wp_2fa_admin',
223 Core\script_url( 'admin', 'admin' ),
224 array( 'jquery-ui-widget', 'jquery-ui-core', 'jquery-ui-autocomplete', 'select2' ),
225 WP_2FA_VERSION,
226 true
227 );
228
229 wp_enqueue_script(
230 'wp_2fa_micromodal',
231 Core\script_url( 'micromodal', 'admin', 'select2' ),
232 array(),
233 WP_2FA_VERSION,
234 true
235 );
236
237 // Data array.
238 $data_array = array(
239 'ajaxURL' => admin_url( 'admin-ajax.php' ),
240 'roles' => WP2FA::wp_2fa_get_roles(),
241 'nonce' => wp_create_nonce( 'wp-2fa-settings-nonce' ),
242 'invalidEmail' => esc_html__( 'Please use a valid email address', 'wp-2fa' ),
243 );
244 wp_localize_script( 'wp_2fa_admin', 'wp2faData', $data_array );
245
246 // Data array.
247 $data_array = array(
248 'ajaxURL' => admin_url( 'admin-ajax.php' ),
249 'nonce' => wp_create_nonce( 'wp2fa-verify-wizard-page' ),
250 'codesPreamble' => esc_html__( 'These are the 2FA backup codes for the user', 'wp-2fa' ),
251 'readyText' => esc_html__( 'I\'m ready', 'wp-2fa' ),
252 'codeReSentText' => esc_html__( 'New code sent', 'wp-2fa' ),
253 );
254
255 /**
256 * Gives the ability to change the default JS wizard settings.
257 *
258 * @param int $data_array - The array with all the JS wizard settings.
259 *
260 * @since 2.2.0
261 */
262 $data_array = apply_filters( WP_2FA_PREFIX . 'js_wizard_settings', $data_array );
263 wp_localize_script( 'wp_2fa_admin', 'wp2faWizardData', $data_array );
264
265 /**
266 * Save Wizard Settings.
267 */
268 $save_step = ( isset( $_POST['save_step'] ) ) ? \sanitize_text_field( \wp_unslash( $_POST['save_step'] ) ) : ''; // phpcs:ignore
269 if ( ! empty( $save_step ) && ! empty( $this->wizard_steps[ $this->current_step ]['save'] ) ) {
270 call_user_func( $this->wizard_steps[ $this->current_step ]['save'] );
271 }
272
273 $this->setup_page_header();
274 $this->setup_page_steps();
275 $this->setup_page_content();
276 $this->setup_page_footer();
277
278 exit();
279 }
280
281 /**
282 * Setup Page Header.
283 */
284 private function setup_page_header() {
285 ?>
286 <!DOCTYPE html>
287 <html <?php language_attributes(); ?>>
288 <head>
289 <meta name="viewport" content="width=device-width" />
290 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
291 <title><?php esc_html_e( 'WP 2FA &rsaquo; Setup Wizard', 'wp-2fa' ); ?></title>
292 <?php wp_print_scripts( 'jquery' ); ?>
293 <?php wp_print_scripts( 'jquery-ui-core' ); ?>
294 <?php wp_print_scripts( 'wp_2fa_setup_wizard' ); ?>
295 <?php wp_print_scripts( 'wp_2fa_micromodal' ); ?>
296 <?php wp_print_scripts( 'wp_2fa_admin' ); ?>
297 <?php wp_print_scripts( 'multi-site-select' ); ?>
298 <?php
299 /**
300 * Gives the ability for 3rd party scripts to add their own JS to the plugin setup page.
301 *
302 * @since 2.2.0
303 */
304 \do_action( WP_2FA_PREFIX . 'setup_page_scripts' );
305 ?>
306 <?php wp_print_styles( 'common' ); ?>
307 <?php wp_print_styles( 'forms' ); ?>
308 <?php wp_print_styles( 'buttons' ); ?>
309 <?php wp_print_styles( 'wp-jquery-ui-dialog' ); ?>
310 <?php wp_print_styles( 'wp_2fa_admin' ); ?>
311 <?php do_action( 'admin_print_styles' ); ?>
312 </head>
313 <body class="wp2fa-setup wp-core-ui">
314 <div class="setup-wizard-wrapper wp-2fa-settings-wrapper wp2fa-form-styles">
315 <h1 id="wp2fa-logo"><a href="https://wpsecurityauditlog.com" target="_blank"><img src="<?php echo esc_url( WP_2FA_URL . 'dist/images/wizard-logo.png' ); ?>"></a></h1>
316 <?php
317 }
318
319 /**
320 * Setup Page Footer.
321 */
322 private function setup_page_footer() {
323 $user = wp_get_current_user();
324
325 $redirect = Settings::get_settings_page_link();
326 ?>
327 <div class="wp2fa-setup-footer">
328 <?php if ( 'welcome' !== $this->current_step && 'finish' !== $this->current_step ) { // Don't show the link on the first & last step. ?>
329 <?php if ( ! User_Helper::get_user_enforced_instantly( $user ) ) { ?>
330 <a class="close-wizard-link" href="<?php echo esc_url( $redirect ); ?>"><?php esc_html_e( 'Close Wizard', 'wp-2fa' ); ?></a>
331 <?php
332 }
333 }
334 ?>
335 </div>
336 </div>
337 </body>
338 </html>
339 <?php
340 // phpcs:ignore
341 echo Generate_Modal::generate_modal(
342 'notify-admin-settings-page',
343 '',
344 __( 'If you cancel this wizard, the default plugin settings will be applied. You can always configure the plugin settings and two-factor authentication policies at a later stage from the ', 'wp-2fa' ) . ' <b>' . __( 'WP 2FA', 'wp-2fa' ) . '</b>' . __( ' entry in your WordPress dashboard menu.', 'wp-2fa' ),
345 array(
346 '<a href="#" id="close-settings" class="modal__btn modal__btn-primary button-primary" data-redirect-url="' . esc_url( $redirect ) . '">' . __( 'OK, close wizard', 'wp-2fa' ) . '</a>',
347 '<a href="#" class="modal__btn modal__btn-primary button-secondary" data-close-2fa-modal>' . __( 'Continue with wizard', 'wp-2fa' ) . '</a>',
348 ),
349 '',
350 '450px'
351 );
352 ?>
353 <?php
354 }
355
356 /**
357 * Setup Page Steps.
358 */
359 private function setup_page_steps() {
360 ?>
361 <ul class="steps">
362 <?php
363 foreach ( $this->wizard_steps as $key => $step ) :
364 if ( 'welcome_wizard' === $step['wizard_type'] || is_array( $step['wizard_type'] ) && in_array( 'welcome_wizard', $step['wizard_type'], true ) ) :
365 if ( $key === $this->current_step ) :
366 ?>
367 <li class="is-active"><?php echo esc_html( $step['name'] ); ?></li>
368 <?php
369 else :
370 ?>
371 <li><?php echo esc_html( $step['name'] ); ?></li>
372 <?php
373 endif;
374 endif;
375 endforeach;
376 ?>
377 </ul>
378 <?php
379 }
380
381 /**
382 * Get Next Step URL.
383 *
384 * @return string
385 */
386 private function get_next_step() {
387 // Get current step.
388 $current_step = $this->current_step;
389
390 // Array of step keys.
391 $keys = array_keys( $this->wizard_steps );
392 if ( end( $keys ) === $current_step ) { // If last step is active then return WP Admin URL.
393 return admin_url();
394 }
395
396 // Search for step index in step keys.
397 $step_index = array_search( $current_step, $keys, true );
398 if ( false === $step_index ) { // If index is not found then return empty string.
399 return '';
400 }
401
402 // Return next step.
403 return add_query_arg( 'current-step', $keys[ $step_index + 1 ] );
404 }
405
406 /**
407 * Setup Page Content.
408 */
409 private function setup_page_content() {
410 ?>
411 <div class="wp2fa-setup-content">
412 <?php
413 if ( ! empty( $this->wizard_steps[ $this->current_step ]['content'] ) ) {
414 call_user_func( $this->wizard_steps[ $this->current_step ]['content'] );
415 }
416 ?>
417 </div>
418 <?php
419 }
420
421 /**
422 * Step View: `Welcome`
423 */
424 private function wp_2fa_step_welcome() {
425 Wizard_Steps::welcome_step( $this->get_next_step() );
426 }
427
428 /**
429 * Step View: `Finish`
430 */
431 private function wp_2fa_step_finish() {
432 $wp2fa_user = User::get_instance();
433 User_Helper::remove_user_needs_to_reconfigure_2fa( $wp2fa_user->get_2fa_wp_user() );
434 Wizard_Steps::congratulations_step( true );
435 }
436
437 /**
438 * Step Save: `Finish`
439 *
440 * @SuppressWarnings(PHPMD.ExitExpression)
441 */
442 private function wp_2fa_step_finish_save() {
443 // Verify nonce.
444 check_admin_referer( 'wp2fa-step-finish' );
445 wp_safe_redirect( esc_url_raw( $this->get_next_step() ) );
446 exit();
447 }
448
449 /**
450 * Step View: `Choose Methods`
451 */
452 private function wp_2fa_step_global_2fa_methods() {
453 ?>
454 <form method="post" class="wp2fa-setup-form wp2fa-form-styles" autocomplete="off">
455 <?php wp_nonce_field( 'wp2fa-step-choose-method' ); ?>
456 <div class="step-setting-wrapper active" data-step-title="<?php esc_html_e( 'Choose 2FA methods', 'wp-2fa' ); ?>">
457 <?php First_Time_Wizard_Steps::select_method( true ); ?>
458 <div class="wp2fa-setup-actions">
459 <a class="button button-primary" name="next_step_setting" value="<?php esc_attr_e( 'Continue Setup', 'wp-2fa' ); ?>"><?php esc_html_e( 'Continue Setup', 'wp-2fa' ); ?></a>
460 </div>
461 </div>
462 <div class="step-setting-wrapper" data-step-title="<?php esc_html_e( '2FA policy', 'wp-2fa' ); ?>">
463 <?php First_Time_Wizard_Steps::enforcement_policy( true ); ?>
464 <div class="wp2fa-setup-actions">
465 <a class="button button-primary" name="next_step_setting" value="<?php esc_attr_e( 'Continue Setup', 'wp-2fa' ); ?>"><?php esc_html_e( 'Continue Setup', 'wp-2fa' ); ?></a>
466 </div>
467 </div>
468 <div class="step-setting-wrapper hidden" data-step-title="<?php esc_html_e( 'Exclude users', 'wp-2fa' ); ?>">
469 <?php First_Time_Wizard_Steps::exclude_users( true ); ?>
470 <div class="wp2fa-setup-actions">
471 <a class="button button-primary" name="next_step_setting" value="<?php esc_attr_e( 'Continue Setup', 'wp-2fa' ); ?>"><?php esc_html_e( 'Continue Setup', 'wp-2fa' ); ?></a>
472 </div>
473 </div>
474
475 <?php if ( WP_Helper::is_multisite() ) : ?>
476 <div class="step-setting-wrapper" data-step-title="<?php esc_html_e( 'Exclude sites', 'wp-2fa' ); ?>">
477 <?php First_Time_Wizard_Steps::excluded_network_sites( true ); ?>
478 <div class="wp2fa-setup-actions">
479 <a class="button button-primary" name="next_step_setting" value="<?php esc_attr_e( 'Continue Setup', 'wp-2fa' ); ?>"><?php esc_html_e( 'Continue Setup', 'wp-2fa' ); ?></a>
480 </div>
481 </div>
482 <?php endif; ?>
483
484 <div class="step-setting-wrapper" data-step-title="<?php esc_html_e( 'Grace period', 'wp-2fa' ); ?>">
485 <h3><?php esc_html_e( 'How long should the grace period for your users be?', 'wp-2fa' ); ?></h3>
486 <p class="description"><?php esc_html_e( 'When you configure the 2FA policies and require users to configure 2FA, they can either have a grace period to configure 2FA, or can be required to configure 2FA before the next time they login. Choose which method you\'d like to use:', 'wp-2fa' ); ?></p>
487 <?php First_Time_Wizard_Steps::grace_period( true ); ?>
488 <div class="wp2fa-setup-actions">
489 <button class="button button-primary save-wizard" type="submit" name="save_step" value="<?php esc_attr_e( 'All done', 'wp-2fa' ); ?>"><?php esc_html_e( 'All done', 'wp-2fa' ); ?></button>
490 </div>
491 </div>
492
493 </form>
494 <?php
495 }
496
497 /**
498 * Step Save: `Choose Method`
499 *
500 * @SuppressWarnings(PHPMD.ExitExpression)
501 */
502 private function wp_2fa_step_global_2fa_methods_save() {
503 // Check nonce.
504 check_admin_referer( 'wp2fa-step-choose-method' );
505
506 $input = ( isset( $_POST[ WP_2FA_POLICY_SETTINGS_NAME ] ) ) ? wp_unslash( $_POST[ WP_2FA_POLICY_SETTINGS_NAME ] ) : array(); // phpcs:ignore
507
508 if ( ! WP_Helper::is_multisite() ) {
509 unregister_setting(
510 WP_2FA_POLICY_SETTINGS_NAME,
511 WP_2FA_POLICY_SETTINGS_NAME
512 );
513 }
514 $settings_page = new Settings_Page_Policies();
515 $sanitized_settings = $settings_page->validate_and_sanitize( $input, 'setup_wizard' );
516 WP2FA::update_plugin_settings( $sanitized_settings );
517
518 wp_safe_redirect( esc_url_raw( $this->get_next_step() ) );
519 exit();
520 }
521
522 /**
523 * Send email with fresh code, or to setup email 2fa.
524 *
525 * @param int $user_id User id we want to send the message to.
526 * @param string $nominated_email_address - The user custom address to use (name of the meta key to check for).
527 *
528 * @return bool
529 *
530 * @SuppressWarnings(PHPMD.ExitExpression)
531 */
532 public static function send_authentication_setup_email( $user_id, $nominated_email_address = 'nominated_email_address' ) {
533
534 // If we have a nonce posted, check it.
535 if ( wp_doing_ajax() && isset( $_POST['nonce'] ) ) {
536 $nonce_check = wp_verify_nonce( sanitize_text_field( \wp_unslash( $_POST['nonce'] ) ), 'wp-2fa-send-setup-email' );
537 if ( ! $nonce_check ) {
538 return false;
539 }
540 }
541
542 if ( isset( $_POST['user_id'] ) ) {
543 $user = get_userdata( intval( $_POST['user_id'] ) );
544 } else {
545 $user = get_userdata( $user_id );
546 }
547
548 // Grab email address is its provided.
549 if ( isset( $_POST['email_address'] ) ) {
550 $email = sanitize_email( \wp_unslash( $_POST['email_address'] ) );
551 } else {
552 $email = sanitize_email( $user->user_email );
553 }
554
555 if ( wp_doing_ajax() && isset( $_POST['nonce'] ) ) {
556 update_user_meta( $user->ID, WP_2FA_PREFIX . 'nominated_email_address', $email );
557 }
558
559 $enabled_email_address = '';
560 if ( ! empty( $nominated_email_address ) ) {
561 $enabled_email_address = get_user_meta( $user->ID, WP_2FA_PREFIX . $nominated_email_address, true );
562 }
563
564 // Generate a token and setup email.
565 $token = Authentication::generate_token( $user->ID );
566 $subject = wp_strip_all_tags( WP2FA::replace_email_strings( WP2FA::get_wp2fa_email_templates( 'login_code_email_subject' ), $user->ID ) );
567 $message = wpautop( WP2FA::replace_email_strings( WP2FA::get_wp2fa_email_templates( 'login_code_email_body' ), $user->ID, $token ) );
568
569 if ( ! empty( $enabled_email_address ) ) {
570 $email_address = $enabled_email_address;
571 } else {
572 $email_address = $user->user_email;
573 }
574
575 return Settings_Page::send_email( $email_address, $subject, $message );
576 }
577
578 /**
579 * Send email to setup authentication
580 */
581 public function regenerate_authentication_key() {
582 // Grab current user.
583 $user = wp_get_current_user();
584
585 $key = Authentication::generate_key();
586
587 $site_name = get_bloginfo( 'name', 'display' );
588 /**
589 * Changing the title of the login screen for the TOTP method.
590 *
591 * @param string $title - The default title.
592 * @param \WP_User $user - The WP user.
593 *
594 * @since 2.0.0
595 */
596 $totp_title = apply_filters( WP_2FA_PREFIX . 'totp_title', $site_name . ':' . $user->user_login, $user );
597 $new_qr = Authentication::get_google_qr_code( $totp_title, $key, $site_name );
598
599 wp_send_json_success(
600 array(
601 'key' => Authentication::decrypt_key_if_needed( $key ),
602 'qr' => $new_qr,
603 )
604 );
605 }
606
607 /**
608 * 3rd Party plugins
609 *
610 * @param array $wizard_steps - Array with the current wizard steps.
611 *
612 * @return array
613 */
614 public function wp_2fa_add_intro_step( $wizard_steps ) {
615 $new_wizard_steps = array(
616 'test' => array(
617 'name' => __( 'Welcome to WP 2FA', 'wp-2fa' ),
618 'content' => array( $this, 'introduction_step' ),
619 'save' => array( $this, 'introduction_step_save' ),
620 'wizard_type' => 'welcome_wizard',
621 ),
622 );
623
624 // combine the two arrays.
625 $wizard_steps = $new_wizard_steps + $wizard_steps;
626
627 return $wizard_steps;
628 }
629
630 /**
631 * Shows introduction step of the wizard
632 *
633 * @return void
634 */
635 private function introduction_step() {
636 Wizard_Steps::introduction_step();
637 }
638
639 /**
640 * Step Save: `Addons`
641 *
642 * @SuppressWarnings(PHPMD.ExitExpression)
643 */
644 private function introduction_step_save() {
645 // Check nonce.
646 check_admin_referer( 'wp2fa-step-addon' );
647
648 wp_safe_redirect( esc_url_raw( $this->get_next_step() ) );
649 exit();
650 }
651 }
652