PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.0.0
WP 2FA – Two-factor authentication for WordPress v2.0.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 / WizardSteps.php
wp-2fa / includes / classes / Admin / Views Last commit date
FirstTimeWizardSteps.php 4 years ago WizardSteps.php 4 years ago class-settings-page-render.php 4 years ago
WizardSteps.php
778 lines
1 <?php
2
3 namespace WP2FA\Admin\Views;
4
5 use WP2FA\WP2FA;
6 use WP2FA\Admin\User;
7 use WP2FA\Utils\UserUtils;
8 use WP2FA\Admin\Controllers\Settings;
9 use WP2FA\Authenticator\Authentication;
10
11 defined( 'ABSPATH' ) || exit; // Exit if accessed directly.
12
13 /**
14 * WP2FA Wizard Settings view controller
15 *
16 * @since 1.7
17 */
18 class WizardSteps {
19
20 /**
21 * Holds the current user
22 *
23 * @since 1.7
24 *
25 * @var \WP2FA\Admin\User
26 */
27 private static $user = null;
28
29 /**
30 * Is the totp method enabled
31 *
32 * @since 1.7
33 *
34 * @var bool
35 */
36 private static $totpEnabled = null;
37
38 /**
39 * Is the mail enabled
40 *
41 * @since 1.7
42 *
43 * @var bool
44 */
45 private static $emailEnabled = null;
46
47 /**
48 * Holds the nonce for json calls
49 *
50 * @since 1.7
51 *
52 * @var string
53 */
54 private static $jsonNonce = null;
55
56 /**
57 * Holds the url to which to redirect the user after the setup is finished
58 *
59 * @var string
60 *
61 * @since 2.0.0
62 */
63 private static $redirect_url = null;
64
65 /**
66 * Introduction step form
67 *
68 * @since 1.7
69 *
70 * @return void
71 */
72 public static function introductionStep() {
73 ?>
74 <form method="post" class="wp2fa-setup-form">
75 <?php wp_nonce_field( 'wp2fa-step-addon' ); ?>
76 <h3><?php esc_html_e( 'You are required to configure 2FA.', 'wp-2fa' ); ?></h3>
77 <p><?php esc_html_e( 'In order to keep this site - and your details secure, this website’s administrator requires you to enable 2FA authentication to continue.', 'wp-2fa' ); ?></p>
78 <p><?php esc_html_e( 'Two factor authentication ensures only you have access to your account by creating an added layer of security when logging in -', 'wp-2fa' ); ?> <a href="https://www.wpwhitesecurity.com/two-factor-authentication-wordpress/" target="_blank" rel="noopener"><?php esc_html_e( 'Learn more', 'wp-2fa' ); ?></a></p>
79
80 <div class="wp2fa-setup-actions">
81 <button class="button button-primary"
82 type="submit"
83 name="save_step"
84 value="<?php esc_attr_e( 'Next', 'wp-2fa' ); ?>">
85 <?php esc_html_e( 'Next', 'wp-2fa' ); ?>
86 </button>
87 </div>
88 </form>
89 <?php
90 }
91
92 /**
93 * Welcome step of the wizard
94 *
95 * @since 1.7
96 *
97 * @param string $nextStep - url of the next step.
98 *
99 * @return void
100 */
101 public static function welcomeStep( $nextStep ) {
102 $redirect = Settings::get_settings_page_link();
103
104 ?>
105 <h3><?php esc_html_e( 'Let us help you get started', 'wp-2fa' ); ?></h3>
106 <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>
107
108 <div class="wp2fa-setup-actions">
109 <a class="button button-primary"
110 href="<?php echo esc_url( $nextStep ); ?>">
111 <?php esc_html_e( 'Let’s get started!', 'wp-2fa' ); ?>
112 </a>
113 <a class="button button-secondary first-time-wizard"
114 href="<?php echo esc_url( $redirect ); ?>">
115 <?php esc_html_e( 'Skip Wizard - I know how to do this', 'wp-2fa' ); ?>
116 </a>
117 </div>
118 <?php
119 }
120
121 /**
122 * Shows the initial totp setup options based on enabled methods
123 *
124 * @since 1.7
125 *
126 * @return void
127 */
128 public static function totpOption() {
129 if ( self::isTotpEnabled() ) {
130 ?>
131 <div class="option-pill">
132 <label for="basic">
133 <input id="basic" name="wp_2fa_enabled_methods" type="radio" value="totp" checked>
134 <?php esc_html_e( 'One-time code generated with your app of choice (most reliable and secure)', 'wp-2fa' ); ?>
135 </label>
136 <?php
137 echo '<p class="description">';
138 printf(
139 /* translators: link to the knowledge base website */
140 esc_html__( 'Refer to the %s for more information on how to setup these apps and which apps are supported.', 'wp-2fa' ),
141 '<a href="https://www.wpwhitesecurity.com/support/kb/configuring-2fa-apps/" target="_blank">' . esc_html__( '2FA apps article on our knowledge base', 'wp-2fa' ) . '</a>'
142 );
143 echo '</p>';
144 ?>
145 </div>
146 <?php
147 }
148 }
149
150 /**
151 * Shows the initial email setup option based on enabled methods
152 *
153 * @since 1.7
154 *
155 * @return void
156 */
157 public static function emailOption() {
158 if ( self::isMailEnabled() ) {
159 ?>
160 <div class="option-pill">
161 <label for="geek">
162 <input id="geek" name="wp_2fa_enabled_methods" type="radio" value="email">
163 <?php esc_html_e( 'One-time code sent to you over email', 'wp-2fa' ); ?>
164 </label>
165 <?php
166 if ( current_user_can( 'administrator' ) ) {
167 echo '<p class="description">' . WP2FA::print_email_deliverability_message() . '</p>'; // @codingStandardsIgnoreLine
168 }
169 ?>
170 </div>
171 <?php
172 }
173 }
174
175
176 /**
177 * Shows the option to reconfigure email (if applicable)
178 *
179 * @since 1.7
180 *
181 * @return void
182 */
183 public static function totpReConfigure() {
184
185 if ( ! self::isTotpEnabled() ) {
186 return;
187 }
188
189 $nonce = self::jsonNonce();
190
191 ?>
192 <div class="option-pill">
193 <h3>
194 <?php esc_html_e( 'Reconfigure the 2FA App', 'wp-2fa' ); ?>
195 </h3>
196 <p>
197 <?php esc_html_e( 'Click the below button to reconfigure the current 2FA method. Note that once reset you will have to re-scan the QR code on all devices you want this to work on because the previous codes will stop working.', 'wp-2fa' ); ?>
198 </p>
199 <div class="wp2fa-setup-actions">
200 <a href="#" class="button button-primary" data-name="next_step_setting_modal_wizard" data-trigger-reset-key data-nonce="<?php echo esc_attr( $nonce ); ?>" data-user-id="<?php echo esc_attr( self::getUser()->getUser()->ID ); ?>" data-next-step="2fa-wizard-totp"><?php esc_html_e( 'Reset Key', 'wp-2fa' ); ?></a>
201 </div>
202 </div>
203 <?php
204 }
205
206 /**
207 * Shows the option for email method reconfiguring (if applicable)
208 *
209 * @since 1.7
210 *
211 * @return void
212 */
213 public static function emailReConfigure() {
214
215 if ( ! self::isMailEnabled() ) {
216 return;
217 }
218
219 $setupnonce = wp_create_nonce( 'wp-2fa-send-setup-email' );
220 ?>
221 <div class="option-pill">
222 <h3><?php esc_html_e( 'Reconfigure one-time code over email method', 'wp-2fa' ); ?></h3>
223 <p>
224 <?php esc_html_e( 'Please select the email address where the one-time code should be sent:', 'wp-2fa' ); ?>
225 </p>
226 <div class="wp2fa-setup-actions">
227 <a class="button button-primary" data-name="next_step_setting_modal_wizard" value="<?php esc_attr_e( 'I\'m Ready', 'wp-2fa' ); ?>" data-user-id="<?php echo esc_attr( self::getUser()->getUser()->ID ); ?>" data-nonce="<?php echo esc_attr( $setupnonce ); ?>" data-next-step="2fa-wizard-email"><?php esc_html_e( 'Change email address', 'wp-2fa' ); ?></a>
228 </div>
229 </div>
230 <?php
231 }
232
233 /**
234 * Reconfigures the totp form
235 *
236 * @since 1.7
237 *
238 * @return void
239 */
240 public static function totpConfigure() {
241
242 if ( ! self::isTotpEnabled() ) {
243 return;
244 }
245 /**
246 * Active on modal, additional attribute is required on standard HTML (check below)
247 */
248 $addStepAttributes = 'active';
249
250 /**
251 * Closing div for extra modal wrappers see lines above
252 */
253 $closeDiv = '';
254
255 $qrCode = '<img class="qr-code" src="' . ( self::getQRCode() ) . '" id="wp-2fa-totp-qrcode" />';
256 $open30Wrapper = '
257 <div class="mb-30 clear-both">
258 ';
259 $open60Wrapper = '
260 <div class="modal-60">
261 ';
262 $open40Wrapper = '
263 <div class="modal-40">
264 ';
265 $closeDiv = '
266 </div>
267 ';
268 $validateNonce = wp_create_nonce( 'wp-2fa-validate-authcode' );
269
270 ?>
271 <div class="step-setting-wrapper <?php echo $addStepAttributes; ?>">
272 <h3><?php esc_html_e( 'Setup the 2FA method', 'wp-2fa' ); ?></h3>
273 <?php echo $open30Wrapper . $open60Wrapper; ?>
274 <div class="option-pill">
275 <ol>
276 <li><?php esc_html_e( 'Download and start the application of your choice (for detailed steps on setting it up click on the application icon of our choice below)', 'wp-2fa' ); ?></li>
277 <li><?php esc_html_e( 'From within the application scan the QR code provided on the right. Otherwise, enter the following code manually in the application:', 'wp-2fa' ); ?>
278 <div><code class="app-key"><?php echo esc_html( self::getUser()->get_totp_decrypted() ); ?></code></div>
279 </li>
280 <li><?php esc_html_e( 'Click the "I\'m ready" button below when you complete the application setup process to proceed with the wizard.', 'wp-2fa' ); ?></li>
281 </ol>
282 </div>
283 <?php
284 echo $closeDiv; // closes 50 wrapper
285 echo $open40Wrapper;
286 ?>
287 <div class="qr-code-wrapper">
288 <?php echo $qrCode; ?>
289 </div>
290 <?php
291 echo $closeDiv; // closes 50 wrapper
292 echo $closeDiv; // closes 30 wrapper
293 ?>
294 <h4><?php esc_html_e( 'For detailed guides for your desired app, click below.', 'wp-2fa' ); ?></h4>
295 <div class="apps-wrapper">
296 <?php foreach ( Authentication::get_apps() as $app ) { ?>
297 <a href="https://www.wpwhitesecurity.com/support/kb/configuring-2fa-apps/#<?php echo $app['hash']; ?>" target="_blank" class="app-logo"><img src="<?php echo esc_url( WP_2FA_URL . 'dist/images/' . $app['logo'] ); ?>"></a>
298 <?php } ?>
299 </div>
300 <div class="wp2fa-setup-actions">
301 <button class="button button-primary" name="next_step_setting" value="<?php esc_attr_e( 'I\'m Ready', 'wp-2fa' ); ?>" type="button"><?php esc_html_e( 'I\'m Ready', 'wp-2fa' ); ?></button>
302 </div>
303 </div>
304 <div class="step-setting-wrapper" data-step-title="<?php esc_html_e( 'Verify configuration', 'wp-2fa' ); ?>">
305 <h3><?php esc_html_e( 'Almost there…', 'wp-2fa' ); ?></h3>
306 <p><?php esc_html_e( 'Please type in the one-time code from your Google Authenticator app to finalize the setup.', 'wp-2fa' ); ?></p>
307 <fieldset>
308 <label for="2fa-totp-authcode">
309 <input type="tel" name="wp-2fa-totp-authcode" id="wp-2fa-totp-authcode" class="input" value="" size="20" pattern="[0-9]*" placeholder="<?php esc_html_e( 'Authentication Code', 'wp-2fa' ); ?>"/>
310 </label>
311 <div class="verification-response"></div>
312 </fieldset>
313 <input type="hidden" name="wp-2fa-totp-key" value="<?php echo esc_attr( self::getUser()->get_totp_decrypted() ); ?>" />
314 <br>
315 <a href="#" class="modal__btn button button-primary" data-validate-authcode-ajax data-nonce="<?php echo esc_attr( $validateNonce ); ?>"><?php esc_html_e( 'Validate & Save Configuration', 'wp-2fa' ); ?></a>
316 <button class="modal__btn button" data-close-2fa-modal aria-label="Close this dialog window"><?php esc_html_e( 'Cancel', 'wp-2fa' ); ?></button>
317 </div>
318
319 <?php
320 }
321
322 /**
323 * Reconfigures email form
324 *
325 * @since 1.7
326 *
327 * @return void
328 */
329 public static function emailConfigure() {
330
331 if ( ! self::isMailEnabled() ) {
332 return;
333 }
334
335 $setupnonce = wp_create_nonce( 'wp-2fa-send-setup-email' );
336
337 $validateNonce = wp_create_nonce( 'wp-2fa-validate-authcode' );
338 ?>
339 <div class="step-setting-wrapper active">
340 <h3><?php esc_html_e( 'Setup the 2FA method', 'wp-2fa' ); ?></h3>
341 <p>
342 <?php esc_html_e( 'Please select the email address where the one-time code should be sent:', 'wp-2fa' ); ?>
343 </p>
344 <fieldset>
345 <div class="option-pill">
346 <label for="use_wp_email">
347 <input type="radio" name="wp_2fa_email_address" id="use_wp_email" value="<?php echo esc_attr( self::getUser()->getUser()->user_email ); ?>" checked>
348 <span><?php esc_html_e( 'Use my user email (', 'wp-2fa' ); ?><small><?php echo esc_attr( self::getUser()->getUser()->user_email ); ?></small><?php esc_html_e( ')', 'wp-2fa' ); ?></span>
349 </label>
350 </div>
351 <?php
352 if ( Settings::get_role_or_default_setting( 'specify-email_hotp', self::getUser()->getUser() ) ) {
353 ?>
354 <div class="option-pill">
355 <label for="use_custom_email">
356 <input type="radio" name="wp_2fa_email_address" id="use_custom_email" value="use_custom_email">
357 <span><?php esc_html_e( 'Use a different email address:', 'wp-2fa' ); ?></span>
358 <input type="email" name="custom-email-address" id="custom-email-address" class="input" value="" placeholder="<?php esc_html_e( 'Email address', 'wp-2fa' ); ?>"/>
359 </label>
360 </div>
361 <?php
362 }
363 ?>
364 </fieldset>
365 <p class="description"><?php esc_html_e( 'Note: you should be able to access the mailbox of the email address to complete the following step.', 'wp-2fa' ); ?></p>
366 <div class="wp2fa-setup-actions">
367 <button class="button button-primary" name="next_step_setting" value="<?php esc_attr_e( 'I\'m Ready', 'wp-2fa' ); ?>" data-trigger-setup-email data-user-id="<?php echo esc_attr( self::getUser()->getUser()->ID ); ?>" data-nonce="<?php echo esc_attr( $setupnonce ); ?>" type="button"><?php esc_html_e( 'I\'m Ready', 'wp-2fa' ); ?></button>
368
369 </div>
370 </div>
371
372 <div class="step-setting-wrapper" data-step-title="<?php esc_html_e( 'Verify configuration', 'wp-2fa' ); ?>" id="2fa-wizard-email">
373 <h3><?php esc_html_e( 'Almost there…', 'wp-2fa' ); ?></h3>
374 <p><?php esc_html_e( 'Please type in the one-time code sent to your email address to finalize the setup.', 'wp-2fa' ); ?></p>
375 <fieldset>
376 <label for="2fa-email-authcode">
377 <input type="tel" name="wp-2fa-email-authcode" id="wp-2fa-email-authcode" class="input" value="" size="20" pattern="[0-9]*" placeholder="<?php esc_html_e( 'Authentication Code', 'wp-2fa' ); ?>"/>
378 </label>
379 <div class="verification-response"></div>
380 </fieldset>
381 <br />
382 <a href="#" class="modal__btn modal__btn-primary button button-primary" data-validate-authcode-ajax data-nonce="<?php echo esc_attr( $validateNonce ); ?>"><?php esc_html_e( 'Validate & Save Configuration', 'wp-2fa' ); ?></a>
383 <a href="#" class="modal__btn button button-secondary resend-email-code" data-trigger-setup-email data-user-id="<?php echo esc_attr( self::getUser()->getUser()->ID ); ?>" data-nonce="<?php echo esc_attr( $setupnonce ); ?>">
384 <span class="resend-inner"><?php esc_html_e( 'Send me another code', 'wp-2fa' ); ?></span>
385 </a>
386 <button class="modal__btn button" data-close-2fa-modal aria-label="Close this dialog window"><?php esc_html_e( 'Cancel', 'wp-2fa' ); ?></button>
387 </div>
388 <?php
389 }
390
391 /**
392 * Configure backup codes step
393 *
394 * @since 1.7
395 *
396 * @return void
397 */
398 public static function backup_codes_configure() {
399
400 $user_type = UserUtils::determine_user_2fa_status( self::getUser()->getUser() );
401
402 $redirect = self::determine_redirect_url();
403
404 $nonce = self::jsonNonce();
405 ?>
406 <div class="step-setting-wrapper active">
407 <h3><?php esc_html_e( 'Your login just got more secure', 'wp-2fa' ); ?></h3>
408 <p><?php esc_html_e( 'Congratulations! You have enabled two-factor authentication for your user. You’ve just helped towards making this website more secure!', 'wp-2fa' ); ?></p>
409 <?php
410 if ( in_array( 'user_needs_to_setup_backup_codes', $user_type, true ) ) {
411 ?>
412 <p><?php esc_html_e( 'You can exit this wizard now or continue to create backup codes.', 'wp-2fa' ); ?></p>
413 <?php } ?>
414 <div class="wp2fa-setup-actions">
415 <?php if ( in_array( 'user_needs_to_setup_backup_codes', $user_type, true ) ) { ?>
416 <button class="button button-primary" name="next_step_setting" value="<?php esc_attr_e( 'Generate backup codes', 'wp-2fa' ); ?>" data-trigger-generate-backup-codes data-nonce="<?php echo esc_attr( $nonce ); ?>">
417 <?php esc_html_e( 'Generate list of backup codes', 'wp-2fa' ); ?>
418 </button>
419 <a href="#" class="button button-secondary" data-close-2fa-modal value="<?php esc_attr_e( 'I’ll generate them later', 'wp-2fa' ); ?>">
420 <?php esc_html_e( 'I’ll generate them later', 'wp-2fa' ); ?>
421 </a>
422 <?php } else { ?>
423 <?php
424 if ( ! empty( $redirect ) ) {
425 ?>
426 <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary close-first-time-wizard">
427 <?php esc_html_e( 'Close wizard', 'wp-2fa' ); ?>
428 </a>
429 <?php
430 } else {
431 ?>
432 <a href="#" class="button button-secondary" data-reload>
433 <?php esc_html_e( 'Close wizard', 'wp-2fa' ); ?>
434 </a>
435 <?php } ?>
436 <?php } ?>
437 </div>
438 </div>
439 <?php
440 }
441
442 /**
443 * Generate backup codes step
444 *
445 * @since 1.7
446 *
447 * @return void
448 */
449 public static function generateBackupCodes() {
450 $nonce = self::jsonNonce();
451
452 ?>
453 <div class="step-setting-wrapper active" data-step-title="<?php esc_html_e( 'Generate codes', 'wp-2fa' ); ?>">
454 <h3><?php esc_html_e( 'Generate backup codes', 'wp-2fa' ); ?></h3>
455 <p><?php esc_html_e( 'It is recommended to generate and print some backup codes in case you lose access to your primary 2FA method. ', 'wp-2fa' ); ?></p>
456 <div class="wp2fa-setup-actions">
457 <button class="button button-primary" name="next_step_setting" value="<?php esc_attr_e( 'Generate backup codes', 'wp-2fa' ); ?>" data-trigger-generate-backup-codes data-nonce="<?php echo esc_attr( $nonce ); ?>">
458 <?php esc_html_e( 'Generate list of backup codes', 'wp-2fa' ); ?>
459 </button>
460 <a href="#" class="button button-secondary" value="<?php esc_attr_e( 'I’ll generate them later', 'wp-2fa' ); ?>" data-close-2fa-modal="">
461 <?php esc_html_e( 'I’ll generate them later', 'wp-2fa' ); ?>
462 </a>
463 </div>
464 </div>
465
466 <?php
467 }
468
469 /**
470 * Creates link for generating the backup codes
471 *
472 * @since 1.7
473 *
474 * @return string
475 */
476 public static function getGenerateCodesLink() {
477 $nonce = self::jsonNonce();
478
479 $label = __( 'Backup 2FA methods:', 'wp-2fa' );
480
481 return $label . '</th><td><a href="#" class="button button-primary remove-2fa" data-trigger-generate-backup-codes data-nonce="' . esc_attr( $nonce ) . '" onclick="MicroModal.show( \'configure-2fa-backup-codes\' );">' . __( 'Generate list of backup codes', 'wp-2fa' ) . '</a>';
482 }
483
484 /**
485 * Shows the wrapper where backup code are generated and showed to the user
486 *
487 * @param boolean $backup_only - If we want to show backup window only - sets the class of the div to active.
488 *
489 * @since 1.7
490 *
491 * @return void
492 */
493 public static function generated_backup_codes( $backup_only = false ) {
494 $nonce = self::jsonNonce();
495
496 $redirect = self::determine_redirect_url();
497
498 ?>
499 <div class="step-setting-wrapper align-center<?php echo ( $backup_only ) ? ' active' : ''; ?>" data-step-title="<?php esc_html_e( 'Your backup codes', 'wp-2fa' ); ?>">
500 <h3><?php esc_html_e( 'Backup codes generated', 'wp-2fa' ); ?></h3>
501 <p><?php esc_html_e( 'Here are your backup codes:', 'wp-2fa' ); ?></p>
502 <code id="backup-codes-wrapper"></code>
503 <div class="wp2fa-setup-actions">
504 <button class="button button-primary" type="submit" value="<?php esc_attr_e( 'Download', 'wp-2fa' ); ?>" data-trigger-backup-code-download data-user="<?php echo esc_attr( self::getUser()->getUser()->display_name ); ?>" data-website-url="<?php echo esc_attr( get_home_url() ); ?>">
505 <?php esc_html_e( 'Download', 'wp-2fa' ); ?>
506 </button>
507 <button class="button button-secondary" type="submit" value="<?php esc_attr_e( 'Print', 'wp-2fa' ); ?>" data-trigger-print data-nonce="<?php echo esc_attr( $nonce ); ?>" data-user-id="<?php echo esc_attr( self::getUser()->getUser()->display_name ); ?>" data-website-url="<?php echo esc_attr( get_home_url() ); ?>">
508 <?php esc_html_e( 'Print', 'wp-2fa' ); ?>
509 </button>
510 <?php
511 if ( ! empty( $redirect ) ) {
512 ?>
513 <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary close-first-time-wizard">
514 <?php esc_html_e( 'I\'m ready, close the wizard', 'wp-2fa' ); ?>
515 </a>
516 <?php
517 } else {
518 ?>
519 <button class="button button-secondary" type="submit" data-close-2fa-modal-and-refresh>
520 <?php esc_html_e( 'I\'m ready, close the wizard', 'wp-2fa' ); ?>
521 </button>
522 <?php } ?>
523 </div>
524 </div>
525 <?php
526 }
527
528 /**
529 * Final step for congratulating the user
530 *
531 * @since 1.7
532 *
533 * @param boolean $setup_wizard - Is that a call from setup wizard or not.
534 *
535 * @return void
536 */
537 public static function congratulations_step( $setup_wizard = false ) {
538
539 if ( $setup_wizard ) {
540 self::congratulations_step_plugin_wizard();
541 return;
542 }
543 ?>
544
545 <div class="step-setting-wrapper active">
546 <h3><?php esc_html_e( 'Congratulations! You are all set.', 'wp-2fa' ); ?></h3>
547 <div class="wp2fa-setup-actions">
548 <button class="modal__btn button" data-close-2fa-modal aria-label="Close this dialog window"><?php esc_html_e( 'Close wizard', 'wp-2fa' ); ?></button>
549 </div>
550 </div>
551 <?php
552 }
553
554 /**
555 * Final step for congratulating the user
556 *
557 * @since 1.7
558 *
559 * @return void
560 */
561 public static function congratulations_step_plugin_wizard() {
562 $redirect = ( '' !== self::determine_redirect_url() ) ? self::determine_redirect_url() : get_edit_profile_url( self::getUser()->getUser()->ID );
563 $slide_title = ( User::is_excluded( self::getUser()->getUser()->ID ) ) ? esc_html__( 'Congratulations.', 'wp-2fa' ) : esc_html__( 'Congratulations, you\'re almost there...', 'wp-2fa' );
564 ?>
565 <h3><?php echo $slide_title; ?></h3>
566 <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>
567
568 <?php
569 if ( User::is_excluded( self::getUser()->getUser()->ID ) ) {
570 ?>
571 <div class="wp2fa-setup-actions">
572 <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary close-first-time-wizard">
573 <?php esc_html_e( 'Close wizard', 'wp-2fa' ); ?>
574 </a>
575 </div>
576 <?php
577 } else {
578 ?>
579 <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>
580 <div class="wp2fa-setup-actions">
581 <a href="<?php echo esc_url( Settings::get_setup_page_link() ); ?>" class="button button-secondary">
582 <?php esc_html_e( 'Configure 2FA now', 'wp-2fa' ); ?>
583 </a>
584 <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary close-first-time-wizard">
585 <?php esc_html_e( 'Close wizard & configure 2FA later', 'wp-2fa' ); ?>
586 </a>
587 </div>
588 <?php } ?>
589 <?php
590 }
591
592 /**
593 * Shows the methods in the modal wizard, so the user can choose from the available ones
594 *
595 * @return void
596 */
597 public static function showModalMethods() {
598 if ( self::isTotpEnabled() ) {
599 ?>
600 <div class="wizard-step" id="2fa-wizard-totp">
601 <fieldset>
602 <?php self::totpConfigure(); ?>
603 </fieldset>
604 </div>
605 <?php
606 }
607 if ( self::isMailEnabled() ) {
608 ?>
609 <div class="wizard-step" id="2fa-wizard-email">
610 <fieldset>
611 <?php self::emailConfigure(); ?>
612 </fieldset>
613 </div>
614 <?php
615 }
616
617 /**
618 * Add an option for external providers to add their own modal methods options.
619 *
620 * @since 2.0.0
621 */
622 do_action( 'wp_2fa_modal_methods' );
623 }
624
625 /**
626 * Gets the current user
627 *
628 * @since 1.7
629 *
630 * @return \WP2FA\Admin\User
631 */
632 public static function getUser() {
633 if ( null === self::$user ) {
634 self::$user = User::get_instance();
635 }
636
637 return self::$user;
638 }
639
640 /**
641 * Choosing backup method step
642 * When there are more than one backup method - give the user ability to choose one
643 *
644 * @return void
645 *
646 * @since 2.0.0
647 */
648 public static function choose_backup_method() {
649 $redirect = get_edit_profile_url( self::getUser()->getUser()->ID );
650 ?>
651 <div class="wizard-step" id="2fa-wizard-backup-methods">
652 <div class="option-pill">
653 <h3><?php esc_html_e( 'Your login just got more secure', 'wp-2fa' ); ?></h3>
654 <p><?php esc_html_e( 'It is recommended to have a backup 2FA method in case you cannot generate a code from your 2FA app and you need to log in. You can configure any of the below. You can always configure any or both from your user profile page later.', 'wp-2fa' ); ?></p>
655 </div>
656 <?php
657 $backup_methods = Settings::get_backup_methods();
658
659 $i = 0;
660 foreach ( $backup_methods as $method_name => $method ) {
661 $checked = '';
662 if ( ! $i ) {
663 $checked = ' checked="checked"';
664 }
665 $i = 1;
666 ?>
667 <div><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']; // @codingStandardsIgnoreLine ?></label><br /></div>
668 <?php
669 }
670 ?>
671 <div class="wp2fa-setup-actions">
672 <a id="select-backup-method" href="<?php echo esc_url( Settings::get_setup_page_link() ); ?>" class="button button-secondary">
673 <?php esc_html_e( 'Configure backup 2FA method', 'wp-2fa' ); ?>
674 </a>
675 <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary close-first-time-wizard">
676 <?php esc_html_e( 'Close wizard & configure 2FA later', 'wp-2fa' ); ?>
677 </a>
678 </div>
679 </div>
680 <?php
681 }
682
683 /**
684 * Generates nonce for JSON calls
685 *
686 * @since 1.7
687 *
688 * @return string
689 */
690 protected static function jsonNonce() {
691 if ( null === self::$jsonNonce ) {
692 self::$jsonNonce = wp_create_nonce( 'wp-2fa-backup-codes-generate-json-' . self::getUser()->getUser()->ID );
693 }
694
695 return self::$jsonNonce;
696 }
697
698 /**
699 * Returns the status of the totp method (enabled | disabled)
700 *
701 * @since 1.7
702 *
703 * @return boolean
704 */
705 private static function isTotpEnabled(): bool {
706 if ( null === self::$totpEnabled ) {
707 self::$totpEnabled = empty( Settings::get_role_or_default_setting( 'enable_totp', 'current' ) ) ? false : true;
708 }
709
710 return self::$totpEnabled;
711 }
712
713 /**
714 * Returns the status of the mail method (enabled | disabled)
715 *
716 * @since 1.7
717 *
718 * @return boolean
719 */
720 private static function isMailEnabled(): bool {
721 if ( null === self::$emailEnabled ) {
722 self::$emailEnabled = empty( Settings::get_role_or_default_setting( 'enable_email', 'current' ) ) ? false : true;
723 }
724
725 return self::$emailEnabled;
726 }
727
728 /**
729 * Retrieves the QR code
730 *
731 * @since 1.7
732 *
733 * @return string
734 */
735 private static function getQRCode(): string {
736
737 // Setup site information, used when generating our QR code.
738 $siteName = get_bloginfo( 'name', 'display' );
739 $totpTitle = apply_filters(
740 'wp_2fa_totp_title',
741 $siteName . ':' . self::getUser()->getUser()->user_login,
742 self::getUser()->getUser()
743 );
744
745 return Authentication::get_google_qr_code( $totpTitle, self::getUser()->getTotpKey(), $siteName );
746 }
747
748 /**
749 * Determines the redirect url for the user
750 *
751 * @return string
752 *
753 * @since 2.0.0
754 */
755 private static function determine_redirect_url(): string {
756 if ( null === self::$redirect_url ) {
757 $redirect_page = Settings::get_role_or_default_setting( 'redirect-user-custom-page-global', self::getUser()->getUser() );
758 self::$redirect_url = ( '' !== trim( $redirect_page ) ) ? \trailingslashit( get_site_url() ) . $redirect_page : '';
759
760 if (
761 'yes' === Settings::get_role_or_default_setting( 'create-custom-user-page', self::getUser()->getUser() ) ||
762 'yes' === Settings::get_role_or_default_setting( 'create-custom-user-page' ) ) {
763 if (
764 '' !== trim( Settings::get_role_or_default_setting( 'redirect-user-custom-page', self::getUser()->getUser() ) ) ||
765 '' !== trim( Settings::get_role_or_default_setting( 'redirect-user-custom-page' ) ) ) {
766 if ( 'yes' === Settings::get_role_or_default_setting( 'create-custom-user-page', self::getUser()->getUser() ) ) {
767 self::$redirect_url = trailingslashit( get_site_url() ) . Settings::get_role_or_default_setting( 'redirect-user-custom-page', self::getUser()->getUser() );
768 } else {
769 self::$redirect_url = trailingslashit( get_site_url() ) . Settings::get_role_or_default_setting( 'redirect-user-custom-page' );
770 }
771 }
772 }
773 }
774
775 return self::$redirect_url;
776 }
777 }
778