Version Description
Download this release
Release Info
Developer | johnbillion |
Plugin | User Switching |
Version | 1.4.0 |
Comparing to | |
See all releases |
Code changes from version 1.3.1 to 1.4.0
- composer.json +2 -2
- readme.txt +71 -15
- user-switching.php +305 -251
composer.json
CHANGED
@@ -27,10 +27,10 @@
|
|
27 |
"behat/mink-goutte-driver": "^1.1",
|
28 |
"johnbillion/php-docs-standards": "^1.2",
|
29 |
"johnbillion/wordpress-behat-extension": "^0.1.5",
|
30 |
-
"johnpbloch/wordpress": ">=4.
|
31 |
"phpunit/phpunit": "^5",
|
32 |
"wimg/php-compatibility": "^8",
|
33 |
-
"wp-coding-standards/wpcs": "
|
34 |
},
|
35 |
"extra": {
|
36 |
"wordpress-install-dir": "vendor/wordpress"
|
27 |
"behat/mink-goutte-driver": "^1.1",
|
28 |
"johnbillion/php-docs-standards": "^1.2",
|
29 |
"johnbillion/wordpress-behat-extension": "^0.1.5",
|
30 |
+
"johnpbloch/wordpress": ">=4.9.0@stable",
|
31 |
"phpunit/phpunit": "^5",
|
32 |
"wimg/php-compatibility": "^8",
|
33 |
+
"wp-coding-standards/wpcs": "1.0"
|
34 |
},
|
35 |
"extra": {
|
36 |
"wordpress-install-dir": "vendor/wordpress"
|
readme.txt
CHANGED
@@ -1,11 +1,12 @@
|
|
1 |
=== User Switching ===
|
2 |
|
3 |
-
Contributors: johnbillion
|
4 |
-
Tags: users, profiles, user switching, fast user switching, multisite, buddypress, bbpress, become, user management, developer
|
5 |
-
Requires at least: 3.7
|
6 |
-
Tested up to: 4.9
|
7 |
-
Stable tag: 1.
|
8 |
-
|
|
|
9 |
|
10 |
Instant switching between user accounts in WordPress.
|
11 |
|
@@ -19,14 +20,15 @@ This plugin allows you to quickly swap between user accounts in WordPress at the
|
|
19 |
* Switch back: Instantly switch back to your originating account.
|
20 |
* Switch off: Log out of your account but retain the ability to instantly switch back in again.
|
21 |
* It's completely secure (see the *Security* section below).
|
22 |
-
* Compatible with WordPress, WordPress Multisite, BuddyPress and bbPress.
|
23 |
|
24 |
= Security =
|
25 |
|
26 |
-
* Only users with the ability to edit other users can switch user accounts. By default this is only Administrators on single site
|
27 |
* Passwords are not (and cannot be) revealed.
|
28 |
* Uses the cookie authentication system in WordPress when remembering the account(s) you've switched from and when switching back.
|
29 |
* Implements the nonce security system in WordPress, meaning only those who intend to switch users can switch.
|
|
|
30 |
* Full support for administration over SSL (if applicable).
|
31 |
|
32 |
= Usage =
|
@@ -39,7 +41,11 @@ See the [FAQ](https://wordpress.org/plugins/user-switching/faq/) for information
|
|
39 |
|
40 |
= Privacy Statement =
|
41 |
|
42 |
-
User Switching makes use of browser cookies in order to allow users to switch to another account. Its cookies operate using the same mechanism as the authentication cookies in WordPress core, therefore
|
|
|
|
|
|
|
|
|
43 |
|
44 |
User Switching does not send data to any third party, nor does it include any third party resources, nor will it ever do so.
|
45 |
|
@@ -78,7 +84,13 @@ One exception I'm aware of is [Duo Security](https://wordpress.org/plugins/duo-w
|
|
78 |
|
79 |
A user needs the `edit_users` capability in order to switch user accounts. By default only Administrators have this capability, and with Multisite enabled only Super Admins have this capability.
|
80 |
|
81 |
-
= Can
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
|
83 |
No. This can be enabled though by installing the [User Switching for Regular Admins](https://github.com/johnbillion/user-switching-for-regular-admins) plugin.
|
84 |
|
@@ -88,11 +100,55 @@ Yes, there's a third party add-on plugin for this: [Admin Bar User Switching](ht
|
|
88 |
|
89 |
= Are any plugin actions called when a user switches account? =
|
90 |
|
91 |
-
Yes. When a user switches to another account, the `switch_to_user` hook is called
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
== Changelog ==
|
98 |
|
1 |
=== User Switching ===
|
2 |
|
3 |
+
Contributors: johnbillion
|
4 |
+
Tags: users, profiles, user switching, fast user switching, multisite, buddypress, bbpress, become, user management, developer
|
5 |
+
Requires at least: 3.7
|
6 |
+
Tested up to: 4.9
|
7 |
+
Stable tag: 1.4.0
|
8 |
+
Requires PHP: 5.3
|
9 |
+
License: GPL v2 or later
|
10 |
|
11 |
Instant switching between user accounts in WordPress.
|
12 |
|
20 |
* Switch back: Instantly switch back to your originating account.
|
21 |
* Switch off: Log out of your account but retain the ability to instantly switch back in again.
|
22 |
* It's completely secure (see the *Security* section below).
|
23 |
+
* Compatible with WordPress, WordPress Multisite, BuddyPress, and bbPress.
|
24 |
|
25 |
= Security =
|
26 |
|
27 |
+
* Only users with the ability to edit other users can switch user accounts. By default this is only Administrators on single site installations, and Super Admins on Multisite installations.
|
28 |
* Passwords are not (and cannot be) revealed.
|
29 |
* Uses the cookie authentication system in WordPress when remembering the account(s) you've switched from and when switching back.
|
30 |
* Implements the nonce security system in WordPress, meaning only those who intend to switch users can switch.
|
31 |
+
* Full support for user session validation where appropriate.
|
32 |
* Full support for administration over SSL (if applicable).
|
33 |
|
34 |
= Usage =
|
41 |
|
42 |
= Privacy Statement =
|
43 |
|
44 |
+
User Switching makes use of browser cookies in order to allow users to switch to another account. Its cookies operate using the same mechanism as the authentication cookies in WordPress core, therefore their values contain the user's `user_login` field in plain text which should be treated as potentially personally identifiable information. The names of the cookies are:
|
45 |
+
|
46 |
+
* `wordpress_user_sw_{COOKIEHASH}`
|
47 |
+
* `wordpress_user_sw_secure_{COOKIEHASH}`
|
48 |
+
* `wordpress_user_sw_olduser_{COOKIEHASH}`
|
49 |
|
50 |
User Switching does not send data to any third party, nor does it include any third party resources, nor will it ever do so.
|
51 |
|
84 |
|
85 |
A user needs the `edit_users` capability in order to switch user accounts. By default only Administrators have this capability, and with Multisite enabled only Super Admins have this capability.
|
86 |
|
87 |
+
= Can the ability to switch accounts be granted to other users or roles? =
|
88 |
+
|
89 |
+
Yes. The `switch_users` meta capability can be explicitly granted to a user or a role to allow them to switch users regardless of whether or not they have the `edit_users` capability. For practical purposes, the user or role will also need the `list_users` capability so they can access the Users menu in the WordPress admin area.
|
90 |
+
|
91 |
+
If you know what you're doing with user capabilities, this capability can also be denied from a user or role to prevent the ability to switch users, regardless of whether or not they have the `edit_users` capability.
|
92 |
+
|
93 |
+
= Can regular admins on Multisite installations switch accounts? =
|
94 |
|
95 |
No. This can be enabled though by installing the [User Switching for Regular Admins](https://github.com/johnbillion/user-switching-for-regular-admins) plugin.
|
96 |
|
100 |
|
101 |
= Are any plugin actions called when a user switches account? =
|
102 |
|
103 |
+
Yes. When a user switches to another account, the `switch_to_user` hook is called:
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Fires when a user switches to another user account.
|
107 |
+
*
|
108 |
+
* @since 0.6.0
|
109 |
+
* @since 1.4.0 The `$new_token` and `$old_token` parameters were added.
|
110 |
+
*
|
111 |
+
* @param int $user_id The ID of the user being switched to.
|
112 |
+
* @param int $old_user_id The ID of the user being switched from.
|
113 |
+
* @param string $new_token The token of the session of the user being switched to. Can be an empty string
|
114 |
+
* or a token for a session that may or may not still be valid.
|
115 |
+
* @param string $old_token The token of the session of the user being switched from.
|
116 |
+
*/
|
117 |
+
do_action( 'switch_to_user', $user_id, $old_user_id, $new_token, $old_token );
|
118 |
+
|
119 |
+
When a user switches back to their originating account, the `switch_back_user` hook is called:
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Fires when a user switches back to their originating account.
|
123 |
+
*
|
124 |
+
* @since 0.6.0
|
125 |
+
* @since 1.4.0 The `$new_token` and `$old_token` parameters were added.
|
126 |
+
*
|
127 |
+
* @param int $user_id The ID of the user being switched back to.
|
128 |
+
* @param int|false $old_user_id The ID of the user being switched from, or false if the user is switching back
|
129 |
+
* after having been switched off.
|
130 |
+
* @param string $new_token The token of the session of the user being switched to. Can be an empty string
|
131 |
+
* or a token for a session that may or may not still be valid.
|
132 |
+
* @param string $old_token The token of the session of the user being switched from.
|
133 |
+
*/
|
134 |
+
|
135 |
+
When a user switches off, the `switch_off_user` hook is called:
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Fires when a user switches off.
|
139 |
+
*
|
140 |
+
* @since 0.6.0
|
141 |
+
* @since 1.4.0 The `$old_token` parameter was added.
|
142 |
+
*
|
143 |
+
* @param int $old_user_id The ID of the user switching off.
|
144 |
+
* @param string $old_token The token of the session of the user switching off.
|
145 |
+
*/
|
146 |
+
|
147 |
+
In addition, User Switching respects the following filters from WordPress core when appropriate:
|
148 |
+
|
149 |
+
* `login_redirect` when switching to another user.
|
150 |
+
* `logout_redirect` when switching off.
|
151 |
+
* `send_auth_cookies` before setting any cookies.
|
152 |
|
153 |
== Changelog ==
|
154 |
|
user-switching.php
CHANGED
@@ -8,15 +8,16 @@
|
|
8 |
* @copyright 2009-2018 John Blackbourn
|
9 |
* @license GPL v2 or later
|
10 |
*
|
11 |
-
* Plugin Name:
|
12 |
-
* Description:
|
13 |
-
* Version:
|
14 |
-
* Plugin URI:
|
15 |
-
* Author:
|
16 |
-
* Author URI:
|
17 |
-
* Text Domain:
|
18 |
-
* Domain Path:
|
19 |
-
* Network:
|
|
|
20 |
*
|
21 |
* This program is free software; you can redistribute it and/or modify
|
22 |
* it under the terms of the GNU General Public License as published by
|
@@ -35,17 +36,16 @@
|
|
35 |
class user_switching {
|
36 |
|
37 |
/**
|
38 |
-
* The name used to identify the application
|
39 |
*
|
40 |
* @var string
|
41 |
*/
|
42 |
public static $application = 'WordPress/User Switching';
|
43 |
|
44 |
/**
|
45 |
-
*
|
46 |
*/
|
47 |
-
|
48 |
-
|
49 |
// Required functionality:
|
50 |
add_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ), 10, 4 );
|
51 |
add_filter( 'map_meta_cap', array( $this, 'filter_map_meta_cap' ), 10, 4 );
|
@@ -67,14 +67,12 @@ class user_switching {
|
|
67 |
add_action( 'bp_member_header_actions', array( $this, 'action_bp_button' ), 11 );
|
68 |
add_action( 'bp_directory_members_actions', array( $this, 'action_bp_button' ), 11 );
|
69 |
add_action( 'bbp_template_after_user_details', array( $this, 'action_bbpress_button' ) );
|
70 |
-
|
71 |
}
|
72 |
|
73 |
/**
|
74 |
-
* Defines the names of
|
75 |
*/
|
76 |
public function action_plugins_loaded() {
|
77 |
-
|
78 |
// User Switching's auth_cookie
|
79 |
if ( ! defined( 'USER_SWITCHING_COOKIE' ) ) {
|
80 |
define( 'USER_SWITCHING_COOKIE', 'wordpress_user_sw_' . COOKIEHASH );
|
@@ -89,11 +87,10 @@ class user_switching {
|
|
89 |
if ( ! defined( 'USER_SWITCHING_OLDUSER_COOKIE' ) ) {
|
90 |
define( 'USER_SWITCHING_OLDUSER_COOKIE', 'wordpress_user_sw_olduser_' . COOKIEHASH );
|
91 |
}
|
92 |
-
|
93 |
}
|
94 |
|
95 |
/**
|
96 |
-
* Outputs the 'Switch To' link on the user editing screen if
|
97 |
*
|
98 |
* @param WP_User $user User object for this screen.
|
99 |
*/
|
@@ -120,32 +117,19 @@ class user_switching {
|
|
120 |
* @return bool Whether the current user is being 'remembered' or not.
|
121 |
*/
|
122 |
public static function remember() {
|
123 |
-
|
124 |
-
/**
|
125 |
-
* Filter the duration of the authentication cookie expiration period.
|
126 |
-
*
|
127 |
-
* This matches the WordPress core filter in `wp_set_auth_cookie()`.
|
128 |
-
*
|
129 |
-
* @since 0.2.2
|
130 |
-
*
|
131 |
-
* @param int $length Duration of the expiration period in seconds.
|
132 |
-
* @param int $user_id User ID.
|
133 |
-
* @param bool $remember Whether to remember the user login. Default false.
|
134 |
-
*/
|
135 |
$cookie_life = apply_filters( 'auth_cookie_expiration', 172800, get_current_user_id(), false );
|
136 |
$current = wp_parse_auth_cookie( '', 'logged_in' );
|
137 |
|
138 |
// Here we calculate the expiration length of the current auth cookie and compare it to the default expiration.
|
139 |
// If it's greater than this, then we know the user checked 'Remember Me' when they logged in.
|
140 |
return ( ( $current['expiration'] - time() ) > $cookie_life );
|
141 |
-
|
142 |
}
|
143 |
|
144 |
/**
|
145 |
* Loads localisation files and routes actions depending on the 'action' query var.
|
146 |
*/
|
147 |
public function action_init() {
|
148 |
-
|
149 |
load_plugin_textdomain( 'user-switching', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
|
150 |
|
151 |
if ( ! isset( $_REQUEST['action'] ) ) {
|
@@ -175,7 +159,6 @@ class user_switching {
|
|
175 |
// Switch user:
|
176 |
$user = switch_to_user( $user_id, self::remember() );
|
177 |
if ( $user ) {
|
178 |
-
|
179 |
$redirect_to = self::get_redirect( $user, $current_user );
|
180 |
|
181 |
// Redirect to the dashboard or the home URL depending on capabilities:
|
@@ -191,7 +174,6 @@ class user_switching {
|
|
191 |
wp_safe_redirect( add_query_arg( $args, admin_url() ), 302, self::$application );
|
192 |
}
|
193 |
exit;
|
194 |
-
|
195 |
} else {
|
196 |
wp_die( esc_html__( 'Could not switch users.', 'user-switching' ) );
|
197 |
}
|
@@ -217,13 +199,13 @@ class user_switching {
|
|
217 |
if ( switch_to_user( $old_user->ID, self::remember(), false ) ) {
|
218 |
|
219 |
if ( ! empty( $_REQUEST['interim-login'] ) ) {
|
220 |
-
$GLOBALS['interim_login'] = 'success';
|
221 |
login_header( '', '' );
|
222 |
exit;
|
223 |
}
|
224 |
|
225 |
$redirect_to = self::get_redirect( $old_user, $current_user );
|
226 |
-
$args
|
227 |
'user_switched' => 'true',
|
228 |
'switched_back' => 'true',
|
229 |
);
|
@@ -253,7 +235,7 @@ class user_switching {
|
|
253 |
// Switch off:
|
254 |
if ( switch_off_user() ) {
|
255 |
$redirect_to = self::get_redirect( null, $current_user );
|
256 |
-
$args
|
257 |
'switched_off' => 'true',
|
258 |
);
|
259 |
|
@@ -270,7 +252,6 @@ class user_switching {
|
|
270 |
break;
|
271 |
|
272 |
}
|
273 |
-
|
274 |
}
|
275 |
|
276 |
/**
|
@@ -281,45 +262,23 @@ class user_switching {
|
|
281 |
* @return string The URL to redirect to.
|
282 |
*/
|
283 |
protected static function get_redirect( WP_User $new_user = null, WP_User $old_user = null ) {
|
284 |
-
|
285 |
if ( ! empty( $_REQUEST['redirect_to'] ) ) {
|
286 |
-
$redirect_to
|
287 |
$requested_redirect_to = wp_unslash( $_REQUEST['redirect_to'] ); // WPCS: sanitization ok
|
288 |
} else {
|
289 |
-
$redirect_to
|
290 |
$requested_redirect_to = '';
|
291 |
}
|
292 |
|
293 |
if ( ! $new_user ) {
|
294 |
-
/**
|
295 |
-
* Filter the redirect URL when a user switches off.
|
296 |
-
*
|
297 |
-
* This matches the WordPress core filter in wp-login.php.
|
298 |
-
*
|
299 |
-
* @since 1.0.4
|
300 |
-
*
|
301 |
-
* @param string $redirect_to The redirect destination URL.
|
302 |
-
* @param string $requested_redirect_to The requested redirect destination URL passed as a parameter.
|
303 |
-
* @param WP_User $old_user The WP_User object for the user that's switching off.
|
304 |
-
*/
|
305 |
$redirect_to = apply_filters( 'logout_redirect', $redirect_to, $requested_redirect_to, $old_user );
|
306 |
} else {
|
307 |
-
/**
|
308 |
-
* Filter the redirect URL when a user switches to another user or switches back.
|
309 |
-
*
|
310 |
-
* This matches the WordPress core filter in wp-login.php.
|
311 |
-
*
|
312 |
-
* @since 0.8.7
|
313 |
-
*
|
314 |
-
* @param string $redirect_to The redirect destination URL.
|
315 |
-
* @param string $requested_redirect_to The requested redirect destination URL passed as a parameter.
|
316 |
-
* @param WP_User $new_user The WP_User object for the user that's being switched to.
|
317 |
-
*/
|
318 |
$redirect_to = apply_filters( 'login_redirect', $redirect_to, $requested_redirect_to, $new_user );
|
319 |
}
|
320 |
|
321 |
return $redirect_to;
|
322 |
-
|
323 |
}
|
324 |
|
325 |
/**
|
@@ -330,12 +289,11 @@ class user_switching {
|
|
330 |
$old_user = self::get_old_user();
|
331 |
|
332 |
if ( $old_user ) {
|
333 |
-
|
334 |
?>
|
335 |
<div id="user_switching" class="updated notice is-dismissible">
|
336 |
-
<p><span class="dashicons dashicons-admin-users" style="color:#56c234"></span>
|
337 |
<?php
|
338 |
-
$message
|
339 |
$just_switched = isset( $_GET['user_switched'] );
|
340 |
if ( $just_switched ) {
|
341 |
$message = esc_html( sprintf(
|
@@ -348,6 +306,7 @@ class user_switching {
|
|
348 |
$switch_back_url = add_query_arg( array(
|
349 |
'redirect_to' => urlencode( self::current_url() ),
|
350 |
), self::switch_back_url( $old_user ) );
|
|
|
351 |
$message .= sprintf(
|
352 |
' <a href="%s">%s</a>.',
|
353 |
esc_url( $switch_back_url ),
|
@@ -376,9 +335,7 @@ class user_switching {
|
|
376 |
</p>
|
377 |
</div>
|
378 |
<?php
|
379 |
-
|
380 |
} elseif ( isset( $_GET['user_switched'] ) ) {
|
381 |
-
|
382 |
?>
|
383 |
<div id="user_switching" class="updated notice is-dismissible">
|
384 |
<p>
|
@@ -402,14 +359,13 @@ class user_switching {
|
|
402 |
</p>
|
403 |
</div>
|
404 |
<?php
|
405 |
-
|
406 |
}
|
407 |
}
|
408 |
|
409 |
/**
|
410 |
* Validates the old user cookie and returns its user data.
|
411 |
*
|
412 |
-
* @return
|
413 |
*/
|
414 |
public static function get_old_user() {
|
415 |
$cookie = user_switching_get_olduser_cookie();
|
@@ -426,14 +382,13 @@ class user_switching {
|
|
426 |
/**
|
427 |
* Authenticates an old user by verifying the latest entry in the auth cookie.
|
428 |
*
|
429 |
-
* @param
|
430 |
* @return bool Whether verification with the auth cookie passed.
|
431 |
*/
|
432 |
public static function authenticate_old_user( WP_User $user ) {
|
433 |
$cookie = user_switching_get_auth_cookie();
|
434 |
if ( ! empty( $cookie ) ) {
|
435 |
-
|
436 |
-
if ( user_switching::secure_auth_cookie() ) {
|
437 |
$scheme = 'secure_auth';
|
438 |
} else {
|
439 |
$scheme = 'auth';
|
@@ -454,7 +409,6 @@ class user_switching {
|
|
454 |
* @param WP_Admin_Bar $wp_admin_bar The admin bar object.
|
455 |
*/
|
456 |
public function action_admin_bar_menu( WP_Admin_Bar $wp_admin_bar ) {
|
457 |
-
|
458 |
if ( ! function_exists( 'is_admin_bar_showing' ) ) {
|
459 |
return;
|
460 |
}
|
@@ -477,7 +431,6 @@ class user_switching {
|
|
477 |
$old_user = self::get_old_user();
|
478 |
|
479 |
if ( $old_user ) {
|
480 |
-
|
481 |
$wp_admin_bar->add_menu( array(
|
482 |
'parent' => $parent,
|
483 |
'id' => 'switch-back',
|
@@ -491,11 +444,9 @@ class user_switching {
|
|
491 |
'redirect_to' => urlencode( self::current_url() ),
|
492 |
), self::switch_back_url( $old_user ) ),
|
493 |
) );
|
494 |
-
|
495 |
}
|
496 |
|
497 |
if ( current_user_can( 'switch_off' ) ) {
|
498 |
-
|
499 |
$url = self::switch_off_url( wp_get_current_user() );
|
500 |
if ( ! is_admin() ) {
|
501 |
$url = add_query_arg( array(
|
@@ -510,9 +461,7 @@ class user_switching {
|
|
510 |
'title' => esc_html__( 'Switch Off', 'user-switching' ),
|
511 |
'href' => $url,
|
512 |
) );
|
513 |
-
|
514 |
}
|
515 |
-
|
516 |
}
|
517 |
|
518 |
/**
|
@@ -533,7 +482,6 @@ class user_switching {
|
|
533 |
), self::switch_back_url( $old_user ) );
|
534 |
echo '<li id="user_switching_switch_on"><a href="' . esc_url( $url ) . '">' . esc_html( $link ) . '</a></li>';
|
535 |
}
|
536 |
-
|
537 |
}
|
538 |
|
539 |
/**
|
@@ -558,7 +506,6 @@ class user_switching {
|
|
558 |
), self::switch_back_url( $old_user ) );
|
559 |
echo '<p id="user_switching_switch_on"><a href="' . esc_url( $url ) . '">' . esc_html( $link ) . '</a></p>';
|
560 |
}
|
561 |
-
|
562 |
}
|
563 |
|
564 |
/**
|
@@ -590,13 +537,12 @@ class user_switching {
|
|
590 |
}
|
591 |
|
592 |
$message .= '<p class="message" id="user_switching_switch_on">';
|
593 |
-
$message .= '<span class="dashicons dashicons-admin-users" style="color:#56c234"></span> ';
|
594 |
$message .= '<a href="' . esc_url( $url ) . '" onclick="window.location.href=\'' . esc_url( $url ) . '\';return false;">' . esc_html( $link ) . '</a>';
|
595 |
$message .= '</p>';
|
596 |
}
|
597 |
|
598 |
return $message;
|
599 |
-
|
600 |
}
|
601 |
|
602 |
/**
|
@@ -653,7 +599,6 @@ class user_switching {
|
|
653 |
'link_text' => esc_html__( 'Switch To', 'user-switching' ),
|
654 |
'wrapper_id' => 'user_switching_switch_to',
|
655 |
) );
|
656 |
-
|
657 |
}
|
658 |
|
659 |
/**
|
@@ -681,7 +626,6 @@ class user_switching {
|
|
681 |
<li><a href="<?php echo esc_url( $link ); ?>"><?php esc_html_e( 'Switch To', 'user-switching' ); ?></a></li>
|
682 |
</ul>
|
683 |
<?php
|
684 |
-
|
685 |
}
|
686 |
|
687 |
/**
|
@@ -704,10 +648,9 @@ class user_switching {
|
|
704 |
* Returns the switch to or switch back URL for a given user.
|
705 |
*
|
706 |
* @param WP_User $user The user to be switched to.
|
707 |
-
* @return string|
|
708 |
*/
|
709 |
public static function maybe_switch_url( WP_User $user ) {
|
710 |
-
|
711 |
$old_user = self::get_old_user();
|
712 |
|
713 |
if ( $old_user && ( $old_user->ID === $user->ID ) ) {
|
@@ -717,7 +660,6 @@ class user_switching {
|
|
717 |
} else {
|
718 |
return false;
|
719 |
}
|
720 |
-
|
721 |
}
|
722 |
|
723 |
/**
|
@@ -817,7 +759,8 @@ class user_switching {
|
|
817 |
*
|
818 |
* Important: This does not get called for Super Admins. See filter_map_meta_cap() below.
|
819 |
*
|
820 |
-
* @param bool[] $user_caps
|
|
|
821 |
* @param string[] $required_caps Required primitive capabilities for the requested capability.
|
822 |
* @param array $args {
|
823 |
* Arguments that accompany the requested capability check.
|
@@ -831,10 +774,21 @@ class user_switching {
|
|
831 |
*/
|
832 |
public function filter_user_has_cap( array $user_caps, array $required_caps, array $args, WP_User $user ) {
|
833 |
if ( 'switch_to_user' === $args[0] ) {
|
|
|
|
|
|
|
|
|
|
|
834 |
$user_caps['switch_to_user'] = ( user_can( $user->ID, 'edit_user', $args[2] ) && ( $args[2] !== $user->ID ) );
|
835 |
} elseif ( 'switch_off' === $args[0] ) {
|
|
|
|
|
|
|
|
|
|
|
836 |
$user_caps['switch_off'] = user_can( $user->ID, 'edit_users' );
|
837 |
}
|
|
|
838 |
return $user_caps;
|
839 |
}
|
840 |
|
@@ -873,217 +827,317 @@ class user_switching {
|
|
873 |
static $instance;
|
874 |
|
875 |
if ( ! isset( $instance ) ) {
|
876 |
-
$instance = new user_switching;
|
877 |
}
|
878 |
|
879 |
return $instance;
|
880 |
}
|
881 |
|
|
|
|
|
|
|
|
|
|
|
882 |
}
|
883 |
|
884 |
if ( ! function_exists( 'user_switching_set_olduser_cookie' ) ) {
|
885 |
-
/**
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
$
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
$
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
|
|
|
|
|
|
905 |
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
|
912 |
-
|
913 |
-
|
914 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
915 |
}
|
916 |
|
917 |
if ( ! function_exists( 'user_switching_clear_olduser_cookie' ) ) {
|
918 |
-
/**
|
919 |
-
|
920 |
-
|
921 |
-
|
922 |
-
|
923 |
-
function user_switching_clear_olduser_cookie( $clear_all = true ) {
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
930 |
-
|
931 |
-
|
932 |
-
|
933 |
-
|
|
|
934 |
|
935 |
-
|
936 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
937 |
} else {
|
938 |
-
|
939 |
-
|
|
|
|
|
|
|
940 |
|
941 |
-
|
942 |
-
|
943 |
-
|
|
|
|
|
|
|
|
|
944 |
}
|
945 |
}
|
946 |
}
|
947 |
-
}
|
948 |
|
949 |
if ( ! function_exists( 'user_switching_get_olduser_cookie' ) ) {
|
950 |
-
/**
|
951 |
-
|
952 |
-
|
953 |
-
|
954 |
-
|
955 |
-
function user_switching_get_olduser_cookie() {
|
956 |
-
|
957 |
-
|
958 |
-
|
959 |
-
|
|
|
960 |
}
|
961 |
}
|
962 |
-
}
|
963 |
|
964 |
if ( ! function_exists( 'user_switching_get_auth_cookie' ) ) {
|
965 |
-
/**
|
966 |
-
|
967 |
-
|
968 |
-
|
969 |
-
|
970 |
-
function user_switching_get_auth_cookie() {
|
971 |
-
|
972 |
-
|
973 |
-
|
974 |
-
|
975 |
-
|
976 |
|
977 |
-
|
978 |
-
|
979 |
-
|
980 |
-
|
981 |
-
|
|
|
|
|
982 |
}
|
983 |
-
return $cookie;
|
984 |
-
}
|
985 |
}
|
986 |
|
987 |
if ( ! function_exists( 'switch_to_user' ) ) {
|
988 |
-
/**
|
989 |
-
|
990 |
-
|
991 |
-
|
992 |
-
|
993 |
-
|
994 |
-
|
995 |
-
|
996 |
-
function switch_to_user( $user_id, $remember = false, $set_old_user = true ) {
|
997 |
-
|
998 |
-
|
999 |
-
if ( ! $user ) {
|
1000 |
-
return false;
|
1001 |
-
}
|
1002 |
|
1003 |
-
|
|
|
|
|
1004 |
|
1005 |
-
|
1006 |
-
|
1007 |
-
|
1008 |
-
|
1009 |
-
}
|
1010 |
|
1011 |
-
|
1012 |
-
|
1013 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1014 |
|
1015 |
-
if ( $set_old_user ) {
|
1016 |
/**
|
1017 |
-
*
|
1018 |
-
*
|
1019 |
-
* @since 0.6.0
|
1020 |
-
*
|
1021 |
-
* @param int $user_id The ID of the user being switched to.
|
1022 |
-
* @param int $old_user_id The ID of the user being switched from.
|
1023 |
-
*/
|
1024 |
-
do_action( 'switch_to_user', $user_id, $old_user_id );
|
1025 |
-
} else {
|
1026 |
-
/**
|
1027 |
-
* Fires when a user switches back to their originating account.
|
1028 |
-
*
|
1029 |
-
* @since 0.6.0
|
1030 |
*
|
1031 |
-
* @param
|
1032 |
-
* @param int
|
1033 |
-
*
|
1034 |
*/
|
1035 |
-
|
1036 |
-
|
|
|
|
|
|
|
1037 |
|
1038 |
-
|
1039 |
-
}
|
1040 |
-
}
|
1041 |
|
1042 |
-
|
1043 |
-
|
1044 |
-
|
1045 |
-
* straight back in using the 'Switch back to {user}' system.
|
1046 |
-
*
|
1047 |
-
* @return bool True on success, false on failure.
|
1048 |
-
*/
|
1049 |
-
function switch_off_user() {
|
1050 |
-
$old_user_id = get_current_user_id();
|
1051 |
|
1052 |
-
|
1053 |
-
|
1054 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1055 |
|
1056 |
-
|
1057 |
-
|
1058 |
-
|
1059 |
|
|
|
1060 |
/**
|
1061 |
-
*
|
|
|
1062 |
*
|
1063 |
-
* @
|
1064 |
-
*
|
1065 |
-
* @param int $old_user_id The ID of the user switching off.
|
1066 |
*/
|
1067 |
-
|
|
|
1068 |
|
1069 |
-
|
1070 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1071 |
}
|
1072 |
|
1073 |
if ( ! function_exists( 'current_user_switched' ) ) {
|
1074 |
-
/**
|
1075 |
-
|
1076 |
-
|
1077 |
-
|
1078 |
-
|
1079 |
-
|
1080 |
-
function current_user_switched() {
|
1081 |
-
|
1082 |
-
|
1083 |
-
|
1084 |
|
1085 |
-
|
1086 |
-
}
|
1087 |
}
|
1088 |
|
1089 |
$GLOBALS['user_switching'] = user_switching::get_instance();
|
|
8 |
* @copyright 2009-2018 John Blackbourn
|
9 |
* @license GPL v2 or later
|
10 |
*
|
11 |
+
* Plugin Name: User Switching
|
12 |
+
* Description: Instant switching between user accounts in WordPress
|
13 |
+
* Version: 1.4.0
|
14 |
+
* Plugin URI: https://johnblackbourn.com/wordpress-plugin-user-switching/
|
15 |
+
* Author: John Blackbourn & contributors
|
16 |
+
* Author URI: https://github.com/johnbillion/user-switching/graphs/contributors
|
17 |
+
* Text Domain: user-switching
|
18 |
+
* Domain Path: /languages/
|
19 |
+
* Network: true
|
20 |
+
* Requires PHP: 5.3
|
21 |
*
|
22 |
* This program is free software; you can redistribute it and/or modify
|
23 |
* it under the terms of the GNU General Public License as published by
|
36 |
class user_switching {
|
37 |
|
38 |
/**
|
39 |
+
* The name used to identify the application during a WordPress redirect.
|
40 |
*
|
41 |
* @var string
|
42 |
*/
|
43 |
public static $application = 'WordPress/User Switching';
|
44 |
|
45 |
/**
|
46 |
+
* Sets up all the filters and actions.
|
47 |
*/
|
48 |
+
public function init_hooks() {
|
|
|
49 |
// Required functionality:
|
50 |
add_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ), 10, 4 );
|
51 |
add_filter( 'map_meta_cap', array( $this, 'filter_map_meta_cap' ), 10, 4 );
|
67 |
add_action( 'bp_member_header_actions', array( $this, 'action_bp_button' ), 11 );
|
68 |
add_action( 'bp_directory_members_actions', array( $this, 'action_bp_button' ), 11 );
|
69 |
add_action( 'bbp_template_after_user_details', array( $this, 'action_bbpress_button' ) );
|
|
|
70 |
}
|
71 |
|
72 |
/**
|
73 |
+
* Defines the names of the cookies used by User Switching.
|
74 |
*/
|
75 |
public function action_plugins_loaded() {
|
|
|
76 |
// User Switching's auth_cookie
|
77 |
if ( ! defined( 'USER_SWITCHING_COOKIE' ) ) {
|
78 |
define( 'USER_SWITCHING_COOKIE', 'wordpress_user_sw_' . COOKIEHASH );
|
87 |
if ( ! defined( 'USER_SWITCHING_OLDUSER_COOKIE' ) ) {
|
88 |
define( 'USER_SWITCHING_OLDUSER_COOKIE', 'wordpress_user_sw_olduser_' . COOKIEHASH );
|
89 |
}
|
|
|
90 |
}
|
91 |
|
92 |
/**
|
93 |
+
* Outputs the 'Switch To' link on the user editing screen if the current user has permission to switch to them.
|
94 |
*
|
95 |
* @param WP_User $user User object for this screen.
|
96 |
*/
|
117 |
* @return bool Whether the current user is being 'remembered' or not.
|
118 |
*/
|
119 |
public static function remember() {
|
120 |
+
/** This filter is documented in wp-includes/pluggable.php */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
$cookie_life = apply_filters( 'auth_cookie_expiration', 172800, get_current_user_id(), false );
|
122 |
$current = wp_parse_auth_cookie( '', 'logged_in' );
|
123 |
|
124 |
// Here we calculate the expiration length of the current auth cookie and compare it to the default expiration.
|
125 |
// If it's greater than this, then we know the user checked 'Remember Me' when they logged in.
|
126 |
return ( ( $current['expiration'] - time() ) > $cookie_life );
|
|
|
127 |
}
|
128 |
|
129 |
/**
|
130 |
* Loads localisation files and routes actions depending on the 'action' query var.
|
131 |
*/
|
132 |
public function action_init() {
|
|
|
133 |
load_plugin_textdomain( 'user-switching', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
|
134 |
|
135 |
if ( ! isset( $_REQUEST['action'] ) ) {
|
159 |
// Switch user:
|
160 |
$user = switch_to_user( $user_id, self::remember() );
|
161 |
if ( $user ) {
|
|
|
162 |
$redirect_to = self::get_redirect( $user, $current_user );
|
163 |
|
164 |
// Redirect to the dashboard or the home URL depending on capabilities:
|
174 |
wp_safe_redirect( add_query_arg( $args, admin_url() ), 302, self::$application );
|
175 |
}
|
176 |
exit;
|
|
|
177 |
} else {
|
178 |
wp_die( esc_html__( 'Could not switch users.', 'user-switching' ) );
|
179 |
}
|
199 |
if ( switch_to_user( $old_user->ID, self::remember(), false ) ) {
|
200 |
|
201 |
if ( ! empty( $_REQUEST['interim-login'] ) ) {
|
202 |
+
$GLOBALS['interim_login'] = 'success'; // @codingStandardsIgnoreLine
|
203 |
login_header( '', '' );
|
204 |
exit;
|
205 |
}
|
206 |
|
207 |
$redirect_to = self::get_redirect( $old_user, $current_user );
|
208 |
+
$args = array(
|
209 |
'user_switched' => 'true',
|
210 |
'switched_back' => 'true',
|
211 |
);
|
235 |
// Switch off:
|
236 |
if ( switch_off_user() ) {
|
237 |
$redirect_to = self::get_redirect( null, $current_user );
|
238 |
+
$args = array(
|
239 |
'switched_off' => 'true',
|
240 |
);
|
241 |
|
252 |
break;
|
253 |
|
254 |
}
|
|
|
255 |
}
|
256 |
|
257 |
/**
|
262 |
* @return string The URL to redirect to.
|
263 |
*/
|
264 |
protected static function get_redirect( WP_User $new_user = null, WP_User $old_user = null ) {
|
|
|
265 |
if ( ! empty( $_REQUEST['redirect_to'] ) ) {
|
266 |
+
$redirect_to = self::remove_query_args( wp_unslash( $_REQUEST['redirect_to'] ) ); // WPCS: sanitization ok
|
267 |
$requested_redirect_to = wp_unslash( $_REQUEST['redirect_to'] ); // WPCS: sanitization ok
|
268 |
} else {
|
269 |
+
$redirect_to = '';
|
270 |
$requested_redirect_to = '';
|
271 |
}
|
272 |
|
273 |
if ( ! $new_user ) {
|
274 |
+
/** This filter is documented in wp-login.php */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
275 |
$redirect_to = apply_filters( 'logout_redirect', $redirect_to, $requested_redirect_to, $old_user );
|
276 |
} else {
|
277 |
+
/** This filter is documented in wp-login.php */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
$redirect_to = apply_filters( 'login_redirect', $redirect_to, $requested_redirect_to, $new_user );
|
279 |
}
|
280 |
|
281 |
return $redirect_to;
|
|
|
282 |
}
|
283 |
|
284 |
/**
|
289 |
$old_user = self::get_old_user();
|
290 |
|
291 |
if ( $old_user ) {
|
|
|
292 |
?>
|
293 |
<div id="user_switching" class="updated notice is-dismissible">
|
294 |
+
<p><span class="dashicons dashicons-admin-users" style="color:#56c234" aria-hidden="true"></span>
|
295 |
<?php
|
296 |
+
$message = '';
|
297 |
$just_switched = isset( $_GET['user_switched'] );
|
298 |
if ( $just_switched ) {
|
299 |
$message = esc_html( sprintf(
|
306 |
$switch_back_url = add_query_arg( array(
|
307 |
'redirect_to' => urlencode( self::current_url() ),
|
308 |
), self::switch_back_url( $old_user ) );
|
309 |
+
|
310 |
$message .= sprintf(
|
311 |
' <a href="%s">%s</a>.',
|
312 |
esc_url( $switch_back_url ),
|
335 |
</p>
|
336 |
</div>
|
337 |
<?php
|
|
|
338 |
} elseif ( isset( $_GET['user_switched'] ) ) {
|
|
|
339 |
?>
|
340 |
<div id="user_switching" class="updated notice is-dismissible">
|
341 |
<p>
|
359 |
</p>
|
360 |
</div>
|
361 |
<?php
|
|
|
362 |
}
|
363 |
}
|
364 |
|
365 |
/**
|
366 |
* Validates the old user cookie and returns its user data.
|
367 |
*
|
368 |
+
* @return false|WP_User False if there's no old user cookie or it's invalid, WP_User object if it's present and valid.
|
369 |
*/
|
370 |
public static function get_old_user() {
|
371 |
$cookie = user_switching_get_olduser_cookie();
|
382 |
/**
|
383 |
* Authenticates an old user by verifying the latest entry in the auth cookie.
|
384 |
*
|
385 |
+
* @param WP_User $user A WP_User object (usually from the logged_in cookie).
|
386 |
* @return bool Whether verification with the auth cookie passed.
|
387 |
*/
|
388 |
public static function authenticate_old_user( WP_User $user ) {
|
389 |
$cookie = user_switching_get_auth_cookie();
|
390 |
if ( ! empty( $cookie ) ) {
|
391 |
+
if ( self::secure_auth_cookie() ) {
|
|
|
392 |
$scheme = 'secure_auth';
|
393 |
} else {
|
394 |
$scheme = 'auth';
|
409 |
* @param WP_Admin_Bar $wp_admin_bar The admin bar object.
|
410 |
*/
|
411 |
public function action_admin_bar_menu( WP_Admin_Bar $wp_admin_bar ) {
|
|
|
412 |
if ( ! function_exists( 'is_admin_bar_showing' ) ) {
|
413 |
return;
|
414 |
}
|
431 |
$old_user = self::get_old_user();
|
432 |
|
433 |
if ( $old_user ) {
|
|
|
434 |
$wp_admin_bar->add_menu( array(
|
435 |
'parent' => $parent,
|
436 |
'id' => 'switch-back',
|
444 |
'redirect_to' => urlencode( self::current_url() ),
|
445 |
), self::switch_back_url( $old_user ) ),
|
446 |
) );
|
|
|
447 |
}
|
448 |
|
449 |
if ( current_user_can( 'switch_off' ) ) {
|
|
|
450 |
$url = self::switch_off_url( wp_get_current_user() );
|
451 |
if ( ! is_admin() ) {
|
452 |
$url = add_query_arg( array(
|
461 |
'title' => esc_html__( 'Switch Off', 'user-switching' ),
|
462 |
'href' => $url,
|
463 |
) );
|
|
|
464 |
}
|
|
|
465 |
}
|
466 |
|
467 |
/**
|
482 |
), self::switch_back_url( $old_user ) );
|
483 |
echo '<li id="user_switching_switch_on"><a href="' . esc_url( $url ) . '">' . esc_html( $link ) . '</a></li>';
|
484 |
}
|
|
|
485 |
}
|
486 |
|
487 |
/**
|
506 |
), self::switch_back_url( $old_user ) );
|
507 |
echo '<p id="user_switching_switch_on"><a href="' . esc_url( $url ) . '">' . esc_html( $link ) . '</a></p>';
|
508 |
}
|
|
|
509 |
}
|
510 |
|
511 |
/**
|
537 |
}
|
538 |
|
539 |
$message .= '<p class="message" id="user_switching_switch_on">';
|
540 |
+
$message .= '<span class="dashicons dashicons-admin-users" style="color:#56c234" aria-hidden="true"></span> ';
|
541 |
$message .= '<a href="' . esc_url( $url ) . '" onclick="window.location.href=\'' . esc_url( $url ) . '\';return false;">' . esc_html( $link ) . '</a>';
|
542 |
$message .= '</p>';
|
543 |
}
|
544 |
|
545 |
return $message;
|
|
|
546 |
}
|
547 |
|
548 |
/**
|
599 |
'link_text' => esc_html__( 'Switch To', 'user-switching' ),
|
600 |
'wrapper_id' => 'user_switching_switch_to',
|
601 |
) );
|
|
|
602 |
}
|
603 |
|
604 |
/**
|
626 |
<li><a href="<?php echo esc_url( $link ); ?>"><?php esc_html_e( 'Switch To', 'user-switching' ); ?></a></li>
|
627 |
</ul>
|
628 |
<?php
|
|
|
629 |
}
|
630 |
|
631 |
/**
|
648 |
* Returns the switch to or switch back URL for a given user.
|
649 |
*
|
650 |
* @param WP_User $user The user to be switched to.
|
651 |
+
* @return string|false The required URL, or false if there's no old user or the user doesn't have the required capability.
|
652 |
*/
|
653 |
public static function maybe_switch_url( WP_User $user ) {
|
|
|
654 |
$old_user = self::get_old_user();
|
655 |
|
656 |
if ( $old_user && ( $old_user->ID === $user->ID ) ) {
|
660 |
} else {
|
661 |
return false;
|
662 |
}
|
|
|
663 |
}
|
664 |
|
665 |
/**
|
759 |
*
|
760 |
* Important: This does not get called for Super Admins. See filter_map_meta_cap() below.
|
761 |
*
|
762 |
+
* @param bool[] $user_caps Array of key/value pairs where keys represent a capability name and boolean values
|
763 |
+
* represent whether the user has that capability.
|
764 |
* @param string[] $required_caps Required primitive capabilities for the requested capability.
|
765 |
* @param array $args {
|
766 |
* Arguments that accompany the requested capability check.
|
774 |
*/
|
775 |
public function filter_user_has_cap( array $user_caps, array $required_caps, array $args, WP_User $user ) {
|
776 |
if ( 'switch_to_user' === $args[0] ) {
|
777 |
+
if ( array_key_exists( 'switch_users', $user_caps ) ) {
|
778 |
+
$user_caps['switch_to_user'] = $user_caps['switch_users'];
|
779 |
+
return $user_caps;
|
780 |
+
}
|
781 |
+
|
782 |
$user_caps['switch_to_user'] = ( user_can( $user->ID, 'edit_user', $args[2] ) && ( $args[2] !== $user->ID ) );
|
783 |
} elseif ( 'switch_off' === $args[0] ) {
|
784 |
+
if ( array_key_exists( 'switch_users', $user_caps ) ) {
|
785 |
+
$user_caps['switch_off'] = $user_caps['switch_users'];
|
786 |
+
return $user_caps;
|
787 |
+
}
|
788 |
+
|
789 |
$user_caps['switch_off'] = user_can( $user->ID, 'edit_users' );
|
790 |
}
|
791 |
+
|
792 |
return $user_caps;
|
793 |
}
|
794 |
|
827 |
static $instance;
|
828 |
|
829 |
if ( ! isset( $instance ) ) {
|
830 |
+
$instance = new user_switching();
|
831 |
}
|
832 |
|
833 |
return $instance;
|
834 |
}
|
835 |
|
836 |
+
/**
|
837 |
+
* Private class constructor. Use `get_instance()` to get the instance.
|
838 |
+
*/
|
839 |
+
final private function __construct() {}
|
840 |
+
|
841 |
}
|
842 |
|
843 |
if ( ! function_exists( 'user_switching_set_olduser_cookie' ) ) {
|
844 |
+
/**
|
845 |
+
* Sets authorisation cookies containing the originating user information.
|
846 |
+
*
|
847 |
+
* @since 1.4.0 The `$token` parameter was added.
|
848 |
+
*
|
849 |
+
* @param int $old_user_id The ID of the originating user, usually the current logged in user.
|
850 |
+
* @param bool $pop Optional. Pop the latest user off the auth cookie, instead of appending the new one. Default false.
|
851 |
+
* @param string $token Optional. The old user's session token to store for later reuse. Default empty string.
|
852 |
+
*/
|
853 |
+
function user_switching_set_olduser_cookie( $old_user_id, $pop = false, $token = '' ) {
|
854 |
+
$secure_auth_cookie = user_switching::secure_auth_cookie();
|
855 |
+
$secure_olduser_cookie = user_switching::secure_olduser_cookie();
|
856 |
+
$expiration = time() + 172800; // 48 hours
|
857 |
+
$auth_cookie = user_switching_get_auth_cookie();
|
858 |
+
$olduser_cookie = wp_generate_auth_cookie( $old_user_id, $expiration, 'logged_in', $token );
|
859 |
+
|
860 |
+
if ( $secure_auth_cookie ) {
|
861 |
+
$auth_cookie_name = USER_SWITCHING_SECURE_COOKIE;
|
862 |
+
$scheme = 'secure_auth';
|
863 |
+
} else {
|
864 |
+
$auth_cookie_name = USER_SWITCHING_COOKIE;
|
865 |
+
$scheme = 'auth';
|
866 |
+
}
|
867 |
|
868 |
+
if ( $pop ) {
|
869 |
+
array_pop( $auth_cookie );
|
870 |
+
} else {
|
871 |
+
array_push( $auth_cookie, wp_generate_auth_cookie( $old_user_id, $expiration, $scheme, $token ) );
|
872 |
+
}
|
873 |
|
874 |
+
$auth_cookie = json_encode( $auth_cookie );
|
875 |
+
|
876 |
+
/**
|
877 |
+
* Fires immediately before the User Switching authentication cookie is set.
|
878 |
+
*
|
879 |
+
* @since 1.4.0
|
880 |
+
*
|
881 |
+
* @param string $auth_cookie JSON-encoded array of authentication cookie values.
|
882 |
+
* @param int $expiration The time when the authentication cookie expires as a UNIX timestamp.
|
883 |
+
* Default is 48 hours from now.
|
884 |
+
* @param int $old_user_id User ID.
|
885 |
+
* @param string $scheme Authentication scheme. Values include 'auth' or 'secure_auth'.
|
886 |
+
* @param string $token User's session token to use for the latest cookie.
|
887 |
+
*/
|
888 |
+
do_action( 'set_user_switching_cookie', $auth_cookie, $expiration, $old_user_id, $scheme, $token );
|
889 |
+
|
890 |
+
/**
|
891 |
+
* Fires immediately before the User Switching old user cookie is set.
|
892 |
+
*
|
893 |
+
* @since 1.4.0
|
894 |
+
*
|
895 |
+
* @param string $olduser_cookie The old user cookie value.
|
896 |
+
* @param int $expiration The time when the logged-in authentication cookie expires as a UNIX timestamp.
|
897 |
+
* Default is 48 hours from now.
|
898 |
+
* @param int $old_user_id User ID.
|
899 |
+
* @param string $scheme Authentication scheme. Default 'logged_in'.
|
900 |
+
* @param string $token User's session token to use for this cookie.
|
901 |
+
*/
|
902 |
+
do_action( 'set_olduser_cookie', $olduser_cookie, $expiration, $old_user_id, 'logged_in', $token );
|
903 |
+
|
904 |
+
/** This filter is documented in wp-includes/pluggable.php */
|
905 |
+
if ( ! apply_filters( 'send_auth_cookies', true ) ) {
|
906 |
+
return;
|
907 |
+
}
|
908 |
+
|
909 |
+
setcookie( $auth_cookie_name, $auth_cookie, $expiration, SITECOOKIEPATH, COOKIE_DOMAIN, $secure_auth_cookie, true );
|
910 |
+
setcookie( USER_SWITCHING_OLDUSER_COOKIE, $olduser_cookie, $expiration, COOKIEPATH, COOKIE_DOMAIN, $secure_olduser_cookie, true );
|
911 |
+
}
|
912 |
}
|
913 |
|
914 |
if ( ! function_exists( 'user_switching_clear_olduser_cookie' ) ) {
|
915 |
+
/**
|
916 |
+
* Clears the cookies containing the originating user, or pops the latest item off the end if there's more than one.
|
917 |
+
*
|
918 |
+
* @param bool $clear_all Optional. Whether to clear the cookies (as opposed to just popping the last user off the end). Default true.
|
919 |
+
*/
|
920 |
+
function user_switching_clear_olduser_cookie( $clear_all = true ) {
|
921 |
+
$auth_cookie = user_switching_get_auth_cookie();
|
922 |
+
if ( ! empty( $auth_cookie ) ) {
|
923 |
+
array_pop( $auth_cookie );
|
924 |
+
}
|
925 |
+
if ( $clear_all || empty( $auth_cookie ) ) {
|
926 |
+
/**
|
927 |
+
* Fires just before the user switching cookies are cleared.
|
928 |
+
*
|
929 |
+
* @since 1.4.0
|
930 |
+
*/
|
931 |
+
do_action( 'clear_olduser_cookie' );
|
932 |
|
933 |
+
/** This filter is documented in wp-includes/pluggable.php */
|
934 |
+
if ( ! apply_filters( 'send_auth_cookies', true ) ) {
|
935 |
+
return;
|
936 |
+
}
|
937 |
+
|
938 |
+
$expire = time() - 31536000;
|
939 |
+
setcookie( USER_SWITCHING_COOKIE, ' ', $expire, SITECOOKIEPATH, COOKIE_DOMAIN );
|
940 |
+
setcookie( USER_SWITCHING_SECURE_COOKIE, ' ', $expire, SITECOOKIEPATH, COOKIE_DOMAIN );
|
941 |
+
setcookie( USER_SWITCHING_OLDUSER_COOKIE, ' ', $expire, COOKIEPATH, COOKIE_DOMAIN );
|
942 |
} else {
|
943 |
+
if ( user_switching::secure_auth_cookie() ) {
|
944 |
+
$scheme = 'secure_auth';
|
945 |
+
} else {
|
946 |
+
$scheme = 'auth';
|
947 |
+
}
|
948 |
|
949 |
+
$old_cookie = end( $auth_cookie );
|
950 |
+
|
951 |
+
$old_user_id = wp_validate_auth_cookie( $old_cookie, $scheme );
|
952 |
+
if ( $old_user_id ) {
|
953 |
+
$parts = wp_parse_auth_cookie( $old_cookie, $scheme );
|
954 |
+
user_switching_set_olduser_cookie( $old_user_id, true, $parts['token'] );
|
955 |
+
}
|
956 |
}
|
957 |
}
|
958 |
}
|
|
|
959 |
|
960 |
if ( ! function_exists( 'user_switching_get_olduser_cookie' ) ) {
|
961 |
+
/**
|
962 |
+
* Gets the value of the cookie containing the originating user.
|
963 |
+
*
|
964 |
+
* @return string|false The old user cookie, or boolean false if there isn't one.
|
965 |
+
*/
|
966 |
+
function user_switching_get_olduser_cookie() {
|
967 |
+
if ( isset( $_COOKIE[ USER_SWITCHING_OLDUSER_COOKIE ] ) ) {
|
968 |
+
return wp_unslash( $_COOKIE[ USER_SWITCHING_OLDUSER_COOKIE ] ); // WPCS: sanitization ok
|
969 |
+
} else {
|
970 |
+
return false;
|
971 |
+
}
|
972 |
}
|
973 |
}
|
|
|
974 |
|
975 |
if ( ! function_exists( 'user_switching_get_auth_cookie' ) ) {
|
976 |
+
/**
|
977 |
+
* Gets the value of the auth cookie containing the list of originating users.
|
978 |
+
*
|
979 |
+
* @return string[] Array of originating user authentication cookie values. Empty array if there are none.
|
980 |
+
*/
|
981 |
+
function user_switching_get_auth_cookie() {
|
982 |
+
if ( user_switching::secure_auth_cookie() ) {
|
983 |
+
$auth_cookie_name = USER_SWITCHING_SECURE_COOKIE;
|
984 |
+
} else {
|
985 |
+
$auth_cookie_name = USER_SWITCHING_COOKIE;
|
986 |
+
}
|
987 |
|
988 |
+
if ( isset( $_COOKIE[ $auth_cookie_name ] ) && is_string( $_COOKIE[ $auth_cookie_name ] ) ) {
|
989 |
+
$cookie = json_decode( wp_unslash( $_COOKIE[ $auth_cookie_name ] ) ); // WPCS: sanitization ok
|
990 |
+
}
|
991 |
+
if ( ! isset( $cookie ) || ! is_array( $cookie ) ) {
|
992 |
+
$cookie = array();
|
993 |
+
}
|
994 |
+
return $cookie;
|
995 |
}
|
|
|
|
|
996 |
}
|
997 |
|
998 |
if ( ! function_exists( 'switch_to_user' ) ) {
|
999 |
+
/**
|
1000 |
+
* Switches the current logged in user to the specified user.
|
1001 |
+
*
|
1002 |
+
* @param int $user_id The ID of the user to switch to.
|
1003 |
+
* @param bool $remember Optional. Whether to 'remember' the user in the form of a persistent browser cookie. Default false.
|
1004 |
+
* @param bool $set_old_user Optional. Whether to set the old user cookie. Default true.
|
1005 |
+
* @return false|WP_User WP_User object on success, false on failure.
|
1006 |
+
*/
|
1007 |
+
function switch_to_user( $user_id, $remember = false, $set_old_user = true ) {
|
1008 |
+
$user = get_userdata( $user_id );
|
|
|
|
|
|
|
|
|
1009 |
|
1010 |
+
if ( ! $user ) {
|
1011 |
+
return false;
|
1012 |
+
}
|
1013 |
|
1014 |
+
$old_user_id = ( is_user_logged_in() ) ? get_current_user_id() : false;
|
1015 |
+
$old_token = function_exists( 'wp_get_session_token' ) ? wp_get_session_token() : '';
|
1016 |
+
$auth_cookie = user_switching_get_auth_cookie();
|
1017 |
+
$cookie_parts = wp_parse_auth_cookie( end( $auth_cookie ) );
|
|
|
1018 |
|
1019 |
+
if ( $set_old_user && $old_user_id ) {
|
1020 |
+
// Switching to another user
|
1021 |
+
$new_token = '';
|
1022 |
+
user_switching_set_olduser_cookie( $old_user_id, false, $old_token );
|
1023 |
+
} else {
|
1024 |
+
// Switching back, either after being switched off or after being switched to another user
|
1025 |
+
$new_token = isset( $cookie_parts['token'] ) ? $cookie_parts['token'] : '';
|
1026 |
+
user_switching_clear_olduser_cookie( false );
|
1027 |
+
}
|
1028 |
|
|
|
1029 |
/**
|
1030 |
+
* Attaches the original user ID and session token to the new session when a user switches to another user.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1031 |
*
|
1032 |
+
* @param array $session Array of extra data.
|
1033 |
+
* @param int $user_id User ID.
|
1034 |
+
* @return array Array of extra data.
|
1035 |
*/
|
1036 |
+
$session_filter = function( array $session, $user_id ) use ( $old_user_id, $old_token ) {
|
1037 |
+
$session['switched_from_id'] = $old_user_id;
|
1038 |
+
$session['switched_from_session'] = $old_token;
|
1039 |
+
return $session;
|
1040 |
+
};
|
1041 |
|
1042 |
+
add_filter( 'attach_session_information', $session_filter, 99, 2 );
|
|
|
|
|
1043 |
|
1044 |
+
wp_clear_auth_cookie();
|
1045 |
+
wp_set_auth_cookie( $user_id, $remember, '', $new_token );
|
1046 |
+
wp_set_current_user( $user_id );
|
|
|
|
|
|
|
|
|
|
|
|
|
1047 |
|
1048 |
+
remove_filter( 'attach_session_information', $session_filter, 99 );
|
1049 |
+
|
1050 |
+
if ( $set_old_user ) {
|
1051 |
+
/**
|
1052 |
+
* Fires when a user switches to another user account.
|
1053 |
+
*
|
1054 |
+
* @since 0.6.0
|
1055 |
+
* @since 1.4.0 The `$new_token` and `$old_token` parameters were added.
|
1056 |
+
*
|
1057 |
+
* @param int $user_id The ID of the user being switched to.
|
1058 |
+
* @param int $old_user_id The ID of the user being switched from.
|
1059 |
+
* @param string $new_token The token of the session of the user being switched to. Can be an empty string
|
1060 |
+
* or a token for a session that may or may not still be valid.
|
1061 |
+
* @param string $old_token The token of the session of the user being switched from.
|
1062 |
+
*/
|
1063 |
+
do_action( 'switch_to_user', $user_id, $old_user_id, $new_token, $old_token );
|
1064 |
+
} else {
|
1065 |
+
/**
|
1066 |
+
* Fires when a user switches back to their originating account.
|
1067 |
+
*
|
1068 |
+
* @since 0.6.0
|
1069 |
+
* @since 1.4.0 The `$new_token` and `$old_token` parameters were added.
|
1070 |
+
*
|
1071 |
+
* @param int $user_id The ID of the user being switched back to.
|
1072 |
+
* @param int|false $old_user_id The ID of the user being switched from, or false if the user is switching back
|
1073 |
+
* after having been switched off.
|
1074 |
+
* @param string $new_token The token of the session of the user being switched to. Can be an empty string
|
1075 |
+
* or a token for a session that may or may not still be valid.
|
1076 |
+
* @param string $old_token The token of the session of the user being switched from.
|
1077 |
+
*/
|
1078 |
+
do_action( 'switch_back_user', $user_id, $old_user_id, $new_token, $old_token );
|
1079 |
+
}
|
1080 |
+
|
1081 |
+
if ( $old_token && $old_user_id && ! $set_old_user ) {
|
1082 |
+
// When switching back, destroy the session for the old user
|
1083 |
+
$manager = WP_Session_Tokens::get_instance( $old_user_id );
|
1084 |
+
$manager->destroy( $old_token );
|
1085 |
+
}
|
1086 |
|
1087 |
+
return $user;
|
1088 |
+
}
|
1089 |
+
}
|
1090 |
|
1091 |
+
if ( ! function_exists( 'switch_off_user' ) ) {
|
1092 |
/**
|
1093 |
+
* Switches off the current logged in user. This logs the current user out while retaining a cookie allowing them to log
|
1094 |
+
* straight back in using the 'Switch back to {user}' system.
|
1095 |
*
|
1096 |
+
* @return bool True on success, false on failure.
|
|
|
|
|
1097 |
*/
|
1098 |
+
function switch_off_user() {
|
1099 |
+
$old_user_id = get_current_user_id();
|
1100 |
|
1101 |
+
if ( ! $old_user_id ) {
|
1102 |
+
return false;
|
1103 |
+
}
|
1104 |
+
|
1105 |
+
$old_token = function_exists( 'wp_get_session_token' ) ? wp_get_session_token() : '';
|
1106 |
+
|
1107 |
+
user_switching_set_olduser_cookie( $old_user_id, false, $old_token );
|
1108 |
+
wp_clear_auth_cookie();
|
1109 |
+
wp_set_current_user( 0 );
|
1110 |
+
|
1111 |
+
/**
|
1112 |
+
* Fires when a user switches off.
|
1113 |
+
*
|
1114 |
+
* @since 0.6.0
|
1115 |
+
* @since 1.4.0 The `$old_token` parameter was added.
|
1116 |
+
*
|
1117 |
+
* @param int $old_user_id The ID of the user switching off.
|
1118 |
+
* @param string $old_token The token of the session of the user switching off.
|
1119 |
+
*/
|
1120 |
+
do_action( 'switch_off_user', $old_user_id, $old_token );
|
1121 |
+
|
1122 |
+
return true;
|
1123 |
+
}
|
1124 |
}
|
1125 |
|
1126 |
if ( ! function_exists( 'current_user_switched' ) ) {
|
1127 |
+
/**
|
1128 |
+
* Returns whether or not the current user switched into their account.
|
1129 |
+
*
|
1130 |
+
* @return false|WP_User False if the user isn't logged in or they didn't switch in; old user object (which evaluates to
|
1131 |
+
* true) if the user switched into the current user account.
|
1132 |
+
*/
|
1133 |
+
function current_user_switched() {
|
1134 |
+
if ( ! is_user_logged_in() ) {
|
1135 |
+
return false;
|
1136 |
+
}
|
1137 |
|
1138 |
+
return user_switching::get_old_user();
|
1139 |
+
}
|
1140 |
}
|
1141 |
|
1142 |
$GLOBALS['user_switching'] = user_switching::get_instance();
|
1143 |
+
$GLOBALS['user_switching']->init_hooks();
|