Identifying roles.

Identifying roles.

by Emanuel Delgado -
Number of replies: 26
Hello,

I'm a bit confused about the roles/capabilities system. How can I easily identify, in a particular context, wether the current user is an admin, teacher ou other? I'm working in 1.8.

Thanks,
ED
Average of ratings: -
In reply to Emanuel Delgado

Re: Identifying roles.

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
If you are asking that question, you have not yet got the point of the roles/capabilities system. wink

In your code, in a particular context, you should check whether the current user has certain capabilities, for example mod/quiz:attempt. Then it is up to the administrator which roles have that capability - and the roles may be admin, teacher, or it may be some roles that no one else has every thought of. The whole point of the roles system is to give the Administrator complete flexibility.
In reply to Tim Hunt

Re: Identifying roles.

by John Isner -
Tim,
Let me ask the same question but phrase it a little differently. In a given context, how can I find all the roles which have been assigned to me, both in the current context and in higher level contexts? I'd like to be able to get a "stack trace" of my roles in debug mode. Just seeing all my current capabilities and their values is not good enough. I'd like to see the whole stack so I can do my own calculations and check that the system is working the way it's supposed to. It would be a great way to explore, learn, and debug the system. The roles system needs greater transparency. It's too much like a black box.
In reply to John Isner

Re: Identifying roles.

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
A debug display of of the relevant information is a good idea.

And actually, although there is not a nice moodle interface to display this, in Moodle 1.9 it is readily available because of the work Martin Langhoff did optimising the roles system. Now, relevant roles information is stored in the session, so doing

print_object($USER->access);

will display everything in a not very readable format.

You could even make a simple PHP script (call is something like moodle/rolesdebug.php) like:

require_once('config.php');
require_login();
print_header_simple();
print_object($USER->access);
print_footer();

With more effort, you could do better, of course.
In reply to Tim Hunt

Re: Identifying roles.

by John Isner -
Tim,
I spent a restless night thinking about a "decent" interface. Here's what I came up with.
  • This only applies to users who have permission to Assign roles to users in a given context
  • On the "roles" page in a given context (e.g., Course administration -> Assign roles), add a View permissions tab
  • Clicking on View permissions tab shows a list of users. In a course or module context, the list would show all course participants.
  • Clicking on user X displays a page Permissions for User X in context Y (the complete list of permissions for the selected user).
This gives complete transparency to the roles system. It lets us see the permissions the algorithm has computed from all assignments and overrides. Currently, we can only guess what those permissions are, or perform tedious experiments to deduce them.

