API « autoriser »

L’interface de programmation (API) « autoriser » introduite dans SPIP 2.0 permet de gérer finement les autorisations données à un auteur d’effectuer une action sur un objet.

  • Apparu en : SPIP 2.0

Vérifier une autorisation

La vérification d’une autorisation se fait par un appel de la forme :

include_spip('inc/autoriser');
if (autoriser('modifier', 'article', $id_article)) {
...
}

La fonction autoriser($faire, $type, $id, $qui, $opt) accepte 5 arguments dont seul le premier est obligatoire :

  • $faire est une chaîne qui désigne l’action soumise à autorisation. C’est en règle générale un verbe simple (modifier, creer, supprimer, voir, configurer...), parfois associé à un contexte (les mots sont alors collés : changerlangue, publierdans...).
    Il y a quelques exceptions où le $faire n’est pas un verbe et s’utilise sans aucun autre argument (autoriser('webmestre') par exemple, ou autoriser('ecrire') —qui désigne ici l’espace d’administration et non l’action—).
  • $type est une chaîne qui désigne sur quoi porte l’action. C’est en général le type d’un objet éditorial (article, rubrique, mot, groupe-mots, ...).
  • $id désigne l’id (la clé primaire) de l’objet sur lequel porte l’action. $id est en général un nombre entier, mais peut être une chaîne si cela correspond à la clé primaire de la table SQL concernée.
  • $qui désigne l’auteur (au sens SPIP) qui va faire l’action. Si il n’est pas fourni (ou null dans l’appel de la fonction autoriser, c’est implicitement l’auteur connecté qui est pris en compte. Sinon $qui peut être l’id_auteur d’un auteur dont on veut vérifier les droits, ou un tableau associatif qui décrit l’auteur (tableau qui contient alors les champs de la table spip_auteurs pour l’auteur concerné)
  • $opt est un tableau associatif de données supplémentaires contextuelles concernant l’action qui sont parfois utilisées par l’autorisation. Par exemple lorsqu’on veut modifier/publier un article, on appellera autoriser('instituer', 'article', $id_article, null, array('statut' => 'publie'))

La fonction autoriser retourne « true » ou « false » en fonction des droits de l’auteur à faire l’action demandée.

Dans un squelette, la vérification d’une autorisation se fait par la balise #AUTORISER.

Donner une autorisation exceptionnelle

Il arrive qu’on ait besoin de faire une action qui sera soumise à autorisation pour un auteur qui normalement n’en a pas le droit. Cela peut se produire, par exemple, dans le cas d’une action programmée qui sera alors exécutée anonymement.

Dans ce cas, il existe un mécanisme via la fonction autoriser_exception qui donne une autorisation exceptionnelle, le temps de réaliser l’action concernée.

include_spip('inc/autoriser');
// donner une autorisation exceptionnelle temporaire
autoriser_exception('modifier', 'article', $id_article);
// réaliser l'action désirée
include_spip('action/editer_objet');
objet_modifier('article', $id_article, array('titre' => 'Nouveau titre'));
// retirer l'autorisation exceptionnelle
autoriser_exception('modifier', 'article', $id_article, false);

La fonction autoriser_exception($faire, $type, $id, $autoriser) prend 4 arguments :

  • $faire avec la même signification que pour autoriser()
  • $type avec la même signification que pour autoriser()
  • $id avec la même signification que pour autoriser()
  • $autoriser qui est un booléen et indique si l’autorisation exceptionnelle est accordée ou non :
    • Lorsque $autoriser vaut « true » ou n’est pas fourni, on accorde une autorisation exceptionnelle : tous les appels suivant à autoriser() avec les mêmes arguments $faire, $type et $id renverront true
    • Lorsque $autoriser vaut « false » cela signifie que l’autorisation revient sous le régime normal et sera vérifiée selon la règle en vigueur (elle peut donc être encore autorisée ou effectivement interdite). Le false n’indique donc pas ici qu’on interdit l’action, mais simplement qu’il n’y a plus d’exception.

Depuis SPIP 4.0 autoriser_exception accepte un argument * en guise d’id :

  • quand on autorise une exception avec *, cela l’autorise pour tout id
  • quand on annule une exception avec *, cela annule toutes les exceptions pour cet objet, même celles qui auraient été posées individuellement avec des ids

Déclarer une nouvelle autorisation

Lorsque la fonction générique autoriser() est appelée, elle cherche une fonction nommée à laquelle déléguer la vérification.

Si aucun $type n’est fourni dans l’appel à autoriser(), la recherche de la fonction se fait dans l’ordre suivant :

  • autoriser_$faire
  • autoriser_$faire_dist
  • autoriser_defaut
  • autoriser_defaut_dist

Si un $type est fourni dans l’appel à autoriser(), la recherche se fait dans l’ordre suivant :

  • autoriser_$type_$faire
  • autoriser_$type_$faire_dist
  • autoriser_$type
  • autoriser_$type_dist
  • autoriser_$faire
  • autoriser_$faire_dist
  • autoriser_defaut
  • autoriser_defaut_dist

Dans les deux cas, la recherche va du plus précis vers le plus général. Cela permet de définir des familles d’autorisation avec une règle générale (pour une action par exemple), que l’on précise ensuite pour certains objets qui suivent une règle différente.

Pour définir une autorisation, il suffit donc de créer une fonction avec l’un des noms de la liste ci-dessus. La fonction recevra en arguments ceux envoyés à la fonction autoriser() et doit renvoyer « true » ou « false ».

On peut définir une autorisation générique. Lorsque c’est une autorisation qui n’est pas encore définie, on la suffixe en général par un _dist qui permet toujours à un webmestre de la surcharger dans son fichier mes_options.php (en déclarant la fonction de même nom, mais sans son suffixe _dist).

Attention : on voit que dans le nom de la fonction, l’ordre de $faire et $type est inversé par rapport à celui de l’appel à autoriser().

À noter également qu’à partir de SPIP 3.0 le $type est présumé correspondre à un objet, et est normalisé lors de l’appel : vérification qu’il correspond bien à un type d’objet et sinon suppression du « s » final. Cela permet d’assurer qu’on appellera bien la bonne fonction d’autorisation même si on utilise un synonyme du $type (syndic au lieu de site par exemple, ou groupes_mot au lieu de groupe_mots qui est une exception de nommage).
Il est cependant possible d’échapper à cette normalisation en préfixant le $type par un ’_’ (underscore) dans l’appel à autoriser(), lorsque cet argument est le nom d’une page de ecrire.

Dans tous les cas, tous les autres caractères ’_’ sont retirés du $type

Ainsi un appel à autoriser('modifier', 'groupes_mots', $id_groupe) délèguera à la fonction autoriser_groupemots_modifier() (ou l’une des variantes selon la règle ci-dessus si cette fonction précise n’existe pas).
Dans les versions antérieures à SPIP 3.0 il convient de toujours faire très attention à bien utiliser le nom de l’objet sans erreur, car sinon l’autorisation par défaut sera appelée ce qui peut conduire à une erreur d’autorisation plus ou moins grave selon le cas.

Exemple de fonction d’autorisation :

/**
 * Autoriser a creer un article :
 * Il faut qu'une rubrique existe et qu'on ait le statut necessaire pour creer
 * 
 * @return bool
 */
function autoriser_article_creer_dist($faire, $type, $id, $qui, $opt) {
	return (sql_countsel('spip_rubriques')>0 AND in_array($qui['statut'], array('0minirezo', '1comite')));
}

Aide au développement

Lors du développement d’un plugin, il peut être utile de comprendre comment sont appelées les autorisations et dans quel ordre d’enchaînement.

Pour cela il suffit d’ajouter la ligne suivante dans le fichier mes_options.php :

define('_DEBUG_AUTORISER', true);

Chaque appel à autoriser() sera alors tracé dans le fichier spip.log avec le nom de la fonction appelée et le résultat qu’elle a retourné.

Auteur cerdic Publié le : Mis à jour : 15/12/23

Traductions : English, français