From 932a28288d8cf5e4baf6108adafd7093df569133 Mon Sep 17 00:00:00 2001 From: iglocska Date: Fri, 21 Jan 2022 13:41:29 +0100 Subject: [PATCH 1/6] new: [CRUD] added some new useful features - afterFind for the edit functions to make last minute decisions on the modification after already having loaded the data to be modified - moved the field restrictions to be able to pass it to the view - try/catch for bulk deletions. A single failure in the beforeSave call will no longer block the entire saving process --- src/Controller/Component/CRUDComponent.php | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Controller/Component/CRUDComponent.php b/src/Controller/Component/CRUDComponent.php index d1c78fc..47dc5bf 100644 --- a/src/Controller/Component/CRUDComponent.php +++ b/src/Controller/Component/CRUDComponent.php @@ -157,9 +157,6 @@ class CRUDComponent extends Component { $this->getMetaTemplates(); $data = $this->Table->newEmptyEntity(); - if (!empty($params['fields'])) { - $this->Controller->set('fields', $params['fields']); - } if ($this->request->is('post')) { $patchEntityParams = [ 'associated' => [], @@ -223,6 +220,9 @@ class CRUDComponent extends Component } } } + if (!empty($params['fields'])) { + $this->Controller->set('fields', $params['fields']); + } $this->Controller->entity = $data; $this->Controller->set('entity', $data); } @@ -295,21 +295,18 @@ class CRUDComponent extends Component $data->where($params['conditions']); } $data = $data->first(); + if (isset($params['afterFind'])) { + $data = $params['afterFind']($data, $params); + } if (empty($data)) { throw new NotFoundException(__('Invalid {0}.', $this->ObjectAlias)); } $data = $this->getMetaFields($id, $data); - if (!empty($params['fields'])) { - $this->Controller->set('fields', $params['fields']); - } if ($this->request->is(['post', 'put'])) { $patchEntityParams = [ 'associated' => [] ]; $input = $this->__massageInput($params); - if (!empty($params['fields'])) { - $patchEntityParams['fields'] = $params['fields']; - } $data = $this->Table->patchEntity($data, $input, $patchEntityParams); if (isset($params['beforeSave'])) { $data = $params['beforeSave']($data); @@ -352,6 +349,9 @@ class CRUDComponent extends Component } } } + if (!empty($params['fields'])) { + $this->Controller->set('fields', $params['fields']); + } $this->Controller->entity = $data; $this->Controller->set('entity', $data); } @@ -469,7 +469,11 @@ class CRUDComponent extends Component } $data = $data->first(); if (isset($params['beforeSave'])) { - $data = $params['beforeSave']($data); + try { + $data = $params['beforeSave']($data); + } catch (Exception $e) { + $data = false; + } } if (!empty($data)) { $success = $this->Table->delete($data); From b556f7f22a860d5050481417634c6867668d51f9 Mon Sep 17 00:00:00 2001 From: Andras Iklody Date: Fri, 21 Jan 2022 14:39:43 +0100 Subject: [PATCH 2/6] Update VERSION.json --- src/VERSION.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VERSION.json b/src/VERSION.json index 5ddd625..f790db8 100644 --- a/src/VERSION.json +++ b/src/VERSION.json @@ -1,4 +1,4 @@ { - "version": "0.1", + "version": "1.3", "application": "Cerebrate" } From 57e2c753523ec792bbdd8974c58a5d3bf0969bf8 Mon Sep 17 00:00:00 2001 From: iglocska Date: Tue, 25 Jan 2022 11:34:22 +0100 Subject: [PATCH 3/6] fix: [users] role based action filtering added - to avoid annoying clickable, but blocked actions for og admins --- src/Controller/UsersController.php | 57 ++++++++++++++++++++++++++---- templates/Users/index.php | 40 +++++++++++++++++++-- 2 files changed, 88 insertions(+), 9 deletions(-) diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 9ffb2fe..6fa1067 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -33,16 +33,28 @@ class UsersController extends AppController if (!empty($responsePayload)) { return $responsePayload; } + $this->set( + 'validRoles', + $this->Users->Roles->find('list')->select(['id', 'name'])->order(['name' => 'asc'])->where(['perm_admin' => 0])->all()->toArray() + ); $this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate'); } public function add() { $currentUser = $this->ACL->getUser(); + $validRoles = []; + if (!$currentUser['role']['perm_admin']) { + $validRoles = $this->Users->Roles->find('list')->order(['name' => 'asc'])->all()->toArray(); + } + $this->CRUD->add([ - 'beforeSave' => function($data) use ($currentUser) { + 'beforeSave' => function($data) use ($currentUser, $validRoles) { if (!$currentUser['role']['perm_admin']) { $data['organisation_id'] = $currentUser['organisation_id']; + if (!in_array($data['role_id'], array_keys($validRoles))) { + throw new MethodNotAllowedException(__('You do not have permission to assign that role.')); + } } $this->Users->enrollUserRouter($data); return $data; @@ -65,9 +77,7 @@ class UsersController extends AppController $org_conditions = ['id' => $currentUser['organisation_id']]; } $dropdownData = [ - 'role' => $this->Users->Roles->find('list', [ - 'sort' => ['name' => 'asc'] - ]), + 'role' => $validRoles, 'individual' => $this->Users->Individuals->find('list', [ 'sort' => ['email' => 'asc'] ]), @@ -98,6 +108,10 @@ class UsersController extends AppController public function edit($id = false) { $currentUser = $this->ACL->getUser(); + $validRoles = []; + if (!$currentUser['role']['perm_admin']) { + $validRoles = $this->Users->Roles->find('list')->select(['id', 'name'])->order(['name' => 'asc'])->where(['perm_admin' => 0])->all()->toArray(); + } if (empty($id)) { $id = $currentUser['id']; } else { @@ -128,6 +142,20 @@ class UsersController extends AppController $params['fields'][] = 'role_id'; $params['fields'][] = 'organisation_id'; $params['fields'][] = 'disabled'; + } else if (!empty($this->ACL->getUser()['role']['perm_org_admin'])) { + $params['fields'][] = 'username'; + $params['fields'][] = 'role_id'; + $params['fields'][] = 'disabled'; + if (!$currentUser['role']['perm_admin']) { + $params['afterFind'] = function ($data, &$params) use ($currentUser, $validRoles) { + if (!$currentUser['role']['perm_admin'] && $currentUser['role']['perm_org_admin']) { + if (!in_array($data['role_id'], array_keys($validRoles))) { + throw new MethodNotAllowedException(__('You cannot edit the given privileged user.')); + } + } + return $data; + }; + } } $this->CRUD->edit($id, $params); $responsePayload = $this->CRUD->getResponsePayload(); @@ -135,9 +163,7 @@ class UsersController extends AppController return $responsePayload; } $dropdownData = [ - 'role' => $this->Users->Roles->find('list', [ - 'sort' => ['name' => 'asc'] - ]), + 'role' => $validRoles, 'individual' => $this->Users->Individuals->find('list', [ 'sort' => ['email' => 'asc'] ]), @@ -161,6 +187,23 @@ class UsersController extends AppController public function delete($id) { + $validRoles = []; + if (!$currentUser['role']['perm_admin']) { + $validRoles = $this->Users->Roles->find('list')->order(['name' => 'asc'])->all()->toArray(); + } + $params = [ + 'beforeSave' => function($data) use ($currentUser, $validRoles) { + if (!$currentUser['role']['perm_admin']) { + if ($data['organisation_id'] !== $currentUser['organisation_id']) { + throw new MethodNotAllowedException(__('You do not have permission to remove the given user.')); + } + if (!in_array($data['role_id'], array_keys($validRoles))) { + throw new MethodNotAllowedException(__('You do not have permission to remove the given user.')); + } + } + return $data; + } + ]; $this->CRUD->delete($id); $responsePayload = $this->CRUD->getResponsePayload(); if (!empty($responsePayload)) { diff --git a/templates/Users/index.php b/templates/Users/index.php index 1ff36bf..21afdc5 100644 --- a/templates/Users/index.php +++ b/templates/Users/index.php @@ -102,12 +102,48 @@ echo $this->element('genericElements/IndexTable/index_table', [ [ 'open_modal' => '/users/edit/[onclick_params_data_path]', 'modal_params_data_path' => 'id', - 'icon' => 'edit' + 'icon' => 'edit', + 'complex_requirement' => [ + 'options' => [ + 'datapath' => [ + 'role_id' => 'role_id' + ] + ], + 'function' => function ($row, $options) use ($loggedUser, $validRoles) { + if (empty($loggedUser['role']['perm_admin'])) { + if (empty($loggedUser['role']['perm_org_admin'])) { + return false; + } + if (!isset($validRoles[$options['datapath']['role_id']])) { + return false; + } + } + return true; + } + ] ], [ 'open_modal' => '/users/delete/[onclick_params_data_path]', 'modal_params_data_path' => 'id', - 'icon' => 'trash' + 'icon' => 'trash', + 'complex_requirement' => [ + 'options' => [ + 'datapath' => [ + 'role_id' => 'role_id' + ] + ], + 'function' => function ($row, $options) use ($loggedUser, $validRoles) { + if (empty($loggedUser['role']['perm_admin'])) { + if (empty($loggedUser['role']['perm_org_admin'])) { + return false; + } + if (!isset($validRoles[$options['datapath']['role_id']])) { + return false; + } + } + return true; + } + ] ], ] ] From 55782af52b8536878384ed6f59edaac7e53699b3 Mon Sep 17 00:00:00 2001 From: iglocska Date: Tue, 25 Jan 2022 15:58:31 +0100 Subject: [PATCH 4/6] fix: [users] add - fixed role selection --- src/Controller/UsersController.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 6fa1067..f03f329 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -45,6 +45,8 @@ class UsersController extends AppController $currentUser = $this->ACL->getUser(); $validRoles = []; if (!$currentUser['role']['perm_admin']) { + $validRoles = $this->Users->Roles->find('list')->select(['id', 'name'])->order(['name' => 'asc'])->where(['perm_admin' => 0])->all()->toArray(); + } else { $validRoles = $this->Users->Roles->find('list')->order(['name' => 'asc'])->all()->toArray(); } @@ -111,6 +113,8 @@ class UsersController extends AppController $validRoles = []; if (!$currentUser['role']['perm_admin']) { $validRoles = $this->Users->Roles->find('list')->select(['id', 'name'])->order(['name' => 'asc'])->where(['perm_admin' => 0])->all()->toArray(); + } else { + $validRoles = $this->Users->Roles->find('list')->order(['name' => 'asc'])->all()->toArray(); } if (empty($id)) { $id = $currentUser['id']; From 1086e41086f7184097e2cb70421e63710249118b Mon Sep 17 00:00:00 2001 From: iglocska Date: Tue, 25 Jan 2022 17:01:27 +0100 Subject: [PATCH 5/6] fix: [modified] saving fixed for sync captures - set the field as not dirty to force an update - stops the exceptions thrown on pulling these objects in --- src/Model/Table/IndividualsTable.php | 1 + src/Model/Table/OrganisationsTable.php | 1 + src/Model/Table/SharingGroupsTable.php | 1 + 3 files changed, 3 insertions(+) diff --git a/src/Model/Table/IndividualsTable.php b/src/Model/Table/IndividualsTable.php index 70f63fd..16a3da2 100644 --- a/src/Model/Table/IndividualsTable.php +++ b/src/Model/Table/IndividualsTable.php @@ -66,6 +66,7 @@ class IndividualsTable extends AppTable $this->patchEntity($existingIndividual, $individual); $entityToSave = $existingIndividual; } + $entityToSave->setDirty('modified', false); $savedEntity = $this->save($entityToSave, ['associated' => false]); if (!$savedEntity) { return null; diff --git a/src/Model/Table/OrganisationsTable.php b/src/Model/Table/OrganisationsTable.php index c56720e..8cd7dec 100644 --- a/src/Model/Table/OrganisationsTable.php +++ b/src/Model/Table/OrganisationsTable.php @@ -71,6 +71,7 @@ class OrganisationsTable extends AppTable $this->patchEntity($existingOrg, $org); $entityToSave = $existingOrg; } + $entityToSave->setDirty('modified', false); $savedEntity = $this->save($entityToSave, ['associated' => false]); if (!$savedEntity) { return null; diff --git a/src/Model/Table/SharingGroupsTable.php b/src/Model/Table/SharingGroupsTable.php index ff39220..e976e8c 100644 --- a/src/Model/Table/SharingGroupsTable.php +++ b/src/Model/Table/SharingGroupsTable.php @@ -66,6 +66,7 @@ class SharingGroupsTable extends AppTable $this->patchEntity($existingSG, $input); $entityToSave = $existingSG; } + $entityToSave->setDirty('modified', false); $savedEntity = $this->save($entityToSave, ['associated' => false]); if (!$savedEntity) { return null; From 19c81b7c114d875453fe202b7d2c7e882be21aec Mon Sep 17 00:00:00 2001 From: iglocska Date: Tue, 25 Jan 2022 17:09:29 +0100 Subject: [PATCH 6/6] fix: [Sharing groups] UUID and owner org shouldn't be editable --- src/Controller/SharingGroupsController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Controller/SharingGroupsController.php b/src/Controller/SharingGroupsController.php index 4e98df8..764f0e6 100644 --- a/src/Controller/SharingGroupsController.php +++ b/src/Controller/SharingGroupsController.php @@ -71,6 +71,7 @@ class SharingGroupsController extends AppController if (empty($currentUser['role']['perm_admin'])) { $params['conditions'] = ['organisation_id' => $currentUser['organisation_id']]; } + $params['fields'] = ['name', 'releasability', 'description', 'active']; $this->CRUD->edit($id, $params); $responsePayload = $this->CRUD->getResponsePayload(); if (!empty($responsePayload)) {