Two possible enhancements to the Permissions for User X in context Y page:
  • Highlight the value of each capability in the parent context (as it's done when displaying overrides)
  • Add an Up button, allowing you to change the page view to the parent context. For example, if the parent context of Y is Z, clicking the Up button will display the page Permissions for User X in context Z. On the parent page, there would be two buttons, Up and Down, allowing you to either go up another level or return to the previous level. Using these buttons, you can "animate" the display of permissions. Naturally, you can only go up as far as you have permission to Assign roles to users.



In reply to John Isner

Re: Identifying roles.

by Ray Lawrence -
John, I hope you sleep easier this evening...big grin

A couple of quick thought on the above:

In a course or module context, the list would show all course participants.

For modules (and blocks) should this exclude users who may not access a module/block owing to inclusion in a grouping?

Naturally, you can only go up as far as you have permission to Assign roles to users.

Agreed, otherwise the roles system is compromised. However, a role assignment at a context higher than the one the user who is making the investigation is assigned to may still impact on a context in which that user is active. Consequently there would need to be an indicator that signals that a permission is set for a capability at a higher (inaccessible) context where this impacts on the context being viewed by that user.

Whist typing this it's occured to me that I may not have fully thought this through, but I think this "higher context indicator" need only be present where the permission in the current context is Inherit/Not set or the permission in the higher context is Prohibit.


In reply to Ray Lawrence

Re: Identifying roles.

by John Isner -
For modules (and blocks) should this exclude users who may not access a module/block owing to inclusion in a grouping?

Good question. I hadn't thought about it. In a given context, which users do you list? The simplest solution would show all users on the site. This avoids the need for a complex analysis to determine who can actually access this context. For example, in a course or module context, I would list user X even if X is not enrolled in the course, since X is a potential enrollee in the course. I would list the guest user even if the course does not allow guests, since the course settings could change to allow guests. I would list the admin users.

Typically, the list will be used to select a prototypical user. For example, I would choose one of my students that I know can access this module by virtue of his membership in a grouping.

Can you give an example of the higher context indicator? It's a bit too abstract for me.

In hindsight, I see nothing wrong with allowing the traceback to run all the way to System level. You can watch your selected user get rolled all the way back to Authenticated user.
In reply to John Isner

Re: Identifying roles.

by Ray Lawrence -
Groupings: Actually, on reflection, I may have overcomplicated this as this issue is one of clarity about the role rather than users assigned to a role.

Higher contexts:

Assume this course layout:
Category A
-----Sub-category AA
-----------Course X

Red is assigned as a Course Creator at Category A context (The Course Creator role allows un-assignment from a role by the user IIRC).

Red is assigned as a Student in Course X.

Blue is a Teacher in Course X.
Blue is an Administrator in Sub-Category AA

Blue notices that Red can un-assign himself from the student role in Course X whilst the other students cannot.

Blue investigates the role assignments in Course X and Sub-Category AA using the roles interface. All seems as it should be... what to do? Is it a bug, is it a plane?

The issue lies in the CC assignment in Category A. Blue should have a notification that there is a permission setting (Allow, Prevent, Prohibit) at the higher context. Blue then knows what the issue is (and possibly where depending on the level of detail in the new roles interface).

Does that help?



In reply to Ray Lawrence

Re: Identifying roles.

by John Isner -
Ray,
Yes, thank you for the example. Now I understand. The issue disappears if we allow Blue to trace Red's permissions all the way to System, as I suggested in my last post. Just being a Teacher in course X should be enough for Blue get the trace. Keep it simple!
In reply to John Isner

Re: Identifying roles.

by John Isner -
I just added MDL-13228 "Improve the transparency of Roles and Capabilities by adding a View permissions tab" based on this discussion.
In reply to Tim Hunt

Re: Identifying roles.

by John Isner -
Hi Tim,
I added a rolesdebug.php to my test site and I could use some guidance interpreting the output (attached output is for a user who is enrolled as a Student in one course). It looks like the $USER->access array contains information about permissions in all possible contexts, since It doesn't change as long as the user doesn't have any role changes. The [/1:5] array looks like Student permissions and [/1:7] looks like Authenticated user permissions. Can you tell me how to interpret the [ra] (role assignments) and [loaded] arrays?
In reply to John Isner

Re: Identifying roles.

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
The bit before the colon is a context path, so /1 is the system context, and /1/123/1234 is probably the course with contextid 1234 in the category with contextid 123. One bit of data is the role_capabilites, which are the original definitions (role_capabilities in the system context) and role overrides (role capabilities in any other context).

The bit after the colon is the role id.

The role assignments are then the role assignments in different contexts for the current user.

When you first log in, the data is loaded for the site context and all course-categories. When you first visit a course, the data is loaded for that course, and all contexts inside that course.

There is quite a lot of work to do to unpick the debug output and work out what it means.


By the way, have you seen my User's roles report? It does not do what you want, but it does show you all the role assignments for a particular user, which is sometimes useful. It complements the work Martin Langhoff did on the extended participants list.

And I quite like your suggestion for an explanatory interface. If only I had the time to play around trying to implement it. Sadly, I am busy with an immense list of work the OU wants finished by July, and it is already looking unlikely.
In reply to Tim Hunt

Re: Identifying roles.

by John Isner -
Thanks, Tim. This information is pure gold. Yes, I saw the discussion Martin referenced here (the one with the screenshot showing all of a users' roles). The report is certainly useful on a gross level, but I'm running into situations where multiple role assignments and overrides aren't adding up the way I think they should (according to "theory"), and for that, a more detailed report needed. Such a report would not only be a powerful debugging tool, it would also be an excellent learning tool.
In reply to Tim Hunt

Re: Identifying roles.

by John Isner -
Tim,
I'm having lots of fun using rolesdebug.php. Thanks again. 

Can you help me interpret the [ra] element?  The main loop in has_capability_in_accessdata loops over this element, so it is obviously very important to understand.

I created the following scenario in 1.9 beta 4.

I have two simple role definitions:

    o Role 13 is allowed to manage lessons
    o Role 14 is allowed to edit lessons

(each of these sets a single permission and leaves all other Not set.)

I assign both roles to a user in a Lesson context (/1/3/4/150).  Then I override both roles in the same context:

    o Override role 13, preventing manage lessons
    o Override role 14, preventing edit lessons

In other words, the overrides simply cancel the assignments, which works just fine.

Here is the output of rolesdebug.php for this user (I cut out elements that aren't relevant to the scenario like Auth user):

Array
(
    [ra] => Array
        (
            [/1/3/4/150] => Array
                (
                    [0] => 14
                    [1] => 13
                )
        )

    [rdef] => Array
        (
            [/1:13] => Array
                (
                    [mod/lesson:manage] => 1
                )

            [/1:14] => Array
                (
                    [mod/lesson:edit] => 1
                )

            [/1/3/4/150:13] => Array
                (
                    [mod/lesson:manage] => -1
                )

            [/1/3/4/150:14] =>; Array
                (
                    [mod/lesson:edit] => -1
                )

        )
)
In reply to Tim Hunt

Re: Identifying roles.

by John Isner -
Tim,
Never mind my last post. I think I have it figured out.
In reply to John Isner

Re: Identifying roles.

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
Hopefully you figured out that they are role assignments, indexed by context.

I am really impressed by the work you are putting in figuring this out. It is a really valuable contribution to the Moodle community, if you can make sense of it and get it written up on Moodle docs, then I will buy you a beer or two next time I see you. (Fingers crossed I can get to San Francisco in June).
In reply to Tim Hunt

Re: Identifying roles.

by John Isner -
Hi Tim,
Thanks for your encouragement. I do enjoy a challenge! After studying the code for several hours this weekend and running a lot of test cases, I do finally understand the algorithm and the data structures. I'm working on a model-based explanation, rather than one based on the implementation.
Average of ratings: Useful (1)
In reply to John Isner

Re: Identifying roles.

by Martin Dougiamas -
Picture of Core developers Picture of Documentation writers Picture of Moodle HQ Picture of Particularly helpful Moodlers Picture of Plugin developers Picture of Testers
Yes Yes Yes Yes Awesome, John approve
In reply to Martin Dougiamas

Re: Identifying roles.

by John Isner -
I just added an article to the documentation wiki on the Rules for adding permissions. It is curently linked to only from the Roles FAQ page, under the question What is my role here?

As Helen always says "Please note that everyone is welcome to contribute to the documentation - it's a wiki" but I will also be pleased to get your feedback in this newly created discussion, and will gladly make changes to the article that people suggest.
In reply to John Isner

Re: Identifying roles.

by Ray Lawrence -
John,

Could you explain why the example at http://docs.moodle.org/en/How_permissions_are_calculated#A_practical_example is not as in my revision below (my additions are emboldened).

Thanks
Attachment perm.png
In reply to Ray Lawrence

Re: Identifying roles.

by John Isner -
Ray,
I don't recall seeing these additions, but then I haven't worked on that part of the article for a while. Can you read the history and tell what happened? If the history shows I deleted it, it was definitely an accident. I wouldn't change anything before talking with you first.
In reply to John Isner

Re: Identifying roles.

by Ray Lawrence -
Hi John,

The additions are mine. I was looking at the page this morning and it struck me that there was some information missing. The bold items in the screenshot above are the bits that seem to be missing. I didn't want to update the wiki page if I've missed something fundamental (or just plain obvious).
In reply to Ray Lawrence

Re: Identifying roles.

by John Isner -
Hi Ray,
I have a feeling that I still haven't answered your question adequately. My last post is only confirming that the tables in the wiki article give the same information as you get by dumping out Moodle's permission data in real time.

I think your question is why the a's in in your table are missing from my table. Let's focus on your first table, which corresponds to circle 2 in my rolesdebug screenshot (above).

Entries in the row zero of the table represent role assignments. In circle 2, you see three role assignments:
  • R7 = user (assigned in System)
  • R2 = coursecreator (assigned in Course category B)
  • R3 = editingteacher (assigned in course)
The A's and the N's in parentheses after the role alias tell us what the role says about mod/lesson:edit. R7 and R2 say nothing, while R3 says "allow".

Entries the remaining rows (1...N) of the table represent role overrides. In circle 2, we see one override:
  • Teacher is overridden in the lesson context, setting mod/lesson:edit = Prevent. We write this exactly like a role assignment, namely, R3(P). We put the entry in the same column as the role assignment and the row corresponding to the context level of the override, namely row 4 (0 = System, 1 = cat A, 2 = cat B, 3 = course, 4 = lesson).
In your first table, it looks like there are two additional overrides: one to creator in context B and an override to editingteacher in the course context. I think what you are trying to say is (1) creator is allowed to edit lessons in the category B context and (2) teacher is allowed to edit lessons in the course context. Well, (1) is not true; Creator is what the cowboys call a one-trick-pony: it can create courses and that's all it can do. (2) is true -- teachers can edit lessons -- but that fact is captured by the role assignment in row 0.

Just remember (1) there are only two types of entries in the table (2) assignments are in row 0 (3) overrides are in the other rows. I read these tables all the time, so it's easy for me, but they do take some getting used to, especially (3).


Attachment my_second_table.png
In reply to Ray Lawrence

Re: Identifying roles.

by John Isner -
Ray,
I set up the scenario from A practical example on my 1.9 site and used my new roles debuggings script to draw the three tables (see screenshots below). The rolesdebug table format is a little different from the table in How permissions are calculated, but it gives the same information.

Notes on the screenshot:
  1. User Joe Blow has been assigned as Course creator in category B. He creates course named 'course' and within it, a lesson named 'Lesson' (I apologize for Joe, he is not very creative when it comes to naming). Joe then ran rolesdebug, specifying the Lesson context and inquiring about capability mod/lesson:edit. He is allowed to edit, as expected.
  2. Now the admin overrides Teacher in the Lesson context, setting mod/lesson:edit = false. Joe logs back in and enters the Lesson context. He then runs rolesdebug.php, giving the same parameters as in 1. He is prevented from editing, as expected.
  3. Now the admin removes the Teacher override in Lesson and overrides Course creator in category B, setting mod/lesson:edit = false. Joe logs back in and enters the Lesson context. He then runs rolesdebug.php, giving the same parameters as in 1. He is allowed to edit.
Attachment rolesdebug_output_for_Ray_Lawrence.png
In reply to Tim Hunt

Re: Identifying roles.

by Michael Shaffer -

Can someone help me understand why authenticated users can no longer update their own profiles after upgrading to 1.9?

There is much discussion on how to prevent users from doing this... I want to allow them to (even though this is supposed to be the default)!

I ran the simple debugroles.php that is in this thread... not sure how to interpret the output. "editownprofile" appears twice, once as "1" and once as "-1000". I'm assuming -1000 is invalid, not sure how it got there!

Array
(
 [ra] => Array
 (
 [/1/14/2236] => Array
 (
 [0] => 5
 )

 [/1/18/3133] => Array
 (
 [0] => 5
 )

 [/1/4/2198] => Array
 (
 [0] => 5
 )

 [/1/74/73] => Array
 (
 [0] => 5
 )

 [/1] => Array
 (
 [0] => 6
 )

 )

 [rdef] => Array
 (
 [/1:5] => Array
 (
 [mod/hotpot:attempt] => 1
 [mod/lams:participate] => 1
 [gradereport/overview:view] => 1
 [mod/quiz:attempt] => 1
 [gradereport/user:view] => 1
 [mod/quiz:view] => 1
 [mod/assignment:submit] => 1
 [mod/scorm:savetrack] => 1
 [mod/assignment:view] => 1
 [mod/scorm:skipview] => 1
 [mod/certificate:view] => 1
 [mod/scorm:viewscores] => 1
 [mod/chat:chat] => 1
 [mod/survey:participate] => 1
 [mod/chat:readlog] => 1
 [mod/wiki:participate] => 1
 [mod/choice:choose] => 1
 [mod/workshop:participate] => 1
 [mod/data:comment] => 1
 [moodle/block:view] => 1
 [mod/data:viewentry] => 1
 [moodle/blog:view] => 1
 [mod/data:writeentry] => 1
 [moodle/course:view] => 1
 [mod/forum:createattachment] => 1
 [moodle/course:viewparticipants] => 1
 [mod/forum:deleteownpost] => 1
 [moodle/course:viewscales] => 1
 [mod/forum:initialsubscriptions] => 1
 [moodle/grade:view] => 1
 [mod/forum:replypost] => 1
 [moodle/legacy:student] => 1
 [mod/forum:startdiscussion] => 1
 [moodle/user:changeownpassword] => 1
 [mod/forum:viewdiscussion] => 1
 [moodle/user:editownprofile] => 1
 [mod/forum:viewrating] => 1
 [moodle/user:readuserblogs] => 1
 [mod/glossary:comment] => 1
 [moodle/user:readuserposts] => 1
 [mod/glossary:write] => 1
 [moodle/user:viewdetails] => 1
 )

 [/1:6] => Array
 (
 [moodle/legacy:guest] => 1
 [moodle/user:viewdetails] => 1
 [moodle/course:view] => 1
 [moodle/blog:view] => 1
 [mod/assignment:view] => 1
 [mod/data:viewentry] => 1
 [mod/forum:viewdiscussion] => 1
 [mod/quiz:view] => 1
 [moodle/my:manageblocks] => 1
 [moodle/user:editownprofile] => -1000
 [moodle/user:changeownpassword] => -1000
 [moodle/block:view] => 1
 )

 )

 [loaded] => Array
 (
 [0] => /1/2
 )

 [dr] => 6
 [time] => 1209593401
)

In reply to Michael Shaffer

Re: Identifying roles.

by John Isner -
This user is a Guest. Most likely you have set Site administration -> Users -> Permissions -> User policies -> Default role for all users = Guest. Set it back to Authorized user and users will be able to edit their own profiles. Let us know if this fixes the problem.