fix: [userSettings] Allow admin to edit other user's settings

cli-modification-summary
Sami Mokaddem 2022-01-26 12:11:44 +01:00
parent 44913c5ed7
commit f53b458103
No known key found for this signature in database
GPG Key ID: 164C473F627A06FA
7 changed files with 80 additions and 32 deletions

View File

@ -188,12 +188,12 @@ class ACLComponent extends Component
'add' => ['*'], 'add' => ['*'],
'edit' => ['*'], 'edit' => ['*'],
'delete' => ['*'], 'delete' => ['*'],
'getSettingByName' => ['*'], 'getMySettingByName' => ['*'],
'setSetting' => ['*'], 'setMySetting' => ['*'],
'saveSetting' => ['*'], 'saveSetting' => ['*'],
'getBookmarks' => ['*'], 'getMyBookmarks' => ['*'],
'saveBookmark' => ['*'], 'saveMyBookmark' => ['*'],
'deleteBookmark' => ['*'] 'deleteMyBookmark' => ['*']
], ],
'Api' => [ 'Api' => [
'index' => ['*'] 'index' => ['*']

View File

@ -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); $setting = $this->UserSettings->getSettingByName($this->ACL->getUser(), $settingsName);
if (is_null($setting)) { if (is_null($setting)) {
@ -140,7 +146,7 @@ class UserSettingsController extends AppController
$this->render('view'); $this->render('view');
} }
public function setSetting($settingsName = false) public function setMySetting($settingsName = false)
{ {
if (!$this->request->is('get')) { if (!$this->request->is('get')) {
$setting = $this->UserSettings->getSettingByName($this->ACL->getUser(), $settingsName); $setting = $this->UserSettings->getSettingByName($this->ACL->getUser(), $settingsName);
@ -160,22 +166,23 @@ class UserSettingsController extends AppController
$this->set('settingName', $settingsName); $this->set('settingName', $settingsName);
} }
public function saveSetting() public function saveSetting($user_id = false)
{ {
$user = $this->getRequestedUserIfAllowed($user_id);
if ($this->request->is('post')) { if ($this->request->is('post')) {
$data = $this->ParamHandler->harvestParams([ $data = $this->ParamHandler->harvestParams([
'name', 'name',
'value' '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 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 { } else {
$result = $this->UserSettings->editSetting($this->ACL->getUser(), $data['name'], $data['value']); $result = $this->UserSettings->editSetting($user, $data['name'], $data['value']);
} }
$success = !empty($result); $success = !empty($result);
$message = $success ? __('Setting saved') : __('Could not save setting'); $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(); $responsePayload = $this->CRUD->getResponsePayload();
if (!empty($responsePayload)) { if (!empty($responsePayload)) {
return $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 = $this->UserSettings->getSettingByName($this->ACL->getUser(), $this->UserSettings->BOOKMARK_SETTING_NAME);
$bookmarks = json_decode($bookmarks['value'], true); $bookmarks = json_decode($bookmarks['value'], true);
@ -193,7 +200,7 @@ class UserSettingsController extends AppController
$this->render('/element/UserSettings/saved-bookmarks'); $this->render('/element/UserSettings/saved-bookmarks');
} }
public function saveBookmark() public function saveMyBookmark()
{ {
if (!$this->request->is('get')) { if (!$this->request->is('get')) {
$result = $this->UserSettings->saveBookmark($this->ACL->getUser(), $this->request->getData()); $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); $this->set('user_id', $this->ACL->getUser()->id);
} }
public function deleteBookmark() public function deleteMyBookmark()
{ {
if (!$this->request->is('get')) { if (!$this->request->is('get')) {
$result = $this->UserSettings->deleteBookmark($this->ACL->getUser(), $this->request->getData()); $result = $this->UserSettings->deleteBookmark($this->ACL->getUser(), $this->request->getData());
@ -248,4 +255,26 @@ class UserSettingsController extends AppController
} }
return $isAllowed; 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;
}
} }

View File

@ -220,14 +220,17 @@ class UsersController extends AppController
public function settings($user_id=false) public function settings($user_id=false)
{ {
$editingAnotherUser = false;
$currentUser = $this->ACL->getUser(); $currentUser = $this->ACL->getUser();
if (empty($currentUser['role']['perm_admin'])) { if (empty($currentUser['role']['perm_admin']) || $user_id == $currentUser->id) {
$user = $currentUser; $user = $currentUser;
} else { } else {
$user = $this->Users->get($user_id, [ $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); $this->set('user', $user);
$all = $this->Users->UserSettings->getSettingsFromProviderForUser($user->id, true); $all = $this->Users->UserSettings->getSettingsFromProviderForUser($user->id, true);
$this->set('settingsProvider', $all['settingsProvider']); $this->set('settingsProvider', $all['settingsProvider']);

View File

@ -10,10 +10,12 @@ foreach ($settingsProvider as $settingTitle => $settingContent) {
]); ]);
} }
$navLinks[] = __('Bookmarks'); if (empty($editingAnotherUser)) {
$tabContents[] = $this->element('UserSettings/saved-bookmarks', [ $navLinks[] = __('Bookmarks');
'bookmarks' => !empty($user->user_settings_by_name['ui.bookmarks']['value']) ? json_decode($user->user_settings_by_name['ui.bookmarks']['value'], true) : [] $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 = [ $tabsOptions = [
'vertical' => true, 'vertical' => true,
@ -29,11 +31,15 @@ $tabsOptions = [
]; ];
$tabs = $this->Bootstrap->tabs($tabsOptions); $tabs = $this->Bootstrap->tabs($tabsOptions);
echo $this->Html->script('settings'); echo $this->Html->script('settings');
$saveUrl = '/userSettings/saveSetting';
if(!empty($editingAnotherUser)) {
$saveUrl .= '/' . h($user->id);
}
?> ?>
<script> <script>
window.settingsFlattened = <?= json_encode($settingsFlattened) ?>; window.settingsFlattened = <?= json_encode($settingsFlattened) ?>;
window.saveSettingURL = '/userSettings/saveSetting' window.saveSettingURL = '<?= $saveUrl ?>'
</script> </script>
<h2 class="fw-light"><?= __('Account settings') ?></h2> <h2 class="fw-light"><?= __('Account settings') ?></h2>
@ -43,7 +49,17 @@ echo $this->Html->script('settings');
<span class="fw-bold font-monospace me-2 fs-5"><?= h($user->username) ?></span> <span class="fw-bold font-monospace me-2 fs-5"><?= h($user->username) ?></span>
<span><?= h($user->individual->full_name) ?></span> <span><?= h($user->individual->full_name) ?></span>
</div> </div>
<div class="fw-light"><?= __('Your personnal account') ?></div> <?php if (!empty($editingAnotherUser)): ?>
<?=
$this->Bootstrap->alert([
'text' => __('Currently editing the account setting of another user.'),
'variant' => 'warning',
'dismissible' => false
])
?>
<?php else: ?>
<div class="fw-light"><?= __('Your personnal account') ?></div>
<?php endif; ?>
</div> </div>
<div class="mt-2"> <div class="mt-2">
<?= $tabs ?> <?= $tabs ?>

View File

@ -57,6 +57,6 @@ $mainPanelHeight = 'calc(100vh - 42px - 1rem - 56px - 38px - 1rem)';
</div> </div>
<?php else: ?> <?php else: ?>
<div> <div>
<?= $contentHtml ?> <?= !empty($contentHtml) ? $contentHtml : sprintf('<p class="text-center mt-3">%s</p>', __('No settings available for this category')) ?>
</div> </div>
<?php endif; ?> <?php endif; ?>

View File

@ -167,7 +167,7 @@ function saveSetting(statusNode, settingName, settingValue) {
} }
function openSaveBookmarkModal(bookmark_url = '') { function openSaveBookmarkModal(bookmark_url = '') {
const url = '/user-settings/saveBookmark'; const url = '/user-settings/saveMyBookmark';
UI.submissionModal(url).then(([modalFactory, ajaxApi]) => { UI.submissionModal(url).then(([modalFactory, ajaxApi]) => {
const $input = modalFactory.$modal.find('input[name="bookmark_url"]') const $input = modalFactory.$modal.find('input[name="bookmark_url"]')
$input.val(bookmark_url) $input.val(bookmark_url)
@ -175,7 +175,7 @@ function openSaveBookmarkModal(bookmark_url = '') {
} }
function deleteBookmark(bookmark, forSidebar=false) { function deleteBookmark(bookmark, forSidebar=false) {
const url = '/user-settings/deleteBookmark' const url = '/user-settings/deleteMyBookmark'
AJAXApi.quickFetchAndPostForm(url, { AJAXApi.quickFetchAndPostForm(url, {
bookmark_name: bookmark.name, bookmark_name: bookmark.name,
bookmark_url: bookmark.url, bookmark_url: bookmark.url,
@ -183,7 +183,7 @@ function deleteBookmark(bookmark, forSidebar=false) {
provideFeedback: true, provideFeedback: true,
statusNode: $('.bookmark-table-container'), statusNode: $('.bookmark-table-container'),
}).then((apiResult) => { }).then((apiResult) => {
const url = `/userSettings/getBookmarks/${forSidebar ? '1' : '0'}` const url = `/userSettings/getMyBookmarks/${forSidebar ? '1' : '0'}`
UI.reload(url, $('.bookmark-table-container').parent()) UI.reload(url, $('.bookmark-table-container').parent())
const theToast = UI.toast({ const theToast = UI.toast({
variant: 'success', variant: 'success',
@ -191,7 +191,7 @@ function deleteBookmark(bookmark, forSidebar=false) {
bodyHtml: $('<div/>').append( bodyHtml: $('<div/>').append(
$('<span/>').text('Cancel deletion operation.'), $('<span/>').text('Cancel deletion operation.'),
$('<button/>').addClass(['btn', 'btn-primary', 'btn-sm', 'ms-3']).text('Restore bookmark').click(function () { $('<button/>').addClass(['btn', 'btn-primary', 'btn-sm', 'ms-3']).text('Restore bookmark').click(function () {
const urlRestore = '/user-settings/saveBookmark' const urlRestore = '/user-settings/saveMyBookmark'
AJAXApi.quickFetchAndPostForm(urlRestore, { AJAXApi.quickFetchAndPostForm(urlRestore, {
bookmark_label: bookmark.label, bookmark_label: bookmark.label,
bookmark_name: bookmark.name, bookmark_name: bookmark.name,
@ -200,7 +200,7 @@ function deleteBookmark(bookmark, forSidebar=false) {
provideFeedback: true, provideFeedback: true,
statusNode: $('.bookmark-table-container') statusNode: $('.bookmark-table-container')
}).then(() => { }).then(() => {
const url = `/userSettings/getBookmarks/${forSidebar ? '1' : '0'}` const url = `/userSettings/getMyBookmarks/${forSidebar ? '1' : '0'}`
UI.reload(url, $('.bookmark-table-container').parent()) UI.reload(url, $('.bookmark-table-container').parent())
}) })
}), }),
@ -297,7 +297,7 @@ $(document).ready(() => {
$sidebar.addClass('expanded') $sidebar.addClass('expanded')
} }
const settingName = 'ui.sidebar.expanded'; const settingName = 'ui.sidebar.expanded';
const url = `/user-settings/setSetting/${settingName}` const url = `/user-settings/setMySetting/${settingName}`
AJAXApi.quickFetchAndPostForm(url, { AJAXApi.quickFetchAndPostForm(url, {
value: expanded ? 0 : 1 value: expanded ? 0 : 1
}, { provideFeedback: false}) }, { provideFeedback: false})

View File

@ -1,7 +1,7 @@
// function saveHiddenColumns(table_setting_id, newTableSettings) { // function saveHiddenColumns(table_setting_id, newTableSettings) {
function mergeAndSaveSettings(table_setting_id, newTableSettings) { function mergeAndSaveSettings(table_setting_id, newTableSettings) {
const settingName = 'ui.table_setting' const settingName = 'ui.table_setting'
const urlGet = `/user-settings/getSettingByName/${settingName}` const urlGet = `/user-settings/getMySettingByName/${settingName}`
AJAXApi.quickFetchJSON(urlGet).then(tableSettings => { AJAXApi.quickFetchJSON(urlGet).then(tableSettings => {
tableSettings = JSON.parse(tableSettings.value) tableSettings = JSON.parse(tableSettings.value)
newTableSettings = mergeNewTableSettingsIntoOld(table_setting_id, tableSettings, newTableSettings) newTableSettings = mergeNewTableSettingsIntoOld(table_setting_id, tableSettings, newTableSettings)
@ -19,7 +19,7 @@ function mergeNewTableSettingsIntoOld(table_setting_id, oldTableSettings, newTab
} }
function saveTableSetting(settingName, newTableSettings) { function saveTableSetting(settingName, newTableSettings) {
const urlSet = `/user-settings/setSetting/${settingName}` const urlSet = `/user-settings/setMySetting/${settingName}`
AJAXApi.quickFetchAndPostForm(urlSet, { AJAXApi.quickFetchAndPostForm(urlSet, {
value: JSON.stringify(newTableSettings) value: JSON.stringify(newTableSettings)
}, { }, {