Permissions de modules

Billet

Dans la version 2.28 de Dotclear, la classe My d'aide aux modules peut gérer complètement leurs permissions.

Depuis quelques versions de Dotclear une aide au développement des modules (plugins et thèmes) est disponible, elle est depuis bien utilisée par les modules de la distribution et par nombre de modules tiers. La version 2.28, complète la classe My en lui ajoutant une nouvelle constante de contexte appelée MODULE. Celle-ci va permettre de supprimer la difficulté d'utiliser des classes dans le fichier _define.php en déplaçant la partie permissions de ce fichier.
Pour déplacer ces permissions et s'affranchir d'appels de classe hasardeux, il suffit d'indiquer dans le fichier _define.php du module qu'on déporte la gestion de permissions, puis dans le fichier My de vérifier ces permissions.

Premier exemple

Exemple du fichier \_define.php du plugin attachments de la distribution :

<?php
use Dotclear\App;

$this->registerModule(
    // ...
    [
        // On indiquait la nécessité des droits usage, content admin ou pages pour utiliser ce plugin
        'permissions' => App::auth()->makePermissions([
            App::auth()::PERMISSION_USAGE,
            App::auth()::PERMISSION_CONTENT_ADMIN,
            initPages::PERMISSION_PAGES,
        ]),
        // ...
    ]
);

Qui deviendra simplement :

<?php
$this->registerModule(
    // ...
    [
        'requires'    => [['pages']],
        // On indique qu'on délègue à la class My la gestion des droits
        'permissions' => 'My',
        // ...
    ]
);

Plus de problème d'appel de classe potentiellement inexistante ici, puisqu'on va tester la disponibilité de module requis avec la directive requires avant de vouloir utiliser sa classe. Mais il faut bien tester les droits qu'on a enlevés, pour cela on va ajouter une règle dans le fichier \src\My.php du module :

<?php
declare(strict_types=1);

namespace Dotclear\Plugin\attachments;

use Dotclear\App;
use Dotclear\Module\MyPlugin;
use Dotclear\Plugin\pages\Pages;

class My extends MyPlugin
{
   // On va gérer des droits particuliers
    public static function checkCustomContext(int $context): ?bool
    {
       // On recherche le contexte de droit
        return match($context) {
            // On utilise le nouveau contexte de droit global pour autoriser un utilisateur avec les droits sur les billets et les pages
            // Attention ici le test demande si on est côté admin avec des droits ou côté public sans besoin de droits !
            self::MODULE => !App::task()->checkContext('BACKEND')
                || (
                    App::blog()->isDefined()
                    && App::auth()->check(App::auth()->makePermissions([
                        App::auth()::PERMISSION_USAGE,
                        App::auth()::PERMISSION_CONTENT_ADMIN,
                        Pages::PERMISSION_PAGES,
                    ]), App::blog()->id())
                ),

            // Pour tous les autres contextes, on laisse les droits par défaut
            default => null,
        };
    }
}

On voit ici que du fait de cette nouvelle gestion, les constantes de module comme les permissions ou les noms de tables de bases de données n'ont plus besoin d'être dans un fichier spécial à la racine du module puisque dorénavant on teste ces permissions après le chargement des modules et donc on a accès à toutes les classes des modules pour les tests. Les constantes de permissions et de tables des modules de la distribution ont donc été déplacés dans leurs classes principales, c'est le cas de Antispam, Blogroll et Pages.

Second exemple

Exemple du fichier \_define.php du plugin tags de la distribution :

<?php
use Dotclear\App;

$this->registerModule(
    // ...
    [
        'permissions' => 'App::auth()->makePermissions([
                    App::auth()::PERMISSION_USAGE,
                    App::auth()::PERMISSION_CONTENT_ADMIN,
                ])',
        // ...
    ]
);

Qui deviendra simplement :

<?php
$this->registerModule(
    // ...
    [
        'permissions' => 'My',
        // ...
    ]
);

Quand au fichier \src\My.php du module, il ne changera pas puisqu'on vérifiait déjà ces droits :

<?php
declare(strict_types=1);

namespace Dotclear\Plugin\tags;

use Dotclear\App;
use Dotclear\Module\MyPlugin;

class My extends MyPlugin
{
    public static function checkCustomContext(int $context): ?bool
    {
        return match ($context) {
            // On indique que la page de gestion et le menu sont autorisés à un utilisateur ayant les droits usage ou content admin
            // On n'a pas eu besoin de changer quoi que ce soit ici
            self::MANAGE, self::MENU => App::task()->checkContext('BACKEND')
                && App::blog()->isDefined()
                && App::auth()->check(App::auth()->makePermissions([
                    App::auth()::PERMISSION_USAGE,
                    App::auth()::PERMISSION_CONTENT_ADMIN,
                ]), App::blog()->id()),

            default => null,
        };
    }
}

Un petit tour dans les fichiers My des plugins de la distribution donnera un bon aperçu des différents cas possibles.

Le contenu de ce document a été écrit suivant le code de la version 2.28 de Dotclear.

La discussion continue ailleurs

URL de rétrolien : https://dotclear.watch/trackback/444