2025-02-18 19:20:42 -07:00
< ? php
2025-02-19 10:06:30 -07:00
/**
* Support Access Manager
*
* Creates temporary WordPress admin accounts with expiration and access limits .
*
* @ package Support_Access_Manager
* @ author Derek Ashauer
* @ copyright Copyright ( c ) 2024 , Derek Ashauer
2025-02-19 13:45:55 -07:00
* @ license MIT
2025-02-19 10:06:30 -07:00
* @ link https :// github . com / derekashauer / support - access - manager
2025-02-19 13:47:01 -07:00
* @ version 0.2 . 1
2025-02-19 10:06:30 -07:00
*
* @ wordpress - plugin
* Requires at least : 5.0
2025-02-19 14:15:41 -07:00
* Requires PHP : 7.4
2025-02-19 10:06:30 -07:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
2025-02-19 09:29:27 -07:00
if ( ! class_exists ( 'Support_Access_Manager' ) ) {
class Support_Access_Manager {
private static $instance = null ;
private $menu_slug ;
private $menu_label ;
private $parent_slug ;
private $textdomain ;
private $default_settings ;
/**
* Get the singleton instance of Support_Access_Manager .
*
* @ param array $args Optional . Configuration arguments for the instance .
* Only used when creating a new instance .
* @ return Support_Access_Manager
*/
2025-02-19 10:00:01 -07:00
public static function instance ( $args = array () ) {
2025-02-19 09:29:27 -07:00
if ( null === self :: $instance ) {
self :: $instance = new self ( $args );
}
return self :: $instance ;
2025-02-18 19:20:42 -07:00
}
2025-02-19 09:29:27 -07:00
/**
* Protected constructor to prevent creating a new instance of the
* Singleton via the `new` operator from outside of this class .
*/
protected function __construct ( $args = array () ) {
$args = wp_parse_args (
$args ,
array (
'menu_slug' => 'support-access' ,
2025-02-19 09:56:59 -07:00
'menu_label' => __ ( 'Support Access' , $this -> textdomain ),
2025-02-19 09:29:27 -07:00
'parent_slug' => 'users.php' ,
'textdomain' => 'support-access' ,
'defaults' => array (),
)
);
$this -> menu_slug = $args [ 'menu_slug' ];
$this -> menu_label = $args [ 'menu_label' ];
$this -> parent_slug = $args [ 'parent_slug' ];
$this -> textdomain = $args [ 'textdomain' ];
// Set default settings with fallbacks
$this -> default_settings = wp_parse_args (
$args [ 'defaults' ],
array (
'duration' => 1 ,
'duration_unit' => 'weeks' ,
'usage_limit' => '' ,
'role' => 'administrator' ,
'locale' => '' ,
)
);
// Schedule cron job on plugin activation.
register_activation_hook ( __FILE__ , array ( $this , 'schedule_access_expiration_check' ) );
// Clear the scheduled cron job on plugin deactivation.
register_deactivation_hook ( __FILE__ , array ( $this , 'clear_access_expiration_check' ) );
2025-02-19 09:14:09 -07:00
2025-02-19 09:29:27 -07:00
// Schedule the cron event to check for expired admins.
add_action ( 'check_access_expiration_event' , array ( $this , 'check_access_expiration' ) );
// Handle temp admin login by checking the URL parameters.
add_action ( 'init' , array ( $this , 'check_access_login' ) );
// Add admin menu page.
add_action ( 'admin_menu' , array ( $this , 'add_support_access_menu' ) );
// Handle form submission to create temp admin users.
2025-02-19 14:14:47 -07:00
add_action ( 'admin_post_create_access_user' , array ( $this , 'handle_access_form_submission' ) );
2025-02-19 09:29:27 -07:00
// Handle deletion of temporary admins.
add_action ( 'admin_post_delete_access_user' , array ( $this , 'handle_access_deletion' ) );
2025-02-19 14:14:47 -07:00
// Handle generating new access URLs.
add_action ( 'admin_init' , array ( $this , 'handle_url_generation' ) );
2025-02-18 19:20:42 -07:00
}
2025-02-19 09:29:27 -07:00
/**
* Prevent cloning of the instance
*/
protected function __clone () {}
/**
* Prevent unserializing of the instance
*/
public function __wakeup () {
throw new \Exception ( 'Cannot unserialize singleton' );
2025-02-18 19:20:42 -07:00
}
2025-02-19 09:29:27 -07:00
/**
* Schedule the cron job when the plugin is activated .
*/
public function schedule_access_expiration_check () {
if ( ! wp_next_scheduled ( 'check_access_expiration_event' ) ) {
wp_schedule_event ( time (), 'hourly' , 'check_access_expiration_event' );
}
}
/**
* Clear the scheduled cron job on plugin deactivation .
*/
public function clear_access_expiration_check () {
$timestamp = wp_next_scheduled ( 'check_access_expiration_event' );
if ( $timestamp ) {
wp_unschedule_event ( $timestamp , 'check_access_expiration_event' );
}
}
/**
* Check for expired admins .
*/
public function check_access_expiration () {
$args = array (
'meta_key' => 'support_access_token' ,
'meta_query' => array (
'relation' => 'AND' ,
array (
'key' => 'support_access_expiration' ,
'compare' => 'EXISTS' ,
),
2025-02-18 20:36:48 -07:00
),
2025-02-19 09:29:27 -07:00
);
2025-02-18 19:20:42 -07:00
2025-02-19 09:29:27 -07:00
$user_query = new WP_User_Query ( $args );
2025-02-18 20:36:48 -07:00
2025-02-19 09:29:27 -07:00
if ( ! empty ( $user_query -> results ) ) {
foreach ( $user_query -> results as $user ) {
$expiration_time = get_user_meta ( $user -> ID , 'support_access_expiration' , true );
if ( $expiration_time && time () > $expiration_time ) {
wp_delete_user ( $user -> ID );
}
2025-02-18 19:20:42 -07:00
}
}
}
2025-02-19 09:29:27 -07:00
/**
* Add a menu item to the specified parent menu ( default : Users ) .
*/
public function add_support_access_menu () {
add_submenu_page (
$this -> parent_slug , // Parent menu slug.
$this -> menu_label , // Page title.
$this -> menu_label , // Menu title.
'manage_options' , // Capability.
$this -> menu_slug , // Menu slug.
array ( $this , 'support_access_page' ) // Callback function for the page content.
);
}
2025-02-18 19:20:42 -07:00
2025-02-19 09:29:27 -07:00
/**
* Admin page content for Support Access .
*/
public function support_access_page () {
2025-02-18 19:20:42 -07:00
?>
2025-02-19 09:29:27 -07:00
< div class = " wrap " >
< h1 >< ? php esc_html_e ( 'Support Access' , $this -> textdomain ); ?> </h1>
< ? php
2025-02-19 14:14:47 -07:00
// Check for success message.
if ( isset ( $_GET [ 'message' ] ) && 'success' === $_GET [ 'message' ] ) {
$access_url = false ;
if ( isset ( $_GET [ 'user_id' ], $_GET [ 'token' ] ) ) {
$user_id = absint ( $_GET [ 'user_id' ] );
$token = sanitize_text_field ( wp_unslash ( $_GET [ 'token' ] ) );
$access_url = add_query_arg (
array (
'support_access' => $user_id . '|' . $token ,
),
home_url ()
);
}
2025-02-19 17:38:51 -07:00
?>
< script >
function copyToClipboard ( text ) {
navigator . clipboard . writeText ( text ) . then ( function () {
const button = document . querySelector ( '.copy-button' );
const originalText = button . innerHTML ;
// Add checkmark with fade
button . innerHTML = '<span class="dashicons dashicons-yes" style="color: #46b450;"></span> <?php esc_html_e( ' Copied ! ', $this->textdomain ); ?>' ;
button . style . transition = 'opacity 0.2s' ;
// Fade back to original after delay
setTimeout (() => {
button . style . opacity = '0' ;
setTimeout (() => {
button . innerHTML = originalText ;
button . style . opacity = '1' ;
}, 200 );
}, 1500 );
});
}
</ script >
< ? php
2025-02-19 09:29:27 -07:00
printf (
2025-02-19 14:14:47 -07:00
'<div class="notice notice-warning is-dismissible"><p>%s</p>%s<p><strong>%s</strong></p></div>' ,
esc_html__ ( 'Support user access created successfully' , $this -> textdomain ),
$access_url ? sprintf (
2025-02-19 17:38:51 -07:00
'<p><strong>%s:</strong> <code>%s</code> <button onclick="copyToClipboard(\'%s\')" class="button copy-button">%s</button></p>' ,
2025-02-19 12:08:02 -07:00
esc_html__ ( 'Access URL' , $this -> textdomain ),
2025-02-19 17:38:51 -07:00
esc_url ( $access_url ),
esc_js ( $access_url ),
esc_html__ ( 'Copy URL' , $this -> textdomain )
2025-02-19 14:14:47 -07:00
) : '' ,
esc_html__ ( 'Important: Copy this URL now. For security reasons it cannot be displayed again.' , $this -> textdomain )
2025-02-19 09:29:27 -07:00
);
}
?>
2025-02-19 14:14:47 -07:00
< form method = " post " action = " <?php echo esc_url( admin_url( 'admin-post.php' ) ); ?> " class = " support-access-form " >
< input type = " hidden " name = " action " value = " create_access_user " >
2025-02-19 09:29:27 -07:00
< ? php wp_nonce_field ( 'create_access_user' ); ?>
< table class = " form-table " >
< tbody >
< tr >
< th scope = " row " >
< label for = " access_duration " >< ? php esc_html_e ( 'Access Duration:' , $this -> textdomain ); ?> </label>
</ th >
< td >
< input type = " number "
name = " access_duration "
id = " access_duration "
value = " <?php echo esc_attr( $this->default_settings ['duration'] ); ?> "
min = " 1 "
class = " small-text "
required >
< select name = " access_duration_unit " id = " access_duration_unit " >
< option value = " hours " < ? php selected ( $this -> default_settings [ 'duration_unit' ], 'hours' ); ?> >
< ? php esc_html_e ( 'Hours' , $this -> textdomain ); ?>
</ option >
< option value = " days " < ? php selected ( $this -> default_settings [ 'duration_unit' ], 'days' ); ?> >
< ? php esc_html_e ( 'Days' , $this -> textdomain ); ?>
</ option >
< option value = " weeks " < ? php selected ( $this -> default_settings [ 'duration_unit' ], 'weeks' ); ?> >
< ? php esc_html_e ( 'Weeks' , $this -> textdomain ); ?>
</ option >
< option value = " months " < ? php selected ( $this -> default_settings [ 'duration_unit' ], 'months' ); ?> >
< ? php esc_html_e ( 'Months' , $this -> textdomain ); ?>
</ option >
</ select >
< p class = " description " >
< ? php esc_html_e ( 'How long the temporary user account will exist before being automatically deleted.' , $this -> textdomain ); ?>
</ p >
</ td >
</ tr >
< tr >
< th scope = " row " >
< label for = " access_limit " >< ? php esc_html_e ( 'Usage Limit:' , $this -> textdomain ); ?> </label>
</ th >
< td >
< input type = " number "
name = " access_limit "
id = " access_limit "
value = " <?php echo esc_attr( $this->default_settings ['usage_limit'] ); ?> "
min = " 0 "
class = " small-text " >
< p class = " description " >
< ? php esc_html_e ( 'Maximum number of times the login link can be used. Enter 0 or leave empty for unlimited uses.' , $this -> textdomain ); ?>
</ p >
</ td >
</ tr >
< tr >
< th scope = " row " >
< label for = " user_role " >< ? php esc_html_e ( 'User Role:' , $this -> textdomain ); ?> </label>
</ th >
< td >
< select name = " user_role " id = " user_role " >
< ? php
$roles = wp_roles () -> get_names ();
foreach ( $roles as $role_id => $role_name ) {
printf (
'<option value="%s" %s>%s</option>' ,
esc_attr ( $role_id ),
selected ( $role_id , $this -> default_settings [ 'role' ], false ),
esc_html ( $role_name )
);
}
?>
</ select >
< p class = " description " >
< ? php esc_html_e ( 'The WordPress role assigned to the temporary user. Choose the minimum role needed for the support task.' , $this -> textdomain ); ?>
</ p >
</ td >
</ tr >
< tr >
< th scope = " row " >
< label for = " user_locale " >< ? php esc_html_e ( 'User Language:' , $this -> textdomain ); ?> </label>
</ th >
< td >
2025-02-18 20:20:41 -07:00
< ? php
2025-02-19 09:29:27 -07:00
require_once ABSPATH . 'wp-admin/includes/translation-install.php' ;
$translations = wp_get_available_translations ();
$languages = array (
'' => sprintf (
/* translators: %s: Current site language name */
__ ( 'Site Default - %s' , $this -> textdomain ),
$translations [ get_locale () ][ 'native_name' ] ? ? 'English (United States)'
),
);
// Add installed languages
$installed_languages = get_available_languages ();
foreach ( $installed_languages as $locale ) {
if ( isset ( $translations [ $locale ] ) ) {
$languages [ $locale ] = $translations [ $locale ][ 'native_name' ];
}
2025-02-18 20:20:41 -07:00
}
2025-02-19 09:29:27 -07:00
// Always include English (US) if not already added
if ( ! isset ( $languages [ 'en_US' ] ) ) {
$languages [ 'en_US' ] = 'English (United States)' ;
2025-02-19 09:21:07 -07:00
}
2025-02-19 09:29:27 -07:00
$current_locale = get_locale ();
?>
< select name = " user_locale " id = " user_locale " >
< ? php
foreach ( $languages as $locale => $native_name ) {
printf (
'<option value="%s" %s>%s</option>' ,
esc_attr ( $locale ),
selected ( $locale , $this -> default_settings [ 'locale' ], false ),
esc_html ( $native_name )
);
}
?>
</ select >
< p class = " description " >
< ? php esc_html_e ( 'The WordPress admin interface language for this temporary user. Choose "Site Default" to use the site\'s language setting.' , $this -> textdomain ); ?>
</ p >
</ td >
</ tr >
</ tbody >
</ table >
< ? php submit_button ( __ ( 'Create User' , $this -> textdomain ) ); ?>
</ form >
< ? php $this -> list_access_users (); ?>
</ div >
< style >
. action - icon {
color : #50575e;
cursor : pointer ;
padding : 4 px ;
text - decoration : none ;
vertical - align : middle ;
}
. action - icon : hover {
color : #135e96;
}
. action - icon . delete {
color : #b32d2e;
}
. action - icon . delete : hover {
color : #991b1c;
}
2025-02-19 17:38:51 -07:00
. button . copy - button span {
vertical - align : middle ;
}
2025-02-19 09:29:27 -07:00
</ style >
< ? php
2025-02-19 09:21:07 -07:00
}
2025-02-18 19:20:42 -07:00
2025-02-19 09:29:27 -07:00
/**
* Handle form submission and create the temp admin user .
*/
public function handle_access_form_submission () {
2025-02-19 19:01:12 +01:00
if ( ! isset ( $_POST [ 'access_duration' ] ) || ! current_user_can ( 'create_users' ) ) {
2025-02-19 09:29:27 -07:00
return ;
}
2025-02-18 19:20:42 -07:00
2025-02-19 09:29:27 -07:00
if ( ! wp_verify_nonce ( $_POST [ '_wpnonce' ], 'create_access_user' ) ) {
wp_die ( 'Invalid nonce' );
}
2025-02-18 19:20:42 -07:00
2025-02-19 09:29:27 -07:00
// Calculate expiration time based on duration and unit
$duration = absint ( $_POST [ 'access_duration' ] );
$unit = sanitize_text_field ( wp_unslash ( $_POST [ 'access_duration_unit' ] ) );
switch ( $unit ) {
case 'hours' :
$expiration_time = time () + ( $duration * HOUR_IN_SECONDS );
break ;
case 'days' :
$expiration_time = time () + ( $duration * DAY_IN_SECONDS );
break ;
case 'weeks' :
$expiration_time = time () + ( $duration * WEEK_IN_SECONDS );
break ;
case 'months' :
$expiration_time = time () + ( $duration * MONTH_IN_SECONDS );
break ;
default :
$expiration_time = time () + WEEK_IN_SECONDS ; // Default to 1 week.
}
2025-02-18 19:20:42 -07:00
2025-02-19 10:14:57 -07:00
$limit = isset ( $_POST [ 'access_limit' ] ) ? absint ( $_POST [ 'access_limit' ] ) : 0 ;
$role = sanitize_text_field ( wp_unslash ( $_POST [ 'user_role' ] ) );
$locale = sanitize_text_field ( wp_unslash ( $_POST [ 'user_locale' ] ) );
2025-02-18 20:20:41 -07:00
2025-02-19 12:08:02 -07:00
// Create temporary user and get access token.
2025-02-19 13:45:55 -07:00
$result = $this -> create_access_user ( $role );
2025-02-19 09:29:27 -07:00
// Store user metadata.
2025-02-19 13:45:55 -07:00
update_user_meta ( $result [ 'user_id' ], 'support_access_login_count' , 0 );
update_user_meta ( $result [ 'user_id' ], 'support_access_expiration' , $expiration_time );
update_user_meta ( $result [ 'user_id' ], 'support_access_limit' , $limit );
2025-02-19 09:29:27 -07:00
if ( ! empty ( $locale ) ) {
2025-02-19 13:45:55 -07:00
update_user_meta ( $result [ 'user_id' ], 'locale' , $locale );
2025-02-19 09:29:27 -07:00
}
2025-02-19 09:21:07 -07:00
2025-02-19 14:14:47 -07:00
// Redirect with success message and access token.
wp_redirect (
add_query_arg (
array (
'page' => 'support-access' ,
'message' => 'success' ,
'user_id' => $result [ 'user_id' ],
'token' => $result [ 'access_token' ],
2025-02-19 13:45:55 -07:00
),
2025-02-19 14:14:47 -07:00
admin_url ( 'users.php' )
)
2025-02-19 09:29:27 -07:00
);
2025-02-18 20:20:41 -07:00
exit ;
}
2025-02-19 09:29:27 -07:00
/**
* Create a temporary admin user .
*
2025-02-19 12:08:02 -07:00
* @ param string $role The role to assign to the user .
* @ return array Array containing user ID and access token .
2025-02-19 09:29:27 -07:00
*/
private function create_access_user ( $role = 'administrator' ) {
$username = 'support_user_' . uniqid ();
$password = wp_generate_password ();
$email = $username . '@example.com' ;
$user_id = wp_create_user ( $username , $password , $email );
$user = new WP_User ( $user_id );
$user -> set_role ( $role );
2025-02-19 14:14:47 -07:00
// Generate random token and store its hash for verification
2025-02-19 12:08:02 -07:00
$access_token = wp_generate_password ( 32 , false );
2025-02-19 13:45:55 -07:00
$token_hash = hash ( 'sha256' , $access_token );
2025-02-19 12:08:02 -07:00
update_user_meta ( $user_id , 'support_access_token_hash' , $token_hash );
return array (
'user_id' => $user_id ,
'access_token' => $access_token ,
);
2025-02-18 19:20:42 -07:00
}
2025-02-19 12:08:02 -07:00
/**
* Check if the access token is valid and log in the user .
*/
public function check_access_login () {
if ( ! isset ( $_GET [ 'support_access' ] ) ) {
return ;
2025-02-19 09:29:27 -07:00
}
2025-02-18 20:20:41 -07:00
2025-02-19 13:45:55 -07:00
$parts = explode ( '|' , sanitize_text_field ( wp_unslash ( $_GET [ 'support_access' ] ) ) );
if ( count ( $parts ) !== 2 ) {
wp_safe_redirect ( home_url () );
exit ;
}
2025-02-18 20:20:41 -07:00
2025-02-19 13:45:55 -07:00
list ( $user_id , $received_token ) = $parts ;
$user_id = absint ( $user_id );
2025-02-18 20:20:41 -07:00
2025-02-19 13:45:55 -07:00
// Get stored hash.
$stored_hash = get_user_meta ( $user_id , 'support_access_token_hash' , true );
if ( empty ( $stored_hash ) ) {
2025-02-19 09:29:27 -07:00
wp_safe_redirect ( home_url () );
exit ;
}
2025-02-18 20:20:41 -07:00
2025-02-19 13:45:55 -07:00
// Verify token.
if ( ! hash_equals ( $stored_hash , hash ( 'sha256' , $received_token ) ) ) {
wp_safe_redirect ( home_url () );
exit ;
}
2025-02-18 20:20:41 -07:00
2025-02-19 13:45:55 -07:00
// Check expiration and limits.
$expiration = get_user_meta ( $user_id , 'support_access_expiration' , true );
$limit = get_user_meta ( $user_id , 'support_access_limit' , true );
$login_count = get_user_meta ( $user_id , 'support_access_login_count' , true );
2025-02-19 09:29:27 -07:00
2025-02-19 13:45:55 -07:00
if ( time () > $expiration ) {
wp_delete_user ( $user_id );
wp_safe_redirect ( home_url () );
exit ;
}
2025-02-19 09:29:27 -07:00
2025-02-19 13:45:55 -07:00
if ( $limit > 0 && $login_count >= $limit ) {
wp_safe_redirect ( home_url () );
exit ;
2025-02-19 12:08:02 -07:00
}
2025-02-19 09:29:27 -07:00
2025-02-19 13:45:55 -07:00
// Log the user in.
wp_set_current_user ( $user_id );
wp_set_auth_cookie ( $user_id );
update_user_meta ( $user_id , 'support_access_login_count' , intval ( $login_count ) + 1 );
wp_safe_redirect ( admin_url () );
2025-02-19 09:29:27 -07:00
exit ;
2025-02-18 19:20:42 -07:00
}
2025-02-19 09:29:27 -07:00
/**
2025-02-19 10:14:57 -07:00
* List temporary admins with login count , expiration date , and delete option .
2025-02-19 09:29:27 -07:00
*/
private function list_access_users () {
$args = array (
'meta_query' => array (
'relation' => 'AND' ,
2025-02-19 12:08:02 -07:00
array (
2025-02-19 13:45:55 -07:00
'key' => 'support_access_token_hash' ,
2025-02-19 12:08:02 -07:00
'compare' => 'EXISTS' ,
),
2025-02-18 20:20:41 -07:00
array (
2025-02-19 09:29:27 -07:00
'key' => 'support_access_expiration' ,
'compare' => 'EXISTS' ,
2025-02-18 20:20:41 -07:00
),
2025-02-19 09:29:27 -07:00
),
);
$user_query = new WP_User_Query ( $args );
if ( ! empty ( $user_query -> results ) ) {
echo '<h2>' . esc_html__ ( 'Temporary Users' , $this -> textdomain ) . '</h2>' ;
echo '<table class="wp-list-table widefat fixed striped users">' ;
echo '<thead>' ;
echo '<tr>' ;
echo '<th>' . esc_html__ ( 'Username' , $this -> textdomain ) . '</th>' ;
echo '<th>' . esc_html__ ( 'Role' , $this -> textdomain ) . '</th>' ;
echo '<th>' . esc_html__ ( 'Login Count' , $this -> textdomain ) . '</th>' ;
echo '<th>' . esc_html__ ( 'Expiration Date' , $this -> textdomain ) . '</th>' ;
echo '<th>' . esc_html__ ( 'Access URL' , $this -> textdomain ) . '</th>' ;
echo '<th>' . esc_html__ ( 'Actions' , $this -> textdomain ) . '</th>' ;
echo '</tr>' ;
echo '</thead>' ;
echo '<tbody>' ;
foreach ( $user_query -> results as $user ) {
$login_count = get_user_meta ( $user -> ID , 'support_access_login_count' , true );
$user_profile_url = get_edit_user_link ( $user -> ID );
$expiration_time = get_user_meta ( $user -> ID , 'support_access_expiration' , true );
$expiration_date = $expiration_time ?
wp_date ( get_option ( 'date_format' ) . ' ' . get_option ( 'time_format' ), $expiration_time ) : '' ;
$limit = get_user_meta ( $user -> ID , 'support_access_limit' , true );
$login_info = ( empty ( $limit ) || '0' === $limit ) ? $login_count . ' / ∞' : $login_count . ' / ' . $limit ;
2025-02-19 12:08:02 -07:00
// Get user's role
2025-02-19 09:29:27 -07:00
$user_roles = array_map (
function ( $role ) {
return translate_user_role ( wp_roles () -> get_names ()[ $role ] );
},
$user -> roles
);
?>
< tr >
< td >< a href = " <?php echo esc_url( $user_profile_url ); ?> " >< ? php echo esc_html ( $user -> user_login ); ?> </a></td>
< td >< ? php echo esc_html ( implode ( ', ' , $user_roles ) ); ?> </td>
< td >< ? php echo esc_html ( $login_info ); ?> </td>
< td >< ? php echo esc_html ( $expiration_date ); ?> </td>
< td >
2025-02-19 14:14:47 -07:00
< a href = "
< ? php
echo esc_url (
wp_nonce_url (
add_query_arg (
array (
'page' => 'support-access' ,
'action' => 'generate_access_url' ,
'user_id' => $user -> ID ,
),
admin_url ( 'users.php' )
),
'generate_access_url_' . $user -> ID
)
);
?>
2025-02-19 14:40:47 -07:00
" >
2025-02-19 14:14:47 -07:00
< span class = " dashicons dashicons-admin-links " style = " vertical-align: text-top; " ></ span >
< ? php esc_html_e ( 'Generate New URL' , $this -> textdomain ); ?>
</ a >
2025-02-19 09:29:27 -07:00
</ td >
< td >
< form method = " post " action = " <?php echo esc_url( admin_url( 'admin-post.php' ) ); ?> " style = " display:inline; " >
< ? php wp_nonce_field ( 'delete_access_user_' . $user -> ID ); ?>
< input type = " hidden " name = " action " value = " delete_access_user " >
< input type = " hidden " name = " delete_access_user_id " value = " <?php echo esc_attr( $user->ID ); ?> " >
< button type = " submit " class = " action-icon delete " style = " border: none; background: none; padding: 0; " >
< span class = " dashicons dashicons-trash "
title = " <?php esc_attr_e( 'Delete User', $this->textdomain ); ?> " >
</ span > < ? php esc_html_e ( 'Delete' , $this -> textdomain ); ?>
</ button >
</ form >
</ td >
</ tr >
< ? php
}
2025-02-18 19:20:42 -07:00
2025-02-19 09:29:27 -07:00
echo '</tbody>' ;
echo '</table>' ;
}
}
/**
* Handle temporary admin deletion .
*/
public function handle_access_deletion () {
if ( isset ( $_POST [ 'delete_access_user_id' ] ) && current_user_can ( 'manage_options' ) ) {
$user_id = absint ( $_POST [ 'delete_access_user_id' ] );
if ( wp_verify_nonce ( $_POST [ '_wpnonce' ], 'delete_access_user_' . $user_id ) ) {
wp_delete_user ( $user_id );
// Store deletion message in transient.
set_transient (
'support_access_message_' . get_current_user_id (),
array (
'type' => 'success' ,
'message' => __ ( 'Support access user deleted successfully.' , $this -> textdomain ),
),
30
);
wp_redirect ( admin_url ( 'users.php?page=support-access' ) );
exit ;
}
2025-02-18 19:20:42 -07:00
}
}
2025-02-19 13:45:55 -07:00
2025-02-19 14:14:47 -07:00
/**
* Handle generating new access URL .
*/
public function handle_url_generation () {
if ( ! isset ( $_GET [ 'action' ], $_GET [ 'user_id' ] ) || 'generate_access_url' !== $_GET [ 'action' ] ) {
return ;
}
if ( ! current_user_can ( 'manage_options' ) ) {
return ;
}
$user_id = absint ( $_GET [ 'user_id' ] );
if ( ! wp_verify_nonce ( $_GET [ '_wpnonce' ], 'generate_access_url_' . $user_id ) ) {
wp_die ( 'Invalid nonce' );
}
// Generate new token and hash
$access_token = wp_generate_password ( 32 , false );
$token_hash = hash ( 'sha256' , $access_token );
update_user_meta ( $user_id , 'support_access_token_hash' , $token_hash );
// Redirect with success message and access token
wp_redirect (
add_query_arg (
array (
'page' => 'support-access' ,
'message' => 'success' ,
'user_id' => $user_id ,
'token' => $access_token ,
),
admin_url ( 'users.php' )
)
);
exit ;
}
2025-02-18 19:20:42 -07:00
}
2025-02-19 09:29:27 -07:00
2025-02-18 19:20:42 -07:00
}