Uploaded image for project: 'Moodle'
  1. Moodle
  2. MDL-30593

External database enrolment: All roles are unassigned and reassigned on logon

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Minor
    • Resolution: Duplicate
    • Affects Version/s: 2.1.3
    • Fix Version/s: None
    • Component/s: Enrolments
    • Labels:
      None
    • Database:
      Any
    • Testing Instructions:
      Hide

      Set up a Moodle site using external database enrolments. Create a user and a course, and create an enrolment using the external database. Set the Moodle database to log all queries.

      Log on as the user that was created. Log out. Watch the database log, as the user logs on again. The user's role will be unassigned and then assigned again during the second log on procedure. This should not happen.

      Show
      Set up a Moodle site using external database enrolments. Create a user and a course, and create an enrolment using the external database. Set the Moodle database to log all queries. Log on as the user that was created. Log out. Watch the database log, as the user logs on again. The user's role will be unassigned and then assigned again during the second log on procedure. This should not happen.
    • Workaround:
      Hide

      In enrol/database/lib.php:188, change $r->id to $r->roleid.

      Show
      In enrol/database/lib.php:188, change $r->id to $r->roleid .
    • Affected Branches:
      MOODLE_21_STABLE

      Description

      When a user logs onto a Moodle site that uses the database enrolment plugin, the sync_user_enrolments()-method of the enrol_database_plugin-class is called for that user.

      This method fetches the user's enrolments from the external database and stores them in an array, $enrols. The array-key is courseid, and the corresponding value is an array of roleids that the user has in the given course.

      A foreach-call is used to go through $enrols, and each courseid is processed as follows:

      An enrolment is reactivated or created, if necessary.

      Relevant role assignments of the user on the course context are fetched from Moodle database and stored in $current.

      The role assignments in $current are then compared to $roles, which is an array containing all roles that the user should have on the current course, according to the external database source. This is where things go wrong.

      The code reads (from https://github.com/moodle/moodle/blob/master/enrol/database/lib.php#L187 ):

      foreach ($current as $r) {
          if (in_array($r->id, $roles)) {
              $existing[$r->roleid] = $r->roleid;
          } else {
              role_unassign($r->roleid, $user->id, $context->id, 'enrol_database', $instance->id);
          }
      }

      Instead of checking whether the current roleid ($r->roleid) is found in $roles (from the external db), it checks whether the role assignment id ($r->id) is found in $roles. This will rarely be the same id, so the role is unassigned at this point.

      Afterwards, we loop through $roles to perform the necessary role assignments for the current course. As no role assignments have been registered as existing, all roles are reassigned.

      This bug is not fatal, as the users will always see their courses, but it can put a lot of unnecessary strain on the database.

        Attachments

          Issue Links

            Activity

              People

              • Votes:
                0 Vote for this issue
                Watchers:
                0 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: