PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.8.0
WP 2FA – Two-factor authentication for WordPress v2.8.0
4.0.0 1.7.1 2.0.0 2.0.1 2.1.0 2.2.0 2.2.1 2.3.0 2.4.0 2.4.1 2.4.2 2.5.0 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.8.0 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0 3.0.1 3.1.0 3.1.1 3.1.1.2 trunk 1.2.0 1.3.0 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.1 1.6.2 1.7.0
wp-2fa / includes / classes / Admin / Methods / class-email-wizard-steps.php
wp-2fa / includes / classes / Admin / Methods Last commit date
Traits 1 year ago class-backup-codes.php 1 year ago class-email-wizard-steps.php 1 year ago class-email.php 1 year ago class-totp-wizard-steps.php 1 year ago class-totp.php 1 year ago index.php 1 year ago
class-email-wizard-steps.php
351 lines
1 <?php
2 /**
3 * Responsible for WP2FA user's Email manipulation.
4 *
5 * @package wp2fa
6 * @subpackage methods-wizard
7 * @since 2.6.0
8 * @copyright 2024 Melapress
9 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
10 *
11 * @see https://wordpress.org/plugins/wp-2fa/
12 */
13
14 declare(strict_types=1);
15
16 namespace WP2FA\Methods\Wizards;
17
18 use WP2FA\WP2FA;
19 use WP2FA\Methods\Email;
20 use WP2FA\Admin\Helpers\WP_Helper;
21 use WP2FA\Admin\Views\Wizard_Steps;
22 use WP2FA\Admin\Helpers\User_Helper;
23 use WP2FA\Admin\Controllers\Settings;
24 use WP2FA\Admin\Methods\Traits\Methods_Wizards_Trait;
25 use WP2FA\Extensions\RoleSettings\Role_Settings_Controller;
26
27 /**
28 * Class for handling email codes.
29 *
30 * @since 2.6.0
31 *
32 * @package WP2FA
33 */
34 if ( ! class_exists( '\WP2FA\Methods\Wizards\Email_Wizard_Steps' ) ) {
35 /**
36 * Email code class, for handling email code generation and such.
37 *
38 * @since 2.6.0
39 */
40 class Email_Wizard_Steps extends Wizard_Steps {
41
42 use Methods_Wizards_Trait;
43
44 /**
45 * Keeps the main class method name, so we can call it when needed.
46 *
47 * @var string
48 *
49 * @since 2.6.0
50 */
51 private static $main_class = Email::class;
52
53 /**
54 * The default value of the method order in the wizards.
55 *
56 * @var integer
57 *
58 * @since 2.6.0
59 */
60 private static $order = 2;
61
62 /**
63 * Inits the class hooks
64 *
65 * @return void
66 *
67 * @since 2.4.0
68 */
69 public static function init() {
70 \add_filter( WP_2FA_PREFIX . 'methods_modal_options', array( __CLASS__, 'email_option' ), 10, 2 );
71 \add_action( WP_2FA_PREFIX . 'modal_methods', array( __CLASS__, 'email_modal_configure' ) );
72 \add_filter( WP_2FA_PREFIX . 'methods_re_configure', array( __CLASS__, 'email_re_configure' ), 10, 2 );
73 \add_filter( WP_2FA_PREFIX . 'methods_settings', array( __CLASS__, 'email_wizard_settings' ), 10, 4 );
74 }
75
76 /**
77 * Shows the option for email method reconfiguring (if applicable)
78 *
79 * @param array $methods - Array of methods collected.
80 * @param string $role - The name of the role to show option to.
81 *
82 * @since 2.6.0 - Parameter $methods is added, parameter $role (name) is added and array is now returned
83 *
84 * @return array
85 */
86 public static function email_re_configure( array $methods, string $role ): array {
87
88 if ( ! Email::is_enabled() ) {
89 return $methods;
90 }
91 \ob_start();
92 ?>
93 <div class="option-pill">
94 <?php echo \wp_kses_post( WP2FA::contextual_reconfigure_text( WP2FA::get_wp2fa_white_label_setting( 'hotp_reconfigure_intro', true ), User_Helper::get_user_object()->ID, 'hotp' ) ); ?>
95 <div class="wp2fa-setup-actions">
96 <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( User_Helper::get_user_object()->ID ); ?>" <?php echo WP_Helper::create_data_nonce( 'wp-2fa-send-setup-email' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> data-next-step="2fa-wizard-email"><?php \esc_html_e( 'Change email address', 'wp-2fa' ); ?></a>
97 </div>
98 </div>
99 <?php
100 $output = ob_get_contents();
101 ob_end_clean();
102
103 $methods[ self::get_order( $role, $methods ) ] = array(
104 'name' => self::$main_class::METHOD_NAME,
105 'output' => $output,
106 );
107
108 return $methods;
109 }
110
111 /**
112 * Shows the initial email setup options based on enabled methods
113 *
114 * @param array $methods - Array of methods collected.
115 * @param string $role - The name of the role to show option to.
116 *
117 * @since 2.6.0 - Parameter $methods is added, parameter $role (name) is added and array is now returned
118 *
119 * @return array
120 */
121 public static function email_option( array $methods, string $role ): array {
122 if ( Email::is_enabled() ) {
123 \ob_start();
124 ?>
125 <div class="option-pill">
126 <label for="geek">
127 <input id="geek" name="wp_2fa_enabled_methods" type="radio" value="email">
128 <?php echo \wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'email-option-label', true ) ); ?>
129 </label>
130 </div>
131 <?php
132 $output = ob_get_contents();
133 ob_end_clean();
134
135 $methods[ self::get_order( $role, $methods ) ] = $output;
136 }
137
138 return $methods;
139 }
140
141 /**
142 * Settings page and first time wizard settings render
143 *
144 * @param array $methods - Array with all the methods in which we have to add this one.
145 * @param boolean $setup_wizard - Is that the first time setup wizard.
146 * @param string $data_role - Additional HTML data attribute.
147 * @param mixed $role - Name of the role.
148 *
149 * @return array - The array with the methods with all the methods wizard steps.
150 *
151 * @since 2.6.0
152 */
153 public static function email_wizard_settings( array $methods, bool $setup_wizard, string $data_role, $role = null ) {
154 $name_prefix = \WP_2FA_POLICY_SETTINGS_NAME;
155 $role_id = '';
156 if ( null !== $role && '' !== trim( (string) $role ) ) {
157 $name_prefix .= "[{$role}]";
158 $data_role = 'data-role="' . $role . '"';
159 $role_id = '-' . $role;
160 }
161 \ob_start();
162 ?>
163 <div id="<?php echo \esc_attr( Email::METHOD_NAME ); ?>-method-wrapper" class="method-wrapper">
164 <?php echo self::hidden_order_setting( $role ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
165 <label for="hotp<?php echo \esc_attr( $role_id ); ?>" style="margin-bottom: 0 !important;">
166 <input type="checkbox" id="hotp<?php echo \esc_attr( $role_id ); ?>" name="<?php echo \esc_attr( $name_prefix ); ?>[enable_email]" value="enable_email"
167 <?php echo $data_role; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
168 <?php if ( null !== $role && ! empty( $role ) ) { ?>
169 <?php \checked( Email::POLICY_SETTINGS_NAME, Role_Settings_Controller::get_setting( $role, Email::POLICY_SETTINGS_NAME ), true ); ?>
170 <?php
171 } else {
172 $use_role_setting = null;
173 if ( null === $role || '' === trim( (string) $role ) ) {
174 $use_role_setting = \WP_2FA_PREFIX . 'no-user';
175 }
176
177 $enabled_settings = Settings::get_role_or_default_setting( Email::POLICY_SETTINGS_NAME, $use_role_setting, $role, true );
178 ?>
179 <?php \checked( $enabled_settings, Email::POLICY_SETTINGS_NAME ); ?>
180 <?php } ?>
181 >
182 <?php
183 \esc_html_e( 'One-time code via email (HOTP)', 'wp-2fa' );
184 \esc_html_e( ' - ensure email deliverability with the free plugin ', 'wp-2fa' );
185 echo '<a href="https://wordpress.org/plugins/wp-mail-smtp/" target="_blank" rel="nofollow">WP Mail SMTP</a>.';
186 ?>
187 </label>
188 <?php
189 if ( $setup_wizard ) {
190 echo '<p class="description">' . \esc_html__( 'When using this method, users will receive the one-time login code over email. Therefore, email deliverability is very important. Users using this method should whitelist the address from which the codes are sent. By default, this is the email address configured in your WordPress. You can run an email test from the plugin\'s settings to confirm email deliverability. If you have had email deliverability / reliability issues, we highly recommend you to install the free plugin ', 'wp-2fa' ) . '<a href="https://wordpress.org/plugins/wp-mail-smtp/" target="_blank" rel="nofollow">WP Mail SMTP</a><br><br>' . \esc_html__( 'Allowing users to set up a secondary 2FA method is highly recommended. You can do this in the next step of the wizard. This will allow users to log in using an alternative method should they, for example lose access to their phone.', 'wp-2fa' ) . '</p>';
191 }
192 ?>
193 <?php
194 if ( null !== $role ) {
195 $enabled_settings = Role_Settings_Controller::get_setting( $role, 'enable_email' );
196 } else {
197 $enabled_settings = Settings::get_role_or_default_setting( 'enable_email', ( ( null !== $role && '' !== $role ) ? '' : false ), $role, true, true );
198 }
199 ?>
200 <?php
201 ?>
202 <?php if ( ! $setup_wizard ) { ?>
203 <div class="use-different-hotp-mail<?php echo \esc_attr( ( false === $enabled_settings ? ' disabled' : '' ) ); ?>">
204 <p class="description">
205 <?php \esc_html_e( 'Allow user to specify the email address of choice', 'wp-2fa' ); ?>
206 </p>
207 <fieldset class="email-hotp-options">
208 <?php
209 $options = array(
210 'yes' => array(
211 'label' => \esc_html__( 'Yes', 'wp-2fa' ),
212 'value' => 'specify-email_hotp',
213 ),
214 'no' => array(
215 'label' => \esc_html__( 'No', 'wp-2fa' ),
216 'value' => '',
217 ),
218 );
219
220 foreach ( $options as $option_key => $option_settings ) {
221 ?>
222 <label for="specify-email_hotp-<?php echo \esc_attr( $option_key ); ?>">
223 <input type="radio"
224 name="<?php echo \esc_attr( $name_prefix ); ?>[specify-email_hotp]"
225 <?php echo $data_role; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
226 id="specify-email_hotp-<?php echo \esc_attr( $option_key ); ?>"
227 value="<?php echo \esc_attr( $option_settings['value'] ); ?>" class="js-nested"
228 <?php if ( null !== $role ) { ?>
229 <?php \checked( Role_Settings_Controller::get_setting( $role, 'specify-email_hotp' ), $option_settings['value'] ); ?>
230 <?php
231 } else {
232
233 $use_role_setting = null;
234 if ( null === $role || '' === trim( (string) $role ) ) {
235 $use_role_setting = \WP_2FA_PREFIX . 'no-user';
236 }
237
238 \checked( Settings::get_role_or_default_setting( 'specify-email_hotp', $use_role_setting, $role, true, false ), $option_settings['value'] );
239 ?>
240 <?php } ?>
241 >
242 <span><?php echo $option_settings['label']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></span>
243 </label>
244 <?php
245 }
246 ?>
247 </fieldset>
248 </div>
249 <?php } ?>
250 </div>
251 <?php
252 $output = ob_get_contents();
253 ob_end_clean();
254
255 $methods[ self::get_order( $role, $methods ) ] = $output;
256
257 return $methods;
258 }
259
260 /**
261 * Reconfigures email form
262 *
263 * @since 2.6.0
264 *
265 * @return void
266 */
267 public static function email_modal_configure() {
268
269 if ( ! Email::is_enabled() ) {
270 return;
271 }
272 ?>
273 <div class="wizard-step" id="2fa-wizard-email">
274 <fieldset>
275 <div class="step-setting-wrapper active">
276 <div class="mb-20">
277 <?php echo \wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'method_help_hotp_intro', true ) ); ?>
278 </div>
279 <fieldset class="radio-cells">
280 <div class="option-pill">
281 <label for="use_wp_email">
282 <input type="radio" name="wp_2fa_email_address" id="use_wp_email" value="<?php echo \esc_attr( User_Helper::get_user_object()->user_email ); ?>" checked>
283 <span><?php \esc_html_e( 'Use my user email (', 'wp-2fa' ); ?><small><?php echo \esc_attr( User_Helper::get_user_object()->user_email ); ?></small><?php \esc_html_e( ')', 'wp-2fa' ); ?></span>
284 </label>
285 </div>
286 <?php
287 if ( Settings::get_role_or_default_setting( 'specify-email_hotp', User_Helper::get_user_object() ) ) {
288 ?>
289 <div class="option-pill">
290 <label for="use_custom_email">
291 <input type="radio" name="wp_2fa_email_address" id="use_custom_email" value="use_custom_email">
292 <span><?php \esc_html_e( 'Use a different email address:', 'wp-2fa' ); ?></span>
293 <?php \esc_html_e( 'Email address', 'wp-2fa' ); ?>
294 <input type="email" name="custom-email-address" id="custom-email-address" class="input" value=""/>
295 </label>
296 </div>
297 <?php
298 }
299 ?>
300 </fieldset>
301 <p class="description"><?php echo \wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'method_help_hotp_help', true ) ); ?></p><br>
302
303 <?php
304 $from_email = \get_option( 'admin_email' );
305
306 $custom_mail = WP2FA::get_wp2fa_email_templates( 'custom_from_email_address' );
307
308 if ( isset( $custom_mail ) && ! empty( (string) $custom_mail ) ) {
309 $from_email = $custom_mail;
310 }
311
312 echo \wp_kses_post( str_replace( '{from_email}', $from_email, WP2FA::get_wp2fa_white_label_setting( 'method_help_hotp_help_email', true ) ) );
313 ?>
314
315 <div class="wp2fa-setup-actions">
316 <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( User_Helper::get_user_object()->ID ); ?>" <?php echo WP_Helper::create_data_nonce( 'wp-2fa-send-setup-email' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> type="button"><?php \esc_html_e( 'I\'m Ready', 'wp-2fa' ); ?></button>
317 <a class="button button-primary wp-2fa-button-primary modal_cancel"><?php \esc_attr_e( 'Cancel', 'wp-2fa' ); ?></a>
318 </div>
319 </div>
320
321 <div class="step-setting-wrapper" data-step-title="<?php \esc_html_e( 'Verify configuration', 'wp-2fa' ); ?>" id="2fa-wizard-email">
322 <div class="mb-20">
323 <?php echo \wp_kses_post( WP2FA::get_wp2fa_white_label_setting( 'method_verification_hotp_pre', true ) ); ?>
324 </div>
325 <fieldset>
326 <label for="2fa-email-authcode">
327 <?php \esc_html_e( 'Authentication Code', 'wp-2fa' ); ?>
328 <input type="tel" name="wp-2fa-email-authcode" id="wp-2fa-email-authcode" class="input" value="" size="20" pattern="[0-9]*" autocomplete="off"/>
329 <script>
330 const email_authcode = document.getElementById('wp-2fa-email-authcode');
331 email_authcode.addEventListener('input', function() {
332 this.value = this.value.trim();
333 });
334 </script>
335 </label>
336 <div class="verification-response"></div>
337 </fieldset>
338 <br />
339 <a href="#" class="button wp-2fa-button-primary" data-validate-authcode-ajax <?php echo WP_Helper::create_data_nonce( 'wp-2fa-validate-authcode' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>><?php \esc_html_e( 'Validate & Save', 'wp-2fa' ); ?></a>
340 <a href="#" class="button wp-2fa-button-primary resend-email-code" data-trigger-setup-email data-user-id="<?php echo \esc_attr( User_Helper::get_user_object()->ID ); ?>" <?php echo WP_Helper::create_data_nonce( 'wp-2fa-send-setup-email' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
341 <span class="resend-inner"><?php \esc_html_e( 'Send me another code', 'wp-2fa' ); ?></span>
342 </a>
343 <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>
344 </div>
345 </fieldset>
346 </div>
347 <?php
348 }
349 }
350 }
351