Introduce a Create permission for Monitors, so that a given user may Edit existing monitors, but not create new ones.

This commit is contained in:
Isaac Connor
2024-01-02 12:18:09 -05:00
parent bb4faada54
commit 2d49e93405
11 changed files with 62 additions and 56 deletions

View File

@@ -776,7 +776,7 @@ CREATE TABLE `Users` (
`Stream` enum('None','View') NOT NULL default 'None',
`Events` enum('None','View','Edit') NOT NULL default 'None',
`Control` enum('None','View','Edit') NOT NULL default 'None',
`Monitors` enum('None','View','Edit') NOT NULL default 'None',
`Monitors` enum('None','View','Edit','Create') NOT NULL default 'None',
`Groups` enum('None','View','Edit') NOT NULL default 'None',
`Devices` enum('None','View','Edit') NOT NULL default 'None',
`Snapshots` enum('None','View','Edit') NOT NULL default 'None',

View File

@@ -1 +1,4 @@
UPDATE Monitors SET ControlAddress='' WHERE ControlAddress='user:port@ip';
ALTER TABLE Users MODIFY `Monitors` enum('None','View','Edit','Create') NOT NULL default 'None';
UPDATE Users SET Monitors='Create' WHERE Monitors='Edit';

View File

@@ -18,7 +18,7 @@
%global zmtargetdistro %{?rhel:el%{rhel}}%{!?rhel:fc%{fedora}}
Name: zoneminder
Version: 1.37.47
Version: 1.37.48
Release: 2%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons

View File

@@ -1 +1 @@
1.37.47
1.37.48

View File

@@ -20,7 +20,7 @@
// Monitor edit actions, monitor id derived, require edit permissions for that monitor
if (!canEdit('Monitors')) {
ZM\Warning('Monitor actions require Monitors Permissions');
ZM\Warning('Monitor actions require Monitors Edit Permissions');
return;
}
@@ -42,6 +42,10 @@ if ($action == 'save') {
if (!$x10Monitor) $x10Monitor = array();
}
} else {
if (!canCreate('Monitors')) {
ZM\Warning('Monitor actions require Monitors Create Permissions');
return;
}
if ($user->unviewableMonitorIds()) {
ZM\Warning('You are restricted to certain monitors so cannot add a new one.');
return;

View File

@@ -338,7 +338,13 @@ function editableMonitor($mid) {
function canEdit($area, $mid=false) {
global $user;
return ( $user && ($user->$area() == 'Edit') && ( !$mid || visibleMonitor($mid) ));
return ( $user && ($user->$area() == 'Edit' or $user->$area() == 'Create') && ( !$mid || visibleMonitor($mid) ));
}
function canCreate($area) {
global $user;
return ( $user && ($user->$area() == 'Create') );
}
function userFromSession() {

View File

@@ -22,6 +22,7 @@ if (!canEdit('Monitors')) {
$view = 'error';
return;
}
$canCreateMonitors = canCreate('Monitors');
$focusWindow = true;
@@ -50,6 +51,9 @@ getBodyTopHTML();
value="<?php echo isset($_COOKIE['addMonitorsprobe_password']) ? $_COOKIE['addMonitorsprobe_password'] : '' ?>"/>
</div>
<div id="contentButtons">
<?php
if ($canCreateMonitors) {
?>
<button type="button" name="addBtn" data-on-click-this="addMonitor" title="<?php echo translate('Add New Monitor') ?>">
<i class="material-icons md-18">add_circle</i>
<span class="text"><?php echo translate('AddNewMonitor') ?></span>
@@ -58,6 +62,9 @@ getBodyTopHTML();
<i class="material-icons md-18">upload</i>
<span class="text"><?php echo translate('Import CSV') ?></span>
</button>
<?php
}
?>
</div>
</div><!--toolbar-->

View File

@@ -18,6 +18,9 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
$canEditMonitors = canEdit('Monitors');
$canCreateMonitors = canCreate('Monitors');
$eventCounts = array(
'Total'=> array(
'title' => translate('Events'),
@@ -179,18 +182,24 @@ echo $navbar ?>
</div>
<div class="middleButtons">
<?php
if ($canEditMonitors) {
?>
<button type="button" id="scanBtn" title="<?php echo translate('Network Scan') ?>" data-on-click="scanNetwork">
<i class="material-icons">wifi</i>
<span class="text"><?php echo translate('Scan Network') ?></span>
</button>
<?php
}
?>
<button type="button" name="addBtn" data-on-click="addMonitor"
<?php echo canEdit('Monitors') ? '' : ' disabled="disabled" title="'.translate('AddMonitorDisabled').'"' ?>
<?php echo $canCreateMonitors ? '' : ' disabled="disabled" title="'.translate('AddMonitorDisabled').'"' ?>
>
<i class="material-icons">add_circle</i>
<span class="text">&nbsp;<?php echo translate('AddNewMonitor') ?></span>
</button>
<button type="button" name="cloneBtn" data-on-click-this="cloneMonitor"
<?php echo canEdit('Monitors') ? '' : ' disabled="disabled"' ?>
<?php echo $canCreateMonitors ? '' : ' disabled="disabled"' ?>
style="display:none;">
<i class="material-icons">content_copy</i>
<!--content_copy used instead of file_copy as there is a bug in material-icons -->
@@ -226,7 +235,7 @@ ob_start();
<table class="table table-striped table-hover table-condensed consoleTable">
<thead class="thead-highlight">
<tr>
<?php if ( canEdit('Monitors') ) { ?>
<?php if ($canEditMonitors) { ?>
<th class="colMark"><input type="checkbox" name="toggleCheck" value="1" data-checkbox-name="markMids[]" data-on-click-this="updateFormCheckboxesByName"/></th>
<?php } ?>
<?php if ( ZM_WEB_ID_ON_CONSOLE ) { ?>
@@ -324,10 +333,10 @@ for ($monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1) {
$scale = max(reScale(SCALE_BASE, $monitor['DefaultScale'], ZM_WEB_DEFAULT_SCALE), SCALE_BASE);
$stream_available = canView('Stream') and $monitor['Type']=='WebSite' or ($monitor['CaptureFPS'] && $monitor['Capturing'] != 'None');
if ( canEdit('Monitors') ) {
if ($canEditMonitors) {
?>
<td class="colMark">
<input type="checkbox" name="markMids[]" value="<?php echo $monitor['Id'] ?>" data-on-click-this="setButtonStates"<?php if ( !canEdit( 'Monitors' ) ) { ?> disabled="disabled"<?php } ?>/>
<input type="checkbox" name="markMids[]" value="<?php echo $monitor['Id'] ?>" data-on-click-this="setButtonStates"/>
</td>
<?php
}
@@ -423,7 +432,7 @@ for ($monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1) {
$Server = isset($ServersById[$monitor['ServerId']]) ? $ServersById[$monitor['ServerId']] : new ZM\Server($monitor['ServerId']);
echo '<td class="colServer">'.validHtmlStr($Server->Name()).'</td>'.PHP_EOL;
}
echo '<td class="colSource">'. makeLink( '?view=monitor&amp;mid='.$monitor['Id'], '<span class="'.$source_class.'">'.validHtmlStr($Monitor->Source()).'</span>', canEdit('Monitors') ).'</td>';
echo '<td class="colSource">'. makeLink( '?view=monitor&amp;mid='.$monitor['Id'], '<span class="'.$source_class.'">'.validHtmlStr($Monitor->Source()).'</span>', $canEditMonitors).'</td>';
if ($show_storage_areas) {
echo '<td class="colStorage">'.
(isset($StorageById[$monitor['StorageId']]) ? validHtmlStr($StorageById[$monitor['StorageId']]->Name()) : ($monitor['StorageId']?'<span class="error">Deleted '.$monitor['StorageId'].'</span>' : '')).'</td>'.PHP_EOL;
@@ -442,7 +451,7 @@ for ($monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1) {
</tbody>
<tfoot>
<tr>
<?php if ( canEdit('Monitors') ) { ?>
<?php if ($canEditMonitors) { ?>
<td class="colMark"></td>
<?php } ?>
<?php if ( ZM_WEB_ID_ON_CONSOLE ) { ?>

View File

@@ -1,6 +1,6 @@
var ProbeResults = {};
var table = null;
//
function ajaxRequest(params) {
return probe(params);
}
@@ -29,15 +29,13 @@ function probe(params) {
alert(data.message);
return;
}
// parses into ProbeResults
//getProbeResponse(data);
if (data.Streams && data.Streams.length) {
for ( i in data.Streams ) {
const stream = data.Streams[i];
if (stream.Monitor) {
stream.buttons = '<input type="button" value="Edit" data-on-click-this="addMonitor" data-url="'+stream.url+'"/>';
} else {
} else if (user.Monitors == 'Create') {
stream.buttons = '<input type="button" value="Add" data-on-click-this="addMonitor" data-url="'+stream.url+'"/>';
}
if (ZM_WEB_LIST_THUMBS && stream.camera.mjpegstream) {
@@ -50,7 +48,6 @@ function probe(params) {
ProbeResults[stream.url] = stream;
} // end for each Stream
//const rows = processRows(ProbeResults);
const rows = data.Streams;
// rearrange the result into what bootstrap-table expects
params.success({total: rows.length, totalNotFiltered: rows.length, rows: rows});
@@ -64,36 +61,6 @@ function probe(params) {
});
}
function processRows(rows) {
$j.each(rows, function(ndx, row) {
var eid = row.Id;
var archived = row.Archived == yesString ? archivedString : '';
var emailed = row.Emailed == yesString ? emailedString : '';
row.Id = '<a href="?view=event&amp;eid=' + eid + filterQuery + sortQuery + '&amp;page=1">' + eid + '</a>';
row.Name = '<a href="?view=event&amp;eid=' + eid + filterQuery + sortQuery + '&amp;page=1">' + row.Name + '</a>' +
'<br/><div class="small text-muted">' + archived + emailed + '</div>';
if ( canEdit.Monitors ) row.Monitor = '<a href="?view=event&amp;eid=' + eid + '">' + row.Monitor + '</a>';
if ( canEdit.Events ) row.Cause = '<a href="#" title="' + row.Notes + '" class="eDetailLink" data-eid="' + eid + '">' + row.Cause + '</a>';
if ( row.Notes.indexOf('detected:') >= 0 ) {
row.Cause = row.Cause + '<a href="#" class="objDetectLink" data-eid=' +eid+ '><div class="small text-muted"><u>' + row.Notes + '</u></div></div></a>';
} else if ( row.Notes != 'Forced Web: ' ) {
row.Cause = row.Cause + '<br/><div class="small text-muted">' + row.Notes + '</div>';
}
row.Frames = '<a href="?view=frames&amp;eid=' + eid + '">' + row.Frames + '</a>';
row.AlarmFrames = '<a href="?view=frames&amp;eid=' + eid + '">' + row.AlarmFrames + '</a>';
row.MaxScore = '<a href="?view=frame&amp;eid=' + eid + '&amp;fid=0">' + row.MaxScore + '</a>';
const date = new Date(0); // Have to init it fresh. setSeconds seems to add time, not set it.
date.setSeconds(row.Length);
row.Length = date.toISOString().substr(11, 8);
if ( WEB_LIST_THUMBS ) row.Thumbnail = '<a href="?view=event&amp;eid=' + eid + filterQuery + sortQuery + '&amp;page=1">' + row.imgHtml + '</a>';
});
return rows;
}
function onvif_probe() {
}

View File

@@ -36,14 +36,21 @@ function scanNetwork(element) {
window.location.assign('?view=add_monitors');
}
function addMonitor(element) {
window.location.assign('?view=monitor');
if (user.Monitors == 'Create')
window.location.assign('?view=monitor');
else
alert('Need create monitors privilege');
}
function cloneMonitor(element) {
if (user.Monitors != 'Create') {
alert('Need create monitors privilege');
return;
}
var form = element.form;
var monitorId=-1;
var monitorId = -1;
// get the value of the first checkbox
for ( var i = 0; i < form.elements.length; i++ ) {
for ( var i=0, len=form.elements.length; i < len; i++ ) {
if (
form.elements[i].type == "checkbox" &&
form.elements[i].name == "markMids[]" &&
@@ -55,6 +62,8 @@ function cloneMonitor(element) {
} // end foreach element
if ( monitorId != -1 ) {
window.location.assign('?view=monitor&dupId='+monitorId);
} else {
alert('Please select a monitor to clone');
}
}
@@ -81,8 +90,8 @@ function editMonitor( element ) {
}
function deleteMonitor( element ) {
if ( confirm( 'Warning, deleting a monitor also deletes all events and database entries associated with it.\nAre you sure you wish to delete?' ) ) {
var form = element.form;
if (confirm('Deleting a monitor only marks it as deleted. Events will age out. If you want them to be immediately removed, please delete them first.\nAre you sure you wish to delete?')) {
const form = element.form;
form.elements['action'].value = 'delete';
form.submit();
}
@@ -191,19 +200,19 @@ function initPage() {
.fail(logAjaxFail);
}
// Makes table sortable
// Setup the thumbnail video animation
if (!isMobile()) initThumbAnimation();
$j('.functionLnk').click(manageFunctionModal);
// Makes table sortable
$j('#consoleTableBody').sortable({
disabled: true,
update: applySort,
axis: 'Y'} );
} // end function initPage
//
function sortMonitors(button) {
if (button.classList.contains('btn-success')) {
$j( "#consoleTableBody" ).sortable('disable');
@@ -221,4 +230,4 @@ function applySort(event, ui) {
.fail(logAjaxFail);
} // end function applySort(event,ui)
$j(document).ready(initPage );
$j(document).ready(initPage);

View File

@@ -41,6 +41,7 @@ if (isset($_REQUEST['uid']) and $_REQUEST['uid']) {
$yesno = array( 0=>translate('No'), 1=>translate('Yes') );
$nv = array( 'None'=>translate('None'), 'View'=>translate('View') );
$nve = array( 'None'=>translate('None'), 'View'=>translate('View'), 'Edit'=>translate('Edit') );
$nvec = array( 'None'=>translate('None'), 'View'=>translate('View'), 'Edit'=>translate('Edit'), 'Create'=>translate('Create') );
$inve = array( 'Inherit'=>translate('Inherit'),'None'=>translate('None'), 'View'=>translate('View'), 'Edit'=>translate('Edit') );
$bandwidths = array_merge( array( ''=>'' ), $bandwidth_options );
$langs = array_merge( array( ''=>'' ), getLanguages() );
@@ -182,7 +183,7 @@ if (canEdit('System')) {
</tr>
<tr class="Monitors">
<th scope="row"><?php echo translate('Monitors') ?></th>
<td><?php echo htmlSelect('user[Monitors]', $nve, $User->Monitors(), ['id'=>'user[Monitors]', 'data-on-change'=>'updateEffectivePermissions']) ?></td>
<td><?php echo htmlSelect('user[Monitors]', $nvec, $User->Monitors(), ['id'=>'user[Monitors]', 'data-on-change'=>'updateEffectivePermissions']) ?></td>
</tr>
<tr class="Groups">
<th scope="row"><?php echo translate('Groups') ?></th>