С Rest V2 (WP4.7), как ограничить определенные RESTFUL глаголы?

20

Я стремлюсь ограничить некоторые глаголы RESTUL для каждого типа сообщения. Например, учитывая пользовательский тип поста Vocabulary, я хотел бы сказать:

Матрица разрешений

+-------+---+----------+
|index  | X | GET      |
|show   | O | GET      |
|create | X | POST     |
|update | X | PATCH/PUT|
|delete | X | DELETE   |
+-------+---+----------+

V2, похоже, не обеспечивает такой уровень контроля. Я просмотрел источник, и из того, что я вижу, нет никаких хуков / фильтров, которые можно было бы использовать для изменения разрешений.

Мое текущее решение заключается в следующем. Это компрометирует класс, где вы можете загрузить в матрицу пользовательских типов записей против разрешенных действий. Затем это можно вызвать в rest_prepare_vocabularyфильтре, уничтожив ответ, если разрешения не совпадают.

проблема

Я не чувствую, что это разумное решение. Это означает, что разрешения разрешаются в двух точках (одна в ядре, поскольку они все еще применяются) и в моих фильтрах.

В идеале это было бы на уровне конфигурации, а именно там, где определены пользовательские типы записей.

Другими словами, я бы предпочел , чтобы пройти в правилах (вдоль линий exclude_from_search, publicly_queryableи т.д.) , а не выполнение после запроса «чик».

Текущее решение (работает, но не желательно)

access.php

class Access
{
    function __construct($permissions) {
        $this->permissions = $permissions;
    }

    protected function hasId($request) {
        return ! is_null($request->get_param('id'));
    }

    protected function resolveType($request) {
        $method = strtoupper($request->get_method());

        if($method === 'GET' && $this->hasId($request)) {
            return 'show';
        } else if($method === 'GET') {
            return 'index';
        } else if($method === 'DELETE') {
            return 'delete';
        } else if($method === 'POST') {
            return 'create';
        } else if($method === 'PATCH') {
            return 'update';
        }
    }

    function validate($type, $request) {
        return in_array($this->resolveType($request), $this->permissions[$type]);
    }
}

functions.php

// bootstrap the permissions for this particular 
// application
// 
$access = new Access([
    'vocabulary' => ['show'],
]);

add_filter('rest_prepare_vocabulary', 'validate_permissions', 30, 3);
function validate_permissions($response, $post, $request) {
    global $access;

    // Give access->validate the type + request data 
    // and it will figure out if this is allowed
    //
    if( ! $access->validate($post->post_type, $request)) {
        $response->set_data([]);
        $response->set_status(403);
    }

    return $response;
};
Крис
источник
1
Почему вы были созданы Accessв глобальном масштабе? Вам это нужно в другом месте? Если вы ответите « да» , вы можете вместо этого присоединить его к фильтру.
Кайзер
3
Справедливый вопрос. Выше приведен фрагмент кода, я использую автозагрузку composer и PSR4 для отрисовки модулей класса в родительский класс приложения, в котором будет находиться приведенный выше фрагмент, так что на самом деле это не глобальный глобал, а пространство имен \Appи доступ на самом деле\App\Services\Access
Крис
1
Я сам не исследовал эту проблему, но вы проверили Trac на наличие билета или создали его, если он не существует? Звучит как разумная особенность иметь ...
kraftner
1
Я не очень понимаю проблему. «Это означает, что разрешения разрешаются в двух точках (одна в ядре, так как они все еще применяются) и в моих фильтрах. В идеале это будет на уровне конфигурации, а именно там, где определены пользовательские типы записей». Можете ли вы уточнить, что вы имеете в виду здесь? Извините, если я тупой!
Джим Магуайр,
2
Я опускаю этот вопрос. Я не понимаю, почему 18 человек проголосовали за это. Это непостижимо.
Джим Магуайр,

Ответы:

1

Я просмотрел источник, и из того, что я вижу, нет никаких хуков / фильтров, которые можно было бы использовать для изменения разрешений.

Насколько я понимаю, это было намеренное дизайнерское решение.

Несмотря на то, что REST API был создан для расширения, не рекомендуется изменять основные конечные точки так, как вы запрашиваете.

В этом разделе справочника по API REST имеется некоторая ограниченная информация , но суть в том, что по мере старения API больше кода (будь то основной или сторонний) начнет зависеть от конкретных действий, доступных и обеспечивающих стандарт ответы.

Вместо этого вы должны создать собственный контроллер.

Пользовательские типы записей могут быть заданы пользовательским контроллером, указав имя класса в rest_controller_classаргументе дляregister_post_type() .

Обзор того, как должны работать пользовательские контроллеры, можно найти в справочнике по REST API .

Следует также помнить, что если вы создадите пользовательский контроллер, который расширяет абстрактный WP_REST_Controllerкласс для типа записей, который поддерживает ревизии, будет автоматически создано несколько конечных точек ревизий для конкретных типов постов.

Если он не расширяет WP_REST_Controllerкласс, register_routes()метод не вызывается, поэтому вам придется вручную зарегистрировать свои собственные маршруты.

ssnepenthe
источник