new: [acl] Check sighting deletion in ACLComponent

pull/8702/head
Jakub Onderka 2022-10-24 15:22:56 +02:00
parent 985c2a6fb6
commit 017c0a1cb6
5 changed files with 40 additions and 19 deletions

View File

@ -606,10 +606,10 @@ class ACLComponent extends Component
'add' => array('perm_sighting'),
'restSearch' => array('perm_sighting'),
'advanced' => array('perm_sighting'),
'delete' => array('perm_sighting'),
'delete' => ['AND' => ['perm_sighting', 'perm_modify_org']],
'index' => array('*'),
'listSightings' => array('*'),
'quickDelete' => array('perm_sighting'),
'quickDelete' => ['AND' => ['perm_sighting', 'perm_modify_org']],
'viewSightings' => array('*'),
'bulkSaveSightings' => array('OR' => array('perm_sync', 'perm_sighting')),
'filterSightingUuidsForPush' => ['perm_sync'],
@ -969,6 +969,28 @@ class ACLComponent extends Component
return $user['org_id'] == $tagCollection['TagCollection']['org_id'];
}
/**
* Only users that can modify organisation can delete sightings as sighting is not linked to user.
*
* @param array $user
* @param array $sighting
* @return bool
*/
public function canDeleteSighting(array $user, array $sighting)
{
if (!isset($sighting['Sighting'])) {
throw new InvalidArgumentException('Passed object does not contain a Sighting.');
}
// Site admin can delete any sighting
if ($user['Role']['perm_site_admin']) {
return true;
}
if (!$user['Role']['perm_modify_org']) {
return false;
}
return $sighting['Sighting']['org_id'] == $user['org_id'];
}
private function __checkLoggedActions($user, $controller, $action)
{
$loggedActions = array(

View File

@ -188,12 +188,8 @@ class SightingsController extends AppController
public function quickDelete($id, $rawId, $context)
{
if (!$this->userRole['perm_modify_org']) {
throw new MethodNotAllowedException('You are not authorised to remove sightings data as you don\'t have permission to modify your organisation\'s data.');
}
if (!$this->request->is('post')) {
$this->set('id', $id);
$sighting = $this->Sighting->find('first', array('conditions' => array('Sighting.id' => $id), 'recursive' => -1, 'fields' => array('Sighting.attribute_id')));
$this->set('rawId', $rawId);
$this->set('context', $context);
$this->render('ajax/quickDeleteConfirmationForm');
@ -205,7 +201,7 @@ class SightingsController extends AppController
if (empty($sighting)) {
return new CakeResponse(array('body' => json_encode(array('saved' => true, 'errors' => 'Invalid sighting.')), 'status' => 200, 'type' => 'json'));
}
if (!$this->_isSiteAdmin() && $sighting['Sighting']['org_id'] != $this->Auth->user('org_id')) {
if (!$this->ACL->canDeleteSighting($this->Auth->user(), $sighting)) {
return new CakeResponse(array('body' => json_encode(array('saved' => true, 'errors' => 'Invalid sighting.')), 'status' => 200, 'type' => 'json'));
}
$result = $this->Sighting->delete($id);
@ -221,9 +217,6 @@ class SightingsController extends AppController
// takes a sighting ID or UUID
public function delete($id)
{
if (!$this->userRole['perm_modify_org']) {
throw new MethodNotAllowedException('You are not authorised to remove sightings data as you don\'t have permission to modify your organisation\'s data.');
}
if (!$this->request->is('post')) {
throw new MethodNotAllowedException('This action can only be accessed via a post request.');
}
@ -235,7 +228,7 @@ class SightingsController extends AppController
if (empty($sighting)) {
throw new NotFoundException('Invalid sighting.');
}
if (!$this->_isSiteAdmin() && $sighting['Sighting']['org_id'] != $this->Auth->user('org_id')) {
if (!$this->ACL->canDeleteSighting($this->Auth->user(), $sighting)) {
throw new NotFoundException('Invalid sighting.');
}
$result = $this->Sighting->delete($sighting['Sighting']['id']);

View File

@ -73,4 +73,14 @@ class AclHelper extends Helper
$me = $this->_View->viewVars['me'];
return $this->ACL->canModifyTagCollection($me, $tagCollection);
}
/**
* @param array $sighting
* @return bool
*/
public function canDeleteSighting(array $sighting)
{
$me = $this->_View->viewVars['me'];
return $this->ACL->canDeleteSighting($me, $sighting);
}
}

View File

@ -30,13 +30,9 @@ $deleteSightingTitle = __('Delete sighting');
<td class="short"><?= h($item['Sighting']['event_id']) ?></td>
<td class="short"><?= h($item['Sighting']['attribute_id']) ?></td>
<td class="short action-links">
<?php
if ($isSiteAdmin || ($item['Sighting']['org_id'] == $me['org_id'] && $isAclAdd)):
?>
<span class="fa fa-trash useCursorPointer" title="<?= $deleteSightingTitle ?>" role="button" tabindex="0" aria-label="<?= $deleteSightingTitle ?>" onClick="quickDeleteSighting('<?= h($item['Sighting']['id']) ?>', '<?= h($rawId) ?>', '<?= h($context) ?>');"></span>
<?php
endif;
?>
<?php if ($this->Acl->canDeleteSighting($item)): ?>
<span class="fa fa-trash useCursorPointer" title="<?= $deleteSightingTitle ?>" role="button" tabindex="0" aria-label="<?= $deleteSightingTitle ?>" onclick="quickDeleteSighting('<?= h($item['Sighting']['id']) ?>', '<?= h($rawId) ?>', '<?= h($context) ?>');"></span>
<?php endif; ?>
</td>
</tr>
<?php

View File

@ -92,7 +92,7 @@ function deleteObject(type, action, id) {
}
function quickDeleteSighting(id, rawId, context) {
url = baseurl + "/sightings/quickDelete/" + id + "/" + rawId + "/" + context;
var url = baseurl + "/sightings/quickDelete/" + id + "/" + rawId + "/" + context;
$.get(url, openConfirmation).fail(xhrFailCallback)
}