accesslib: initial has_capability() rewrite
- has_capability() renamed has_capability_old() and we fallback when we cannot answer the question - has_capability() works great for the course-and-above contexts for the logged in user - does not touch the DB - works based on $USER->access which has a pretty compact view of the user's access rights... TODO: - deal with contexts below the course - here we need to trigger the role-assignment and role-defs load when needed - deal with "other" contexts that hang from the system context - deal with global roleswitch, local roleswitch
This commit is contained in:
+108
-1
@@ -347,7 +347,113 @@ function get_parent_cats($context) {
|
||||
}
|
||||
|
||||
|
||||
function has_capability($capability, $context=NULL, $userid=NULL, $doanything=true) {
|
||||
global $USER, $CONTEXT, $CFG;
|
||||
|
||||
/// Make sure we know the current context
|
||||
if (empty($context)) { // Use default CONTEXT if none specified
|
||||
if (empty($CONTEXT)) {
|
||||
return false;
|
||||
} else {
|
||||
$context = $CONTEXT;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_null($userid) || $userid===0) {
|
||||
$userid = $USER->id;
|
||||
}
|
||||
|
||||
$contexts = array();
|
||||
if ($context->path === '') {
|
||||
$contexts(SITECONTEXTID, $context->id);
|
||||
} else {
|
||||
$contexts = explode('/', $context->path);
|
||||
array_shift($contexts);
|
||||
}
|
||||
|
||||
if ($USER->id === $userid) {
|
||||
if ($context->contextlevel <= CONTEXT_COURSE) {
|
||||
// Course and above are always preloaded
|
||||
return has_cap_fromsess($capability, $context, $USER->access, $doanything);
|
||||
}
|
||||
///$coursepath = get_course_from_path($context->path);
|
||||
/// if ($USER->access) {
|
||||
/// $USER->access['courses'] = get_course_access($context, $userid);
|
||||
|
||||
}
|
||||
error_log("not implemented $userid $capability {$context->contextlevel} {$context->path} ");
|
||||
return has_capability_old($capability, $context, $userid, $doanything);
|
||||
/*
|
||||
if ($context->contextlevel === CONTEXT_COURSE) {
|
||||
if (in_array($context->id, $USER->access_courses)) {
|
||||
}
|
||||
return
|
||||
}
|
||||
if () {
|
||||
}
|
||||
|
||||
return false;*/
|
||||
}
|
||||
|
||||
function get_course_from_path ($path) {
|
||||
// assume that nothing is more than 1 course deep
|
||||
if (preg_match('!^(/.+)/\d+$!', $path, $matches)) {
|
||||
return $matches[1];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function has_cap_fromsess($capability, $context, $sess, $doanything) {
|
||||
|
||||
$path = $context->path;
|
||||
|
||||
// build $contexts as a list of "paths" of the current
|
||||
// contexts and parents with the order top-to-bottom
|
||||
$contexts = array($path);
|
||||
while (preg_match('!^(/.+)/\d+$!', $path, $matches)) {
|
||||
$path = $matches[1];
|
||||
array_unshift($contexts, $path);
|
||||
}
|
||||
$cc = count($contexts);
|
||||
|
||||
$can = false;
|
||||
// From the bottom up...
|
||||
for ($n=$cc-1;$n>=0;$n--) {
|
||||
$ctxp = $contexts[$n];
|
||||
if (isset($USER->access['ra'][$ctxp])) {
|
||||
// Found a role assignment
|
||||
$roleid = $sess['ra'][$ctxp];
|
||||
error_log("found ra $roleid for $ctxp");
|
||||
// Walk the path for capabilities
|
||||
// from the bottom up...
|
||||
for ($m=$cc-1;$m>=0;$m--) {
|
||||
$capctxp = $contexts[$m];
|
||||
if (isset($sess['rdef']["{$capctxp}:$roleid"][$capability])) {
|
||||
$perm = $sess['rdef']["{$capctxp}:$roleid"][$capability];
|
||||
error_log("found rc for $roleid for $ctxp in {$capctxp}:$roleid $capability $perm");
|
||||
if ($perm === CAP_PROHIBIT) {
|
||||
return false;
|
||||
} else {
|
||||
$can += $perm;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($can < 1) {
|
||||
if ($doanything) {
|
||||
// didn't find it as an explicit cap,
|
||||
// but maybe the user candoanything in this context...
|
||||
return has_cap_fromsess('moodle/site:doanything', $context, $sess, false);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* This function checks for a capability assertion being true. If it isn't
|
||||
* then the page is terminated neatly with a standard error message
|
||||
@@ -439,7 +545,7 @@ function has_capability_including_child_contexts($context, $capabilitynames) {
|
||||
* @param bool $doanything - if false, ignore do anything
|
||||
* @return bool
|
||||
*/
|
||||
function has_capability($capability, $context=NULL, $userid=NULL, $doanything=true) {
|
||||
function has_capability_old($capability, $context=NULL, $userid=NULL, $doanything=true) {
|
||||
|
||||
global $USER, $CONTEXT, $CFG;
|
||||
|
||||
@@ -1331,6 +1437,7 @@ function load_all_capabilities() {
|
||||
}
|
||||
|
||||
load_user_capability();
|
||||
$USER->access=get_user_sitewide_access($USER->id);
|
||||
|
||||
// when in "course login as" - load only course caqpabilitites (it may not always work as expected)
|
||||
if (!empty($USER->realuser) and $USER->loginascontext->contextlevel != CONTEXT_SYSTEM) {
|
||||
|
||||
Reference in New Issue
Block a user