Avec Rest V2 (WP4.7) comment restreindre certains verbes RESTFUL?


20

Je vise à restreindre certains verbes RESTUL par type de publication personnalisé. Par exemple, étant donné un type de message personnalisé de vocabulaire, je voudrais dire:

Matrice des autorisations

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

Le V2 ne semble pas fournir ce niveau de contrôle. J'ai parcouru la source, et d'après ce que je peux voir, il n'y a pas de crochets / filtres pour exploiter les autorisations changeantes.

Ma solution actuelle est la suivante. Il compromet une classe où vous pouvez charger dans une matrice de types de publication personnalisés contre les actions autorisées. Cela peut ensuite être appelé dans le rest_prepare_vocabularyfiltre, détruisant la réponse si les autorisations ne s'alignent pas.

Problème

Je ne pense pas que ce soit une solution raisonnable. Cela signifie que les autorisations sont résolues à deux endroits (un, dans le noyau, car ils sont toujours appliqués) et dans mes filtres.

Idéalement, ce serait au niveau de la configuration, à savoir où les types de publication personnalisés sont définis.

En d' autres termes, je préférerais passer dans les règles ( le long des lignes de exclude_from_search, publicly_queryable, etc.) plutôt que d' effectuer une requête post « snip ».

Solution actuelle (fonctionne mais n'est pas souhaitable)

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
Pourquoi avez-vous instancié Accessdans la portée mondiale? En avez-vous besoin ailleurs? Si vous répondez par oui , vous voudrez peut-être le joindre à un filtre.
kaiser

3
Juste question - Ce qui précède n'est qu'un extrait de code, j'utilise le chargement automatique de compositeur et PSR4 pour dessiner des modules de classe dans une classe d'application parente, dont l'extrait ci-dessus serait dans - donc ce n'est pas réellement global global, ce serait l'espace de noms \Appet l'accès est en fait\App\Services\Access
Chris

1
Je n'ai pas enquêté sur ce problème moi-même, mais avez-vous vérifié Trac pour un ticket ou en avez-vous créé un s'il n'existe pas?
Cela

1
Je ne comprends pas vraiment le problème. "Cela signifie que les autorisations sont résolues à deux endroits (un, dans le noyau, car ils sont toujours appliqués) et dans mes filtres. Idéalement, ce serait au niveau de la configuration, à savoir où les types de messages personnalisés sont définis." Pouvez-vous éventuellement clarifier ce que vous voulez dire ici? Désolé si je suis stupide!
Jim Maguire

2
Je sous-vote cette question. Je ne comprends pas pourquoi 18 personnes l'ont voté. C'est incompréhensible.
Jim Maguire

Réponses:


1

J'ai parcouru la source, et d'après ce que je peux voir, il n'y a pas de crochets / filtres pour exploiter les autorisations changeantes.

Je crois comprendre que c'était une décision de conception intentionnelle.

Bien que l'API REST ait été conçue pour être extensible, il n'est pas recommandé de modifier les points de terminaison principaux comme vous le demandez.

Il existe des informations limitées disponibles dans cette section du manuel de l'API REST , mais l'essentiel est que, à mesure que l'API vieillit, plus de code (qu'il soit principal ou tiers) commence à dépendre d'actions spécifiques disponibles et fournissant des normes réponses.

Au lieu de cela, vous devez créer un contrôleur personnalisé.

Les types de publication personnalisés peuvent recevoir un contrôleur personnalisé en spécifiant un nom de classe dans l' rest_controller_classargument deregister_post_type() .

Vous trouverez une vue d'ensemble du fonctionnement des contrôleurs personnalisés dans le manuel de l'API REST .

Une autre chose à garder à l'esprit est que si vous créez un contrôleur personnalisé qui étend la WP_REST_Controllerclasse abstraite pour un type de publication qui prend en charge les révisions, un certain nombre de points de terminaison de révision spécifiques au type de publication seront automatiquement créés.

S'il n'étend pas la WP_REST_Controllerclasse, la register_routes()méthode n'est pas appelée, vous devrez donc enregistrer manuellement vos itinéraires personnalisés.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.