Attention : vous consultez actuellement la documentation dédiée aux versions 1.x de Moodle. La documentation pour les versions 2.x de Moodle est consultable ici : Comment les permissions sont calculées ?, celle pour les versions 3.x de Moodle est consultable ici : Comment les permissions sont calculées ? et celle pour Moodle 4.x est consultable là : Comment les permissions sont calculées ?.

« Comment les permissions sont calculées ? » : différence entre les versions

De MoodleDocs
Aller à :navigation, rechercher
(Ajout de liens)
Ligne 22 : Ligne 22 :
* ''false'' signifie que l'utilisateur n'est pas autorisé à effectuer l'action.
* ''false'' signifie que l'utilisateur n'est pas autorisé à effectuer l'action.


===Données utilisées par la fonction===
=== Données utilisées par la fonction ===


Supposons que l'utilisateur UTILISATEUR soit sur le point de tenter un test (CAP = ''mod/quiz:attempt'') dans le contexte d'un module imbriqué quatre niveaux au-dessous du contexte Système.
Supposons que l'utilisateur UTILISATEUR soit sur le point de tenter un test (CAP = ''mod/quiz:attempt'') dans le contexte d'un module imbriqué quatre niveaux au-dessous du contexte Système.
Ligne 40 : Ligne 40 :
La fonction considère les données de permissions suivantes :
La fonction considère les données de permissions suivantes :


* les ''définitions des rôles'' (situées dans le contexte Système),
* les ''[[Définir les rôles|définitions des rôles]]'' (situées dans le contexte Système),
* les ''attributions de rôles'' qui ont été effectuées dans n'importe lequel des cinq contextes concernés,
* les ''[[Attribuer des rôles|attributions de rôles]]'' qui ont été effectuées dans n'importe lequel des cinq contextes concernés,
* les ''dérogations aux rôles'' ayant été définies dans n'importe lequel des contextes, sauf le contexte Système (il n'y a pas de dérogation de rôles possible dans le contexte Système).   
* les ''[[Définir des dérogations aux rôles|dérogations aux rôles]]'' ayant été définies dans n'importe lequel des contextes, sauf le contexte Système (il n'y a pas de dérogation de rôles possible dans le contexte Système).   


Il est à remarquer qu'il peut y avoir plusieurs rôles attribués et/ou plusieurs dérogations définies dans un même contexte.   
Il est à remarquer qu'il peut y avoir plusieurs rôles attribués et/ou plusieurs dérogations définies dans un même contexte.   
Ligne 52 : Ligne 52 :
* les rôles qui ne sont pas attribués à l'utilisateur,
* les rôles qui ne sont pas attribués à l'utilisateur,
* les capacités autres que celles que nous testons et
* les capacités autres que celles que nous testons et
* les permissions qui ne sont pas définies.
* les permissions qui ne sont pas définies.


Cette simplification nous permet de voir chaque rôle ou chaque dérogation comme une ''simple permission'' ayant l'une des valeurs suivantes
Cette simplification nous permet de voir chaque rôle ou chaque dérogation comme une ''simple permission'' ayant l'une des valeurs suivantes
Ligne 85 : Ligne 85 :
=== Représentation des données dans un tableau ===
=== Représentation des données dans un tableau ===


Pour afficher de manière concise les données de permission, nous utilisons un tableau conprenant
Pour afficher de manière concise les données de permission, nous utilisons un tableau comprenant
* une colonne pour chaque attribution de rôle, triées par ordre croissant de profondeur de l'attribution. Les colonnes sont étiquetées avec les noms des rôles ;     
* une colonne pour chaque attribution de rôle, triées par ordre croissant de profondeur de l'attribution. Les colonnes sont étiquetées avec les noms des rôles ;     
* une rangée pour chaque niveau de contexte, triées par ordre croissant de profondeur de l'imbrication. Les rangées sont étiquetées avec le niveau du contexte.
* une rangée pour chaque niveau de contexte, triées par ordre croissant de profondeur de l'imbrication. Les rangées sont étiquetées avec le niveau du contexte.
Ligne 164 : Ligne 164 :
#*Si la somme est nulle, aller à l'étape 3.
#*Si la somme est nulle, aller à l'étape 3.


