[spip-dev] API de modifs des objets pas générique car autorisations

L'API de modification des objets objet_inserer/modifier/instituer est censée être générique afin de pouvoir appeler uniquement ces fonctions de haut niveau qui font passer automatiquement les modifs dans les pipelines officiels de SPIP. Super.

Sauf qu'à l'intérieur même de certaines, il y a des tests d'autorisations ! Ce qui est par définition non générique, puisque dépendant d'un contexte précis.

autoriser('instituer', $objet, ...

Du coup, il est impossible d'appeler ces fonctions pourtant très propres, pour faire des modifications dans d'autres contextes que ceux par défaut.

Par exemple pour changer le statut d'un objet ça teste si on a le droit : généralement il faut alors être admin ou auteur de l'objet. Et du coup ça interdit la modification *propre* dans un formulaire actionné par des visiteurs anonymes ou de moindre droit. Ou par un script d'ailleurs.

Je ne peux pas appeler :

objet_modifier('article', $id, array('statut' => $truc));

dans un formulaire de mon cru, qui pour telle ou telle condition voudrait changer le statut d'un article (ou d'une patate), et ce peu importe qui actionne ce formulaire.

Je pense qu'il y a un truc qui ne va pas, donc.

À mon avis, il faut dissocier
- les actions unitaires CRUD, qui peuvent être utilisés dans moult contextes qu'on a PAS à prévoir
- et l'action par défaut d'édition d'un objet (action/editer_truc) qui elle doit appeler des autorisations, oui, et qui ensuite appelle les actions de CRUD

Il ne me semble pas anormal que les actions CRUD bas niveau soient elles aussi soumis à autorisation, pour securité.

Avec un autre CMS que j’utilise, et pour lequel le problème que tu évoques se pose régulièrement aussi, le problème se résout de 2 manières (au moins à à connaissance) :

  • par création d’un fichier de “metadonnées” accompagnant notre script maison et indiquant le “passe-droit”
  • notre script lui même déclare un pseudo switch d’utilisateur avant l’exécution du script, et re-switch à l’utilisateur courant dès sa fin. (déclaration de nouvelles permissions le temps de l’exécution)

Juste histoire d’apporter comment un autre CMS s’en sort,
Mais tout ça n’est pas forcément idéal…

Julien

Désolé de revenir à la charge, mais j'ai de nouveau le cas pour au moins deux plugins. À mon avis ce n'est pas du tout un cas bizarre, ça devrait être possible de base.

En effet, j'ai besoin qu'une *tâche programmée*, que ce soit un cron, une date exact, ou au plus tôt, fasse des changements d'institution de plusieurs objets. Plus précisément dans mon cas là, j'ai besoin qu'au bout d'un certain temps, automatiquement, des objets changent de statut.

Or une tâche programmée, cron ou pas, c'est neutre, ça peut être actionné par n'importe qui, souvent par les hits des visiteurs ou par un robot curl sur le serveur.

Mais quand on veut ça, on veut que le changement de statut se fasse bien par objet_instituer(), passant par tous les pipelines, levant des drapeaux pour les plugins, etc ! Pas en écrivant en dur des sql_updateq().

Et pour insister :

1) Non, il n'est pas possible de *simuler* un statut, car il est rigoureusement *impossible* de savoir QUELLE autorisation il faut pour instituer tel objet : l'autorisation peut contenir n'importe quoi, que ce soit par défaut ou par une surcharge, c'est pas du tout forcément le fait d'être admin ou webmaster ou tel statut ! On ne peut donc pas du tout faire de session_set() avant objet_instituer() qui pourrait changer la donne, ça serait juste du hasard.

2) La fonction objet_modifier() elle, n'a aucun test d'autorisation : alors ça veut donc dire que par l'API objet_truc() on aurait le droit de modifier quasiment tous les champs éditables, y compris donc *en modifiant complètement le sens* du contenu de l'objet MAIS on ne peut pas changer son statut ou sa date comme on veut : elle est où la cohérence là ? Soit ya des autorisations partout, soit nulle part !

