Le 26/02/2013 23:03, Francis a écrit :
> Un model ne peut pas savoir qui est l'utilisateur actuel, c'est le
> boulot du controlleur.

Non, par contre il doit savoir qui le modifie s'il veut pouvoir faire
son boulot (implémenter les règles métier qui le concerne et donc en
particulier le contrôle d'accès). Ou alors il ne faut jamais faire de
model.save dans un contrôleur mais appeler un objet intermédiaire qui
sait faire le contrôle d'accès, mais ça risque de devenir lourd très
rapidement.

Confier le boulot au modèle permet de l'utiliser en-dehors d'un
contrôleur sans court-circuité les contrôles d'accès et/ou d'éviter de
dupliquer le code de vérification entre les contrôleurs (dupliquer c'est
mal, mais quand en plus c'est du code qui gère les droits d'écriture sur
les objets de l'application c'est dangereux).

Donc à mon sens le contrôleur doit au minimum demander au modèle de
valider que l'objet qui va le modifier (l'acteur) en a le droit avant de
faire le save. Je suis même partisan d'aller plus loin pour éviter les
erreurs de codage : un modèle balance une SecurityError si on ne lui a
pas passé un acteur adéquat.

Comme je n'avais rien trouvé qui faisait ça il y a 6/7 ans quand je me
suis penché sur le sujet, j'ai codé un module qui lorsqu'il est inclus
dans un modèle ajoute :
- un "attr_accessor :actor",
- quelques méthodes en plus pour tester un acteur sans faire le save
(typiquement pour pouvoir déterminer si une fonctionnalité est
disponible à un acteur),
- un appel d'une méthode writable_by? avec l'acteur stocké dans le
modèle dans la chaîne de validation qui permet au dev d'implémenter les
validations concernant les droits d'accès.
Comme indiqué plus haut par défaut (:actor => nil) ça ne passe pas et
balance une SecurityError avec un message destiné à être mis en log (le
codeur du hook a pour responsabilité de lever une SecurityError aussi si
l'acteur passé n'est pas valide). Le coe de writable_by? ressemble en
général à une whitelist, mais c'est du code quit peut en pratique tester
ce qu'on veut. En particulier j'ai du code qui vérifie pour certains
modèles si des attributs précis ont changé pour n'autoriser cette
opération qu'à certains rôles...

À partir de ce principe il y a des raffinements pour rendre ça robuste
et un minimum intrusif pour les utilisateurs des modèles (de tête) :
* :actor est réinitialisé à chaque save (le comportement par défaut est
de refuser le save sans valeur dans :actor), il est protégé contre le
mass assignment, ...
* les associations sont gérées également en permettant plusieurs options
selon les règles métiers les concernant lorsqu'ils sont également sauvés :
- passer l'acteur initial aux modèles associés,
- passer le modèle en tant qu'acteur aux modèles associés,
- court-circuiter la validation de l'acteur pour les modèles associés.
- ...
* un "super-acteur" unique qui a tous les droits (ce qui permet de
facilement trouver à quels endroits dans le code les contrôles sont
court-circuités), en pratique c'est surtout utilisé dans les tests
unitaires qui n'ont pas pour but de vérifier la gestion des droits.

Ce n'est pas open-source : il a évolué dans le bon sens mais il reste
trop lié au reste du code pour être publiable et j'ai toujours manqué de
temps pour le nettoyer (et l'améliorer).

Lionel

-- 
-- 
Vous avez reçu ce message, car vous êtes abonné au groupe "Railsfrance" de 
Google Groups.
Pour transmettre des messages à ce groupe, envoyez un e-mail à l'adresse 
[email protected]
Pour résilier votre abonnement envoyez un e-mail à l'adresse 
[email protected]
--- 
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes 
Railsfrance.
Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, 
envoyez un e-mail à l'adresse [email protected].
Pour plus d'options, visitez le site https://groups.google.com/groups/opt_out .


Répondre à