How To Ban A WordPress User

I was asked a few days ago to create a system would ban a WordPress user from an install. So I created a simple plugin and I wanted to share with you the basics of this plugin. In this tutorial we will be covering WordPress filters, actions, users columns management and some more great things.
Step 1: Create The Plugin
Once again, here it’s very complicated, all you have to do is to create a new folder with “wp-content/plugins” called “ban-users”. In this folder, create a new file called “ban-users.php”, open it an paste this code:
<?php
/*
Plugin Name: Ban Users
Plugin URI: http://www.remicorson.com
Description: Allows you to ban users
Author: Remi Corson
Version: 1.0
Author URI: http://www.remicorson.com
*/
Step 2: Add A Checkbox On Users’ Profile Page
The first thing we need to to do is to add a checkbox on each user profile edition page. When you’ll check this checkbox it will store a user meta option that will indicated that the user isn’t allowed anymore to login to your website.
Here is the code:
/**
* Admin init
*
* @access public
* @since 1.0
* @return void
*/
function rc_admin_init(){
// Edit user profile
add_action( 'edit_user_profile', 'rc_edit_user_profile' );
add_action( 'edit_user_profile_update', 'rc_edit_user_profile_update' );
}
add_action('admin_init', 'rc_admin_init' );
This code is simply creating a call to a function that we have to create now. This function will add a checkbox to users profile page.
/**
* Adds custom checkbox to user edition page
*
* @access public
* @since 1.0
* @return void
*/
function rc_edit_user_profile() {
if ( !current_user_can( 'edit_users' ) ) {
return;
}
global $user_id;
// User cannot disable itself
$current_user = wp_get_current_user();
$current_user_id = $current_user->ID;
if ( $current_user_id == $user_id ) {
return;
}
// Check if enabled
$checked = checked( get_user_option( 'rc_banned', $user_id, false ) );
// Display checkbox
echo '<table class="form-table">
<tr>
<th scope="row">Ban User</th>
<td>
<label for="rc_ban">
<input name="rc_ban" type="checkbox" id="rc_ban" '. $checked .' />Ban this user</label>
</td>
</tr>
</table>';
}
We now need to have the function that will save into the database the value of the checkbox:
/**
* Save custom checkbox
*
* @access public
* @since 1.0
* @return void
*/
function rc_edit_user_profile_update() {
if ( !current_user_can( 'edit_users' ) ) {
return;
}
global $user_id;
// User cannot disable itself
$current_user = wp_get_current_user();
$current_user_id = $current_user->ID;
if ( $current_user_id == $user_id ) {
return;
}
// Lock
if( isset( $_POST['rc_ban'] ) && $_POST['rc_ban'] = 'on' ) {
rc_ban_user( $user_id );
} else { // Unlock
rc_unban_user( $user_id );
}
}
As you can see this new function uses two other functions: rc_ban_users() and rc_unban_users(). Their names are pretty explicit, the first one will store in the database the fact that a user is ban, the second will unlock users.
Step 3: Ban Users
It’s now time to create the rc_ban_users() function. In this function we need to check if a value is already stored, and if not we need to store the value. That’s the reason why i call a function that I’ll describe later: rc_is_user_banned():
/**
* Ban user
*
* @access public
* @since 1.0
* @return void
*/
function rc_ban_user( $user_id ) {
$old_status = rc_is_user_banned( $user_id );
// Update status
if ( !$old_status ) {
update_user_option( $user_id, 'rc_banned', true, false );
}
}
Step 4: Un-ban Users
The following function is the opposite as the one we just created: we have to give the ability to “un-ban” users:
/**
* Un-ban user
*
* @access public
* @since 1.0
* @return void
*/
function rc_unban_user( $user_id ) {
$old_status = rc_is_user_banned( $user_id );
// Update status
if ( $old_status ) {
update_user_option( $user_id, 'rc_banned', false, false );
}
}
Step 5: Is User Banned?
We saw in rc_ban_users() and rc_unban_users() that we use a function called rc_is_user_banned() to check if a user is banned or not. Let’s create it:
/**
* Checks if a user is already banned
*
* @access public
* @since 1.0
* @return void
*/
function rc_is_user_banned( $user_id ) {
return get_user_option( 'rc_banned', $user_id, false );
}
Basically, this function simply returns the value of the option saved in rc_ban_users().
At this time we have a new checkbox on the user edition page that should like that:
The last step is to hook a function to the login form to avoid banned users to login.
Step 5: Avoid Banned Users To Login
To do so we need to use a WordPress default filter called “wp_authenticate_user”. To this filter we’ll hook a function called “rc_authenticate_user()”. This function will use the WP_Error class.
/**
* Check if user is locked while login process
*
* @access public
* @since 1.0
* @return void
*/
function rc_authenticate_user( $user ) {
if ( is_wp_error( $user ) ) {
return $user;
}
// Return error if user account is banned
$banned = get_user_option( 'rc_banned', $user->ID, false );
if ( $banned ) {
return new WP_Error( 'rc_banned', __('<strong>ERROR</strong>: This user account is disabled.', 'rc') );
}
return $user;
}
Now, we just need to add the filter:
add_filter( 'wp_authenticate_user', 'rc_authenticate_user', 1 );
We created a plugin that adds a checkbox to the user profile edition page. We used a second function to store the value on the checkbox and we create a function to ban a WordPress user and another on to unlock a user. We also created a small function to check if a user is banned or not. And we finally hooked a function to the “wp_authenticate_user” filter using the WP_Error WordPress default class.
This is great 😉 Much better then simply deleting their account.
Nice article, I’m just curious, is there a reason why the first two actions are called on admin_init? Would they not work outside the function rc_admin_init?
Yes that’s correct
Great functionality addition, I can see how simply suspending an account and then warning users is alot better than deleting the account like AJ Clarke mentioned.
Interesting code … I like it 🙂
great method there, a bit differently I am trying to modify checkbox to be able to checked by default in the user profile field.
php echo (esc_attr( get_the_author_meta( ‘filed_ID’, $user->ID ) ) ? ‘checked=”checked” ‘ : ‘ ‘);
this code makes the checkbox disabled by default, how can i have it checked by default? any idea?
I’m prety sure the meta value still needs to be registered into the database so even if it was checked by default, you would still have to re-save all your user meta options to register it. So I really don’t see a point.
What might be better is to just switch your if statements. So if it is checked the the user is not banned and if it is not checked then they are. I’m, not really sure what you are trying to do…
Remi this is really great script,
Implemented on my site, just one thing after banning anf reloading user page check box is not checked. If I save it again user is unbanned. You wanted like that to be?
thanks Dragos
Great tutorial but just one problem. If the admin clicks the checkbutton and saves the profile, when the profile page is reloaded, the button does not remain checked. How can we fix this so that it remains checked so that a different admin can clearly see that the user is banned…?
I managed to get step 1 creating the file, but became lost on Step 2. Does that go in the plugin file?
Yes, all the code goes right below step 1 in the plugin file. You only need one file for this plugin with all the code 😉 Here I’ve created a Github post with everything so you can see – https://github.com/wpexplorer/ban-users-wordpress/blob/master/README.md
Hi there,
Good work Remi.
Little typo here :
A single equal makes the control true. You have to use double (simple control) or triple equal (strict control).
Thank you.
Geoffrey
Hi,
I’ve tried to use this but when I login a banned account it shows the error on the wp-login page but it doesn’t stop them all they have to do is navigate to a new page…
Also, if they’re logged in then the same problem happens they don’t get logged out.
Any ideas
Great Code… Thanx for this tutorial…..
Nice
I used this on my codes.