Я стремлюсь ограничить некоторые глаголы 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;
};
Access
в глобальном масштабе? Вам это нужно в другом месте? Если вы ответите « да» , вы можете вместо этого присоединить его к фильтру.\App
и доступ на самом деле\App\Services\Access
Ответы:
Насколько я понимаю, это было намеренное дизайнерское решение.
Несмотря на то, что REST API был создан для расширения, не рекомендуется изменять основные конечные точки так, как вы запрашиваете.
В этом разделе справочника по API REST имеется некоторая ограниченная информация , но суть в том, что по мере старения API больше кода (будь то основной или сторонний) начнет зависеть от конкретных действий, доступных и обеспечивающих стандарт ответы.
Вместо этого вы должны создать собственный контроллер.
Пользовательские типы записей могут быть заданы пользовательским контроллером, указав имя класса в
rest_controller_class
аргументе дляregister_post_type()
.Обзор того, как должны работать пользовательские контроллеры, можно найти в справочнике по REST API .
Следует также помнить, что если вы создадите пользовательский контроллер, который расширяет абстрактный
WP_REST_Controller
класс для типа записей, который поддерживает ревизии, будет автоматически создано несколько конечных точек ревизий для конкретных типов постов.Если он не расширяет
WP_REST_Controller
класс,register_routes()
метод не вызывается, поэтому вам придется вручную зарегистрировать свои собственные маршруты.источник