Bonjour à vous, je suis en train de réaliser un module pour codeigniter avec un système de membres et gestion des permissions par groupes. Cependant je coince au début de mon raisonnement sur le comment gérer les permissions des groupes.

Pour le moment je suis parti comme ceci :

Une table groupes contenant les informations relatives aux groupes, une table group_user contenant l'id du groupe et l'id de l'user et une table group_permissions contenant les permissions du groupe.

Ce qui me manque c'est le comment gérer les permissions des groupes. J'hésite à partir sur un système sérialisé du style news:3;users:1 etc ou news représenterait le controller par exemple et 3 le niveau de permission.

Qu'en pensez vous, est-ce une bonne idée où y aurait-il plus simple ?

5 réponses


Perso je suis plus pour un système avec une table classique users et une table roles['id', 'user_id', 'action']
exemple
[1, 1, 'post.edit,']
[2, 1, 'post.create']

je vérifie avant d'afficher l'écran en question si l'user a les droits. Dans mon cas l'utilisateur 1 peut créer, modifier mais pas supprimer les posts. Et si tu utilises une relation polymorphique tu peux utiliser cette table pour un user, un groupe, un sous-groupe. Mais si tu ne veux gérer que les groupes alors tu crées une table pivot [user, group] et dans mon exemple il ne s'agit plus d'users mais de groupes :)

C'est simple et ca me semble suffisant dans beaucoup de cas

Je ne suis pas fan de ton système de calcul de permissions. On faisait ça à l'époque où nous devions limiter l'usage des disques, mais pour avoir la permission on doit faire des calculs et c chiant :) maintenant on peut se lâcher sur l'espace de stockage autant en profiter :)

Effectivement ça me semble plus simple de cette manière. Mais du coup peut être moins efficace en terme de performance. Et du coup impossible d'associer un utilisateur a plusieurs groupes.

Tu as une table pivot (groups-users), ensuite tu fais de la table que je t'ai donné une table polymorphique (id, table_name, table_name_id, action)

tu vas donc avoir

pivot (user 1 qui est dans groupes 1 et 2)
1 -1
2 -1

droits
1, users, 1 , 'post.edit'
2 users, 1, 'post.create
3 groups, 1, post.edit
4 groups, 1, post.create
5, groups, 1, post.delete
6, groups, 2, image.view

Avec cette méthode, tu peux soit définir un user en tant qu'individu qui peut créer et modifier un post, ET ul est du groupe 1 qui peut créer, modifier et supprimer post, et comme il est du groupe 2 il peut aussi voir les images :)

J'espère avoir été clair, et ce système me semble assez simple et très puissant. En terme de performance je pense que c'est bon.
EN même temps je pense pas que tu auras 100 groupes ou que tu mixeras pour chaque users les 2 (droits personnels et droits de groupes)

J'étais parti sur plus simple mais ça semble encore plus intéressant en effet :)

Mon soucis actuellement c'est pour enregistrer en mémoire les permissions d'un utilisateur pour pouvoir éviter de faire une requête à chaque fois que je veux faire une vérification si l'utilisateur a le droit ou non de réaliser telle action. Je suis parti pour tout stocker dans les sessions mais j'ai peur qu'en terme de sécurité cela soit peu fiable, et puis assez lourd a stocker finalement.

Enfin je ne sais pas.

La vérification est relativement light.
Dans mon exemple, Si tu dois afficher une image tu commences par un

 count(id) de   table_name = 'users' ET user_id = $user_id ET action='image.view'.
     si 0 (donc vérifier si les groupes de l'user ont cette action possible)
         count(id) de table_name ='groups' AND table_name_id IN (pivot (user_id=user_id) ET action='image.view'

          SI > 0 alors fais ton action.
          sinon c'est que ton utilisateur n'a pas la permission

Désolé avec ces saloperies d'ORM je ne sais plus faire de SQL :( mais j'espère que tu comprends le principe.
Perso je ne suis pas pour stocker les données en local, si données sensibles trop faciles à minipuler sauf tout crypter et là le temps que tu pourrais gagner tu risque de le perdre sans compter la difficulté accrue.

Sinon j'ai une idée mais qui me semble lourde et bordélique mais qui peut être plus simple question accès DB. En gros c'est rajouter un champ LONGTEXT dans ta table users. Lorsque tu ajoutes un utisateur, change de groupe, modifie les persmissions, tu vas regénérer pour tous les users une liste de privilèges et tout stocker dans ce champ au format json ou array par exemple.
Ainsi comme tu as toujours $user, tu fais par exemple

si $user['privilèges]['image.view'] alors faire ce que tu veux.

Le soucis est que tout doit être "reconstruit à chaque modification de privilèges d'user ou de groupes (masi bon c'est moins souvent que l'accès)