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( Settings::get_settings_page_link() ); ?>" 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 |