summaryrefslogtreecommitdiffstats
path: root/modules-available
diff options
context:
space:
mode:
authorUdo Walter2018-01-10 16:46:36 +0100
committerUdo Walter2018-01-10 16:46:36 +0100
commitcb9e1f591bc67864d36f65b3ba452e7fdab9b602 (patch)
treece0594a41b11e463e697c581b465bb7be8771ae2 /modules-available
parent[locations] fixed root location not getting disabled in the dropdown if (diff)
parent[exams] implemented permission system (diff)
downloadslx-admin-cb9e1f591bc67864d36f65b3ba452e7fdab9b602.tar.gz
slx-admin-cb9e1f591bc67864d36f65b3ba452e7fdab9b602.tar.xz
slx-admin-cb9e1f591bc67864d36f65b3ba452e7fdab9b602.zip
Merge remote-tracking branch 'origin/permission-manager' into permission-manager
Diffstat (limited to 'modules-available')
-rw-r--r--modules-available/exams/lang/de/permissions.json5
-rw-r--r--modules-available/exams/lang/en/permissions.json5
-rw-r--r--modules-available/exams/page.inc.php303
-rw-r--r--modules-available/exams/permissions/permissions.json5
-rw-r--r--modules-available/exams/templates/page-add-edit-exam.html2
-rw-r--r--modules-available/exams/templates/page-exams.html7
-rw-r--r--modules-available/exams/templates/page-upcoming-lectures.html2
-rw-r--r--modules-available/rebootcontrol/lang/de/permissions.json5
-rw-r--r--modules-available/rebootcontrol/lang/en/permissions.json5
-rw-r--r--modules-available/rebootcontrol/page.inc.php66
-rw-r--r--modules-available/rebootcontrol/permissions/permissions.json5
-rw-r--r--modules-available/rebootcontrol/templates/_page.html90
12 files changed, 363 insertions, 137 deletions
diff --git a/modules-available/exams/lang/de/permissions.json b/modules-available/exams/lang/de/permissions.json
new file mode 100644
index 00000000..3ead6249
--- /dev/null
+++ b/modules-available/exams/lang/de/permissions.json
@@ -0,0 +1,5 @@
+{
+ "exams.add": "Neues Examen hinzufügen.",
+ "exams.delete": "Examen löschen.",
+ "exams.edit": "Examen bearbeiten."
+} \ No newline at end of file
diff --git a/modules-available/exams/lang/en/permissions.json b/modules-available/exams/lang/en/permissions.json
new file mode 100644
index 00000000..3e14a761
--- /dev/null
+++ b/modules-available/exams/lang/en/permissions.json
@@ -0,0 +1,5 @@
+{
+ "exams.add": "Add new exam.",
+ "exams.delete": "Delete exam.",
+ "exams.edit": "Edit exam."
+} \ No newline at end of file
diff --git a/modules-available/exams/page.inc.php b/modules-available/exams/page.inc.php
index 75fb6a0b..b32f758c 100644
--- a/modules-available/exams/page.inc.php
+++ b/modules-available/exams/page.inc.php
@@ -9,6 +9,10 @@ class Page_Exams extends Page
private $currentExam;
private $rangeMin;
private $rangeMax;
+ private $userEditLocations = [];
+ private $userDeleteLocations = [];
+ private $userAddLocations = [];
+ private $allowedLocations = [];
/** if examid is set, also add a column 'selected' **/
@@ -37,9 +41,33 @@ class Page_Exams extends Page
. "LEFT JOIN sat.lecture l USING (lectureid) "
. "GROUP BY examid "
. "ORDER BY examid ASC");
+
while ($exam = $tmp->fetch(PDO::FETCH_ASSOC)) {
- $this->exams[] = $exam;
+ // check if allowed to edit this exam
+ if ($this->allowedToEdit($exam['examid'])) {
+ $exam['allowedEdit'] = True;
+ }
+ // check if allowed to delete this exam
+ if ($this->allowedToDelete($exam['examid'])) {
+ $exam['allowedDelete'] = True;
+ }
+
+
+ $locationids = explode(',', $exam['locationids']);
+ // if global permission, add all exams to the list, no filter required
+ if ($locationids[0] == 0) {
+ $this->exams[] = $exam;
+ } else {
+ foreach($locationids as $locid) {
+ // only add the exam if permisson for atleast one of the exam locations
+ if (in_array($locid, $this->allowedLocations)) {
+ $this->exams[] = $exam;
+ break;
+ }
+ }
+ }
}
+
}
protected function readLectures()
@@ -58,6 +86,67 @@ class Page_Exams extends Page
}
}
+ // Returns the list of locations of the exam
+ protected function getExamLocations($examid) {
+ $res = Database::simpleQuery("SELECT locationid FROM exams_x_location WHERE examid= :examid", array('examid' => $examid));
+ return $res;
+ }
+
+ // Initialise the user-permission-based lists
+ protected function setUserLocations() {
+
+ // all locations the user has permission to edit
+ $this->userEditLocations = User::getAllowedLocations("exams.edit");
+ // all locations the user has permission to delete
+ $this->userDeleteLocations = User::getAllowedLocations("exams.delete");
+ // all locations the user has permission to add
+ $this->userAddLocations = User::getAllowedLocations("exams.add");
+ // all locations the user has at least one of the 3 permissions
+ $this->allowedLocations = array_unique(array_merge($this->userAddLocations, $this->userEditLocations, $this->userDeleteLocations));
+ }
+
+ // returns true if user is allowed to delete the exam
+ protected function allowedToDelete($examid) {
+
+ $res = $this->getExamLocations($examid);
+ $locations = [];
+ while ($locId = $res->fetch(PDO::FETCH_ASSOC)) {
+ $locations[] = $locId['locationid'];
+ }
+
+ return empty(array_diff($locations, $this->userDeleteLocations));
+
+ }
+
+ // returns true if user is allowed to add an exam
+ protected function allowedToAdd() {
+ return User::hasPermission("exams.add");
+ }
+
+ // returns true if user is allowed to edit the exam
+ protected function allowedToEdit($examid) {
+
+ $res = $this->getExamLocations($examid);
+ $locations = [];
+ while ($locId = $res->fetch(PDO::FETCH_ASSOC)) {
+ $locations[] = $locId['locationid'];
+ }
+
+ return empty(array_diff($locations, $this->userEditLocations));
+
+ }
+
+ // checks if user is allowed to save an exam with all the locations
+ // needs information if it's add (second para = true) or edit (second para = false)
+ protected function allowedToSave($locationids, $isAdd) {
+
+ if ($isAdd) {
+ return empty(array_diff($locationids, $this->userAddLocations));
+ } else {
+ return empty(array_diff($locationids, $this->userEditLocations));
+ }
+ }
+
protected function makeItemsForVis()
{
$out = [];
@@ -88,6 +177,7 @@ class Page_Exams extends Page
$locationids[] = $location['locationid'];
}
}
+
foreach ($locationids as $locationid) {
$out[] = [
'id' => 'shadow_' . $unique_ids++,
@@ -131,13 +221,17 @@ class Page_Exams extends Page
protected function makeGroupsForVis()
{
+
$out = [];
+
foreach ($this->locations as $l) {
- $out[] = [
- 'id' => $l['locationid'],
- 'content' => $l['locationpad'] . ' ' . $l['locationname'],
- 'sortIndex' => $l['sortIndex'],
- ];
+ if (in_array($l["locationid"], $this->allowedLocations)) {
+ $out[] = [
+ 'id' => $l['locationid'],
+ 'content' => $l['locationpad'] . ' ' . $l['locationname'],
+ 'sortIndex' => $l['sortIndex'],
+ ];
+ }
}
return json_encode($out);
}
@@ -189,7 +283,7 @@ class Page_Exams extends Page
}
return $out;
}
-
+
protected function makeEditFromArray($source)
{
if (!isset($source['description']) && isset($source['displayname'])) {
@@ -242,42 +336,45 @@ class Page_Exams extends Page
if ($examid === 0) {
// No examid given, is add
- $res = Database::exec("INSERT INTO exams(lectureid, starttime, endtime, autologin, description) VALUES(:lectureid, :starttime, :endtime, :autologin, :description);",
- compact('lectureid', 'starttime', 'endtime', 'autologin', 'description')) !== false;
+ if ($this->allowedToSave($locationids, True)) {
+ $res = Database::exec("INSERT INTO exams(lectureid, starttime, endtime, autologin, description) VALUES(:lectureid, :starttime, :endtime, :autologin, :description);",
+ compact('lectureid', 'starttime', 'endtime', 'autologin', 'description')) !== false;
- $exam_id = Database::lastInsertId();
- foreach ($locationids as $lid) {
- $res = $res && Database::exec("INSERT INTO exams_x_location(examid, locationid) VALUES(:exam_id, :lid)", compact('exam_id', 'lid')) !== false;
- }
- if ($res === false) {
- Message::addError('exam-not-added');
- } else {
- Message::addInfo('exam-added-success');
+ $exam_id = Database::lastInsertId();
+ foreach ($locationids as $lid) {
+ $res = $res && Database::exec("INSERT INTO exams_x_location(examid, locationid) VALUES(:exam_id, :lid)", compact('exam_id', 'lid')) !== false;
+ }
+ if ($res === false) {
+ Message::addError('exam-not-added');
+ } else {
+ Message::addInfo('exam-added-success');
+ }
}
Util::redirect('?do=exams');
}
// Edit
+ if ($this->allowedToSave($locationids, False)) {
+ $this->currentExam = Database::queryFirst("SELECT * FROM exams WHERE examid = :examid", array('examid' => $examid));
+ if ($this->currentExam === false) {
+ Message::addError('invalid-exam-id', $examid);
+ Util::redirect('?do=exams');
+ }
- $this->currentExam = Database::queryFirst("SELECT * FROM exams WHERE examid = :examid", array('examid' => $examid));
- if ($this->currentExam === false) {
- Message::addError('invalid-exam-id', $examid);
- Util::redirect('?do=exams');
- }
-
- /* update fields */
- $res = Database::exec("UPDATE exams SET lectureid = :lectureid, starttime = :starttime, endtime = :endtime, autologin = :autologin, description = :description WHERE examid = :examid",
- compact('lectureid', 'starttime', 'endtime', 'description', 'examid', 'autologin')) !== false;
- /* drop all connections and reconnect to rooms */
- $res = $res && Database::exec("DELETE FROM exams_x_location WHERE examid = :examid", compact('examid')) !== false;
- /* reconnect */
- foreach ($locationids as $lid) {
- $res = $res && Database::exec("INSERT INTO exams_x_location(examid, locationid) VALUES(:examid, :lid)", compact('examid', 'lid')) !== false;
- }
- if ($res !== false) {
- Message::addInfo("changes-successfully-saved");
- } else {
- Message::addError("error-while-saving-changes");
+ /* update fields */
+ $res = Database::exec("UPDATE exams SET lectureid = :lectureid, starttime = :starttime, endtime = :endtime, autologin = :autologin, description = :description WHERE examid = :examid",
+ compact('lectureid', 'starttime', 'endtime', 'description', 'examid', 'autologin')) !== false;
+ /* drop all connections and reconnect to rooms */
+ $res = $res && Database::exec("DELETE FROM exams_x_location WHERE examid = :examid", compact('examid')) !== false;
+ /* reconnect */
+ foreach ($locationids as $lid) {
+ $res = $res && Database::exec("INSERT INTO exams_x_location(examid, locationid) VALUES(:examid, :lid)", compact('examid', 'lid')) !== false;
+ }
+ if ($res !== false) {
+ Message::addInfo("changes-successfully-saved");
+ } else {
+ Message::addError("error-while-saving-changes");
+ }
}
Util::redirect('?do=exams');
}
@@ -286,7 +383,7 @@ class Page_Exams extends Page
{
User::load();
- if (!User::hasPermission('superadmin')) {
+ if (!User::isLoggedIn()) {
Message::addError('main.no-permission');
Util::redirect('?do=Main');
}
@@ -299,26 +396,40 @@ class Page_Exams extends Page
$this->action = $req_action;
}
- if ($this->action === 'show') {
+ if (Request::isPost()) {
+ $examid = Request::post('examid', 0, 'int');
+ } else if (Request::isGet()) {
+ $examid = Request::get('examid', 0, 'int');
+ } else {
+ die('Neither Post nor Get Request send.');
+ }
+
+ // initialise user-permission-lists
+ $this->setUserLocations();
+ if ($this->action === 'show') {
$this->readExams();
$this->readLocations();
$this->readLectures();
} elseif ($this->action === 'add') {
- $this->readLectures();
+ if($this->allowedToAdd()) {
+ $this->readLectures();
+ }
} elseif ($this->action === 'edit') {
- $examid = Request::get('examid', 0, 'int');
- $this->currentExam = Database::queryFirst("SELECT * FROM exams WHERE examid = :examid", array('examid' => $examid));
- if ($this->currentExam === false) {
- Message::addError('invalid-exam-id', $examid);
- Util::redirect('?do=exams');
+ if($this->allowedToEdit($examid)) {
+ $this->currentExam = Database::queryFirst("SELECT * FROM exams WHERE examid = :examid", array('examid' => $examid));
+ if ($this->currentExam === false) {
+ Message::addError('invalid-exam-id', $examid);
+ Util::redirect('?do=exams');
+ }
+ $this->readLocations($examid);
+ $this->readLectures();
+
}
- $this->readLocations($examid);
- $this->readLectures();
} elseif ($this->action === 'save') {
@@ -329,14 +440,17 @@ class Page_Exams extends Page
if (!Request::isPost()) {
die('delete only works with a post request');
}
- $examid = Request::post('examid');
- $res1 = Database::exec("DELETE FROM exams WHERE examid = :examid;", compact('examid'));
- $res2 = Database::exec("DELETE FROM exams_x_location WHERE examid = :examid;", compact('examid'));
- if ($res1 === false || $res2 === false) {
- Message::addError('exam-not-deleted-error');
- } else {
- Message::addInfo('exam-deleted-success');
+
+ if ($this->allowedToDelete($examid)) {
+ $res1 = Database::exec("DELETE FROM exams WHERE examid = :examid;", compact('examid'));
+ $res2 = Database::exec("DELETE FROM exams_x_location WHERE examid = :examid;", compact('examid'));
+ if ($res1 === false || $res2 === false) {
+ Message::addError('exam-not-deleted-error');
+ } else {
+ Message::addInfo('exam-deleted-success');
+ }
}
+
Util::redirect('?do=exams');
} elseif ($this->action === false) {
@@ -348,13 +462,22 @@ class Page_Exams extends Page
protected function doRender()
{
+ if (Request::isPost()) {
+ $examid = Request::post('examid', 0, 'int');
+ } else if (Request::isGet()) {
+ $examid = Request::get('examid', 0, 'int');
+ } else {
+ die('Neither Post nor Get Request send.');
+ }
+
if ($this->action === "show") {
// General title and description
Render::addTemplate('page-main-heading');
// List of defined exam periods
Render::addTemplate('page-exams', [
- 'exams' => $this->makeExamsForTemplate()
+ 'exams' => $this->makeExamsForTemplate(),
+ 'allowedToAdd' => $this->allowedToAdd()
]);
// List of upcoming lectures marked as exam
$upcoming = $this->makeLectureExamList();
@@ -363,6 +486,7 @@ class Page_Exams extends Page
} else {
Render::addTemplate('page-upcoming-lectures', [
'pending_lectures' => $upcoming,
+ 'allowedToAdd' => $this->allowedToAdd(),
'decollapse' => array_key_exists('class', end($upcoming))
]);
}
@@ -380,37 +504,62 @@ class Page_Exams extends Page
} elseif ($this->action === "add") {
- Render::setTitle(Dictionary::translate('title_add-exam'));
- $data = [];
- $baseLecture = Request::any('lectureid', false, 'string');
- $locations = null;
- if ($baseLecture !== false) {
- foreach ($this->lectures as &$lecture) {
- if ($lecture['lectureid'] === $baseLecture) {
- $data['exam'] = $this->makeEditFromArray($lecture);
- $locations = explode(',', $lecture['lids']);
- $lecture['selected'] = 'selected';
- break;
+ if($this->allowedToAdd()) {
+ Render::setTitle(Dictionary::translate('title_add-exam'));
+ $data = [];
+ $baseLecture = Request::any('lectureid', false, 'string');
+ $locations = null;
+ if ($baseLecture !== false) {
+ foreach ($this->lectures as &$lecture) {
+ if ($lecture['lectureid'] === $baseLecture) {
+ $data['exam'] = $this->makeEditFromArray($lecture);
+ $locations = explode(',', $lecture['lids']);
+ $lecture['selected'] = 'selected';
+ break;
+ }
+ }
+ unset($lecture);
+ }
+
+ $this->readLocations($locations);
+ $data['lectures'] = $this->lectures;
+ $data['locations'] = $this->locations;
+
+ // if user has no permission to add for this location, disable the location in the select
+ foreach ($data['locations'] as &$loc) {
+ if (!in_array($loc["locationid"], $this->userAddLocations)) {
+ $loc["disabled"] = "disabled";
}
}
- unset($lecture);
+
+ Render::addTemplate('page-add-edit-exam', $data);
}
- $data['lectures'] = $this->lectures;
- $this->readLocations($locations);
- $data['locations'] = $this->locations;
- Render::addTemplate('page-add-edit-exam', $data);
} elseif ($this->action === 'edit') {
- Render::setTitle(Dictionary::translate('title_edit-exam'));
- $exam = $this->makeEditFromArray($this->currentExam);
- foreach ($this->lectures as &$lecture) {
- if ($lecture['lectureid'] === $this->currentExam['lectureid']) {
- $lecture['selected'] = 'selected';
+ if ($this->allowedToEdit($examid)) {
+ Render::setTitle(Dictionary::translate('title_edit-exam'));
+ $exam = $this->makeEditFromArray($this->currentExam);
+ foreach ($this->lectures as &$lecture) {
+ if ($lecture['lectureid'] === $this->currentExam['lectureid']) {
+ $lecture['selected'] = 'selected';
+ }
+ }
+
+ $data = [];
+ $data['exam'] = $exam;
+ $data['locations'] = $this->locations;
+ $data['lectures'] = $this->lectures;
+
+ // if user has no permission to edit for this location, disable the location in the select
+ foreach ($data['locations'] as &$loc) {
+ if (!in_array($loc["locationid"], $this->userEditLocations)) {
+ $loc["disabled"] = "disabled";
+ }
}
- }
- Render::addTemplate('page-add-edit-exam', ['exam' => $exam, 'locations' => $this->locations, 'lectures' => $this->lectures]);
+ Render::addTemplate('page-add-edit-exam', $data);
+ }
}
}
diff --git a/modules-available/exams/permissions/permissions.json b/modules-available/exams/permissions/permissions.json
new file mode 100644
index 00000000..215b3399
--- /dev/null
+++ b/modules-available/exams/permissions/permissions.json
@@ -0,0 +1,5 @@
+[
+ "exams.add",
+ "exams.delete",
+ "exams.edit"
+] \ No newline at end of file
diff --git a/modules-available/exams/templates/page-add-edit-exam.html b/modules-available/exams/templates/page-add-edit-exam.html
index 58c61b11..11bffed8 100644
--- a/modules-available/exams/templates/page-add-edit-exam.html
+++ b/modules-available/exams/templates/page-add-edit-exam.html
@@ -19,7 +19,7 @@
</div>
<select id="locations" multiple name="locations[]">
{{#locations}}
- <option value="{{locationid}}" {{#selected}}selected{{/selected}}>{{locationpad}} {{locationname}}</option>
+ <option value="{{locationid}}" {{disabled}} {{#selected}}selected{{/selected}}>{{locationpad}} {{locationname}}</option>
{{/locations}}
</select>
</div>
diff --git a/modules-available/exams/templates/page-exams.html b/modules-available/exams/templates/page-exams.html
index 29b8c319..bb6cbd0a 100644
--- a/modules-available/exams/templates/page-exams.html
+++ b/modules-available/exams/templates/page-exams.html
@@ -43,10 +43,9 @@
{{^liesInPast}}
<a onclick="slxShow({{starttime}}, {{endtime}})" class="btn btn-default btn-sm"><span class="glyphicon glyphicon-eye-open"></span></a>
{{/liesInPast}}
- <a href="?do=exams&action=edit&examid={{examid}}" class="btn btn-default btn-sm" >{{lang_edit}}</a>
- <input type="hidden" name="token" value="{{token}}">
+ <a href="?do=exams&action=edit&examid={{examid}}" class="btn btn-default btn-sm {{^allowedEdit}}disabled{{/allowedEdit}}"><span class="glyphicon glyphicon-edit"></span></a> <input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="examid" value="{{examid}}">
- <button class="btn {{btnClass}} btn-sm">{{lang_delete}}</button>
+ <button {{^allowedDelete}}disabled{{/allowedDelete}} class="btn {{btnClass}} btn-sm"><span class="glyphicon glyphicon-trash"></span></button>
</form>
</td>
</tr>
@@ -56,7 +55,7 @@
</div>
<div class="text-right">
<div class="btn-group" role="group">
- <a href="?do=exams&action=add" class="btn btn-success"><span class="glyphicon glyphicon-plus-sign"></span> {{lang_addExam}}</a>
+ <a href="?do=exams&action=add" class="btn btn-success {{^allowedToAdd}}disabled{{/allowedToAdd}}"><span class="glyphicon glyphicon-plus-sign"></span> {{lang_addExam}}</a>
</div>
</div>
</div>
diff --git a/modules-available/exams/templates/page-upcoming-lectures.html b/modules-available/exams/templates/page-upcoming-lectures.html
index 8ff8143e..074aa42d 100644
--- a/modules-available/exams/templates/page-upcoming-lectures.html
+++ b/modules-available/exams/templates/page-upcoming-lectures.html
@@ -31,7 +31,7 @@
<td width="20%">
<div class="pull-right text-nowrap">
<a class="btn btn-sm btn-default" role="button" onclick="slxShow({{starttime}}, {{endtime}})"><span class="glyphicon glyphicon-eye-open"></span></a>
- <a href="?do=exams&amp;action=add&amp;lectureid={{lectureid}}" class="btn btn-sm btn-success" role="button">
+ <a href="?do=exams&amp;action=add&amp;lectureid={{lectureid}}" class="btn btn-sm btn-success {{^allowedToAdd}}disabled{{/allowedToAdd}}" role="button">
<span class="glyphicon glyphicon-plus-sign"></span>
<span class="hidden-sm">{{lang_addExam}}</span>
</a>
diff --git a/modules-available/rebootcontrol/lang/de/permissions.json b/modules-available/rebootcontrol/lang/de/permissions.json
new file mode 100644
index 00000000..92eeb37e
--- /dev/null
+++ b/modules-available/rebootcontrol/lang/de/permissions.json
@@ -0,0 +1,5 @@
+{
+ "shutdown": "Client herunterfahren.",
+ "reboot": "Client neustarten.",
+ "newkeypair": "Neues Schlüsselpaar generieren."
+} \ No newline at end of file
diff --git a/modules-available/rebootcontrol/lang/en/permissions.json b/modules-available/rebootcontrol/lang/en/permissions.json
new file mode 100644
index 00000000..077890fb
--- /dev/null
+++ b/modules-available/rebootcontrol/lang/en/permissions.json
@@ -0,0 +1,5 @@
+{
+ "shutdown": "Shutdown Client.",
+ "reboot": "Reboot Client.",
+ "newkeypair": "Generate new Keypair."
+} \ No newline at end of file
diff --git a/modules-available/rebootcontrol/page.inc.php b/modules-available/rebootcontrol/page.inc.php
index fc3ded8f..fa34a05a 100644
--- a/modules-available/rebootcontrol/page.inc.php
+++ b/modules-available/rebootcontrol/page.inc.php
@@ -4,6 +4,9 @@ class Page_RebootControl extends Page
{
private $action = false;
+ private $allowedShutdownLocs = [];
+ private $allowedRebootLocs = [];
+ private $allowedLocs = [];
/**
* Called before any page rendering happens - early hook to check parameters etc.
@@ -17,21 +20,40 @@ class Page_RebootControl extends Page
Util::redirect('?do=Main'); // does not return
}
+ $this->allowedShutdownLocs = User::getAllowedLocations("shutdown");
+ $this->allowedRebootLocs = User::getAllowedLocations("reboot");
+ $this->allowedLocs = array_unique(array_merge($this->allowedShutdownLocs, $this->allowedRebootLocs));
+
$this->action = Request::any('action', 'show', 'string');
if ($this->action === 'startReboot' || $this->action === 'startShutdown') {
- $clients = Request::post('clients');
- if (!is_array($clients) || empty($clients)) {
- Message::addError('no-clients-selected');
- Util::redirect();
- }
+
$locationId = Request::post('locationId', false, 'int');
if ($locationId === false) {
Message::addError('locations.invalid-location-id', $locationId);
Util::redirect();
}
+
$shutdown = $this->action === "startShutdown";
+ // Check user permission (if user has no permission, the getAllowed-list will be empty and the check will fail)
+ if ($shutdown) {
+ if (!in_array($locationId, $this->allowedShutdownLocs)) {
+ Message::addError('main.no-permission');
+ Util::redirect();
+ }
+ } else {
+ if (!in_array($locationId, $this->allowedRebootLocs)) {
+ Message::addError('main.no-permission');
+ Util::redirect();
+ }
+ }
+
+ $clients = Request::post('clients');
+ if (!is_array($clients) || empty($clients)) {
+ Message::addError('no-clients-selected');
+ Util::redirect();
+ }
$minutes = Request::post('minutes', 0, 'int');
$list = RebootQueries::getMachinesByUuid($clients);
@@ -72,12 +94,34 @@ class Page_RebootControl extends Page
//location you want to see, default are "not assigned" clients
$requestedLocation = Request::get('location', 0, 'int');
- $data['data'] = RebootQueries::getMachineTable($requestedLocation);
- $data['locations'] = Location::getLocations($requestedLocation, 0, true);
+ // only fill table if user has at least one permission for the location
+ if (in_array($requestedLocation, $this->allowedLocs)) {
+ $data['data'] = RebootQueries::getMachineTable($requestedLocation);
+ $data['allowedToSelect'] = True;
+ }
+ $data['locations'] = Location::getLocations($requestedLocation, 0, true);
+ // Always show public key (it's public, isn't it?)
$data['pubKey'] = SSHKey::getPublicKey();
+ // disable each location user has no permission for
+ foreach ($data['locations'] as &$loc) {
+ if (!in_array($loc["locationid"], $this->allowedLocs)) {
+ $loc["disabled"] = "disabled";
+ }
+ }
+
+ // Only enable shutdown/reboot-button if user has permission for the location
+ if (in_array($requestedLocation, $this->allowedShutdownLocs)) {
+ $data['allowedToShutdown'] = True;
+ }
+ if (in_array($requestedLocation, $this->allowedRebootLocs)) {
+ $data['allowedToReboot'] = True;
+ }
+ $data['allowedToGenerateKey'] = User::hasPermission("newkeypair");
+
Render::addTemplate('_page', $data);
+
}
}
}
@@ -86,8 +130,12 @@ class Page_RebootControl extends Page
{
$this->action = Request::post('action', false, 'string');
if ($this->action === 'generateNewKeypair') {
- Property::set("rebootcontrol-private-key", false);
- echo SSHKey::getPublicKey();
+ if (User::hasPermission("newkeypair")) {
+ Property::set("rebootcontrol-private-key", false);
+ echo SSHKey::getPublicKey();
+ } else {
+ echo 'No permission.';
+ }
} else {
echo 'Invalid action.';
}
diff --git a/modules-available/rebootcontrol/permissions/permissions.json b/modules-available/rebootcontrol/permissions/permissions.json
new file mode 100644
index 00000000..5230c9bd
--- /dev/null
+++ b/modules-available/rebootcontrol/permissions/permissions.json
@@ -0,0 +1,5 @@
+[
+ "shutdown",
+ "reboot",
+ "newkeypair"
+] \ No newline at end of file
diff --git a/modules-available/rebootcontrol/templates/_page.html b/modules-available/rebootcontrol/templates/_page.html
index 1bef8dd4..9b470943 100644
--- a/modules-available/rebootcontrol/templates/_page.html
+++ b/modules-available/rebootcontrol/templates/_page.html
@@ -8,15 +8,15 @@
<input type="hidden" name="token" value="{{token}}">
<div class="row">
<div class="col-md-12">
- <label>{{lang_location}}:
- <select id="locationDropdown" name="locationId" class="form-control" onchange="selectLocation()">
- {{#locations}}
- <option value="{{locationid}}" {{#selected}}selected{{/selected}}>{{locationpad}} {{locationname}}</option>
- {{/locations}}
- </select>
- </label>
- <button type="button" id="selectAllButton" class="btn btn-primary pull-right" onclick="selectAllRows()"><span class="glyphicon glyphicon-check"></span> {{lang_selectall}}</button>
- <button type="button" id="unselectAllButton" class="btn btn-default pull-right" onclick="unselectAllRows()" style="display: none;"><span class="glyphicon glyphicon-unchecked"></span> {{lang_unselectall}}</button>
+ <label>{{lang_location}}:
+ <select id="locationDropdown" name="locationId" class="form-control" onchange="selectLocation()">
+ {{#locations}}
+ <option value="{{locationid}}" {{disabled}} {{#selected}}selected{{/selected}}>{{locationpad}} {{locationname}}</option>
+ {{/locations}}
+ </select>
+ </label>
+ <button type="button" id="selectAllButton" {{^allowedToSelect}}disabled{{/allowedToSelect}} class="btn btn-primary pull-right" onclick="selectAllRows()"><span class="glyphicon glyphicon-check"></span> {{lang_selectall}}</button>
+ <button type="button" id="unselectAllButton" {{^allowedToSelect}}disabled{{/allowedToSelect}} class="btn btn-default pull-right" onclick="unselectAllRows()" style="display: none;"><span class="glyphicon glyphicon-unchecked"></span> {{lang_unselectall}}</button>
<button type="button" id="rebootButton" class="btn btn-warning pull-right" data-toggle="modal" data-target="#rebootModal" disabled><span class="glyphicon glyphicon-repeat"></span> {{lang_rebootButton}}</button>
<button type="button" id="shutdownButton" class="btn btn-danger pull-right" data-toggle="modal" data-target="#shutdownModal" disabled><span class="glyphicon glyphicon-off"></span> {{lang_shutdownButton}}</button>
</div>
@@ -25,41 +25,41 @@
<div class="col-md-12">
<table class="table table-condensed table-hover stupidtable" id="dataTable">
<thead>
- <tr>
- <th data-sort="string">{{lang_client}}</th>
- <th data-sort="ipv4">{{lang_ip}}</th>
- <th data-sort="string">{{lang_status}}</th>
- <th data-sort="string">{{lang_session}}</th>
- <th data-sort="string">{{lang_user}}</th>
- <th data-sort="int" data-sort-default="desc">{{lang_selected}}</th>
- </tr>
+ <tr>
+ <th data-sort="string">{{lang_client}}</th>
+ <th data-sort="ipv4">{{lang_ip}}</th>
+ <th data-sort="string">{{lang_status}}</th>
+ <th data-sort="string">{{lang_session}}</th>
+ <th data-sort="string">{{lang_user}}</th>
+ <th data-sort="int" data-sort-default="desc">{{lang_selected}}</th>
+ </tr>
</thead>
<tbody>
{{#data}}
- <tr>
- <td>
- {{hostname}}
- {{^hostname}}{{clientip}}{{/hostname}}
- </td>
- <td>{{clientip}}</td>
- <td class="statusColumn">
- {{#status}}
- <span class="text-success">{{lang_on}}</span>
- {{/status}}
- {{^status}}
- <span class="text-danger">{{lang_off}}</span>
- {{/status}}
- </td>
- <td>{{#status}}{{currentsession}}{{/status}}</td>
- <td>{{#status}}{{currentuser}}{{/status}}</td>
- <td data-sort-value="0" class="checkboxColumn">
- <div class="checkbox">
- <input id="m-{{machineuuid}}" type="checkbox" name="clients[]" value='{{machineuuid}}'>
- <label for="m-{{machineuuid}}"></label>
- </div>
- </td>
- </tr>
+ <tr>
+ <td>
+ {{hostname}}
+ {{^hostname}}{{clientip}}{{/hostname}}
+ </td>
+ <td>{{clientip}}</td>
+ <td class="statusColumn">
+ {{#status}}
+ <span class="text-success">{{lang_on}}</span>
+ {{/status}}
+ {{^status}}
+ <span class="text-danger">{{lang_off}}</span>
+ {{/status}}
+ </td>
+ <td>{{#status}}{{currentsession}}{{/status}}</td>
+ <td>{{#status}}{{currentuser}}{{/status}}</td>
+ <td data-sort-value="0" class="checkboxColumn">
+ <div class="checkbox">
+ <input id="m-{{machineuuid}}" type="checkbox" name="clients[]" value='{{machineuuid}}'>
+ <label for="m-{{machineuuid}}"></label>
+ </div>
+ </td>
+ </tr>
{{/data}}
</tbody>
</table>
@@ -79,7 +79,7 @@
</div>
<div class="modal-body">
<span id="pubKeyTitle">{{lang_pubKey}}</span>
- <button class="btn btn-s btn-warning pull-right" onclick="generateNewKeypair()" type="button"><span class="glyphicon glyphicon-refresh"></span> {{lang_genNew}}</button>
+ <button {{^allowedToGenerateKey}}disabled{{/allowedToGenerateKey}} class="btn btn-s btn-warning pull-right" onclick="generateNewKeypair()" type="button"><span class="glyphicon glyphicon-refresh"></span> {{lang_genNew}}</button>
<pre id="pubKey">{{pubKey}}</pre>
</div>
<div class="modal-footer">
@@ -100,7 +100,7 @@
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{lang_cancel}}</button>
- <button type="submit" name="action" value="startReboot" class="btn btn-warning"><span class="glyphicon glyphicon-repeat"></span> {{lang_reboot}}</button>
+ <button type="submit" {{^allowedToReboot}}disabled{{/allowedToReboot}} name="action" value="startReboot" class="btn btn-warning"><span class="glyphicon glyphicon-repeat"></span> {{lang_reboot}}</button>
</div>
</div>
</div>
@@ -115,11 +115,11 @@
</div>
<div class="modal-body">
{{lang_shutdownCheck}}
- {{lang_shutdownIn}} <input id="shutdownTimer" name="minutes" title="{{lang_shutdownIn}}" type="number" value="0" min="0" onkeypress="return isNumberKey(event)"> {{lang_minutes}}
+ {{lang_shutdownIn}} <input id="shutdownTimer" name="minutes" title="{{lang_shutdownIn}}" type="number" value="0" min="0" onkeypress="return isNumberKey(event)"> {{lang_minutes}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{lang_cancel}}</button>
- <button type="submit" name="action" value="startShutdown" class="btn btn-danger"><span class="glyphicon glyphicon-off"></span> {{lang_shutdownButton}}</button>
+ <button type="submit" {{^allowedToShutdown}}disabled{{/allowedToShutdown}} name="action" value="startShutdown" class="btn btn-danger"><span class="glyphicon glyphicon-off"></span> {{lang_shutdownButton}}</button>
</div>
</div>
</div>
@@ -162,7 +162,7 @@
$('#rebootButton').prop('disabled', false);
$('#shutdownButton').prop('disabled', false);
}
- });
+ });
$('.checkboxColumn').click(function(e) {
if (e.target === this) {
$(this).find('input[type="checkbox"]').click();