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