3) Mieux encore, objet_inserer() permet de l'appeler avec un tableau des champs en paramètre où l'on peut très bien mettre "id_rubrique=123" et "statut=publie", donc ça veut bien dire qu'on peut publier avec cette API de fonctions unitaires... mais pas avec objet_instituer() !

Il faut donc vraiment supprimer ces autorisations dans objet_instituer(), elles n'ont aucun sens.

Si le sens, c'est que objet_instituer() est le plus simple endroit pour savoir si ya à la fois un statut, un parent, etc, alors il faut à minima un cinquième argument "$eviter_autorisation=false" qui lorsqu'il est vrai permet d'inhiber les tests de cette fonction générique, et donc de faire les modifs avec pipelines.

Cela ne casse rien, et laisse le comportement actuel par défaut.
(Mais ça reste quand même n'importe quoi qu'il y ait des autorisations dans une des fonctions et pas dans les autres !)

Gogogo ?

L’API de modification des objets objet_inserer/modifier/instituer est

censée être générique afin de pouvoir appeler uniquement ces fonctions

de haut niveau qui font passer automatiquement les modifs dans les

pipelines officiels de SPIP. Super.

Sauf qu’à l’intérieur même de certaines, il y a des tests

d’autorisations ! Ce qui est par définition non générique, puisque

dépendant d’un contexte précis.

Ces autorisations sont à ce niveaux pour éviter tout risque d’action non autorisée par un auteur.
Je crois que dans le cas de instituer() ça avait été ajouté sur les articles (et rendu generique sur les objets par mimétisme) car il y a des scenarios dans lesquels, dans l’interface, un admin restreint peut arriver à choisir une rubrique qui ne lui est pas autorisée pour un article publié.

De manière générale, ces autorisations à ce niveau me paraissent plutôt saines car elle assurent que même si en amont le dev de plugin n’a pas forcément bien bordé toutes les scenarios et les autorisations dans son interface, cela ne permettra pas in fine de faire quelque chose qui est de toute façon interdit.
De même, cela protège contre des actions malveillantes via hack sur les urls d’actions.

Désolé de revenir à la charge, mais j’ai de nouveau le cas pour au moins deux plugins. À mon avis ce n’est pas du tout un cas bizarre, ça devrait être possible de base.

En effet, j’ai besoin qu’une tâche programmée, que ce soit un cron, une date exact, ou au plus tôt, fasse des changements d’institution de plusieurs objets. Plus précisément dans mon cas là, j’ai besoin qu’au bout d’un certain temps, automatiquement, des objets changent de statut.

Or une tâche programmée, cron ou pas, c’est neutre, ça peut être actionné par n’importe qui, souvent par les hits des visiteurs ou par un robot curl sur le serveur.

Mais quand on veut ça, on veut que le changement de statut se fasse bien par objet_instituer(), passant par tous les pipelines, levant des drapeaux pour les plugins, etc ! Pas en écrivant en dur des sql_updateq().

Oui et précisemment pour ça il y a une fonction autoriser_exception() qui permet de lever une autorisation là où on en a besoin :
http://core.spip.org/projects/spip/repository/entry/branches/spip-3.0/ecrire/inc/autoriser.php#L181

et un exemple d’utilisation :
http://zone.spip.org/trac/spip-zone/browser/plugins/mailsubscribers/trunk/newsletter/subscribe.php#L128

Et pour insister :

  1. Non, il n’est pas possible de simuler un statut, car il est rigoureusement impossible de savoir QUELLE autorisation il faut pour instituer tel objet : l’autorisation peut contenir n’importe quoi, que ce soit par défaut ou par une surcharge, c’est pas du tout forcément le fait d’être admin ou webmaster ou tel statut ! On ne peut donc pas du tout faire de session_set() avant objet_instituer() qui pourrait changer la donne, ça serait juste du hasard.

  2. La fonction objet_modifier() elle, n’a aucun test d’autorisation : alors ça veut donc dire que par l’API objet_truc() on aurait le droit de modifier quasiment tous les champs éditables, y compris donc en modifiant complètement le sens du contenu de l’objet MAIS on ne peut pas changer son statut ou sa date comme on veut : elle est où la cohérence là ? Soit ya des autorisations partout, soit nulle part !

