SettingsPage.php
5 years ago
SetupWizard.php
5 years ago
UserNotices.php
5 years ago
UserProfile.php
5 years ago
UserRegistered.php
5 years ago
SettingsPage.php
1947 lines
| 1 | <?php // phpcs:ignore |
| 2 | |
| 3 | namespace WP2FA\Admin; |
| 4 | |
| 5 | use \WP2FA\WP2FA as WP2FA; |
| 6 | use \WP2FA\Authenticator\Authentication as Authentication; |
| 7 | use \WP2FA\BackgroundProcessing\ProcessUserMetaUpdate as ProcessUserMetaUpdate; |
| 8 | |
| 9 | /** |
| 10 | * SettingsPage - Class for handling settings |
| 11 | */ |
| 12 | class SettingsPage { |
| 13 | |
| 14 | /** |
| 15 | * Create admin menu entru and settings page |
| 16 | */ |
| 17 | public function create_settings_admin_menu() { |
| 18 | // Create sub menu item. |
| 19 | add_options_page( |
| 20 | esc_html__( 'WP 2FA Settings', 'wp-2fa' ), |
| 21 | esc_html__( 'Two-factor Authentication', 'wp-2fa' ), |
| 22 | 'manage_options', |
| 23 | 'wp-2fa-settings', |
| 24 | array( $this, 'settings_page_render' ) |
| 25 | ); |
| 26 | |
| 27 | // Register our settings page. |
| 28 | register_setting( |
| 29 | 'wp_2fa_settings', |
| 30 | 'wp_2fa_settings', |
| 31 | array( $this, 'validate_and_sanitize' ) |
| 32 | ); |
| 33 | |
| 34 | register_setting( |
| 35 | 'wp_2fa_email_settings', |
| 36 | 'wp_2fa_email_settings', |
| 37 | array( $this, 'validate_and_sanitize_email' ) |
| 38 | ); |
| 39 | } |
| 40 | |
| 41 | /** |
| 42 | * Create admin menu entru and settings page |
| 43 | */ |
| 44 | public function create_settings_admin_menu_multisite() { |
| 45 | // Create sub menu item. |
| 46 | add_submenu_page( |
| 47 | 'settings.php', |
| 48 | esc_html__( 'WP 2FA Settings', 'wp-2fa' ), |
| 49 | esc_html__( 'Two-factor Authentication', 'wp-2fa' ), |
| 50 | 'manage_options', |
| 51 | 'wp-2fa-settings', |
| 52 | array( $this, 'settings_page_render' ) |
| 53 | ); |
| 54 | // Register our settings page. |
| 55 | register_setting( |
| 56 | 'wp_2fa_settings', |
| 57 | 'wp_2fa_settings', |
| 58 | array( $this, 'validate_and_sanitize' ) |
| 59 | ); |
| 60 | |
| 61 | register_setting( |
| 62 | 'wp_2fa_email_settings', |
| 63 | 'wp_2fa_email_settings', |
| 64 | array( $this, 'validate_and_sanitize_email' ) |
| 65 | ); |
| 66 | } |
| 67 | |
| 68 | /** |
| 69 | * Render the settings |
| 70 | */ |
| 71 | public function settings_page_render() { |
| 72 | $user = wp_get_current_user(); |
| 73 | $user_id = (int) $user->ID; |
| 74 | if ( ! empty( WP2FA::get_wp2fa_setting( '2fa_settings_last_updated_by' ) ) ) { |
| 75 | $main_user = (int) WP2FA::get_wp2fa_setting( '2fa_settings_last_updated_by' ); |
| 76 | } else { |
| 77 | $main_user = ''; |
| 78 | } |
| 79 | |
| 80 | // Check if new user page has been published. |
| 81 | if ( ! empty( get_transient( 'wp_2fa_new_custom_page_created' ) ) ) { |
| 82 | delete_transient( 'wp_2fa_new_custom_page_created' ); |
| 83 | $new_page_id = WP2FA::get_wp2fa_setting( 'custom-user-page-id' ); |
| 84 | $new_page_permalink = get_permalink( $new_page_id ); |
| 85 | ?> |
| 86 | <div class="wp2fa-modal micromodal-slide" id="new-page-created" aria-hidden="false"> |
| 87 | <div class="modal__overlay" tabindex="-1" data-micromodal-close> |
| 88 | <div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="modal-1-title"> |
| 89 | <main class="modal__content" id="modal-1-content"> |
| 90 | <h3><?php esc_html_e( 'The plugin created the 2FA settings page with the URL:', 'wp-2fa' ); ?></h3> |
| 91 | <h4> |
| 92 | <a target="_blank" href="<?php echo esc_url( $new_page_permalink ); ?>"><?php echo esc_attr( $new_page_permalink ); ?></a> |
| 93 | </h4> |
| 94 | <p> |
| 95 | <?php esc_html_e( 'You can edit this page using the page editor, like you do with all other pages.', 'wp-2fa' ); ?> |
| 96 | </p> |
| 97 | <p> |
| 98 | <?php esc_html_e( 'Use the', 'wp-2fa' ); ?> <strong><?php esc_html_e( '{2fa_settings_page_url}', 'wp-2fa' ); ?></strong> <?php esc_html_e( 'html tag in the email templates to include the URL of the 2FA configuration page when notifying the users to configure two-factor authentication.', 'wp-2fa' ); ?> |
| 99 | </p> |
| 100 | </main> |
| 101 | <footer class="modal__footer"> |
| 102 | <a href="#" class="modal__btn modal__btn-primary" data-trigger-remove-new-page-notice onclick="MicroModal.close('new-page-created');"><?php esc_html_e( 'OK', 'wp-2fa' ); ?></a> |
| 103 | </footer> |
| 104 | </div> |
| 105 | </div> |
| 106 | </div> |
| 107 | <script> |
| 108 | MicroModal.show('new-page-created'); |
| 109 | </script> |
| 110 | <?php |
| 111 | } |
| 112 | ?> |
| 113 | <div class="wp2fa-modal micromodal-slide" id="notify-users" aria-hidden="false"> |
| 114 | <div class="modal__overlay" tabindex="-1" data-micromodal-close> |
| 115 | <div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="modal-1-title"> |
| 116 | <main class="modal__content" id="modal-1-content"> |
| 117 | <h3><?php esc_html_e( 'Notify users?', 'wp-2fa' ); ?></h3> |
| 118 | <p> |
| 119 | <?php esc_html_e( 'Would you like to notify all applicable users based on your changes?', 'wp-2fa' ); ?> |
| 120 | </p> |
| 121 | </main> |
| 122 | <footer class="modal__footer"> |
| 123 | <a href="#" id="send-notification-email" class="modal__btn modal__btn"><?php esc_html_e( 'Notify users & save settings', 'wp-2fa' ); ?></a> |
| 124 | <a href="#" id="save-settings" class="modal__btn modal__btn-primary"><?php esc_html_e( 'Save settings only', 'wp-2fa' ); ?></a> |
| 125 | </footer> |
| 126 | </div> |
| 127 | </div> |
| 128 | </div> |
| 129 | <div class="wrap wp-2fa-settings-wrapper"> |
| 130 | <h2><?php esc_html_e( 'WP 2FA Settings', 'wp-2fa' ); ?></h2> |
| 131 | <hr> |
| 132 | <?php if ( ! empty( WP2FA::get_wp2fa_setting( 'limit_access' ) ) && $main_user !== $user->ID ) { ?> |
| 133 | |
| 134 | <?php |
| 135 | echo esc_html__( 'These settings have been disabled by your site administrator, please contact them for further assistance.', 'wp-2fa' ); |
| 136 | ?> |
| 137 | |
| 138 | <?php } else { ?> |
| 139 | |
| 140 | <div class="nav-tab-wrapper"> |
| 141 | <a href="<?php echo esc_url( add_query_arg( array( 'page' => 'wp-2fa-settings' ), network_admin_url( 'admin.php' ) ) ); ?>" class="nav-tab <?php echo ! isset( $_REQUEST['tab'] ) ? 'nav-tab-active' : ''; ?>"><?php _e( '2FA Settings', 'wp-2fa' ); ?></a> |
| 142 | <a href=" |
| 143 | <?php |
| 144 | echo esc_url( |
| 145 | add_query_arg( |
| 146 | array( |
| 147 | 'page' => 'wp-2fa-settings', |
| 148 | 'tab' => 'email-settings', |
| 149 | ), |
| 150 | network_admin_url( 'admin.php' ) |
| 151 | ) |
| 152 | ); |
| 153 | ?> |
| 154 | " class="nav-tab <?php echo isset( $_REQUEST['tab'] ) && 'email-settings' === $_REQUEST['tab'] ? 'nav-tab-active' : ''; ?>"><?php _e( 'Email Settings & Templates', 'wp-2fa' ); ?></a> |
| 155 | </div> |
| 156 | <?php |
| 157 | if ( ! current_user_can( 'manage_options' ) ) { |
| 158 | return; |
| 159 | } |
| 160 | if ( WP2FA::is_this_multisite() ) { |
| 161 | $action = 'edit.php?action=update_wp2fa_network_options'; |
| 162 | } else { |
| 163 | $action = 'options.php'; |
| 164 | } |
| 165 | if ( ! isset( $_REQUEST['tab'] ) || isset( $_REQUEST['tab'] ) && '2fa-settings' === $_REQUEST['tab'] ) : |
| 166 | ?> |
| 167 | <br/> |
| 168 | <?php |
| 169 | printf( '<p class="description">%1$s <a href="mailto:support@wpwhitesecurity.com">%2$s</a></p>', esc_html__( 'Use the settings below to configure the properties of the two-factor authentication on your website and how users use it. If you have any questions send us an email at', 'wp-2fa' ), esc_html__( 'support@wpwhitesecurity.com', 'wp-2fa' ) ); |
| 170 | ?> |
| 171 | <br/> |
| 172 | <?php $total_users = count_users(); ?> |
| 173 | <form id="wp-2fa-admin-settings" action='<?php echo esc_attr( $action ); ?>' method='post' autocomplete="off" data-2fa-total-users="<?php echo $total_users['total_users']; ?>"> |
| 174 | <?php |
| 175 | if ( ! current_user_can( 'manage_options' ) ) { |
| 176 | return; |
| 177 | } |
| 178 | |
| 179 | settings_fields( 'wp_2fa_settings' ); |
| 180 | $this->select_method_setting(); |
| 181 | $this->select_enforcment_policy_setting(); |
| 182 | $this->user_profile_settings(); |
| 183 | $this->excluded_roles_or_users_setting(); |
| 184 | if ( WP2FA::is_this_multisite() ) { |
| 185 | $this->excluded_network_sites(); |
| 186 | } |
| 187 | $this->grace_period_setting(); |
| 188 | $this->disable_2fa_removal_setting(); |
| 189 | $this->limit_settings_access(); |
| 190 | $this->remove_data_upon_uninstall(); |
| 191 | submit_button(); |
| 192 | ?> |
| 193 | </form> |
| 194 | <?php endif; ?> |
| 195 | |
| 196 | <?php |
| 197 | if ( WP2FA::is_this_multisite() ) { |
| 198 | $action = 'edit.php?action=update_wp2fa_network_email_options'; |
| 199 | } else { |
| 200 | $action = 'options.php'; |
| 201 | } |
| 202 | ?> |
| 203 | |
| 204 | <?php if ( isset( $_REQUEST['tab'] ) && 'email-settings' === $_REQUEST['tab'] ) : ?> |
| 205 | <br/> |
| 206 | <?php |
| 207 | printf( '<p class="description">%1$s <a href="mailto:support@wpwhitesecurity.com">%2$s</a></p>', esc_html__( 'Use the settings below to configure the emails which are sent to users as part of the 2FA plugin. If you have any questions send us an email at', 'wp-2fa' ), esc_html__( 'support@wpwhitesecurity.com', 'wp-2fa' ) ); |
| 208 | ?> |
| 209 | <br/> |
| 210 | <form action='<?php echo esc_attr( $action ); ?>' method='post' autocomplete="off"> |
| 211 | <?php |
| 212 | if ( ! current_user_can( 'manage_options' ) ) { |
| 213 | return; |
| 214 | } |
| 215 | |
| 216 | settings_fields( 'wp_2fa_email_settings' ); |
| 217 | $this->email_from_settings(); |
| 218 | $this->email_settings(); |
| 219 | submit_button( 'Save email settings and templates' ); |
| 220 | ?> |
| 221 | </form> |
| 222 | <?php endif; ?> |
| 223 | |
| 224 | <?php } ?> |
| 225 | </div> |
| 226 | <?php |
| 227 | } |
| 228 | |
| 229 | /** |
| 230 | * General settings |
| 231 | */ |
| 232 | private function select_method_setting() { |
| 233 | ?> |
| 234 | <h3><?php esc_html_e( 'Which two-factor authentication methods can your users use on this website?', 'wp-2fa' ); ?></h3> |
| 235 | <p class="description"> |
| 236 | <?php esc_html_e( 'When you disable one of the below 2FA methods none of your users can use it.', 'wp-2fa' ); ?> |
| 237 | </p> |
| 238 | <table class="form-table"> |
| 239 | <tbody> |
| 240 | <tr> |
| 241 | <th><label for="2fa-method"><?php esc_html_e( 'Select the methods:', 'wp-2fa' ); ?></label></th> |
| 242 | <td> |
| 243 | <fieldset> |
| 244 | <label for="totp"> |
| 245 | <input type="checkbox" id="totp" name="wp_2fa_settings[enable_totp]" value="enable_totp" |
| 246 | <?php checked( 'enable_totp', WP2FA::get_wp2fa_setting( 'enable_totp' ), true ); ?> |
| 247 | > |
| 248 | <?php esc_html_e( 'one-time code via 2FA App (TOTP) - ', 'wp-2fa' ); ?><a href="https://www.wpwhitesecurity.com/support/kb/configuring-2fa-apps/?utm_source=plugin&utm_medium=referral&utm_campaign=wp2fa&utm_content=settings+pages" target="_blank"><?php esc_html_e( 'complete list of supported 2FA apps.', 'wp-2fa' ); ?></a> |
| 249 | </label> |
| 250 | <br/> |
| 251 | <label for="email"> |
| 252 | <input type="checkbox" id="hotp" name="wp_2fa_settings[enable_email]" value="enable_email" |
| 253 | <?php checked( WP2FA::get_wp2fa_setting( 'enable_email' ), 'enable_email' ); ?> |
| 254 | > |
| 255 | <?php esc_html_e( 'one-time code via email (HOTP)', 'wp-2fa' ); ?> |
| 256 | </label> |
| 257 | <br /> |
| 258 | </fieldset> |
| 259 | </td> |
| 260 | </tr> |
| 261 | </tbody> |
| 262 | </table> |
| 263 | <?php |
| 264 | } |
| 265 | |
| 266 | /** |
| 267 | * Policy settings |
| 268 | */ |
| 269 | private function select_enforcment_policy_setting() { |
| 270 | ?> |
| 271 | <h3><?php esc_html_e( 'Do you want to enforce 2FA for some, or all the users? ', 'wp-2fa' ); ?></h3> |
| 272 | <p class="description"> |
| 273 | <?php esc_html_e( 'When you enforce 2FA the users will be prompted to configure 2FA the next time they login. Users have a grace period for configuring 2FA. You can configure the grace period and also exclude user(s) or role(s) in this settings page. ', 'wp-2fa' ); ?> <a href="https://www.wpwhitesecurity.com/support/kb/configure-2fa-policies-enforce/?utm_source=plugin&utm_medium=referral&utm_campaign=wp2fa&utm_content=settings+pages" target="_blank"><?php esc_html_e( 'Learn more.', 'wp-2fa' ); ?></a> |
| 274 | </p> |
| 275 | <table class="form-table"> |
| 276 | <tbody> |
| 277 | <tr> |
| 278 | <th><label for="enforcment-policy"><?php esc_html_e( 'Enforce 2FA on:', 'wp-2fa' ); ?></label></th> |
| 279 | <td> |
| 280 | <fieldset class="contains-hidden-inputs"> |
| 281 | <label for="all-users"> |
| 282 | <input type="radio" name="wp_2fa_settings[enforcment-policy]" id="all-users" value="all-users" |
| 283 | <?php checked( WP2FA::get_wp2fa_setting( 'enforcment-policy' ), 'all-users' ); ?> |
| 284 | > |
| 285 | <span><?php esc_html_e( 'All users', 'wp-2fa' ); ?></span> |
| 286 | </label> |
| 287 | |
| 288 | <br/> |
| 289 | <label for="certain-roles-only"> |
| 290 | <input type="radio" name="wp_2fa_settings[enforcment-policy]" id="certain-roles-only" value="certain-roles-only" |
| 291 | <?php checked( WP2FA::get_wp2fa_setting( 'enforcment-policy' ), 'certain-roles-only' ); ?> |
| 292 | <?php checked( WP2FA::get_wp2fa_setting( 'enforcment-policy' ), 'certain-users-only' ); ?> |
| 293 | data-unhide-when-checked=".certain-roles-only-inputs, .certain-users-only-inputs"> |
| 294 | <span><?php esc_html_e( 'Only for specific users and roles', 'wp-2fa' ); ?></span> |
| 295 | </label> |
| 296 | <fieldset class="hidden certain-roles-only-inputs"> |
| 297 | <br/> |
| 298 | <input type="text" id="enforced_roles_search" placeholder="Search roles"> |
| 299 | <input type="hidden" id="enforced_roles" name="wp_2fa_settings[enforced_roles]" value="<?php echo esc_attr( WP2FA::get_wp2fa_setting( 'enforced_roles' ) ); ?>"> |
| 300 | <div id="enforced_roles_buttons"></div> |
| 301 | </fieldset> |
| 302 | <fieldset class="hidden certain-users-only-inputs"> |
| 303 | <br/> |
| 304 | <input type="text" id="enforced_users_search" placeholder="Search users"> |
| 305 | <input type="hidden" id="enforced_users" name="wp_2fa_settings[enforced_users]" value="<?php echo esc_attr( WP2FA::get_wp2fa_setting( 'enforced_users' ) ); ?>"> |
| 306 | <div id="enforced_users_buttons"></div> |
| 307 | </fieldset> |
| 308 | |
| 309 | <br/> |
| 310 | <label for="do-not-enforce"> |
| 311 | <input type="radio" name="wp_2fa_settings[enforcment-policy]" id="do-not-enforce" value="do-not-enforce" |
| 312 | <?php checked( WP2FA::get_wp2fa_setting( 'enforcment-policy' ), 'do-not-enforce' ); ?> |
| 313 | > |
| 314 | <span><?php esc_html_e( 'Do not enforce on any users', 'wp-2fa' ); ?></span> |
| 315 | </label> |
| 316 | <br/> |
| 317 | </fieldset> |
| 318 | </td> |
| 319 | </tr> |
| 320 | </tbody> |
| 321 | </table> |
| 322 | <?php |
| 323 | } |
| 324 | |
| 325 | /** |
| 326 | * User profile settings |
| 327 | */ |
| 328 | private function user_profile_settings() { |
| 329 | ?> |
| 330 | <h3><?php esc_html_e( 'Can users access the WordPress dashboard or you have custom profile pages? ', 'wp-2fa' ); ?></h3> |
| 331 | <p class="description"> |
| 332 | <?php esc_html_e( 'If your users do not have access to the WordPress dashboard (because you use custom user profile pages) enable this option. Once enabled, the plugin creates a page which ONLY authenticated users can access to configure their user 2FA settings. A link to this page is sent in the 2FA welcome email.', 'wp-2fa' ); ?></a> |
| 333 | </p> |
| 334 | <table class="form-table"> |
| 335 | <tbody> |
| 336 | <tr> |
| 337 | <th><label for="enforcment-policy"><?php esc_html_e( 'Create custom 2FA settings page', 'wp-2fa' ); ?></label></th> |
| 338 | <td> |
| 339 | <fieldset> |
| 340 | <label class="radio-inline"> |
| 341 | <input id="use_custom_page" type="radio" name="wp_2fa_settings[create-custom-user-page]" value="yes" |
| 342 | <?php checked( WP2FA::get_wp2fa_setting( 'create-custom-user-page' ), 'yes' ); ?> |
| 343 | > |
| 344 | <?php esc_html_e( 'Yes', 'wp-2fa' ); ?> |
| 345 | </label> |
| 346 | <label class="radio-inline"> |
| 347 | <input id="dont_use_custom_page" type="radio" name="wp_2fa_settings[create-custom-user-page]" value="no" |
| 348 | <?php checked( WP2FA::get_wp2fa_setting( 'create-custom-user-page' ), 'no' ); ?> |
| 349 | <?php checked( WP2FA::get_wp2fa_setting( 'create-custom-user-page' ), '' ); ?> |
| 350 | > |
| 351 | <?php esc_html_e( 'No', 'wp-2fa' ); ?> |
| 352 | </label> |
| 353 | </fieldset> |
| 354 | </td> |
| 355 | </tr> |
| 356 | <tr class="custom-user-page-setting disabled"> |
| 357 | <th><label for="enforcment-policy"><?php esc_html_e( 'Custom 2FA settings page', 'wp-2fa' ); ?></label></th> |
| 358 | <td> |
| 359 | <fieldset> |
| 360 | <?php |
| 361 | if ( ! empty( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) ) ) { |
| 362 | $custom_slug = get_post_field( 'post_name', get_post( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) ) ); |
| 363 | } else { |
| 364 | $custom_slug = WP2FA::get_wp2fa_setting( 'custom-user-page-url' ); |
| 365 | } |
| 366 | ?> |
| 367 | <?php esc_html_e( 'Specify a URL for the Custom 2FA settings page URL:', 'wp-2fa' ); ?> <?php echo trailingslashit( get_site_url() ); ?> |
| 368 | <input type="text" id="custom-user-page-url" name="wp_2fa_settings[custom-user-page-url]" value="<?php echo sanitize_text_field( $custom_slug ); ?>"> |
| 369 | </fieldset> |
| 370 | <?php |
| 371 | if ( ! empty( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) ) ) { |
| 372 | $edit_post_link = get_edit_post_link( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) ); |
| 373 | $view_post_link = get_permalink( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) ); |
| 374 | ?> |
| 375 | <br> |
| 376 | <a href="<?php echo esc_url( $edit_post_link ); ?>" target="_blank" class="button button-secondary" style="margin-right: 5px;"><?php esc_html_e( 'Edit Page', 'wp-2fa' ); ?></a> <a href="<?php echo esc_url( $view_post_link ); ?>" target="_blank" class="button button-primary"><?php esc_html_e( 'View Page', 'wp-2fa' ); ?></a> |
| 377 | <?php |
| 378 | } |
| 379 | ?> |
| 380 | </td> |
| 381 | </tr> |
| 382 | </tbody> |
| 383 | </table> |
| 384 | <?php |
| 385 | } |
| 386 | |
| 387 | /** |
| 388 | * Role and users exclusion settings |
| 389 | */ |
| 390 | private function excluded_roles_or_users_setting() { |
| 391 | ?> |
| 392 | <br> |
| 393 | <h3><?php esc_html_e( 'Do you want to exclude any users or roles from 2FA? ', 'wp-2fa' ); ?></h3> |
| 394 | <p class="description"> |
| 395 | <?php esc_html_e( 'If you are enforcing 2FA on all users but for some reason you would like to exclude individual user(s) or users with a specific role, you can exclude them below', 'wp-2fa' ); ?> |
| 396 | </p> |
| 397 | <table class="form-table"> |
| 398 | <tbody> |
| 399 | <tr> |
| 400 | <th><label for="enforcment-policy"><?php esc_html_e( 'Exclude the following users', 'wp-2fa' ); ?></label></th> |
| 401 | <td> |
| 402 | <fieldset> |
| 403 | <input type="text" id="excluded_users_search" placeholder="Search user name"> |
| 404 | <input type="hidden" id="excluded_users" name="wp_2fa_settings[excluded_users]" |
| 405 | value="<?php echo sanitize_text_field( WP2FA::get_wp2fa_setting( 'excluded_users' ) ); ?>"> |
| 406 | <div id="excluded_users_buttons"></div> |
| 407 | </fieldset> |
| 408 | </td> |
| 409 | </tr> |
| 410 | <tr> |
| 411 | <th><label for="enforcment-policy"><?php esc_html_e( 'Exclude the following roles:', 'wp-2fa' ); ?></label></th> |
| 412 | <td> |
| 413 | <fieldset> |
| 414 | <input type="text" id="excluded_roles_search" placeholder="Search roles"> |
| 415 | <input type="hidden" id="excluded_roles" name="wp_2fa_settings[excluded_roles]" |
| 416 | value="<?php echo sanitize_text_field( WP2FA::get_wp2fa_setting( 'excluded_roles' ) ); ?>"> |
| 417 | <div id="excluded_roles_buttons"></div> |
| 418 | </fieldset> |
| 419 | </td> |
| 420 | </tr> |
| 421 | </tbody> |
| 422 | </table> |
| 423 | <?php |
| 424 | } |
| 425 | |
| 426 | /** |
| 427 | * Role and users exclusion settings |
| 428 | */ |
| 429 | private function excluded_network_sites() { |
| 430 | ?> |
| 431 | <br> |
| 432 | <h3><?php esc_html_e( 'Do you want to exclude all the users of a site from 2FA? ', 'wp-2fa' ); ?></h3> |
| 433 | <p class="description"> |
| 434 | <?php esc_html_e( 'If you are enforcing 2FA on all users but for some reason you do not want to enforce it on a specific sub site, specify the sub site name below:', 'wp-2fa' ); ?> |
| 435 | </p> |
| 436 | <table class="form-table"> |
| 437 | <tbody> |
| 438 | <tr> |
| 439 | <th><label for="enforcment-policy"><?php esc_html_e( 'Exclude the following sites', 'wp-2fa' ); ?></label></th> |
| 440 | <td> |
| 441 | <fieldset> |
| 442 | <input type="text" id="excluded_sites_search" placeholder="Search sites in your network"> |
| 443 | <input type="hidden" id="excluded_sites" name="wp_2fa_settings[excluded_sites]" |
| 444 | value="<?php echo sanitize_text_field( WP2FA::get_wp2fa_setting( 'excluded_sites' ) ); ?>"> |
| 445 | <div id="excluded_sites_buttons"></div> |
| 446 | </fieldset> |
| 447 | </td> |
| 448 | </tr> |
| 449 | </tbody> |
| 450 | </table> |
| 451 | <?php |
| 452 | } |
| 453 | |
| 454 | /** |
| 455 | * Grace period settings |
| 456 | */ |
| 457 | private function grace_period_setting() { |
| 458 | $user = wp_get_current_user(); |
| 459 | |
| 460 | $grace_period = (int) WP2FA::get_wp2fa_setting( 'grace-period' ); |
| 461 | $testing = get_option( 'wp_2fa_test_grace' ); |
| 462 | if ( '1' === $testing ) { |
| 463 | $grace_max = 600; |
| 464 | } else { |
| 465 | $grace_max = 10; |
| 466 | } |
| 467 | ?> |
| 468 | <br> |
| 469 | <h3><?php esc_html_e( 'Should users be asked to setup 2FA instantly or should they have a grace period?', 'wp-2fa' ); ?></h3> |
| 470 | <p class="description"> |
| 471 | <?php esc_html_e( 'When you enforce 2FA on user(s) they have a grace period to configure 2FA. If they fail to configure it within the configured stipulated time, their account will be locked and have to be unlocked manually. Maximum grace period is 10 days.', 'wp-2fa' ); ?> <a href="https://www.wpwhitesecurity.com/support/kb/configure-grace-period-2fa/?utm_source=plugin&utm_medium=referral&utm_campaign=wp2fa&utm_content=settings+pages" target="_blank"><?php esc_html_e( 'Learn more.', 'wp-2fa' ); ?></a> |
| 472 | </p> |
| 473 | |
| 474 | <table class="form-table"> |
| 475 | <tbody> |
| 476 | <tr> |
| 477 | <th><label for="grace-policy"><?php esc_html_e( 'Grace period:', 'wp-2fa' ); ?></label></th> |
| 478 | <td> |
| 479 | <fieldset class="contains-hidden-inputs"> |
| 480 | <label for="no-grace-period"> |
| 481 | <input type="radio" name="wp_2fa_settings[grace-policy]" id="no-grace-period" value="no-grace-period" |
| 482 | <?php checked( WP2FA::get_wp2fa_setting( 'grace-policy' ), 'no-grace-period' ); ?> |
| 483 | > |
| 484 | <span><?php esc_html_e( 'Users have to configure 2FA straight away.', 'wp-2fa' ); ?></span> |
| 485 | </label> |
| 486 | |
| 487 | <br/> |
| 488 | <label for="use-grace-period"> |
| 489 | <input type="radio" name="wp_2fa_settings[grace-policy]" id="use-grace-period" value="use-grace-period" |
| 490 | <?php checked( WP2FA::get_wp2fa_setting( 'grace-policy' ), 'use-grace-period' ); ?> |
| 491 | data-unhide-when-checked=".grace-period-inputs"> |
| 492 | <span><?php esc_html_e( 'Give users a grace period to configure 2FA', 'wp-2fa' ); ?></span> |
| 493 | </label> |
| 494 | <fieldset class="hidden grace-period-inputs"> |
| 495 | <br/> |
| 496 | <input type="number" id="grace-period" name="wp_2fa_settings[grace-period]" value="<?php echo esc_attr( $grace_period ); ?>" min="1" max="<?php echo esc_attr( $grace_max ); ?>"> |
| 497 | <label class="radio-inline"> |
| 498 | <input type="radio" name="wp_2fa_settings[grace-period-denominator]" value="hours" |
| 499 | <?php checked( WP2FA::get_wp2fa_setting( 'grace-period-denominator' ), 'hours' ); ?> |
| 500 | > |
| 501 | <?php esc_html_e( 'Hours', 'wp-2fa' ); ?> |
| 502 | </label> |
| 503 | <label class="radio-inline"> |
| 504 | <input type="radio" name="wp_2fa_settings[grace-period-denominator]" value="days" |
| 505 | <?php checked( WP2FA::get_wp2fa_setting( 'grace-period-denominator' ), 'days' ); ?> |
| 506 | > |
| 507 | <?php esc_html_e( 'Days', 'wp-2fa' ); ?> |
| 508 | </label> |
| 509 | <?php |
| 510 | $testing = get_option( 'wp_2fa_test_grace' ); |
| 511 | if ( '1' === $testing ) { |
| 512 | ?> |
| 513 | <label class="radio-inline"> |
| 514 | <input type="radio" name="wp_2fa_settings[grace-period-denominator]" value="seconds" |
| 515 | <?php checked( WP2FA::get_wp2fa_setting( 'grace-period-denominator' ), 'seconds' ); ?> |
| 516 | > |
| 517 | <?php esc_html_e( 'Seconds', 'wp-2fa' ); ?> |
| 518 | </label> |
| 519 | <?php |
| 520 | } |
| 521 | |
| 522 | if ( ! empty( WP2FA::get_wp2fa_setting( '2fa_settings_last_updated_by' ) ) ) { |
| 523 | $last_user_to_update_settings = WP2FA::get_wp2fa_setting( '2fa_settings_last_updated_by' ); |
| 524 | } else { |
| 525 | $last_user_to_update_settings = $user->ID; |
| 526 | } |
| 527 | |
| 528 | ?> |
| 529 | <input type="hidden" id="2fa_main_user" name="wp_2fa_settings[2fa_settings_last_updated_by]" value="<?php echo esc_attr( $last_user_to_update_settings ); ?>"> |
| 530 | </fieldset> |
| 531 | <br/> |
| 532 | </fieldset> |
| 533 | </td> |
| 534 | </tr> |
| 535 | </tbody> |
| 536 | </table> |
| 537 | |
| 538 | |
| 539 | <h3><?php esc_html_e( 'How often should the plugin check if a user\'s grace period is over?', 'wp-2fa' ); ?></h3> |
| 540 | <p class="description"> |
| 541 | <?php esc_html_e( 'By default the plugin checks if a users grace periods to setup 2FA has passed when the user tries to login. If you would like the plugin to advise the user within an hour, enable the below option to add a cron job that runs every hour.', 'wp-2fa' ); ?> |
| 542 | </p> |
| 543 | <table class="form-table"> |
| 544 | <tbody> |
| 545 | <tr> |
| 546 | <th><label for="grace-period"><?php esc_html_e( 'Enable cron', 'wp-2fa' ); ?></label></th> |
| 547 | <td> |
| 548 | <fieldset> |
| 549 | <input type="checkbox" id="grace-cron" name="wp_2fa_settings[enable_grace_cron]" value="enable_grace_cron" |
| 550 | <?php checked( 1, WP2FA::get_wp2fa_setting( 'enable_grace_cron' ), true ); ?> |
| 551 | > |
| 552 | <?php esc_html_e( 'Use cron job to check grace periods', 'wp-2fa' ); ?> |
| 553 | </fieldset> |
| 554 | </td> |
| 555 | </tr> |
| 556 | <tr class="disabled destory-session-setting"> |
| 557 | <th><label for="destory-session"><?php esc_html_e( 'Destroy session', 'wp-2fa' ); ?></label></th> |
| 558 | <td> |
| 559 | <fieldset> |
| 560 | <input type="checkbox" id="destory-session" name="wp_2fa_settings[enable_destroy_session]" value="enable_destroy_session" |
| 561 | <?php checked( 1, WP2FA::get_wp2fa_setting( 'enable_destroy_session' ), true ); ?> |
| 562 | > |
| 563 | <?php esc_html_e( 'Destory user session when grace period expires?', 'wp-2fa' ); ?> |
| 564 | </fieldset> |
| 565 | </td> |
| 566 | </tr> |
| 567 | </tbody> |
| 568 | </table> |
| 569 | <?php |
| 570 | } |
| 571 | |
| 572 | /** |
| 573 | * Disable removal of 2FA settings |
| 574 | */ |
| 575 | private function disable_2fa_removal_setting() { |
| 576 | $user = wp_get_current_user(); |
| 577 | ?> |
| 578 | <br> |
| 579 | <h3><?php esc_html_e( 'Should users be able to disable 2FA on their user profile?', 'wp-2fa' ); ?></h3> |
| 580 | <p class="description"> |
| 581 | <?php esc_html_e( 'Users can configure and also disable 2FA on their profile by clicking the "Remove 2FA" button. Enable this setting to disable the Remove 2FA button so users cannot disable 2FA from their user profile.', 'wp-2fa' ); ?> |
| 582 | </p> |
| 583 | <table class="form-table"> |
| 584 | <tbody> |
| 585 | <tr> |
| 586 | <th><label for="hide-remove-2fa"><?php esc_html_e( 'Hide the Remove 2FA button', 'wp-2fa' ); ?></label></th> |
| 587 | <td> |
| 588 | <fieldset> |
| 589 | <input type="checkbox" id="hide-remove-2fa" name="wp_2fa_settings[hide_remove_button]" value="hide_remove_button" |
| 590 | <?php checked( 1, WP2FA::get_wp2fa_setting( 'hide_remove_button' ), true ); ?> |
| 591 | > |
| 592 | <?php esc_html_e( 'Hide the Remove 2FA button on user profile pages', 'wp-2fa' ); ?> |
| 593 | </fieldset> |
| 594 | </td> |
| 595 | </tr> |
| 596 | </tbody> |
| 597 | </table> |
| 598 | <?php |
| 599 | } |
| 600 | |
| 601 | /** |
| 602 | * Limit settings setting |
| 603 | */ |
| 604 | private function limit_settings_access() { |
| 605 | ?> |
| 606 | <br> |
| 607 | <h3><?php esc_html_e( 'Limit 2FA settings access?', 'wp-2fa' ); ?></h3> |
| 608 | <p class="description"> |
| 609 | <?php esc_html_e( 'Use this setting to hide this plugin configuration area from all other admins.', 'wp-2fa' ); ?> |
| 610 | </p> |
| 611 | <table class="form-table"> |
| 612 | <tbody> |
| 613 | <tr> |
| 614 | <th><label for="grace-period"><?php esc_html_e( 'Limited access', 'wp-2fa' ); ?></label></th> |
| 615 | <td> |
| 616 | <fieldset> |
| 617 | <input type="checkbox" id="limit_access" name="wp_2fa_settings[limit_access]" value="limit_access" |
| 618 | <?php checked( 1, WP2FA::get_wp2fa_setting( 'limit_access' ), true ); ?> |
| 619 | > |
| 620 | <?php esc_html_e( 'Hide settings from other administrators', 'wp-2fa' ); ?> |
| 621 | </fieldset> |
| 622 | </td> |
| 623 | </tr> |
| 624 | </tbody> |
| 625 | </table> |
| 626 | <?php |
| 627 | } |
| 628 | |
| 629 | /** |
| 630 | * Limit settings setting |
| 631 | */ |
| 632 | private function remove_data_upon_uninstall() { |
| 633 | ?> |
| 634 | <div class="danger-zone-wrapper"> |
| 635 | <h3><?php esc_html_e( 'Do you want to delete the plugin data from the database upon uninstall?', 'wp-2fa' ); ?></h3> |
| 636 | <p class="description"> |
| 637 | <?php esc_html_e( 'The plugin saves its settings in the WordPress database. By default the plugin settings are kept in the database so if it is installed again, you do not have to reconfigure the plugin. Enable this setting to delete the plugin settings from the database upon uninstall.', 'wp-2fa' ); ?> |
| 638 | </p> |
| 639 | <table class="form-table"> |
| 640 | <tbody> |
| 641 | <tr> |
| 642 | <th><label for="delete_data"><?php esc_html_e( 'Delete data', 'wp-2fa' ); ?></label></th> |
| 643 | <td> |
| 644 | <fieldset> |
| 645 | <input type="checkbox" id="elete_data" name="wp_2fa_settings[delete_data_upon_uninstall]" value="delete_data_upon_uninstall" |
| 646 | <?php checked( 1, WP2FA::get_wp2fa_setting( 'delete_data_upon_uninstall' ), true ); ?> |
| 647 | > |
| 648 | <?php esc_html_e( 'Delete data upon uninstall', 'wp-2fa' ); ?> |
| 649 | </fieldset> |
| 650 | </td> |
| 651 | </tr> |
| 652 | </tbody> |
| 653 | </table> |
| 654 | <table class="form-table hidden"> |
| 655 | <tbody> |
| 656 | <tr> |
| 657 | <th></th> |
| 658 | <td> |
| 659 | <fieldset> |
| 660 | <input type="checkbox" id="notify_users" name="wp_2fa_settings[notify_users]" value="notify_users"> |
| 661 | </fieldset> |
| 662 | </td> |
| 663 | </tr> |
| 664 | </tbody> |
| 665 | </table> |
| 666 | </div> |
| 667 | <?php |
| 668 | } |
| 669 | |
| 670 | /** |
| 671 | * Get all useers |
| 672 | */ |
| 673 | public function get_all_users() { |
| 674 | // Die if user does not have permission to view. |
| 675 | if ( ! current_user_can( 'administrator' ) ) { |
| 676 | die( 'Access Denied.' ); |
| 677 | } |
| 678 | // Filter $_GET array for security. |
| 679 | $get_array = filter_input_array( INPUT_GET ); |
| 680 | |
| 681 | // Die if nonce verification failed. |
| 682 | if ( ! wp_verify_nonce( sanitize_text_field( $get_array['wp_2fa_nonce'] ), 'wp-2fa-settings-nonce' ) ) { |
| 683 | die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) ); |
| 684 | } |
| 685 | // Fetch users. |
| 686 | $users = array(); |
| 687 | if ( WP2FA::is_this_multisite() ) { |
| 688 | $users_args = array( 'blog_id' => 0 ); |
| 689 | } else { |
| 690 | $users_args = array(); |
| 691 | } |
| 692 | |
| 693 | foreach ( get_users( $users_args ) as $user ) { |
| 694 | if ( strpos( $user->user_login, $get_array['term'] ) !== false ) { |
| 695 | array_push( $users, $user->user_login ); |
| 696 | } |
| 697 | } |
| 698 | echo wp_json_encode( $users ); |
| 699 | exit; |
| 700 | } |
| 701 | |
| 702 | /** |
| 703 | * Get all network sites |
| 704 | */ |
| 705 | public function get_all_network_sites() { |
| 706 | // Die if user does not have permission to view. |
| 707 | if ( ! current_user_can( 'administrator' ) ) { |
| 708 | die( 'Access Denied.' ); |
| 709 | } |
| 710 | // Filter $_GET array for security. |
| 711 | $get_array = filter_input_array( INPUT_GET ); |
| 712 | // Die if nonce verification failed. |
| 713 | if ( ! wp_verify_nonce( sanitize_text_field( $get_array['wp_2fa_nonce'] ), 'wp-2fa-settings-nonce' ) ) { |
| 714 | die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) ); |
| 715 | } |
| 716 | // Fetch sites. |
| 717 | $sites_found = array(); |
| 718 | |
| 719 | foreach ( get_sites() as $site ) { |
| 720 | $subsite_id = get_object_vars( $site )['blog_id']; |
| 721 | $subsite_name = get_blog_details( $subsite_id )->blogname; |
| 722 | $site_details = ''; |
| 723 | $site_details[ $subsite_id ] = $subsite_name; |
| 724 | if ( stripos( $subsite_name, $get_array['term'] ) !== false ) { |
| 725 | $site_details = $subsite_name . ':' . $subsite_id; |
| 726 | array_push( $sites_found, $site_details ); |
| 727 | } |
| 728 | } |
| 729 | echo wp_json_encode( $sites_found ); |
| 730 | exit; |
| 731 | } |
| 732 | |
| 733 | /** |
| 734 | * Unlock users accounts if they have overrun grace period |
| 735 | * |
| 736 | * @param int $user_id User ID. |
| 737 | */ |
| 738 | public function unlock_account( $user_id ) { |
| 739 | // Die if user does not have permission to view. |
| 740 | if ( ! current_user_can( 'administrator' ) ) { |
| 741 | die( 'Access Denied.' ); |
| 742 | } |
| 743 | |
| 744 | $grace_period = WP2FA::get_wp2fa_setting( 'grace-period' ); |
| 745 | $grace_period_denominator = WP2FA::get_wp2fa_setting( 'grace-period-denominator' ); |
| 746 | $create_a_string = $grace_period . ' ' . $grace_period_denominator; |
| 747 | // Turn that string into a time. |
| 748 | $grace_expiry = strtotime( $create_a_string ); |
| 749 | |
| 750 | // Filter $_GET array for security. |
| 751 | $get_array = filter_input_array( INPUT_GET ); |
| 752 | $nonce = sanitize_text_field( $get_array['wp_2fa_nonce'] ); |
| 753 | |
| 754 | // Die if nonce verification failed. |
| 755 | if ( ! wp_verify_nonce( $nonce, 'wp-2fa-unlock-account-nonce' ) ) { |
| 756 | die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) ); |
| 757 | } |
| 758 | |
| 759 | if ( isset( $get_array['user_id'] ) ) { |
| 760 | $unlock = delete_user_meta( intval( $get_array['user_id'] ), 'wp_2fa_user_grace_period_expired' ); |
| 761 | $notification = delete_user_meta( intval( $get_array['user_id'] ), 'wp_2fa_locked_account_notification' ); |
| 762 | $update = update_user_meta( intval( $get_array['user_id'] ), 'wp_2fa_grace_period_expiry', $grace_expiry ); |
| 763 | $this->send_account_unlocked_email( intval( $get_array['user_id'] ) ); |
| 764 | add_action( 'admin_notices', array( $this, 'user_unlocked_notice' ) ); |
| 765 | } |
| 766 | } |
| 767 | |
| 768 | /** |
| 769 | * Remove user 2fa config |
| 770 | * |
| 771 | * @param int $user_id User ID. |
| 772 | */ |
| 773 | public function remove_user_2fa( $user_id ) { |
| 774 | // Filter $_GET array for security. |
| 775 | $get_array = filter_input_array( INPUT_GET ); |
| 776 | $nonce = sanitize_text_field( $get_array['wp_2fa_nonce'] ); |
| 777 | |
| 778 | if ( ! wp_verify_nonce( $nonce, 'wp-2fa-remove-user-2fa-nonce' ) ) { |
| 779 | die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) ); |
| 780 | } |
| 781 | |
| 782 | if ( isset( $get_array['user_id'] ) ) { |
| 783 | $user_id = intval( $get_array['user_id'] ); |
| 784 | $wipe_totp_key = delete_user_meta( $user_id, 'wp_2fa_totp_key' ); |
| 785 | $wipe_backup_codes = delete_user_meta( $user_id, 'wp_2fa_backup_codes' ); |
| 786 | $wipe_enabled_methods = delete_user_meta( $user_id, 'wp_2fa_enabled_methods' ); |
| 787 | $wipe_grace_period = delete_user_meta( $user_id, 'wp_2fa_grace_period_expiry' ); |
| 788 | $wipe_email_address = delete_user_meta( $user_id, 'wp_2fa_nominated_email_address' ); |
| 789 | $is_needed = Authentication::is_user_eligible_for_2fa( $user_id ); |
| 790 | if ( $is_needed ) { |
| 791 | if ( 'do-not-enforce' !== WP2FA::get_wp2fa_setting( 'enforcment-policy' ) ) { |
| 792 | // Turn inputs into a useable string. |
| 793 | $create_a_string = WP2FA::get_wp2fa_setting( 'grace-period' ) . ' ' . WP2FA::get_wp2fa_setting( 'grace-period-denominator' ); |
| 794 | // Turn that string into a time. |
| 795 | $grace_expiry = strtotime( $create_a_string ); |
| 796 | update_user_meta( $user_id, 'wp_2fa_grace_period_expiry', $grace_expiry ); |
| 797 | update_user_meta( $user_id, 'wp_2fa_update_nag_dismissed', true ); |
| 798 | } |
| 799 | } |
| 800 | if ( isset( $get_array['admin_reset'] ) ) { |
| 801 | add_action( 'admin_notices', array( $this, 'admin_deleted_2fa_notice' ) ); |
| 802 | } else { |
| 803 | add_action( 'admin_notices', array( $this, 'user_deleted_2fa_notice' ) ); |
| 804 | } |
| 805 | } |
| 806 | } |
| 807 | |
| 808 | /** |
| 809 | * Send account unlocked notification via email. |
| 810 | * |
| 811 | * @param int $user_id user ID. |
| 812 | */ |
| 813 | public static function send_account_unlocked_email( $user_id ) { |
| 814 | // Bail if the user has not enabled this email. |
| 815 | if ( 'enable_account_unlocked_email' !== WP2FA::get_wp2fa_email_templates( 'send_account_unlocked_email' ) ) { |
| 816 | return false; |
| 817 | } |
| 818 | |
| 819 | // Grab user data. |
| 820 | $user = get_userdata( $user_id ); |
| 821 | // Grab user email. |
| 822 | $email = $user->user_email; |
| 823 | // Setup the email contents. |
| 824 | $subject = wp_strip_all_tags( WP2FA::replace_email_strings( WP2FA::get_wp2fa_email_templates( 'user_account_unlocked_email_subject' ) ) ); |
| 825 | $message = wpautop( WP2FA::replace_email_strings( WP2FA::get_wp2fa_email_templates( 'user_account_unlocked_email_body' ), $user_id ) ); |
| 826 | // Specify our desired headers. |
| 827 | $headers = 'Content-type: text/html;charset=utf-8' . "\r\n"; |
| 828 | |
| 829 | if ( 'use-custom-email' === WP2FA::get_wp2fa_email_templates( 'email_from_setting' ) ) { |
| 830 | $headers .= 'From: ' . WP2FA::get_wp2fa_email_templates( 'custom_from_display_name' ) . ' <' . WP2FA::get_wp2fa_email_templates( 'custom_from_email_address' ) . '>' . "\r\n"; |
| 831 | } |
| 832 | |
| 833 | // Fire our email. |
| 834 | $mail = wp_mail( $user->user_email, $subject, $message, $headers ); |
| 835 | } |
| 836 | |
| 837 | /** |
| 838 | * Validate options before saving |
| 839 | * |
| 840 | * @param array $input The settings array. |
| 841 | */ |
| 842 | public function validate_and_sanitize( $input ) { |
| 843 | // Bail if user doesnt have permissions to be here. |
| 844 | if ( ! current_user_can( 'manage_options' ) ) { |
| 845 | return; |
| 846 | } |
| 847 | |
| 848 | // Setup args we may need, depending if this is a MS setup or not. |
| 849 | $users = array(); |
| 850 | $users_args = array(); |
| 851 | if ( WP2FA::is_this_multisite() ) { |
| 852 | $users_args['blog_id'] = 0; |
| 853 | } |
| 854 | $total_users = count_users(); |
| 855 | $batch_size = 2000; |
| 856 | $slices = ceil( $total_users['total_users'] / $batch_size ); |
| 857 | |
| 858 | if ( ! isset( $input['enable_totp'] ) && ! isset( $input['enable_email'] ) ) { |
| 859 | add_settings_error( |
| 860 | 'wp_2fa_settings', |
| 861 | esc_attr( 'enable_email_settings_error' ), |
| 862 | esc_html__( 'At least one 2FA method should be enabled.', 'wp-2fa' ), |
| 863 | 'error' |
| 864 | ); |
| 865 | } |
| 866 | |
| 867 | // Compare current to old value to see if a method which was once enabled, has now been disabled. |
| 868 | if ( ! isset( $input['enable_totp'] ) && 'enable_totp' === WP2FA::get_wp2fa_setting( 'enable_totp' ) || ! isset( $input['enable_email'] ) && 'enable_email' === WP2FA::get_wp2fa_setting( 'enable_email' ) ) { |
| 869 | if ( ! isset( $input['enable_totp'] ) && 'enable_totp' === WP2FA::get_wp2fa_setting( 'enable_totp' ) ) { |
| 870 | $removing = 'totp'; |
| 871 | } elseif ( ! isset( $input['enable_email'] ) && 'enable_email' === WP2FA::get_wp2fa_setting( 'enable_email' ) ) { |
| 872 | $removing = 'email'; |
| 873 | } |
| 874 | // Flush the old expiry away from ALL users, we will re-apply them based on the current setup at the end of this. |
| 875 | for ( $count = 0; $count < $slices; $count++ ) { |
| 876 | $users_args = array( |
| 877 | 'number' => $batch_size, |
| 878 | 'offset' => $count * $batch_size, |
| 879 | 'fields' => array( 'ID' ), |
| 880 | ); |
| 881 | $users = get_users( $users_args ); |
| 882 | if ( ! empty( $users ) ) { |
| 883 | $background_process = new ProcessUserMetaUpdate(); |
| 884 | $item_to_process = array(); |
| 885 | $item_to_process['users'] = $users; |
| 886 | $item_to_process['task'] = 'remove_enabled_methods'; |
| 887 | $item_to_process['method_to_remove'] = $removing; |
| 888 | $background_process->push_to_queue( $item_to_process ); |
| 889 | } |
| 890 | |
| 891 | $background_process->save()->dispatch(); |
| 892 | } |
| 893 | } |
| 894 | |
| 895 | if ( isset( $input['enable_totp'] ) && 'enable_totp' === $input['enable_totp'] ) { |
| 896 | $output['enable_totp'] = sanitize_text_field( $input['enable_totp'] ); |
| 897 | } |
| 898 | |
| 899 | if ( isset( $input['enable_email'] ) && 'enable_email' === $input['enable_email'] ) { |
| 900 | $output['enable_email'] = sanitize_text_field( $input['enable_email'] ); |
| 901 | } |
| 902 | |
| 903 | if ( isset( $input['enforcment-policy'] ) && 'all-users' === $input['enforcment-policy'] || isset( $input['enforcment-policy'] ) && 'certain-users-only' === $input['enforcment-policy'] || isset( $input['enforcment-policy'] ) && 'certain-roles-only' === $input['enforcment-policy'] || isset( $input['enforcment-policy'] ) && 'do-not-enforce' === $input['enforcment-policy'] ) { |
| 904 | // Clear enforced roles/users if setting has changed. |
| 905 | if ( 'all-users' === $input['enforcment-policy'] ) { |
| 906 | $input['enforced_users'] = ''; |
| 907 | $input['enforced_roles'] = ''; |
| 908 | } |
| 909 | |
| 910 | $output['enforcment-policy'] = sanitize_text_field( $input['enforcment-policy'] ); |
| 911 | } |
| 912 | |
| 913 | if ( WP2FA::get_wp2fa_setting( 'enforcment-policy' ) !== $input['enforcment-policy'] && 'do-not-enforce' === $input['enforcment-policy'] ) { |
| 914 | $input['enforced_users'] = ''; |
| 915 | $input['enforced_roles'] = ''; |
| 916 | } |
| 917 | |
| 918 | if ( 'certain-roles-only' === $input['enforcment-policy'] && empty( $input['enforced_roles'] ) && empty( $input['enforced_users'] ) ) { |
| 919 | add_settings_error( |
| 920 | 'wp_2fa_settings', |
| 921 | esc_attr( 'enforced_roles_settings_error' ), |
| 922 | esc_html__( 'You must specify at least one role or user', 'wp-2fa' ), |
| 923 | 'error' |
| 924 | ); |
| 925 | } |
| 926 | |
| 927 | if ( isset( $input['enforced_roles'] ) ) { |
| 928 | $output['enforced_roles'] = trim( sanitize_text_field( $input['enforced_roles'] ) ); |
| 929 | } |
| 930 | |
| 931 | if ( isset( $input['enforced_users'] ) ) { |
| 932 | $output['enforced_users'] = trim( sanitize_text_field( $input['enforced_users'] ) ); |
| 933 | } |
| 934 | |
| 935 | if ( isset( $input['excluded_users'] ) ) { |
| 936 | $output['excluded_users'] = trim( sanitize_text_field( $input['excluded_users'] ) ); |
| 937 | |
| 938 | // Wipe user 2fa data. |
| 939 | $user_array = explode( ',', $output['excluded_users'] ); |
| 940 | foreach ( $user_array as $user ) { |
| 941 | if ( ! empty( $user ) ) { |
| 942 | $user_to_wipe = get_user_by( 'login', $user ); |
| 943 | $wipe_totp_key = delete_user_meta( $user_to_wipe->ID, 'wp_2fa_totp_key' ); |
| 944 | $wipe_backup_codes = delete_user_meta( $user_to_wipe->ID, 'wp_2fa_backup_codes' ); |
| 945 | $wipe_enabled_methods = delete_user_meta( $user_to_wipe->ID, 'wp_2fa_enabled_methods' ); |
| 946 | $wipe_grace_period = delete_user_meta( $user_to_wipe->ID, 'wp_2fa_grace_period_expiry' ); |
| 947 | } |
| 948 | } |
| 949 | } |
| 950 | |
| 951 | if ( isset( $input['excluded_roles'] ) ) { |
| 952 | $output['excluded_roles'] = trim( sanitize_text_field( $input['excluded_roles'] ) ); |
| 953 | $excluded_roles_array = array_filter( explode( ',', strtolower( $output['excluded_roles'] ) ) ); |
| 954 | |
| 955 | // Flush the old expiry away from ALL users, we will re-apply them based on the current setup at the end of this. |
| 956 | for ( $count = 0; $count < $slices; $count++ ) { |
| 957 | $users_args = array( |
| 958 | 'number' => $batch_size, |
| 959 | 'offset' => $count * $batch_size, |
| 960 | 'fields' => array( 'ID' ), |
| 961 | ); |
| 962 | $users = get_users( $users_args ); |
| 963 | if ( ! empty( $users ) ) { |
| 964 | $background_process = new ProcessUserMetaUpdate(); |
| 965 | $item_to_process = array(); |
| 966 | $item_to_process['users'] = $users; |
| 967 | $item_to_process['task'] = 'wipe_all_2fa_user_data'; |
| 968 | $item_to_process['excluded_roles'] = $excluded_roles_array; |
| 969 | $background_process->push_to_queue( $item_to_process ); |
| 970 | } |
| 971 | |
| 972 | $background_process->save()->dispatch(); |
| 973 | } |
| 974 | } |
| 975 | |
| 976 | if ( WP2FA::is_this_multisite() ) { |
| 977 | if ( isset( $input['excluded_sites'] ) ) { |
| 978 | $output['excluded_sites'] = trim( sanitize_text_field( $input['excluded_sites'] ) ); |
| 979 | } |
| 980 | } else { |
| 981 | $output['excluded_sites'] = ''; |
| 982 | } |
| 983 | |
| 984 | if ( isset( $input['grace-policy'] ) ) { |
| 985 | $output['grace-policy'] = sanitize_text_field( $input['grace-policy'] ); |
| 986 | } |
| 987 | |
| 988 | if ( isset( $input['notify_users'] ) ) { |
| 989 | $output['notify_users'] = sanitize_text_field( $input['notify_users'] ); |
| 990 | } else { |
| 991 | $input['notify_users'] = ''; |
| 992 | } |
| 993 | |
| 994 | if ( isset( $input['grace-period'] ) ) { |
| 995 | if ( 0 === (int) $input['grace-period'] ) { |
| 996 | add_settings_error( |
| 997 | 'wp_2fa_settings', |
| 998 | esc_attr( 'grace_settings_error' ), |
| 999 | esc_html__( 'Grace period must be at least 1 day/hour', 'wp-2fa' ), |
| 1000 | 'error' |
| 1001 | ); |
| 1002 | $output['grace-period'] = 1; |
| 1003 | } else { |
| 1004 | $output['grace-period'] = (int) $input['grace-period']; |
| 1005 | } |
| 1006 | } |
| 1007 | |
| 1008 | if ( isset( $input['grace-period-denominator'] ) && 'days' === $input['grace-period-denominator'] || isset( $input['grace-period-denominator'] ) && 'hours' === $input['grace-period-denominator'] || isset( $input['grace-period-denominator'] ) && 'seconds' === $input['grace-period-denominator'] ) { |
| 1009 | $output['grace-period-denominator'] = sanitize_text_field( $input['grace-period-denominator'] ); |
| 1010 | } |
| 1011 | |
| 1012 | if ( isset( $input['create-custom-user-page'] ) && 'yes' === $input['create-custom-user-page'] || isset( $input['create-custom-user-page'] ) && 'no' === $input['create-custom-user-page'] ) { |
| 1013 | $output['create-custom-user-page'] = sanitize_text_field( $input['create-custom-user-page'] ); |
| 1014 | } |
| 1015 | |
| 1016 | if ( isset( $input['custom-user-page-url'] ) ) { |
| 1017 | if ( $input['custom-user-page-url'] !== WP2FA::get_wp2fa_setting( 'custom-user-page-url' ) ) { |
| 1018 | if ( ! empty( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) ) ) { |
| 1019 | $updated_post = array( |
| 1020 | 'ID' => WP2FA::get_wp2fa_setting( 'custom-user-page-id' ), |
| 1021 | 'post_name' => sanitize_title_with_dashes( $input['custom-user-page-url'] ), |
| 1022 | ); |
| 1023 | wp_update_post( $updated_post ); |
| 1024 | $output['custom-user-page-url'] = sanitize_title_with_dashes( $input['custom-user-page-url'] ); |
| 1025 | $output['custom-user-page-id'] = WP2FA::get_wp2fa_setting( 'custom-user-page-id' ); |
| 1026 | } elseif ( 'yes' === $input['create-custom-user-page'] && ! empty( $input['custom-user-page-url'] ) ) { |
| 1027 | $output['custom-user-page-url'] = sanitize_title_with_dashes( $input['custom-user-page-url'] ); |
| 1028 | $create_page = $this->generate_custom_user_profile_page( $output['custom-user-page-url'] ); |
| 1029 | $output['custom-user-page-id'] = (int) $create_page; |
| 1030 | } |
| 1031 | } else { |
| 1032 | $output['custom-user-page-url'] = sanitize_title_with_dashes( $input['custom-user-page-url'] ); |
| 1033 | $output['custom-user-page-id'] = WP2FA::get_wp2fa_setting( 'custom-user-page-id' ); |
| 1034 | } |
| 1035 | } |
| 1036 | |
| 1037 | if ( isset( $_REQUEST['page'] ) && 'wp-2fa-setup' !== $_REQUEST['page'] || isset( $_REQUEST['wp_2fa_settings']['create-custom-user-page'] ) ) { |
| 1038 | |
| 1039 | if ( isset( $input['create-custom-user-page'] ) && 'no' === $input['create-custom-user-page'] ) { |
| 1040 | $output['custom-user-page-url'] = ''; |
| 1041 | $output['custom-user-page-id'] = ''; |
| 1042 | wp_delete_post( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ), true ); |
| 1043 | } |
| 1044 | } |
| 1045 | |
| 1046 | if ( isset( $input['create-custom-user-page'] ) && 'yes' === $input['create-custom-user-page'] && empty( $input['custom-user-page-url'] ) ) { |
| 1047 | add_settings_error( |
| 1048 | 'wp_2fa_settings', |
| 1049 | esc_attr( 'no_page_slug_provided' ), |
| 1050 | esc_html__( 'You must provide a new page slug.', 'wp-2fa' ), |
| 1051 | 'error' |
| 1052 | ); |
| 1053 | } |
| 1054 | |
| 1055 | if ( isset( $input['enable_grace_cron'] ) ) { |
| 1056 | $output['enable_grace_cron'] = (bool) $input['enable_grace_cron']; |
| 1057 | } |
| 1058 | |
| 1059 | if ( isset( $input['enable_destroy_session'] ) ) { |
| 1060 | $output['enable_destroy_session'] = (bool) $input['enable_destroy_session']; |
| 1061 | } |
| 1062 | |
| 1063 | if ( isset( $input['2fa_settings_last_updated_by'] ) ) { |
| 1064 | $output['2fa_settings_last_updated_by'] = esc_attr( trim( $input['2fa_settings_last_updated_by'] ) ); |
| 1065 | } |
| 1066 | |
| 1067 | if ( isset( $input['limit_access'] ) ) { |
| 1068 | $output['limit_access'] = (bool) $input['limit_access']; |
| 1069 | } |
| 1070 | |
| 1071 | if ( isset( $input['delete_data_upon_uninstall'] ) ) { |
| 1072 | $output['delete_data_upon_uninstall'] = (bool) $input['delete_data_upon_uninstall']; |
| 1073 | } |
| 1074 | |
| 1075 | if ( isset( $input['grace-period'] ) && isset( $input['grace-period-denominator'] ) ) { |
| 1076 | // Turn inputs into a useable string. |
| 1077 | $create_a_string = $output['grace-period'] . ' ' . $output['grace-period-denominator']; |
| 1078 | // Turn that string into a time. |
| 1079 | $grace_expiry = strtotime( $create_a_string ); |
| 1080 | $output['grace-period-expiry-time'] = sanitize_text_field( $grace_expiry ); |
| 1081 | } |
| 1082 | |
| 1083 | if ( isset( $input['hide_remove_button'] ) ) { |
| 1084 | $output['hide_remove_button'] = (bool) $input['hide_remove_button']; |
| 1085 | } |
| 1086 | |
| 1087 | // Fetch users and apply the grace period tp their user meta. |
| 1088 | if ( isset( $input['enforcment-policy'] ) && 'do-not-enforce' !== $input['enforcment-policy'] && ! isset( $input['grace-period-expiry-time'] ) ) { |
| 1089 | // Flush the old expiry away from ALL users, we will re-apply them based on the current setup at the end of this. |
| 1090 | for ( $count = 0; $count < $slices; $count++ ) { |
| 1091 | $users_args = array( |
| 1092 | 'number' => $batch_size, |
| 1093 | 'offset' => $count * $batch_size, |
| 1094 | 'fields' => array( 'ID' ), |
| 1095 | ); |
| 1096 | if ( WP2FA::is_this_multisite() ) { |
| 1097 | $users_args['blog_id'] = 0; |
| 1098 | } |
| 1099 | $users = get_users( $users_args ); |
| 1100 | if ( ! empty( $users ) ) { |
| 1101 | $background_process = new ProcessUserMetaUpdate(); |
| 1102 | $item_to_process = array(); |
| 1103 | $item_to_process['users'] = $users; |
| 1104 | $item_to_process['task'] = 'delete_grace_period'; |
| 1105 | $background_process->push_to_queue( $item_to_process ); |
| 1106 | } |
| 1107 | $background_process->save()->dispatch(); |
| 1108 | } |
| 1109 | |
| 1110 | // If we are specifying to enforce 2fa for specific users, we have no need to check if they are eligble or excluded, so we dont. |
| 1111 | if ( isset( $input['enforcment-policy'] ) && 'certain-roles-only' === $input['enforcment-policy'] && isset( $input['enforced_users'] ) && WP2FA::get_wp2fa_setting( 'enforced_users' ) !== $input['enforced_users'] || isset( $input['enforcment-policy'] ) && 'certain-roles-only' === $input['enforcment-policy'] && isset( $input['enforced_roles'] ) && WP2FA::get_wp2fa_setting( 'enforced_roles' ) !== $input['enforced_roles'] ) { |
| 1112 | $enforced_users_array = array_filter( explode( ',', $input['enforced_users'] ) ); |
| 1113 | |
| 1114 | // Flush the old expiry away from ALL users, we will re-apply them based on the current setup at the end of this. |
| 1115 | for ( $count = 0; $count < $slices; $count++ ) { |
| 1116 | $users_args = array( |
| 1117 | 'number' => $batch_size, |
| 1118 | 'offset' => $count * $batch_size, |
| 1119 | 'fields' => array( 'ID', 'user_login' ), |
| 1120 | ); |
| 1121 | if ( WP2FA::is_this_multisite() ) { |
| 1122 | $users_args['blog_id'] = 0; |
| 1123 | } |
| 1124 | $users = get_users( $users_args ); |
| 1125 | if ( ! empty( $users ) ) { |
| 1126 | foreach ( $users as $user ) { |
| 1127 | if ( in_array( $user->user_login, $enforced_users_array ) ) { |
| 1128 | $background_process = new ProcessUserMetaUpdate(); |
| 1129 | $item_to_process = array(); |
| 1130 | $item_to_process['user'] = $user; |
| 1131 | $item_to_process['task'] = 'enforce_2fa_for_user'; |
| 1132 | $item_to_process['grace_expiry'] = $grace_expiry; |
| 1133 | $item_to_process['grace_policy'] = sanitize_text_field( $input['grace-policy'] ); |
| 1134 | $item_to_process['notify_users'] = $input['notify_users']; |
| 1135 | $background_process->push_to_queue( $item_to_process ); |
| 1136 | } else { |
| 1137 | if ( isset( $output['enforced_roles'] ) && empty( $output['enforced_roles'] ) ) { |
| 1138 | $enforced_roles = 'none'; |
| 1139 | } else { |
| 1140 | $enforced_roles = $output['enforced_roles']; |
| 1141 | } |
| 1142 | if ( isset( $output['enforced_users'] ) && empty( $output['enforced_users'] ) ) { |
| 1143 | $enforced_users = 'none'; |
| 1144 | } else { |
| 1145 | $enforced_users = $output['enforced_users']; |
| 1146 | } |
| 1147 | $is_needed = Authentication::is_user_eligible_for_2fa( $user->ID, $input['enforcment-policy'], $output['excluded_users'], $output['excluded_roles'], $enforced_users, $enforced_roles ); |
| 1148 | $is_user_excluded = WP2FA::is_user_excluded( $user, $output['excluded_users'], $output['excluded_roles'], $output['excluded_sites'] ); |
| 1149 | if ( $is_needed && ! $is_user_excluded ) { |
| 1150 | $item_to_process = array(); |
| 1151 | $item_to_process['user'] = $user; |
| 1152 | $item_to_process['task'] = 'enforce_2fa_for_user'; |
| 1153 | $item_to_process['grace_expiry'] = $grace_expiry; |
| 1154 | $item_to_process['grace_policy'] = sanitize_text_field( $input['grace-policy'] ); |
| 1155 | $item_to_process['notify_users'] = $input['notify_users']; |
| 1156 | $background_process->push_to_queue( $item_to_process ); |
| 1157 | } |
| 1158 | } |
| 1159 | } |
| 1160 | } |
| 1161 | |
| 1162 | $background_process->save()->dispatch(); |
| 1163 | } |
| 1164 | |
| 1165 | } else { |
| 1166 | |
| 1167 | // Flush the old expiry away from ALL users, we will re-apply them based on the current setup at the end of this. |
| 1168 | for ( $count = 0; $count < $slices; $count++ ) { |
| 1169 | $users_args = array( |
| 1170 | 'number' => $batch_size, |
| 1171 | 'offset' => $count * $batch_size, |
| 1172 | 'fields' => array( 'ID' ), |
| 1173 | ); |
| 1174 | if ( WP2FA::is_this_multisite() ) { |
| 1175 | $users_args['blog_id'] = 0; |
| 1176 | } |
| 1177 | $users = get_users( $users_args ); |
| 1178 | |
| 1179 | if ( ! empty( $users ) ) { |
| 1180 | $background_process = new ProcessUserMetaUpdate(); |
| 1181 | $item_to_process = array(); |
| 1182 | $item_to_process['users'] = $users; |
| 1183 | $item_to_process['task'] = 'enforce_2fa_for_user'; |
| 1184 | $item_to_process['grace_expiry'] = $grace_expiry; |
| 1185 | $item_to_process['grace_policy'] = sanitize_text_field( $input['grace-policy'] ); |
| 1186 | $item_to_process['notify_users'] = $input['notify_users']; |
| 1187 | $item_to_process['enforcment-policy'] = $input['enforcment-policy']; |
| 1188 | $item_to_process['excluded_users'] = $output['excluded_users']; |
| 1189 | $item_to_process['excluded_roles'] = $output['excluded_roles']; |
| 1190 | $item_to_process['enforced_users'] = $output['enforced_users']; |
| 1191 | $item_to_process['enforced_roles'] = $output['enforced_roles']; |
| 1192 | $item_to_process['excluded_sites'] = $output['excluded_sites']; |
| 1193 | $background_process->push_to_queue( $item_to_process ); |
| 1194 | } |
| 1195 | |
| 1196 | $background_process->save()->dispatch(); |
| 1197 | } |
| 1198 | } |
| 1199 | } |
| 1200 | |
| 1201 | if ( isset( $input['enforcment-policy'] ) && 'do-not-enforce' === $input['enforcment-policy'] && ! isset( $input['grace-period-expiry-time'] ) ) { |
| 1202 | for ( $count = 0; $count < $slices; $count++ ) { |
| 1203 | $users_args = array( |
| 1204 | 'number' => $batch_size, |
| 1205 | 'offset' => $count * $batch_size, |
| 1206 | 'fields' => array( 'ID' ), |
| 1207 | ); |
| 1208 | if ( WP2FA::is_this_multisite() ) { |
| 1209 | $users_args['blog_id'] = 0; |
| 1210 | } |
| 1211 | $users = get_users( $users_args ); |
| 1212 | if ( ! empty( $users ) ) { |
| 1213 | $background_process = new ProcessUserMetaUpdate(); |
| 1214 | $item_to_process = array(); |
| 1215 | $item_to_process['users'] = $users; |
| 1216 | $item_to_process['task'] = 'delete_grace_period'; |
| 1217 | $background_process->push_to_queue( $item_to_process ); |
| 1218 | } |
| 1219 | $background_process->save()->dispatch(); |
| 1220 | } |
| 1221 | } |
| 1222 | |
| 1223 | // Remove duplicates from settings errors. We do this as this sanitization callback is actually fired twice, so we end up with duplicates when saving the settings for the FIRST TIME only. The issue is not present once the settings are in the DB as the sanitization wont fire again. For details on this core issue - https://core.trac.wordpress.org/ticket/21989 |
| 1224 | global $wp_settings_errors; |
| 1225 | if ( isset( $wp_settings_errors ) ) { |
| 1226 | $errors = array_map( 'unserialize', array_unique( array_map( 'serialize', $wp_settings_errors ) ) ); |
| 1227 | $wp_settings_errors = $errors; |
| 1228 | } |
| 1229 | |
| 1230 | return $output; |
| 1231 | } |
| 1232 | |
| 1233 | /** |
| 1234 | * Hide settings menu item |
| 1235 | */ |
| 1236 | public function hide_settings() { |
| 1237 | $user = wp_get_current_user(); |
| 1238 | |
| 1239 | // Check we have a user before doing anything else. |
| 1240 | if ( is_a( $user, '\WP_User' ) ) { |
| 1241 | $user_id = (int) $user->ID; |
| 1242 | if ( ! empty( WP2FA::get_wp2fa_setting( '2fa_settings_last_updated_by' ) ) ) { |
| 1243 | $main_user = (int) WP2FA::get_wp2fa_setting( '2fa_settings_last_updated_by' ); |
| 1244 | } else { |
| 1245 | $main_user = ''; |
| 1246 | } |
| 1247 | if ( ! empty( WP2FA::get_wp2fa_setting( 'limit_access' ) ) && $user->ID !== $main_user ) { |
| 1248 | // Remove admin menu item. |
| 1249 | remove_submenu_page( 'options-general.php', 'wp-2fa-settings' ); |
| 1250 | } |
| 1251 | } |
| 1252 | } |
| 1253 | |
| 1254 | /** |
| 1255 | * Add unlock user link to user actions. |
| 1256 | * |
| 1257 | * @param array $links Default row content. |
| 1258 | */ |
| 1259 | public function add_plugin_action_links( $links ) { |
| 1260 | |
| 1261 | if ( WP2FA::is_this_multisite() ) { |
| 1262 | $url = network_admin_url( '/settings.php?page=wp-2fa-settings' ); |
| 1263 | } else { |
| 1264 | $url = admin_url( '/options-general.php?page=wp-2fa-settings' ); |
| 1265 | } |
| 1266 | |
| 1267 | $links = array_merge( |
| 1268 | array( |
| 1269 | '<a href="' . esc_url( $url ) . '">' . esc_html__( 'Configure 2FA Settings', 'wp-2fa' ) . '</a>', |
| 1270 | ), |
| 1271 | $links |
| 1272 | ); |
| 1273 | |
| 1274 | return $links; |
| 1275 | |
| 1276 | } |
| 1277 | |
| 1278 | /** |
| 1279 | * User unlocked notice. |
| 1280 | */ |
| 1281 | public function user_unlocked_notice() { |
| 1282 | ?> |
| 1283 | <div class="notice notice-success is-dismissible"> |
| 1284 | <p><?php esc_html_e( 'User account successfully unlocked. User can login again.', 'wp-2fa' ); ?></p> |
| 1285 | <button type="button" class="notice-dismiss"> |
| 1286 | <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span> |
| 1287 | </button> |
| 1288 | </div> |
| 1289 | <?php |
| 1290 | } |
| 1291 | |
| 1292 | /** |
| 1293 | * User deleted 2FA settings notification |
| 1294 | */ |
| 1295 | public function user_deleted_2fa_notice() { |
| 1296 | ?> |
| 1297 | <div class="notice notice-success is-dismissible"> |
| 1298 | <p><?php esc_html_e( 'Your 2FA settings have been removed.', 'wp-2fa' ); ?></p> |
| 1299 | <button type="button" class="notice-dismiss"> |
| 1300 | <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span> |
| 1301 | </button> |
| 1302 | </div> |
| 1303 | <?php |
| 1304 | } |
| 1305 | |
| 1306 | /** |
| 1307 | * Admin deleted user 2FA settings notification |
| 1308 | */ |
| 1309 | public function admin_deleted_2fa_notice() { |
| 1310 | ?> |
| 1311 | <div class="notice notice-success is-dismissible"> |
| 1312 | <p><?php esc_html_e( 'User 2FA settings have been removed.', 'wp-2fa' ); ?></p> |
| 1313 | <button type="button" class="notice-dismiss"> |
| 1314 | <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span> |
| 1315 | </button> |
| 1316 | </div> |
| 1317 | <?php |
| 1318 | } |
| 1319 | |
| 1320 | /** |
| 1321 | * Semd email to let user know they need to enabled 2FA |
| 1322 | * |
| 1323 | * @param int $user_id User ID. |
| 1324 | */ |
| 1325 | public static function send_2fa_enforced_email( $user_id, $override_grace_period = '' ) { |
| 1326 | // Bail if the user has not enabled this email. |
| 1327 | if ( 'enable_enforced_email' !== WP2FA::get_wp2fa_email_templates( 'send_enforced_email' ) ) { |
| 1328 | return false; |
| 1329 | } |
| 1330 | |
| 1331 | $user_id = (int) $user_id; |
| 1332 | // Grab user data. |
| 1333 | $user = get_userdata( $user_id ); |
| 1334 | |
| 1335 | // Check if user has any enabled 2FA methods before sending. |
| 1336 | $enabled_methods = get_user_meta( $user->ID, 'wp_2fa_enabled_methods', true ); |
| 1337 | if ( ! empty( $enabled_methods ) ) { |
| 1338 | return false; |
| 1339 | } |
| 1340 | |
| 1341 | // Grab user email. |
| 1342 | $email = $user->user_email; |
| 1343 | |
| 1344 | $subject = wp_strip_all_tags( WP2FA::replace_email_strings( WP2FA::get_wp2fa_email_templates( 'enforced_email_subject' ), $user_id, '', $override_grace_period ) ); |
| 1345 | $message = wpautop( WP2FA::replace_email_strings( WP2FA::get_wp2fa_email_templates( 'enforced_email_body' ), $user_id, '', $override_grace_period ) ); |
| 1346 | |
| 1347 | $headers = 'Content-type: text/html;charset=utf-8' . "\r\n"; |
| 1348 | |
| 1349 | if ( 'use-custom-email' === WP2FA::get_wp2fa_email_templates( 'email_from_setting' ) ) { |
| 1350 | $headers .= 'From: ' . WP2FA::get_wp2fa_email_templates( 'custom_from_display_name' ) . ' <' . WP2FA::get_wp2fa_email_templates( 'custom_from_email_address' ) . '>' . "\r\n"; |
| 1351 | } |
| 1352 | |
| 1353 | $mail = wp_mail( $user->user_email, $subject, $message, $headers ); |
| 1354 | } |
| 1355 | |
| 1356 | public function update_wp2fa_network_options() { |
| 1357 | check_admin_referer( 'wp_2fa_settings-options' ); |
| 1358 | |
| 1359 | if ( isset( $_POST['wp_2fa_settings'] ) ) { |
| 1360 | $options = $this->validate_and_sanitize( wp_unslash( $_POST['wp_2fa_settings'] ) ); |
| 1361 | $update_options = update_network_option( null, 'wp_2fa_settings', $options ); |
| 1362 | } |
| 1363 | |
| 1364 | // redirect back to our options page. |
| 1365 | wp_safe_redirect( |
| 1366 | add_query_arg( |
| 1367 | array( |
| 1368 | 'page' => 'wp-2fa-settings', |
| 1369 | 'wp_2fa_network_settings_updated' => 'true', |
| 1370 | ), |
| 1371 | network_admin_url( 'settings.php' ) |
| 1372 | ) |
| 1373 | ); |
| 1374 | exit; |
| 1375 | } |
| 1376 | |
| 1377 | /** |
| 1378 | * Handle saving email options to the network main site options. |
| 1379 | */ |
| 1380 | public function update_wp2fa_network_email_options() { |
| 1381 | if ( isset( $_POST['email_from_setting'] ) ) { |
| 1382 | $options = $this->validate_and_sanitize_email( wp_unslash( $_POST ) ); |
| 1383 | |
| 1384 | if ( isset( $_POST['email_from_setting'] ) && 'use-custom-email' === $_POST['email_from_setting'] && isset( $_POST['custom_from_display_name'] ) && empty( $_POST['custom_from_display_name'] ) || isset( $_POST['email_from_setting'] ) && 'use-custom-email' === $_POST['email_from_setting'] && isset( $_POST['custom_from_email_address'] ) && empty( $_POST['custom_from_email_address'] ) ) { |
| 1385 | // redirect back to our options page. |
| 1386 | wp_safe_redirect( |
| 1387 | add_query_arg( |
| 1388 | array( |
| 1389 | 'page' => 'wp-2fa-settings', |
| 1390 | 'wp_2fa_network_settings_updated' => 'false', |
| 1391 | 'tab' => 'email-settings', |
| 1392 | ), |
| 1393 | network_admin_url( 'settings.php' ) |
| 1394 | ) |
| 1395 | ); |
| 1396 | exit; |
| 1397 | } |
| 1398 | |
| 1399 | $update_options = update_network_option( null, 'wp_2fa_email_settings', $options ); |
| 1400 | } |
| 1401 | |
| 1402 | // redirect back to our options page. |
| 1403 | wp_safe_redirect( |
| 1404 | add_query_arg( |
| 1405 | array( |
| 1406 | 'page' => 'wp-2fa-settings', |
| 1407 | 'wp_2fa_network_settings_updated' => 'true', |
| 1408 | 'tab' => 'email-settings', |
| 1409 | ), |
| 1410 | network_admin_url( 'settings.php' ) |
| 1411 | ) |
| 1412 | ); |
| 1413 | exit; |
| 1414 | } |
| 1415 | |
| 1416 | /** |
| 1417 | * These are used instead of add_settings_error which in a network site. Used to show if settings have been updated or failed. |
| 1418 | */ |
| 1419 | public function settings_saved_network_admin_notice() { |
| 1420 | if ( isset( $_GET['wp_2fa_network_settings_updated'] ) && $_GET['wp_2fa_network_settings_updated'] == 'true' ) : |
| 1421 | ?> |
| 1422 | <div class="notice notice-success is-dismissible"> |
| 1423 | <p><?php esc_html_e( '2FA Settings Updated', 'wp-2fa' ); ?></p> |
| 1424 | <button type="button" class="notice-dismiss"> |
| 1425 | <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span> |
| 1426 | </button> |
| 1427 | </div> |
| 1428 | <?php |
| 1429 | endif; |
| 1430 | if ( isset( $_GET['wp_2fa_network_settings_updated'] ) && $_GET['wp_2fa_network_settings_updated'] == 'false' ) : |
| 1431 | ?> |
| 1432 | <div class="notice notice-error is-dismissible"> |
| 1433 | <p><?php esc_html_e( 'Please ensure both custom email address and display name are provided.', 'wp-2fa' ); ?></p> |
| 1434 | <button type="button" class="notice-dismiss"> |
| 1435 | <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span> |
| 1436 | </button> |
| 1437 | </div> |
| 1438 | <?php |
| 1439 | endif; |
| 1440 | } |
| 1441 | |
| 1442 | /** |
| 1443 | * Email settings |
| 1444 | */ |
| 1445 | private function email_from_settings() { |
| 1446 | ?> |
| 1447 | <h3><?php esc_html_e( 'Which email address should the plugin use as a from address?', 'wp-2fa' ); ?></h3> |
| 1448 | <p class="description"> |
| 1449 | <?php esc_html_e( 'Use these settings to customize the "from" name and email address for all correspondence sent from our plugin.', 'wp-2fa' ); ?> |
| 1450 | </p> |
| 1451 | <table class="form-table"> |
| 1452 | <tbody> |
| 1453 | <tr> |
| 1454 | <th><label for="2fa-method"><?php esc_html_e( 'From email & name', 'wp-2fa' ); ?></label> |
| 1455 | </th> |
| 1456 | <td> |
| 1457 | <fieldset class="contains-hidden-inputs"> |
| 1458 | <label for="use-defaults"> |
| 1459 | <input type="radio" name="email_from_setting" id="use-defaults" value="use-defaults" |
| 1460 | <?php checked( WP2FA::get_wp2fa_email_templates( 'email_from_setting' ), 'use-defaults' ); ?> |
| 1461 | > |
| 1462 | <span><?php esc_html_e( 'Use the email address from the WordPress general settings.', 'wp-2fa' ); ?></span> |
| 1463 | </label> |
| 1464 | |
| 1465 | <br/> |
| 1466 | <label for="use-custom-email"> |
| 1467 | <input type="radio" name="email_from_setting" id="use-custom-email" value="use-custom-email" |
| 1468 | <?php checked( WP2FA::get_wp2fa_email_templates( 'email_from_setting' ), 'use-custom-email' ); ?> |
| 1469 | data-unhide-when-checked=".custom-from-inputs"> |
| 1470 | <span><?php esc_html_e( 'Use another email address', 'wp-2fa' ); ?></span> |
| 1471 | </label> |
| 1472 | <fieldset class="hidden custom-from-inputs"> |
| 1473 | <br/> |
| 1474 | <span><?php esc_html_e( 'Email Address:', 'wp-2fa' ); ?></span> <input type="text" id="custom_from_email_address" name="custom_from_email_address" value="<?php echo WP2FA::get_wp2fa_email_templates( 'custom_from_email_address' ); ?>"><br><br> |
| 1475 | <span><?php esc_html_e( 'Display Name:', 'wp-2fa' ); ?></span> <input type="text" id="custom_from_display_name" name="custom_from_display_name" value="<?php echo WP2FA::get_wp2fa_email_templates( 'custom_from_display_name' ); ?>"> |
| 1476 | </fieldset> |
| 1477 | |
| 1478 | </fieldset> |
| 1479 | </td> |
| 1480 | </tr> |
| 1481 | </tbody> |
| 1482 | </table> |
| 1483 | |
| 1484 | <br> |
| 1485 | <hr> |
| 1486 | |
| 1487 | <?php |
| 1488 | } |
| 1489 | |
| 1490 | /** |
| 1491 | * Email settings |
| 1492 | */ |
| 1493 | private function email_settings() { |
| 1494 | ?> |
| 1495 | <h1><?php esc_html_e( 'Email Templates', 'wp-2fa' ); ?></h1> |
| 1496 | <h3><?php esc_html_e( 'Enforced 2FA email', 'wp-2fa' ); ?></h3> |
| 1497 | <p class="description"> |
| 1498 | <?php esc_html_e( 'This is the email sent to applicable users when you enforce 2fa.', 'wp-2fa' ); ?> |
| 1499 | </p> |
| 1500 | <table class="form-table"> |
| 1501 | <tbody> |
| 1502 | <tr> |
| 1503 | <th><label for="2fa-method"><?php esc_html_e( 'Send this email', 'wp-2fa' ); ?></label> |
| 1504 | </th> |
| 1505 | <td> |
| 1506 | <fieldset> |
| 1507 | <input type="checkbox" id="send_enforced_email" name="send_enforced_email" value="enable_enforced_email" |
| 1508 | <?php checked( 'enable_enforced_email', WP2FA::get_wp2fa_email_templates( 'send_enforced_email' ), true ); ?> |
| 1509 | > |
| 1510 | <label for="send_enforced_email"><?php esc_html_e( 'Uncheck to disable this message.', 'wp-2fa' ); ?></label> |
| 1511 | </fieldset> |
| 1512 | </td> |
| 1513 | </tr> |
| 1514 | <tr> |
| 1515 | <th><label for="2fa-method"><?php esc_html_e( 'Email subject', 'wp-2fa' ); ?></label> |
| 1516 | </th> |
| 1517 | <td> |
| 1518 | <fieldset> |
| 1519 | <input type="text" id="enforced_email_subject" name="enforced_email_subject" class="large-text" value="<?php esc_html_e( WP2FA::get_wp2fa_email_templates( 'enforced_email_subject' ) ); ?>"> |
| 1520 | </fieldset> |
| 1521 | </td> |
| 1522 | </tr> |
| 1523 | <tr> |
| 1524 | <th><label for="2fa-method"><?php esc_html_e( 'Email body', 'wp-2fa' ); ?></label> |
| 1525 | </br> |
| 1526 | <label for="2fa-method" style="font-weight: 400;"><?php esc_html_e( 'Available template tags:', 'wp-2fa' ); ?></label> |
| 1527 | </br></br> |
| 1528 | <span style="font-weight: 400;"> |
| 1529 | {site_url}</br> |
| 1530 | {site_name}</br> |
| 1531 | {grace_period}</br> |
| 1532 | {user_login_name}</br> |
| 1533 | {login_code} |
| 1534 | <?php |
| 1535 | if ( ! empty( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) ) ) { |
| 1536 | echo '</br>{2fa_settings_page_url}'; |
| 1537 | } |
| 1538 | ?> |
| 1539 | </span> |
| 1540 | </th> |
| 1541 | <td> |
| 1542 | <fieldset> |
| 1543 | <?php |
| 1544 | $message = WP2FA::get_wp2fa_email_templates( 'enforced_email_body' ); |
| 1545 | $content = $message; |
| 1546 | $editor_id = 'enforced_email_body'; |
| 1547 | $settings = array( |
| 1548 | 'media_buttons' => false, |
| 1549 | 'editor_height' => 200, |
| 1550 | ); |
| 1551 | wp_editor( $content, $editor_id, $settings ); |
| 1552 | ?> |
| 1553 | </fieldset> |
| 1554 | </td> |
| 1555 | </tr> |
| 1556 | </tbody> |
| 1557 | </table> |
| 1558 | |
| 1559 | <br> |
| 1560 | <hr> |
| 1561 | |
| 1562 | <h3><?php esc_html_e( 'Login code email', 'wp-2fa' ); ?></h3> |
| 1563 | <p class="description"> |
| 1564 | <?php esc_html_e( 'This is the email sent to a user when a login code is required.', 'wp-2fa' ); ?> |
| 1565 | </p> |
| 1566 | <table class="form-table"> |
| 1567 | <tbody> |
| 1568 | <tr> |
| 1569 | <th><label for="2fa-method"><?php esc_html_e( 'Email subject', 'wp-2fa' ); ?></label> |
| 1570 | </th> |
| 1571 | <td> |
| 1572 | <fieldset> |
| 1573 | <input type="text" id="login_code_email_subject" name="login_code_email_subject" class="large-text" value="<?php esc_html_e( WP2FA::get_wp2fa_email_templates( 'login_code_email_subject' ) ); ?>"> |
| 1574 | </fieldset> |
| 1575 | </td> |
| 1576 | </tr> |
| 1577 | <tr> |
| 1578 | <th><label for="2fa-method"><?php esc_html_e( 'Email body', 'wp-2fa' ); ?></label> |
| 1579 | </br> |
| 1580 | <label for="2fa-method" style="font-weight: 400;"><?php esc_html_e( 'Available template tags:', 'wp-2fa' ); ?></label> |
| 1581 | </br></br> |
| 1582 | <span style="font-weight: 400;"> |
| 1583 | {site_url}</br> |
| 1584 | {site_name}</br> |
| 1585 | {grace_period}</br> |
| 1586 | {user_login_name}</br> |
| 1587 | {login_code} |
| 1588 | <?php |
| 1589 | if ( ! empty( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) ) ) { |
| 1590 | echo '</br>{2fa_settings_page_url}'; |
| 1591 | } |
| 1592 | ?> |
| 1593 | </span> |
| 1594 | </th> |
| 1595 | <td> |
| 1596 | <fieldset> |
| 1597 | <?php |
| 1598 | $message = WP2FA::get_wp2fa_email_templates( 'login_code_email_body' ); |
| 1599 | $content = $message; |
| 1600 | $editor_id = 'login_code_email_body'; |
| 1601 | $settings = array( |
| 1602 | 'media_buttons' => false, |
| 1603 | 'editor_height' => 200, |
| 1604 | ); |
| 1605 | wp_editor( $content, $editor_id, $settings ); |
| 1606 | ?> |
| 1607 | </fieldset> |
| 1608 | </td> |
| 1609 | </tr> |
| 1610 | </tbody> |
| 1611 | </table> |
| 1612 | |
| 1613 | <br> |
| 1614 | <hr> |
| 1615 | |
| 1616 | <h3><?php esc_html_e( 'User account locked email', 'wp-2fa' ); ?></h3> |
| 1617 | <p class="description"> |
| 1618 | <?php esc_html_e( 'This is the email sent to a user upon grace period expiry.', 'wp-2fa' ); ?> |
| 1619 | </p> |
| 1620 | <table class="form-table"> |
| 1621 | <tbody> |
| 1622 | <tr> |
| 1623 | <th><label for="2fa-method"><?php esc_html_e( 'Send this email', 'wp-2fa' ); ?></label> |
| 1624 | </th> |
| 1625 | <td> |
| 1626 | <fieldset> |
| 1627 | <input type="checkbox" id="send_account_locked_email" name="send_account_locked_email" value="enable_account_locked_email" |
| 1628 | <?php checked( 'enable_account_locked_email', WP2FA::get_wp2fa_email_templates( 'send_account_locked_email' ), true ); ?> |
| 1629 | > |
| 1630 | <label for="send_account_locked_email"><?php esc_html_e( 'Uncheck to disable this message.', 'wp-2fa' ); ?></label> |
| 1631 | </fieldset> |
| 1632 | </td> |
| 1633 | </tr> |
| 1634 | <tr> |
| 1635 | <th><label for="2fa-method"><?php esc_html_e( 'Email subject', 'wp-2fa' ); ?></label> |
| 1636 | </th> |
| 1637 | <td> |
| 1638 | <fieldset> |
| 1639 | <input type="text" id="user_account_locked_email_subject" name="user_account_locked_email_subject" class="large-text" value="<?php esc_html_e( WP2FA::get_wp2fa_email_templates( 'user_account_locked_email_subject' ) ); ?>"> |
| 1640 | </fieldset> |
| 1641 | </td> |
| 1642 | </tr> |
| 1643 | <tr> |
| 1644 | <th><label for="2fa-method"><?php esc_html_e( 'Email body', 'wp-2fa' ); ?></label> |
| 1645 | </br> |
| 1646 | <label for="2fa-method" style="font-weight: 400;"><?php esc_html_e( 'Available template tags:', 'wp-2fa' ); ?></label> |
| 1647 | </br></br> |
| 1648 | <span style="font-weight: 400;"> |
| 1649 | {site_url}</br> |
| 1650 | {site_name}</br> |
| 1651 | {grace_period}</br> |
| 1652 | {user_login_name}</br> |
| 1653 | {login_code} |
| 1654 | <?php |
| 1655 | if ( ! empty( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) ) ) { |
| 1656 | echo '</br>{2fa_settings_page_url}'; |
| 1657 | } |
| 1658 | ?> |
| 1659 | </span> |
| 1660 | </th> |
| 1661 | <td> |
| 1662 | <fieldset> |
| 1663 | <?php |
| 1664 | $message = WP2FA::get_wp2fa_email_templates( 'user_account_locked_email_body' ); |
| 1665 | $content = $message; |
| 1666 | $editor_id = 'user_account_locked_email_body'; |
| 1667 | $settings = array( |
| 1668 | 'media_buttons' => false, |
| 1669 | 'editor_height' => 200, |
| 1670 | ); |
| 1671 | wp_editor( $content, $editor_id, $settings ); |
| 1672 | ?> |
| 1673 | </fieldset> |
| 1674 | </td> |
| 1675 | </tr> |
| 1676 | </tbody> |
| 1677 | </table> |
| 1678 | |
| 1679 | <br> |
| 1680 | <hr> |
| 1681 | |
| 1682 | <h3><?php esc_html_e( 'User account unlocked email', 'wp-2fa' ); ?></h3> |
| 1683 | <p class="description"> |
| 1684 | <?php esc_html_e( 'This is the email sent to a user when the user\'s account has been unlocked.', 'wp-2fa' ); ?> |
| 1685 | </p> |
| 1686 | <table class="form-table"> |
| 1687 | <tbody> |
| 1688 | <tr> |
| 1689 | <th><label for="2fa-method"><?php esc_html_e( 'Send this email', 'wp-2fa' ); ?></label> |
| 1690 | </th> |
| 1691 | <td> |
| 1692 | <fieldset> |
| 1693 | <input type="checkbox" id="send_account_unlocked_email" name="send_account_unlocked_email" value="enable_account_unlocked_email" |
| 1694 | <?php checked( 'enable_account_unlocked_email', WP2FA::get_wp2fa_email_templates( 'send_account_unlocked_email' ), true ); ?> |
| 1695 | > |
| 1696 | <label for="send_account_unlocked_email"><?php esc_html_e( 'Uncheck to disable this message.', 'wp-2fa' ); ?></label> |
| 1697 | </fieldset> |
| 1698 | </td> |
| 1699 | </tr> |
| 1700 | <tr> |
| 1701 | <th><label for="2fa-method"><?php esc_html_e( 'Email subject', 'wp-2fa' ); ?></label> |
| 1702 | </th> |
| 1703 | <td> |
| 1704 | <fieldset> |
| 1705 | <input type="text" id="user_account_unlocked_email_subject" name="user_account_unlocked_email_subject" class="large-text" value="<?php esc_html_e( WP2FA::get_wp2fa_email_templates( 'user_account_unlocked_email_subject' ) ); ?>"> |
| 1706 | </fieldset> |
| 1707 | </td> |
| 1708 | </tr> |
| 1709 | <tr> |
| 1710 | <th><label for="2fa-method"><?php esc_html_e( 'Email body', 'wp-2fa' ); ?></label> |
| 1711 | </br> |
| 1712 | <label for="2fa-method" style="font-weight: 400;"><?php esc_html_e( 'Available template tags:', 'wp-2fa' ); ?></label> |
| 1713 | </br></br> |
| 1714 | <span style="font-weight: 400;"> |
| 1715 | {site_url}</br> |
| 1716 | {site_name}</br> |
| 1717 | {grace_period}</br> |
| 1718 | {user_login_name}</br> |
| 1719 | {login_code} |
| 1720 | <?php |
| 1721 | if ( ! empty( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) ) ) { |
| 1722 | echo '</br>{2fa_settings_page_url}'; |
| 1723 | } |
| 1724 | ?> |
| 1725 | </span> |
| 1726 | </th> |
| 1727 | <td> |
| 1728 | <fieldset> |
| 1729 | <?php |
| 1730 | $message = WP2FA::get_wp2fa_email_templates( 'user_account_unlocked_email_body' ); |
| 1731 | $content = $message; |
| 1732 | $editor_id = 'user_account_unlocked_email_body'; |
| 1733 | $settings = array( |
| 1734 | 'media_buttons' => false, |
| 1735 | 'editor_height' => 200, |
| 1736 | ); |
| 1737 | wp_editor( $content, $editor_id, $settings ); |
| 1738 | ?> |
| 1739 | </fieldset> |
| 1740 | </td> |
| 1741 | </tr> |
| 1742 | </tbody> |
| 1743 | </table> |
| 1744 | <?php |
| 1745 | } |
| 1746 | |
| 1747 | /** |
| 1748 | * Validate email templates before saving |
| 1749 | * |
| 1750 | * @param array $input The settings array. |
| 1751 | */ |
| 1752 | public function validate_and_sanitize_email( $input ) { |
| 1753 | |
| 1754 | // Bail if user doesnt have permissions to be here. |
| 1755 | if ( ! current_user_can( 'manage_options' ) ) { |
| 1756 | return; |
| 1757 | } |
| 1758 | |
| 1759 | if ( empty( $_POST ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'wp_2fa_email_settings-options' ) && ! wp_verify_nonce( $_POST['_wpnonce'], 'wp_2fa_settings-options' ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'wp_2fa_email_settings-options' ) && ! wp_verify_nonce( $_POST['_wpnonce'], 'wp_2fa_settings-options' ) ) { |
| 1760 | die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) ); |
| 1761 | } |
| 1762 | |
| 1763 | if ( isset( $_POST['email_from_setting'] ) && 'use-defaults' === $_POST['email_from_setting'] || isset( $_POST['email_from_setting'] ) && 'use-custom-email' === $_POST['email_from_setting'] ) { |
| 1764 | $output['email_from_setting'] = sanitize_text_field( wp_unslash( $_POST['email_from_setting'] ) ); |
| 1765 | } |
| 1766 | |
| 1767 | if ( isset( $_POST['email_from_setting'] ) && 'use-custom-email' === $_POST['email_from_setting'] && isset( $_POST['custom_from_email_address'] ) && empty( $_POST['custom_from_email_address'] ) ) { |
| 1768 | add_settings_error( |
| 1769 | 'wp_2fa_settings', |
| 1770 | esc_attr( 'email_from_settings_error' ), |
| 1771 | esc_html__( 'Please provide an email address', 'wp-2fa' ), |
| 1772 | 'error' |
| 1773 | ); |
| 1774 | $output['custom_from_email_address'] = ''; |
| 1775 | } |
| 1776 | |
| 1777 | if ( isset( $_POST['email_from_setting'] ) && 'use-custom-email' === $_POST['email_from_setting'] && isset( $_POST['custom_from_display_name'] ) && empty( $_POST['custom_from_display_name'] ) ) { |
| 1778 | add_settings_error( |
| 1779 | 'wp_2fa_settings', |
| 1780 | esc_attr( 'display_name_settings_error' ), |
| 1781 | esc_html__( 'Please provide a display name.', 'wp-2fa' ), |
| 1782 | 'error' |
| 1783 | ); |
| 1784 | $output['custom_from_email_address'] = ''; |
| 1785 | } |
| 1786 | |
| 1787 | if ( isset( $_POST['custom_from_email_address'] ) && ! empty( $_POST['custom_from_email_address'] ) ) { |
| 1788 | if ( ! filter_var( $_POST['custom_from_email_address'], FILTER_VALIDATE_EMAIL ) ) { |
| 1789 | add_settings_error( |
| 1790 | 'wp_2fa_settings', |
| 1791 | esc_attr( 'email_invalid_settings_error' ), |
| 1792 | esc_html__( 'Please provide a valid email address. Your email address has not been updated.', 'wp-2fa' ), |
| 1793 | 'error' |
| 1794 | ); |
| 1795 | } |
| 1796 | $output['custom_from_email_address'] = sanitize_email( wp_unslash( $_POST['custom_from_email_address'] ) ); |
| 1797 | } |
| 1798 | |
| 1799 | if ( isset( $_POST['custom_from_display_name'] ) && ! empty( $_POST['custom_from_display_name'] ) ) { |
| 1800 | // Check if the string contains HTML/tags. |
| 1801 | preg_match( "/<\/?\w+((\s+\w+(\s*=\s*(?:\".*?\"|'.*?'|[^'\">\s]+))?)+\s*|\s*)\/?>/", $_POST['custom_from_display_name'], $matches ); |
| 1802 | if ( count( $matches ) > 0 ) { |
| 1803 | add_settings_error( |
| 1804 | 'wp_2fa_settings', |
| 1805 | esc_attr( 'display_name_invalid_settings_error' ), |
| 1806 | esc_html__( 'Please only use alphanumeric text. Your display name has not been updated.', 'wp-2fa' ), |
| 1807 | 'error' |
| 1808 | ); |
| 1809 | } else { |
| 1810 | $output['custom_from_display_name'] = sanitize_text_field( wp_unslash( $_POST['custom_from_display_name'] ) ); |
| 1811 | } |
| 1812 | } |
| 1813 | |
| 1814 | if ( isset( $_POST['enforced_email_subject'] ) ) { |
| 1815 | $output['enforced_email_subject'] = wp_kses_post( wp_unslash( $_POST['enforced_email_subject'] ) ); |
| 1816 | } |
| 1817 | |
| 1818 | if ( isset( $_POST['enforced_email_body'] ) ) { |
| 1819 | $output['enforced_email_body'] = wpautop( wp_kses_post( wp_unslash( $_POST['enforced_email_body'] ) ) ); |
| 1820 | } |
| 1821 | |
| 1822 | if ( isset( $_POST['login_code_email_subject'] ) ) { |
| 1823 | $output['login_code_email_subject'] = wp_kses_post( wp_unslash( $_POST['login_code_email_subject'] ) ); |
| 1824 | } |
| 1825 | |
| 1826 | if ( isset( $_POST['login_code_email_body'] ) ) { |
| 1827 | $output['login_code_email_body'] = wpautop( wp_kses_post( wp_unslash( $_POST['login_code_email_body'] ) ) ); |
| 1828 | } |
| 1829 | |
| 1830 | if ( isset( $_POST['user_account_locked_email_subject'] ) ) { |
| 1831 | $output['user_account_locked_email_subject'] = wp_kses_post( wp_unslash( $_POST['user_account_locked_email_subject'] ) ); |
| 1832 | } |
| 1833 | |
| 1834 | if ( isset( $_POST['user_account_locked_email_body'] ) ) { |
| 1835 | $output['user_account_locked_email_body'] = wpautop( wp_kses_post( wp_unslash( $_POST['user_account_locked_email_body'] ) ) ); |
| 1836 | } |
| 1837 | |
| 1838 | if ( isset( $_POST['user_account_unlocked_email_subject'] ) ) { |
| 1839 | $output['user_account_unlocked_email_subject'] = wp_kses_post( wp_unslash( $_POST['user_account_unlocked_email_subject'] ) ); |
| 1840 | } |
| 1841 | |
| 1842 | if ( isset( $_POST['user_account_unlocked_email_body'] ) ) { |
| 1843 | $output['user_account_unlocked_email_body'] = wpautop( wp_kses_post( wp_unslash( $_POST['user_account_unlocked_email_body'] ) ) ); |
| 1844 | } |
| 1845 | |
| 1846 | if ( isset( $_POST['send_enforced_email'] ) && 'enable_enforced_email' === $_POST['send_enforced_email'] ) { |
| 1847 | $output['send_enforced_email'] = sanitize_text_field( $_POST['send_enforced_email'] ); |
| 1848 | } |
| 1849 | |
| 1850 | if ( isset( $_POST['send_account_locked_email'] ) && 'enable_account_locked_email' === $_POST['send_account_locked_email'] ) { |
| 1851 | $output['send_account_locked_email'] = sanitize_text_field( $_POST['send_account_locked_email'] ); |
| 1852 | } |
| 1853 | |
| 1854 | if ( isset( $_POST['send_account_unlocked_email'] ) && 'enable_account_unlocked_email' === $_POST['send_account_unlocked_email'] ) { |
| 1855 | $output['send_account_unlocked_email'] = sanitize_text_field( $_POST['send_account_unlocked_email'] ); |
| 1856 | } |
| 1857 | |
| 1858 | // Remove duplicates from settings errors. We do this as this sanitization callback is actually fired twice, so we end up with duplicates when saving the settings for the FIRST TIME only. The issue is not present once the settings are in the DB as the sanitization wont fire again. For details on this core issue - https://core.trac.wordpress.org/ticket/21989. |
| 1859 | global $wp_settings_errors; |
| 1860 | if ( isset( $wp_settings_errors ) ) { |
| 1861 | $errors = array_map( 'unserialize', array_unique( array_map( 'serialize', $wp_settings_errors ) ) ); |
| 1862 | $wp_settings_errors = $errors; |
| 1863 | } |
| 1864 | |
| 1865 | if ( isset( $output ) ) { |
| 1866 | return $output; |
| 1867 | } else { |
| 1868 | return; |
| 1869 | } |
| 1870 | |
| 1871 | } |
| 1872 | |
| 1873 | /** |
| 1874 | * Creates a new page with our shortcode present. |
| 1875 | */ |
| 1876 | public function generate_custom_user_profile_page( $page_slug ) { |
| 1877 | // Bail if user doesnt have permissions to be here. |
| 1878 | if ( ! current_user_can( 'manage_options' ) ) { |
| 1879 | return; |
| 1880 | } |
| 1881 | |
| 1882 | // Check if a page with slug exists. |
| 1883 | $page_exists = $this->get_post_by_post_name( $page_slug, 'page' ); |
| 1884 | if ( $page_exists ) { |
| 1885 | // Seeing as the page exisits, return its ID. |
| 1886 | return $page_exists->ID; |
| 1887 | } |
| 1888 | |
| 1889 | $generated_by_message = sprintf( |
| 1890 | /* translators: %1$s: is the user name, %2$s is the website address */ |
| 1891 | '<p>%1$s <a href="https://www.wpwhitesecurity.com/wordpress-plugins/wp-2fa/" target="_blank">%2$s</a></p>', |
| 1892 | esc_html__( 'Page generated by', 'wp-2fa' ), |
| 1893 | esc_html__( 'WP 2FA Plugin', 'wp-2fa' ) |
| 1894 | ); |
| 1895 | |
| 1896 | $user = wp_get_current_user(); |
| 1897 | $post_data = array( |
| 1898 | 'post_title' => 'WP 2FA User Profile', |
| 1899 | 'post_name' => $page_slug, |
| 1900 | 'post_content' => '[wp-2fa-setup-form] ' . $generated_by_message, |
| 1901 | 'post_status' => 'publish', |
| 1902 | 'post_author' => $user->ID, |
| 1903 | 'post_type' => 'page', |
| 1904 | ); |
| 1905 | |
| 1906 | // Lets insert the post now. |
| 1907 | $result = wp_insert_post( $post_data ); |
| 1908 | |
| 1909 | if ( $result && ! is_wp_error( $result ) ) { |
| 1910 | $post_id = $result; |
| 1911 | set_transient( 'wp_2fa_new_custom_page_created', true, 60 ); |
| 1912 | set_site_transient( 'wp_2fa_new_custom_page_created', true, 60 ); |
| 1913 | return $post_id; |
| 1914 | } |
| 1915 | } |
| 1916 | |
| 1917 | /** |
| 1918 | * Check if page with slug exisits. |
| 1919 | */ |
| 1920 | public function get_post_by_post_name( $slug = '', $post_type = '' ) { |
| 1921 | if ( ! $slug || ! $post_type ) { |
| 1922 | return false; |
| 1923 | } |
| 1924 | |
| 1925 | $post_object = get_page_by_path( $slug, OBJECT, $post_type ); |
| 1926 | |
| 1927 | if ( ! $post_object ) { |
| 1928 | return false; |
| 1929 | } |
| 1930 | |
| 1931 | return $post_object; |
| 1932 | } |
| 1933 | |
| 1934 | /** |
| 1935 | * Add our custom state to our created page. |
| 1936 | */ |
| 1937 | public function add_display_post_states( $post_states, $post ) { |
| 1938 | if ( ! empty( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) ) ) { |
| 1939 | if ( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) === $post->ID ) { |
| 1940 | $post_states['wp_2fa_page_for_user'] = __( 'WP 2FA User Page', 'wp-2fa' ); |
| 1941 | } |
| 1942 | } |
| 1943 | |
| 1944 | return $post_states; |
| 1945 | } |
| 1946 | } |
| 1947 |