Droits d'utilisation des actions
[copié / collé et synthèse de différents méls par
CharlesNepote]
Besoin fonctionnel
[...] il me semble important de gérer également des droits sur les actions, il ne suffit pas que l'admin technique accorde des droits à un admin fonctionnel sur une page d'administration contenant une action telle que "reinitialiser le mot de passe". Il faut également que l'action ne soit pas accessible à un simple utilisateur, qui pourrait, sinon, l'inclure dans une page de son choix et l'exécuter.
--
DavidDelon
Mille fois oui ! C'est exactement le problème qui se pose pour la sélection de feuille de style : passer par un fichier type switcher.php (que j'ai décrit), peut provoquer un trou de sécurité. Il faudrait donc passer par une action mais accessible seulement par certains utilisateurs.
--
CharlesNepote
En résumé
- Certaines actions ne doivent pouvoir être appelée que par certains utilisateurs.
- Tous les utilisateurs peuvent voir le résultat d'une action (pour autant qu'ils aient accès à la page contenant l'action).
- Une action "protégée" peut-être appelée n'importe où dans un wiki pour autant que l'auteur ait accès à la page et à l'action
- Qui défini les droits d'accès aux actions ? le développeur ? l'administrateur technique ? l'administrateur fonctionnel ?
Cas d'utilisation fonctionnels
Proposition 1 de cas d'utilisation.
- l'utilisateur demande au système de modifier une page
- le système sert la page en mode édition
- l'utilisateur modifie la page [par exemple il ajoute l'appel suivant : {{recentchanges user="CharlesNepote"}}]
- l'utilisateur demande au système de sauver la page
- le système analyse la page
- le système enregistre la page
- [cas alternatif] le système trouve une action sujette à un droit d'accès avec un ticket
- [cas alternatif] le système trouve une action sujette à un droit d'accès sans ticket
- le système controle que l'utilisateur passé en paramètre a le droit d'utiliser l'action
- le système ajoute à l'appel un ticket d'authentification [par exemple : {{recentchanges user="CharlesNepote" ticket="fjfjfjfsryjrygfcukfvg"}} (note : il faut différencier "ticket" des autres attributs)]
- le système enregistre la page
- le système vérifie que le ticket correspond avec le contenu de l'action (?)
- le système enregistre la page
- [cas alternatif] le système remplace l'action par un message informant que l'utilisateur n'a pas le droit...
Ma première proposition me paraît a posteriori bien alambiquée et je pense avoir trouvé une solution beaucoup plus simple.
Proposition 2 de cas d'utilisation.
- 1. l'utilisateur demande au système de modifier une page
- 2. le système sert la page en mode édition
- 3. l'utilisateur modifie la page [par exemple il ajoute l'appel suivant : {{recentchanges}}]
- 4. l'utilisateur demande au système de sauver la page
- 5. le système analyse la page
- 6. le système ne trouve aucune action sujette à droit d'accès et supprime toute acceptation autre que celles vérifiées en 7a (1) ou spécifiées en 9b
- 6a. [cas alternatif] le système trouve une action sujette à un droit d'accès
- 7a. le système vérifie que cette action a été préalablement acceptée dans cette page
- 8a. retour à 5.
- 8b. [cas alternatif 2] le système vérifie que l'utilisateur a bien le droit d'utiliser cette action
- 9b. le système accepte cette action dans la page - retour à 5.
- 9c. le système averti l'utilisateur qu'il n'a pas le droit d'utiliser ou modifier cette action (fin du cas).
- 7. le système enregistre la page (fin du cas).
(1) dans le cas où on a effacé une action sujette à droit d'utilisation, il ne faut pas que l'utilisateur suivant puisse s'en reservir dans cette page.
D'un point de vu fonctionnel, il y a donc deux correspondances à ajouter :
- pour chaque action, les utilisateurs pouvant les utiliser
- pour les pages concernées, les actions acceptées sujettes à droits.
(Les cas d'utilisation que je viens de décrire devraient être assez simple à réaliser. Hors le fichier edit.php, les grosses modifications concernent la création de nouveaux champs ou tables dans la base de données.)
Quelquesoit la proposition de cas d'utilisation, je pense qu'on ne fera pas l'économie, techniquement, d'analyser (parser) la page à chaque enregistrement pour y rechercher les éventuelles actions sujettes à droits d'utilisation. Cela risque de pénaliser un peu les performances au moment de l'enregistrement de la page.
Si vous acceptez la proposition 2, je veux bien essayer de la coder (avec une relecture de David ou Patrick, à moins que vous ne soyez volontaires), mais il faut encore se décider sur une solution pour stocker les correspondances de variables que j'ai indiqué plus haut. Il me semble que dans un premier temps, on peut utiliser la solution d'une nouvelle table formée d'un triplet "à la RDF" contenant :
- <action> "est accessible par" <NomUtilisateur?>
- <NomDePage?> "a pour fonction protégée" <action>
cf.
BaseDeDonneesEvolutive.
Cette solution me parait bien plus simple, ok pour sa mise en place --
DavidDelon
Solutions
J'ai commencé à réfléchir la-dessus.
Je pensais à une solution qui ne demande aucun changement par rapport au système actuel (simplement en considérant les actions comme des pages avec des ACL).
--
PatrickPaul
La solution est séduisante et n'est pas sans rappeler ma proposition de gérer les groupes utilisateurs et groupes de pages... via des pages...
Là aussi je pense qu'il faut bien en discuter. Ce besoin me paraît plus prioritaire que les groupes d'utilisateurs et groupes de pages.
--
CharlesNepote
Bien alors je me met au travail pour les droits sur les actions. --
PatrickPaul
Je pense qu'il y a deux grand types de solutions techniques pour la gestion des droits :
- un appel au contenu d'une page externe (protégée par les ACL et dans laquelle l'action mise en oeuvre est autorisée pour le propriétaire de la page). Par exemple : [[|WikiNi UnePageDeTest]] (à la manière d'un appel du type WikiNiSyndication)
- avantages : mise en oeuvre aisée de ce système ?
- inconvénients : multiplie le nombre de pages ; créé des pages dont le contenu ne sert qu'à alimenter d'autres pages (ces pages n'ont qu'une valeur technique ; elles n'ont a pas de valeur éditoriale), ce qui n'est pas très intuitif pour l'utilisateur
- un chiffrement de l'appel de l'action :
- l'utilisateur qui apelle une action soumise à une droit, utilise une action particulière et ajoute en paramètre son nom d'utilisateur et l'action demandée (avec tous ces paramètres) ; au moment de l'enregistrement de la page, l'application vérifie que l'utilisateur passé en paramètre est bien l'utilisateur qui publie ; lorsque la page est éditée par un autre utilisateur, le contenu de la l'appel apparaît chiffré.
- Exemple de syntaxe : CharlesNepote pourra entrer {{protected action="recentchanges" max="3" username="CharlesNepote"}} ; si UtilisateurBidon? édite la page, il verra {{protected content="e6ahe4kefzy8njdnchh1zfa5fe3gzefef56ezf56qzf5487zgq453gfsgxcva"}} ;
- Autre exemple : CharlesNepote pourra entrer {{action="recentchanges" max="3" username="CharlesNepote"}} ; si UtilisateurBidon? édite la page, il verra {{action="recentchanges" max="3" username="CharlesNepote" passkey="e6ahe4kefzy8njdnch1zfa5fe3gzefef56ezf56qzf5487zgq453gfsgxcva"}} ;
- avantages : s'intègre bien dans la gestion fonctionnelle du site (pas de page supplémentaire)
- inconvénients : possibilité, difficulté de réalisation ?
Dans les deux cas il faut gérer le droit d'accès aux actions en plus : il faut un moyen à l'application de vérifier que
TelUtilisateur? a le droit d'utiliser
TelleAction? (voir :
BaseDeDonneesEvolutive).
Je pense qu'il faut bien prendre le temps de discuter cet aspect parce qu'il va impacter tout le développement futur de
WikiNi.
Je pense aussi qu'il faut qu'on avance sur l'aspect du droit d'accès aux fonctions car cela nous permettra de mettre en place plus facilement l'upload, le choix de plusieurs feuilles de styles, etc.
--
CharlesNepote
Oui, cet aspect de gestion de droits sur les actions est un peu bloquant ... J'avoue que je ne vois pas trop l'interêt de chiffrer l'appel d'une action, du moment que son execution est conditionnée par la possessions des droits adéquats.
Ta proposition de table supplémentaire est séduisante, de toute façon il faudra bien passer par là. J'y réfléchis.
--
DavidDelon
J'avoue que je ne vois pas trop l'interêt de chiffrer l'appel d'une action, du moment que son execution est conditionnée par la possessions des droits adéquats.
C'est pour montrer que c'est bien la personne qui a les droits qui a créé ou modifié l'appel de l'action.
Exemple : 1. En tant qu'utilisateur
CharlesNepote, je fait appel sur cette présente page à une action "feuille_de_style" que j'ai le droit d'utiliser (par exemple {{feuille_de_style style="une_adresse"}}). L'application détecte l'appel à cette action, détecte que c'est bien moi qui ai modifié la page et autorise donc l'enregistrement de cette page (ainsi donc que son affichage ultérieur). 2. Un
UtilisateurBidon? n'ayant pas de droits sur l'action "feuille_de_style" vient modifier cette page : comment l'application détecte-t-elle que ce n'est pas lui qui a écrit {{feuille_de_style style="une_adresse"}} ? doit-elle alors lui interdire de publier toute information sur cette page ?
Ma solution : quand l'application détecte que j'ai (
CharlesNepote) créé l'appel de fonction {{feuille_de_style style="une_adresse"}}, elle ajoute à cet appel ma "signature", cette signature intégrant un "checksum" de la chaîne {{feuille_de_style style="une_adresse"}} : si un autre utilisateur vient modifier la chaîne {{feuille_de_style style="une_adresse" passkey="e6ahe4kefzy8njdnch1zfa5fe3gzefef56ezf56qzf5487zgq453gfsgxcva"}}, l'application détectera que la valeur "passkey" ne signe pas correctement l'action.
(Je vais publier plus tard mes cas d'utilisation).
--
CharlesNepote
Ok, je comprends mieux ce que tu veux dire. --
DavidDelon
Mais je ne sais pas si c'est techniquement réalisable. --
CharlesNepote
Je suggère {{MonAction}} qui lors de la sauvegarde est remplacé par
- Si utilisateur anonyme ayant acces à
MonAction?:
{{MonAction}}
- Si l'utilisateur identifié a accès à
MonAction? par:
{{MonAction sign="EricDelord" hash="645879d2225dcdsssxddddxcxxx"}}
hash=md5(
MonAction?.
EricDelord.md5(password[
EricDelord]))
- Si pas d'accès on remplace par {{MonAction error="no write access"}}
De meme {{MonAction sign="EricDelord" hash="645879d2225dcdsssxddddxcxxx"}} est sauvegardé comme:
- si hash=md5(
MonAction?.
EricDelord.md5(password[
EricDelord]))
par {{MonAction sign="EricDelord" hash="645879d2225dcdsssxddddxcxxx"}}
- Si l'utilisateur identifié a accès à
MonAction? par:
{{MonAction sign="utilisateur" hash="645879d2225dcdsssxddddxcxxx"}}
hash=md5(
MonAction?.Utilisateur.md5(password[utilisateur]))
- Si pas d'accès on remplace par {{MonAction error="no write access"}}
Inconvenient:
- si l'utilisateur change de mot de passe il faut changer tous les hash....
- {{Mon Action}} peut être effacé...mais bon c'est un wiki ;)
--
EricDelord
Sinon pour gérer les droits d'accès, pourquoi ne pas inclure des fonctions pour chaque module d'action:
Actuellement si j'inclus le module Action, j'ai mon buffer de sortie qui est alimenté, pourquoi ne pas créer une structure pour l'ensemble des modules qui soit une bibliotheque de fonctions, ie lorsque j'inclus le module
MonAction?, j'inclue les fonctions:
MonAction_output($what){
switch $what:
case :noaccess
Erreur pas d'acces
case :body
Affichage standard
}
MonAction_hasaccess(privilege)
Cas simple
if (UserIsOwner?) {
}else{
}
Traitement via acls
include_once(acls.php);
je fais ca car je trouve que acls devrait traité comme un module optionnel
return HasAccess?(...)
Ca semble bien modulaire et plus lisible non ?
Quelques idées en vrac par
LordFarquaad:
Pour une gestion simple des actions (et, par extension, des handlers et de tout ce qu'on veut), je serais assez pour une gestion similaire à celle des fichiers sous Unix et Linux:
- Chaque action possède un propriétaie et est liée à un groupe
- Chaque action possède des droits pour
- son propriétaire
- son groupe
- les membres inscrits
- tout le monde
- Ces droits sont de différents types (à définir), a priori on peut envisager (un peu pour rester dans le style de unix)
- droit de lecture (affichage du résultat d'une action)
- droit d'écriture (utilisation de l'action dans une page, c'est à dire vérification lors de la sauvegarde)
- droit d'exécution (interaction avec l'action: envoi d'informations via les méthodes GET/POST)
Au niveau des droits, on peut se contenter du droit de lecture, très simple à programmer (la méthode
Action() n'a qu'à vérifier si la personne a le droit en lecture, et retourner un message d'erreur sinon).
Les deux autres sont plus compliquées:
- pour l'écriture cela implique une vérification lors de la sauvegarde (mes idées plus loin, si j'ai le temps)
- pour l'exécution cela nécessite une vérification à l'intérieur de l'action en elle-même (ce qui implique de modifier les actions concernées...)
Question:
ces deux droits sont-ils vraiment nécessaires ?
- Si une action est réservée aux administrateurs, eux et eux seuls ont le droit d'exécution, et c'est le seul intérêt que présente l'action, donc:
- le droit de lecture serait réservé aux administrateur
- le droit d'écriture ne présente aucun intérêt pour les autres (étant donné que même s'ils placent l'action, ils ne pourront rien en faire...)
- Cela implique que le droit de lecture suffit à règlementer les droits de cette action
- Si une action possède une partie configuration (options etc.) réservées aux administrateurs et une partie visualisation accessible à tous, elle peut certainement être séparée en deux actions:
- l'une réservée à la configuration, et dont le droit en lecture est réservée aux admins
- l'autre réservée à la visualisation, et pouvant consulter les informations de configuration
- Questions: Exemples pratiques ? Est-ce vraiment utile ?
- Si oui: on peut envisager que chaque action puisse stocker des informations sur sa propre configuration, et que chaque action puisse modifier les configurations des autres actions
- Si une action possède une partie visualisation et une partie exécution:
- Exemple pratique: l'ActionTextSearch
- De même que pour le cas précédent, l'action pourrait être séparée en deux
- Question: y a-t-il des actions qui possèdent une partie "exécution" mais dont le seul accès en lecture apporte vraiment quelque chose ? Y aurait-il un intérêt à le restreindre ?
- exemple: le cas de l'ActionTextSearch:
- avoir un simple accès en lecture permet de faire des recherches grâce à ses paramètres (d'après ma définition de la lecture)
- avoir un accès en exécution ne confère aucun droit supplémentaire, il n'y a donc aucun intérêt de le restreindre...
Question:
Comment gérer le propriétaire, le groupe et les droits des actions ?
Réponse: via des actions !
- Ceci permettrait en effet de ne pas restreindre cette possibilité à l'administrateur technique. Ainsi il suffirait de conférer les droits nécessaires sur ces actions de gestion à certaines personnes pour qu'elles s'occupent de tous les droits. Ces personnes seraient en quelque sorte les véritables administrateurs alors que les autres seraient plutôt des "modérateurs".
Extensions possibles:
- plusieurs propriétaires pour une même action
- plusieurs groupes pour une même action
- droits spécifiques à une action (l'action devrait alors être accompagnée d'une interface pour la gestion de ceux-ci)
Comment gérer les groupes ?
- Une table avec un identifiant numérique (groupid) et le noms de chaque groupe (champ groupname) pour chacun (il est plus simple de travailler avec des nombres qu'avec des chaines...)
- Une table de correspondance entre les groupes et les utilisateurs, avec un champ username et un champ groupid
NB.: cela permet en une seule requête simple de tenter (par exemple) de lier un utilisateur à une action:
- SELECT * FROM actions a, users_in_groups uig, users u WHERE a.owner = u.name OR (a.groupid = uig.groupid AND uig.username = u.name)
- (cette requête récupère en un coup tous les utilisateurs ayant des droits sur l'action, en la modifiant un peu, notemment en fonction de l'organisation choisie, on pourrait envisager de chercher uniquement ceux qui ont un droit de lecture [ou autre], ou vérifier si tel utilisateur a un droit en lecture [ou autre])
Si les groupes utilisateurs de chaque groupe sont stockés dans une chaine, il faut soit préocédéer avec des regexp dans la requête, soit procéder en deux requêtes (plus fréquent quand on ne sait pas exactement ce qu'on cherche)... pas glop je trouve...
Les données pourraient certainement être stockées en RSS-like, mais dans le cas présent j'y vois plusieurs inconvéniants:
- Il vaut mieux ne pas mélanger des informations de configuration (nom du site, root_page, navigation_links etc.) avec des informations de gestion et d'organisation. Il vaut mieux réunir des données du même type dans une même table (droits des actions/handlers etc., liste des liens interwiki et comme ça l'est déjà: liste des pages, liste des utilisateurs, ACLs, liens, referrers...). Sinon cela pose plusieurs problèmes:
- difficulté de s'y retrouver dans les données: pour rechercher une information précise l'administrateur technique devra procéder par sélections conditionnelles (c. à d. avec une where_clause)
- pour retrouver une information de configuration dont il a oublié le nom, il se retrouve dans un amas d'autres informations dont il n'a que faire...
- on a un mélange de données de types différents dans une même table, ce qui empêche d'optimiser les champs (type, longueur, indexation etc.) en fonction du contenu.
- Mieux vaut réfléchir à une organisation plus spécifique à ce que l'on veut faire. Dans le cas présent, on veut, pour chaque action:
- un proprio
- un groupe
- les permissions du prorprio
- les permissions pour le groupe
- les permissions pour les membres inscrits
- les permissions pour tous
- ...
- Ces informations se retrouvent pour chaque action, mieux vaut donc avoir un champ pour chacune d'entre elles, optimisé en fonction du type de données.
Cela présente plusieurs avantages:
- simplification des requêtes (pas besoin notemment de travailler plusieurs fois avec la même table dans une même requête)
- réduction du nombre de requêtes (si on n'a pas besoin de requête complexes pour tirer de simples informations, alors on peut faire des requêtes plus complexes pour tirer des informations plus complexes)
- réduction du traitement en php
Et il est toujours possible d'en récupérer le contenu et de le retravailler pour le présenter au format rss !
--
LordFarquaad (
LordFarquaadASuivreEnPriorite)
(je parlerai plus tard de mes idées concernant les droits d'écriture, si je me souviens encore de mes idées --
LordFarquaad)
Opinion d'un utilisateur très peu informaticien.
Plus vous intégrez de choix, plus la combinatoire devient difficile à comprendre par l'utilisateur.
Plus la combinatoire sera informatiquement traitée dans chaque action, plus il y aura de pagaille possible. Risque renouvelé à chaque nouvelle action..
Bon, propositions d'un php-novice ;
Actuellement :
-Config.php contient des droits sur des actions : default_write...comment
-Chaque handler vérifie l'autorisation ex : $this->
HasAccess?("comment")
Généralisons :
-Config.php : chaque action contient une ligne default_action =>"...
-Chaque action vérifie si l'user
HasAccess?("action")...
Pour plus de sureté la vérification de sécurité le vérifie ...
Ca reste simple pour l'utilisateur ET pour le bidouilleur qui veut créer une nouvelle action (c'est la grande force de wikini)
Bon, m'en demandez pas plus question php ! ... ;-o) bonne chance... --
FidelioEspoir