From 44913c5ed77a9fe7d2921808e70c6c3a3053d29e Mon Sep 17 00:00:00 2001 From: Sami Mokaddem Date: Tue, 25 Jan 2022 15:27:34 +0100 Subject: [PATCH 1/2] fix: [users:settings] Allow admin to see account settings of other users --- src/Controller/UsersController.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 9ffb2fe..74aec0d 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -218,10 +218,18 @@ class UsersController extends AppController } } - public function settings() + public function settings($user_id=false) { - $this->set('user', $this->ACL->getUser()); - $all = $this->Users->UserSettings->getSettingsFromProviderForUser($this->ACL->getUser()['id'], true); + $currentUser = $this->ACL->getUser(); + if (empty($currentUser['role']['perm_admin'])) { + $user = $currentUser; + } else { + $user = $this->Users->get($user_id, [ + 'contain' => ['Roles', 'Individuals' => 'Organisations'] + ]); + } + $this->set('user', $user); + $all = $this->Users->UserSettings->getSettingsFromProviderForUser($user->id, true); $this->set('settingsProvider', $all['settingsProvider']); $this->set('settings', $all['settings']); $this->set('settingsFlattened', $all['settingsFlattened']); From f53b458103827c231b976ccb796ed669242caf68 Mon Sep 17 00:00:00 2001 From: Sami Mokaddem Date: Wed, 26 Jan 2022 12:11:44 +0100 Subject: [PATCH 2/2] fix: [userSettings] Allow admin to edit other user's settings --- src/Controller/Component/ACLComponent.php | 10 ++--- src/Controller/UserSettingsController.php | 49 ++++++++++++++++++----- src/Controller/UsersController.php | 7 +++- templates/Users/settings.php | 28 ++++++++++--- templates/element/Settings/category.php | 2 +- webroot/js/main.js | 12 +++--- webroot/js/table-settings.js | 4 +- 7 files changed, 80 insertions(+), 32 deletions(-) diff --git a/src/Controller/Component/ACLComponent.php b/src/Controller/Component/ACLComponent.php index fb51f49..8e50a67 100644 --- a/src/Controller/Component/ACLComponent.php +++ b/src/Controller/Component/ACLComponent.php @@ -188,12 +188,12 @@ class ACLComponent extends Component 'add' => ['*'], 'edit' => ['*'], 'delete' => ['*'], - 'getSettingByName' => ['*'], - 'setSetting' => ['*'], + 'getMySettingByName' => ['*'], + 'setMySetting' => ['*'], 'saveSetting' => ['*'], - 'getBookmarks' => ['*'], - 'saveBookmark' => ['*'], - 'deleteBookmark' => ['*'] + 'getMyBookmarks' => ['*'], + 'saveMyBookmark' => ['*'], + 'deleteMyBookmark' => ['*'] ], 'Api' => [ 'index' => ['*'] diff --git a/src/Controller/UserSettingsController.php b/src/Controller/UserSettingsController.php index d28f6ca..bced32b 100644 --- a/src/Controller/UserSettingsController.php +++ b/src/Controller/UserSettingsController.php @@ -124,7 +124,13 @@ class UserSettingsController extends AppController } } - public function getSettingByName($settingsName) + /** + * Get a setting by name for the currently logged-in user + * + * @param [type] $settingsName + * @return void + */ + public function getMySettingByName($settingsName) { $setting = $this->UserSettings->getSettingByName($this->ACL->getUser(), $settingsName); if (is_null($setting)) { @@ -140,7 +146,7 @@ class UserSettingsController extends AppController $this->render('view'); } - public function setSetting($settingsName = false) + public function setMySetting($settingsName = false) { if (!$this->request->is('get')) { $setting = $this->UserSettings->getSettingByName($this->ACL->getUser(), $settingsName); @@ -160,22 +166,23 @@ class UserSettingsController extends AppController $this->set('settingName', $settingsName); } - public function saveSetting() + public function saveSetting($user_id = false) { + $user = $this->getRequestedUserIfAllowed($user_id); if ($this->request->is('post')) { $data = $this->ParamHandler->harvestParams([ 'name', 'value' ]); - $setting = $this->UserSettings->getSettingByName($this->ACL->getUser(), $data['name']); + $setting = $this->UserSettings->getSettingByName($user, $data['name']); if (is_null($setting)) { // setting not found, create it - $result = $this->UserSettings->createSetting($this->ACL->getUser(), $data['name'], $data['value']); + $result = $this->UserSettings->createSetting($user, $data['name'], $data['value']); } else { - $result = $this->UserSettings->editSetting($this->ACL->getUser(), $data['name'], $data['value']); + $result = $this->UserSettings->editSetting($user, $data['name'], $data['value']); } $success = !empty($result); $message = $success ? __('Setting saved') : __('Could not save setting'); - $this->CRUD->setResponseForController('setSetting', $success, $message, $result); + $this->CRUD->setResponseForController('saveSetting', $success, $message, $result); $responsePayload = $this->CRUD->getResponsePayload(); if (!empty($responsePayload)) { return $responsePayload; @@ -183,7 +190,7 @@ class UserSettingsController extends AppController } } - public function getBookmarks($forSidebar = false) + public function getMyBookmarks($forSidebar = false) { $bookmarks = $this->UserSettings->getSettingByName($this->ACL->getUser(), $this->UserSettings->BOOKMARK_SETTING_NAME); $bookmarks = json_decode($bookmarks['value'], true); @@ -193,7 +200,7 @@ class UserSettingsController extends AppController $this->render('/element/UserSettings/saved-bookmarks'); } - public function saveBookmark() + public function saveMyBookmark() { if (!$this->request->is('get')) { $result = $this->UserSettings->saveBookmark($this->ACL->getUser(), $this->request->getData()); @@ -208,7 +215,7 @@ class UserSettingsController extends AppController $this->set('user_id', $this->ACL->getUser()->id); } - public function deleteBookmark() + public function deleteMyBookmark() { if (!$this->request->is('get')) { $result = $this->UserSettings->deleteBookmark($this->ACL->getUser(), $this->request->getData()); @@ -248,4 +255,26 @@ class UserSettingsController extends AppController } return $isAllowed; } + + /** + * Return the requested user if user permissions allow it. Otherwise, return the user currently logged-in + * + * @param bool|int $user_id + * @return void + */ + private function getRequestedUserIfAllowed($user_id = false) + { + $currentUser = $this->ACL->getUser(); + if (is_bool($user_id)) { + return $currentUser; + } + if (!empty($currentUser['role']['perm_admin'])) { + $user = $this->Users->get($user_id, [ + 'contain' => ['Roles', 'Individuals' => 'Organisations'] + ]); + } else { + $user = $currentUser; + } + return $user; + } } diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 74aec0d..d484b5c 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -220,14 +220,17 @@ class UsersController extends AppController public function settings($user_id=false) { + $editingAnotherUser = false; $currentUser = $this->ACL->getUser(); - if (empty($currentUser['role']['perm_admin'])) { + if (empty($currentUser['role']['perm_admin']) || $user_id == $currentUser->id) { $user = $currentUser; } else { $user = $this->Users->get($user_id, [ - 'contain' => ['Roles', 'Individuals' => 'Organisations'] + 'contain' => ['Roles', 'Individuals' => 'Organisations', 'Organisations', 'UserSettings'] ]); + $editingAnotherUser = true; } + $this->set('editingAnotherUser', $editingAnotherUser); $this->set('user', $user); $all = $this->Users->UserSettings->getSettingsFromProviderForUser($user->id, true); $this->set('settingsProvider', $all['settingsProvider']); diff --git a/templates/Users/settings.php b/templates/Users/settings.php index da014ca..4681def 100644 --- a/templates/Users/settings.php +++ b/templates/Users/settings.php @@ -10,10 +10,12 @@ foreach ($settingsProvider as $settingTitle => $settingContent) { ]); } -$navLinks[] = __('Bookmarks'); -$tabContents[] = $this->element('UserSettings/saved-bookmarks', [ - 'bookmarks' => !empty($user->user_settings_by_name['ui.bookmarks']['value']) ? json_decode($user->user_settings_by_name['ui.bookmarks']['value'], true) : [] -]); +if (empty($editingAnotherUser)) { + $navLinks[] = __('Bookmarks'); + $tabContents[] = $this->element('UserSettings/saved-bookmarks', [ + 'bookmarks' => !empty($user->user_settings_by_name['ui.bookmarks']['value']) ? json_decode($user->user_settings_by_name['ui.bookmarks']['value'], true) : [] + ]); +} $tabsOptions = [ 'vertical' => true, @@ -29,11 +31,15 @@ $tabsOptions = [ ]; $tabs = $this->Bootstrap->tabs($tabsOptions); echo $this->Html->script('settings'); +$saveUrl = '/userSettings/saveSetting'; +if(!empty($editingAnotherUser)) { + $saveUrl .= '/' . h($user->id); +} ?>

@@ -43,7 +49,17 @@ echo $this->Html->script('settings'); username) ?> individual->full_name) ?> -
+ + Bootstrap->alert([ + 'text' => __('Currently editing the account setting of another user.'), + 'variant' => 'warning', + 'dismissible' => false + ]) + ?> + +
+
diff --git a/templates/element/Settings/category.php b/templates/element/Settings/category.php index 03e17e4..317dac0 100644 --- a/templates/element/Settings/category.php +++ b/templates/element/Settings/category.php @@ -57,6 +57,6 @@ $mainPanelHeight = 'calc(100vh - 42px - 1rem - 56px - 38px - 1rem)';
- + %s

