Change a student's permission to allow user update in one instance

Change a student's permission to allow user update in one instance

by Brad Ayers -
Number of replies: 5

I am making a simple local plugin that randomly displays a modal with a question and answer pair (provided by student) to confirm that the student is present while their chosen course is opened.  If this is not answered correctly within the allotted time the student account is to be suspended.  Everything is working except the suspend account part.

Since the 'sesskey' and 'user' that calls the function that should change user->suspended from 0 to 1 is from the student who is logged in, I am getting Debug info of "Error code: nopermissions" and the notification "Sorry, but you do not currently have permissions to do that (Update user profiles)".

This is the section of code where I encounter the error:

if (confirm_sesskey()) {
        require_capability('moodle/user:update', $sitecontext);
         if ($user = $DB->get_record('user', array('id'=>$id, 'deleted'=>0))) {
                if (!is_siteadmin($user) and $user->suspended != 1) {
                    $user->suspended = 1;
                    }
                    // Force logout.
                    \core\session\manager::kill_user_sessions($user->id);
                    user_update_user($user, false);
                }
            }
            //redirect($returnurl);
        }

How would I go about changing the permissions for this student during the instance this script is called so that the account can be suspended, then return the students permissions to their prior default after this action?

Thank you in advance for any help on this. I'm new to Moodle and this is the last piece of this plugin to get it working.

Average of ratings: -
In reply to Brad Ayers

Re: Change a student's permission to allow user update in one instance

by Brad Ayers -
I have not heard from anyone and continue to get "Sorry, but you do not currently have permissions to do that (Update user profiles)." Is this an authorization issue that simply has no easy work around? Perhaps I could create a new user profile for a student that has the ability to suspend themselves? Any feedback would be greatly appreciate. Even if that feedback is that there is no solution.
In reply to Brad Ayers

Re: Change a student's permission to allow user update in one instance

by Davo Smith -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
Could simply be that in the UK (where a lot of the regular posters on this forum are based) it is a bank holiday weekend, so many people won't have been on the forums between Saturday (when you first posted) and Monday (when you followed up).

The bit of code you show checks to see if the user making the call has permission to arbitrarily update any user account on the system (moodle/user:update) then, if they do, suspends the user in question.

Is this existing code in Moodle core that you are calling, or is it new custom code that you've written (or copied from somewhere in core?).

I would suggest that changing the user's permission (to give them the ability to modify any user's account on the system), even on a temporary basis would be incredibly dangerous; this is the case, even if your script it only able to suspend user accounts (and nothing else) - it appears to be the case that the account to suspend is controlled by a param sent by the javascript (?) in which case, it could be modified to suspend any user on the system ...

Far better would be a custom script that, on the server side, accepts the answer given, compares it with the expected answer, then handles the user suspension, without a capability check, but limit it to suspending $USER (the currently logged-in user) not an arbitrary $id passed from the client browser.

Does that make sense?
Average of ratings: Useful (2)
In reply to Davo Smith

Re: Change a student's permission to allow user update in one instance

by Brad Ayers -
Thanks for your reply, Dave. I really appreciate your feedback. As you suggested, the bit of code I was using is from admin/user.php. My main concern was to avoid any risk that may arise from writing my own script. But the more I researched the more I realized that, as you said, changing user permission is not a simple matter and could be very dangerous.

So, I ended up writing my own script in the plugin that just does the suspend outside of changing any permissions. As a security precaution, it does verify login and sesskey before performing the suspend on the currently logged in user.

The only thing that I did different from your recommendation is that the question and answer script is separate from the suspend script. So, the modal does an AJAX call to the question and answer script then, if the user fails to answer the question, the page is redirected to the suspend script (the only parameter passed, via GET, is the SESSKEY)  where the logged in user is suspended, logged out and redirected to the login URL.

If there is any other validation you recommend should be done in addition to the require_login() and confirm_sesskey(), I would be grateful for your feedback so that the custom script can be as secure as possible. Lastly, this is my first Moodle plugin and I am installing it in the local directory. It occurred to me that the availability directory may be appropriate as well. Thoughts? Thank you again.
In reply to Brad Ayers

Re: Change a student's permission to allow user update in one instance

by Davo Smith -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
Brad - it comes down to a matter of trust - do you trust the user's browser (potentially under the full control of the user) to make the decision about whether or not they should be suspended, or do you trust your server-side code to interpret the response sent back by the browser and make that decision?

require_login() + require_sesskey() (wraps around confirm_sesskey(), but automatically throws an exception and stops the execution if the sesskey doesn't match) should be sufficient to confirm the user identity and their intention. Normally, if possible, you would want to POST to a URL that makes changes to the DB, rather than using a redirect. However, that may be tricky to do in this case.

The "availability" directory is for plugins that directly interact with the APIs for controlling the availability of individual activities or course sections to the user (e.g. "must complete activity X first", "date must be after 1st April", etc.) - that doesn't sound at all like what you're doing here, so a local plugin is probably the correct place.
Average of ratings: Useful (1)
In reply to Davo Smith

Re: Change a student's permission to allow user update in one instance

by Brad Ayers -
Thanks for your feedback on this, Davo. Your follow up is appreciated more than you know. I'll leave the plugin in the local directory and see if I can switch to an AJAX POST rather than the redirect.

It's been a few years since I've done anything on git, but I may push this on there in case it is of any interest to anyone.