Oui je suis d’accord, il manque un autoriser(‹ modifier ›,$objet,$id_objet) dans les fonctions xxx_modifier()

  1. Mieux encore, objet_inserer() permet de l’appeler avec un tableau des champs en paramètre où l’on peut très bien mettre « id_rubrique=123 » et « statut=publie », donc ça veut bien dire qu’on peut publier avec cette API de fonctions unitaires… mais pas avec objet_instituer() !

exact : ce $set est un ajout récent non releasé, et il faudrait aussi filtrer ce qu’il contient ou gérer les autorisations

Il faut donc vraiment supprimer ces autorisations dans objet_instituer(), elles n’ont aucun sens.

Si le sens, c’est que objet_instituer() est le plus simple endroit pour savoir si ya à la fois un statut, un parent, etc, alors il faut à minima un cinquième argument « $eviter_autorisation=false » qui lorsqu’il est vrai permet d’inhiber les tests de cette fonction générique, et donc de faire les modifs avec pipelines.

Cela ne casse rien, et laisse le comportement actuel par défaut.
(Mais ça reste quand même n’importe quoi qu’il y ait des autorisations dans une des fonctions et pas dans les autres !)

Donc comme tu as compris, je suis plutot pour ajouter les appels à autorisation là où elles manquent.
Mais je pense que cela doit se faire dans la branche dev pour ne pas casser des trucs qui fonctionnent actuellement.

Cédric

Oui et précisemment pour ça il y a une fonction autoriser_exception()
qui permet de lever une autorisation là où on en a besoin :
http://core.spip.org/projects/spip/repository/entry/branches/spip-3.0/ecrire/inc/autoriser.php#L181

et un exemple d'utilisation :
Connexion · GitLab

Aaaaaaaaah ben en voilà un truc *génial*, inconnu du monde... Merci !

Donc comme tu as compris, je suis plutot pour ajouter les appels à
autorisation là où elles manquent.
Mais je pense que cela doit se faire dans la branche dev pour ne pas
casser des trucs qui fonctionnent actuellement.

Ok, et je suis d'accord : cohérence, cohérence !

Bonjour,
Je me permets une intrusion :

Oui et précisemment pour ça il y a une fonction autoriser_exception()
qui permet de lever une autorisation là où on en a besoin :
http://core.spip.org/projects/spip/repository/entry/branches/spip-3.0/ecrire/inc/autoriser.php#L181

et un exemple d'utilisation :
Connexion · GitLab

Aaaaaaaaah ben en voilà un truc *génial*, inconnu du monde... Merci !

C'est très bien décrit ici : API de gestion des autorisations (`autoriser`) - Programmer avec SPIP 4 :wink:

Donc comme tu as compris, je suis plutot pour ajouter les appels à
autorisation là où elles manquent.
Mais je pense que cela doit se faire dans la branche dev pour ne pas
casser des trucs qui fonctionnent actuellement.

Ok, et je suis d'accord : cohérence, cohérence !

Christophe

Super !

Mais personnellement moi-même je je je, n'aurais *jamais* pensé à chercher une documentation de trucs en PHP, de *programmation*, dans le site spip.net.

J'ai donc rajouté ce point sur Programmer SPIP, dans le chapitre qui concerne les autorisations :
http://programmer3.spip.net/Donner-une-autorisation

(PS Marcimat : faudrait peut-être augmenter le nombre de caractères pour les URLs, parce que franchement 30 caractères... on a pas les titres entiers, même lorsqu'ils font juste 4 ou 5 mots...)