Руководство разработчика плагинов для WordPress (часть 10) 05 Марта 2018

Руководство разработчика плагинов для WordPress (часть 10)

Проверка возможностей пользователя

Если ваш плагин позволяет пользователям сохранять данные, будь то в консоли администратора или в любом общедоступном месте, эти данные должны быть проверены возможности пользователя.

Роли и возможности пользователя

Наиболее важным шагом в создании эффективного слоя безопасности является размещение системы управления доступом для пользователей. WordPress предоставляет это в форме ролей и возможностей пользователей. Каждому пользователю, зарегистрированному в WordPress, автоматически присваиваются специфические права доступа в зависимости от роли этого пользователя. Роли пользователей это всего-лишь «виртуальный» способ указания того, к какой группе принадлежит данный пользователь. Каждая группа имеет специфический набор предустановленных возможностей. Например, главный пользователь вашего веб-сайта будет иметь роль пользователя — Администратор, в то время как другие пользователи могут иметь роли вроде Редактор или Автор. Вы можете иметь более одного пользователя, привязанного к одной роли, например, на одном веб-сайте могут быть два Администратора. Возможности пользователя — это специфические разрешения, которые вы присваиваете каждому пользователю или роли пользователя. Например, Администраторы имеют возможность «manage_options» («управление опциями»), которая позволяет им просматривать, редактировать и сохранять опции для данного веб-сайта. Редакторы, с другой стороны, не имеют данной возможности, которая будет запрещать им любые взаимодействия с опциями. Эти возможности затем отмечены в различных точках внутри консоли Администратора. В зависимости от возможностей, присвоенных роли, меню, функции и другие аспекты WordPress могут быть добавлены или удалены. Когда вы создаете плагин, убедитесь, что ваш код запускается только, когда текущий пользователь имеет необходимые возможности.

Иерархия

Чем выше роль пользователя, тем больше возможностей данный пользователь имеет. Каждая пользовательская роль наследует предыдущие роли в иерархии. Например, «Администратор», который является высочайшей ролью в иерархии ролей на единичном сайте, наследует следующие роли и их возможности: «Подписчик», «Contributor», «Автор» и «Редактор».

Примеры

Без ограничений

Представленный ниже пример создает ссылку на общедоступной странице, которая дает возможность удалять записи. Поскольку этот код не проверяет возможности пользователя, он позволяет любому посетителю сайта удалять записи!
 <?php
             /**
              * generate a Delete link based on the homepage url
              */
             function wporg_generate_delete_link($content)
             {
                // run only for single post page
                if (is_single() && in_the_loop() && is_main_query()) {
                    // add query arguments: action, post
                    $url = add_query_arg(
                        [
                            "action" => "wporg_frontend_delete",
                            "post"   => get_the_ID(),
                        ],
                        home_url()
                    );
                    return $content . " <a href="" . esc_url($url) . "">" . esc_html__("Delete Post", "wporg") . "</a>";
                }
                return null;
             }

             /**
             * request handler
             */
             function wporg_delete_post()
             {
                if (isset($_GET["action"]) && $_GET["action"] === "wporg_frontend_delete") {

                    // verify we have a post id
                    $post_id = (isset($_GET["post"])) ? ($_GET["post"]) : (null);

                    // verify there is a post with such a number
                    $post = get_post((int)$post_id);
                    if (empty($post)) {
                        return;
                    }

                    // delete the post
                    wp_trash_post($post_id);

                    // redirect to admin page
                    $redirect = admin_url("edit.php");
                    wp_safe_redirect($redirect);

                    // we are done
                    die;
                }
             }

             /**
             * add the delete link to the end of the post content
             */
             add_filter("the_content", "wporg_generate_delete_link");

             /**
             * register our request handler with the init hook
             */
             add_action("init", "wporg_delete_post");

            

Ограничения на специфические возможности

Пример выше позволяет любому посетителю сайта нажать на ссылку «Delete» (Удалить) и удалить запись. Однако, нам нужно, чтобы только Редакторы и роли выше имели возможность нажать на ссылку «Delete». Чтобы это реализовать, мы будем проверять, имеет ли текущий пользователь возможность edit_others_posts, которую имеют только Редакторы и роли выше:
 <?php
             /**
             * generate a Delete link based on the homepage url
             */
             function wporg_generate_delete_link($content)
             {
                // run only for single post page
                if (is_single() && in_the_loop() && is_main_query()) {
                    // add query arguments: action, post
                    $url = add_query_arg(
                        [
                            "action" => "wporg_frontend_delete",
                            "post"   => get_the_ID(),
                        ],
                        home_url()
                    );
                    return $content . " <a href="" . esc_url($url) . "">" . esc_html__("Delete Post", "wporg") . "</a>";
                }
                return null;
             }

             /**
             * request handler
             */
             function wporg_delete_post()
             {
                if (isset($_GET["action"]) && $_GET["action"] === "wporg_frontend_delete") {

                    // verify we have a post id
                    $post_id = (isset($_GET["post"])) ? ($_GET["post"]) : (null);

                    // verify there is a post with such a number
                    $post = get_post((int)$post_id);
                    if (empty($post)) {
                        return;
                    }

                    // delete the post
                    wp_trash_post($post_id);

                    // redirect to admin page
                    $redirect = admin_url("edit.php");
                    wp_safe_redirect($redirect);

                    // we are done
                    die;
                }
             }

             if (current_user_can("edit_others_posts")) {
                /**
                 * add the delete link to the end of the post content
                 */
                add_filter("the_content", "wporg_generate_delete_link");

                /**
                 * register our request handler with the init hook
                 */
                add_action("init", "wporg_delete_post");
             }