Last active
January 6, 2025 11:41
-
-
Save Qubadi/c413c2dfec5f5227100392bc99756ce5 to your computer and use it in GitHub Desktop.
User approval system for Wordpress
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Description: | |
This code implements a secure user approval system for WordPress, allowing administrators to manage user access based on approval status. | |
New users are marked as “pending approval” by default, preventing any login until they are approved. | |
When a user is approved by an administrator, they automatically receive an email containing their login URL and further instructions. | |
Administrators can approve or unapprove users directly from the admin panel, with real-time session termination for unapproved accounts. | |
The system is compatible with all login methods, employs nonce-based security for critical actions, and excludes administrators | |
from approval workflows. | |
These two lines need to be updated with your own URLs: | |
Replace the URL for redirecting to the "account pending" page: | |
wp_redirect('YOUR_OWN_URL_HERE'); | |
Replace the URL in the email message: | |
esc_url('YOUR_OWN_URL_HERE/'); | |
Copy the following PHP code and create a PHP snippet using your snippet plugins. | |
Paste the code into the plugin and save it. | |
_________________________________________________ | |
<?php | |
// Automatically approve all existing users who don't have the 'is_approved' meta field | |
function approve_existing_users() { | |
$users = get_users(array( | |
'meta_key' => 'is_approved', | |
'meta_compare' => 'NOT_EXISTS', | |
'exclude' => get_users(array( | |
'role' => 'administrator', | |
'fields' => 'ID' | |
)) | |
)); | |
foreach ($users as $user) { | |
update_user_meta($user->ID, 'is_approved', 1); | |
} | |
} | |
// Add 'is_approved' meta field to newly registered users | |
function add_user_approval_meta($user_id) { | |
$user = get_userdata($user_id); | |
if (in_array('administrator', $user->roles)) { | |
return; // Do not add approval status for administrators | |
} | |
update_user_meta($user_id, 'is_approved', 0); // Default to unapproved | |
} | |
add_action('user_register', 'add_user_approval_meta'); | |
// Redirect unapproved users to the "account pending" page | |
// (instead of returning a WP_Error), so the default login remains accessible | |
function prevent_non_approved_user_login($user, $username, $password) { | |
// Sanitize login data | |
$username = sanitize_user($username); | |
$user_data = get_user_by('login', $username); | |
if (!$user_data) { | |
$email = sanitize_email($username); | |
$user_data = get_user_by('email', $email); | |
} | |
// If user found and not an administrator, check approval | |
if ($user_data && !in_array('administrator', $user_data->roles)) { | |
$is_approved = get_user_meta($user_data->ID, 'is_approved', true); | |
if ($is_approved != 1) { | |
// Redirect to the "account pending" page | |
wp_redirect('ADD YOUR URL HERE'); | |
exit; | |
} | |
} | |
return $user; | |
} | |
add_filter('authenticate', 'prevent_non_approved_user_login', 30, 3); | |
// Add an approval status column to the admin user list | |
function add_approval_column($columns) { | |
$columns['approval_status'] = __('Approval Status'); | |
return $columns; | |
} | |
add_filter('manage_users_columns', 'add_approval_column'); | |
// Show approval status and provide approve/unapprove actions in the user list | |
function show_approval_status($value, $column_name, $user_id) { | |
if ($column_name === 'approval_status') { | |
$user = get_userdata($user_id); | |
if (in_array('administrator', $user->roles)) { | |
return __('N/A'); // Exclude administrators | |
} | |
$is_approved = get_user_meta($user_id, 'is_approved', true); | |
$nonce = wp_create_nonce('user_approval_nonce'); | |
if ($is_approved == 1) { | |
return sprintf( | |
'<a href="%s" class="button button-secondary">Unapprove</a>', | |
esc_url( | |
add_query_arg(array( | |
'action' => 'unapprove_user', | |
'user' => $user_id, | |
'_wpnonce' => $nonce | |
), admin_url('users.php')) | |
) | |
); | |
} else { | |
return sprintf( | |
'<a href="%s" class="button button-primary">Approve</a>', | |
esc_url( | |
add_query_arg(array( | |
'action' => 'approve_user', | |
'user' => $user_id, | |
'_wpnonce' => $nonce | |
), admin_url('users.php')) | |
) | |
); | |
} | |
} | |
return $value; | |
} | |
add_filter('manage_users_custom_column', 'show_approval_status', 10, 3); | |
// Handle approve/unapprove actions in the admin interface | |
function handle_user_approval_actions() { | |
if (!current_user_can('manage_options')) { | |
return; | |
} | |
if (!isset($_GET['action'], $_GET['user'], $_GET['_wpnonce'])) { | |
return; | |
} | |
$action = sanitize_text_field($_GET['action']); | |
$user_id = intval($_GET['user']); | |
if (!wp_verify_nonce($_GET['_wpnonce'], 'user_approval_nonce')) { | |
return; | |
} | |
$user = get_userdata($user_id); | |
if (!$user || in_array('administrator', $user->roles)) { | |
return; | |
} | |
if ($action === 'approve_user') { | |
update_user_meta($user_id, 'is_approved', 1); | |
} elseif ($action === 'unapprove_user') { | |
update_user_meta($user_id, 'is_approved', 0); | |
// Log out the user immediately if unapproved | |
$sessions = WP_Session_Tokens::get_instance($user_id); | |
$sessions->destroy_all(); | |
} | |
wp_safe_redirect(admin_url('users.php')); | |
exit; | |
} | |
add_action('admin_init', 'handle_user_approval_actions'); | |
// Notify users when their account is approved | |
// (includes the same custom login link as in code nr1) | |
function notify_user_approval($user_id) { | |
$user = get_userdata($user_id); | |
if (in_array('administrator', $user->roles)) { | |
return; // Administrators do not receive approval emails | |
} | |
$email = $user->user_email; | |
$subject = 'Your account has been approved!'; | |
$message = sprintf( | |
'Hello,<br>Your account on %s has been approved. You can now <a href="%s">log in</a>.', | |
get_bloginfo('name'), | |
esc_url('ADD YOUR URL HERE/') | |
); | |
$headers = array( | |
'From: ' . get_bloginfo('name') . ' <no-reply@' . sanitize_text_field($_SERVER['SERVER_NAME']) . '>', | |
'Content-Type: text/html; charset=UTF-8' | |
); | |
wp_mail($email, $subject, $message, $headers); | |
} | |
function maybe_notify_user($meta_id, $user_id, $meta_key, $meta_value) { | |
if ($meta_key === 'is_approved' && intval($meta_value) === 1) { | |
notify_user_approval($user_id); | |
} | |
} | |
add_action('updated_user_meta', 'maybe_notify_user', 10, 4); | |
// Allow sorting the admin user list by approval status | |
function make_approval_column_sortable($columns) { | |
$columns['approval_status'] = 'approval_status'; | |
return $columns; | |
} | |
add_filter('manage_users_sortable_columns', 'make_approval_column_sortable'); | |
// Add sorting functionality for approval status | |
function approval_status_orderby($query) { | |
if (is_admin() && $query->is_main_query()) { | |
$orderby = $query->get('orderby'); | |
if ($orderby === 'approval_status') { | |
$query->set('meta_key', 'is_approved'); | |
$query->set('orderby', 'meta_value'); | |
} | |
} | |
} | |
add_action('pre_get_users', 'approval_status_orderby'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment