Com o Rest V2 (WP4.7), como restringir certos verbos RESTFUL?

20

Meu objetivo é restringir certos verbos RESTUL por tipo de postagem personalizada. Por exemplo, dado um tipo de postagem personalizada de vocabulário, gostaria de dizer:

Matriz de permissão

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

O V2 não parece fornecer esse nível de controle. Passei pela fonte e, pelo que posso ver, não há ganchos / filtros para alterar as permissões.

Minha solução atual é a seguinte. Isso compromete uma classe na qual você pode carregar uma matriz de tipos de postagem personalizados em relação às ações permitidas. Isso pode ser chamado no rest_prepare_vocabularyfiltro, destruindo a resposta se as permissões não estiverem alinhadas.

Problema

Não acho que essa seja uma solução razoável. Isso significa que as permissões estão sendo resolvidas em dois pontos (um, no núcleo, como ainda são aplicados) e nos meus filtros.

Idealmente, seria em um nível de configuração, ou seja, onde os tipos de postagem personalizados são definidos.

Em outras palavras, eu preferiria passar em regras (ao longo das linhas exclude_from_search, publicly_queryable, etc) em vez de executar uma consulta post "snip".

Solução atual (funciona, mas não é desejável)

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;
};
Chris
fonte
11
Por que você instancia Accessno escopo global? Você precisa em outro lugar? Caso você responda sim , você pode anexá-lo a um filtro.
Kaiser
3
Pergunta justa - O acima é apenas um trecho, estou usando o compositor e o PSR4 para carregar automaticamente os módulos de classe em uma classe App principal, da qual o trecho acima estaria - portanto, não é globalmente global, seria um namespace \Appe o acesso é realmente\App\Services\Access
Chris
11
Eu não investiguei esse problema pessoalmente, mas você verificou o Trac quanto a um ticket ou criou um, se ele não existir? Soa como um recurso razoável ter ...
kraftner
11
Eu realmente não entendo o problema. "Isso significa que as permissões estão sendo resolvidas em dois pontos (um, no núcleo, como ainda são aplicados) e nos meus filtros. Idealmente, seria no nível de configuração, ou seja, onde os tipos de postagem personalizados são definidos." Você pode esclarecer o que quer dizer aqui? Desculpe se sou estúpido!
perfil completo de Jim Maguire
2
Estou votando negativamente nesta pergunta. Não entendo por que 18 pessoas votaram positivo. Isso é incompreensível.
Jim Maguire

Respostas:

1

Passei pela fonte e, pelo que posso ver, não há ganchos / filtros para alterar as permissões.

Meu entendimento é que essa foi uma decisão de design intencional.

Embora a API REST tenha sido construída para ser extensível, não é recomendável modificar os terminais principais da maneira que você está solicitando.

Há algumas informações limitadas disponíveis nesta seção do manual da API REST , mas a essência é que, à medida que a API envelhece, mais código (seja ele principal ou de terceiros) começará a depender de ações específicas disponíveis e fornecer padrões respostas.

Em vez disso, você deve criar um controlador personalizado.

Os tipos de postagem personalizados podem receber um controlador personalizado, especificando um nome de classe no rest_controller_classargumento pararegister_post_type() .

Uma visão geral de como os controladores personalizados devem funcionar pode ser encontrada no manual da API REST .

Outra coisa a ter em mente é que, se você criar um controlador personalizado que estenda a WP_REST_Controllerclasse abstrata para um tipo de postagem que suporta revisões, vários pontos de extremidade de revisão específicos do tipo de postagem serão criados automaticamente.

Se não estender a WP_REST_Controllerclasse, o register_routes()método não será chamado, portanto você terá que registrar manualmente suas rotas personalizadas.

ssnepenthe
fonte