diff options
author | Udo Walter | 2017-10-03 20:07:15 +0200 |
---|---|---|
committer | Udo Walter | 2017-10-03 20:07:15 +0200 |
commit | 3941f2482e26590e7f0f24147bc87740ab7f18af (patch) | |
tree | b782293185db8ea8847b335628fb709f2928b69f | |
parent | [internetaccess] implemented new permission system (diff) | |
download | slx-admin-3941f2482e26590e7f0f24147bc87740ab7f18af.tar.gz slx-admin-3941f2482e26590e7f0f24147bc87740ab7f18af.tar.xz slx-admin-3941f2482e26590e7f0f24147bc87740ab7f18af.zip |
[locations] implemented new permission system
-rw-r--r-- | modules-available/locations/inc/location.inc.php | 3 | ||||
-rw-r--r-- | modules-available/locations/page.inc.php | 102 | ||||
-rw-r--r-- | modules-available/locations/permissions/permissions.json | 9 | ||||
-rw-r--r-- | modules-available/locations/style.css | 13 | ||||
-rw-r--r-- | modules-available/locations/templates/location-subnets.html | 40 | ||||
-rw-r--r-- | modules-available/locations/templates/locations.html | 17 | ||||
-rw-r--r-- | modules-available/locations/templates/subnets.html | 10 | ||||
-rw-r--r-- | modules-available/permissionmanager/inc/permissionutil.inc.php | 2 |
8 files changed, 154 insertions, 42 deletions
diff --git a/modules-available/locations/inc/location.inc.php b/modules-available/locations/inc/location.inc.php index 8b2ef262..c2bf14ef 100644 --- a/modules-available/locations/inc/location.inc.php +++ b/modules-available/locations/inc/location.inc.php @@ -352,7 +352,8 @@ class Location */ public static function getSubnets() { - $res = Database::simpleQuery("SELECT startaddr, endaddr, locationid FROM subnet"); + $res = Database::simpleQuery("SELECT startaddr, endaddr, locationid FROM subnet WHERE locationid IN (:locations)", + array("locations" => User::getAllowedLocations("subnetlist.view"))); $subnets = array(); while ($row = $res->fetch(PDO::FETCH_ASSOC)) { settype($row['locationid'], 'int'); diff --git a/modules-available/locations/page.inc.php b/modules-available/locations/page.inc.php index 20af7b63..ed78a6c7 100644 --- a/modules-available/locations/page.inc.php +++ b/modules-available/locations/page.inc.php @@ -12,7 +12,7 @@ class Page_Locations extends Page protected function doPreprocess() { User::load(); - if (!User::hasPermission('superadmin')) { + if (!User::isLoggedIn()) { Message::addError('main.no-permission'); Util::redirect('?do=Main'); } @@ -47,6 +47,12 @@ class Page_Locations extends Page Message::addError('main.value-invalid', 'locationid', $loc); continue; } + + $oldLoc = Database::queryFirst("SELECT locationid FROM subnet WHERE subnetid = :subnetid", array("subnetid" => $subnetid))["locationid"]; + if (($loc == $oldLoc && !User::hasPermission("subnet.edit", $loc)) || + ($loc != $oldLoc && (!User::hasPermission("subnet.delete", $oldLoc) || !User::hasPermission("subnet.add", $loc)))) + continue; + $range = $this->rangeToLongVerbose($start, $end); if ($range === false) continue; @@ -57,7 +63,7 @@ class Page_Locations extends Page } AutoLocation::rebuildAll(); Message::addSuccess('subnets-updated', $count); - Util::redirect('?do=Locations'); + Util::redirect('?do=Locations&action=showsubnets'); } private function addLocations() @@ -75,6 +81,8 @@ class Page_Locations extends Page if (empty($name)) continue; $parent = isset($parents[$idx]) ? (int)$parents[$idx] : 0; + if (!User::hasPermission("location.add", $parent)) + continue; if ($parent !== 0) { $ok = false; foreach ($locs as $loc) { @@ -115,15 +123,25 @@ class Page_Locations extends Page $change = false; // Delete location? if ($locationId === $del) { + if (!User::hasPermission("location.delete", $locationId)) { + Message::addError('main.no-permission', 'locationid', $locationId); + Util::redirect('?do=Locations'); + } $this->deleteLocation($location); $change = true; } // Update subnets $change |= $this->updateLocationSubnets(); - // Insert subnets - $change |= $this->addNewLocationSubnets($location); - // Update location! - $change |= $this->updateLocationData($location); + + if (User::hasPermission("subnet.add", $locationId)) { + // Insert subnets + $change |= $this->addNewLocationSubnets($location); + } + if (User::hasPermission("location.edit", $locationId)) { + // Update location! + $change |= $this->updateLocationData($location); + } + if ($change) { // In case subnets or tree layout changed, recalc this AutoLocation::rebuildAll(); @@ -195,9 +213,12 @@ class Page_Locations extends Page private function updateLocationSubnets() { $change = false; + + $locationId = Request::post('locationid', false, 'integer'); + // Deletion first $dels = Request::post('deletesubnet', false); - if (is_array($dels)) { + if (is_array($dels) && User::hasPermission("subnet.delete", $locationId)) { $count = 0; $stmt = Database::prepare('DELETE FROM subnet WHERE subnetid = :id'); foreach ($dels as $key => $value) { @@ -212,6 +233,9 @@ class Page_Locations extends Page $change = true; } } + if (!User::hasPermission("subnet.edit", $locationId)) + return $change; + // Now actual updates $starts = Request::post('startaddr', false); $ends = Request::post('endaddr', false); @@ -291,15 +315,28 @@ class Page_Locations extends Page Util::redirect('?do=Locations&action=showlocations'); } if ($getAction === 'showsubnets') { - $res = Database::simpleQuery("SELECT subnetid, startaddr, endaddr, locationid FROM subnet"); + $res = Database::simpleQuery("SELECT subnetid, startaddr, endaddr, locationid FROM subnet + WHERE locationid IN (:locations)", + array("locations" => User::getAllowedLocations("location.view"))); $rows = array(); while ($row = $res->fetch(PDO::FETCH_ASSOC)) { $row['startaddr'] = long2ip($row['startaddr']); $row['endaddr'] = long2ip($row['endaddr']); $row['locations'] = Location::getLocations($row['locationid']); + + $allowedLocs = User::getAllowedLocations("subnet.add"); + foreach ($row['locations'] as &$loc) { + if (!(in_array($loc["locationid"], $allowedLocs) || $loc["locationid"] == $row['locationid'])) { + $loc["disabled"] = "disabled"; + } + } + + $row['editThisSubnetAllowed'] = User::hasPermission("subnet.edit", $row['locationid']); + $row['deleteThisSubnetAllowed'] = User::hasPermission("subnet.delete", $row['locationid']); $rows[] = $row; } - Render::addTemplate('subnets', array('list' => $rows)); + + Render::addTemplate('subnets', array('list' => $rows, 'editSubnetAllowed' => User::hasPermission("subnet.edit"))); } elseif ($getAction === 'showlocations') { $this->showLocationList(); } @@ -388,6 +425,32 @@ class Page_Locations extends Page } } } + + $allowedLocs = User::getAllowedLocations("location.view"); + $withParents = array(); + foreach ($allowedLocs as $loc) { + $withParents = array_merge($withParents, Location::getLocationRootChain($loc)); + } + + foreach ($locs as $key => $loc) { + if (!in_array($loc["locationid"], $withParents)) { + unset($locs[$key]); + } elseif (!in_array($loc["locationid"], $allowedLocs)) { + $id = $locs[$key]["locationid"]; + $name = $locs[$key]["locationname"]; + $depth = $locs[$key]["depth"]; + $locs[$key] = array("locationid" => $id, "locationname" => $name, "depth" => $depth, "linkClass" => "not-allowed"); + } + } + + $addAllowedLocs = User::getAllowedLocations("location.add"); + $addAllowedList = Location::getLocations(0, 0, True); + foreach ($addAllowedList as &$loc) { + if (!in_array($loc["locationid"], $addAllowedLocs)) { + $loc["disabled"] = "disabled"; + } + } + // Output Render::addTemplate('locations', array( 'list' => array_values($locs), @@ -400,6 +463,8 @@ class Page_Locations extends Page 'haveOverlapOther' => !empty($overlapOther), 'unassignedCount' => $unassigned, 'defaultConfig' => $defaultConfig, + 'addAllowed' => User::hasPermission("location.add"), + 'addAllowedList' => array_values($addAllowedList) )); } @@ -422,6 +487,11 @@ class Page_Locations extends Page private function ajaxShowLocation() { $locationId = Request::any('locationid', 0, 'integer'); + + if (!User::hasPermission("location.view", $locationId)) { + die('Permission denied'); + } + $loc = Database::queryFirst('SELECT locationid, parentlocationid, locationname FROM location WHERE locationid = :lid', array('lid' => $locationId)); if ($loc === false) { @@ -442,6 +512,14 @@ class Page_Locations extends Page 'roomplanner' => Module::get('roomplanner') !== false && Location::isLeaf($locationId), 'parents' => Location::getLocations($loc['parentlocationid'], $locationId, true) ); + + $allowedLocs = User::getAllowedLocations("location.edit"); + foreach ($data['parents'] as &$parent) { + if (!(in_array($parent["locationid"], $allowedLocs) || $parent["locationid"] == $loc['parentlocationid'])) { + $parent["disabled"] = "disabled"; + } + } + if (Module::get('dozmod') !== false) { $lectures = Database::queryFirst('SELECT Count(*) AS cnt FROM sat.lecture l ' . ' INNER JOIN sat.lecture_x_location ll ON (l.lectureid = ll.lectureid AND ll.locationid = :lid)', @@ -474,6 +552,12 @@ class Page_Locations extends Page $data['havebaseconfig'] = Module::get('baseconfig') !== false; $data['havesysconfig'] = Module::get('sysconfig') !== false; + $data['editAllowed'] = User::hasPermission("location.edit", $locationId); + $data['deleteAllowed'] = User::hasPermission("location.delete", $locationId); + $data['editSubnetAllowed'] = User::hasPermission("subnet.edit", $locationId); + $data['deleteSubnetAllowed'] = User::hasPermission("subnet.delete", $locationId); + $data['addSubnetAllowed'] = User::hasPermission("subnet.add", $locationId); + $data['saveButton'] = $data['editAllowed'] || $data['editSubnetAllowed'] || $data['deleteSubnetAllowed'] || $data['addSubnetAllowed']; // echo '<pre>'; // var_dump($data); diff --git a/modules-available/locations/permissions/permissions.json b/modules-available/locations/permissions/permissions.json new file mode 100644 index 00000000..db0ac5f6 --- /dev/null +++ b/modules-available/locations/permissions/permissions.json @@ -0,0 +1,9 @@ +{ + "location.view": "View locations.", + "location.edit": "Edit locations.", + "location.add": "Add locations.", + "location.delete": "Delete locations.", + "subnet.edit": "Edit subnets.", + "subnet.add": "Add subnets.", + "subnet.delete": "Delete subnets." +}
\ No newline at end of file diff --git a/modules-available/locations/style.css b/modules-available/locations/style.css index 86f9dfca..042ac4d1 100644 --- a/modules-available/locations/style.css +++ b/modules-available/locations/style.css @@ -1,3 +1,14 @@ table.locations tbody td:nth-of-type(even) { background-color: rgba(0, 0, 0, 0.025); -}
\ No newline at end of file +} + +.not-allowed { + pointer-events: none; + cursor: default; + color: inherit; +} + +.disabled { + pointer-events: none; + opacity: 0.6; +} diff --git a/modules-available/locations/templates/location-subnets.html b/modules-available/locations/templates/location-subnets.html index 9cfa5cc8..754616c6 100644 --- a/modules-available/locations/templates/location-subnets.html +++ b/modules-available/locations/templates/location-subnets.html @@ -8,24 +8,26 @@ <button type="submit" class="btn btn-primary">Save</button> </div> <div class="row"> - <div class="col-sm-5"> - <div class="input-group"> - <span class="input-group-addon slx-ga">{{lang_name}}</span> - <input class="form-control" type="text" name="locationname" value="{{locationname}}" pattern=".*\S.*"> + <div class="{{^editAllowed}}disabled{{/editAllowed}}"> + <div class="col-sm-5"> + <div class="input-group"> + <span class="input-group-addon slx-ga">{{lang_name}}</span> + <input class="form-control" type="text" name="locationname" value="{{locationname}}" pattern=".*\S.*"> + </div> </div> - </div> - <div class="col-sm-6"> - <div class="input-group"> - <span class="input-group-addon slx-ga2">{{lang_parentLocation}}</span> - <select class="form-control" name="parentlocationid"> - {{#parents}} - <option value="{{locationid}}" {{#selected}}selected="selected"{{/selected}}>{{locationpad}} {{locationname}}</option> - {{/parents}} - </select> + <div class="col-sm-6"> + <div class="input-group"> + <span class="input-group-addon slx-ga2">{{lang_parentLocation}}</span> + <select class="form-control" name="parentlocationid"> + {{#parents}} + <option {{disabled}} value="{{locationid}}" {{#selected}}selected="selected"{{/selected}}>{{locationpad}} {{locationname}}</option> + {{/parents}} + </select> + </div> </div> </div> <div class="col-sm-1 text-center"> - <button type="button" class="btn btn-sm btn-danger" data-toggle="modal" data-target="#deleteLocationModal{{locationid}}"><span class="glyphicon glyphicon-trash"></span></button> + <button {{^deleteAllowed}}disabled{{/deleteAllowed}} type="button" class="btn btn-sm btn-danger" data-toggle="modal" data-target="#deleteLocationModal{{locationid}}"><span class="glyphicon glyphicon-trash"></span></button> </div> </div> <br> @@ -41,11 +43,11 @@ {{#list}} <tr class="cidrmagic"> <td>{{subnetid}}</td> - <td><input class="form-control cidrstart" type="text" name="startaddr[{{subnetid}}]" value="{{startaddr}}" pattern="\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"></td> - <td><input class="form-control cidrend" type="text" name="endaddr[{{subnetid}}]" value="{{endaddr}}" pattern="\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"></td> + <td class="{{^editSubnetAllowed}}disabled{{/editSubnetAllowed}}"><input class="form-control cidrstart" type="text" name="startaddr[{{subnetid}}]" value="{{startaddr}}" pattern="\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"></td> + <td class="{{^editSubnetAllowed}}disabled{{/editSubnetAllowed}}"><input class="form-control cidrend" type="text" name="endaddr[{{subnetid}}]" value="{{endaddr}}" pattern="\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"></td> <td class="danger"> <div class="checkbox text-center" style="margin-left: 9px"> - <input type="checkbox" name="deletesubnet[{{subnetid}}]" value="on"> + <input {{^deleteSubnetAllowed}}disabled{{/deleteSubnetAllowed}} type="checkbox" name="deletesubnet[{{subnetid}}]" value="on"> <label class="text-left"></label> </div> </td> @@ -53,7 +55,7 @@ {{/list}} <tr id="loc-sub-{{locationid}}"> <td colspan="4"> - <button class="btn btn-success btn-sm pull-right" type="button" onclick="slxAddSubnetRow(this, {{locationid}})" title="{{lang_addNewSubnet}}"> + <button {{^addSubnetAllowed}}disabled{{/addSubnetAllowed}} class="btn btn-success btn-sm pull-right" type="button" onclick="slxAddSubnetRow(this, {{locationid}})" title="{{lang_addNewSubnet}}"> <span class="glyphicon glyphicon-plus"></span> {{lang_subnet}} </button> </td> @@ -86,7 +88,7 @@ </div> <div class="col-md-4 text-right"> - <button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}}</button> + <button {{^saveButton}}disabled{{/saveButton}} type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}}</button> </div> </div> diff --git a/modules-available/locations/templates/locations.html b/modules-available/locations/templates/locations.html index 451d8add..afbca3c6 100644 --- a/modules-available/locations/templates/locations.html +++ b/modules-available/locations/templates/locations.html @@ -24,9 +24,10 @@ <tr> <td> <div style="display:inline-block;width:{{depth}}em"></div> - <a href="#" onclick="slxOpenLocation(this, {{locationid}}); return false">{{locationname}} <b class="caret"></b></a> + <a href="#" class="{{linkClass}}" onclick="slxOpenLocation(this, {{locationid}}); return false">{{locationname}}{{^linkClass}} <b class="caret"></b>{{/linkClass}}</a> </td> <td class="text-nowrap" align="right"> + {{^linkClass}} {{#havestatistics}} {{clientCount}} <span class="text-muted"> @@ -35,13 +36,17 @@ </span> <a class="btn btn-default btn-xs" href="?do=Statistics&show=list&filters=location={{locationid}}"><span class="glyphicon glyphicon-eye-open"></span></a> {{/havestatistics}} + {{/linkClass}} </td> <td class="text-nowrap" align="right"> + {{^linkClass}} {{#havestatistics}} {{clientLoad}} {{/havestatistics}} + {{/linkClass}} </td> <td class="text-nowrap"> + {{^linkClass}} {{#havebaseconfig}} <div class="pull-right" style="z-index:-1"> <a class="btn btn-default btn-xs" href="?do=baseconfig&module=locations&locationid={{locationid}}"><span class="glyphicon glyphicon-edit"></span></a> @@ -50,8 +55,10 @@ {{lang_overrideCount}}: {{overriddenVars}}   {{/overriddenVars}} {{/havebaseconfig}} + {{/linkClass}} </td> <td class="text-nowrap"> + {{^linkClass}} {{#havesysconfig}} <div class="pull-right"> <a class="btn btn-default btn-xs" href="?do=sysconfig&locationid={{locationid}}"><span class="glyphicon glyphicon-edit"></span></a> @@ -60,6 +67,7 @@ {{configName}}   </span> {{/havesysconfig}} + {{/linkClass}} </td> </tr> {{/list}} @@ -90,12 +98,10 @@ <button id="saveLocationRows" type="submit" class="btn btn-primary" style="display: none"> <span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}} </button> - <button class="btn btn-success" type="button" onclick="slxAddLocationRow()"> + <button {{^addAllowed}}disabled{{/addAllowed}} class="btn btn-success" type="button" onclick="slxAddLocationRow()"> <span class="glyphicon glyphicon-plus"></span> {{lang_location}} </button> - </td> - </tr> </table> </form> @@ -122,8 +128,7 @@ function slxAddLocationRow() { tr.before('<tr id="row' + slxAddCounter + '">\ <td><input class="form-control" type="text" name="newlocation[' + slxAddCounter + ']" placeholder="{{lang_locationName}}" pattern=".*\\S.*"></td>\ <td><select class="form-control" name="newparent[' + slxAddCounter + ']">\ - <option value="0">{{lang_noParent}}</option>\ - {{#list}}<option value="{{locationid}}">{{locationpad}} {{locationname}}</option>{{/list}}\ + {{#addAllowedList}}<option {{disabled}} value="{{locationid}}">{{locationpad}} {{locationname}}</option>{{/addAllowedList}}\ </select></td>\ <td class="text-center"><button class="btn btn-default btn-sm" type="button" onclick="removeNewLocationRow(' + slxAddCounter + ')"><span class="glyphicon glyphicon-remove"></span></button></td>\ </tr>'); diff --git a/modules-available/locations/templates/subnets.html b/modules-available/locations/templates/subnets.html index 4c96cc4d..0a1eca21 100644 --- a/modules-available/locations/templates/subnets.html +++ b/modules-available/locations/templates/subnets.html @@ -17,12 +17,12 @@ {{#list}} <tr class="cidrmagic"> <td>{{subnetid}}</td> - <td><input class="form-control cidrstart" type="text" name="startaddr[{{subnetid}}]" value="{{startaddr}}"></td> - <td><input class="form-control cidrend" type="text" name="endaddr[{{subnetid}}]" value="{{endaddr}}"></td> - <td> + <td class="{{^editThisSubnetAllowed}}disabled{{/editThisSubnetAllowed}}"><input class="form-control cidrstart" type="text" name="startaddr[{{subnetid}}]" value="{{startaddr}}"></td> + <td class="{{^editThisSubnetAllowed}}disabled{{/editThisSubnetAllowed}}"><input class="form-control cidrend" type="text" name="endaddr[{{subnetid}}]" value="{{endaddr}}"></td> + <td class="{{^deleteThisSubnetAllowed}}disabled{{/deleteThisSubnetAllowed}}"> <select class="form-control" name="location[{{subnetid}}]"> {{#locations}} - <option value="{{locationid}}" {{#selected}}selected="selected"{{/selected}}>{{locationpad}} {{locationname}}</option> + <option {{disabled}} value="{{locationid}}" {{#selected}}selected="selected"{{/selected}}>{{locationpad}} {{locationname}}</option> {{/locations}} </select> </td> @@ -30,7 +30,7 @@ {{/list}} </table> <div class="text-right" style="margin-bottom: 20px"> - <button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}}</button> + <button {{^editSubnetAllowed}}disabled{{/editSubnetAllowed}} type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}}</button> </div> </form> </div> diff --git a/modules-available/permissionmanager/inc/permissionutil.inc.php b/modules-available/permissionmanager/inc/permissionutil.inc.php index df877520..5c3eef58 100644 --- a/modules-available/permissionmanager/inc/permissionutil.inc.php +++ b/modules-available/permissionmanager/inc/permissionutil.inc.php @@ -45,7 +45,7 @@ class PermissionUtil } $allowedLocations = array_keys($allowedLocations); $locations = Location::getTree(); - if (count($allowedLocations) == 1 && $allowedLocations[0] == "0") { + if (in_array("0", $allowedLocations)) { $allowedLocations = array_map("intval", Location::extractIds($locations)); } else { $allowedLocations = self::getSublocations($locations, $allowedLocations); |