Obsolete:Enrolment rewrite and role tweaks proposal
Note: You are currently viewing documentation for Moodle 1.9. Up-to-date documentation for the latest stable version is available here: Enrolment rewrite and role tweaks proposal.
- 1 Main objectives
- 2 Known problems
- 3 List of changes
- 3.1 New course_participants database table
- 3.2 New enrol plugin instance table
- 3.3 More enrolment plugins and new UIs
- 3.4 New permission evaluation
- 3.5 New simplified UI for permissions overview and overriding
- 3.6 New moodle/course:visit capability
- 3.7 Hidden role assignments not needed
- 3.8 Legacy role concept replaced by role archetypes
- 3.9 Remove all legacy capability tests
- 3.10 Admin role restrictions
- 3.11 New Editor role partially replacing admin role
- 3.12 New global groups tables, capabilities and enrol plugin
- 3.13 Meta courses not needed
- 3.14 Role assignment time restrictions moved to course participation table and plugins
- 3.15 Change unique index in role_assignments
- 3.16 New $USER->participating and $USER->visiting caching
- 3.17 Move role definitions cache from $USER to $SESSION
- 3.18 New functions returning SQL instead of arrays of users and courses
- 3.19 Rewrite stats sql
- 4 Use cases and examples
- 5 Key areas that will benefit
- 6 See also
- Redesign enrolment infrastructure (multiple instances, guest access, participation status, global groups, etc.).
- Better performance and new improvement possibilities (SQL used again instead of functions returning arrays of users or courses).
- Simplify some role and permission aspects.
There are very many ways how to solve all the enrolment and role issues. During 1.7dev phase we made some fundamental decisions before solving of expected enrolment problems. Later it was not possible to make any major design changes mostly due to time constrains during 1.8dev and 1.9dev release cycles. 2.0 is the first and possibly our last chance to solve all known problems.
This document describes a completely different enrolment infrastructure. At present the concept of roles handles most of the enrolment needs, unfortunately there are two major problems, first is performance because we can not use SQL any more to find out who is course participant, second is not enough flexibility needed for all enrolment plugins. Another indirectly related problem is the usability of permission overriding.
- enrolment configuration is stored in course table – often we need to store different configuration for multiple plugin instances in one course
- role assignment table does not have enough room for all course enrolment/participation related data
- negative guest capability – capabilities must be always positive, allowing you to do something; problems on frontpage if guest account used as default role there
- not possible to temporarily suspend user enrolment or all users enrolled through one plugin
- unenrolment removes some user data and settings – it should remove everything or nothing
- usability regressions after migrating activity settings into capabilities
- very complex permission evaluation
- administrator role used for everything, confusing admin role overriding, admin lock-up incidents
- parental access not supported in require_login() and other parts
- global groups not implemented
- graded role in gradebook - role assignment used instead of capability and participation
- extremely slow stats processing on large sites
- meta courses are slow, lack of group support and often misunderstood
- cached role definitions not reused when checking permission of other users
- legacy capabilities and functions still used in many places
List of changes
Please note that majority of these changes can not be implemented separately because they are interdependent due to technical, performance or usability reasons.
New course_participants database table
Table course_participants stores users participating in courses (aka enroled users).
|status||int(10)||0||0 means active enrolment, anything else means inactive (user can not access course) and is defined by plugin|
|enrolid||int(10)||foreign key, references enrol.id|
|userid||int(10)||foreign key, references user.id|
|timestart||int(10)||0||time stamp, start of active participation period|
|timeend||int(10)||2147483647||time stamp, end of active participation period, max date used for performance reason|
|modifierid||int(10)||last user who modified enrolment, references user.id|
|timemodified||int(10)||timestamp, last modification|
New enrol plugin instance table
Table enrol stores information about enrolment plugins used in course, includes plugin configuration data and status.
|name||char(255)||optional plugin instance name, useful when multiple instances of the same plugin used in course|
|enrol||char(20)||enrolment plugin name|
|status||int(10)||0||0 means active plugin, anything else means inactive (user can not access course) and is defined by plugin|
|courseid||int(10)||foreign key, references course.id|
|lockedroles||int(1)||1||flag indicating role assignments added by this plugin can not be removed manually or by any other plugin|
|enrolperiod||int(10)||0||optional default enrolment period, in seconds|
|enrolstartdate||int(10)||0||timestamp, optional default enrolment start date|
|enrolenddate||int(10)||0||timestamp, optional default enrolment end date|
|password||char(255)||optional enrolment password|
|cost||char(20)||optional cost field|
|currency||char(3)||optional currency field|
|roleid1||int(10)||general optional field|
|roleid2||int(10)||general optional field|
|customint1||int(10)||general optional field|
|customint2||int(10)||general optional field|
|customchar1||char(255)||general optional field|
|customchar2||char(255)||general optional field|
|customtext1||text||general optional field|
|customtext2||text||general optional field|
|timecreated||int(10)||timestamp, date when instance created|
|timemodified||int(10)||timestamp, date when instance last modified|
Course table does not contain any enrolment related fields any more.
More enrolment plugins and new UIs
- guest - Guest user access, temporary user guest access, optional password protection (no entry in course_participant table)
- self - optional password, enrolment duration, role selection, group keys enabled, new self-enrolments allowed
- manual - manual enrolments (usually done by teachers and admins that have "enrol/manual:enrol" capability)
- globalgroups - maps global groups to course groups and enrols users from global groups, assigns roles to users in global groups
- parent - allows parents to access courses children are participating in, similar to guest access, user is not real participant (no entry in course_participant table)
Screenshot above shows refactored course edit form. Each plugin usually has own field set. Enrol plugins should use the same UI as auth plugins both for general configuration and course presets.
New permission evaluation
Change evaluation algorithm, instead of aggregation caps from all roles in each step, calculate resulting capability for each role and use OR logical operation on the result. The prohibit would work the same way as before.
See Development:Role overrides revisited for more details and examples.
New simplified UI for permissions overview and overriding
- Should give overview of all permissions in context without going through several other pages.
- Hopefully easier to understand for normal teachers.
- Supports read only mode, safe and normal overrides.
- All actions require confirmations, it is also possible to display extra explanation. For example using prohibit for Authenticated users. Extra warning before allowing caps with XSS risk.
- Dangerous overrides in roles with student/guest/authenticated archetypes may be highlighted (major security improvement).
The current override page would be still used in advanced mode because it has more detailed information (especially when inheritance is involved).
New moodle/course:visit capability
User can access course (require_login() function) if there is an active participation record, if enrol/parent plugin grants temporary guest access or when user has moodle/course:visit capability.
The capability replaces often abused doanything capability or hidden role assignments with moodle/course:view capability.
Hidden role assignments not needed
The hidden role feature was introduced because we needed a way to hide managers and inspectors assigned above the course context on the course participation page and user profile.
Replace by combination of course participation and new course inspect capability. Instead of ignoring hidden role assignments we could just display role relevant to course participation (obtained from enrol plugin instances). New capability moodle/role:viewall would enable some users to see all role assignments including those granted above course context or user not participating in course. Another option is to manually select which roles are "public" in course participation and profile (new field in course table).
Questions and potential problems:
- Are hidden role assignments used for any other purposes?
- Are there any other places except participation page and user profile where we show roles of participants?
Legacy role concept replaced by role archetypes
Legacy capabilities were originally intended as a temporary solution for backwards compatibility with old code. Internally the code allows allowing multiple legacy caps in one role, it is prevented in UI now.
Later we realised that we need them for other purposes too:
- new capabilities during upgrade
- role resetting
- admin settings
The word "legacy" is often confusing and a bit hard to explain, because ideally it should be used only for non-legacy purposes above.
The proposal here is to use word archetype instead of legacy and store the archetype flag directly in roles table. Benefits are better usability and it also helps fixing of legacy issues too.
Remove all legacy capability tests
Including isguest(), replaced by course participation concept and role archetypes. Major reason for keeping of legacy capability checks were the shortcomings in current enrolment/roles code, all of these should be finally solved.
Admin role restrictions
- only one admin role allowed - all admin roles are the same because the have do anything
- doanything capability allowed only in admin role - giving do anything in subcontexts or other roles is restricted in UI already
- Admin role can not be deleted - there were reported many accidents
- Admin role can not be overriden - do anything has to win, we need to prevent admin lockouts
- Admin role can be assigned in system contex only (Manager role used in other contexts)
- Admin role must be assigned to at least one user
- We might also use admin role archetype instead of doanything capability
- simplified code
- better usability
- no lock-up accidents
New Editor role partially replacing admin role
Admin role is not suitable for everyday tasks and teaching for the same reasons why we are not using root account everyday in Linux. Any successful XSS attack on admin results in full control including PHP code execution and shell execution. Ideally there should be a way to administer server without opening Moodle session in a browser.
user with Editor role may enter any course and manage it without actually participating in the course. Category admin accounts are currently used for this which is far from optimal.
New global groups tables, capabilities and enrol plugin
- global groups separate from course groups and groupings
- enrolment plugin handles synchronisation of global groups with course groups (synchronised later when global group membership changes)
- global groups used in manual enrolment plugin when enroling groups of people (not synchronised later)
- global groups used when assigning roles (not synchronised later)
Table globalgroups definition of global groups
|contextid||int(10)||foreign key, references context.id|
|name||char(255)||name of global group|
|modifierid||int(10)||last user who modified membership, references user.id|
|timecreated||int(10)||timestamp, creation date|
|timemodified||int(10)||timestamp, last modification|
Context specified can be system or course category level, defining of global groups at course context does not make much sense.
Table globalgroups_members stores global group members
|globalgroupid||int(10)||foreign key, references globalgroups.id|
|userid||int(10)||foreign key, references user.id|
|modifierid||int(10)||who added membership, references user.id|
|timeadded||int(10)||timestamp, when added|
- moodle/globalgroups:assign (add/delete members)
- moodle/globalgroups:manage (add/delete/move global groups)
- moodle/globalgroups:view (view membership and use global groups elsewhere)
Meta courses not needed
Meta courses are often used as a way to synchronise course enrolment in multiple courses or as a workaround for missing global groups. Internally metacourses try to replicate role assignments from one course into another course. If we decide to reimplement enrolments we would have to synchronise course participation too.
Current major problems are performance, missing groups support, minor bugs and usability. New global groups should theoretically solve all these problems.
Questions and potential problems:
- Can global groups fully replace meta courses?
- If not what are the use cases?
Role assignment time restrictions moved to course participation table and plugins
Enrolment plugins can now implement advanced role handling code either from cron or at run time. The enrolment duration flags solve course access issues (equivalent to time restricting of role with moodle/course:view capability). Other uses would be easily implemented in enrolment plugins.
For example enrolment plugin may assign read only role before the course starts, then switch to normal student role, after course end it may switch to read only role again and after one year forbid access to course completely by setting status flag in course_participant table. All this time user would be participant (would appear in gradebook, assignments, groups, etc.), but his/here could change and access to course could be limited in any way.
- Current roles system does not allow multiple assignment of the same role in the same context - this might be a problem for advanced enrolment plugins when manual enrolments used at the same time.
Change unique index in role_assignments
At present the index
<INDEX NAME="contextid-roleid-userid" UNIQUE="true" FIELDS="contextid, roleid, userid" NEXT="sortorder"/>
collides with concept of multiple enrol plugins and role assignment locking in new enrol plugin instances, it should be more flexible if changed to:
<INDEX NAME="contextid-roleid-userid-enrolid" UNIQUE="true" FIELDS="contextid, roleid, userid, enrolid" NEXT="sortorder"/>
New $USER->participating and $USER->visiting caching
These flags will be used in require_login() and may also be used elsewhere.
Move role definitions cache from $USER to $SESSION
The current caching is not efficient in cron script, we might also use this cache in other new functions. $SESSION is not affected when switching users in cron or other cli scripts.
It might be also interesting to find out if there are some better compression routines for rdef arrays, for example using capability id instead of name because we are loading the list of caps from db anyway.
New functions returning SQL instead of arrays of users and courses
function get_participating_courses_sql($userid, $activeonly=false, array $fields=null, array $sorts=null, $prefix=, $extrajoin=null, $extrawhere=null, array $extraparams=null) function get_participants_sql($courseid, $groupid=null, $activeonly=false, array $fields=null, array $sorts=null, $prefix=, $withcapability=null, $context=null, $extrajoin=null, $extrawhere=null, array $extraparams=null)
Rewrite stats sql
Current emulated course participation joins are the most expensive part of stats processing, simple joins with course_participant will make it multiple times faster, more cross db compatible and also more accurate.
Use cases and examples
- Give students forum moderator rights
- Enable students to grade assignment submissions
- Give students the rights to approve database module entries
- Allow students to clean up saved chat sessions
- Create an archive forum
- Enable students to rate forum posts
- Allow students to unenrol themselves from a course
- Hide a block from guests
- Give students unlimited time to complete timed quizzes
- Enable students to create questions
- Assign a student the role of calendar editor
- Provide temporary read-only access to naughty students
See also: Roles_use_cases
Key areas that will benefit
My Moodle and "My courses" queries using course_participants will be greatly improved in speed, allowing us to push it more as a standard customisable portal-type interface for users.
- Obsolete:Enrolment rewrite and role tweaks proposal - the fightback (one alternate opinion)