class-first-time-wizard-steps.php
3 years ago
class-settings-page-render.php
3 years ago
class-wizard-steps.php
3 years ago
class-wizard-steps.php
876 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Settings page render class. |
| 4 | * |
| 5 | * @package wp2fa |
| 6 | * @subpackage views |
| 7 | * @copyright 2023 WP White Security |
| 8 | * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 |
| 9 | * @link https://wordpress.org/plugins/wp-2fa/ |
| 10 | */ |
| 11 | |
| 12 | namespace WP2FA\Admin\Views; |
| 13 | |
| 14 | use WP2FA\WP2FA; |
| 15 | use WP2FA\Admin\User; |
| 16 | use WP2FA\Utils\User_Utils; |
| 17 | use WP2FA\Admin\Helpers\User_Helper; |
| 18 | use WP2FA\Admin\Controllers\Settings; |
| 19 | use WP2FA\Authenticator\Authentication; |
| 20 | |
| 21 | defined( 'ABSPATH' ) || exit; // Exit if accessed directly. |
| 22 | |
| 23 | /** |
| 24 | * WP2FA Wizard Settings view controller |
| 25 | * |
| 26 | * @since 1.7 |
| 27 | */ |
| 28 | class Wizard_Steps { |
| 29 | |
| 30 | /** |
| 31 | * Holds the current user |
| 32 | * |
| 33 | * @since 1.7 |
| 34 | * |
| 35 | * @var \WP2FA\Admin\User |
| 36 | */ |
| 37 | private static $user = null; |
| 38 | |
| 39 | /** |
| 40 | * Is the totp method enabled |
| 41 | * |
| 42 | * @since 1.7 |
| 43 | * |
| 44 | * @var bool |
| 45 | */ |
| 46 | private static $totp_enabled = null; |
| 47 | |
| 48 | /** |
| 49 | * Is the mail enabled |
| 50 | * |
| 51 | * @since 1.7 |
| 52 | * |
| 53 | * @var bool |
| 54 | */ |
| 55 | private static $email_enabled = null; |
| 56 | |
| 57 | /** |
| 58 | * Holds the nonce for json calls |
| 59 | * |
| 60 | * @since 1.7 |
| 61 | * |
| 62 | * @var string |
| 63 | */ |
| 64 | private static $json_nonce = null; |
| 65 | |
| 66 | /** |
| 67 | * Holds the url to which to redirect the user after the setup is finished |
| 68 | * |
| 69 | * @var string |
| 70 | * |
| 71 | * @since 2.0.0 |
| 72 | */ |
| 73 | private static $redirect_url = null; |
| 74 | |
| 75 | /** |
| 76 | * Introduction step form |
| 77 | * |
| 78 | * @since 1.7 |
| 79 | * |
| 80 | * @return void |
| 81 | */ |
| 82 | public static function optional_user_welcome_step() { |
| 83 | ?> |
| 84 | <div class="wizard-step active"> |
| 85 | <div class="mb-20"> |
| 86 | <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'welcome', true ) ); ?> |
| 87 | </div> |
| 88 | |
| 89 | <div class="wp2fa-setup-actions"> |
| 90 | <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> |
| 91 | <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> |
| 92 | </div> |
| 93 | </div> |
| 94 | <?php |
| 95 | } |
| 96 | |
| 97 | /** |
| 98 | * Introduction step form |
| 99 | * |
| 100 | * @since 1.7 |
| 101 | * |
| 102 | * @return void |
| 103 | */ |
| 104 | public static function introduction_step() { |
| 105 | ?> |
| 106 | <form method="post" class="wp2fa-setup-form"> |
| 107 | <?php wp_nonce_field( 'wp2fa-step-addon' ); ?> |
| 108 | <div class="mb-20"> |
| 109 | <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( '2fa_required_intro', true ) ); ?> |
| 110 | </div> |
| 111 | |
| 112 | <div class="wp2fa-setup-actions"> |
| 113 | <button class="button button-primary wp-2fa-button-primary" |
| 114 | type="submit" |
| 115 | name="save_step" |
| 116 | value="<?php esc_attr_e( 'Next', 'wp-2fa' ); ?>"> |
| 117 | <?php esc_html_e( 'Next', 'wp-2fa' ); ?> |
| 118 | </button> |
| 119 | </div> |
| 120 | </form> |
| 121 | <?php |
| 122 | } |
| 123 | |
| 124 | /** |
| 125 | * Welcome step of the wizard |
| 126 | * |
| 127 | * @since 1.7 |
| 128 | * |
| 129 | * @param string $next_step - url of the next step. |
| 130 | * |
| 131 | * @return void |
| 132 | */ |
| 133 | public static function welcome_step( $next_step ) { |
| 134 | $redirect = Settings::get_settings_page_link(); |
| 135 | |
| 136 | ?> |
| 137 | <h3><?php esc_html_e( 'Let us help you get started', 'wp-2fa' ); ?></h3> |
| 138 | <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> |
| 139 | |
| 140 | <div class="wp2fa-setup-actions"> |
| 141 | <a class="button button-primary" |
| 142 | href="<?php echo esc_url( $next_step ); ?>"> |
| 143 | <?php esc_html_e( 'Let’s get started!', 'wp-2fa' ); ?> |
| 144 | </a> |
| 145 | <a class="button button-secondary wp-2fa-button-secondary first-time-wizard" |
| 146 | href="<?php echo esc_url( $redirect ); ?>"> |
| 147 | <?php esc_html_e( 'Skip Wizard - I know how to do this', 'wp-2fa' ); ?> |
| 148 | </a> |
| 149 | </div> |
| 150 | <?php |
| 151 | } |
| 152 | |
| 153 | /** |
| 154 | * Shows the initial totp setup options based on enabled methods |
| 155 | * |
| 156 | * @since 1.7 |
| 157 | * |
| 158 | * @return void |
| 159 | */ |
| 160 | public static function totp_option() { |
| 161 | if ( self::is_totp_enabled() ) { |
| 162 | ?> |
| 163 | <div class="option-pill"> |
| 164 | <label for="basic"> |
| 165 | <input id="basic" name="wp_2fa_enabled_methods" type="radio" value="totp" checked> |
| 166 | <?php esc_html_e( 'One-time code via 2FA app', 'wp-2fa' ); ?><span class="wizard-tooltip" data-tooltip-content="data-totp-tooltip-content-wrapper">i</span> |
| 167 | </label> |
| 168 | <?php |
| 169 | echo '<p class="description tooltip-content-wrapper" data-totp-tooltip-content-wrapper>'; |
| 170 | printf( |
| 171 | /* translators: link to the knowledge base website */ |
| 172 | esc_html__( 'Refer to the %s for more information on how to setup these apps and which apps are supported.', 'wp-2fa' ), |
| 173 | '<a href="https://wp2fa.io/support/kb/configuring-2fa-apps/" target="_blank">' . esc_html__( 'guide on how to set up 2FA apps', 'wp-2fa' ) . '</a>' |
| 174 | ); |
| 175 | echo '</p>'; |
| 176 | ?> |
| 177 | </div> |
| 178 | <?php |
| 179 | } |
| 180 | } |
| 181 | |
| 182 | /** |
| 183 | * Shows the initial email setup option based on enabled methods |
| 184 | * |
| 185 | * @since 1.7 |
| 186 | * |
| 187 | * @return void |
| 188 | */ |
| 189 | public static function email_option() { |
| 190 | if ( self::is_mail_enabled() ) { |
| 191 | ?> |
| 192 | <div class="option-pill"> |
| 193 | <label for="geek"> |
| 194 | <input id="geek" name="wp_2fa_enabled_methods" type="radio" value="email"> |
| 195 | <?php esc_html_e( 'One-time code via email', 'wp-2fa' ); ?> |
| 196 | </label> |
| 197 | </div> |
| 198 | <?php |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | |
| 203 | /** |
| 204 | * Shows the option to reconfigure email (if applicable) |
| 205 | * |
| 206 | * @since 1.7 |
| 207 | * |
| 208 | * @return void |
| 209 | */ |
| 210 | public static function totp_re_configure() { |
| 211 | |
| 212 | if ( ! self::is_totp_enabled() ) { |
| 213 | return; |
| 214 | } |
| 215 | |
| 216 | $nonce = self::json_nonce(); |
| 217 | |
| 218 | ?> |
| 219 | <div class="option-pill"> |
| 220 | <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'totp_reconfigure_intro', true ) ); ?> |
| 221 | <div class="wp2fa-setup-actions"> |
| 222 | <a href="#" class="button button-primary wp-2fa-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::get_user()->get_2fa_wp_user()->ID ); ?>" data-next-step="2fa-wizard-totp"><?php esc_html_e( 'Reset Key', 'wp-2fa' ); ?></a> |
| 223 | </div> |
| 224 | </div> |
| 225 | <?php |
| 226 | } |
| 227 | |
| 228 | /** |
| 229 | * Shows the option for email method reconfiguring (if applicable) |
| 230 | * |
| 231 | * @since 1.7 |
| 232 | * |
| 233 | * @return void |
| 234 | */ |
| 235 | public static function email_re_configure() { |
| 236 | |
| 237 | if ( ! self::is_mail_enabled() ) { |
| 238 | return; |
| 239 | } |
| 240 | |
| 241 | $setupnonce = wp_create_nonce( 'wp-2fa-send-setup-email' ); |
| 242 | ?> |
| 243 | <div class="option-pill"> |
| 244 | <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'hotp_reconfigure_intro', true ) ); ?> |
| 245 | <div class="wp2fa-setup-actions"> |
| 246 | <a class="button button-primary wp-2fa-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::get_user()->get_2fa_wp_user()->ID ); ?>" data-nonce="<?php echo esc_attr( $setupnonce ); ?>" data-next-step="2fa-wizard-email"><?php esc_html_e( 'Change email address', 'wp-2fa' ); ?></a> |
| 247 | </div> |
| 248 | </div> |
| 249 | <?php |
| 250 | } |
| 251 | |
| 252 | /** |
| 253 | * Reconfigures the totp form |
| 254 | * |
| 255 | * @since 1.7 |
| 256 | * |
| 257 | * @return void |
| 258 | */ |
| 259 | public static function totp_configure() { |
| 260 | |
| 261 | if ( ! self::is_totp_enabled() ) { |
| 262 | return; |
| 263 | } |
| 264 | /** |
| 265 | * Active on modal, additional attribute is required on standard HTML (check below) |
| 266 | */ |
| 267 | $add_step_attributes = 'active'; |
| 268 | |
| 269 | /** |
| 270 | * Closing div for extra modal wrappers see lines above |
| 271 | */ |
| 272 | $close_div = ''; |
| 273 | |
| 274 | $qr_code = '<img class="qr-code" src="' . ( self::get_qr_code() ) . '" id="wp-2fa-totp-qrcode" />'; |
| 275 | $open30_wrapper = ' |
| 276 | <div class="mb-30 clear-both"> |
| 277 | '; |
| 278 | $open60_wrapper = ' |
| 279 | <div class="modal-60"> |
| 280 | '; |
| 281 | $open40_wrapper = ' |
| 282 | <div class="modal-40"> |
| 283 | '; |
| 284 | $close_div = ' |
| 285 | </div> |
| 286 | '; |
| 287 | $validate_nonce = wp_create_nonce( 'wp-2fa-validate-authcode' ); |
| 288 | |
| 289 | ?> |
| 290 | <div class="step-setting-wrapper <?php echo $add_step_attributes; // phpcs:ignore ?>"> |
| 291 | <div class="mb-20"> |
| 292 | <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'method_help_totp_intro', true ) ); ?> |
| 293 | </div> |
| 294 | <?php echo $open30_wrapper . $open40_wrapper; // phpcs:ignore ?> |
| 295 | |
| 296 | <div class="qr-code-wrapper"> |
| 297 | <?php echo $qr_code; // phpcs:ignore ?> |
| 298 | </div> |
| 299 | <?php |
| 300 | echo $close_div; // phpcs:ignore |
| 301 | echo $open60_wrapper; // phpcs:ignore |
| 302 | ?> |
| 303 | |
| 304 | <div class="radio-cells option-pill mb-0"> |
| 305 | <ol class="wizard-custom-counter"> |
| 306 | <li><?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'method_help_totp_step_1', true ) ); ?><?php if ( ! empty( WP2FA::get_wp2fa_white_label_setting( 'show_help_text' ) ) ) { ?><span class="wizard-tooltip" data-tooltip-content="data-totp-setup-tooltip-content-wrapper">i</span><?php } ?></li> |
| 307 | <li><?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'method_help_totp_step_2', true ) ); ?> |
| 308 | <div class="app-key-wrapper"> |
| 309 | <input type="text" id="app-key-input" readonly value="<?php echo esc_html( self::get_user()->get_totp_decrypted() ); ?>" class="app-key"> |
| 310 | <?php |
| 311 | if ( is_ssl() ) { |
| 312 | ?> |
| 313 | <span class="click-to-copy"><?php esc_html_e( 'COPY', 'wp-2fa' ); ?></span> |
| 314 | <?php } ?> |
| 315 | </div> |
| 316 | </li> |
| 317 | <li><?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'method_help_totp_step_3', true ) ); ?></li> |
| 318 | </ol> |
| 319 | </div> |
| 320 | <?php |
| 321 | echo $close_div; // phpcs:ignore |
| 322 | echo $close_div; // phpcs:ignore |
| 323 | ?> |
| 324 | <?php if ( ! empty( WP2FA::get_wp2fa_white_label_setting( 'show_help_text' ) ) ) : ?> |
| 325 | <div class="tooltip-content-wrapper" data-totp-setup-tooltip-content-wrapper> |
| 326 | <p class="description"><?php esc_html_e( 'Click on the icon of the app that you are using for a detailed guide on how to set it up.', 'wp-2fa' ); ?></p> |
| 327 | <div class="apps-wrapper"> |
| 328 | <?php foreach ( Authentication::get_apps() as $app ) { ?> |
| 329 | <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'] ); // phpcs:ignore ?>"></a> |
| 330 | <?php } ?> |
| 331 | </div> |
| 332 | </div> |
| 333 | <?php endif; ?> |
| 334 | <div class="wp2fa-setup-actions"> |
| 335 | <button class="button wp-2fa-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> |
| 336 | </div> |
| 337 | </div> |
| 338 | <div class="step-setting-wrapper" data-step-title="<?php esc_html_e( 'Verify configuration', 'wp-2fa' ); ?>"> |
| 339 | <div class="mb-20"> |
| 340 | <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'method_verification_totp_pre', true ) ); ?> |
| 341 | </div> |
| 342 | <fieldset> |
| 343 | <label for="2fa-totp-authcode"> |
| 344 | <?php esc_html_e( 'Authentication Code', 'wp-2fa' ); ?> |
| 345 | <input type="tel" name="wp-2fa-totp-authcode" id="wp-2fa-totp-authcode" class="input" value="" size="20" pattern="[0-9]*"/> |
| 346 | </label> |
| 347 | <div class="verification-response"></div> |
| 348 | </fieldset> |
| 349 | <input type="hidden" name="wp-2fa-totp-key" value="<?php echo esc_attr( self::get_user()->get_totp_decrypted() ); ?>" /> |
| 350 | |
| 351 | <a href="#" class="modal__btn button button-primary wp-2fa-button-primary" data-validate-authcode-ajax data-nonce="<?php echo esc_attr( $validate_nonce ); ?>"><?php esc_html_e( 'Validate & Save', 'wp-2fa' ); ?></a> |
| 352 | <button class="modal__btn 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> |
| 353 | </div> |
| 354 | |
| 355 | <?php |
| 356 | } |
| 357 | |
| 358 | /** |
| 359 | * Reconfigures email form |
| 360 | * |
| 361 | * @since 1.7 |
| 362 | * |
| 363 | * @return void |
| 364 | */ |
| 365 | public static function email_configure() { |
| 366 | |
| 367 | if ( ! self::is_mail_enabled() ) { |
| 368 | return; |
| 369 | } |
| 370 | |
| 371 | $setupnonce = wp_create_nonce( 'wp-2fa-send-setup-email' ); |
| 372 | |
| 373 | $validate_nonce = wp_create_nonce( 'wp-2fa-validate-authcode' ); |
| 374 | ?> |
| 375 | <div class="step-setting-wrapper active"> |
| 376 | <div class="mb-20"> |
| 377 | <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'method_help_hotp_intro', true ) ); ?> |
| 378 | </div> |
| 379 | <fieldset class="radio-cells"> |
| 380 | <div class="option-pill"> |
| 381 | <label for="use_wp_email"> |
| 382 | <input type="radio" name="wp_2fa_email_address" id="use_wp_email" value="<?php echo esc_attr( self::get_user()->get_2fa_wp_user()->user_email ); ?>" checked> |
| 383 | <span><?php esc_html_e( 'Use my user email (', 'wp-2fa' ); ?><small><?php echo esc_attr( self::get_user()->get_2fa_wp_user()->user_email ); ?></small><?php esc_html_e( ')', 'wp-2fa' ); ?></span> |
| 384 | </label> |
| 385 | </div> |
| 386 | <?php |
| 387 | if ( Settings::get_role_or_default_setting( 'specify-email_hotp', self::get_user()->get_2fa_wp_user() ) ) { |
| 388 | ?> |
| 389 | <div class="option-pill"> |
| 390 | <label for="use_custom_email"> |
| 391 | <input type="radio" name="wp_2fa_email_address" id="use_custom_email" value="use_custom_email"> |
| 392 | <span><?php esc_html_e( 'Use a different email address:', 'wp-2fa' ); ?></span> |
| 393 | <?php esc_html_e( 'Email address', 'wp-2fa' ); ?> |
| 394 | <input type="email" name="custom-email-address" id="custom-email-address" class="input" value=""/> |
| 395 | </label> |
| 396 | </div> |
| 397 | <?php |
| 398 | } |
| 399 | ?> |
| 400 | </fieldset> |
| 401 | <p class="description"><?php esc_html_e( 'To complete the 2FA configuration you will be sent a one-time code over email, therefore you should have access to the mailbox of this email address. If you do not receive the email with the one-time code please check your spam folder and contact your administrator.', 'wp-2fa' ); ?></p><br> |
| 402 | |
| 403 | <?php |
| 404 | echo sprintf( '<b>%1$1s</b> %2$1s %3$1s', |
| 405 | esc_html__( 'IMPORTANT: ', 'wp-2fa' ), |
| 406 | esc_html__( 'To ensure you always receive the one-time code whitelist the email address from which the codes are sent. This is ', 'wp-2fa' ), |
| 407 | esc_attr( self::get_user()->get_2fa_wp_user()->user_email ) |
| 408 | ); |
| 409 | ?> |
| 410 | |
| 411 | <div class="wp2fa-setup-actions"> |
| 412 | <button class="button button-primary wp-2fa-button-primary" name="next_step_setting_email_verify" value="<?php esc_attr_e( 'I\'m Ready', 'wp-2fa' ); ?>" data-trigger-setup-email data-user-id="<?php echo esc_attr( self::get_user()->get_2fa_wp_user()->ID ); ?>" data-nonce="<?php echo esc_attr( $setupnonce ); ?>" type="button"><?php esc_html_e( 'I\'m Ready', 'wp-2fa' ); ?></button> |
| 413 | |
| 414 | </div> |
| 415 | </div> |
| 416 | |
| 417 | <div class="step-setting-wrapper" data-step-title="<?php esc_html_e( 'Verify configuration', 'wp-2fa' ); ?>" id="2fa-wizard-email"> |
| 418 | <div class="mb-20"> |
| 419 | <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'method_verification_hotp_pre', true ) ); ?> |
| 420 | </div> |
| 421 | <fieldset> |
| 422 | <label for="2fa-email-authcode"> |
| 423 | <?php esc_html_e( 'Authentication Code', 'wp-2fa' ); ?> |
| 424 | <input type="tel" name="wp-2fa-email-authcode" id="wp-2fa-email-authcode" class="input" value="" size="20" pattern="[0-9]*"/> |
| 425 | </label> |
| 426 | <div class="verification-response"></div> |
| 427 | </fieldset> |
| 428 | <br /> |
| 429 | <a href="#" class="button wp-2fa-button-primary" data-validate-authcode-ajax data-nonce="<?php echo esc_attr( $validate_nonce ); ?>"><?php esc_html_e( 'Validate & Save', 'wp-2fa' ); ?></a> |
| 430 | <a href="#" class="button wp-2fa-button-primary resend-email-code" data-trigger-setup-email data-user-id="<?php echo esc_attr( self::get_user()->get_2fa_wp_user()->ID ); ?>" data-nonce="<?php echo esc_attr( $setupnonce ); ?>"> |
| 431 | <span class="resend-inner"><?php esc_html_e( 'Send me another code', 'wp-2fa' ); ?></span> |
| 432 | </a> |
| 433 | <button class="wp-2fa-button-secondary button" data-close-2fa-modal aria-label="Close this dialog window"><?php esc_html_e( 'Cancel', 'wp-2fa' ); ?></button> |
| 434 | </div> |
| 435 | <?php |
| 436 | } |
| 437 | |
| 438 | /** |
| 439 | * Configure backup codes step |
| 440 | * |
| 441 | * @since 1.7 |
| 442 | * |
| 443 | * @return void |
| 444 | */ |
| 445 | public static function backup_codes_configure() { |
| 446 | |
| 447 | $user_type = User_Utils::determine_user_2fa_status( self::get_user()->get_2fa_wp_user() ); |
| 448 | |
| 449 | $redirect = self::determine_redirect_url(); |
| 450 | |
| 451 | $nonce = self::json_nonce(); |
| 452 | ?> |
| 453 | <div class="step-setting-wrapper active"> |
| 454 | <?php |
| 455 | if ( in_array( 'user_needs_to_setup_backup_codes', $user_type, true ) ) { |
| 456 | ?> |
| 457 | <div class="mb-20"> |
| 458 | <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'backup_codes_intro_continue', true ) ); ?> |
| 459 | </div> |
| 460 | <?php } else { ?> |
| 461 | <div class="mb-20"> |
| 462 | <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'backup_codes_intro', true ) ); ?> |
| 463 | </div> |
| 464 | <?php } ?> |
| 465 | <div class="wp2fa-setup-actions"> |
| 466 | <?php if ( in_array( 'user_needs_to_setup_backup_codes', $user_type, true ) ) { ?> |
| 467 | <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 data-nonce="<?php echo esc_attr( $nonce ); ?>"> |
| 468 | <?php esc_html_e( 'Generate list of backup codes', 'wp-2fa' ); ?> |
| 469 | </button> |
| 470 | <?php |
| 471 | if ( ! empty( $redirect ) ) { |
| 472 | ?> |
| 473 | <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary wp-2fa-button-secondary wp-2fa-button-secondary close-first-time-wizard"> |
| 474 | <?php esc_html_e( 'I’ll generate them later', 'wp-2fa' ); ?> |
| 475 | </a> |
| 476 | <?php |
| 477 | } else { |
| 478 | ?> |
| 479 | <a href="#" class="button wp-2fa-button-secondary" data-close-2fa-modal value="<?php esc_attr_e( 'I’ll generate them later', 'wp-2fa' ); ?>"> |
| 480 | <?php esc_html_e( 'I’ll generate them later', 'wp-2fa' ); ?> |
| 481 | </a> |
| 482 | <?php } ?> |
| 483 | <?php } else { ?> |
| 484 | <?php |
| 485 | if ( ! empty( $redirect ) ) { |
| 486 | ?> |
| 487 | <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary wp-2fa-button-secondary close-first-time-wizard"> |
| 488 | <?php esc_html_e( 'Close wizard', 'wp-2fa' ); ?> |
| 489 | </a> |
| 490 | <?php |
| 491 | } else { |
| 492 | ?> |
| 493 | <a href="#" class="button button-secondary wp-2fa-button-secondary" data-reload> |
| 494 | <?php esc_html_e( 'Close wizard', 'wp-2fa' ); ?> |
| 495 | </a> |
| 496 | <?php } ?> |
| 497 | <?php } ?> |
| 498 | </div> |
| 499 | </div> |
| 500 | <?php |
| 501 | } |
| 502 | |
| 503 | /** |
| 504 | * Generate backup codes step |
| 505 | * |
| 506 | * @since 1.7 |
| 507 | * |
| 508 | * @return void |
| 509 | */ |
| 510 | public static function generate_backup_codes() { |
| 511 | $nonce = self::json_nonce(); |
| 512 | |
| 513 | ?> |
| 514 | <div class="step-setting-wrapper active" data-step-title="<?php esc_html_e( 'Generate codes', 'wp-2fa' ); ?>"> |
| 515 | <div class="mb-20"> |
| 516 | <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'backup_codes_generate_intro', true ) ); ?> |
| 517 | </div> |
| 518 | <div class="wp2fa-setup-actions"> |
| 519 | <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 ); ?>"> |
| 520 | <?php esc_html_e( 'Generate list of backup codes', 'wp-2fa' ); ?> |
| 521 | </button> |
| 522 | <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=""> |
| 523 | <?php esc_html_e( 'I’ll generate them later', 'wp-2fa' ); ?> |
| 524 | </a> |
| 525 | </div> |
| 526 | </div> |
| 527 | |
| 528 | <?php |
| 529 | } |
| 530 | |
| 531 | /** |
| 532 | * Creates link for generating the backup codes |
| 533 | * |
| 534 | * @since 1.7 |
| 535 | * |
| 536 | * @return string |
| 537 | */ |
| 538 | public static function get_generate_codes_link() { |
| 539 | $nonce = self::json_nonce(); |
| 540 | |
| 541 | $label = __( 'Backup 2FA methods:', 'wp-2fa' ); |
| 542 | |
| 543 | 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>'; |
| 544 | } |
| 545 | |
| 546 | /** |
| 547 | * Shows the wrapper where backup code are generated and showed to the user |
| 548 | * |
| 549 | * @param boolean $backup_only - If we want to show backup window only - sets the class of the div to active. |
| 550 | * |
| 551 | * @since 1.7 |
| 552 | * |
| 553 | * @return void |
| 554 | */ |
| 555 | public static function generated_backup_codes( $backup_only = false ) { |
| 556 | $nonce = self::json_nonce(); |
| 557 | |
| 558 | $redirect = self::determine_redirect_url(); |
| 559 | |
| 560 | ?> |
| 561 | <div class="step-setting-wrapper align-center<?php echo ( $backup_only ) ? ' active' : ''; ?>" data-step-title="<?php esc_html_e( 'Your backup codes', 'wp-2fa' ); ?>"> |
| 562 | <div class="mb-20"> |
| 563 | <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'backup_codes_generated', true ) ); ?> |
| 564 | </div> |
| 565 | <div class="backup-key-wrapper"> |
| 566 | <textarea id="backup-codes-wrapper" readonly rows="4" cols="50" class="app-key"></textarea> |
| 567 | </div> |
| 568 | <div class="wp2fa-setup-actions"> |
| 569 | <?php if ( is_ssl() ) { ?> |
| 570 | <button class="button button-primary wp-2fa-button-primary" type="submit" value="<?php esc_attr_e( 'Download', 'wp-2fa' ); ?>" data-trigger-backup-code-copy> |
| 571 | <?php esc_html_e( 'Copy', 'wp-2fa' ); ?> |
| 572 | </button> |
| 573 | <?php } else { ?> |
| 574 | <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( self::get_user()->get_2fa_wp_user()->display_name ); ?>" data-website-url="<?php echo esc_attr( get_home_url() ); ?>"> |
| 575 | <?php esc_html_e( 'Download', 'wp-2fa' ); ?> |
| 576 | </button> |
| 577 | <?php } ?> |
| 578 | <button class="button button-primary wp-2fa-button-primary" 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::get_user()->get_2fa_wp_user()->display_name ); ?>" data-website-url="<?php echo esc_attr( get_home_url() ); ?>"> |
| 579 | <?php esc_html_e( 'Print', 'wp-2fa' ); ?> |
| 580 | </button> |
| 581 | |
| 582 | <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 data-nonce="<?php echo esc_attr( wp_create_nonce( 'wp-2fa-send-backup-codes-email-nonce' ) ); ?>" data-user-id="<?php echo esc_attr( self::get_user()->get_2fa_wp_user()->ID ); ?>" data-website-url="<?php echo esc_attr( get_home_url() ); ?>"> |
| 583 | <?php esc_html_e( 'Send me the codes via email', 'wp-2fa' ); ?> |
| 584 | </button> |
| 585 | <?php |
| 586 | if ( ! empty( $redirect ) ) { |
| 587 | ?> |
| 588 | <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary wp-2fa-button-secondary wp-2fa-button-secondary close-first-time-wizard"> |
| 589 | <?php esc_html_e( 'I\'m ready, close the wizard', 'wp-2fa' ); ?> |
| 590 | </a> |
| 591 | <?php |
| 592 | } else { |
| 593 | ?> |
| 594 | <button class="button button-secondary wp-2fa-button-secondary wp-2fa-button-secondary" type="submit" data-close-2fa-modal-and-refresh> |
| 595 | <?php esc_html_e( 'I\'m ready, close the wizard', 'wp-2fa' ); ?> |
| 596 | </button> |
| 597 | <?php } ?> |
| 598 | </div> |
| 599 | </div> |
| 600 | <?php |
| 601 | } |
| 602 | |
| 603 | /** |
| 604 | * Final step for congratulating the user |
| 605 | * |
| 606 | * @since 1.7 |
| 607 | * |
| 608 | * @param boolean $setup_wizard - Is that a call from setup wizard or not. |
| 609 | * |
| 610 | * @return void |
| 611 | */ |
| 612 | public static function congratulations_step( $setup_wizard = false ) { |
| 613 | |
| 614 | if ( $setup_wizard ) { |
| 615 | self::congratulations_step_plugin_wizard(); |
| 616 | return; |
| 617 | } |
| 618 | ?> |
| 619 | |
| 620 | <div class="step-setting-wrapper active"> |
| 621 | <div class="mb-20"> |
| 622 | <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'no_further_action', true ) ); ?> |
| 623 | </div> |
| 624 | <div class="wp2fa-setup-actions"> |
| 625 | <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> |
| 626 | </div> |
| 627 | </div> |
| 628 | <?php |
| 629 | } |
| 630 | |
| 631 | /** |
| 632 | * Final step for congratulating the user |
| 633 | * |
| 634 | * @since 1.7 |
| 635 | * |
| 636 | * @return void |
| 637 | */ |
| 638 | public static function congratulations_step_plugin_wizard() { |
| 639 | $redirect = ( '' !== self::determine_redirect_url() ) ? self::determine_redirect_url() : get_edit_profile_url( self::get_user()->get_2fa_wp_user()->ID ); |
| 640 | $slide_title = ( User_Helper::is_excluded( self::get_user()->get_2fa_wp_user()->ID ) ) ? esc_html__( 'Congratulations.', 'wp-2fa' ) : esc_html__( 'Congratulations, you\'re almost there...', 'wp-2fa' ); |
| 641 | ?> |
| 642 | <h3><?php echo \esc_html( $slide_title ); ?></h3> |
| 643 | <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> |
| 644 | |
| 645 | <?php |
| 646 | if ( User_Helper::is_excluded( self::get_user()->get_2fa_wp_user()->ID ) ) { |
| 647 | ?> |
| 648 | <div class="wp2fa-setup-actions"> |
| 649 | <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary wp-2fa-button-secondary close-first-time-wizard"> |
| 650 | <?php esc_html_e( 'Close wizard', 'wp-2fa' ); ?> |
| 651 | </a> |
| 652 | </div> |
| 653 | <?php |
| 654 | } else { |
| 655 | ?> |
| 656 | <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> |
| 657 | <div class="wp2fa-setup-actions"> |
| 658 | <a href="<?php echo esc_url( Settings::get_setup_page_link() ); ?>" class="button button-primary wp-2fa-button-secondary"> |
| 659 | <?php esc_html_e( 'Configure 2FA now', 'wp-2fa' ); ?> |
| 660 | </a> |
| 661 | <a href="<?php echo esc_url( Settings::get_settings_page_link() ); ?>" class="button button-secondary wp-2fa-button-secondary close-first-time-wizard"> |
| 662 | <?php esc_html_e( 'Close wizard & configure 2FA later', 'wp-2fa' ); ?> |
| 663 | </a> |
| 664 | </div> |
| 665 | <?php } ?> |
| 666 | <?php |
| 667 | } |
| 668 | |
| 669 | /** |
| 670 | * Shows the methods in the modal wizard, so the user can choose from the available ones |
| 671 | * |
| 672 | * @return void |
| 673 | */ |
| 674 | public static function show_modal_methods() { |
| 675 | if ( self::is_totp_enabled() ) { |
| 676 | ?> |
| 677 | <div class="wizard-step" id="2fa-wizard-totp"> |
| 678 | <fieldset> |
| 679 | <?php self::totp_configure(); ?> |
| 680 | </fieldset> |
| 681 | </div> |
| 682 | <?php |
| 683 | } |
| 684 | if ( self::is_mail_enabled() ) { |
| 685 | ?> |
| 686 | <div class="wizard-step" id="2fa-wizard-email"> |
| 687 | <fieldset> |
| 688 | <?php self::email_configure(); ?> |
| 689 | </fieldset> |
| 690 | </div> |
| 691 | <?php |
| 692 | } |
| 693 | |
| 694 | /** |
| 695 | * Add an option for external providers to add their own modal methods options. |
| 696 | * |
| 697 | * @since 2.0.0 |
| 698 | */ |
| 699 | do_action( WP_2FA_PREFIX . 'modal_methods' ); |
| 700 | } |
| 701 | |
| 702 | /** |
| 703 | * Gets the current user |
| 704 | * |
| 705 | * @since 1.7 |
| 706 | * |
| 707 | * @return \WP2FA\Admin\User |
| 708 | */ |
| 709 | public static function get_user() { |
| 710 | if ( null === self::$user ) { |
| 711 | self::$user = User::get_instance(); |
| 712 | } |
| 713 | |
| 714 | return self::$user; |
| 715 | } |
| 716 | |
| 717 | /** |
| 718 | * Choosing backup method step |
| 719 | * When there are more than one backup method - give the user ability to choose one |
| 720 | * |
| 721 | * @return void |
| 722 | * |
| 723 | * @since 2.0.0 |
| 724 | */ |
| 725 | public static function choose_backup_method() { |
| 726 | $redirect = self::determine_redirect_url(); |
| 727 | ?> |
| 728 | <div class="wizard-step" id="2fa-wizard-backup-methods"> |
| 729 | <div class="option-pill mb-20"> |
| 730 | <?php echo wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'backup_codes_intro_multi', true ) ); ?> |
| 731 | </div> |
| 732 | <div class="radio-cells"> |
| 733 | <?php |
| 734 | $backup_methods = Settings::get_backup_methods(); |
| 735 | |
| 736 | $i = 0; |
| 737 | foreach ( $backup_methods as $method_name => $method ) { |
| 738 | $checked = ''; |
| 739 | if ( ! $i ) { |
| 740 | $checked = ' checked="checked"'; |
| 741 | } |
| 742 | $i = 1; |
| 743 | ?> |
| 744 | <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> |
| 745 | <?php |
| 746 | } |
| 747 | ?> |
| 748 | </div> |
| 749 | <div class="wp2fa-setup-actions"> |
| 750 | <a id="select-backup-method" href="<?php echo esc_url( Settings::get_setup_page_link() ); ?>" class="button button-primary wp-2fa-button-primary"> |
| 751 | <?php esc_html_e( 'Configure backup 2FA method', 'wp-2fa' ); ?> |
| 752 | </a> |
| 753 | <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary wp-2fa-button-secondary close-first-time-wizard" <?php echo ( ( '' === trim( $redirect ) ) ? 'data-close-it=""' : '' ); ?> > |
| 754 | <?php esc_html_e( 'Close wizard & configure 2FA later', 'wp-2fa' ); ?> |
| 755 | </a> |
| 756 | <script> |
| 757 | const closeButton = document.querySelector('[data-close-it]'); |
| 758 | |
| 759 | closeButton.addEventListener('click', (event) => { |
| 760 | event.preventDefault(); |
| 761 | let url = new URL( location.href ); |
| 762 | let params = new URLSearchParams( url.search ); |
| 763 | params.delete('show'); |
| 764 | location.replace( `${location.pathname}?${params}` ); |
| 765 | }); |
| 766 | </script> |
| 767 | </div> |
| 768 | </div> |
| 769 | <?php |
| 770 | } |
| 771 | |
| 772 | /** |
| 773 | * Determines the redirect url for the user |
| 774 | * |
| 775 | * @return string |
| 776 | * |
| 777 | * @since 2.0.0 |
| 778 | */ |
| 779 | public static function determine_redirect_url(): string { |
| 780 | if ( null === self::$redirect_url ) { |
| 781 | $redirect_page = Settings::get_role_or_default_setting( 'redirect-user-custom-page-global', self::get_user()->get_2fa_wp_user() ); |
| 782 | self::$redirect_url = ( '' !== trim( $redirect_page ) ) ? \trailingslashit( get_site_url() ) . $redirect_page : ''; |
| 783 | |
| 784 | if ( |
| 785 | 'yes' === Settings::get_role_or_default_setting( 'create-custom-user-page', self::get_user()->get_2fa_wp_user() ) || |
| 786 | 'yes' === Settings::get_role_or_default_setting( 'create-custom-user-page' ) ) { |
| 787 | if ( |
| 788 | '' !== trim( Settings::get_role_or_default_setting( 'redirect-user-custom-page', self::get_user()->get_2fa_wp_user() ) ) || |
| 789 | '' !== trim( Settings::get_role_or_default_setting( 'redirect-user-custom-page' ) ) ) { |
| 790 | if ( 'yes' === Settings::get_role_or_default_setting( 'create-custom-user-page', self::get_user()->get_2fa_wp_user() ) ) { |
| 791 | self::$redirect_url = trailingslashit( get_site_url() ) . Settings::get_role_or_default_setting( 'redirect-user-custom-page', self::get_user()->get_2fa_wp_user() ); |
| 792 | } else { |
| 793 | self::$redirect_url = trailingslashit( get_site_url() ) . Settings::get_role_or_default_setting( 'redirect-user-custom-page' ); |
| 794 | } |
| 795 | } |
| 796 | } |
| 797 | } |
| 798 | |
| 799 | return self::$redirect_url; |
| 800 | } |
| 801 | |
| 802 | /** |
| 803 | * Generates nonce for JSON calls |
| 804 | * |
| 805 | * @since 1.7 |
| 806 | * |
| 807 | * @return string |
| 808 | */ |
| 809 | protected static function json_nonce() { |
| 810 | if ( null === self::$json_nonce ) { |
| 811 | self::$json_nonce = wp_create_nonce( 'wp-2fa-backup-codes-generate-json-' . self::get_user()->get_2fa_wp_user()->ID ); |
| 812 | } |
| 813 | |
| 814 | return self::$json_nonce; |
| 815 | } |
| 816 | |
| 817 | /** |
| 818 | * Returns the status of the totp method (enabled | disabled) |
| 819 | * |
| 820 | * @since 1.7 |
| 821 | * |
| 822 | * @return boolean |
| 823 | */ |
| 824 | private static function is_totp_enabled(): bool { |
| 825 | if ( null === self::$totp_enabled ) { |
| 826 | self::$totp_enabled = empty( Settings::get_role_or_default_setting( 'enable_totp', 'current' ) ) ? false : true; |
| 827 | } |
| 828 | |
| 829 | return self::$totp_enabled; |
| 830 | } |
| 831 | |
| 832 | /** |
| 833 | * Returns the status of the mail method (enabled | disabled) |
| 834 | * |
| 835 | * @since 1.7 |
| 836 | * |
| 837 | * @return boolean |
| 838 | */ |
| 839 | private static function is_mail_enabled(): bool { |
| 840 | if ( null === self::$email_enabled ) { |
| 841 | self::$email_enabled = empty( Settings::get_role_or_default_setting( 'enable_email', 'current' ) ) ? false : true; |
| 842 | } |
| 843 | |
| 844 | return self::$email_enabled; |
| 845 | } |
| 846 | |
| 847 | /** |
| 848 | * Retrieves the QR code |
| 849 | * |
| 850 | * @since 1.7 |
| 851 | * |
| 852 | * @return string |
| 853 | */ |
| 854 | private static function get_qr_code(): string { |
| 855 | |
| 856 | // Setup site information, used when generating our QR code. |
| 857 | $site_name = site_url(); |
| 858 | $site_name = trim( str_replace( array( 'http://', 'https://' ), '', $site_name ), '/' ); |
| 859 | /** |
| 860 | * Changing the title of the login screen for the TOTP method. |
| 861 | * |
| 862 | * @param string $title - The default title. |
| 863 | * @param \WP_User $user - The WP user. |
| 864 | * |
| 865 | * @since 2.0.0 |
| 866 | */ |
| 867 | $totp_title = apply_filters( |
| 868 | WP_2FA_PREFIX . 'totp_title', |
| 869 | $site_name . ':' . self::get_user()->get_2fa_wp_user()->user_login, |
| 870 | self::get_user()->get_2fa_wp_user() |
| 871 | ); |
| 872 | |
| 873 | return Authentication::get_google_qr_code( $totp_title, self::get_user()->get_totp_key(), $site_name ); |
| 874 | } |
| 875 | } |
| 876 |