使用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_searchpublicly_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在全局范围内实例化?您是否需要其他地方?如果使用yes回答,则可能需要将其附加到过滤器。
kaiser

3
公平的问题-上面只是一个片段,我正在使用composer和PSR4自动加载将类模块绘制到父App类中,上面的片段将在其中-因此它实际上不是global global,而是将其命名为\Appand访问实际上是\App\Services\Access
克里斯

1
我自己尚未调查此问题,但是您是否检查过Trac的票证或是否创建了该票证?听起来像是一个合理的功能……
kraftner

1
我不太了解这个问题。“这意味着权限将在两个位置(一个仍在应用中,在核心位置)和我的过滤器中进行解析。理想情况下,它将在配置级别上进行,即定义自定义帖子类型。” 您能否在这里澄清您的意思?对不起,如果我很傻!
Jim Maguire

2
我正在否决这个问题。我不明白为什么有18个人对此表示反对。这是不可理解的。
吉姆·马奎尔

Answers:


1

我已经浏览了源代码,从我所看到的内容来看,没有任何挂钩/过滤器可用于更改权限。

我的理解是,这是一个故意的设计决定。

尽管REST API的构建是可扩展的,但不建议按照您要求的方式修改核心终结点。

REST API手册的此部分中提供了一些有限的信息,但是要点是,随着API的老化,更多代码(无论是核心还是第三方)将开始取决于可用的特定操作并提供标准回应。

相反,您应该创建一个自定义控制器。

通过在的rest_controller_class参数中register_post_type()指定类名称,可以为自定义帖子类型提供自定义控制器。

REST API手册中提供了有关自定义控制器应如何工作的概述。

还有一点要记住的是,如果您创建了一个自定义控制器,该控制器扩展了WP_REST_Controller支持修订版本的帖子类型的抽象类,则将自动创建许多特定于帖子类型的修订版本端点。

如果未扩展WP_REST_Controller该类,register_routes()则不会调用该方法,因此您将必须手动注册自定义路由。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.