L'algorithme se termine soit (1) quand un résultat déterminant est obtenu, soit (2) quand la ligne du haut de la première colonne est atteinte sans obtenir de résultat déterminant.
L'algorithme se termine soit :
* quand un résultat déterminant est obtenu,
* quand la ligne du haut de la première colonne est atteinte sans obtenir de résultat déterminant.


=== Application de l'algorithme à notre exemple ===
=== Application de l'algorithme à notre exemple ===
Ligne 198 : Ligne 200 :
La permission calculée est ''A'', la fonction retourne la valeur ''true'', permettant ainsi à UTILISATEUR d'effectuer l'action.
La permission calculée est ''A'', la fonction retourne la valeur ''true'', permettant ainsi à UTILISATEUR d'effectuer l'action.


Cependant, si la permission calculée avait été ''P'' ou ''X'', la fonction n'aurait pas retourné tout de suite ''false''. Elle testerait encore si UTILISATEUR a la capacité ''moodle/site:doanything = A'' (car cette permission a priorité sur toutes les autres). La fonction effectue ce contrôle en s'auto-appelant :
Cependant, si la permission calculée avait été ''P'' ou ''X'', la fonction n'aurait pas retourné tout de suite ''false''. Elle testerait encore si UTILISATEUR a la capacité ''[[Capabilities/moodle/site:doanything|moodle/site:doanything]] = A'' (car cette permission a priorité sur toutes les autres). La fonction effectue ce contrôle en s'auto-appelant :


         résultat final = has_capability(moodle/site:doanything, CONTEXTE, UTILISATEUR);
         résultat final = has_capability(moodle/site:doanything, CONTEXTE, UTILISATEUR);
Ligne 261 : Ligne 263 :
Much to everyone's surprise, the user is still allowed to edit the Lesson!  If you understood this article, you shouldn't be surprised, and you should be able to explain what happened.
Much to everyone's surprise, the user is still allowed to edit the Lesson!  If you understood this article, you shouldn't be surprised, and you should be able to explain what happened.


==Voir aussi ==
== Voir aussi ==


