chg: [tags:org/individual] Relaxed ACL on tagging

- Before only `site_admin` could add tags.
- Now `org_admins` can add tags for their orgs and individuals
- Regular users can self manage their own individual tag
refacto/CRUDComponent
Sami Mokaddem 2023-02-24 11:17:55 +01:00
parent cbdf64a784
commit af8f1e9e74
No known key found for this signature in database
GPG Key ID: 164C473F627A06FA
5 changed files with 48 additions and 24 deletions

View File

@ -90,8 +90,8 @@ class ACLComponent extends Component
'edit' => ['perm_admin', 'perm_org_admin'], 'edit' => ['perm_admin', 'perm_org_admin'],
'filtering' => ['*'], 'filtering' => ['*'],
'index' => ['*'], 'index' => ['*'],
'tag' => ['perm_tagger'], 'tag' => ['*'],
'untag' => ['perm_tagger'], 'untag' => ['*'],
'view' => ['*'], 'view' => ['*'],
'viewTags' => ['*'] 'viewTags' => ['*']
], ],
@ -152,8 +152,8 @@ class ACLComponent extends Component
'edit' => ['perm_admin'], 'edit' => ['perm_admin'],
'filtering' => ['*'], 'filtering' => ['*'],
'index' => ['*'], 'index' => ['*'],
'tag' => ['perm_tagger'], 'tag' => ['perm_org_admin'],
'untag' => ['perm_tagger'], 'untag' => ['perm_org_admin'],
'view' => ['*'], 'view' => ['*'],
'viewTags' => ['*'] 'viewTags' => ['*']
], ],

View File

@ -68,25 +68,15 @@ class IndividualsController extends AppController
if (!empty($responsePayload)) { if (!empty($responsePayload)) {
return $responsePayload; return $responsePayload;
} }
$this->set('canEdit', $this->canEdit($id));
} }
public function edit($id) public function edit($id)
{ {
$currentUser = $this->ACL->getUser(); if (!$this->canEdit($id)) {
if (!$currentUser['role']['perm_admin']) { throw new MethodNotAllowedException(__('You cannot modify that individual.'));
$validIndividuals = $this->Individuals->getValidIndividualsToEdit($currentUser);
if (!in_array($id, $validIndividuals)) {
throw new MethodNotAllowedException(__('You cannot modify that individual.'));
}
} }
$currentUser = $this->ACL->getUser(); $currentUser = $this->ACL->getUser();
$validIndividualIds = [];
if (!$currentUser['role']['perm_admin']) {
$validIndividualIds = $this->Individuals->getValidIndividualsToEdit($currentUser);
if (!in_array($id, $validIndividualIds)) {
throw new NotFoundException(__('Invalid individual.'));
}
}
$this->CRUD->edit($id, [ $this->CRUD->edit($id, [
'beforeSave' => function($data) use ($currentUser) { 'beforeSave' => function($data) use ($currentUser) {
if ($currentUser['role']['perm_admin'] && isset($data['uuid'])) { if ($currentUser['role']['perm_admin'] && isset($data['uuid'])) {
@ -113,6 +103,9 @@ class IndividualsController extends AppController
public function tag($id) public function tag($id)
{ {
if (!$this->canEdit($id)) {
throw new MethodNotAllowedException(__('You cannot tag that individual.'));
}
$this->CRUD->tag($id); $this->CRUD->tag($id);
$responsePayload = $this->CRUD->getResponsePayload(); $responsePayload = $this->CRUD->getResponsePayload();
if (!empty($responsePayload)) { if (!empty($responsePayload)) {
@ -122,6 +115,9 @@ class IndividualsController extends AppController
public function untag($id) public function untag($id)
{ {
if (!$this->canEdit($id)) {
throw new MethodNotAllowedException(__('You cannot untag that individual.'));
}
$this->CRUD->untag($id); $this->CRUD->untag($id);
$responsePayload = $this->CRUD->getResponsePayload(); $responsePayload = $this->CRUD->getResponsePayload();
if (!empty($responsePayload)) { if (!empty($responsePayload)) {
@ -137,4 +133,17 @@ class IndividualsController extends AppController
return $responsePayload; return $responsePayload;
} }
} }
public function canEdit($indId): bool
{
$currentUser = $this->ACL->getUser();
if ($currentUser['role']['perm_admin']) {
return true;
}
$validIndividuals = $this->Individuals->getValidIndividualsToEdit($currentUser);
if (in_array($indId, $validIndividuals)) {
return true;
}
return false;
}
} }

View File

@ -101,7 +101,6 @@ class OrganisationsController extends AppController
if (!empty($responsePayload)) { if (!empty($responsePayload)) {
return $responsePayload; return $responsePayload;
} }
$this->set('metaGroup', 'ContactDB');
} }
public function view($id) public function view($id)
@ -111,16 +110,12 @@ class OrganisationsController extends AppController
if (!empty($responsePayload)) { if (!empty($responsePayload)) {
return $responsePayload; return $responsePayload;
} }
$this->set('metaGroup', 'ContactDB'); $this->set('canEdit', $this->canEdit($id));
} }
public function edit($id) public function edit($id)
{ {
$currentUser = $this->ACL->getUser(); if (!$this->canEdit($id)) {
if (
!($currentUser['organisation']['id'] == $id && $currentUser['role']['perm_org_admin']) &&
!$currentUser['role']['perm_admin']
) {
throw new MethodNotAllowedException(__('You cannot modify that organisation.')); throw new MethodNotAllowedException(__('You cannot modify that organisation.'));
} }
$this->CRUD->edit($id); $this->CRUD->edit($id);
@ -144,6 +139,9 @@ class OrganisationsController extends AppController
public function tag($id) public function tag($id)
{ {
if (!$this->canEdit($id)) {
throw new MethodNotAllowedException(__('You cannot tag that organisation.'));
}
$this->CRUD->tag($id); $this->CRUD->tag($id);
$responsePayload = $this->CRUD->getResponsePayload(); $responsePayload = $this->CRUD->getResponsePayload();
if (!empty($responsePayload)) { if (!empty($responsePayload)) {
@ -153,6 +151,9 @@ class OrganisationsController extends AppController
public function untag($id) public function untag($id)
{ {
if (!$this->canEdit($id)) {
throw new MethodNotAllowedException(__('You cannot untag that organisation.'));
}
$this->CRUD->untag($id); $this->CRUD->untag($id);
$responsePayload = $this->CRUD->getResponsePayload(); $responsePayload = $this->CRUD->getResponsePayload();
if (!empty($responsePayload)) { if (!empty($responsePayload)) {
@ -168,4 +169,16 @@ class OrganisationsController extends AppController
return $responsePayload; return $responsePayload;
} }
} }
public function canEdit($orgId): bool
{
$currentUser = $this->ACL->getUser();
if ($currentUser['role']['perm_admin']) {
return true;
}
if ($currentUser['role']['perm_org_admin'] && $currentUser['organisation']['id'] == $orgId) {
return true;
}
return false;
}
} }

View File

@ -31,6 +31,7 @@ echo $this->element(
[ [
'key' => __('Tags'), 'key' => __('Tags'),
'type' => 'tags', 'type' => 'tags',
'editable' => $canEdit,
], ],
[ [
'key' => __('Alignments'), 'key' => __('Alignments'),

View File

@ -40,6 +40,7 @@ echo $this->element(
[ [
'key' => __('Tags'), 'key' => __('Tags'),
'type' => 'tags', 'type' => 'tags',
'editable' => $canEdit,
], ],
[ [
'key' => __('Alignments'), 'key' => __('Alignments'),