summaryrefslogtreecommitdiffstats
path: root/modules-available/permissionmanager/inc/permissionutil.inc.php
diff options
context:
space:
mode:
Diffstat (limited to 'modules-available/permissionmanager/inc/permissionutil.inc.php')
-rw-r--r--modules-available/permissionmanager/inc/permissionutil.inc.php91
1 files changed, 79 insertions, 12 deletions
diff --git a/modules-available/permissionmanager/inc/permissionutil.inc.php b/modules-available/permissionmanager/inc/permissionutil.inc.php
index a3a2b610..46b8c065 100644
--- a/modules-available/permissionmanager/inc/permissionutil.inc.php
+++ b/modules-available/permissionmanager/inc/permissionutil.inc.php
@@ -40,6 +40,9 @@ class PermissionUtil
}
}
+ private static $permissionCacheLoc = [];
+ private static $permissionCacheAny = [];
+
/**
* Check if the user has the given permission (for the given location).
*
@@ -58,12 +61,24 @@ class PermissionUtil
return true;
// Limit query to first part of permissionid, which is always the module id
$prefix = $parts[0] . '.%';
- if (is_null($locationid)) {
+ $key = $userid . '_' . $permissionid;
+ $cacheAll = false;
+ if ($locationid === null) {
+ // Check if permission exists for any location (i.e. permission not location dependent)
+ $cache =& self::$permissionCacheAny;
+ if (array_key_exists($key, $cache))
+ return $cache[$key];
$res = Database::simpleQuery("SELECT permissionid FROM role_x_permission
INNER JOIN role_x_user USING (roleid)
WHERE role_x_user.userid = :userid AND (permissionid LIKE :prefix OR permissionid LIKE '*')",
compact('userid', 'prefix'));
+ // Quick bailout - no results
+ if ($res->rowCount() === 0) {
+ $cache[$key] = false;
+ return false;
+ }
} else {
+ // Check if permission exists for specific location
if ($locationid === 0) {
$locations = [0];
} else {
@@ -72,26 +87,78 @@ class PermissionUtil
$locations = [0];
}
}
- $res = Database::simpleQuery("SELECT permissionid FROM role_x_permission
+ $cache =& self::$permissionCacheLoc;
+ if (array_key_exists($key, $cache)) {
+ if (array_key_exists($locationid, $cache[$key]))
+ return $cache[$key][$locationid]; // Exact match - return immedtiately
+ foreach ($locations as $lid) {
+ if (array_key_exists($lid, $cache[$key]) && $cache[$key][$lid]) {
+ $cache[$key][$locationid] = true;
+ return true; // We have a parent location that allows access - take it
+ }
+ }
+ $cacheAll = true;
+ }
+ $params = compact('userid', 'prefix');
+ if ($cacheAll) {
+ $extra = '';
+ } else {
+ $extra = 'AND (locationid IN (:locations) OR locationid IS NULL)';
+ $params['locations'] = $locations;
+ }
+ $res = Database::simpleQuery("SELECT permissionid, locationid FROM role_x_permission
INNER JOIN role_x_user USING (roleid)
INNER JOIN role_x_location USING (roleid)
WHERE role_x_user.userid = :userid AND (permissionid LIKE :prefix OR permissionid LIKE '*')
- AND (locationid IN (:locations) OR locationid IS NULL)",
- compact('userid', 'prefix', 'locations'));
+ $extra", $params);
+ // Quick bailout - no results
+ if ($res->rowCount() === 0 && !$cacheAll) {
+ foreach ($locations as $lid) {
+ $cache[$key][$lid] = false;
+ }
+ return false;
+ }
}
- // Quick bailout - no results
- if ($res->rowCount() === 0)
- return false;
// Compare to database result
+ if ($cacheAll) {
+ $allLocs = Location::getLocationsAssoc();
+ }
self::makeComparisonVariants($parts, $compare, $wildcard, $wclen);
+ $retval = false;
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
- if (in_array($row['permissionid'], $compare, true))
- return true;
- if ($wildcard !== false && strncmp($row['permissionid'], $wildcard, $wclen) === 0)
- return true;
+ if (in_array($row['permissionid'], $compare, true)
+ || ($wildcard !== false && strncmp($row['permissionid'], $wildcard, $wclen) === 0)) {
+ if (!$cacheAll || ($row['locationid'] == $locationid) || $row['locationid'] === null) {
+ $retval = true;
+ if (!$cacheAll)
+ break;
+ }
+ if ($cacheAll) {
+ $cache[$key][(int)$row['locationid']] = true;
+ $list = ($row['locationid'] === null) ? array_keys($allLocs) : $allLocs[(int)$row['locationid']]['children'];
+ foreach ($list as $lid) {
+ $cache[$key][$lid] = true;
+ }
+ if ($row['locationid'] === null)
+ break;
+ }
+ }
+ }
+ if ($locationid === null) {
+ $cache[$key] = $retval;
+ } else {
+ $cache[$key][$locationid] = $retval;
+ if ($cacheAll) {
+ $locations = array_keys($allLocs);
+ }
+ foreach ($locations as $lid) {
+ if (!array_key_exists($lid, $cache[$key])) {
+ $cache[$key][$lid] = false;
+ }
+ }
}
- return false;
+ return $retval;
}
/**