From 676bb4aebcbb65f6271f062d03aef2a48346f2e3 Mon Sep 17 00:00:00 2001
From: Simon Rettberg
Date: Fri, 9 Feb 2018 16:17:03 +0100
Subject: [backup] Use permission helpers
---
style/default.css | 6 ++++++
1 file changed, 6 insertions(+)
(limited to 'style/default.css')
diff --git a/style/default.css b/style/default.css
index 7273dba2..3b02ffdb 100644
--- a/style/default.css
+++ b/style/default.css
@@ -178,6 +178,7 @@ body {
display: block;
cursor: pointer;
}
+
input[readonly] {
background-color: white !important;
cursor: text !important;
@@ -598,3 +599,8 @@ table.slx-ellipsis td {
text-overflow: ellipsis;
white-space: nowrap;
}
+
+div.disabled input, div.disabled label {
+ pointer-events: none;
+ cursor: not-allowed;
+}
\ No newline at end of file
--
cgit v1.2.3-55-g7522
From 8054a02ec70886a969a7c38c24469a015ee42282 Mon Sep 17 00:00:00 2001
From: Simon Rettberg
Date: Mon, 12 Feb 2018 16:10:29 +0100
Subject: [default.css] Fix style of labels in input-group-addon
---
style/default.css | 5 +++++
1 file changed, 5 insertions(+)
(limited to 'style/default.css')
diff --git a/style/default.css b/style/default.css
index 3b02ffdb..7ca519d9 100644
--- a/style/default.css
+++ b/style/default.css
@@ -603,4 +603,9 @@ table.slx-ellipsis td {
div.disabled input, div.disabled label {
pointer-events: none;
cursor: not-allowed;
+}
+
+.input-group-addon > label {
+ font-weight: normal;
+ margin-bottom: inherit;
}
\ No newline at end of file
--
cgit v1.2.3-55-g7522
From 4f50828773b43cfdaa76d783c72f4800589224d4 Mon Sep 17 00:00:00 2001
From: Simon Rettberg
Date: Mon, 12 Feb 2018 17:15:24 +0100
Subject: [default.css] Fix panel heading bg-img being applied for all panel
styles
Should only override bg for default panel
---
style/default.css | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'style/default.css')
diff --git a/style/default.css b/style/default.css
index 7ca519d9..57f76f69 100644
--- a/style/default.css
+++ b/style/default.css
@@ -7,7 +7,7 @@ body {
padding-bottom: 10px;
}
-.panel-heading, .panel-footer, .jumbotron, pre, .input-group-addon {
+.panel-default > .panel-heading, .panel-footer, .jumbotron, pre, .input-group-addon {
background-image: url('bg.png');
}
--
cgit v1.2.3-55-g7522
From d879774ad2b6cc5ce3f870eb85972245464c56b3 Mon Sep 17 00:00:00 2001
From: Simon Rettberg
Date: Mon, 12 Feb 2018 18:00:45 +0100
Subject: slx-fixes.js/default.css: Fix disabled cursor-style
---
script/slx-fixes.js | 7 +++++++
style/default.css | 14 ++++++++++++--
2 files changed, 19 insertions(+), 2 deletions(-)
(limited to 'style/default.css')
diff --git a/script/slx-fixes.js b/script/slx-fixes.js
index 1ed71cb9..9cd93c05 100644
--- a/script/slx-fixes.js
+++ b/script/slx-fixes.js
@@ -41,4 +41,11 @@ if (history && history.replaceState && window && window.location && window.locat
// Simple decollapse functionality for tables
$('.slx-decollapse').click(function () {
$(this).siblings('.collapse').removeClass('collapse');
+});
+
+$('a.disabled').each(function() {
+ var $this = $(this);
+ var $hax = $('
');
+ $this.after($hax);
+ $hax.append($this);
});
\ No newline at end of file
diff --git a/style/default.css b/style/default.css
index 57f76f69..a9d45681 100644
--- a/style/default.css
+++ b/style/default.css
@@ -600,12 +600,22 @@ table.slx-ellipsis td {
white-space: nowrap;
}
-div.disabled input, div.disabled label {
- pointer-events: none;
+div.disabled {
cursor: not-allowed;
}
+div.disabled input, div.disabled label, div.disabled .btn {
+ pointer-events: none;
+}
+
.input-group-addon > label {
font-weight: normal;
margin-bottom: inherit;
+}
+
+div.disabled-hack {
+ cursor: not-allowed;
+ margin: 0;
+ padding: 0;
+ display: inline-block;
}
\ No newline at end of file
--
cgit v1.2.3-55-g7522
From f73a41753d2608187a0c85a28e419b8ea839d671 Mon Sep 17 00:00:00 2001
From: Simon Rettberg
Date: Fri, 23 Feb 2018 15:26:17 +0100
Subject: [adduser] Extend module to simple user manager (add/edit/remove)
TODO: Assign roles
---
modules-available/adduser/config.json | 1 +
modules-available/adduser/lang/de/messages.json | 7 +-
modules-available/adduser/lang/de/module.json | 3 +
.../adduser/lang/de/template-tags.json | 14 +-
modules-available/adduser/lang/en/messages.json | 7 +-
modules-available/adduser/lang/en/module.json | 3 +
.../adduser/lang/en/template-tags.json | 14 +-
modules-available/adduser/page.inc.php | 198 +++++++++++++++++----
.../adduser/permissions/permissions.json | 14 ++
modules-available/adduser/style.css | 15 ++
modules-available/adduser/templates/header.html | 3 +
.../adduser/templates/page-adduser.html | 35 ++--
.../adduser/templates/page-edituser.html | 72 ++++++++
.../adduser/templates/page-userlist.html | 73 ++++++++
.../systemstatus/templates/_page.html | 2 +-
style/default.css | 14 --
16 files changed, 404 insertions(+), 71 deletions(-)
create mode 100644 modules-available/adduser/lang/de/module.json
create mode 100644 modules-available/adduser/lang/en/module.json
create mode 100644 modules-available/adduser/permissions/permissions.json
create mode 100644 modules-available/adduser/style.css
create mode 100644 modules-available/adduser/templates/header.html
create mode 100644 modules-available/adduser/templates/page-edituser.html
create mode 100644 modules-available/adduser/templates/page-userlist.html
(limited to 'style/default.css')
diff --git a/modules-available/adduser/config.json b/modules-available/adduser/config.json
index 2c63c085..706412d0 100644
--- a/modules-available/adduser/config.json
+++ b/modules-available/adduser/config.json
@@ -1,2 +1,3 @@
{
+ "category":"main.content"
}
diff --git a/modules-available/adduser/lang/de/messages.json b/modules-available/adduser/lang/de/messages.json
index 4f62dcbf..0ab4571f 100644
--- a/modules-available/adduser/lang/de/messages.json
+++ b/modules-available/adduser/lang/de/messages.json
@@ -1,5 +1,8 @@
{
+ "adduser-success": "Benutzer erfolgreich hinzugef\u00fcgt",
+ "db-error": "Datenbankfehler: {{0}}",
+ "password-changed": "Passwort ge\u00e4ndert",
"password-mismatch": "Passwort und Passwortbest\u00e4tigung stimmen nicht \u00fcberein",
- "adduser-disabled": "Keine ausreichenden Rechte, um weitere Benutzer hinzuzuf\u00fcgen",
- "adduser-success": "Benutzer erfolgreich hinzugef\u00fcgt"
+ "user-edited": "Benutzerdaten wurden ge\u00e4ndert",
+ "user-not-found": "Benutzer mit ID {{0}} nicht gefunden"
}
\ No newline at end of file
diff --git a/modules-available/adduser/lang/de/module.json b/modules-available/adduser/lang/de/module.json
new file mode 100644
index 00000000..e4c785b5
--- /dev/null
+++ b/modules-available/adduser/lang/de/module.json
@@ -0,0 +1,3 @@
+{
+ "module_name": "Nutzerverwaltung"
+}
\ No newline at end of file
diff --git a/modules-available/adduser/lang/de/template-tags.json b/modules-available/adduser/lang/de/template-tags.json
index 99d17947..0b6b2530 100644
--- a/modules-available/adduser/lang/de/template-tags.json
+++ b/modules-available/adduser/lang/de/template-tags.json
@@ -1,6 +1,16 @@
{
+ "lang_addUser": "Nutzer hinzuf\u00fcgen",
+ "lang_changeLoginHint": "Sie k\u00f6nnen den Namen, den der Nutzer beim Login angeben muss, \u00e4ndern. Dies ist nur bei lokalen Nutzern m\u00f6glich, die nicht \u00fcber LDAP\/AD authentifiziert werden.",
+ "lang_changeOwnPasswordHint": "Ihr eigenes Passwort k\u00f6nnen Sie \u00fcber den Button \"Passwort \u00e4ndern\" im Men\u00fc \u00e4ndern.",
+ "lang_changePassword": "Neues Passwort",
"lang_confirmation": "Wiederholen",
"lang_createUser": "Benutzer anlegen",
+ "lang_editUser": "Benutzer bearbeiten",
+ "lang_email": "E-Mail",
"lang_fullName": "Vollst\u00e4ndiger Name",
- "lang_telephone": "Telefon"
-}
+ "lang_login": "Login",
+ "lang_name": "Name",
+ "lang_phone": "Telefon",
+ "lang_userManagement": "Benutzerverwaltung",
+ "lang_userlist": "Benutzerliste"
+}
\ No newline at end of file
diff --git a/modules-available/adduser/lang/en/messages.json b/modules-available/adduser/lang/en/messages.json
index 3a402278..69af3227 100644
--- a/modules-available/adduser/lang/en/messages.json
+++ b/modules-available/adduser/lang/en/messages.json
@@ -1,5 +1,8 @@
{
+ "adduser-success": "User successfully added",
+ "db-error": "Database error: {{0}}",
+ "password-changed": "Password changed",
"password-mismatch": "Password and password confirmation do not match",
- "adduser-disabled": "Insufficient privileges to add more users",
- "adduser-success": "User successfully added"
+ "user-edited": "User data has been updated",
+ "user-not-found": "User with ID {{0}} not found"
}
\ No newline at end of file
diff --git a/modules-available/adduser/lang/en/module.json b/modules-available/adduser/lang/en/module.json
new file mode 100644
index 00000000..f376db34
--- /dev/null
+++ b/modules-available/adduser/lang/en/module.json
@@ -0,0 +1,3 @@
+{
+ "module_name": "User management"
+}
\ No newline at end of file
diff --git a/modules-available/adduser/lang/en/template-tags.json b/modules-available/adduser/lang/en/template-tags.json
index 24f8cd42..2c9b8b53 100644
--- a/modules-available/adduser/lang/en/template-tags.json
+++ b/modules-available/adduser/lang/en/template-tags.json
@@ -1,6 +1,16 @@
{
+ "lang_addUser": "Add user",
+ "lang_changeLoginHint": "You can change the login identifier used for logging in. This is only enabled for local acounts that are not linked to LDAP\/AD servers.",
+ "lang_changeOwnPasswordHint": "You can change your own password by clicking the \"change password\" button in the menu.",
+ "lang_changePassword": "Change password",
"lang_confirmation": "Confirm Password",
"lang_createUser": "Create User",
+ "lang_editUser": "Edit user",
+ "lang_email": "Email",
"lang_fullName": "Full Name",
- "lang_telephone": "Telephone"
-}
+ "lang_login": "Login",
+ "lang_name": "Name",
+ "lang_phone": "Phone",
+ "lang_userManagement": "User management",
+ "lang_userlist": "User list"
+}
\ No newline at end of file
diff --git a/modules-available/adduser/page.inc.php b/modules-available/adduser/page.inc.php
index 87aaeef1..a4edcf59 100644
--- a/modules-available/adduser/page.inc.php
+++ b/modules-available/adduser/page.inc.php
@@ -7,51 +7,177 @@ class Page_AddUser extends Page
{
User::load();
- if (isset($_POST['action']) && $_POST['action'] === 'adduser') {
- // Check required fields
- if (empty($_POST['user']) || empty($_POST['pass1']) || empty($_POST['pass2']) || empty($_POST['fullname'])) {
- Message::addError('main.empty-field');
- Util::redirect('?do=AddUser');
- } elseif ($_POST['pass1'] !== $_POST['pass2']) {
- Message::addError('password-mismatch');
- Util::redirect('?do=AddUser');
- } elseif (!User::hasPermission('superadmin') && Database::queryFirst('SELECT userid FROM user LIMIT 1') !== false) {
- Message::addError('adduser-disabled');
- Util::redirect('?do=Session&action=login');
+ $action = Request::post(('action'), false, 'string');
+
+ if ($action === 'adduser') {
+ $this->addUser();
+ } elseif ($action === 'edituser') {
+ $this->editUser();
+ } elseif ($action === 'deleteuser') {
+ $this->deleteUser();
+ }
+ if (Request::isPost()) {
+ Util::redirect('?do=adduser');
+ }
+ }
+
+ private function addUser()
+ {
+ // Check required fields
+ $login = Request::post('login', '', 'string');
+ $pass1 = Request::post('pass1', '', 'string');
+ $pass2 = Request::post('pass2', '', 'string');
+ $fullname = Request::post('fullname', '', 'string');
+ $phone = Request::post('phone', '', 'string');
+ $email = Request::post('email', '', 'string');
+ if (empty($login) || empty($pass1) || empty($pass2) || empty($fullname)) {
+ Message::addError('main.empty-field');
+ return;
+ } elseif ($pass1 !== $pass2) {
+ Message::addError('password-mismatch');
+ return;
+ } else {
+ if (Database::queryFirst('SELECT userid FROM user LIMIT 1') !== false) {
+ User::assertPermission('user.add');
+ }
+ $data = array(
+ 'login' => $login,
+ 'pass' => Crypto::hash6($pass1),
+ 'fullname' => $fullname,
+ 'phone' => $phone,
+ 'email' => $email,
+ );
+ Database::exec('INSERT INTO user SET login = :login, passwd = :pass, fullname = :fullname, phone = :phone, email = :email', $data);
+ $id = Database::lastInsertId();
+ // Make it superadmin if first user. This method sucks as it's a race condition but hey...
+ $ret = Database::queryFirst('SELECT Count(*) AS num FROM user');
+ if ($ret !== false && $ret['num'] == 1) {
+ $ret = Database::exec('UPDATE user SET permissions = 1, userid = 1 WHERE userid = :id', ['id' => $id], true);
+ if ($ret !== false) {
+ EventLog::clear();
+ }
+ EventLog::info('Created first user ' . $login);
+ } else {
+ EventLog::info(User::getName() . ' created user ' . $login);
+ }
+ Message::addInfo('adduser-success');
+ return;
+ }
+ }
+
+ private function editUser()
+ {
+ User::assertPermission('user.edit');
+ $userid = Request::post('userid', false, 'int');
+ if ($userid === false) {
+ Message::addError('main.parameter-missing', 'userid');
+ return;
+ }
+ $user = Database::queryFirst('SELECT userid, login, fullname, phone, email
+ FROM user WHERE userid = :userid', compact('userid'));
+ if ($user === false) {
+ Message::addError('user-not-found', $userid);
+ return;
+ }
+ // Check required fields
+ $login = Request::post('login', '', 'string');
+ $pass1 = Request::post('pass1', '', 'string');
+ $pass2 = Request::post('pass2', '', 'string');
+ $fullname = Request::post('fullname', '', 'string');
+ $phone = Request::post('phone', '', 'string');
+ $email = Request::post('email', '', 'string');
+ if (empty($login) || empty($fullname)) {
+ Message::addError('main.empty-field');
+ } elseif (!(empty($pass1) && empty($pass2)) && $pass1 !== $pass2) {
+ Message::addError('password-mismatch');
+ } else {
+ $data = array(
+ 'login' => $login,
+ 'fullname' => $fullname,
+ 'phone' => $phone,
+ 'email' => $email,
+ 'userid' => $userid,
+ );
+ $ret = Database::exec('UPDATE user SET login = :login, fullname = :fullname, phone = :phone, email = :email WHERE userid = :userid', $data, true);
+ if ($ret === false) {
+ Message::addError('db-error', Database::lastError());
} else {
- $data = array(
- 'user' => $_POST['user'],
- 'pass' => Crypto::hash6($_POST['pass1']),
- 'fullname' => $_POST['fullname'],
- 'phone' => $_POST['phone'],
- 'email' => $_POST['email'],
- );
- if (Database::exec('INSERT INTO user SET login = :user, passwd = :pass, fullname = :fullname, phone = :phone, email = :email', $data) != 1) {
- Util::traceError('Could not create new user in DB');
+ if ($ret > 0) {
+ Message::addSuccess('user-edited');
}
- // Make it superadmin if first user. This method sucks as it's a race condition but hey...
- $ret = Database::queryFirst('SELECT Count(*) AS num FROM user');
- if ($ret !== false && $ret['num'] == 1) {
- Database::exec('UPDATE user SET permissions = 1');
- EventLog::clear();
- EventLog::info('Created first user ' . $_POST['user']);
- } else {
- EventLog::info(User::getName() . ' created user ' . $_POST['user']);
+ if (!empty($pass1)) {
+ $data = [
+ 'pass' => Crypto::hash6($pass1),
+ 'userid' => $userid,
+ ];
+ Database::exec('UPDATE user SET passwd = :pass WHERE userid = :userid', $data);
+ Message::addSuccess('password-changed');
}
- Message::addInfo('adduser-success');
- Util::redirect('?do=Session&action=login');
}
}
+ Util::redirect('?do=adduser&show=edituser&userid=' . $userid);
+ }
+
+ private function deleteUser()
+ {
+ User::assertPermission('user.remove');
+ $userid = Request::post('userid', false, 'int');
+ if ($userid === false) {
+ Message::addError('main.parameter-missing', 'userid');
+ return;
+ }
+ //\\
+ $user = Database::queryFirst('SELECT userid, login, fullname, phone, email
+ FROM user WHERE userid = :userid', compact('userid'));
+ if ($user === false) {
+ Message::addError('user-not-found', $userid);
+ return;
+ }
+ if ($user['userid'] == 1 || $user['userid'] == User::getId()) {
+ Message::addError('cannot-delete-1-self');
+ return;
+ }
+ Database::exec('DELETE FROM user WHERE userid = :userid', compact('userid'));
+ Message::addSuccess('user-deleted', $userid);
}
protected function doRender()
{
- // No user was added, check if current user is allowed to add a new user
- // Currently you can only add users if there is no user yet. :)
- if (!User::hasPermission('superadmin') && Database::queryFirst('SELECT userid FROM user LIMIT 1') !== false) {
- Message::addError('adduser-disabled');
- } else {
- Render::addTemplate('page-adduser', $_POST);
+ Render::addTemplate('header');
+ $hasUsers = (Database::queryFirst('SELECT userid FROM user LIMIT 1') !== false);
+ $show = Request::get('show', ($hasUsers ? 'list' : 'adduser'), 'string');
+ if ($show === 'adduser') {
+ // Can add user if: - no user exists yet; - user has explicit permission to add users
+ if ($hasUsers) {
+ User::assertPermission('user.add');
+ }
+ Render::addTemplate('page-adduser');
+ } elseif ($show === 'edituser') {
+ User::assertPermission('user.edit');
+ $userid = Request::get('userid', false, 'int');
+ if ($userid === false) {
+ Message::addError('main.parameter-missing', 'userid');
+ Util::redirect('?do=adduser&show=list');
+ }
+ $user = Database::queryFirst('SELECT userid, login, fullname, phone, email
+ FROM user WHERE userid = :userid', compact('userid'));
+ if ($user === false) {
+ Message::addError('user-not-found', $userid);
+ } else {
+ // TODO: LDAP -> disallow pw change, maybe other fields too?
+ Render::addTemplate('page-edituser', $user);
+ }
+ } elseif ($show === 'list') {
+ User::assertPermission('list.view');
+ $page = new Paginate('SELECT userid, login, fullname, phone, email FROM user ORDER BY login', 50);
+ $data = ['list' => $page->exec()->fetchAll(PDO::FETCH_ASSOC)];
+ foreach ($data['list'] as &$u) {
+ // Don't allow deleting user 1 and self
+ $u['hide_delete'] = $u['userid'] == 1 || $u['userid'] == User::getId();
+ }
+ unset($u);
+ Permission::addGlobalTags($data['perms'], null, ['user.add', 'user.edit', 'user.remove']);
+ $page->render('page-userlist', $data);
}
}
diff --git a/modules-available/adduser/permissions/permissions.json b/modules-available/adduser/permissions/permissions.json
new file mode 100644
index 00000000..e778b893
--- /dev/null
+++ b/modules-available/adduser/permissions/permissions.json
@@ -0,0 +1,14 @@
+{
+ "user.add": {
+ "location-aware": false
+ },
+ "user.edit": {
+ "location-aware": false
+ },
+ "user.remove": {
+ "location-aware": false
+ },
+ "list.view": {
+ "location-aware": false
+ }
+}
\ No newline at end of file
diff --git a/modules-available/adduser/style.css b/modules-available/adduser/style.css
new file mode 100644
index 00000000..e459352b
--- /dev/null
+++ b/modules-available/adduser/style.css
@@ -0,0 +1,15 @@
+.form-adduser {
+ max-width: 600px;
+ padding: 10px;
+ margin: 0 auto;
+}
+
+.form-adduser .form-control {
+ position: relative;
+ font-size: 16px;
+ height: auto;
+ padding: 10px;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
diff --git a/modules-available/adduser/templates/header.html b/modules-available/adduser/templates/header.html
new file mode 100644
index 00000000..34011e29
--- /dev/null
+++ b/modules-available/adduser/templates/header.html
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/modules-available/adduser/templates/page-adduser.html b/modules-available/adduser/templates/page-adduser.html
index deb911c0..58d705f8 100644
--- a/modules-available/adduser/templates/page-adduser.html
+++ b/modules-available/adduser/templates/page-adduser.html
@@ -1,28 +1,39 @@
diff --git a/modules-available/adduser/templates/page-edituser.html b/modules-available/adduser/templates/page-edituser.html
new file mode 100644
index 00000000..b8e51b5c
--- /dev/null
+++ b/modules-available/adduser/templates/page-edituser.html
@@ -0,0 +1,72 @@
+
diff --git a/modules-available/adduser/templates/page-userlist.html b/modules-available/adduser/templates/page-userlist.html
new file mode 100644
index 00000000..5b14f7e5
--- /dev/null
+++ b/modules-available/adduser/templates/page-userlist.html
@@ -0,0 +1,73 @@
+
{{lang_userlist}}
+
+{{{pagenav}}}
+
+
+
+
+
\ No newline at end of file
diff --git a/modules-available/systemstatus/templates/_page.html b/modules-available/systemstatus/templates/_page.html
index 59fffa3a..64830ea3 100644
--- a/modules-available/systemstatus/templates/_page.html
+++ b/modules-available/systemstatus/templates/_page.html
@@ -92,7 +92,7 @@
{{lang_maintenance}}