From af5c4258439341fd2153a951fb871269bd754e58 Mon Sep 17 00:00:00 2001
From: Simon Rettberg
Date: Mon, 12 Feb 2018 17:18:45 +0100
Subject: [permissionmanager] Tweak style, fix role filtering (and make it
AND), minor cleanups
---
.../permissionmanager/templates/header-menu.html | 25 ++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 modules-available/permissionmanager/templates/header-menu.html
(limited to 'modules-available/permissionmanager/templates/header-menu.html')
diff --git a/modules-available/permissionmanager/templates/header-menu.html b/modules-available/permissionmanager/templates/header-menu.html
new file mode 100644
index 00000000..ce31d237
--- /dev/null
+++ b/modules-available/permissionmanager/templates/header-menu.html
@@ -0,0 +1,25 @@
+
\ No newline at end of file
--
cgit v1.2.3-55-g7522
From 7afe5a3ffee64ff5c1ee7692a2ac4c83d46d6a78 Mon Sep 17 00:00:00 2001
From: Simon Rettberg
Date: Mon, 19 Feb 2018 13:36:35 +0100
Subject: [permissionmanager] Implement permissions:
Permissinmanager is now protected by permissions.
In order to prevent complete lockout, the user with
userid == 1 will always be able to edit and assign permissions.
(TODO: Communicate this somehow)
---
inc/permission.inc.php | 2 +-
.../inc/getpermissiondata.inc.php | 22 +++++++-
.../permissionmanager/inc/permissionutil.inc.php | 34 ++++++++-----
.../permissionmanager/lang/de/permissions.json | 7 +++
.../permissionmanager/lang/de/template-tags.json | 6 ++-
.../permissionmanager/lang/en/permissions.json | 7 +++
.../permissionmanager/lang/en/template-tags.json | 6 ++-
modules-available/permissionmanager/page.inc.php | 59 +++++++++++++++-------
.../permissionmanager/permissions/permissions.json | 17 +++++++
modules-available/permissionmanager/style.css | 4 ++
.../permissionmanager/templates/header-menu.html | 6 +--
.../permissionmanager/templates/roleeditor.html | 5 +-
.../permissionmanager/templates/rolestable.html | 25 ++++++---
.../permissionmanager/templates/treenode.html | 2 +-
.../permissionmanager/templates/treepanel.html | 2 +-
.../roomplanner/permissions/permissions.json | 10 ++++
16 files changed, 164 insertions(+), 50 deletions(-)
create mode 100644 modules-available/permissionmanager/lang/de/permissions.json
create mode 100644 modules-available/permissionmanager/lang/en/permissions.json
create mode 100644 modules-available/permissionmanager/permissions/permissions.json
create mode 100644 modules-available/roomplanner/permissions/permissions.json
(limited to 'modules-available/permissionmanager/templates/header-menu.html')
diff --git a/inc/permission.inc.php b/inc/permission.inc.php
index e61c7423..aaef6ba6 100644
--- a/inc/permission.inc.php
+++ b/inc/permission.inc.php
@@ -33,7 +33,7 @@ class Permission
}
$temp =& $array;
foreach (explode('.', $perm) as $sub) {
- if (empty($sub))
+ if (empty($sub) || $sub === '*')
continue;
$temp =& $temp[$sub];
}
diff --git a/modules-available/permissionmanager/inc/getpermissiondata.inc.php b/modules-available/permissionmanager/inc/getpermissiondata.inc.php
index dd100d42..496c8224 100644
--- a/modules-available/permissionmanager/inc/getpermissiondata.inc.php
+++ b/modules-available/permissionmanager/inc/getpermissiondata.inc.php
@@ -3,6 +3,9 @@
class GetPermissionData
{
+ const WITH_USER_COUNT = 1;
+ const WITH_LOCATION_COUNT = 2;
+
/**
* Get data for all users.
*
@@ -64,11 +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()
+ public static function getRoles($flags = 0)
{
- return Database::queryAll("SELECT roleid, rolename FROM role ORDER BY rolename ASC");
+ $cols = $joins = '';
+ if ($flags & self::WITH_USER_COUNT) {
+ $cols .= ', Count(DISTINCT rxu.userid) AS users';
+ $joins .= ' LEFT JOIN user_x_role rxu ON (r.roleid = rxu.roleid)';
+ }
+ 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 $cols FROM role r
+ $joins
+ ORDER BY rolename ASC");
}
/**
diff --git a/modules-available/permissionmanager/inc/permissionutil.inc.php b/modules-available/permissionmanager/inc/permissionutil.inc.php
index b4d54055..bc42c5a0 100644
--- a/modules-available/permissionmanager/inc/permissionutil.inc.php
+++ b/modules-available/permissionmanager/inc/permissionutil.inc.php
@@ -53,6 +53,9 @@ class PermissionUtil
$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)) {
@@ -103,21 +106,26 @@ class PermissionUtil
$permissionid = strtolower($permissionid);
self::validatePermission($permissionid);
$parts = explode('.', $permissionid);
- // 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 user_x_role USING (roleid)
- INNER JOIN role_x_location USING (roleid)
- WHERE user_x_role.userid = :userid AND (permissionid LIKE :prefix OR permissionid LIKE '*')",
- compact('userid', 'prefix'));
+ // 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 user_x_role USING (roleid)
+ INNER JOIN role_x_location USING (roleid)
+ WHERE user_x_role.userid = :userid AND (permissionid LIKE :prefix OR permissionid LIKE '*')",
+ compact('userid', 'prefix'));
- // 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)
+ // 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[(int)$row['locationid']] = true;
+ }
}
}
$locations = Location::getTree();
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 2ec25b37..52073dee 100644
--- a/modules-available/permissionmanager/lang/de/template-tags.json
+++ b/modules-available/permissionmanager/lang/de/template-tags.json
@@ -1,18 +1,20 @@
{
"lang_addRole": "Rollen erteilen",
"lang_addRoleHeading": "Neue Rolle hinzuf\u00fcgen",
- "lang_deleteCheck": "Sind Sie sich sicher, dass Sie diese Rolle l\u00f6schen wollen?",
"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_newRole": "Rolle anlegen",
+ "lang_numAssignedUsers": "Benutzer mit dieser Rolle",
"lang_permissions": "Rechte",
"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_selected": "ausgew\u00e4hlte",
"lang_selectizePlaceholder": "Nach Rollen filtern...",
- "lang_users": "Nutzer"
+ "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 cef23422..b7a1d77a 100644
--- a/modules-available/permissionmanager/lang/en/template-tags.json
+++ b/modules-available/permissionmanager/lang/en/template-tags.json
@@ -1,18 +1,20 @@
{
"lang_addRole": "Grant Roles",
"lang_addRoleHeading": "Add new role",
- "lang_deleteCheck": "Are you sure you want to delete this role?",
"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_newRole": "New Role",
+ "lang_numAssignedUsers": "Users with this role",
"lang_permissions": "Permissions",
"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_selected": "selected",
"lang_selectizePlaceholder": "Filter for roles...",
- "lang_users": "Users"
+ "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 1c2d56bf..a78f935f 100644
--- a/modules-available/permissionmanager/page.inc.php
+++ b/modules-available/permissionmanager/page.inc.php
@@ -17,17 +17,21 @@ 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') {
+ User::assertPermission('roles.edit');
$id = Request::post('deleteId', false, 'string');
PermissionDbUpdate::deleteRole($id);
} elseif ($action === 'saveRole') {
+ User::assertPermission('roles.edit');
$roleID = Request::post("roleid", false);
$rolename = Request::post("rolename");
$locations = self::processLocations(Request::post("locations"));
@@ -44,33 +48,51 @@ class Page_PermissionManager extends Page
*/
protected function doRender()
{
- $show = Request::get("show", "roles");
+ $show = Request::get("show", false, 'string');
+
+ if ($show === false) {
+ foreach (['roles', 'users', 'locations'] as $show) {
+ if (User::hasPermission($show . '.*'))
+ break;
+ }
+ }
// switch between tables, but always show menu to switch tables
// get menu button colors
- $buttonColors = array();
+ $data = array();
if ($show === "roleEditor") {
- $buttonColors['groupClass'] = 'slx-fade';
- $buttonColors['rolesButtonClass'] = 'active';
+ $data['groupClass'] = 'btn-group-muted';
+ $data['rolesButtonClass'] = 'active';
} else {
- $buttonColors[$show . 'ButtonClass'] = 'active';
+ $data[$show . 'ButtonClass'] = 'active';
}
+ Permission::addGlobalTags($data['perms'], null, ['roles.*', 'users.*', 'locations.*']);
- Render::addtemplate('header-menu', $buttonColors);
+ Render::addtemplate('header-menu', $data);
if ($show === "roles") {
- $data = array("roles" => GetPermissionData::getRoles());
+ 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") {
- $data = array("user" => GetPermissionData::getUserData(), "allroles" => GetPermissionData::getRoles());
+ 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") {
+ User::assertPermission('roles.*');
$data = array("cancelShow" => Request::get("cancel", "roles"));
+ Permission::addGlobalTags($data['perms'], null, ['roles.edit']);
$selectedPermissions = array();
$selectedLocations = array();
@@ -83,8 +105,10 @@ class Page_PermissionManager extends Page
$selectedLocations = $roleData["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,
+ false, '', ['perms' => $data['perms']]);
Render::addTemplate('roleeditor', $data);
}
@@ -99,7 +123,7 @@ class Page_PermissionManager extends Page
* @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 == "";
@@ -132,12 +156,12 @@ class Page_PermissionManager extends Page
"toplevel" => $toplevel,
"checkboxname" => "permissions",
"selected" => $selected,
- "HTML" => $leaf ? "" : self::generatePermissionHTML($v, $selectedPermissions, $selected, $nextPermString),
+ "HTML" => $leaf ? "" : self::generatePermissionHTML($v, $selectedPermissions, $selected, $nextPermString, $tags),
);
if ($leaf) {
$data += $v;
}
- $res .= Render::parse("treenode", $data);
+ $res .= Render::parse("treenode", $data + $tags);
}
if ($toplevel) {
$res = Render::parse("treepanel",
@@ -145,7 +169,7 @@ class Page_PermissionManager extends Page
"name" => Dictionary::translateFile("template-tags", "lang_permissions"),
"checkboxname" => "permissions",
"selected" => $selectAll,
- "HTML" => $res));
+ "HTML" => $res) + $tags);
}
return $res;
}
@@ -159,7 +183,7 @@ 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)) {
@@ -174,7 +198,8 @@ class Page_PermissionManager extends Page
"checkboxname" => "locations",
"selected" => $selected,
"HTML" => array_key_exists("children", $location) ?
- self::generateLocationHTML($location["children"], $selectedLocations, $selected, false) : ""));
+ self::generateLocationHTML($location["children"], $selectedLocations, $selected, false, $tags) : "")
+ + $tags);
}
if ($toplevel) {
$res = Render::parse("treepanel",
@@ -182,7 +207,7 @@ class Page_PermissionManager extends Page
"name" => Dictionary::translateFile("template-tags", "lang_locations"),
"checkboxname" => "locations",
"selected" => $selectAll,
- "HTML" => $res));
+ "HTML" => $res) + $tags);
}
return $res;
}
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 8285fdd2..6169b26f 100644
--- a/modules-available/permissionmanager/style.css
+++ b/modules-available/permissionmanager/style.css
@@ -55,3 +55,7 @@ td > .label {
column-count: 3;
}
}
+
+.btn-group-muted > button {
+ color: #aaa;
+}
\ No newline at end of file
diff --git a/modules-available/permissionmanager/templates/header-menu.html b/modules-available/permissionmanager/templates/header-menu.html
index ce31d237..91bfa3af 100644
--- a/modules-available/permissionmanager/templates/header-menu.html
+++ b/modules-available/permissionmanager/templates/header-menu.html
@@ -4,17 +4,17 @@
- {{lang_deleteCheck}}
+
{{lang_roleDeleteConfirm}}
+ {{lang_numAssignedUsers}}:
@@ -56,12 +66,13 @@