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 / Views / class-wizard-steps.php
wp-2fa / includes / classes / Admin / Views Last commit date
class-first-time-wizard-steps.php 2 years ago class-grace-period-notifications.php 2 years ago class-passord-reset-2fa.php 2 years ago class-wizard-steps.php 2 years ago index.php 2 years ago
class-wizard-steps.php
477 lines
1 <?php
2 /**
3 * Settings page render class.
4 *
5 * @package wp2fa
6 * @subpackage views
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\Views;
13
14 use WP2FA\WP2FA;
15 use WP2FA\Methods\Email;
16 use WP2FA\Utils\User_Utils;
17 use WP2FA\Admin\Helpers\WP_Helper;
18 use WP2FA\Admin\Helpers\User_Helper;
19 use WP2FA\Admin\Controllers\Settings;
20
21 defined( 'ABSPATH' ) || exit; // Exit if accessed directly.
22
23 if ( ! class_exists( '\WP2FA\Admin\Views\Wizard_Steps' ) ) {
24 /**
25 * WP2FA Wizard Settings view controller
26 *
27 * @since 1.7
28 */
29 class Wizard_Steps {
30
31 /**
32 * Holds the nonce for json calls
33 *
34 * @since 1.7
35 *
36 * @var string
37 */
38 private static $json_nonce = null;
39
40 /**
41 * Holds the url to which to redirect the user after the setup is finished
42 *
43 * @var string
44 *
45 * @since 2.0.0
46 */
47 private static $redirect_url = null;
48
49 /**
50 * Introduction step form
51 *
52 * @since 1.7
53 *
54 * @return void
55 */
56 public static function optional_user_welcome_step() {
57 ?>
58 <div class="wizard-step active">
59 <div class="mb-20">
60 <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'welcome', true ) ); ?>
61 </div>
62
63 <div class="wp2fa-setup-actions">
64 <a href="#" class="button wp-2fa-button-primary button-primary" data-name="next_step_setting_modal_wizard" data-next-step="choose-2fa-method"><?php esc_html_e( 'Next Step', 'wp-2fa' ); ?></a>
65 <button class="wp-2fa-button-secondary button button-secondary wp-2fa-button-secondary" data-close-2fa-modal aria-label="Close this dialog window"><?php esc_html_e( 'Cancel', 'wp-2fa' ); ?></button>
66 </div>
67 </div>
68 <?php
69 }
70
71 /**
72 * Introduction step form
73 *
74 * @since 1.7
75 *
76 * @return void
77 */
78 public static function introduction_step() {
79 ?>
80 <form method="post" class="wp2fa-setup-form">
81 <?php wp_nonce_field( 'wp2fa-step-addon' ); ?>
82 <div class="mb-20">
83 <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( '2fa_required_intro', true ) ); ?>
84 </div>
85
86 <div class="wp2fa-setup-actions">
87 <button class="button button-primary wp-2fa-button-primary"
88 type="submit"
89 name="save_step"
90 value="<?php esc_attr_e( 'Next', 'wp-2fa' ); ?>">
91 <?php esc_html_e( 'Next', 'wp-2fa' ); ?>
92 </button>
93 </div>
94 </form>
95 <?php
96 }
97
98 /**
99 * Welcome step of the wizard
100 *
101 * @since 1.7
102 *
103 * @param string $next_step - url of the next step.
104 *
105 * @return void
106 */
107 public static function welcome_step( $next_step ) {
108 $redirect = Settings::get_settings_page_link();
109
110 ?>
111 <h3><?php esc_html_e( 'Let us help you get started', 'wp-2fa' ); ?></h3>
112 <p><?php esc_html_e( 'Thank you for installing the WP 2FA plugin. This quick wizard will assist you with configuring the plugin and the two-factor authentication (2FA) settings for your user and the users on this website.', 'wp-2fa' ); ?></p>
113
114 <div class="wp2fa-setup-actions">
115 <a class="button button-primary"
116 href="<?php echo esc_url( $next_step ); ?>">
117 <?php esc_html_e( 'Let’s get started!', 'wp-2fa' ); ?>
118 </a>
119 <a class="button button-secondary wp-2fa-button-secondary first-time-wizard"
120 href="<?php echo esc_url( $redirect ); ?>">
121 <?php esc_html_e( 'Skip Wizard - I know how to do this', 'wp-2fa' ); ?>
122 </a>
123 </div>
124 <?php
125 }
126
127 /**
128 * Configure backup codes step
129 *
130 * @since 1.7
131 *
132 * @return void
133 */
134 public static function backup_codes_configure() {
135
136 $user_type = User_Utils::determine_user_2fa_status( User_Helper::get_user_object() );
137
138 $redirect = self::determine_redirect_url();
139 ?>
140 <div class="step-setting-wrapper active">
141 <?php
142 if ( in_array( 'user_needs_to_setup_backup_codes', $user_type, true ) ) {
143 ?>
144 <div class="mb-20">
145 <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'backup_codes_intro_continue', true ) ); ?>
146 </div>
147 <?php } else { ?>
148 <div class="mb-20">
149 <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'backup_codes_intro', true ) ); ?>
150 </div>
151 <?php } ?>
152 <div class="wp2fa-setup-actions">
153 <?php if ( in_array( 'user_needs_to_setup_backup_codes', $user_type, true ) ) { ?>
154 <button class="button button-primary wp-2fa-button-primary" name="next_step_setting" value="<?php esc_attr_e( 'Generate backup codes', 'wp-2fa' ); ?>" data-trigger-generate-backup-codes <?php echo WP_Helper::create_data_nonce( self::json_nonce() ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
155 <?php esc_html_e( 'Generate list of backup codes', 'wp-2fa' ); ?>
156 </button>
157 <?php
158 if ( ! empty( $redirect ) ) {
159 ?>
160 <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary wp-2fa-button-secondary wp-2fa-button-secondary close-first-time-wizard">
161 <?php esc_html_e( 'I’ll generate them later', 'wp-2fa' ); ?>
162 </a>
163 <?php
164 } else {
165 ?>
166 <a href="#" class="button wp-2fa-button-secondary" data-close-2fa-modal value="<?php esc_attr_e( 'I’ll generate them later', 'wp-2fa' ); ?>">
167 <?php esc_html_e( 'I’ll generate them later', 'wp-2fa' ); ?>
168 </a>
169 <?php } ?>
170 <?php } else { ?>
171 <?php
172 if ( ! empty( $redirect ) ) {
173 ?>
174 <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary wp-2fa-button-secondary close-first-time-wizard">
175 <?php esc_html_e( 'Close wizard', 'wp-2fa' ); ?>
176 </a>
177 <?php
178 } else {
179 ?>
180 <a href="#" class="button button-secondary wp-2fa-button-secondary" data-reload>
181 <?php esc_html_e( 'Close wizard', 'wp-2fa' ); ?>
182 </a>
183 <?php } ?>
184 <?php } ?>
185 </div>
186 </div>
187 <?php
188 }
189
190 /**
191 * Generate backup codes step
192 *
193 * @since 1.7
194 *
195 * @return void
196 */
197 public static function generate_backup_codes() {
198 ?>
199 <div class="step-setting-wrapper active" data-step-title="<?php esc_html_e( 'Generate codes', 'wp-2fa' ); ?>">
200 <div class="mb-20">
201 <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'backup_codes_generate_intro', true ) ); ?>
202 </div>
203 <div class="wp2fa-setup-actions">
204 <button class="button button-primary" name="next_step_setting" value="<?php esc_attr_e( 'Generate backup codes', 'wp-2fa' ); ?>" data-trigger-generate-backup-codes <?php echo WP_Helper::create_data_nonce( self::json_nonce() ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
205 <?php esc_html_e( 'Generate list of backup codes', 'wp-2fa' ); ?>
206 </button>
207 <a href="#" class="button button-secondary wp-2fa-button-secondary" value="<?php esc_attr_e( 'I’ll generate them later', 'wp-2fa' ); ?>" data-close-2fa-modal="">
208 <?php esc_html_e( 'I’ll generate them later', 'wp-2fa' ); ?>
209 </a>
210 </div>
211 </div>
212
213 <?php
214 }
215
216 /**
217 * Creates link for generating the backup codes
218 *
219 * @since 1.7
220 *
221 * @return string
222 */
223 public static function get_generate_codes_label() {
224 $label = __( 'Backup 2FA methods:', 'wp-2fa' );
225
226 return $label . '</th><td>';
227 }
228
229 /**
230 * Creates backup codes URL link
231 *
232 * @return string
233 *
234 * @since 2.6.0
235 */
236 public static function get_backup_codes_link(): string {
237 return '<a href="#" class="button button-primary remove-2fa" data-trigger-generate-backup-codes ' . WP_Helper::create_data_nonce( self::json_nonce() ) . ' onclick="MicroModal.show( \'configure-2fa-backup-codes\' );">' . __( 'Generate list of backup codes', 'wp-2fa' ) . '</a>';
238 }
239
240 /**
241 * Shows the wrapper where backup code are generated and showed to the user
242 *
243 * @param boolean $backup_only - If we want to show backup window only - sets the class of the div to active.
244 *
245 * @since 1.7
246 *
247 * @return void
248 */
249 public static function generated_backup_codes( $backup_only = false ) {
250
251 $redirect = self::determine_redirect_url();
252
253 ?>
254 <div class="step-setting-wrapper align-center<?php echo ( $backup_only ) ? ' active' : ''; ?>" data-step-title="<?php esc_html_e( 'Your backup codes', 'wp-2fa' ); ?>">
255 <div class="mb-20">
256 <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'backup_codes_generated', true ) ); ?>
257 </div>
258 <div class="backup-key-wrapper">
259 <textarea id="backup-codes-wrapper" readonly rows="4" cols="50" class="app-key"></textarea>
260 </div>
261 <div class="wp2fa-setup-actions">
262 <?php if ( is_ssl() ) { ?>
263 <button class="button button-primary wp-2fa-button-primary" type="submit" value="<?php esc_attr_e( 'Download', 'wp-2fa' ); ?>" data-trigger-backup-code-copy>
264 <?php esc_html_e( 'Copy', 'wp-2fa' ); ?>
265 </button>
266 <?php } else { ?>
267 <button class="button button-primary wp-2fa-button-primary" type="submit" value="<?php esc_attr_e( 'Download', 'wp-2fa' ); ?>" data-trigger-backup-code-download data-user="<?php echo esc_attr( User_Helper::get_user_object()->display_name ); ?>" data-website-url="<?php echo esc_attr( get_home_url() ); ?>">
268 <?php esc_html_e( 'Download', 'wp-2fa' ); ?>
269 </button>
270 <?php } ?>
271 <button class="button button-primary wp-2fa-button-primary" type="submit" value="<?php esc_attr_e( 'Print', 'wp-2fa' ); ?>" data-trigger-print <?php echo WP_Helper::create_data_nonce( self::json_nonce() ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> data-user-id="<?php echo esc_attr( User_Helper::get_user_object()->display_name ); ?>" data-website-url="<?php echo esc_attr( get_home_url() ); ?>">
272 <?php esc_html_e( 'Print', 'wp-2fa' ); ?>
273 </button>
274
275 <button class="button button-primary wp-2fa-button-primary" type="submit" value="<?php esc_attr_e( 'Send me the codes via email', 'wp-2fa' ); ?>" data-trigger-backup-code-email <?php echo WP_Helper::create_data_nonce( 'wp-2fa-send-backup-codes-email-nonce' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> data-user-id="<?php echo esc_attr( User_Helper::get_user_object()->ID ); ?>" data-website-url="<?php echo esc_attr( get_home_url() ); ?>">
276 <?php esc_html_e( 'Send me the codes via email', 'wp-2fa' ); ?>
277 </button>
278 <?php
279 if ( ! empty( $redirect ) ) {
280 ?>
281 <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary wp-2fa-button-secondary wp-2fa-button-secondary close-first-time-wizard">
282 <?php esc_html_e( 'I\'m ready, close the wizard', 'wp-2fa' ); ?>
283 </a>
284 <?php
285 } else {
286 ?>
287 <button class="button button-secondary wp-2fa-button-secondary wp-2fa-button-secondary" type="submit" data-close-2fa-modal-and-refresh>
288 <?php esc_html_e( 'I\'m ready, close the wizard', 'wp-2fa' ); ?>
289 </button>
290 <?php } ?>
291 </div>
292 </div>
293 <?php
294 }
295
296 /**
297 * Final step for congratulating the user
298 *
299 * @since 1.7
300 *
301 * @param boolean $setup_wizard - Is that a call from setup wizard or not.
302 *
303 * @return void
304 */
305 public static function congratulations_step( $setup_wizard = false ) {
306
307 if ( $setup_wizard ) {
308 self::congratulations_step_plugin_wizard();
309 return;
310 }
311 ?>
312
313 <div class="step-setting-wrapper active">
314 <div class="mb-20">
315 <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'no_further_action', true ) ); ?>
316 </div>
317 <div class="wp2fa-setup-actions">
318 <button class="modal__btn wp-2fa-button-secondary button" data-close-2fa-modal aria-label="Close this dialog window"><?php esc_html_e( 'Close wizard', 'wp-2fa' ); ?></button>
319 </div>
320 </div>
321 <?php
322 }
323
324 /**
325 * Final step for congratulating the user
326 *
327 * @since 1.7
328 *
329 * @return void
330 */
331 public static function congratulations_step_plugin_wizard() {
332 $redirect = ( '' !== self::determine_redirect_url() ) ? self::determine_redirect_url() : get_edit_profile_url( User_Helper::get_user_object()->ID );
333 $slide_title = ( User_Helper::is_excluded( User_Helper::get_user_object()->ID ) ) ? esc_html__( 'Congratulations.', 'wp-2fa' ) : esc_html__( 'Congratulations, you\'re almost there...', 'wp-2fa' );
334 ?>
335 <h3><?php echo \esc_html( $slide_title ); ?></h3>
336 <p><?php esc_html_e( 'Great job, the plugin and 2FA policies are now configured. You can always change the plugin settings and 2FA policies at a later stage from the WP 2FA entry in the WordPress menu.', 'wp-2fa' ); ?></p>
337
338 <?php
339 if ( User_Helper::is_excluded( User_Helper::get_user_object()->ID ) ) {
340 ?>
341 <div class="wp2fa-setup-actions">
342 <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary wp-2fa-button-secondary close-first-time-wizard">
343 <?php esc_html_e( 'Close wizard', 'wp-2fa' ); ?>
344 </a>
345 </div>
346 <?php
347 } else {
348 ?>
349 <p><?php esc_html_e( 'Now you need to configure 2FA for your own user account. You can do this now (recommended) or later.', 'wp-2fa' ); ?></p>
350 <div class="wp2fa-setup-actions">
351 <a href="<?php echo esc_url( Settings::get_setup_page_link() ); ?>" class="button button-primary wp-2fa-button-secondary">
352 <?php esc_html_e( 'Configure 2FA now', 'wp-2fa' ); ?>
353 </a>
354 <a href="<?php echo esc_url( Settings::get_settings_page_link() ); ?>" class="button button-secondary wp-2fa-button-secondary close-first-time-wizard">
355 <?php esc_html_e( 'Close wizard & configure 2FA later', 'wp-2fa' ); ?>
356 </a>
357 </div>
358 <?php } ?>
359 <?php
360 }
361
362 /**
363 * Shows the methods in the modal wizard, so the user can choose from the available ones
364 *
365 * @return void
366 */
367 public static function show_modal_methods() {
368 /**
369 * Add an option for external providers to add their own modal methods options.
370 *
371 * @since 2.0.0
372 */
373 do_action( WP_2FA_PREFIX . 'modal_methods' );
374 }
375
376 /**
377 * Choosing backup method step
378 * When there are more than one backup method - give the user ability to choose one
379 *
380 * @return void
381 *
382 * @since 2.0.0
383 */
384 public static function choose_backup_method() {
385 $redirect = self::determine_redirect_url();
386 ?>
387 <div class="wizard-step" id="2fa-wizard-backup-methods">
388 <div class="option-pill mb-20">
389 <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'backup_codes_intro_multi', true ) ); ?>
390 </div>
391 <div class="radio-cells">
392 <?php
393 $backup_methods = Settings::get_backup_methods();
394
395 $i = 0;
396 foreach ( $backup_methods as $method_name => $method ) {
397 $checked = '';
398 if ( ! $i ) {
399 $checked = ' checked="checked"';
400 }
401 $i = 1;
402 ?>
403 <div class="option-pill"><label for="<?php echo \esc_attr( $method_name ); ?>"><input name="backup_method_select" data-step="<?php echo \esc_attr( $method['wizard-step'] ); ?>" type="radio" id="<?php echo \esc_attr( $method_name ); ?>" <?php echo $checked; ?>><?php echo $method['button_name']; // phpcs:ignore ?></label><br /></div>
404 <?php
405 }
406 ?>
407 </div>
408 <div class="wp2fa-setup-actions">
409 <a id="select-backup-method" href="<?php echo esc_url( Settings::get_setup_page_link() ); ?>" class="button button-primary wp-2fa-button-primary">
410 <?php esc_html_e( 'Configure backup 2FA method', 'wp-2fa' ); ?>
411 </a>
412 <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary wp-2fa-button-secondary close-first-time-wizard" <?php echo ( ( '' === trim( (string) $redirect ) ) ? 'data-close-it=""' : '' ); ?> >
413 <?php esc_html_e( 'Close wizard & configure 2FA later', 'wp-2fa' ); ?>
414 </a>
415 <script>
416 const closeButton = document.querySelector('[data-close-it]');
417
418 closeButton.addEventListener('click', (event) => {
419 event.preventDefault();
420 let url = new URL( location.href );
421 let params = new URLSearchParams( url.search );
422 params.delete('show');
423 location.replace( `${location.pathname}?${params}` );
424 });
425 </script>
426 </div>
427 </div>
428 <?php
429 }
430
431 /**
432 * Determines the redirect url for the user
433 *
434 * @return string
435 *
436 * @since 2.0.0
437 */
438 public static function determine_redirect_url(): string {
439 if ( null === self::$redirect_url ) {
440 $redirect_page = Settings::get_role_or_default_setting( 'redirect-user-custom-page-global', User_Helper::get_user_object() );
441 self::$redirect_url = ( '' !== trim( (string) $redirect_page ) ) ? \trailingslashit( get_site_url() ) . $redirect_page : '';
442
443 if (
444 'yes' === Settings::get_role_or_default_setting( 'create-custom-user-page', User_Helper::get_user_object() ) ||
445 'yes' === Settings::get_role_or_default_setting( 'create-custom-user-page' ) ) {
446 if (
447 '' !== trim( (string) Settings::get_role_or_default_setting( 'redirect-user-custom-page', User_Helper::get_user_object() ) ) ||
448 '' !== trim( (string) Settings::get_role_or_default_setting( 'redirect-user-custom-page' ) ) ) {
449 if ( 'yes' === Settings::get_role_or_default_setting( 'create-custom-user-page', User_Helper::get_user_object() ) ) {
450 self::$redirect_url = trailingslashit( get_site_url() ) . Settings::get_role_or_default_setting( 'redirect-user-custom-page', User_Helper::get_user_object() );
451 } else {
452 self::$redirect_url = trailingslashit( get_site_url() ) . Settings::get_role_or_default_setting( 'redirect-user-custom-page' );
453 }
454 }
455 }
456 }
457
458 return self::$redirect_url;
459 }
460
461 /**
462 * Generates nonce for JSON calls
463 *
464 * @since 1.7
465 *
466 * @return string
467 */
468 protected static function json_nonce() {
469 if ( null === self::$json_nonce ) {
470 self::$json_nonce = 'wp-2fa-backup-codes-generate-json-' . User_Helper::get_user_object()->ID;
471 }
472
473 return self::$json_nonce;
474 }
475 }
476 }
477