*Discussions [http://moodle.org/mod/forum/discuss.php?d=90140 Logged in: what role am I?] et [http://moodle.org/mod/forum/discuss.php?d=66782 What happens if a user has multiple roles in a course?] dans les forums de Using Moodle (en anglais)
* Les discussions [http://moodle.org/mod/forum/discuss.php?d=90140 Logged in: what role am I?] et [http://moodle.org/mod/forum/discuss.php?d=66782 What happens if a user has multiple roles in a course?] dans les forums de Using Moodle (en anglais)


[[Category:Rôles]]
[[Catégorie:Rôles]]


[[en:How permissions are calculated]]
[[en:How permissions are calculated]]

Version du 28 février 2008 à 08:54

Une des questions posées très fréquemment est : Quelles permissions possède un utilisateur pour un contexte donné ?

Cette page explique la fonction principale de Moodle utilisée pour répondre à cette question. Cette fonction est has_capability(). Elle se trouve dans le fichier lib/accesslib.php. Cette fonction implémente les règles pour calculer la "somme" des permissions de multiples rôles et dérogations. Pour un utilisateur donné, une capacité, et un contexte, la fonction renvoi true (vrai) si l'utilisateur est autorisé à effectuer l'action contrôlée par la capacité dans le contexte donné, et false (faux) sinon.

Cette page est écrite autant pour les non programmeurs que pour les programmeurs. Elle décrit ce que la fonction fait, pas comment. Le comment est compliqué, alors que le quoi est relativement simple !

Remarquez que la fonction n'essaie pas de répondre à la grande question posée dans la première phrase de cette page. Elle répond plutôt à la petite question Un utilisateur peut-il ici faire l'action correspondant à la capacité CAP ? Moodle ne calcule jamais la totalité des permissions d'un utilisateur. Une telle opération serait très coûteuse et n'apporterait pas grand chose, puisque la plupart des permissions ne seraient jamais testées. Moodle calcule donc les permissions à la demande. Moodle ne place pas en cache les permissions calculées, mais les recalcule chaque fois qu'il est nécessaire de les tester. C'est la raison pour laquelle les attributions de rôles et les dérogations prennent effet immédiatement (ce n'était pas le cas dans Moodle 1.7).

Le calcul

La fonction est appelée ainsi :

   has_capability(CAP,CONTEXTE,UTILISATEUR);
  • CAP est la capacité testée (par exemple mod/quiz:attempt)
  • CONTEXTE est le contexte Système ou tout autre contexte imbriqué de façon arbitraire dans le contexte Système. À l'interne, la fonction utilise une notation analogue à celle des chemins d'accès des fichiers Unix pour représenter les contextes (par exemple, /1/3/4/150). De tels détails ne sont pas nécessaires dans cette discussion.
  • UTILISATEUR est l'utilisateur.

La fonction retourne un résultat vrai/faux :

  • true signifie que l'utilisateur est autorisé à effectuer l'action ;
  • false signifie que l'utilisateur n'est pas autorisé à effectuer l'action.

Données utilisées par la fonction

Supposons que l'utilisateur UTILISATEUR soit sur le point de tenter un test (CAP = mod/quiz:attempt) dans le contexte d'un module imbriqué quatre niveaux au-dessous du contexte Système.

     Système
        |
    Catégorie A
        |					      
   Sous-catégorie B
        |
      Cours
        |
      Test  <--- l'utilisateur est ici

Le module Test fera appel à la fonction has_capability() pour déterminer s'il doit permettre à l'utilisateur d'effectuer cette action.

La fonction considère les données de permissions suivantes :

  • les définitions des rôles (situées dans le contexte Système),
  • les attributions de rôles qui ont été effectuées dans n'importe lequel des cinq contextes concernés,
  • les dérogations aux rôles ayant été définies dans n'importe lequel des contextes, sauf le contexte Système (il n'y a pas de dérogation de rôles possible dans le contexte Système).

Il est à remarquer qu'il peut y avoir plusieurs rôles attribués et/ou plusieurs dérogations définies dans un même contexte.

La permission pour l'utilisateur de tenter le test ou non dépend des données ci-dessus, ainsi que de l'emplacement de ces données dans la chaîne des contextes.

La fonction has_capability() considère tous les rôles et toutes les dérogations ayant un impact sur UTILISATEUR dans CONTEXTE, mais elle ignore toutes les capacités autres que CAP. Elle ignore notamment :

  • les rôles qui ne sont pas attribués à l'utilisateur,
  • les capacités autres que celles que nous testons et
  • les permissions qui ne sont pas définies.

Cette simplification nous permet de voir chaque rôle ou chaque dérogation comme une simple permission ayant l'une des valeurs suivantes

   N - Non défini
   A - Autoriser
   P - Empêcher
   X - Interdire

Pour indiquer la permission associée à un rôle, nous utilisons la notation suivante : Si le rôle R1 a la permission P, nous écrivons R1(P).

Un exemple

Dans l'exemple de notre test, nous admettons que UTILISATEUR a quatre rôles : R1, R2, R3 et R4, et que chaque rôle a été attribué ou qu'une dérogation a été définie ainsi :

   0     Système         <---- Définition des permissions R1(A), R2(N), R3(N), R4(P)
            |                  Attribution du rôle R1
            |
   1    Catégorie A      <-------------- Définition des dérogations R1(N) et R4(N)
            |                          
            |                          
   2  Sous-catégorie B   <---- Attribution des rôles R2 et R3
            |
            |
   3      Cours          <-------------- Définition des dérogations R2(X) et R3(A)
            |
            |
   4      Test           <---- Attribution des rôles R4 et R1

Il est à remarquer que le rôle R1 a été attribué dans deux contextes distincts. C'est une pratique inhabituelle, vraisemblablement une erreur, mais comme c'est autorisé dans Moodle, nous devons considérer cette possibilité qui pourrait survenir. En réalité, cet exemple a été construit afin d'explorer les cas limites de l'algorithme. Dans la pratique, le calcul des permissions est trivial et la fonction calcule le résultat que le bon sens et une simple analyse suggèrent (pour une discussion plus complète sur ce sujet, voir Une remarque au sujet de l'algorithme à la fin de cette page).

Représentation des données dans un tableau

Pour afficher de manière concise les données de permission, nous utilisons un tableau comprenant

  • une colonne pour chaque attribution de rôle, triées par ordre croissant de profondeur de l'attribution. Les colonnes sont étiquetées avec les noms des rôles ;
  • une rangée pour chaque niveau de contexte, triées par ordre croissant de profondeur de l'imbrication. Les rangées sont étiquetées avec le niveau du contexte.

Dans l'exemple du test, R1 est attribué dans le contexte Système. On le place donc dans la 1ère colonne. Les rôles R2 et R3 sont attribués dans le deuxième plus haut contexte. Ils sont donc placés dans les deux colonnes suivantes (leur ordre n'importe pas). Les rôles R4 et R1 sont attribués dans le contexte le plus bas. Nous les plaçons donc en dernier (ici encore, leur ordre n'importe pas). Voici donc notre tableau avec les colonnes et les rangées et leurs étiquettes :

        R1   R2   R3   R4   R1
     +------------------------
   0 |
   1 |
   2 |
   3 |
   4 |

Nous ajoutons des lignes verticales pour grouper les attributions de rôle effectuées dans le même contexte.

        R1   R2   R3   R4   R1
     +-----+---------+--------
   0 |     |         |
   1 |     |         |
   2 |     |         |
   3 |     |         |
   4 |     |         |

Nous pouvons maintenant incorporer au tableau les données de permission. Dans la première rangée, nous plaçons les permissions indiquées dans la définition des rôles.

        R1   R2   R3   R4   R1
     +-----+---------+--------
   0 |  A  | N    N  | P    A
   1 |     |         |
   2 |     |         |
   3 |     |         |
   4 |     |         |

Le reste des données provient des dérogations. Nous plaçons la valeur de chaque dérogation dans

  • la colonne correspondant au rôle pour lequel la dérogation est effectuée ;
  • la rangée correspondant au niveau dans lequel la dérogation est effectuée.

Commençons par ajouter l'une des dérogations :

        R1   R2   R3   R4   R1
     +-----+---------+--------
   0 |  A  | N    N  | P    A
   1 |     |         |
   2 |     |         |
   3 |     | X       |
   4 |     |         |

Le X représente la dérogation du rôle R2 effectuée dans le contexte du cours. Ajoutons maintenant le reste des dérogations :

        R1   R2   R3   R4   R1
     +-----+---------+--------
   0 |  A  | N    N  | P    A
   1 |  N  |         | N    N
   2 |     |         |
   3 |     | X    A  |
   4 |     |         |

Le tableau est maintenant complet. Nous pouvons calculer la permission.

L'algorithme

L'algorithme parcourt le tableau de droite à gauche (en commençant par la colonne à l'extrême droite du tableau) et de bas en haut (ligne après ligne, en commençant par la ligne du bas). Les colonnes représentant des attributions de rôles effectuées dans le même contexte (i.e. celles qui ne sont pas séparées par une ligne verticale) sont traitées ensemble. L'algorithme se termine dès qu'une permission effective est obtenue.

Dans le tableau de notre exemple, nous considérons donc la suite de permissions ou groupe de permissions suivant :

   (N  N) -> (P  A) -> (X  A) -> (N  N) -> (N) -> (A)

Voici comment fonctionne l'algorithme :

  1. Si le tableau contient un X, STOP. La permission calculée est X.
  2. Commencer au bas de la dernière colonne.
  3. Si nous sommes en haut de la première colonne, STOP. La permission calculée est P.
  4. Sinon, passer à la permission suivante ou au groupe de permission suivante.
  5. Additionner les permissions du groupe en prenant les valeurs numériques suivantes : N = 0, A = +1, P = -1.
    • Si la somme est positive, la permission calculée est A ; STOP.
    • Si la somme est négative, la permission calculée est P ; STOP.
    • Si la somme est nulle, aller à l'étape 3.

L'algorithme se termine soit :

  • quand un résultat déterminant est obtenu,
  • quand la ligne du haut de la première colonne est atteinte sans obtenir de résultat déterminant.

Application de l'algorithme à notre exemple

Si nous appliquons l'algorithme avec les données de notre exemple, nous nous arrêtons tout de suite à l'étape 1 avec une permission calculée X. Pour rendre l'exemple plus intéressant, remplaçons le X par un P' :

        R1   R2   R3   R4   R1
     +-----+---------+--------
   0 |  A  | A    P  | P    A
   1 |  N  |         | N    N
   2 |     |         |
   3 |     | P    A  |
   4 |     |         |

et effectuons maintenant les étapes de l'algorithme.

  • Il n'y a pas de X dans le tableau.
  • Commencer au bas de la dernière colonne.
  • Passer au groupe de permissions suivant.
  • N + N = 0
  • La somme est 0, passer au groupe de permissions suivant.
  • P + A = 0.
  • La somme est 0, passer au groupe de permissions suivant.
  • P + A = 0.
  • La somme est 0, passer au groupe de permissions suivant.
  • A + P = 0.
  • La somme est 0, passer au groupe de permissions suivant.
  • N = 0.
  • La somme est 0, passer au groupe de permissions suivant.
  • A = +1.
  • La somme est non-nulle, STOP. La permission calculée est A.

La permission calculée est A, la fonction retourne la valeur true, permettant ainsi à UTILISATEUR d'effectuer l'action.

Cependant, si la permission calculée avait été P ou X, la fonction n'aurait pas retourné tout de suite false. Elle testerait encore si UTILISATEUR a la capacité moodle/site:doanything = A (car cette permission a priorité sur toutes les autres). La fonction effectue ce contrôle en s'auto-appelant :

       résultat final = has_capability(moodle/site:doanything, CONTEXTE, UTILISATEUR);

Une remarque au sujet de l'algorithme

Earlier, we said that the algorithm "calculates the result you would expect." But what do we expect? Intuition tells us that permissions closer to the user should carry more weight than more distant permissions. That's why we set up the table the way we did and why the algorithm walks the table in the order that it does. The last column of the table represents the role assignment(s) closest to the user. The second-to-last column represents the role assignent(s) that are next in terms of distance from the user, and so-on. That's why the algorithm considers the columns from right-to-left. Within a column, the algorithm searches upward in order to give higher weight to overrides that are closer to the user. Once again, this matches our intuition about overrides. If there are no overrides in a column (or the overrides are all Not set), the permission in the role definition is used.

Un exemple pratique

Suppose that a user, who is assigned the role of Course creator in category B, creates a course (becoming Teacher in the course) and then creates a Lesson within the course. The user is about to edit the lesson (editing lessons is controlled by capability mod/lesson:edit). Here is the permission data:


   0     Système         <---- define Auth user(N), Creator(N), Teacher(A)
            |                  assign Auth user
            |
   1    Catégorie A
            |                          
            |                          
   2  Sous-catégorie B   <---- assign Creator
            |
            |
   3      Cours          <---- assign Teacher
            |
            |
   4      Leçon          <---- user attempts to edit lesson

We set up the table and populate it with permission data.

        AuthUser  Creator  Teacher
     +----------+--------+--------
   0 |     N    |   N    |    A   
   1 |          |        | 
   2 |          |        |
   3 |          |        |       
   4 |          |        |

Since there are no overrides, the table only has data in the first row. The algorithm quickly calculates a permission of A and returns true. The user is allowed to edit the Lesson!

Now suppose Teacher is overridden in the Lesson context with mod/lesson:edit = P. Then the table changes

        AuthUser  Creator  Teacher
     +----------+--------+--------
   0 |     N    |   N    |    A
   1 |          |        |
   2 |          |        | 
   3 |          |        |         
   4 |          |        |    P                

and clearly the user is no longer allowed to edit the Lesson.

But suppose the administrator (or whoever is making the overrides) decided instead to override the Creator role, setting mod/lesson:edit = Prevent in the Categoy B context:

        AuthUser  Creator  Teacher
     +----------+--------+--------
   0 |     N    |   N    |    A
   1 |          |        | 
   2 |          |   P    | 
   3 |          |        |      
   4 |          |        |                       

Much to everyone's surprise, the user is still allowed to edit the Lesson! If you understood this article, you shouldn't be surprised, and you should be able to explain what happened.

Voir aussi