PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.6.0
WP 2FA – Two-factor authentication for WordPress v2.6.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 / Helpers / class-ajax-helper.php
wp-2fa / includes / classes / Admin / Helpers Last commit date
class-ajax-helper.php 2 years ago class-classes-helper.php 2 years ago class-file-writer.php 2 years ago class-methods-helper.php 2 years ago class-php-helper.php 2 years ago class-user-helper.php 2 years ago class-wp-helper.php 2 years ago index.php 2 years ago
class-ajax-helper.php
417 lines
1 <?php
2 /**
3 * Responsible for the AJAX calls.
4 *
5 * @package wp2fa
6 * @subpackage helpers
7 *
8 * @since 2.6.0
9 *
10 * @copyright %%YEAR%% Melapress
11 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
12 *
13 * @see https://wordpress.org/plugins/wp-2fa/
14 */
15
16 declare(strict_types=1);
17
18 namespace WP2FA\Admin\Helpers;
19
20 use WP2FA\WP2FA;
21 use WP2FA\Utils\User_Utils;
22 use WP2FA\Admin\Settings_Page;
23 use WP2FA\Utils\Settings_Utils;
24 use WP2FA\Admin\Helpers\WP_Helper;
25 use WP2FA\Admin\SettingsPages\Settings_Page_Email;
26
27 // Exit if accessed directly.
28 if ( ! defined( 'ABSPATH' ) ) {
29 exit;
30 }
31
32 if ( ! class_exists( '\WP2FA\Admin\Helpers\Ajax_Helper' ) ) {
33 /**
34 * Responsible for the proper AJAX calls and responses.
35 */
36 class Ajax_Helper {
37
38 /**
39 * Get all users in AJAX matter and returns them
40 *
41 * @SuppressWarnings(PHPMD.ExitExpression)
42 *
43 * @since 2.6.0
44 */
45 public static function get_all_users() {
46 // Die if user does not have permission to view.
47 if ( ! current_user_can( 'manage_options' ) ) {
48 die( 'Access Denied.' );
49 }
50 // Filter $_GET array for security.
51 $get_array = filter_input_array( INPUT_GET );
52
53 // Die if nonce verification failed.
54 if ( ! wp_verify_nonce( sanitize_text_field( $get_array['wp_2fa_nonce'] ), 'wp-2fa-settings-nonce' ) ) {
55 die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) );
56 }
57
58 $users_args = array(
59 'fields' => array( 'ID', 'user_login' ),
60 );
61 if ( WP_Helper::is_multisite() ) {
62 $users_args['blog_id'] = 0;
63 }
64 $users_data = User_Utils::get_all_user_ids_and_login_names( 'query', $users_args );
65
66 // Create final array which we will fill in below.
67 $users = array();
68
69 foreach ( $users_data as $user ) {
70 if ( stripos( $user['user_login'], $get_array['term'] ) !== false ) {
71 array_push(
72 $users,
73 array(
74 'value' => $user['user_login'],
75 'label' => $user['user_login'],
76 )
77 );
78 }
79 }
80
81 echo wp_json_encode( $users );
82 exit;
83 }
84
85 /**
86 * Get all network sites in AJAX way
87 *
88 * @SuppressWarnings(PHPMD.ExitExpression)
89 *
90 * @since 2.6.0
91 */
92 public static function get_all_network_sites() {
93 // Die if user does not have permission to view.
94 if ( ! current_user_can( 'manage_options' ) ) {
95 die( 'Access Denied.' );
96 }
97 // Filter $_GET array for security.
98 $get_array = filter_input_array( INPUT_GET );
99 // Die if nonce verification failed.
100 if ( ! wp_verify_nonce( sanitize_text_field( $get_array['wp_2fa_nonce'] ), 'wp-2fa-settings-nonce' ) ) {
101 die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) );
102 }
103 // Fetch sites.
104 $sites_found = array();
105
106 foreach ( get_sites() as $site ) {
107 $subsite_id = get_object_vars( $site )['blog_id'];
108 $subsite_name = get_blog_details( $subsite_id )->blogname;
109 $site_details = '';
110 $site_details[ $subsite_id ] = $subsite_name;
111 if ( false !== stripos( $subsite_name, $get_array['term'] ) ) {
112 array_push(
113 $sites_found,
114 array(
115 'label' => $subsite_id,
116 'value' => $subsite_name,
117 )
118 );
119 }
120 }
121 echo wp_json_encode( $sites_found );
122 exit;
123 }
124
125 /**
126 * Unlock users accounts if they have overrun grace period it ia also used in AJAX calls
127 *
128 * @param int $user_id User ID.
129 *
130 * @SuppressWarnings(PHPMD.ExitExpression)
131 *
132 * @since 2.6.0
133 */
134 public static function unlock_account( $user_id ) {
135 // Die if user does not have permission to view.
136 if ( ! current_user_can( 'manage_options' ) ) {
137 die( 'Access Denied.' );
138 }
139
140 $grace_period = WP2FA::get_wp2fa_setting( 'grace-period' );
141 $grace_period_denominator = WP2FA::get_wp2fa_setting( 'grace-period-denominator' );
142 $create_a_string = $grace_period . ' ' . $grace_period_denominator;
143 // Turn that string into a time.
144 $grace_expiry = strtotime( $create_a_string );
145
146 // Filter $_GET array for security.
147 $get_array = filter_input_array( INPUT_GET );
148 $nonce = sanitize_text_field( $get_array['wp_2fa_nonce'] );
149
150 // Die if nonce verification failed.
151 if ( ! wp_verify_nonce( $nonce, 'wp-2fa-unlock-account-nonce' ) ) {
152 die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) );
153 }
154
155 if ( isset( $get_array['user_id'] ) ) {
156 User_Helper::remove_meta( WP_2FA_PREFIX . 'locked_account_notification', intval( $get_array['user_id'] ) );
157 User_Helper::remove_grace_period( intval( $get_array['user_id'] ) );
158
159 User_Helper::set_user_expiry_date( (string) $grace_expiry, intval( $get_array['user_id'] ) );
160 Settings_Page::send_account_unlocked_email( intval( $get_array['user_id'] ) );
161
162 /*
163 * Fires after the user is unlocked.
164 *
165 * @param \WP_User $user - The user for which the method has been set.
166 *
167 * @since 2.6.0
168 */
169 \do_action( WP_2FA_PREFIX . 'user_is_unlocked', User_Helper::get_user( intval( $get_array['user_id'] ) ) );
170
171 \add_action( 'admin_notices', array( __CLASS__, 'user_unlocked_notice' ) );
172 }
173 }
174
175 /**
176 * Sets the salt key into the wp-config.php file via AJAX request.
177 *
178 * @return void
179 *
180 * @since 2.4.0
181 */
182 public static function set_salt_key() {
183 if ( \wp_doing_ajax() ) {
184 if ( isset( $_REQUEST['_wpnonce'] ) ) {
185 $nonce_check = \wp_verify_nonce( \sanitize_text_field( \wp_unslash( $_REQUEST['_wpnonce'] ) ), 'wp-2fa-set-salt-nonce' );
186 if ( ! $nonce_check ) {
187 \wp_send_json_error( new \WP_Error( 500, \esc_html__( 'Nonce checking failed', 'wp-2fa' ) ), 400 );
188 } elseif ( \current_user_can( 'manage_options' ) ) {
189 if ( ! File_Writer::can_write_to_file( File_Writer::get_wp_config_file_path() ) ) {
190 \wp_send_json_error(
191 new \WP_Error(
192 500,
193 \esc_html__(
194 'Unable to write to wp-config.php',
195 'wp-2fa'
196 )
197 ),
198 400
199 );
200 } else {
201 $secret_key = Settings_Utils::get_option( 'secret_key' );
202 if ( ! empty( $secret_key ) ) {
203 File_Writer::save_secret_key( $secret_key );
204 Settings_Utils::delete_option( 'secret_key' );
205 \wp_send_json_success(
206 \esc_html__(
207 'wp-config.php successfully update, global setting deleted',
208 'wp-2fa'
209 )
210 );
211 } else {
212 \wp_send_json_error(
213 new \WP_Error(
214 500,
215 \esc_html__(
216 'Unable to find global secret key',
217 'wp-2fa'
218 )
219 ),
220 400
221 );
222 }
223 }
224 }
225 }
226 }
227 }
228
229 /**
230 * Remove user 2fa config
231 *
232 * @param int $user_id User ID.
233 *
234 * @SuppressWarnings(PHPMD.ExitExpression)
235 *
236 * @since 2.6.0
237 */
238 public static function remove_user_2fa( $user_id ) {
239 // Filter $_GET array for security.
240 $get_array = filter_input_array( INPUT_GET );
241 $nonce = sanitize_text_field( $get_array['wp_2fa_nonce'] );
242
243 if ( ! wp_verify_nonce( $nonce, 'wp-2fa-remove-user-2fa-nonce' ) ) {
244 die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) );
245 }
246
247 if ( isset( $get_array['user_id'] ) ) {
248 $user_id = intval( $get_array['user_id'] );
249
250 if ( ! current_user_can( 'manage_options' ) && get_current_user_id() !== $user_id ) {
251 return;
252 }
253
254 User_Helper::remove_2fa_for_user( $user_id );
255
256 if ( isset( $get_array['admin_reset'] ) ) {
257 add_action( 'admin_notices', array( __CLASS__, 'admin_deleted_2fa_notice' ) );
258 } else {
259 add_action( 'admin_notices', array( __CLASS__, 'user_deleted_2fa_notice' ) );
260 }
261 }
262 }
263
264 /**
265 * Returns the user roles in AJAX matter.
266 *
267 * @return void
268 *
269 * @since 2.6.0
270 */
271 public static function get_ajax_user_roles() {
272 if ( \wp_doing_ajax() ) {
273 // Filter $_GET array for security.
274 $get_array = filter_input_array( INPUT_GET );
275
276 // Die if nonce verification failed.
277 if ( ! wp_verify_nonce( sanitize_text_field( $get_array['wp_2fa_nonce'] ), 'wp-2fa-settings-nonce' ) ) {
278 die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) );
279 }
280 $roles = array();
281
282 foreach ( WP_Helper::get_roles_wp() as $role => $human_readable ) {
283 if ( stripos( $human_readable, $get_array['term'] ) !== false ) {
284 array_push(
285 $roles,
286 array(
287 'label' => $role,
288 'value' => $human_readable,
289 )
290 );
291 }
292 }
293
294 echo wp_json_encode( $roles );
295 exit;
296 }
297 }
298
299 /**
300 * Handles AJAX calls for sending test emails.
301 *
302 * @return void
303 *
304 * @since 2.6.0
305 */
306 public static function handle_send_test_email_ajax() {
307
308 // check user permissions.
309 if ( ! current_user_can( 'manage_options' ) ) {
310 wp_send_json_error();
311 }
312
313 // check email id.
314 $email_id = isset( $_POST['email_id'] ) ? sanitize_text_field( \wp_unslash( $_POST['email_id'] ) ) : null;
315 if ( null === $email_id || false === $email_id ) {
316 wp_send_json_error();
317 }
318
319 // check nonce.
320 $nonce = isset( $_POST['_wpnonce'] ) ? sanitize_text_field( \wp_unslash( $_POST['_wpnonce'] ) ) : null;
321 if ( null === $nonce || false === $nonce || ! wp_verify_nonce( $nonce, 'wp-2fa-email-test-' . $email_id ) ) {
322 wp_send_json_error();
323 }
324
325 $user_id = get_current_user_id();
326 // Grab user data.
327 $user = get_userdata( $user_id );
328 // Grab user email.
329 $email = $user->user_email;
330
331 if ( 'config_test' === $email_id ) {
332 $email_sent = Settings_Page::send_email(
333 $email,
334 esc_html__( 'Test email from WP 2FA', 'wp-2fa' ),
335 esc_html__( 'This email was sent by the WP 2FA plugin to test the email delivery.', 'wp-2fa' )
336 );
337 if ( $email_sent ) {
338 wp_send_json_success( 'Test email was successfully sent to <strong>' . $email . '</strong>' );
339 }
340
341 wp_send_json_error();
342 }
343
344 /**
345 * All email templates
346 *
347 * @var Email_Template[] $email_templates
348 */
349 $email_templates = Settings_Page_Email::get_email_notification_definitions();
350 foreach ( $email_templates as $email_template ) {
351 if ( $email_id === $email_template->get_email_content_id() ) {
352 // send the test email.
353
354 // Setup the email contents.
355 $subject = wp_strip_all_tags( \WP2FA\WP2FA::replace_email_strings( \WP2FA\WP2FA::get_wp2fa_email_templates( $email_id . '_email_subject' ) ) );
356 $message = wpautop( \WP2FA\WP2FA::replace_email_strings( \WP2FA\WP2FA::get_wp2fa_email_templates( $email_id . '_email_body' ), $user_id ) );
357
358 $email_sent = Settings_Page::send_email( $email, $subject, $message );
359 if ( $email_sent ) {
360 wp_send_json_success( 'Test email <strong>' . $email_template->get_title() . '</strong> was successfully sent to <strong>' . $email . '</strong>' );
361 }
362
363 wp_send_json_error();
364 }
365 }
366 }
367
368 /**
369 * User deleted 2FA settings notification
370 *
371 * @since 2.6.0
372 */
373 public static function user_deleted_2fa_notice() {
374 ?>
375 <div class="notice notice-success is-dismissible">
376 <p><?php esc_html_e( 'Your 2FA settings have been removed.', 'wp-2fa' ); ?></p>
377 <button type="button" class="notice-dismiss">
378 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
379 </button>
380 </div>
381 <?php
382 }
383
384 /**
385 * Admin deleted user 2FA settings notification
386 *
387 * @since 2.6.0
388 */
389 public static function admin_deleted_2fa_notice() {
390 ?>
391 <div class="notice notice-success is-dismissible">
392 <p><?php esc_html_e( 'User 2FA settings have been removed.', 'wp-2fa' ); ?></p>
393 <button type="button" class="notice-dismiss">
394 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
395 </button>
396 </div>
397 <?php
398 }
399
400 /**
401 * User unlocked notice.
402 *
403 * @since 2.6.0
404 */
405 public static function user_unlocked_notice() {
406 ?>
407 <div class="notice notice-success is-dismissible">
408 <p><?php esc_html_e( 'User account successfully unlocked. User can login again.', 'wp-2fa' ); ?></p>
409 <button type="button" class="notice-dismiss">
410 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
411 </button>
412 </div>
413 <?php
414 }
415 }
416 }
417