summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2018-02-23 18:41:49 +0100
committerSimon Rettberg2018-02-23 18:41:49 +0100
commit00851bd25e57938a79356d2efb36c2bea1697760 (patch)
tree11a759430f5a9ddc3b7977bb6c4451aa71287622
parent[adduser] Extend module to simple user manager (add/edit/remove) (diff)
downloadslx-admin-00851bd25e57938a79356d2efb36c2bea1697760.tar.gz
slx-admin-00851bd25e57938a79356d2efb36c2bea1697760.tar.xz
slx-admin-00851bd25e57938a79356d2efb36c2bea1697760.zip
[adduser] Support setting user's roles on add/edit
-rw-r--r--modules-available/adduser/page.inc.php33
-rw-r--r--modules-available/adduser/templates/page-adduser.html74
-rw-r--r--modules-available/adduser/templates/page-edituser.html120
-rw-r--r--modules-available/adduser/templates/user-permissions.html24
-rw-r--r--modules-available/permissionmanager/inc/permissiondbupdate.inc.php28
-rw-r--r--modules-available/permissionmanager/inc/permissionutil.inc.php23
6 files changed, 198 insertions, 104 deletions
diff --git a/modules-available/adduser/page.inc.php b/modules-available/adduser/page.inc.php
index a4edcf59..d1615828 100644
--- a/modules-available/adduser/page.inc.php
+++ b/modules-available/adduser/page.inc.php
@@ -61,6 +61,7 @@ class Page_AddUser extends Page
EventLog::info(User::getName() . ' created user ' . $login);
}
Message::addInfo('adduser-success');
+ $this->saveRoles($id);
return;
}
}
@@ -113,6 +114,7 @@ class Page_AddUser extends Page
Database::exec('UPDATE user SET passwd = :pass WHERE userid = :userid', $data);
Message::addSuccess('password-changed');
}
+ $this->saveRoles($userid);
}
}
Util::redirect('?do=adduser&show=edituser&userid=' . $userid);
@@ -141,6 +143,19 @@ class Page_AddUser extends Page
Message::addSuccess('user-deleted', $userid);
}
+ private function saveRoles($userid)
+ {
+ if (!Module::isAvailable('permissionmanager'))
+ return;
+ if (!User::hasPermission('.permissionmanager.users.edit-roles'))
+ return;
+ $roles = Request::post('roles', [], 'array');
+ $ret = PermissionDbUpdate::setRolesForUser([$userid], $roles);
+ if ($ret > 0) {
+ Message::addSuccess('roles-updated');
+ }
+ }
+
protected function doRender()
{
Render::addTemplate('header');
@@ -151,7 +166,12 @@ class Page_AddUser extends Page
if ($hasUsers) {
User::assertPermission('user.add');
}
+ Render::openTag('form', ['class' => 'form-adduser', 'action' => '?do=adduser', 'method' => 'post']);
Render::addTemplate('page-adduser');
+ if ($hasUsers) {
+ $this->showPermissions();
+ }
+ Render::closeTag('form');
} elseif ($show === 'edituser') {
User::assertPermission('user.edit');
$userid = Request::get('userid', false, 'int');
@@ -165,7 +185,10 @@ class Page_AddUser extends Page
Message::addError('user-not-found', $userid);
} else {
// TODO: LDAP -> disallow pw change, maybe other fields too?
+ Render::openTag('form', ['class' => 'form-adduser', 'action' => '?do=adduser', 'method' => 'post']);
Render::addTemplate('page-edituser', $user);
+ $this->showPermissions($userid);
+ Render::closeTag('form');
}
} elseif ($show === 'list') {
User::assertPermission('list.view');
@@ -181,4 +204,14 @@ class Page_AddUser extends Page
}
}
+ private function showPermissions($userid = false)
+ {
+ if (!Module::isAvailable('permissionmanager'))
+ return;
+ if (!User::hasPermission('.permissionmanager.users.edit-roles'))
+ return;
+ $data = ['roles' => PermissionUtil::getRoles($userid, false)];
+ Render::addTemplate('user-permissions', $data);
+ }
+
}
diff --git a/modules-available/adduser/templates/page-adduser.html b/modules-available/adduser/templates/page-adduser.html
index 58d705f8..bd16dbbf 100644
--- a/modules-available/adduser/templates/page-adduser.html
+++ b/modules-available/adduser/templates/page-adduser.html
@@ -1,39 +1,37 @@
-<form class="form-adduser" action="?do=AddUser" method="post">
- <input type="text" name="prevent_autofill" id="prevent_autofill" value="" style="position:absolute;top:-2000px" tabindex="-1">
- <input type="password" name="password_fake" id="password_fake" value="" style="position:absolute;top:-2000px" tabindex="-1">
- <h2>{{lang_createUser}}</h2>
- <div class="row">
- <div class="col-md-4"><label for="login">{{lang_login}} *</label></div>
- <div class="col-md-4"><input id="label" type="text" name="login" value="{{login}}" class="form-control" placeholder="{{lang_username}}" autofocus></div>
+<input type="text" name="prevent_autofill" id="prevent_autofill" value="" style="position:absolute;top:-2000px" tabindex="-1">
+<input type="password" name="password_fake" id="password_fake" value="" style="position:absolute;top:-2000px" tabindex="-1">
+<h2>{{lang_createUser}}</h2>
+<div class="row">
+ <div class="col-md-4"><label for="login">{{lang_login}} *</label></div>
+ <div class="col-md-4"><input id="label" type="text" name="login" value="{{login}}" class="form-control" placeholder="{{lang_username}}" autofocus></div>
+</div>
+<br>
+<div class="row">
+ <div class="col-md-4"><label for="pass1">{{lang_password}} *</label></div>
+ <div class="col-md-4"><input id="pass1" type="password" name="pass1" class="form-control" placeholder="{{lang_password}}"></div>
+ <div class="col-md-4"><input type="password" name="pass2" class="form-control" placeholder="{{lang_confirmation}}"></div>
+</div>
+<br>
+<div class="row">
+ <div class="col-md-4"><label for="fullname">{{lang_fullName}} *</label></div>
+ <div class="col-md-4"><input id="fullname" type="text" name="fullname" value="{{fullname}}" class="form-control" placeholder="{{lang_fullName}}"></div>
+</div>
+<br>
+<div class="row">
+ <div class="col-md-4"><label for="phone">{{lang_phone}}</label></div>
+ <div class="col-md-4"><input id=phone" type="text" name="phone" value="{{phone}}" class="form-control" placeholder="{{lang_phone}}"></div>
+</div>
+<br>
+<div class="row">
+ <div class="col-md-4"><label for="email">{{lang_email}}</label></div>
+ <div class="col-md-4"><input id="email" type="text" name="email" value="{{email}}" class="form-control" placeholder="{{lang_email}}"></div>
+</div>
+<br>
+<div class="row">
+ <div class="col-md-4"></div>
+ <div class="col-md-8">
+ <button class="btn btn-lg btn-primary btn-block" type="submit">{{lang_createUser}}</button>
</div>
- <br>
- <div class="row">
- <div class="col-md-4"><label for="pass1">{{lang_password}} *</label></div>
- <div class="col-md-4"><input id="pass1" type="password" name="pass1" class="form-control" placeholder="{{lang_password}}"></div>
- <div class="col-md-4"><input type="password" name="pass2" class="form-control" placeholder="{{lang_confirmation}}"></div>
- </div>
- <br>
- <div class="row">
- <div class="col-md-4"><label for="fullname">{{lang_fullName}} *</label></div>
- <div class="col-md-4"><input id="fullname" type="text" name="fullname" value="{{fullname}}" class="form-control" placeholder="{{lang_fullName}}"></div>
- </div>
- <br>
- <div class="row">
- <div class="col-md-4"><label for="phone">{{lang_phone}}</label></div>
- <div class="col-md-4"><input id=phone" type="text" name="phone" value="{{phone}}" class="form-control" placeholder="{{lang_phone}}"></div>
- </div>
- <br>
- <div class="row">
- <div class="col-md-4"><label for="email">{{lang_email}}</label></div>
- <div class="col-md-4"><input id="email" type="text" name="email" value="{{email}}" class="form-control" placeholder="{{lang_email}}"></div>
- </div>
- <br>
- <div class="row">
- <div class="col-md-4"></div>
- <div class="col-md-8">
- <button class="btn btn-lg btn-primary btn-block" type="submit">{{lang_createUser}}</button>
- </div>
- </div>
- <input type="hidden" name="action" value="adduser">
- <input type="hidden" name="token" value="{{token}}">
-</form>
+</div>
+<input type="hidden" name="action" value="adduser">
+<input type="hidden" name="token" value="{{token}}">
diff --git a/modules-available/adduser/templates/page-edituser.html b/modules-available/adduser/templates/page-edituser.html
index b8e51b5c..36293b11 100644
--- a/modules-available/adduser/templates/page-edituser.html
+++ b/modules-available/adduser/templates/page-edituser.html
@@ -1,72 +1,70 @@
-<form class="form-adduser" action="?do=AddUser" method="post">
- <input type="text" name="prevent_autofill" id="prevent_autofill" value="" style="position:absolute;top:-2000px" tabindex="-1">
- <input type="password" name="password_fake" id="password_fake" value="" style="position:absolute;top:-2000px" tabindex="-1">
- <h2>{{lang_editUser}}</h2>
+<input type="text" name="prevent_autofill" id="prevent_autofill" value="" style="position:absolute;top:-2000px" tabindex="-1">
+<input type="password" name="password_fake" id="password_fake" value="" style="position:absolute;top:-2000px" tabindex="-1">
+<h2>{{lang_editUser}}</h2>
- <div class="row">
- <div class="col-md-4"><label for="login">{{lang_login}}</label></div>
- <div class="col-md-4"><input id="label" type="text" name="login" value="{{login}}" class="form-control"
- placeholder="{{lang_username}}" autofocus></div>
- </div>
- <div class="row">
- <div class="col-md-4"></div>
- <div class="col-md-8">
- <p>
- {{lang_changeLoginHint}}
- </p>
- </div>
+<div class="row">
+ <div class="col-md-4"><label for="login">{{lang_login}}</label></div>
+ <div class="col-md-4"><input id="label" type="text" name="login" value="{{login}}" class="form-control"
+ placeholder="{{lang_username}}" autofocus></div>
+</div>
+<div class="row">
+ <div class="col-md-4"></div>
+ <div class="col-md-8">
+ <p>
+ {{lang_changeLoginHint}}
+ </p>
</div>
+</div>
- <div class="row">
- <div class="col-md-4"><label for="pass1">{{lang_changePassword}}</label></div>
- <div class="col-md-4"><input id="pass1" {{password_disabled}} type="password" name="pass1" class="form-control" placeholder="{{lang_password}}">
- </div>
- <div class="col-md-4"><input {{password_disabled}} type="password" name="pass2" class="form-control"
- placeholder="{{lang_confirmation}}"></div>
+<div class="row">
+ <div class="col-md-4"><label for="pass1">{{lang_changePassword}}</label></div>
+ <div class="col-md-4"><input id="pass1" {{password_disabled}} type="password" name="pass1" class="form-control" placeholder="{{lang_password}}">
</div>
- {{#password_disabled}}
- <div class="row">
- <div class="col-md-4"></div>
- <div class="col-md-8">
- <p>
- {{lang_changeOwnPasswordHint}}
- </p>
- </div>
+ <div class="col-md-4"><input {{password_disabled}} type="password" name="pass2" class="form-control"
+ placeholder="{{lang_confirmation}}"></div>
+</div>
+{{#password_disabled}}
+<div class="row">
+ <div class="col-md-4"></div>
+ <div class="col-md-8">
+ <p>
+ {{lang_changeOwnPasswordHint}}
+ </p>
</div>
- {{/password_disabled}}
- <br>
+</div>
+{{/password_disabled}}
+<br>
- <div class="row">
- <div class="col-md-4"><label for="fullname">{{lang_fullName}}</label></div>
- <div class="col-md-4"><input id="fullname" type="text" name="fullname" value="{{fullname}}" class="form-control"
- placeholder="{{lang_fullName}}"></div>
- </div>
- <br>
+<div class="row">
+ <div class="col-md-4"><label for="fullname">{{lang_fullName}}</label></div>
+ <div class="col-md-4"><input id="fullname" type="text" name="fullname" value="{{fullname}}" class="form-control"
+ placeholder="{{lang_fullName}}"></div>
+</div>
+<br>
- <div class="row">
- <div class="col-md-4"><label for="phone">{{lang_phone}}</label></div>
- <div class="col-md-4"><input id=phone" type="text" name="phone" value="{{phone}}" class="form-control"
- placeholder="{{lang_phone}}"></div>
- </div>
- <br>
+<div class="row">
+ <div class="col-md-4"><label for="phone">{{lang_phone}}</label></div>
+ <div class="col-md-4"><input id=phone" type="text" name="phone" value="{{phone}}" class="form-control"
+ placeholder="{{lang_phone}}"></div>
+</div>
+<br>
- <div class="row">
- <div class="col-md-4"><label for="email">{{lang_email}}</label></div>
- <div class="col-md-4"><input id="email" type="text" name="email" value="{{email}}" class="form-control" placeholder="{{lang_email}}">
- </div>
+<div class="row">
+ <div class="col-md-4"><label for="email">{{lang_email}}</label></div>
+ <div class="col-md-4"><input id="email" type="text" name="email" value="{{email}}" class="form-control" placeholder="{{lang_email}}">
</div>
- <br>
+</div>
+<br>
- <div class="row">
- <div class="col-md-4"></div>
- <div class="col-md-8">
- <button class="btn btn-lg btn-primary btn-block" type="submit">
- <span class="glyphicon glyphicon-floppy-disk"></span>
- {{lang_save}}
- </button>
- </div>
+<div class="row">
+ <div class="col-md-4"></div>
+ <div class="col-md-8">
+ <button class="btn btn-lg btn-primary btn-block" type="submit">
+ <span class="glyphicon glyphicon-floppy-disk"></span>
+ {{lang_save}}
+ </button>
</div>
- <input type="hidden" name="action" value="edituser">
- <input type="hidden" name="userid" value="{{userid}}">
- <input type="hidden" name="token" value="{{token}}">
-</form>
+</div>
+<input type="hidden" name="action" value="edituser">
+<input type="hidden" name="userid" value="{{userid}}">
+<input type="hidden" name="token" value="{{token}}">
diff --git a/modules-available/adduser/templates/user-permissions.html b/modules-available/adduser/templates/user-permissions.html
new file mode 100644
index 00000000..ce51630f
--- /dev/null
+++ b/modules-available/adduser/templates/user-permissions.html
@@ -0,0 +1,24 @@
+<h3>{{lang_assignRoles}}</h3>
+
+<table class="table table-condensed table-hover">
+ <thead>
+ <tr>
+ <th data-sort="string">{{lang_role}}</th>
+ <th class="text-center slx-smallcol"></th>
+ </tr>
+ </thead>
+
+ <tbody>
+ {{#roles}}
+ <tr>
+ <td class="rolename">{{rolename}}</td>
+ <td class="text-center">
+ <div class="checkbox">
+ <input type="checkbox" name="roles[]" value="{{roleid}}" {{#hasRole}}checked{{/hasRole}}>
+ <label></label>
+ </div>
+ </td>
+ </tr>
+ {{/roles}}
+ </tbody>
+</table> \ No newline at end of file
diff --git a/modules-available/permissionmanager/inc/permissiondbupdate.inc.php b/modules-available/permissionmanager/inc/permissiondbupdate.inc.php
index 1f56f4ea..5f528a37 100644
--- a/modules-available/permissionmanager/inc/permissiondbupdate.inc.php
+++ b/modules-available/permissionmanager/inc/permissiondbupdate.inc.php
@@ -7,17 +7,19 @@ class PermissionDbUpdate
* Insert all user/role combinations into the role_x_user table.
*
* @param int[] $users userids
- * @param string[] $roles roleids
+ * @param int[] $roles roleids
*/
public static function addRoleToUser($users, $roles)
{
+ if (empty($users) || empty($roles))
+ return 0;
$arg = array();
foreach ($users AS $userid) {
foreach ($roles AS $roleid) {
$arg[] = compact('userid', 'roleid');
}
}
- Database::exec("INSERT IGNORE INTO role_x_user (userid, roleid) VALUES :arg",
+ return Database::exec("INSERT IGNORE INTO role_x_user (userid, roleid) VALUES :arg",
['arg' => $arg]);
}
@@ -25,12 +27,28 @@ class PermissionDbUpdate
* Remove all user/role combinations from the role_x_user table.
*
* @param int[] $users userids
- * @param string[] $roles roleids
+ * @param int[] $roles roleids
*/
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)";
- Database::exec($query, array("users" => $users, "roles" => $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);
}
/**
@@ -40,7 +58,7 @@ class PermissionDbUpdate
*/
public static function deleteRole($roleid)
{
- Database::exec("DELETE FROM role WHERE roleid = :roleid", array("roleid" => $roleid));
+ return Database::exec("DELETE FROM role WHERE roleid = :roleid", array("roleid" => $roleid));
}
/**
diff --git a/modules-available/permissionmanager/inc/permissionutil.inc.php b/modules-available/permissionmanager/inc/permissionutil.inc.php
index 29663ed9..a3a2b610 100644
--- a/modules-available/permissionmanager/inc/permissionutil.inc.php
+++ b/modules-available/permissionmanager/inc/permissionutil.inc.php
@@ -232,6 +232,28 @@ class PermissionUtil
}
/**
+ * 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
@@ -252,4 +274,5 @@ class PermissionUtil
}
$tree = array('description' => $description, 'location-aware' => $locationAware, 'isLeaf' => true);
}
+
} \ No newline at end of file