', __('No settings available for this category')) ?>
\ No newline at end of file diff --git a/webroot/js/main.js b/webroot/js/main.js index fc2a4dc..420d1bf 100644 --- a/webroot/js/main.js +++ b/webroot/js/main.js @@ -167,7 +167,7 @@ function saveSetting(statusNode, settingName, settingValue) { } function openSaveBookmarkModal(bookmark_url = '') { - const url = '/user-settings/saveBookmark'; + const url = '/user-settings/saveMyBookmark'; UI.submissionModal(url).then(([modalFactory, ajaxApi]) => { const $input = modalFactory.$modal.find('input[name="bookmark_url"]') $input.val(bookmark_url) @@ -175,7 +175,7 @@ function openSaveBookmarkModal(bookmark_url = '') { } function deleteBookmark(bookmark, forSidebar=false) { - const url = '/user-settings/deleteBookmark' + const url = '/user-settings/deleteMyBookmark' AJAXApi.quickFetchAndPostForm(url, { bookmark_name: bookmark.name, bookmark_url: bookmark.url, @@ -183,7 +183,7 @@ function deleteBookmark(bookmark, forSidebar=false) { provideFeedback: true, statusNode: $('.bookmark-table-container'), }).then((apiResult) => { - const url = `/userSettings/getBookmarks/${forSidebar ? '1' : '0'}` + const url = `/userSettings/getMyBookmarks/${forSidebar ? '1' : '0'}` UI.reload(url, $('.bookmark-table-container').parent()) const theToast = UI.toast({ variant: 'success', @@ -191,7 +191,7 @@ function deleteBookmark(bookmark, forSidebar=false) { bodyHtml: $('
').append( $('').text('Cancel deletion operation.'), $('