Logout users upon login, based on caps/role?
-
20-05-2021 - |
Pergunta
To reduce spam registrations, users are assigned the pending
role until they're vetted (at which point they're assigned the subscriber
role). The pending
role has no capabilities. When pending
users log in, I want to log them out immediately and direct them to a page with an explanation. First, I tried the following:
function logout_pending_users() {
$current_user = wp_get_current_user() ;
if ( ! $current_user->has_cap( 'read' ) ) {
$url = 'https://example.com/pending/' ;
wp_redirect( $url ) ;
wp_logout() ;
exit ;
}
} add_action('wp_login', 'logout_pending_users') ;
Result: both pending
and subscriber
users are logged out. I tried inverting the order of wp_redirect()
and wp_logout()
:
$url = 'https://example.com/pending/' ;
wp_logout() ;
wp_redirect( $url ) ;
exit ;
Same result. Then I tried checking roles instead of caps (I know, you shouldn't...):
function logout_pending_users() {
$current_user = wp_get_current_user() ;
$role = $current_user->roles[0] ;
if ( $role === 'pending' ) {
$url = 'https://example.com/pending/' ;
wp_redirect( $url ) ;
wp_logout() ;
exit ;
}
} add_action('wp_login', 'logout_pending_users') ;
Again, same result. Next, I tried something based on an example on the WP Developer site:
function logout_pending_users() {
$current_user = wp_get_current_user() ;
if ( ! $current_user->has_cap( 'read' ) ) {
wp_logout() ;
}
} add_action('wp_login', 'logout_pending_users');
function redirect_pending_users() {
$current_user = wp_get_current_user() ;
if ( ! $current_user->has_cap( 'read' ) ) {
$url = 'https://example.com/pending/' ;
wp_redirect( $url ) ;
exit;
} add_action( 'wp_logout()', 'redirect_pending_users');
Result: both pending
and subscriber
users are stuck at the login page, with URL:
https://example.com/wp-login.php?redirect_to=https%3A%2F%2Fexample.com%2Fwp-admin%2Fprofile.php&reauth=1
During each attempt, I verified that the pending
role has no read
capacity (or any capacity), and that the subscriber
role does. I also verified that $current_user->roles[0]
does, indeed, contain the correct role.
What am I missing? Is there another way? Thank you for any help!
Solução
There are a couple of "timing" issues you're running into here.
When you're calling wp_get_current_user()
this isn't really available at the moment of logging in, so to capture the logging-in user, you have to use a slightly different approach.
The same is with logout, as it uses the same method of getting the current user.
In the solution below you're capturing the logging-in user directly from the wp_login hook, and then instead of calling wp_logout()
, you're calling the actual functions that do the logging-out for you. And, instead of adding multiple hooks, you're doing it all within the one hook: wp_login
There's also a sanity check to ensure the $user
is actually an \WP_User
object, or you'll get a fatal error on checking the capability.
function logout_pending_users( $username, $user ) {
if ( $user instanceof \WP_User && !$user->has_cap( 'read' ) ) {
wp_destroy_current_session();
wp_clear_auth_cookie();
wp_set_current_user( 0 );
wp_redirect( 'https://example.com/pending/' );
exit;
}
}
add_action( 'wp_login', 'logout_pending_users', 100, 2 );