summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2018-03-05 14:17:36 +0100
committerSimon Rettberg2018-03-05 14:17:36 +0100
commitda8870e85f59dc8e83d2c4f50432f688080cb1d1 (patch)
treea36e939019e32ae8954137c02334bcf4b332f170
parent[locationinfo] Add permission entry to runmode config (diff)
downloadslx-admin-da8870e85f59dc8e83d2c4f50432f688080cb1d1.tar.gz
slx-admin-da8870e85f59dc8e83d2c4f50432f688080cb1d1.tar.xz
slx-admin-da8870e85f59dc8e83d2c4f50432f688080cb1d1.zip
[locationinfo] Add permissions
-rw-r--r--modules-available/locationinfo/inc/splittime.php.txt80
-rw-r--r--modules-available/locationinfo/page.inc.php128
-rw-r--r--modules-available/locationinfo/permissions/permissions.json20
-rw-r--r--modules-available/locationinfo/templates/page-locations.html4
-rw-r--r--modules-available/locationinfo/templates/page-panels.html8
-rw-r--r--modules-available/locationinfo/templates/page-servers.html9
-rw-r--r--modules-available/locationinfo/templates/page-tabs.html6
7 files changed, 221 insertions, 34 deletions
diff --git a/modules-available/locationinfo/inc/splittime.php.txt b/modules-available/locationinfo/inc/splittime.php.txt
new file mode 100644
index 00000000..53510fee
--- /dev/null
+++ b/modules-available/locationinfo/inc/splittime.php.txt
@@ -0,0 +1,80 @@
+(Unfinished)
+
+ /*
+ error_log('Pre calendar: ' . print_r($calendar, true));
+ $bad = array();
+ for ($i = 0; $i < count($calendar); ++$i) { // Use for..count as we append while iterating
+ $entry =& $calendar[$i];
+ // YYYY-MM-DD<T>HH:MM:SS
+ $s = explode('T', $entry['start']);
+ $e = explode('T', $entry['end']);
+ if (count($s) !== 2 || count($e) !== 2) {
+ error_log('Ignoring invalid calendar entry from backend ' . $this->serverId . ': ' . json_encode($entry));
+ $bad[] = $i;
+ continue;
+ }
+ if ($e[0] === $s[0]) // Same day
+ continue;
+ $stime = explode(':', $s[1]);
+ $etime = explode(':', $e[1]);
+ if (count($stime) < 2 || count($etime) < 2) {
+ error_log('Ignoring invalid calendar entry from backend ' . $this->serverId . ': ' . json_encode($entry));
+ $bad[] = $i;
+ continue;
+ }
+ // Fix start
+ if ($stime[0] == 23 && $stime[1] >= 30) {
+ // clamp to next day
+ $day = strtotime($s[0] . ' 12:00 +1 day');
+ if ($day === false || $day <= 0) {
+ error_log('Ignoring invalid calendar entry from backend ' . $this->serverId . ': ' . json_encode($entry));
+ $bad[] = $i;
+ continue;
+ }
+ $day = date('Y-m-d', $day);
+ $bad[] = $i;
+ $calendar[] = array(
+ 'title' => $entry['title'],
+ 'start' => $day . 'T00:00:01',
+ 'end' => $entry['end']
+ );
+ continue;
+ }
+
+ // Fix end
+ if ($etime[0] == 0 && $etime[1] <= 30) {
+ // clamp to next day
+ $day = strtotime($e[0] . ' 12:00 -1 day');
+ if ($day === false || $day <= 0) {
+ error_log('Ignoring invalid calendar entry from backend ' . $this->serverId . ': ' . json_encode($entry));
+ $bad[] = $i;
+ continue;
+ }
+ $day = date('Y-m-d', $day);
+ $bad[] = $i;
+ $calendar[] = array(
+ 'title' => $entry['title'],
+ 'start' => $day . 'T23:59:59',
+ 'end' => $entry['end']
+ );
+ continue;
+ }
+ // Split
+ $nextday = strtotime($s[0] . ' 12:00 +1 day');
+ $nextday = date('Y-m-d', $nextday);
+ $calendar[] = array(
+ 'title' => $entry['title'],
+ 'start' => $nextday . 'T00:00:01',
+ 'end' => $entry['end']
+ );
+ $entry['end'] = $s[0] . 'T23:59:59';
+ }
+ unset($entry);
+ if (!empty($bad)) {
+ foreach ($bad as $i) {
+ unset($calendar[$i]);
+ }
+ $calendar = array_values($calendar);
+ }
+ */
+ error_log('Post calendar: ' . print_r($calendar, true)); \ No newline at end of file
diff --git a/modules-available/locationinfo/page.inc.php b/modules-available/locationinfo/page.inc.php
index 777b84db..690012ea 100644
--- a/modules-available/locationinfo/page.inc.php
+++ b/modules-available/locationinfo/page.inc.php
@@ -2,16 +2,15 @@
class Page_LocationInfo extends Page
{
-
- private $action;
+ private $show;
/**
* Called before any page rendering happens - early hook to check parameters etc.
*/
protected function doPreprocess()
{
- $show = Request::any('show', '', 'string');
- if ($show === 'panel') {
+ $this->show = Request::any('show', false, 'string');
+ if ($this->show === 'panel') {
$this->showPanel();
exit(0);
}
@@ -20,30 +19,39 @@ class Page_LocationInfo extends Page
Message::addError('main.no-permission');
Util::redirect('?do=Main'); // does not return
}
- $this->action = Request::post('action');
- if ($this->action === 'writePanelConfig') {
+ $action = Request::post('action');
+ if ($action === 'writePanelConfig') {
$this->writePanelConfig();
- } elseif ($this->action === 'writeLocationConfig') {
+ } elseif ($action === 'writeLocationConfig') {
$this->writeLocationConfig();
$show = 'locations';
- } elseif ($this->action === 'deleteServer') {
+ } elseif ($action === 'deleteServer') {
$this->deleteServer();
- } elseif ($this->action === 'deletePanel') {
+ } elseif ($action === 'deletePanel') {
$this->deletePanel();
- } elseif ($this->action === 'checkConnection') {
+ } elseif ($action === 'checkConnection') {
$this->checkConnection(Request::post('serverid', 0, 'int'));
$show = 'backends';
- } elseif ($this->action === 'updateServerSettings') {
+ } elseif ($action === 'updateServerSettings') {
$this->updateServerSettings();
$show = 'backends';
} elseif (Request::isPost()) {
- Message::addWarning('main.invalid-action', $this->action);
+ Message::addWarning('main.invalid-action', $action);
}
- if (Request::isPost()) {
+ if (Request::isPost() || $this->show === false) {
if (!empty($show)) {
- $show = '&show=' . $show;
+ //
+ } elseif (User::hasPermission('panel.list')) {
+ $show = 'panels';
+ } elseif (User::hasPermission('location.*')) {
+ $show = 'locations';
+ } elseif (User::hasPermission('backend.*')) {
+ $show = 'backends';
+ } else {
+ Message::addError('main.no-permission');
+ Util::redirect('?do=main');
}
- Util::redirect('?do=locationinfo' . $show);
+ Util::redirect('?do=locationinfo&show=' . $show);
}
}
@@ -53,10 +61,13 @@ class Page_LocationInfo extends Page
protected function doRender()
{
// Do this here so we always see backend errors
- $backends = $this->loadBackends();
- $show = Request::get('show', '', 'string');
- Render::addTemplate('page-tabs', array('class-' . $show => 'active'));
- switch ($show) {
+ if (User::hasPermission('backend.*')) {
+ $backends = $this->loadBackends();
+ }
+ $data = array('class-' . $this->show => 'active');
+ Permission::addGlobalTags($data['perms'], null, ['backend.*', 'location.*', 'panel.list']);
+ Render::addTemplate('page-tabs', $data);
+ switch ($this->show) {
case 'locations':
$this->showLocationsTable();
break;
@@ -66,7 +77,7 @@ class Page_LocationInfo extends Page
case 'edit-panel':
$this->showPanelConfig();
break;
- case '':
+ case 'panels':
$this->showPanelsTable();
break;
default:
@@ -79,6 +90,7 @@ class Page_LocationInfo extends Page
*/
private function deleteServer()
{
+ User::assertPermission('backend.edit');
$id = Request::post('serverid', false, 'int');
if ($id === false) {
Message::addError('server-id-missing');
@@ -97,6 +109,7 @@ class Page_LocationInfo extends Page
Message::addError('main.parameter-missing', 'uuid');
return;
}
+ $this->assertPanelPermission($id, 'panel.edit');
$res = Database::exec("DELETE FROM `locationinfo_panel` WHERE paneluuid = :id", array('id' => $id));
if ($res !== 1) {
Message::addWarning('invalid-panel-id', $id);
@@ -123,6 +136,8 @@ class Page_LocationInfo extends Page
Message::addError('location.invalid-location-id', $locationid);
return false;
}
+ User::assertPermission('location.edit', $locationid);
+
$serverid = Request::post('serverid', 0, 'int');
if ($serverid === 0) {
$serverid = null;
@@ -304,6 +319,8 @@ class Page_LocationInfo extends Page
Util::redirect('?do=locationinfo');
}
+ // Permission
+ $this->assertPanelPermission($paneluuid, 'panel.edit', $params['locationids']);
if ($paneluuid === 'new') {
$paneluuid = Util::randomUuid();
@@ -379,6 +396,7 @@ class Page_LocationInfo extends Page
*/
private function updateServerSettings()
{
+ User::assertPermission('backend.edit');
$serverid = Request::post('id', -1, 'int');
$servername = Request::post('name', 'unnamed', 'string');
$servertype = Request::post('type', '', 'string');
@@ -423,6 +441,7 @@ class Page_LocationInfo extends Page
if ($serverid === 0) {
Util::traceError('checkConnection called with no server id');
}
+ User::assertPermission('backend.check');
$dbresult = Database::queryFirst("SELECT servertype, credentials
FROM `locationinfo_coursebackend`
@@ -482,14 +501,22 @@ class Page_LocationInfo extends Page
*/
private function showBackendsTable($serverlist)
{
- // Pass the data to the html and render it.
- Render::addTemplate('page-servers', array(
+ User::assertPermission('backend.*');
+ $data = array(
'serverlist' => $serverlist,
- ));
+ );
+ Permission::addGlobalTags($data['perms'], null, ['backend.edit', 'backend.check']);
+ // Pass the data to the html and render it.
+ Render::addTemplate('page-servers', $data);
}
private function showLocationsTable()
{
+ $allowedLocations = User::getAllowedLocations('location.edit');
+ if (empty($allowedLocations)) {
+ Message::addError('main.no-permission');
+ return;
+ }
$locations = Location::getLocations(0, 0, false, true);
// Get hidden state of all locations
@@ -499,7 +526,7 @@ class Page_LocationInfo extends Page
while ($row = $dbquery->fetch(PDO::FETCH_ASSOC)) {
$locid = (int)$row['locationid'];
- if (!isset($locations[$locid]))
+ if (!isset($locations[$locid]) || !in_array($locid, $allowedLocations))
continue;
$glyph = !empty($row['openingtime']) ? 'ok' : '';
$backend = '';
@@ -517,6 +544,7 @@ class Page_LocationInfo extends Page
$stack = array();
$depth = -1;
foreach ($locations as &$location) {
+ $location['allowed'] = in_array($location['locationid'], $allowedLocations);
while ($location['depth'] <= $depth) {
array_pop($stack);
$depth--;
@@ -537,6 +565,13 @@ class Page_LocationInfo extends Page
private function showPanelsTable()
{
+ $visibleLocations = User::getAllowedLocations('panel.list');
+ $editLocations = User::getAllowedLocations('panel.edit');
+ $assignLocations = USer::getAllowedLocations('panel.assign-client');
+ if (empty($visibleLocations)) {
+ Message::addError('main.no-permission');
+ return;
+ }
$res = Database::simpleQuery('SELECT p.paneluuid, p.panelname, p.locationids, p.panelconfig,
p.paneltype FROM locationinfo_panel p
ORDER BY panelname ASC');
@@ -550,8 +585,17 @@ class Page_LocationInfo extends Page
if ($row['paneltype'] === 'URL') {
$url = json_decode($row['panelconfig'], true)['url'];
$row['locations'] = $row['locationurl'] = $url;
+ $row['edit_disabled'] = empty($editLocations) ? 'disabled' : '';
+ $row['runmode_disabled'] = empty($assignLocations) ? 'disabled' : '';
} else {
$lids = explode(',', $row['locationids']);
+ // Permissions
+ if (!empty(array_diff($lids, $visibleLocations))) {
+ continue;
+ }
+ $row['edit_disabled'] = !empty(array_diff($lids, $editLocations)) ? 'disabled' : '';
+ $row['runmode_disabled'] = !empty(array_diff($lids, $assignLocations)) ? 'disabled' : '';
+ // Locations
$locs = array_map(function ($id) use ($locations) {
return isset($locations[$id]) ? $locations[$id]['locationname'] : $id;
}, $lids);
@@ -594,6 +638,7 @@ class Page_LocationInfo extends Page
*/
private function ajaxServerSettings($id)
{
+ User::assertPermission('backend.edit');
$oldConfig = Database::queryFirst('SELECT servername, servertype, credentials
FROM `locationinfo_coursebackend` WHERE serverid = :id', array('id' => $id));
@@ -641,6 +686,7 @@ class Page_LocationInfo extends Page
*/
private function ajaxConfigLocation($id)
{
+ User::assertPermission('location.edit', $id);
$locConfig = Database::queryFirst("SELECT serverid, serverlocationid, openingtime FROM `locationinfo_locationconfig` WHERE locationid = :id", array('id' => $id));
if ($locConfig !== false) {
$openingtimes = json_decode($locConfig['openingtime'], true);
@@ -845,6 +891,9 @@ class Page_LocationInfo extends Page
$config = json_decode($panel['panelconfig'], true);
}
+ // Permission
+ $this->assertPanelPermission($panel, 'panel.edit');
+
$def = LocationInfo::defaultPanelConfig($panel['paneltype']);
if (!is_array($config)) {
$config = $def;
@@ -953,4 +1002,35 @@ class Page_LocationInfo extends Page
die('Unknown panel type ' . $type);
}
+ /**
+ * @param string|array $panelOrUuid UUID of panel, or array with keys paneltype and locationds
+ * @param string $permission
+ * @param null|int[] $additionalLocations
+ */
+ private function assertPanelPermission($panelOrUuid, $permission, $additionalLocations = null)
+ {
+ if (is_array($panelOrUuid)) {
+ $panel = $panelOrUuid;
+ } else {
+ $panel = Database::queryFirst('SELECT paneltype, locationids FROM locationinfo_panel
+ WHERE paneluuid = :uuid', ['uuid' => $panelOrUuid]);
+ }
+ if ($panel === false || $panel['paneltype'] === 'URL' || empty($panel['locationids'])) {
+ if (empty($additionalLocations)) {
+ User::assertPermission($permission, null, '?do=locationinfo');
+ }
+ }
+ $allowed = User::getAllowedLocations($permission);
+ if (!empty($allowed)) {
+ $locations = explode(',', $panel['locationids']);
+ if (!empty($additionalLocations)) {
+ $locations = array_merge($locations, $additionalLocations);
+ }
+ if (empty(array_diff($locations, $allowed)))
+ return;
+ }
+ Message::addError('main.no-permission');
+ Util::redirect('?do=locationinfo');
+ }
+
}
diff --git a/modules-available/locationinfo/permissions/permissions.json b/modules-available/locationinfo/permissions/permissions.json
new file mode 100644
index 00000000..be95a7bd
--- /dev/null
+++ b/modules-available/locationinfo/permissions/permissions.json
@@ -0,0 +1,20 @@
+{
+ "backend.edit": {
+ "location-aware": false
+ },
+ "backend.check": {
+ "location-aware": false
+ },
+ "location.edit": {
+ "location-aware": true
+ },
+ "panel.list": {
+ "location-aware": true
+ },
+ "panel.edit": {
+ "location-aware": true
+ },
+ "panel.assign-client": {
+ "location-aware": true
+ }
+} \ No newline at end of file
diff --git a/modules-available/locationinfo/templates/page-locations.html b/modules-available/locationinfo/templates/page-locations.html
index 37d8dd96..94c4cd40 100644
--- a/modules-available/locationinfo/templates/page-locations.html
+++ b/modules-available/locationinfo/templates/page-locations.html
@@ -17,10 +17,14 @@
<tr>
<td>
<div style="display:inline-block;width:{{depth}}em"></div>
+ {{#allowed}}
<a href="#" class="loc-name {{^depth}}slx-bold{{/depth}}" data-locationid="{{locationid}}">
+ {{/allowed}}
{{locationname}}
+ {{#allowed}}
<span class="glyphicon glyphicon-edit"></span>
</a>
+ {{/allowed}}
</td>
<td {{#backendMissing}}class="text-danger"{{/backendMissing}}>
{{backend}}
diff --git a/modules-available/locationinfo/templates/page-panels.html b/modules-available/locationinfo/templates/page-panels.html
index e17b6584..2bccc796 100644
--- a/modules-available/locationinfo/templates/page-panels.html
+++ b/modules-available/locationinfo/templates/page-panels.html
@@ -34,19 +34,21 @@
</td>
{{#hasRunmode}}
<td>
- <a class="btn btn-default btn-xs" href="?do=runmode&amp;module=locationinfo&amp;modeid={{paneluuid}}&amp;redirect=?do=locationinfo">
+ <a class="btn btn-default btn-xs {{runmode_disabled}}"
+ href="?do=runmode&amp;module=locationinfo&amp;modeid={{paneluuid}}&amp;redirect=?do=locationinfo">
<span class="glyphicon glyphicon-edit"></span>
</a>
{{assignedMachineCount}}
</td>
{{/hasRunmode}}
<td>
- <a class="btn btn-default btn-xs" href="?do=locationinfo&amp;show=edit-panel&amp;uuid={{paneluuid}}">
+ <a class="btn btn-default btn-xs {{edit_disabled}}"
+ href="?do=locationinfo&amp;show=edit-panel&amp;uuid={{paneluuid}}">
<span class="glyphicon glyphicon-cog"></span>
</a>
</td>
<td>
- <button type="submit" name="uuid" value="{{paneluuid}}" class="btn btn-danger btn-xs">
+ <button type="submit" name="uuid" value="{{paneluuid}}" class="btn btn-danger btn-xs" {{edit_disabled}}>
<span class="glyphicon glyphicon-trash"></span>
</button>
</td>
diff --git a/modules-available/locationinfo/templates/page-servers.html b/modules-available/locationinfo/templates/page-servers.html
index dbf18b5f..3edb0e66 100644
--- a/modules-available/locationinfo/templates/page-servers.html
+++ b/modules-available/locationinfo/templates/page-servers.html
@@ -22,18 +22,19 @@
<td align="center" nowrap>
<button class="btn btn-xs {{^autherror}}btn-default{{/autherror}}{{#autherror}}btn-danger{{/autherror}}"
- data-server-edit="{{serverid}}" {{disabled}} type="button">
+ data-server-edit="{{serverid}}" {{disabled}} {{perms.backend.edit.disabled}} type="button">
<span class="glyphicon glyphicon-cog"></span>
{{lang_edit}}
</button>
- <button class="btn btn-xs btn-primary server-check" {{disabled}} name="action" value="checkConnection"
- type="submit">
+ <button class="btn btn-xs btn-primary server-check" {{disabled}} {{perms.backend.check.disabled}}
+ name="action" value="checkConnection" type="submit">
<span class="glyphicon glyphicon-refresh"></span>
{{lang_checkConnection}}
</button>
</td>
<td align="center" nowrap>
- <button class="btn btn-xs btn-danger server-delete" type="submit" name="action" value="deleteServer">
+ <button class="btn btn-xs btn-danger server-delete" type="submit" name="action" value="deleteServer"
+ {{perms.backend.edit.disabled}}>
<span class="glyphicon glyphicon-trash"></span>
{{lang_delete}}
</button>
diff --git a/modules-available/locationinfo/templates/page-tabs.html b/modules-available/locationinfo/templates/page-tabs.html
index ed3f01fd..743297e7 100644
--- a/modules-available/locationinfo/templates/page-tabs.html
+++ b/modules-available/locationinfo/templates/page-tabs.html
@@ -1,6 +1,6 @@
<ul class="nav nav-tabs">
- <li class="{{class-}}"><a href="?do=locationinfo">{{lang_panels}}</a></li>
- <li class="{{class-locations}}"><a href="?do=locationinfo&amp;show=locations">{{lang_locationSettings}}</a></li>
- <li class="{{class-backends}}"><a href="?do=locationinfo&amp;show=backends">{{lang_backends}}</a></li>
+ <li class="{{class-panels}} {{perms.panel.list.disabled}}"><a href="?do=locationinfo&show=panels">{{lang_panels}}</a></li>
+ <li class="{{class-locations}} {{perms.location.disabled}}"><a href="?do=locationinfo&amp;show=locations">{{lang_locationSettings}}</a></li>
+ <li class="{{class-backends}} {{perms.backend.disabled}}"><a href="?do=locationinfo&amp;show=backends">{{lang_backends}}</a></li>
</ul>
<br> \ No newline at end of file