Development:Roles and modules: Difference between revisions

From MoodleDocs
(link to Roles and Capabilities forum instead of General Developer's one)
m (Roles development moved to Development:Roles and modules)
(No difference)

Revision as of 09:56, 7 February 2007

This is a page for developers that describes how to make Moodle modules work under 1.7 roles system. =) For more background information, please read Development:Roles. For any clarifications please post to the Roles and Capabilities forum.

Introduction

Moodle 1.6 and below uses 7 default roles, namely primary admin, admin, editing teachers, non-editing teachers, students and guests. The set of capabilities that users associated to these roles can perform is fixed. To check permissions, we normally use isteacheredit($courseid), isguest() etc.

Template:Moodle 1.7 Under the new 1.7 system, roles do not have a fixed set of capabilities anymore. We use a different function called has_capability() to check for specific capabilities, more on this later.

Context

Context is an important concept to make roles work. There are currently 8 levels

define('CONTEXT_SYSTEM', 10);
define('CONTEXT_PERSONAL', 20);
define('CONTEXT_USERID', 30);
define('CONTEXT_COURSECAT', 40);
define('CONTEXT_COURSE', 50);
define('CONTEXT_GROUP', 60);
define('CONTEXT_MODULE', 70);
define('CONTEXT_BLOCK', 80);

They are stored as a tuple [contextlevel][instanceid]. For example course with id =2 would be [50][2]. Module with id 495 would be [70][495].

At module level, you only need to worry about CONTEXT_MODULE. Normally, foreach page accessible in your module you would need to load the module using get_context_instance(). The way to use it for modules is $context = get_context_instance(CONTEXT_MODULE, $cm->id); where $cm is the course module object that you would normally have anyway. The contextid is needed for every permission check later on in all your pages.

The has_capability($capability, $contextid, $kill) function

inputs:

$capability is the name of the capability $contextid is normally $context->id, the module context id $kill set to 1 if you want to kill the page, it will throw an error and inform the user that required permission is missing. For example you place has_capability('forum_read', $context->id, true) at the top of the page to prevent users from reading the whole page.

This function looks up a capability for a given context and associated parents recursively. We are pretty much relying on this funciton alone to resolve all capability issues. Original isteacher(), isadmin(), isstudent() etc should all be changed accordingly.

==Loading capabilities== - for now, this plan might change later

Loading capabilities is done when a user first log in. Because it is quite an expensive call, we only load it once and stores everything in the session. So when has_capability() is called, it looks for the values stored in the session variable.

Code rewrite

Some modules might require some tiny rewrites because permission is only checked once at the top, for example some scripts only checks for isstudent() at the top. Now we are able to refine those capabilities, so we need to put the required code changes (add has_capability()) to where the specific capability is needed. For example, in a forum we check to see if user is a student before displaying a discussion page, now we need to check individual permissions for forum_read and forum_reply.

Sample code

// somewhere at the top, after getting $cm, load context

$context = get_context_instance(CONTEXT_MODULE, $cm->id); 

...

has_capability('forum_read', $cm->id, true); // kills this page if user is not allowed to read

...

if (has_capability('forum_reply', $cm->id) {
    print_reply_link();
}

Core API

The core API is located at libdir/accesslib, if you would like to read it =)