diff options
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 |