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 ?

De MoodleDocs
Aller à :navigation, rechercher

Remarque : la traduction de cet article n'est pas terminée. N'hésitez pas à traduire tout ou partie de cette page ou à la compléter. Vous pouvez aussi utiliser la page de discussion pour vos recommandations et suggestions d'améliorations.


One of the most frequently asked question is: What permissions does a user have in a given context? This article will document the main function in Moodle that is used to answer the question. The function is has_capability_in_accessdata(). It can be found in lib/accesslib.php. The function implements the rules for "summing" permissions from multiple roles and overrides. Given a user, a capability, and a context, the function returns true if the user is allowed to perform the action controlled by the capability in the given context, and false otherwise.

This article is written for non-programmers as well as programmers. It describes what the function does, not how. The how is complicated. The what turns out to be surprisingly simple!

Notice that the function does not attempt to answer the Big Question posed in the first sentence of this article. Instead, it answers the little question "Can some user do C here?" where C is a specific capability. Moodle never computes a user's complete set of permissions. It would be very costly to do so, and also wasteful, since most of the permissions would never be tested. Instead, Moodle computes permissions lazily, i.e., on demand. Moodle does not cache computed permissions, but recomputes them every time they need to be tested. This is why role assignments and overrides no longer have delayed effects, as they did in in Moodle 1.7.

The first part of the function handles role switches. This article describes the second half of the function, which handles the "normal" case.

The function is called as follows:

   has_capability_in_userdata(U,C,X);

Where

  • U is the user
  • C is the capability
  • X is the context

The function returns a true/false result

  • true means the user should be allowed to perform the action
  • false means the user should be prevented from perfoming the action

The context X can be System context or some context nested arbitrarily deeply within System. Internally, the function uses Unix-style paths to represent contexts (e.g., /1/3/4/150), but such details do not concern us here.

Suppose a user is about to attempt a quiz (mod/quiz:attempt) in a module context nested four levels deep within System.

     System
        |
    Category A
        |					      
   Subcategory B
        |
      Course
        |
      Quiz  <--- the user is here


Moodle will call has_capability_in_userdata() to see if the user should be allowed to perform this action.

The function considers the following permissions data:

  • Role definitions (these are in the System context)
  • Role assignments which have been made in any of the five contexts
  • Role overrides which may occur in any of the contexts except System (there is no concept of override in System).

Note that there may be multiple assignments and/or overrides in any single context.

Whether or not the user can attempt the quiz is a function of the data, as well as the location of the data in the context chain.

The function ignores any data that isn't used in the computation. It ignores

  • roles that aren't assigned to the user
  • capabilities other than one we're testing
  • permissions that are Not set.

After ignoring the above data, we are left with a very simple "data slice" consisting of just those permissions for the capability we're testing, in which all values are either Allow (A), Prevent (P), or Prohibit (P*). This data can be represented in a neat tabular form, resembling an addition problem. For our quiz example, suppose we have

   P  A  P
         A
   P  A  P*
   A     P
      P  A
   --------
      ?    

The top row represents the permissions in the role definitions, one permission from each role. In the example, you can see that the user is currently assigned three roles. The remaining rows represent the overrides. In the example, you can see that the user has

  • one override in category A,
  • three overrides in the category B
  • two overrides the course
  • two overrides in the quiz itself.

When representing the problem like this, it is convenient to line up the override permissions under the role that's being overridden, but it is not necessary to do so because we don't "add" permissions in columns the way we add numbers.

We will "add" the permissions in some sense and write the result below the horizontal line. The result, which we call the computed permission, will be either A, P, or P*. The function will return true or false based on the computed permission.

Before we start "adding," check the data to see if it contains a P* anywhere. If it does, we're done. The computed permission is P*. For our example...

   P  A  P
         A
   P  A  P*
   A     P
      P  A
   --------
      P*    <----- computed permission


If there is no P*, the addition algorithm must be used. Unlike normal addition, the addition algorithm

  • starts on the bottom line and works its way up
  • considers one whole line at a time (rather than working in columns)
  • may stop with a result before reaching the top line.

Here is the algorithm:

  1. Start on the bottom line.
  2. If there is only one permission on the line, take its value as the computed permission and STOP
  3. If there are two more permissions on the line, add them using the following numerical equivalents: A = +1, P = -1
    1. If the sum is positive, the computed permission is A. STOP
    2. If the sum is negative, the computed permission is P. STOP
    3. If the sum is zero, the calculation is inconclusive. If this this is already the top line, the computed permission is P; STOP. Otherwise, move to the line above and go to step 2.

Notice that the algorithm stops when either (1) a conclusive result is obtained, or (2) the top line is reached without obtaining a conclusive result.

Let's take our original example, replacing the P* by P to make it more interesting:

   P  A  P
         A
   P  A  P
   A     P
      P  A
   --------
      ?   

Now carry out the steps of the algorithm

  • There are two permissions on line 5
  • Since P + A = 0, the result is inconclusive and we must look at line 4.
  • There are two permissions on line 4.
  • Since A + P = 0, the result is inconclusive and we must look at line 3.
  • There are three permissions on line 3.
  • Since A + P + P = -1 we have a conclusive result! The computed permission is P.
   P  A  P
         A
   P  A  P
   A     P
      P  A
   --------
      P       <----- computed permission

If the computed permission had been A, the function would have returned true without further ado, allowing the user to perform the action.

However if the computed permission is P or P*, the function does not immediately return false. Rather, it tests if the user has moodle/site:doanything = Allow (since this permission trumps all others). The function does this by calling itself:

       final result = has_capability_in_userdata(U,moodle/site:doanything,X);

Voir aussi