summaryrefslogtreecommitdiffstats
path: root/modules-available/permissionmanager
diff options
context:
space:
mode:
Diffstat (limited to 'modules-available/permissionmanager')
-rw-r--r--modules-available/permissionmanager/api.inc.php7
-rw-r--r--modules-available/permissionmanager/clientscript.js45
-rw-r--r--modules-available/permissionmanager/config.json10
-rw-r--r--modules-available/permissionmanager/hooks/translation-global.inc.php38
-rw-r--r--modules-available/permissionmanager/inc/getpermissiondata.inc.php55
-rw-r--r--modules-available/permissionmanager/inc/permissiondbupdate.inc.php110
-rw-r--r--modules-available/permissionmanager/inc/permissionutil.inc.php225
-rw-r--r--modules-available/permissionmanager/install.inc.php137
-rw-r--r--modules-available/permissionmanager/lang/de/permissions.json7
-rw-r--r--modules-available/permissionmanager/lang/de/template-tags.json36
-rw-r--r--modules-available/permissionmanager/lang/en/permissions.json7
-rw-r--r--modules-available/permissionmanager/lang/en/template-tags.json36
-rw-r--r--modules-available/permissionmanager/page.inc.php218
-rw-r--r--modules-available/permissionmanager/permissions/permissions.json17
-rw-r--r--modules-available/permissionmanager/style.css85
-rw-r--r--modules-available/permissionmanager/templates/_page.html29
-rw-r--r--modules-available/permissionmanager/templates/header-menu.html25
-rw-r--r--modules-available/permissionmanager/templates/locationstable.html56
-rw-r--r--modules-available/permissionmanager/templates/page-permission-denied.html21
-rw-r--r--modules-available/permissionmanager/templates/role-filter-selectize.html6
-rw-r--r--modules-available/permissionmanager/templates/roleeditor.html96
-rw-r--r--modules-available/permissionmanager/templates/rolestable.html45
-rw-r--r--modules-available/permissionmanager/templates/treenode.html23
-rw-r--r--modules-available/permissionmanager/templates/treepanel.html4
-rw-r--r--modules-available/permissionmanager/templates/userstable.html40
25 files changed, 902 insertions, 476 deletions
diff --git a/modules-available/permissionmanager/api.inc.php b/modules-available/permissionmanager/api.inc.php
deleted file mode 100644
index 0d84ebce..00000000
--- a/modules-available/permissionmanager/api.inc.php
+++ /dev/null
@@ -1,7 +0,0 @@
-<?php
-
-echo json_encode(array(
- 'key' => 'value',
- 'number' => 123,
- 'list' => array(1,2,3,4,5,6,'foo')
-));
diff --git a/modules-available/permissionmanager/clientscript.js b/modules-available/permissionmanager/clientscript.js
index 4770fa6a..90d66688 100644
--- a/modules-available/permissionmanager/clientscript.js
+++ b/modules-available/permissionmanager/clientscript.js
@@ -10,36 +10,21 @@ document.addEventListener("DOMContentLoaded", function() {
plugins: ["remove_button"]
})[0].selectize;
- // If Site gets refreshed, all data-selectizeCounts will be reset to 0, so delete the filters from the selectize
- selectize.clear();
-
- selectize.on("item_add", function (value, $item) {
- // When first item gets added the filter isn't empty anymore, so hide all rows
- if (selectize.items.length === 1) {
- $(".dataTable tbody").find("tr").hide();
- }
- // Find all rows which shall be shown and increase their counter by 1
- $(".roleid-" + value).closest("tr").each(function () {
- $(this).data("selectizeCount", $(this).data("selectizeCount") + 1);
- $(this).show();
- });
- });
-
- selectize.on("item_remove", function (value, $item) {
- // When no items in the filter, show all rows again
- if (selectize.items.length === 0) {
- $(".dataTable tbody").find("tr").show();
+ var $body = $(".dataTable tbody");
+ var filterFunc = function(value) {
+ var selected = selectize.getValue();
+ if (!selected || !selected.length) {
+ $body.find("tr").show();
} else {
- // Find all rows which have the delete role, decrease their counter by 1
- $(".roleid-" + value).closest("tr").each(function () {
- $(this).data("selectizeCount", $(this).data("selectizeCount") - 1);
- // If counter is 0, hide the row (no filter given to show the row anymore)
- if ($(this).data("selectizeCount") === 0) {
- $(this).closest("tr").hide();
- }
- });
+ $body.find("tr").hide();
+ var str = 'tr.roleid-' + selected.join('.roleid-');
+ $body.find(str).show();
}
- });
+ };
+
+ selectize.on("item_add", filterFunc);
+
+ selectize.on("item_remove",filterFunc);
}
$("tr").on("click", function(e) {
@@ -47,8 +32,4 @@ document.addEventListener("DOMContentLoaded", function() {
$(this).find("input[type=checkbox]").trigger("click");
}
});
-
- $("form input").keydown(function(e) {
- if (e.keyCode === 13) e.preventDefault();
- });
}); \ No newline at end of file
diff --git a/modules-available/permissionmanager/config.json b/modules-available/permissionmanager/config.json
index c92e917a..25b61de3 100644
--- a/modules-available/permissionmanager/config.json
+++ b/modules-available/permissionmanager/config.json
@@ -1,4 +1,8 @@
{
- "category":"main.content",
- "dependencies": [ "locations", "js_stupidtable", "bootstrap_switch", "js_selectize" ]
-}
+ "category": "main.content",
+ "dependencies": [
+ "locations",
+ "js_stupidtable",
+ "js_selectize"
+ ]
+} \ No newline at end of file
diff --git a/modules-available/permissionmanager/hooks/translation-global.inc.php b/modules-available/permissionmanager/hooks/translation-global.inc.php
new file mode 100644
index 00000000..4810a719
--- /dev/null
+++ b/modules-available/permissionmanager/hooks/translation-global.inc.php
@@ -0,0 +1,38 @@
+<?php
+
+$HANDLER = array();
+
+if (file_exists('modules/' . $moduleName . '/permissions/permissions.json')) {
+
+ /**
+ * List of valid subsections
+ */
+ $HANDLER['subsections'] = array(
+ 'permissions'
+ );
+
+ /*
+ * Handlers for the subsections that will return an array of expected tags.
+ * This is optional, if you don't want to define expected tags, don't create a function.
+ */
+
+ /**
+ * Configuration categories.
+ *
+ * @param \Module $module
+ * @return array
+ */
+ $HANDLER['grep_permissions'] = function ($module) {
+ $file = 'modules/' . $module->getIdentifier() . '/permissions/permissions.json';
+ if (!file_exists($file))
+ return [];
+ $array = json_decode(file_get_contents($file), true);
+ if (!is_array($array))
+ return [];
+ foreach ($array as &$entry) {
+ $entry = true;
+ }
+ return $array;
+ };
+
+}
diff --git a/modules-available/permissionmanager/inc/getpermissiondata.inc.php b/modules-available/permissionmanager/inc/getpermissiondata.inc.php
index 982fa0b7..660c94ae 100644
--- a/modules-available/permissionmanager/inc/getpermissiondata.inc.php
+++ b/modules-available/permissionmanager/inc/getpermissiondata.inc.php
@@ -1,27 +1,32 @@
<?php
-class GetPermissionData {
+class GetPermissionData
+{
+
+ const WITH_USER_COUNT = 1;
+ const WITH_LOCATION_COUNT = 2;
/**
* Get data for all users.
*
* @return array array of users (each with userid, username and roles (each with roleid and rolename))
*/
- public static function getUserData() {
+ public static function getUserData()
+ {
$res = Database::simpleQuery("SELECT user.userid AS userid, user.login AS login, role.rolename AS rolename, role.roleid AS roleid
FROM user
- LEFT JOIN user_x_role ON user.userid = user_x_role.userid
- LEFT JOIN role ON user_x_role.roleid = role.roleid
+ LEFT JOIN role_x_user ON user.userid = role_x_user.userid
+ LEFT JOIN role ON role_x_user.roleid = role.roleid
");
- $userdata= array();
+ $userdata = array();
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
- $userdata[$row['userid'].' '.$row['login']][] = array(
+ $userdata[$row['userid'] . ' ' . $row['login']][] = array(
'roleid' => $row['roleid'],
'rolename' => $row['rolename']
);
}
$data = array();
- foreach($userdata AS $user => $roles) {
+ foreach ($userdata AS $user => $roles) {
$user = explode(" ", $user, 2);
$data[] = array(
'userid' => $user[0],
@@ -37,8 +42,9 @@ class GetPermissionData {
*
* @return array array of locations (each including the roles that have permissions for them)
*/
- public static function getLocationData() {
- $res = Database::simpleQuery("SELECT role.roleid as roleid, rolename, GROUP_CONCAT(COALESCE(locationid, 0)) AS locationids FROM role
+ public static function getLocationData()
+ {
+ $res = Database::simpleQuery("SELECT role.roleid AS roleid, rolename, GROUP_CONCAT(COALESCE(locationid, 0)) AS locationids FROM role
INNER JOIN role_x_location ON role.roleid = role_x_location.roleid GROUP BY roleid ORDER BY rolename ASC");
$locations = Location::getLocations(0, 0, false, true);
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
@@ -61,18 +67,26 @@ class GetPermissionData {
/**
* Get all roles.
*
+ * @param int $flags Bitmask specifying additional data to fetch (WITH_* constants of this class)
* @return array array roles (each with roleid and rolename)
*/
- public static function getRoles() {
- $res = Database::simpleQuery("SELECT roleid, rolename FROM role ORDER BY rolename ASC");
- $data = array();
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
- $data[] = array(
- 'roleid' => $row['roleid'],
- 'rolename' => $row['rolename']
- );
+ public static function getRoles($flags = 0)
+ {
+ $cols = $joins = '';
+ if ($flags & self::WITH_USER_COUNT) {
+ $cols .= ', Count(DISTINCT rxu.userid) AS users';
+ $joins .= ' LEFT JOIN role_x_user rxu ON (r.roleid = rxu.roleid)';
}
- return $data;
+ if ($flags & self::WITH_LOCATION_COUNT) {
+ $cols .= ', Count(DISTINCT rxl.locationid) AS locations';
+ $joins .= ' LEFT JOIN role_x_location rxl ON (r.roleid = rxl.roleid)';
+ }
+ if (!empty($joins)) {
+ $joins .= ' GROUP BY r.roleid';
+ }
+ return Database::queryAll("SELECT r.roleid, r.rolename, r.roledescription $cols FROM role r
+ $joins
+ ORDER BY rolename ASC");
}
/**
@@ -81,8 +95,9 @@ class GetPermissionData {
* @param string $roleid id of the role
* @return array array containing an array of permissions and an array of locations
*/
- public static function getRoleData($roleid) {
- $query = "SELECT roleid, rolename FROM role WHERE roleid = :roleid";
+ public static function getRoleData($roleid)
+ {
+ $query = "SELECT roleid, rolename, roledescription FROM role WHERE roleid = :roleid";
$data = Database::queryFirst($query, array("roleid" => $roleid));
$query = "SELECT roleid, locationid FROM role_x_location WHERE roleid = :roleid";
$res = Database::simpleQuery($query, array("roleid" => $roleid));
diff --git a/modules-available/permissionmanager/inc/permissiondbupdate.inc.php b/modules-available/permissionmanager/inc/permissiondbupdate.inc.php
index ffe5fac0..0cd89b3a 100644
--- a/modules-available/permissionmanager/inc/permissiondbupdate.inc.php
+++ b/modules-available/permissionmanager/inc/permissiondbupdate.inc.php
@@ -1,67 +1,107 @@
<?php
-class PermissionDbUpdate {
+class PermissionDbUpdate
+{
/**
- * Insert all user/role combinations into the user_x_role table.
+ * Insert all user/role combinations into the role_x_user table.
*
- * @param array $users userids
- * @param array $roles roleids
+ * @param int[] $users userids
+ * @param int[] $roles roleids
*/
- public static function addRoleToUser($users, $roles) {
- $query = "INSERT IGNORE INTO user_x_role (userid, roleid) VALUES (:userid, :roleid)";
- foreach($users AS $userid) {
+ public static function addRoleToUser($users, $roles)
+ {
+ if (empty($users) || empty($roles))
+ return 0;
+ $arg = array();
+ foreach ($users AS $userid) {
foreach ($roles AS $roleid) {
- Database::exec($query, array("userid" => $userid, "roleid" => $roleid));
+ $arg[] = compact('userid', 'roleid');
}
}
+ return Database::exec("INSERT IGNORE INTO role_x_user (userid, roleid) VALUES :arg",
+ ['arg' => $arg]);
}
/**
- * Remove all user/role combinations from the user_x_role table.
+ * Remove all user/role combinations from the role_x_user table.
*
- * @param array $users userids
- * @param array $roles roleids
+ * @param int[] $users userids
+ * @param int[] $roles roleids
*/
- public static function removeRoleFromUser($users, $roles) {
- $query = "DELETE FROM user_x_role WHERE userid IN (:users) AND roleid IN (:roles)";
- Database::exec($query, array("users" => $users, "roles" => $roles));
+ public static function removeRoleFromUser($users, $roles)
+ {
+ if (empty($users) || empty($roles))
+ return 0;
+ $query = "DELETE FROM role_x_user WHERE userid IN (:users) AND roleid IN (:roles)";
+ return Database::exec($query, array("users" => $users, "roles" => $roles));
+ }
+
+ /**
+ * Assign the specified roles to given users, removing any roles from the users
+ * that are not in the given set.
+ *
+ * @param int[] $users list of user ids
+ * @param int[] $roles list of role ids
+ */
+ public static function setRolesForUser($users, $roles)
+ {
+ $count = Database::exec("DELETE FROM role_x_user WHERE userid in (:users) AND roleid NOT IN (:roles)",
+ compact('users', 'roles'));
+ return $count + self::addRoleToUser($users, $roles);
}
/**
* Delete role from the role table.
*
- * @param string $roleid roleid
+ * @param int $roleid roleid
*/
- public static function deleteRole($roleid) {
- Database::exec("DELETE FROM role WHERE roleid = :roleid", array("roleid" => $roleid));
+ public static function deleteRole($roleid)
+ {
+ return Database::exec("DELETE FROM role WHERE roleid = :roleid", array("roleid" => $roleid));
}
/**
* Save changes to a role or create a new one.
*
- * @param string $rolename rolename
- * @param array $locations array of locations
- * @param array $permissions array of permissions
- * @param string|null $roleid roleid or null if the role does not exist yet
+ * @param string $roleName rolename
+ * @param int[] $locations array of locations
+ * @param string[] $permissions array of permissions
+ * @param int|null $roleId roleid or null if the role does not exist yet
*/
- public static function saveRole($rolename, $locations, $permissions, $roleid = NULL) {
- if ($roleid) {
- Database::exec("UPDATE role SET rolename = :rolename WHERE roleid = :roleid",
- array("rolename" => $rolename, "roleid" => $roleid));
- Database::exec("DELETE FROM role_x_location WHERE roleid = :roleid", array("roleid" => $roleid));
- Database::exec("DELETE FROM role_x_permission WHERE roleid = :roleid", array("roleid" => $roleid));
+ public static function saveRole($roleName, $roleDescription, $locations, $permissions, $roleId = null)
+ {
+ foreach ($permissions as &$permission) {
+ $permission = strtolower($permission);
+ }
+ unset($permission);
+ if ($roleId) {
+ Database::exec("UPDATE role SET rolename = :rolename, roledescription = :roledescription WHERE roleid = :roleid",
+ array("rolename" => $roleName, "roledescription" => $roleDescription, "roleid" => $roleId));
+ Database::exec("DELETE FROM role_x_location
+ WHERE roleid = :roleid AND (locationid NOT IN (:locations) OR locationid IS NULL)",
+ array("roleid" => $roleId, 'locations' => $locations));
+ Database::exec("DELETE FROM role_x_permission
+ WHERE roleid = :roleid AND permissionid NOT IN (:permissions)",
+ array("roleid" => $roleId, 'permissions' => $permissions));
} else {
- Database::exec("INSERT INTO role (rolename) VALUES (:rolename)", array("rolename" => $rolename));
- $roleid = Database::lastInsertId();
+ Database::exec("INSERT INTO role (rolename, roledescription) VALUES (:rolename, :roledescription)",
+ array("rolename" => $roleName, "roledescription" => $roleDescription));
+ $roleId = Database::lastInsertId();
}
- foreach ($locations as $locationid) {
- Database::exec("INSERT INTO role_x_location (roleid, locationid) VALUES (:roleid, :locationid)",
- array("roleid" => $roleid, "locationid" => $locationid));
+
+ if (!empty($locations)) {
+ $arg = array_map(function ($loc) use ($roleId) {
+ return compact('roleId', 'loc');
+ }, $locations);
+ Database::exec("INSERT IGNORE INTO role_x_location (roleid, locationid) VALUES :arg", ['arg' => $arg]);
}
- foreach ($permissions as $permissionid) {
- Database::exec("INSERT INTO role_x_permission (roleid, permissionid) VALUES (:roleid, :permissionid)",
- array("roleid" => $roleid, "permissionid" => $permissionid));
+
+ if (!empty($permissions)) {
+ $arg = array_map(function ($perm) use ($roleId) {
+ return compact('roleId', 'perm');
+ }, $permissions);
+ Database::exec("INSERT IGNORE INTO role_x_permission (roleid, permissionid) VALUES :arg", ['arg' => $arg]);
}
}
diff --git a/modules-available/permissionmanager/inc/permissionutil.inc.php b/modules-available/permissionmanager/inc/permissionutil.inc.php
index 5ff41046..a3a2b610 100644
--- a/modules-available/permissionmanager/inc/permissionutil.inc.php
+++ b/modules-available/permissionmanager/inc/permissionutil.inc.php
@@ -2,6 +2,44 @@
class PermissionUtil
{
+
+ /**
+ * Generate all possible variants to match against, eg. $permissionid = a.b.c then we get:
+ * [ *, a.*, a.b.*, a.b.c ]
+ * In case $permissionid ends with an asterisk, also set $wildcard and $wclen, e.g.
+ * $permissionid = a.b.* --> $wildcard = a.b. and $wclen = 4
+ *
+ * @param $permission string|string[] permission to mangle
+ * @param string[] $compare all the generated variants
+ * @param string|false $wildcard if $permission is a wildcard string this returns the matching variant
+ * @param int|false $wclen if $permission is a wildcard string, this is the length of the matching variant
+ */
+ private static function makeComparisonVariants($permission, &$compare, &$wildcard, &$wclen)
+ {
+ if (!is_array($permission)) {
+ $permission = explode('.', $permission);
+ }
+ $partCount = count($permission);
+ $compare = [];
+ for ($i = 0; $i < $partCount; ++$i) {
+ $compare[] = $permission[0];
+ }
+ for ($i = 1; $i < $partCount; ++$i) {
+ $compare[$i - 1] .= '.*';
+ for ($j = $i; $j < $partCount; ++$j) {
+ $compare[$j] .= '.' . $permission[$i];
+ }
+ }
+ $compare[] = '*';
+
+ if ($permission[$partCount - 1] === '*') {
+ $wildcard = substr($compare[$partCount - 1], 0, -1);
+ $wclen = strlen($wildcard);
+ } else {
+ $wclen = $wildcard = false;
+ }
+ }
+
/**
* Check if the user has the given permission (for the given location).
*
@@ -10,26 +48,48 @@ class PermissionUtil
* @param int|null $locationid locationid to check or null if the location should be disregarded
* @return bool true if user has permission, false if not
*/
- public static function userHasPermission($userid, $permissionid, $locationid) {
- $locations = array();
- if (!is_null($locationid)) {
- $locations = Location::getLocationRootChain($locationid);
- if (count($locations) == 0) return false;
- else $locations[] = 0;
+ public static function userHasPermission($userid, $permissionid, $locationid)
+ {
+ $permissionid = strtolower($permissionid);
+ self::validatePermission($permissionid);
+ $parts = explode('.', $permissionid);
+ // Special case: To prevent lockout, userid === 1 always has permissionmanager.*
+ if ($parts[0] === 'permissionmanager' && User::getId() === 1)
+ return true;
+ // Limit query to first part of permissionid, which is always the module id
+ $prefix = $parts[0] . '.%';
+ if (is_null($locationid)) {
+ $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'));
+ } else {
+ if ($locationid === 0) {
+ $locations = [0];
+ } else {
+ $locations = Location::getLocationRootChain($locationid);
+ if (empty($locations)) { // Non-existent location, still continue as user might have global perms
+ $locations = [0];
+ }
+ }
+ $res = Database::simpleQuery("SELECT permissionid 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'));
}
+ // Quick bailout - no results
+ if ($res->rowCount() === 0)
+ return false;
- $res = Database::simpleQuery("SELECT permissionid, locationid FROM user_x_role
- INNER JOIN role_x_permission ON user_x_role.roleid = role_x_permission.roleid
- LEFT JOIN (SELECT roleid, COALESCE(locationid, 0) AS locationid FROM role_x_location) t1
- ON role_x_permission.roleid = t1.roleid
- WHERE user_x_role.userid = :userid", array("userid" => $userid));
-
+ // Compare to database result
+ self::makeComparisonVariants($parts, $compare, $wildcard, $wclen);
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
- $userPermission = rtrim($row["permissionid"], ".*").".";
- if ((is_null($locationid) || (!is_null($row["locationid"]) && in_array($row["locationid"], $locations))) &&
- (substr($permissionid.".", 0, strlen($userPermission)) === $userPermission || $userPermission === ".")) {
+ if (in_array($row['permissionid'], $compare, true))
+ return true;
+ if ($wildcard !== false && strncmp($row['permissionid'], $wildcard, $wclen) === 0)
return true;
- }
}
return false;
}
@@ -41,26 +101,40 @@ class PermissionUtil
* @param string $permissionid permissionid to check
* @return array array of locationids where the user has the given permission
*/
- public static function getAllowedLocations($userid, $permissionid) {
-
- $res = Database::simpleQuery("SELECT permissionid, COALESCE(locationid, 0) AS locationid FROM user_x_role
- INNER JOIN role_x_permission ON user_x_role.roleid = role_x_permission.roleid
- INNER JOIN role_x_location ON role_x_permission.roleid = role_x_location.roleid
- WHERE user_x_role.userid = :userid", array("userid" => $userid));
+ public static function getAllowedLocations($userid, $permissionid)
+ {
+ $permissionid = strtolower($permissionid);
+ self::validatePermission($permissionid);
+ $parts = explode('.', $permissionid);
+ // Special case: To prevent lockout, userid === 1 always has permissionmanager.*
+ if ($parts[0] === 'permissionmanager' && User::getId() === 1) {
+ $allowedLocations = [true];
+ } else {
+ // Limit query to first part of permissionid, which is always the module id
+ $prefix = $parts[0] . '.%';
+ $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 '*')",
+ compact('userid', 'prefix'));
- $allowedLocations = array();
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
- $userPermission = rtrim($row["permissionid"], ".*").".";
- if (substr($permissionid.".", 0, strlen($userPermission)) === $userPermission || $userPermission === ".") {
- $allowedLocations[$row["locationid"]] = 1;
+ // Gather locationid from relevant rows
+ self::makeComparisonVariants($parts, $compare, $wildcard, $wclen);
+ $allowedLocations = array();
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ if (in_array($row['permissionid'], $compare, true)
+ || ($wildcard !== false && strncmp($row['permissionid'], $wildcard, $wclen) === 0)) {
+ $allowedLocations[(int)$row['locationid']] = true;
+ }
}
}
- $allowedLocations = array_keys($allowedLocations);
$locations = Location::getTree();
- if (in_array("0", $allowedLocations)) {
- $allowedLocations = array_map("intval", Location::extractIds($locations));
- $allowedLocations[] = 0;
+ if (isset($allowedLocations[0])) {
+ // Trivial case - have permission for all locations, so populate list with all valid locationds
+ $allowedLocations = Location::extractIds($locations);
+ $allowedLocations[] = 0; // .. plus 0 to show that we have global perms
} else {
+ // We have a specific list of locationds - add any sublocations to list
$allowedLocations = self::getSublocations($locations, $allowedLocations);
}
return $allowedLocations;
@@ -70,17 +144,18 @@ class PermissionUtil
* Extend an array of locations by adding all sublocations.
*
* @param array $tree tree of all locations (structured like Location::getTree())
- * @param array $locations the array of locationids to extend
+ * @param array $allowedLocations the array of locationids to extend
* @return array extended array of locationids
*/
- public static function getSublocations($tree, $locations) {
- $result = array_flip($locations);
+ public static function getSublocations($tree, $allowedLocations)
+ {
+ $result = $allowedLocations;
foreach ($tree as $location) {
if (array_key_exists("children", $location)) {
- if (in_array($location["locationid"], $locations)) {
+ if (isset($allowedLocations[$location["locationid"]])) {
$result += array_flip(Location::extractIds($location["children"]));
} else {
- $result += array_flip(self::getSublocations($location["children"], $locations));
+ $result += array_flip(self::getSublocations($location["children"], $allowedLocations));
}
}
}
@@ -88,6 +163,37 @@ class PermissionUtil
}
/**
+ * If in debug mode, validate that the checked permission is actually defined
+ * in the according permissions.json and complain if that's not the case.
+ * This is supposed to catch misspelled permission checks.
+ *
+ * @param string $permissionId permission to check
+ */
+ private static function validatePermission($permissionId)
+ {
+ if (!CONFIG_DEBUG || $permissionId === '*')
+ return;
+ $split = explode('.', $permissionId, 2);
+ if (count($split) !== 2) {
+ trigger_error('[skip:3]Cannot check malformed permission "' . $permissionId . '"', E_USER_WARNING);
+ return;
+ }
+ if ($split[1] === '*')
+ return;
+ $data = json_decode(file_get_contents('modules/' . $split[0] . '/permissions/permissions.json'), true);
+ if (substr($split[1], -2) === '.*') {
+ $len = strlen($split[1]) - 1;
+ foreach ($data as $perm => $v) {
+ if (strncmp($split[1], $perm, $len) === 0)
+ return;
+ }
+ trigger_error('[skip:3]Permission "' . $permissionId . '" does not match anything defined for module', E_USER_WARNING);
+ } elseif (!is_array($data) || !array_key_exists($split[1], $data)) {
+ trigger_error('[skip:3]Permission "' . $permissionId . '" not defined for module', E_USER_WARNING);
+ }
+ }
+
+ /**
* Get all permissions of all active modules that have permissions in their permissions/permissions.json file.
*
* @return array permission tree as a multidimensional array
@@ -100,30 +206,62 @@ class PermissionUtil
if (!is_array($data))
continue;
preg_match('#^modules/([^/]+)/#', $file, $out);
- foreach( $data as $p ) {
- $description = Dictionary::translateFileModule($out[1], "permissions", $p);
- self::putInPermissionTree($out[1].".".$p, $description, $permissions);
+ $moduleId = $out[1];
+ if (Module::get($moduleId) === false)
+ continue;
+ foreach ($data as $perm => $permissionFlags) {
+ $description = Dictionary::translateFileModule($moduleId, "permissions", $perm);
+ self::putInPermissionTree($moduleId . "." . $perm, $permissionFlags['location-aware'], $description, $permissions);
}
}
ksort($permissions);
global $MENU_CAT_OVERRIDE;
$sortingOrder = $MENU_CAT_OVERRIDE;
- foreach ($permissions as $module => $v) $sortingOrder[Module::get($module)->getCategory()][] = $module;
+ foreach ($permissions as $module => $v) {
+ $sortingOrder[Module::get($module)->getCategory()][] = $module;
+ }
$permissions = array_replace(array_flip(call_user_func_array('array_merge', $sortingOrder)), $permissions);
- foreach ($permissions as $module => $v) if (is_int($v)) unset($permissions[$module]);
+ foreach ($permissions as $module => $v) {
+ if (is_int($v)) {
+ unset($permissions[$module]);
+ }
+ }
return $permissions;
}
/**
+ * Get all existing roles.
+ *
+ * @param int|false $userid Which user to consider, false = none
+ * @param bool $onlyMatching true = filter roles the user doesn't have
+ * @return array list of roles
+ */
+ public static function getRoles($userid = false, $onlyMatching = true)
+ {
+ if ($userid === false) {
+ return Database::queryAll('SELECT roleid, rolename FROM role ORDER BY rolename ASC');
+ }
+ $ret = Database::queryAll('SELECT r.roleid, r.rolename, u.userid AS hasRole FROM role r
+ LEFT JOIN role_x_user u ON (r.roleid = u.roleid AND u.userid = :userid)
+ GROUP BY r.roleid
+ ORDER BY rolename ASC', ['userid' => $userid]);
+ foreach ($ret as &$role) {
+ settype($role['hasRole'], 'bool');
+ }
+ return $ret;
+ }
+
+ /**
* Place a permission into the given permission tree.
*
* @param string $permission the permission to place in the tree
+ * @param bool $locationAware whether this permissions can be restricted to specific locations only
* @param string $description the description of the permission
* @param array $tree the permission tree to modify
*/
- private static function putInPermissionTree($permission, $description, &$tree)
+ private static function putInPermissionTree($permission, $locationAware, $description, &$tree)
{
$subPermissions = explode('.', $permission);
foreach ($subPermissions as $subPermission) {
@@ -134,6 +272,7 @@ class PermissionUtil
$tree =& $tree[$subPermission];
}
}
- $tree = $description;
+ $tree = array('description' => $description, 'location-aware' => $locationAware, 'isLeaf' => true);
}
+
} \ No newline at end of file
diff --git a/modules-available/permissionmanager/install.inc.php b/modules-available/permissionmanager/install.inc.php
index 71ee7a1e..7f9c80ef 100644
--- a/modules-available/permissionmanager/install.inc.php
+++ b/modules-available/permissionmanager/install.inc.php
@@ -5,20 +5,27 @@ $res = array();
$res[] = tableCreate('role', "
roleid int(10) unsigned NOT NULL AUTO_INCREMENT,
rolename varchar(200) NOT NULL,
+ roledescription TEXT,
PRIMARY KEY (roleid)
");
-$res[] = tableCreate('user_x_role', "
+if (tableExists('user_x_role')) {
+ if (tableExists('role_x_user')) {
+ Database::exec('DROP TABLE user_x_role');
+ } else {
+ $res[] = tableRename('user_x_role', 'role_x_user');
+ }
+}
+$res[] = tableCreate('role_x_user', "
userid int(10) unsigned NOT NULL,
roleid int(10) unsigned NOT NULL,
PRIMARY KEY (userid, roleid)
");
$res[] = tableCreate('role_x_location', "
- id int(10) unsigned NOT NULL AUTO_INCREMENT,
roleid int(10) unsigned NOT NULL,
locationid int(11),
- PRIMARY KEY (id)
+ CONSTRAINT role_loc UNIQUE (roleid, locationid)
");
$res[] = tableCreate('role_x_permission', "
@@ -27,24 +34,38 @@ $res[] = tableCreate('role_x_permission', "
PRIMARY KEY (roleid, permissionid)
");
+if (tableHasColumn('role_x_location', 'id')) {
+ $cnt = Database::exec('DELETE a FROM role_x_location a, role_x_location b
+ WHERE a.roleid = b.roleid AND (a.locationid = b.locationid OR (a.locationid IS NULL AND b.locationid IS NULL))
+ AND a.id > b.id');
+ $ret = Database::exec('ALTER TABLE role_x_location DROP COLUMN id,
+ ADD CONSTRAINT role_loc UNIQUE (roleid, locationid)');
+ if ($ret === false) {
+ $res[] = UPDATE_NOOP;
+ } else {
+ $res[] = UPDATE_DONE;
+ }
+
+}
+
if (!tableExists('user') || !tableExists('location')) {
finalResponse(UPDATE_RETRY, 'Cannot add constraint yet. Please retry.');
} else {
- $c = tableGetContraints('user_x_role', 'userid', 'user', 'userid');
+ $c = tableGetContraints('role_x_user', 'userid', 'user', 'userid');
if ($c === false)
finalResponse(UPDATE_FAILED, 'Cannot get constraints of user table: ' . Database::lastError());
if (empty($c)) {
- $alter = Database::exec('ALTER TABLE user_x_role ADD FOREIGN KEY (userid) REFERENCES user (userid) ON DELETE CASCADE ON UPDATE CASCADE');
+ $alter = Database::exec('ALTER TABLE role_x_user ADD FOREIGN KEY (userid) REFERENCES user (userid) ON DELETE CASCADE ON UPDATE CASCADE');
if ($alter === false)
finalResponse(UPDATE_FAILED, 'Cannot add userid constraint referencing user table: ' . Database::lastError());
$res[] = UPDATE_DONE;
}
- $c = tableGetContraints('user_x_role', 'roleid', 'role', 'roleid');
+ $c = tableGetContraints('role_x_user', 'roleid', 'role', 'roleid');
if ($c === false)
finalResponse(UPDATE_FAILED, 'Cannot get constraints of role table: ' . Database::lastError());
if (empty($c)) {
- $alter = Database::exec('ALTER TABLE user_x_role ADD FOREIGN KEY (roleid) REFERENCES role (roleid) ON DELETE CASCADE ON UPDATE CASCADE');
+ $alter = Database::exec('ALTER TABLE role_x_user ADD FOREIGN KEY (roleid) REFERENCES role (roleid) ON DELETE CASCADE ON UPDATE CASCADE');
if ($alter === false)
finalResponse(UPDATE_FAILED, 'Cannot add roleid constraint referencing role table: ' . Database::lastError());
$res[] = UPDATE_DONE;
@@ -80,6 +101,108 @@ if (!tableExists('user') || !tableExists('location')) {
$res[] = UPDATE_DONE;
}
}
+
+// 2018-04-13 role description field; add a couple default roles
+if (!tableHasColumn('role', 'roledescription')) {
+ $alter = Database::exec("ALTER TABLE role ADD roledescription TEXT");
+ if ($alter === false)
+ finalResponse(UPDATE_FAILED, 'Cannot add roledescription field to table role: ' . Database::lastError());
+ $res[] = UPDATE_DONE;
+}
+
+if (!tableHasColumn('role', 'roledescription')) {
+ finalResponse(UPDATE_RETRY, 'Try again later');
+}
+
+if (Database::exec("INSERT INTO `role` VALUES
+ (1,'Super-Admin', 'Hat keinerlei Zugriffsbeschränkungen'),
+ (2,'Admin', 'Alles bis auf Rechte-/Nutzerverwaltung'),
+ (3,'Prüfungsadmin', 'Kann E-Prüfungen verwalten, Prüfungsmodus einschalten, etc.'),
+ (4,'Lesezugriff', 'Kann auf die meisten Seiten zugreifen, jedoch keine Änderungen vornehmen')") !== false) {
+ // Success, there probably were no roles before, keep going
+ // Assign roles to location (all)
+ Database::exec("INSERT INTO `role_x_location` VALUES (1,NULL),(2,NULL),(3,NULL),(4,NULL)");
+ // Assign permissions to roles
+ Database::exec("INSERT INTO `role_x_permission` VALUES
+ (3,'exams.exams.*'),
+ (3,'rebootcontrol.action.*'),
+ (3,'statistics.hardware.projectors.view'),
+ (3,'statistics.machine.note.*'),
+ (3,'statistics.machine.view-details'),
+ (3,'statistics.view.*'),
+ (3,'syslog.view'),
+
+ (1,'*'),
+
+ (4,'adduser.user.view-list'),
+ (4,'backup.create'),
+ (4,'baseconfig.view'),
+ (4,'dnbd3.access-page'),
+ (4,'dnbd3.refresh'),
+ (4,'dnbd3.view.details'),
+ (4,'dozmod.actionlog.view'),
+ (4,'dozmod.users.view'),
+ (4,'eventlog.view'),
+ (4,'exams.exams.view'),
+ (4,'locationinfo.backend.check'),
+ (4,'locationinfo.panel.list'),
+ (4,'locations.location.view'),
+ (4,'minilinux.view'),
+ (4,'news.*'),
+ (4,'permissionmanager.locations.view'),
+ (4,'permissionmanager.roles.view'),
+ (4,'permissionmanager.users.view'),
+ (4,'runmode.list-all'),
+ (4,'serversetup.access-page'),
+ (4,'serversetup.download'),
+ (4,'statistics.hardware.projectors.view'),
+ (4,'statistics.machine.note.view'),
+ (4,'statistics.machine.view-details'),
+ (4,'statistics.view.*'),
+ (4,'statistics_reporting.reporting.download'),
+ (4,'statistics_reporting.table.export'),
+ (4,'statistics_reporting.table.view.*'),
+ (4,'sysconfig.config.view-list'),
+ (4,'sysconfig.module.download'),
+ (4,'sysconfig.module.view-list'),
+ (4,'syslog.view'),
+ (4,'systemstatus.show.overview.*'),
+ (4,'systemstatus.tab.*'),
+ (4,'webinterface.access-page'),
+
+ (2,'adduser.user.view-list'),
+ (2,'backup.*'),
+ (2,'baseconfig.*'),
+ (2,'dnbd3.*'),
+ (2,'dozmod.*'),
+ (2,'eventlog.view'),
+ (2,'exams.exams.*'),
+ (2,'locationinfo.*'),
+ (2,'locations.*'),
+ (2,'minilinux.*'),
+ (2,'news.*'),
+ (2,'permissionmanager.locations.view'),
+ (2,'permissionmanager.roles.view'),
+ (2,'permissionmanager.users.view'),
+ (2,'rebootcontrol.*'),
+ (2,'roomplanner.edit'),
+ (2,'runmode.list-all'),
+ (2,'serversetup.*'),
+ (2,'statistics.*'),
+ (2,'statistics_reporting.*'),
+ (2,'sysconfig.*'),
+ (2,'syslog.*'),
+ (2,'systemstatus.*'),
+ (2,'vmstore.edit'),
+ (2,'webinterface.*')");
+ // Asign the first user to the superadmin role (if one exists)
+ Database::exec("INSERT INTO `role_x_user` VALUES (1,1)");
+ $res[] = UPDATE_DONE;
+}
+
+//
+//
+
if (in_array(UPDATE_DONE, $res)) {
finalResponse(UPDATE_DONE, 'Tables created successfully');
}
diff --git a/modules-available/permissionmanager/lang/de/permissions.json b/modules-available/permissionmanager/lang/de/permissions.json
new file mode 100644
index 00000000..444c1e8c
--- /dev/null
+++ b/modules-available/permissionmanager/lang/de/permissions.json
@@ -0,0 +1,7 @@
+{
+ "locations.view": "Orte mit zugewiesenen Rollen sehen.",
+ "roles.edit": "Rollen bearbeiten.",
+ "roles.view": "Rollen sehen.",
+ "users.edit-roles": "Benutzern Rollen zuweisen oder entziehen.",
+ "users.view": "Benutzer mit zugewiesenen Rolen sehen."
+} \ No newline at end of file
diff --git a/modules-available/permissionmanager/lang/de/template-tags.json b/modules-available/permissionmanager/lang/de/template-tags.json
index 71bd4075..504ef6d2 100644
--- a/modules-available/permissionmanager/lang/de/template-tags.json
+++ b/modules-available/permissionmanager/lang/de/template-tags.json
@@ -1,24 +1,24 @@
{
- "lang_roles": "Rollen",
- "lang_users": "Nutzer",
- "lang_locations": "Räume",
"lang_addRole": "Rollen erteilen",
- "lang_removeRole": "Rollen entziehen",
- "lang_newRole": "Rolle anlegen",
- "lang_selected": "Ausgewählt",
- "lang_edit": "Bearbeiten",
- "lang_delete": "Löschen",
- "lang_removeCheck": "Sind Sie sich sicher, dass Sie diese Rolle entfernen wollen?",
- "lang_deleteCheck": "Sind Sie sich sicher, dass Sie diese Rolle löschen wollen?",
- "lang_emptyNameWarning": "Der Name der Rolle darf nicht leer sein!",
+ "lang_addRoleHeading": "Neue Rolle hinzuf\u00fcgen",
+ "lang_description": "Beschreibung",
+ "lang_editRoleHeading": "Rolle bearbeiten",
+ "lang_locationAwareDesc": "Berechtigungen mit diesem Symbol k\u00f6nnen auf bestimmte R\u00e4ume\/Orte beschr\u00e4nkt werden. Alle anderen Berechtigungen sind unabh\u00e4ngig von den f\u00fcr diese Rolle ausgew\u00e4hlten Orten.",
+ "lang_locations": "R\u00e4ume",
+ "lang_moduleName": "Rechtemanager",
"lang_name": "Name",
- "lang_cancel": "Abbrechen",
- "lang_save": "Speichern",
- "lang_all": "alle",
- "lang_selected": "ausgewählte",
+ "lang_newRole": "Rolle anlegen",
+ "lang_numAssignedUsers": "Benutzer mit dieser Rolle",
+ "lang_permission": "Berechtigung",
+ "lang_permissionDeniedBody": "Ihnen fehlt eine oder mehrere Berechtigungen, um auf diese Seite oder Funktion zuzugreifen.",
+ "lang_permissionDeniedHeader": "Zugriff verweigert",
"lang_permissions": "Rechte",
- "lang_selectizePlaceholder": "Nach Rollen filtern...",
+ "lang_removeRole": "Rollen entziehen",
+ "lang_roleDeleteConfirm": "Sind Sie sich sicher, dass Sie diese Rolle l\u00f6schen m\u00f6chten? Benutzer, denen diese Rolle zugewiesen ist, werden die entsprechenden Berechtigungen verlieren.",
+ "lang_roles": "Rollen",
"lang_searchPlaceholder": "Nach Rollen suchen...",
- "lang_moduleName": "Rechtemanager",
- "lang_roleEditor": "Rollen Editor"
+ "lang_selected": "ausgew\u00e4hlte",
+ "lang_selectizePlaceholder": "Nach Rollen filtern...",
+ "lang_users": "Nutzer",
+ "lang_view": "Anzeigen"
} \ No newline at end of file
diff --git a/modules-available/permissionmanager/lang/en/permissions.json b/modules-available/permissionmanager/lang/en/permissions.json
new file mode 100644
index 00000000..9f7263db
--- /dev/null
+++ b/modules-available/permissionmanager/lang/en/permissions.json
@@ -0,0 +1,7 @@
+{
+ "locations.view": "See locations with assigned roles.",
+ "roles.edit": "Edit roles.",
+ "roles.view": "Show roles.",
+ "users.edit-roles": "Assign or remove roles from users.",
+ "users.view": "See users with assigned roles."
+} \ No newline at end of file
diff --git a/modules-available/permissionmanager/lang/en/template-tags.json b/modules-available/permissionmanager/lang/en/template-tags.json
index 2d31b294..6f1fa614 100644
--- a/modules-available/permissionmanager/lang/en/template-tags.json
+++ b/modules-available/permissionmanager/lang/en/template-tags.json
@@ -1,24 +1,24 @@
{
- "lang_roles": "Roles",
- "lang_users": "Users",
- "lang_locations": "Locations",
"lang_addRole": "Grant Roles",
- "lang_removeRole": "Revoke Roles",
- "lang_newRole": "New Role",
- "lang_selected": "Selected",
- "lang_edit": "Edit",
- "lang_delete": "Delete",
- "lang_removeCheck": "Are you sure you want to remove this role?",
- "lang_deleteCheck": "Are you sure you want to delete this role?",
- "lang_emptyNameWarning": "Role name can not be empty!",
+ "lang_addRoleHeading": "Add new role",
+ "lang_description": "Description",
+ "lang_editRoleHeading": "Edit role",
+ "lang_locationAwareDesc": "Permissions with this symbol can be restricted to certain locations. All other permissions are independent of the locations selected for this role.",
+ "lang_locations": "Locations",
+ "lang_moduleName": "Permission Manager",
"lang_name": "Name",
- "lang_cancel": "Cancel",
- "lang_save": "Save",
- "lang_all": "all",
- "lang_selected": "selected",
+ "lang_newRole": "New Role",
+ "lang_numAssignedUsers": "Users with this role",
+ "lang_permission": "Permission",
+ "lang_permissionDeniedBody": "You are missing one or more permissions to access this page or functionality.",
+ "lang_permissionDeniedHeader": "Access denied",
"lang_permissions": "Permissions",
- "lang_selectizePlaceholder": "Filter for roles...",
+ "lang_removeRole": "Revoke Roles",
+ "lang_roleDeleteConfirm": "Are you sure you want to delete this role? Users currently assigned to this role will lose the according permissions.",
+ "lang_roles": "Roles",
"lang_searchPlaceholder": "Search for roles...",
- "lang_moduleName": "Permission Manager",
- "lang_roleEditor": "Role Editor"
+ "lang_selected": "selected",
+ "lang_selectizePlaceholder": "Filter for roles...",
+ "lang_users": "Users",
+ "lang_view": "View"
} \ No newline at end of file
diff --git a/modules-available/permissionmanager/page.inc.php b/modules-available/permissionmanager/page.inc.php
index 13d81c6a..462d3163 100644
--- a/modules-available/permissionmanager/page.inc.php
+++ b/modules-available/permissionmanager/page.inc.php
@@ -17,22 +17,38 @@ class Page_PermissionManager extends Page
$action = Request::any('action', 'show', 'string');
if ($action === 'addRoleToUser') {
+ User::assertPermission('users.edit-roles');
$users = Request::post('users', '');
$roles = Request::post('roles', '');
PermissionDbUpdate::addRoleToUser($users, $roles);
} elseif ($action === 'removeRoleFromUser') {
+ User::assertPermission('users.edit-roles');
$users = Request::post('users', '');
$roles = Request::post('roles', '');
PermissionDbUpdate::removeRoleFromUser($users, $roles);
} elseif ($action === 'deleteRole') {
- $id = Request::post('deleteId', false, 'string');
+ User::assertPermission('roles.edit');
+ $id = Request::post('deleteId', false, 'int');
PermissionDbUpdate::deleteRole($id);
} elseif ($action === 'saveRole') {
- $roleID = Request::post("roleid", false);
- $rolename = Request::post("rolename");
- $locations = self::processLocations(Request::post("locations"));
+ User::assertPermission('roles.edit');
+ $roleID = Request::post("roleid", false, 'int');
+ if ($roleID === false) {
+ Message::addError('main.parameter-missing', 'roleid');
+ Util::redirect('?do=permissionmanager');
+ }
+ $roleName = Request::post("rolename", '', 'string');
+ if (empty($roleName)) {
+ Message::addError('main.parameter-empty', 'rolename');
+ Util::redirect('?do=permissionmanager');
+ }
+ $roleDescription = Request::post('roledescription', '', 'string');
+ $locations = self::processLocations(Request::post("locations", [], 'array'));
$permissions = self::processPermissions(Request::post("permissions"));
- PermissionDbUpdate::saveRole($rolename, $locations, $permissions, $roleID);
+ PermissionDbUpdate::saveRole($roleName, $roleDescription, $locations, $permissions, $roleID);
+ }
+ if (Request::isPost()) {
+ Util::redirect('?do=permissionmanager&show=' . Request::get("show", "roles"));
}
}
@@ -41,47 +57,76 @@ class Page_PermissionManager extends Page
*/
protected function doRender()
{
- $show = Request::get("show", "roles");
+ $show = Request::get("show", false, 'string');
+
+ // "Public" page -- nice "permission denied" message
+ if ($show === 'denied') {
+ Render::addTemplate('page-permission-denied', [
+ 'name' => User::getName(),
+ 'permission' => Request::get('permission', false, 'string'),
+ ]);
+ return;
+ }
+
+ if ($show === false) {
+ foreach (['roles', 'users', 'locations'] as $show) {
+ if (User::hasPermission($show . '.*'))
+ break;
+ }
+ }
// switch between tables, but always show menu to switch tables
- if ( $show === 'roles' || $show === 'users' || $show === 'locations' ) {
- // get menu button colors
- $buttonColors = array();
- $buttonColors['rolesButtonClass'] = $show === 'roles' ? 'active' : '';
- $buttonColors['usersButtonClass'] = $show === 'users' ? 'active' : '';
- $buttonColors['locationsButtonClass'] = $show === 'locations' ? 'active' : '';
-
- Render::addtemplate('_page', $buttonColors);
-
- if ($show === "roles") {
- $data = array("roles" => GetPermissionData::getRoles());
- Render::addTemplate('rolestable', $data);
- } elseif ($show === "users") {
- $data = array("user" => GetPermissionData::getUserData(), "roles" => GetPermissionData::getRoles());
- Render::addTemplate('userstable', $data);
- } elseif ($show === "locations") {
- $data = array("location" => GetPermissionData::getLocationData(), "allroles" => GetPermissionData::getRoles());
- Render::addTemplate('locationstable', $data);
+ // get menu button colors
+ $data = array();
+ if ($show === "roleEditor") {
+ $data['groupClass'] = 'btn-group-muted';
+ $data['rolesButtonClass'] = 'active';
+ } else {
+ $data[$show . 'ButtonClass'] = 'active';
+ }
+ Permission::addGlobalTags($data['perms'], null, ['roles.*', 'users.*', 'locations.*']);
+
+ Render::addtemplate('header-menu', $data);
+
+ if ($show === "roles") {
+ User::assertPermission('roles.*');
+ $data = array("roles" => GetPermissionData::getRoles(GetPermissionData::WITH_USER_COUNT));
+ Permission::addGlobalTags($data['perms'], null, ['roles.edit']);
+ Render::addTemplate('rolestable', $data);
+ } elseif ($show === "users") {
+ User::assertPermission('users.*');
+ $data = array("user" => GetPermissionData::getUserData());
+ if (User::hasPermission('users.edit-roles')) {
+ $data['allroles'] = GetPermissionData::getRoles();
}
+ Permission::addGlobalTags($data['perms'], null, ['users.edit-roles']);
+ Render::addTemplate('role-filter-selectize', $data);
+ Render::addTemplate('userstable', $data);
+ } elseif ($show === "locations") {
+ User::assertPermission('locations.*');
+ $data = array("location" => GetPermissionData::getLocationData(), "allroles" => GetPermissionData::getRoles());
+ Render::addTemplate('role-filter-selectize', $data);
+ Render::addTemplate('locationstable', $data);
} elseif ($show === "roleEditor") {
- $data = array("cancelShow" => Request::get("cancel", "roles"));
+ User::assertPermission('roles.*');
+ $data = array("cancelShow" => Request::get("cancel", "roles", 'string'));
+ Permission::addGlobalTags($data['perms'], null, ['roles.edit']);
$selectedPermissions = array();
$selectedLocations = array();
- $roleid = Request::get("roleid", false);
- if ($roleid) {
- $roleData = GetPermissionData::getRoleData($roleid);
- $data["roleid"] = $roleid;
- $data["rolename"] = $roleData["rolename"];
- $selectedPermissions = $roleData["permissions"];
- $selectedLocations = $roleData["locations"];
+ $roleid = Request::get("roleid", false, 'int');
+ if ($roleid !== false) {
+ $data += GetPermissionData::getRoleData($roleid);
+ $selectedPermissions = $data["permissions"];
+ $selectedLocations = $data["locations"];
}
- $data["permissionHTML"] = self::generatePermissionHTML(PermissionUtil::getPermissions(), $selectedPermissions);
- $data["locationHTML"] = self::generateLocationHTML(Location::getTree(), $selectedLocations);
+ $data["permissionHTML"] = self::generatePermissionHTML(PermissionUtil::getPermissions(), $selectedPermissions,
+ false, '', ['perms' => $data['perms']]);
+ $data["locationHTML"] = self::generateLocationHTML(Location::getTree(), $selectedLocations,
+ $roleid === false, true, ['perms' => $data['perms']]);
Render::addTemplate('roleeditor', $data);
-
}
}
@@ -90,36 +135,57 @@ class Page_PermissionManager extends Page
*
* @param array $permissions the permission tree
* @param array $selectedPermissions permissions that should be preselected
- * @param array $selectAll true if all pemrissions should be preselected, false if only those in $selectedPermissions
- * @param array $permString the prefix permission string with which all permissions in the permission tree should start
+ * @param bool $selectAll true if all permissions should be preselected, false if only those in $selectedPermissions
+ * @param string $permString the prefix permission string with which all permissions in the permission tree should start
* @return string generated html code
*/
- private static function generatePermissionHTML($permissions, $selectedPermissions = array(), $selectAll = false, $permString = "")
+ private static function generatePermissionHTML($permissions, $selectedPermissions = array(), $selectAll = false, $permString = "", $tags = [])
{
$res = "";
$toplevel = $permString == "";
- if ($toplevel && in_array("*", $selectedPermissions)) $selectAll = true;
+ if ($toplevel && in_array("*", $selectedPermissions)) {
+ $selectAll = true;
+ }
foreach ($permissions as $k => $v) {
- $leaf = !is_array($v);
- $nextPermString = $permString ? $permString.".".$k : $k;
- $id = $leaf ? $nextPermString : $nextPermString.".*";
- $selected = $selectAll || in_array($id, $selectedPermissions);
- $res .= Render::parse("treenode",
- array("id" => $id,
- "name" => $toplevel ? Module::get($k)->getDisplayName() : $k,
- "toplevel" => $toplevel,
- "checkboxname" => "permissions",
- "selected" => $selected,
- "HTML" => $leaf ? "" : self::generatePermissionHTML($v, $selectedPermissions, $selected, $nextPermString),
- "description" => $leaf ? $v : ""));
+ $selected = $selectAll;
+ $nextPermString = $permString ? $permString . "." . $k : $k;
+ if ($toplevel) {
+ $displayName = Module::get($k)->getDisplayName();
+ } else {
+ $displayName = $k;
+ }
+ do {
+ $leaf = isset($v['isLeaf']) && $v['isLeaf'];
+ $id = $leaf ? $nextPermString : $nextPermString . ".*";
+ $selected = $selected || in_array($id, $selectedPermissions);
+ if ($leaf || count($v) !== 1)
+ break;
+ reset($v);
+ $k = key($v);
+ $v = $v[$k];
+ $nextPermString .= '.' . $k;
+ $displayName .= '.' . $k;
+ } while (true);
+ $data = array(
+ "id" => $id,
+ "name" => $displayName,
+ "toplevel" => $toplevel,
+ "checkboxname" => "permissions",
+ "selected" => $selected,
+ "HTML" => $leaf ? "" : self::generatePermissionHTML($v, $selectedPermissions, $selected, $nextPermString, $tags),
+ );
+ if ($leaf) {
+ $data += $v;
+ }
+ $res .= Render::parse("treenode", $data + $tags);
}
if ($toplevel) {
$res = Render::parse("treepanel",
array("id" => "*",
- "name" => Dictionary::translateFile("template-tags", "lang_permissions"),
- "checkboxname" => "permissions",
- "selected" => $selectAll,
- "HTML" => $res));
+ "name" => Dictionary::translateFile("template-tags", "lang_permissions"),
+ "checkboxname" => "permissions",
+ "selected" => $selectAll,
+ "HTML" => $res) + $tags);
}
return $res;
}
@@ -133,28 +199,31 @@ class Page_PermissionManager extends Page
* @param array $toplevel true if the location tree are the children of the root location, false if not
* @return string generated html code
*/
- private static function generateLocationHTML($locations, $selectedLocations = array(), $selectAll = false, $toplevel = true)
+ private static function generateLocationHTML($locations, $selectedLocations = array(), $selectAll = false, $toplevel = true, $tags = [])
{
$res = "";
- if ($toplevel && in_array(0, $selectedLocations)) $selectAll = true;
+ if ($toplevel && in_array(0, $selectedLocations)) {
+ $selectAll = true;
+ }
foreach ($locations as $location) {
$selected = $selectAll || in_array($location["locationid"], $selectedLocations);
$res .= Render::parse("treenode",
- array("id" => $location["locationid"],
- "name" => $location["locationname"],
- "toplevel" => $toplevel,
- "checkboxname" => "locations",
- "selected" => $selected,
- "HTML" => array_key_exists("children", $location) ?
- self::generateLocationHTML($location["children"], $selectedLocations, $selected, false) : ""));
+ array("id" => $location["locationid"],
+ "name" => $location["locationname"],
+ "toplevel" => $toplevel,
+ "checkboxname" => "locations",
+ "selected" => $selected,
+ "HTML" => array_key_exists("children", $location) ?
+ self::generateLocationHTML($location["children"], $selectedLocations, $selected, false, $tags) : "")
+ + $tags);
}
if ($toplevel) {
$res = Render::parse("treepanel",
array("id" => 0,
- "name" => Dictionary::translateFile("template-tags", "lang_locations"),
- "checkboxname" => "locations",
- "selected" => $selectAll,
- "HTML" => $res));
+ "name" => Dictionary::translateFile("template-tags", "lang_locations"),
+ "checkboxname" => "locations",
+ "selected" => $selectAll,
+ "HTML" => $res) + $tags);
}
return $res;
}
@@ -167,12 +236,14 @@ class Page_PermissionManager extends Page
*/
private static function processLocations($locations)
{
- if (in_array(0, $locations)) return array(NULL);
+ if (in_array(0, $locations))
+ return array(null);
$result = array();
foreach ($locations as $location) {
$rootchain = array_reverse(Location::getLocationRootChain($location));
foreach ($rootchain as $l) {
- if (in_array($l, $result)) break;
+ if (in_array($l, $result))
+ break;
if (in_array($l, $locations)) {
$result[] = $l;
break;
@@ -190,7 +261,8 @@ class Page_PermissionManager extends Page
*/
private static function processPermissions($permissions)
{
- if (in_array("*", $permissions)) return array("*");
+ if (in_array("*", $permissions))
+ return array("*");
$result = array();
foreach ($permissions as $permission) {
$x =& $result;
@@ -213,10 +285,10 @@ class Page_PermissionManager extends Page
foreach ($permissions as $permission => $a) {
if (is_array($a)) {
if (array_key_exists("*", $a)) {
- $result[] = $permission.".*";
+ $result[] = $permission . ".*";
} else {
foreach (self::extractPermissions($a) as $subPermission) {
- $result[] = $permission.".".$subPermission;
+ $result[] = $permission . "." . $subPermission;
}
}
} else {
diff --git a/modules-available/permissionmanager/permissions/permissions.json b/modules-available/permissionmanager/permissions/permissions.json
new file mode 100644
index 00000000..3981a2c3
--- /dev/null
+++ b/modules-available/permissionmanager/permissions/permissions.json
@@ -0,0 +1,17 @@
+{
+ "roles.view": {
+ "location-aware": false
+ },
+ "roles.edit": {
+ "location-aware": false
+ },
+ "users.view": {
+ "location-aware": false
+ },
+ "users.edit-roles": {
+ "location-aware": false
+ },
+ "locations.view": {
+ "location-aware": false
+ }
+} \ No newline at end of file
diff --git a/modules-available/permissionmanager/style.css b/modules-available/permissionmanager/style.css
index 49d631a8..dca38eeb 100644
--- a/modules-available/permissionmanager/style.css
+++ b/modules-available/permissionmanager/style.css
@@ -1,82 +1,46 @@
-#switchForm {
- text-align: center;
- margin-bottom: 50px;
-}
-
-#saveButton {
- margin-left: 10px;
-}
-
-#rolename {
- width: 200px;
- display: inline-block;
- margin-left: 10px;
-}
-
-.missingInput {
- border-color: rgba(255, 0, 0, 0.8);
- box-shadow: 0 1px 1px rgba(255, 0, 0, 0.075) inset, 0 0 8px rgba(255, 0, 0, 0.6);
-}
-
.table {
margin-top: 20px;
}
-.table > tbody > tr > td {
- vertical-align: middle;
- height: 50px;
-}
-
.scrollingTable {
height: 500px;
overflow: auto;
}
-.customSpanMargin {
+/* vcenter .label in table cell */
+td > .label {
display: inline-block;
- margin-top: 2px;
- margin-bottom: 2px;
+ margin: 2px 0;
}
-.panel-primary > .panel-heading {
- background-image: none;
+/* lists in tree view: hide bullet points, first entry bold, ... */
+.tree-container ul {
+ list-style-type: none;
}
-.panel{
- margin-bottom: 20px;
+.tree-container > ul {
+ display: inline-block;
+ width: 100%;
+ padding: 0;
}
-.selectize-input {
- overflow: visible;
-}
-
-
-.tree-container .selected {
- background-color: rgba(0, 182, 41, 0.23);
+.tree-container > ul > li > div > label {
+ font-weight: bold;
}
+/* number of columns in tree view depending on screen size */
.tree-container {
-moz-column-gap: 20px;
-webkit-column-gap: 20px;
column-gap: 20px;
+ -moz-column-count: 1;
+ -webkit-column-count: 1;
+ column-count: 1;
+ padding-left: 20px;
+ padding-right: 20px;
}
-
-.tree-container > ul {
- display: inline-block;
- width: 100%;
- padding: 0;
-}
-
-@media (max-width: 767px) {
- .tree-container {
- -moz-column-count: 1;
- -webkit-column-count: 1;
- column-count: 1;
- }
-}
-
-@media (min-width: 768px) and (max-width: 991px) {
+@media (min-width: 768px) {
.tree-container {
-moz-column-count: 2;
-webkit-column-count: 2;
@@ -92,6 +56,11 @@
}
}
-ul {
- list-style-type: none;
-} \ No newline at end of file
+.btn-group-muted > button {
+ color: #aaa;
+}
+
+h1 span.glyphicon {
+ top: 9px;
+}
+
diff --git a/modules-available/permissionmanager/templates/_page.html b/modules-available/permissionmanager/templates/_page.html
deleted file mode 100644
index 4140ce78..00000000
--- a/modules-available/permissionmanager/templates/_page.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<div class="row">
- <div class="col-md-12" style="margin-bottom: 0;">
- <div class='page-header'>
- <div class='pull-right'>
- <form id="switchForm" method="GET" action="?do=permissionmanager">
- <input type="hidden" name="do" value="permissionmanager">
-
- <div class="btn-group">
- <button class="btn btn-default {{rolesButtonClass}}" type="submit" name="show" value="roles">
- <span class="glyphicon glyphicon-education"></span>
- {{lang_roles}}
- </button>
-
- <button class="btn btn-default {{usersButtonClass}}" type="submit" name="show" value="users">
- <span class="glyphicon glyphicon-user"></span>
- {{lang_users}}
- </button>
-
- <button class="btn btn-default {{locationsButtonClass}}" type="submit" name="show" value="locations">
- <span class="glyphicon glyphicon-home"></span>
- {{lang_locations}}
- </button>
- </div>
- </form>
- </div>
- <h1>{{lang_moduleName}}</h1>
- </div>
- </div>
-</div> \ No newline at end of file
diff --git a/modules-available/permissionmanager/templates/header-menu.html b/modules-available/permissionmanager/templates/header-menu.html
new file mode 100644
index 00000000..91bfa3af
--- /dev/null
+++ b/modules-available/permissionmanager/templates/header-menu.html
@@ -0,0 +1,25 @@
+<div class='page-header'>
+ <div class='pull-right'>
+ <form method="GET">
+ <input type="hidden" name="do" value="permissionmanager">
+
+ <div class="btn-group {{groupClass}}">
+ <button class="btn btn-default {{rolesButtonClass}}" type="submit" name="show" value="roles" {{perms.roles.disabled}}>
+ <span class="glyphicon glyphicon-education"></span>
+ {{lang_roles}}
+ </button>
+
+ <button class="btn btn-default {{usersButtonClass}}" type="submit" name="show" value="users" {{perms.users.disabled}}>
+ <span class="glyphicon glyphicon-user"></span>
+ {{lang_users}}
+ </button>
+
+ <button class="btn btn-default {{locationsButtonClass}}" type="submit" name="show" value="locations" {{perms.locations.disabled}}>
+ <span class="glyphicon glyphicon-home"></span>
+ {{lang_locations}}
+ </button>
+ </div>
+ </form>
+ </div>
+ <h1>{{lang_moduleName}}</h1>
+</div> \ No newline at end of file
diff --git a/modules-available/permissionmanager/templates/locationstable.html b/modules-available/permissionmanager/templates/locationstable.html
index 153258fe..35058387 100644
--- a/modules-available/permissionmanager/templates/locationstable.html
+++ b/modules-available/permissionmanager/templates/locationstable.html
@@ -1,37 +1,21 @@
-<div class="row">
- <div class="col-md-4"></div>
- <div class="col-md-4">
- <select multiple name="roles[]" id="select-role">
- <option value>{{lang_selectizePlaceholder}}</option>
- {{#allroles}}
- <option value="{{roleid}}">{{rolename}}</option>
- {{/allroles}}
- </select>
- </div>
-</div>
+<table id="locationsTable" class="table table-condensed table-hover dataTable">
+ <thead>
+ <tr>
+ <th>{{lang_locations}}</th>
+ <th class="slx-smallcol">{{lang_roles}}</th>
+ </tr>
+ </thead>
-<div class="row">
- <div class="col-md-12">
- <table id="locationsTable" class="table table-condensed table-hover stupidtable dataTable">
- <thead>
- <tr>
- <th data-sort="string">{{lang_locations}}</th>
- <th>{{lang_roles}}</th>
- </tr>
- </thead>
-
- <tbody>
- {{#location}}
- <tr data-selectizeCount='0'>
- <td>{{locationpad}} {{locationname}}</td>
- <td>
- {{#roles}}
- <a href="?do=permissionmanager&show=roleEditor&cancel=locations&roleid={{roleid}}" class="label label-default customSpanMargin roleid-{{roleid}}">{{rolename}}</a>
- {{/roles}}
- </td>
- </tr>
- {{/location}}
- </tbody>
- </table>
- </div>
-</div> \ No newline at end of file
+ <tbody>
+ {{#location}}
+ <tr class="{{#roles}}roleid-{{roleid}} {{/roles}}">
+ <td>{{locationpad}} {{locationname}}</td>
+ <td class="slx-smallcol">
+ {{#roles}}
+ <a href="?do=permissionmanager&show=roleEditor&cancel=locations&roleid={{roleid}}" class="label label-default customSpanMargin">{{rolename}}</a>
+ {{/roles}}
+ </td>
+ </tr>
+ {{/location}}
+ </tbody>
+</table> \ No newline at end of file
diff --git a/modules-available/permissionmanager/templates/page-permission-denied.html b/modules-available/permissionmanager/templates/page-permission-denied.html
new file mode 100644
index 00000000..cc357a0b
--- /dev/null
+++ b/modules-available/permissionmanager/templates/page-permission-denied.html
@@ -0,0 +1,21 @@
+<br><br>
+<div class="jumbotron">
+ <h1>
+ <span class="text-danger">
+ <span class="glyphicon glyphicon-ban-circle"></span>
+ {{lang_permissionDeniedHeader}}
+ </span>
+ </h1>
+ <br><br>
+ <p>
+ {{lang_permissionDeniedBody}}
+ </p>
+ {{#permission}}
+ <div>
+ {{lang_permission}}: <b>{{permission}}</b>
+ </div>
+ {{/permission}}
+ <div>
+ {{lang_user}}: <b>{{name}}</b>
+ </div>
+</div>
diff --git a/modules-available/permissionmanager/templates/role-filter-selectize.html b/modules-available/permissionmanager/templates/role-filter-selectize.html
new file mode 100644
index 00000000..ceadec75
--- /dev/null
+++ b/modules-available/permissionmanager/templates/role-filter-selectize.html
@@ -0,0 +1,6 @@
+<select multiple id="select-role">
+ <option value>{{lang_selectizePlaceholder}}</option>
+ {{#allroles}}
+ <option value="{{roleid}}">{{rolename}}</option>
+ {{/allroles}}
+</select> \ No newline at end of file
diff --git a/modules-available/permissionmanager/templates/roleeditor.html b/modules-available/permissionmanager/templates/roleeditor.html
index 871fd0cc..c464c1fc 100644
--- a/modules-available/permissionmanager/templates/roleeditor.html
+++ b/modules-available/permissionmanager/templates/roleeditor.html
@@ -1,36 +1,55 @@
-<h1>{{lang_roleEditor}}</h1>
+<h2>
+ {{#roleid}}
+ {{lang_editRoleHeading}}
+ {{/roleid}}
+ {{^roleid}}
+ {{lang_addRoleHeading}}
+ {{/roleid}}
+</h2>
+
<form method="post" action="?do=permissionmanager">
<input type="hidden" name="action" value="saveRole">
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="roleid" value="{{roleid}}">
- <div class="row">
- <div class="col-md-12" style="margin-bottom: 20px;">
- <ul class="nav nav-tabs text-center" role="tablist">
- <li role="presentation" class="active"><a href="#permissions" role="tab" data-toggle="tab">{{lang_permissions}}</a></li>
- <li role="presentation"><a href="#locations" role="tab" data-toggle="tab">{{lang_locations}}</a></li>
- <li style="float: none; display: inline-block">
- <label for="rolename">{{lang_name}}:</label>
- <input id="rolename" name="rolename" value="{{rolename}}" type="text" class="form-control">
- </li>
- <li style="float: right;">
- <span><a href="?do=permissionmanager&show={{cancelShow}}" id="cancelButton" class="btn btn-default">{{lang_cancel}}</a></span>
- <button type="submit" id="saveButton" class="btn btn-primary"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}}</button>
- </li>
- </ul>
- </div>
+ <div class="input-group">
+ <span class="input-group-addon slx-ga">
+ <label for="rolename">{{lang_name}}</label>
+ </span>
+ <input id="rolename" name="rolename" value="{{rolename}}" type="text" class="form-control" required>
</div>
- <div class="row" style="margin-bottom: 20px;">
- <div class="col-md-12">
- <div class="tab-content">
- <div role="tabpanel" class="tab-pane active" id="permissions">
- {{{permissionHTML}}}
- </div>
- <div role="tabpanel" class="tab-pane" id="locations">
- {{{locationHTML}}}
+ <div class="input-group">
+ <span class="input-group-addon slx-ga">
+ <label for="roledescription">{{lang_description}}</label>
+ </span>
+ <input id="roledescription" name="roledescription" value="{{roledescription}}" type="text" class="form-control">
+ </div>
+ <br>
+
+ <div class="pull-right">
+ <a href="?do=permissionmanager&amp;show={{cancelShow}}" class="btn btn-default">{{lang_cancel}}</a>
+ <button type="submit" class="btn btn-primary" {{perms.roles.edit.disabled}}>
+ <span class="glyphicon glyphicon-floppy-disk"></span>
+ {{lang_save}}
+ </button>
+ </div>
+ <ul class="nav nav-tabs text-center" role="tablist">
+ <li role="presentation" class="active"><a href="#permissions" role="tab" data-toggle="tab">{{lang_permissions}}</a></li>
+ <li role="presentation"><a href="#locations" role="tab" data-toggle="tab">{{lang_locations}}</a></li>
+ </ul>
+ <div class="tab-content">
+ <div role="tabpanel" class="tab-pane active" id="permissions">
+ {{{permissionHTML}}}
+ <div class="panel panel-default">
+ <div class="panel-body">
+ <span class="glyphicon glyphicon-home text-muted"></span>&emsp;
+ {{lang_locationAwareDesc}}
</div>
</div>
</div>
+ <div role="tabpanel" class="tab-pane" id="locations">
+ {{{locationHTML}}}
+ </div>
</div>
</form>
@@ -39,16 +58,14 @@
document.addEventListener("DOMContentLoaded", function () {
- $(".tree-panel input[type=checkbox]").change(function () {
- var checked = $(this).prop("checked");
- var parent = $(this).parent().parent();
- if (parent.hasClass("panel-heading")) parent = parent.parent();
+ $(".tree-container input[type=checkbox]").change(function () {
+ // (Un)Mark all sub-elements when changing a checkbox in the panel body
+ var $this = $(this);
+ var checked = $this.prop("checked");
+ $this.closest('li').find("input[type=checkbox]").prop("checked", checked);
- var checkboxes = parent.find("input[type=checkbox]");
- if (checked) {
- checkboxes.prop("checked", true);
- } else {
- checkboxes.prop("checked", false);
+ if (!checked) {
+ var parent = $(this).parent().parent();
while (!parent.hasClass("tree-panel")) {
parent = parent.parent().parent();
if (parent.hasClass("tree-container")) parent = parent.parent().parent();
@@ -56,14 +73,11 @@
}
}
});
-
- $('form').submit(function () {
- var input = $("#rolename");
- var name = $.trim(input.val());
- if (!name) {
- input.addClass("missingInput");
- return false;
- }
+ $("input.master-checkbox").change(function () {
+ // (Un)Mark everything within the panel when the master checkbox on top is clicked
+ var $this = $(this);
+ var checked = $this.prop("checked");
+ $this.closest('.tree-panel').find("input[type=checkbox]").prop("checked", checked);
});
$('[data-toggle="tooltip"]').tooltip({
diff --git a/modules-available/permissionmanager/templates/rolestable.html b/modules-available/permissionmanager/templates/rolestable.html
index b121a9e0..d520db33 100644
--- a/modules-available/permissionmanager/templates/rolestable.html
+++ b/modules-available/permissionmanager/templates/rolestable.html
@@ -1,15 +1,8 @@
<form method="post" action="?do=permissionmanager">
<input type="hidden" name="token" value="{{token}}">
- <div class="row">
- <div class="col-md-4">
- </div>
- <div class="col-md-4">
- <input type="text" class="form-control" id="roleNameSearchField" onkeyup="searchFieldFunction()" placeholder="{{lang_searchPlaceholder}}">
- </div>
- <div class="col-md-4 text-right">
- <a href="?do=permissionmanager&show=roleEditor" class="btn btn-success"><span class="glyphicon glyphicon-plus"></span> {{lang_newRole}}</a>
- </div>
+ <div>
+ <input type="text" class="form-control" id="roleNameSearchField" onkeyup="searchFieldFunction()" placeholder="{{lang_searchPlaceholder}}">
</div>
<div class="row">
@@ -18,8 +11,16 @@
<thead>
<tr>
<th data-sort="string">{{lang_roles}}</th>
- <th class="text-center">{{lang_edit}}</th>
- <th class="text-center">{{lang_delete}}</th>
+ <th data-sort="string">{{lang_description}}</th>
+ <th class="text-center slx-smallcol">
+ {{#perms.roles.edit.disabled}}
+ {{lang_view}}
+ {{/perms.roles.edit.disabled}}
+ {{^perms.roles.edit.disabled}}
+ {{lang_edit}}
+ {{/perms.roles.edit.disabled}}
+ </th>
+ <th class="text-center slx-smallcol">{{lang_delete}}</th>
</tr>
</thead>
@@ -27,11 +28,14 @@
{{#roles}}
<tr>
<td class="rolename">{{rolename}}</td>
+ <td class="text-muted"><table class="slx-ellipsis"><tr><td>{{roledescription}}</td></tr></table></td>
<td class="text-center">
- <a class="btn btn-xs btn-primary" href="?do=permissionmanager&show=roleEditor&roleid={{roleid}}"><span class="glyphicon glyphicon-edit"></span></a>
+ <a class="btn btn-xs btn-primary" href="?do=permissionmanager&amp;show=roleEditor&amp;roleid={{roleid}}"><span class="glyphicon glyphicon-edit"></span></a>
</td>
<td class="text-center">
- <a class="btn btn-xs btn-danger" href="#deleteModal" data-toggle="modal" data-target="#deleteModal" onclick="deleteRole('{{roleid}}')"><span class="glyphicon glyphicon-trash"></span></a>
+ <button type="button" class="btn btn-xs btn-danger" data-toggle="modal" data-target="#deleteModal" onclick="deleteRole('{{roleid}}', '{{users}}')" {{perms.roles.edit.disabled}}>
+ <span class="glyphicon glyphicon-trash"></span>
+ </button>
</td>
</tr>
{{/roles}}
@@ -40,7 +44,6 @@
</div>
</div>
-
<!-- Modals -->
<div class ="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
@@ -50,10 +53,11 @@
<h4 class="modal-title" id="myModalLabel">{{lang_delete}}</h4>
</div>
<div class="modal-body">
- {{lang_deleteCheck}}
+ <p>{{lang_roleDeleteConfirm}}</p>
+ {{lang_numAssignedUsers}}: <span id="delete-role-users"></span>
</div>
<div class="modal-footer">
- <input type="hidden" id="deleteId" name="deleteId" value=""/>
+ <input type="hidden" id="delete-role-id" name="deleteId" value="">
<button type="button" class="btn btn-default" data-dismiss="modal">{{lang_cancel}}</button>
<button type="submit" name="action" value="deleteRole" class="btn btn-danger"><span class="glyphicon glyphicon-trash"></span> {{lang_delete}}</button>
</div>
@@ -63,9 +67,14 @@
</form>
+<div class="text-right">
+ <a href="?do=permissionmanager&amp;show=roleEditor" class="btn btn-success {{perms.roles.edit.disabled}}"><span class="glyphicon glyphicon-plus"></span> {{lang_newRole}}</a>
+</div>
+
<script>
- function deleteRole($roleid) {
- $(".modal-footer #deleteId").val($roleid);
+ function deleteRole(roleid, users) {
+ $("#delete-role-id").val(roleid);
+ $("#delete-role-users").text(users);
}
function searchFieldFunction() {
diff --git a/modules-available/permissionmanager/templates/treenode.html b/modules-available/permissionmanager/templates/treenode.html
index ced973ca..f8ee3df5 100644
--- a/modules-available/permissionmanager/templates/treenode.html
+++ b/modules-available/permissionmanager/templates/treenode.html
@@ -1,11 +1,14 @@
{{#toplevel}}<ul>{{/toplevel}}
- <li title="{{description}}" data-toggle="tooltip" data-placement="left">
- <div class='checkbox'>
- <input id="{{id}}" name="{{checkboxname}}[]" value="{{id}}" type="checkbox" class="form-control" {{#selected}}checked{{/selected}}>
- <label for="{{id}}">{{#toplevel}}<b>{{/toplevel}}{{name}}{{#toplevel}}</b>{{/toplevel}}</label>
- </div>
- <ul>
- {{{HTML}}}
- </ul>
- </li>
-{{#toplevel}}</ul>{{/toplevel}}
+<li {{#description}}title="{{description}}" data-toggle="tooltip" data-placement="left"{{/description}}>
+ <div class='checkbox'>
+ <input id="{{id}}" name="{{checkboxname}}[]" value="{{id}}" type="checkbox" {{#selected}}checked{{/selected}} {{edit_disabled}} {{perms.roles.edit.disabled}}>
+ <label for="{{id}}">
+ {{name}}
+ {{#location-aware}}<span class="glyphicon glyphicon-home text-muted"></span>{{/location-aware}}
+ </label>
+ </div>
+ <ul>
+ {{{HTML}}}
+ </ul>
+</li>
+{{#toplevel}}</ul>{{/toplevel}} \ No newline at end of file
diff --git a/modules-available/permissionmanager/templates/treepanel.html b/modules-available/permissionmanager/templates/treepanel.html
index 6f358825..eccecb58 100644
--- a/modules-available/permissionmanager/templates/treepanel.html
+++ b/modules-available/permissionmanager/templates/treepanel.html
@@ -1,12 +1,12 @@
<div class="panel panel-primary tree-panel">
<div class="panel-heading">
<div class="checkbox">
- <input id="{{id}}" name="{{checkboxname}}[]" value="{{id}}" type="checkbox" class="form-control" {{#selected}}checked{{/selected}}>
+ <input id="{{id}}" name="{{checkboxname}}[]" value="{{id}}" type="checkbox" class="master-checkbox" {{#selected}}checked{{/selected}} {{perms.roles.edit.disabled}}>
<label for="{{id}}">{{name}}</label>
</div>
</div>
<div class="panel-body">
- <div class="tree-container" style="padding-left: 20px; padding-right: 20px;">
+ <div class="tree-container">
{{{HTML}}}
</div>
</div>
diff --git a/modules-available/permissionmanager/templates/userstable.html b/modules-available/permissionmanager/templates/userstable.html
index bb0e228e..4cda2b1b 100644
--- a/modules-available/permissionmanager/templates/userstable.html
+++ b/modules-available/permissionmanager/templates/userstable.html
@@ -2,40 +2,23 @@
<input type="hidden" name="token" value="{{token}}">
<div class="row">
- <div class="col-md-4">
- </div>
- <div class="col-md-4">
- <select multiple name="roles[]" id="select-role">
- <option value>{{lang_selectizePlaceholder}}</option>
- {{#roles}}
- <option value="{{roleid}}">{{rolename}}</option>
- {{/roles}}
- </select>
- </div>
- <div class="col-md-4 text-right">
- <button class="roleButtons btn btn-success" type="button" data-toggle="modal" data-target="#addRoleToUserModal" disabled><span class="glyphicon glyphicon-share-alt"></span> {{lang_addRole}}</button>
- <button class="roleButtons btn btn-danger" type="button" data-toggle="modal" data-target="#removeRoleFromUserModal" disabled><span class="glyphicon glyphicon-remove-circle"></span> {{lang_removeRole}}</button>
- </div>
- </div>
-
- <div class="row">
<div class="col-md-12">
<table id="usersTable" class="table table-condensed table-hover stupidtable dataTable">
<thead>
<tr>
<th data-sort="string">{{lang_users}}</th>
- <th>{{lang_roles}}</th>
- <th data-sort="int" data-sort-default="desc">{{lang_selected}}</th>
+ <th class="slx-smallcol">{{lang_roles}}</th>
+ <th class="slx-smallcol" data-sort="int" data-sort-default="desc">{{lang_selected}}</th>
</tr>
</thead>
<tbody>
{{#user}}
- <tr data-selectizeCount='0'>
+ <tr class="{{#roles}}roleid-{{roleid}} {{/roles}}">
<td>{{username}}</td>
- <td>
+ <td class="slx-smallcol">
{{#roles}}
- <a href="?do=permissionmanager&show=roleEditor&cancel=users&roleid={{roleid}}" class="label label-default customSpanMargin roleid-{{roleid}}">{{rolename}}</a>
+ <a href="?do=permissionmanager&show=roleEditor&cancel=users&roleid={{roleid}}" class="label label-default customSpanMargin">{{rolename}}</a>
{{/roles}}
</td>
<td data-sort-value="0">
@@ -71,7 +54,7 @@
</thead>
<tbody>
- {{#roles}}
+ {{#allroles}}
<tr>
<td>{{rolename}}</td>
<td data-sort-value="0">
@@ -81,7 +64,7 @@
</div>
</td>
</tr>
- {{/roles}}
+ {{/allroles}}
</tbody>
</table>
</div>
@@ -114,7 +97,7 @@
</thead>
<tbody>
- {{#roles}}
+ {{#allroles}}
<tr>
<td>{{rolename}}</td>
<td data-sort-value="0">
@@ -124,7 +107,7 @@
</div>
</td>
</tr>
- {{/roles}}
+ {{/allroles}}
</tbody>
</table>
</div>
@@ -139,6 +122,11 @@
</div>
</form>
+<div class="text-right">
+ <button class="roleButtons btn btn-success" type="button" data-toggle="modal" data-target="#addRoleToUserModal" disabled><span class="glyphicon glyphicon-share-alt"></span> {{lang_addRole}}</button>
+ <button class="roleButtons btn btn-danger" type="button" data-toggle="modal" data-target="#removeRoleFromUserModal" disabled><span class="glyphicon glyphicon-remove-circle"></span> {{lang_removeRole}}</button>
+</div>
+
<script>
selectedUsersCounter = 0;
selectedAddRolesCounter = 0;