2019-09-25 11:50:54 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Feature developed as part of a training given by CIRCL in Luxembourg on 26/09/2019
|
|
|
|
* Verbose comments for educational purposes only
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
App::uses('AppController', 'Controller');
|
|
|
|
|
2021-03-20 13:35:58 +01:00
|
|
|
/**
|
|
|
|
* @property UserSetting $UserSetting
|
|
|
|
*/
|
2019-09-25 11:50:54 +02:00
|
|
|
class UserSettingsController extends AppController
|
|
|
|
{
|
|
|
|
public $components = array('Session', 'RequestHandler');
|
|
|
|
|
|
|
|
public $paginate = array(
|
|
|
|
'limit' => 60,
|
|
|
|
'maxLimit' => 9999,
|
|
|
|
'order' => array(
|
|
|
|
'UserSetting.id' => 'DESC'
|
|
|
|
),
|
|
|
|
'contain' => array(
|
|
|
|
'User.id',
|
|
|
|
'User.email'
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2020-03-01 18:05:21 +01:00
|
|
|
public function beforeFilter()
|
|
|
|
{
|
|
|
|
parent::beforeFilter();
|
2021-03-20 13:35:58 +01:00
|
|
|
$this->Security->unlockedActions[] = 'eventIndexColumnToggle';
|
2020-03-01 18:05:21 +01:00
|
|
|
}
|
|
|
|
|
2019-09-25 11:50:54 +02:00
|
|
|
public function index()
|
|
|
|
{
|
|
|
|
$filterData = array(
|
|
|
|
'request' => $this->request,
|
|
|
|
'paramArray' => array('setting', 'user_id', 'sort', 'direction', 'page', 'limit'),
|
|
|
|
'named_params' => $this->params['named']
|
|
|
|
);
|
|
|
|
$exception = false;
|
|
|
|
$filters = $this->_harvestParameters($filterData, $exception);
|
|
|
|
$conditions = array();
|
|
|
|
if (!empty($filters['setting'])) {
|
|
|
|
$conditions['AND'][] = array(
|
|
|
|
'setting' => $filters['setting']
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (!empty($filters['user_id'])) {
|
|
|
|
if ($filters['user_id'] === 'all') {
|
|
|
|
$context = 'all';
|
|
|
|
} else if ($filters['user_id'] === 'me') {
|
|
|
|
$conditions['AND'][] = array(
|
|
|
|
'user_id' => $this->Auth->user('id')
|
|
|
|
);
|
|
|
|
$context = 'me';
|
|
|
|
} else if ($filters['user_id'] === 'org') {
|
|
|
|
$conditions['AND'][] = array(
|
|
|
|
'user_id' => $this->UserSetting->User->find(
|
|
|
|
'list', array(
|
|
|
|
'conditions' => array(
|
|
|
|
'User.org_id' => $this->Auth->user('org_id')
|
|
|
|
),
|
|
|
|
'fields' => array(
|
|
|
|
'User.id', 'User.id'
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
$context = 'org';
|
|
|
|
} else {
|
|
|
|
$conditions['AND'][] = array(
|
|
|
|
'user_id' => $filters['user_id']
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!$this->_isSiteAdmin()) {
|
|
|
|
if ($this->_isAdmin()) {
|
|
|
|
$conditions['AND'][] = array(
|
|
|
|
'UserSetting.user_id' => $this->UserSetting->User->find(
|
|
|
|
'list', array(
|
|
|
|
'conditions' => array(
|
|
|
|
'User.org_id' => $this->Auth->user('org_id')
|
|
|
|
),
|
|
|
|
'fields' => array(
|
|
|
|
'User.id', 'User.id'
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
$conditions['AND'][] = array(
|
|
|
|
'UserSetting.user_id' => $this->Auth->user('id')
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2022-02-19 13:40:19 +01:00
|
|
|
// Do not show internal settings
|
|
|
|
if (!$this->_isSiteAdmin()) {
|
|
|
|
$conditions['AND'][] = ['NOT' => ['UserSetting.setting' => $this->UserSetting->getInternalSettingNames()]];
|
|
|
|
}
|
|
|
|
|
2019-09-25 11:50:54 +02:00
|
|
|
if ($this->_isRest()) {
|
|
|
|
$params = array(
|
|
|
|
'conditions' => $conditions
|
|
|
|
);
|
|
|
|
if (!empty($filters['page'])) {
|
|
|
|
$params['page'] = $filters['page'];
|
|
|
|
$params['limit'] = $this->paginate['limit'];
|
|
|
|
}
|
|
|
|
if (!empty($filters['limit'])) {
|
|
|
|
$params['limit'] = $filters['limit'];
|
|
|
|
}
|
|
|
|
$userSettings = $this->UserSetting->find('all', $params);
|
|
|
|
return $this->RestResponse->viewData($userSettings, $this->response->type());
|
|
|
|
} else {
|
|
|
|
$this->paginate['conditions'] = $conditions;
|
2019-10-10 11:58:26 +02:00
|
|
|
$data = $this->paginate();
|
|
|
|
foreach ($data as $k => $v) {
|
2021-10-25 21:28:19 +02:00
|
|
|
if (!empty(UserSetting::VALID_SETTINGS[$v['UserSetting']['setting']])) {
|
|
|
|
$data[$k]['UserSetting']['restricted'] = empty(UserSetting::VALID_SETTINGS[$v['UserSetting']['setting']]['restricted']) ? '' : UserSetting::VALID_SETTINGS[$v['UserSetting']['setting']]['restricted'];
|
2019-10-10 11:58:26 +02:00
|
|
|
} else {
|
|
|
|
$data[$k]['UserSetting']['restricted'] = array();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$this->set('data', $data);
|
2019-09-25 11:50:54 +02:00
|
|
|
$this->set('context', empty($context) ? 'null' : $context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function view($id)
|
|
|
|
{
|
2022-02-19 13:37:10 +01:00
|
|
|
if (!$this->_isRest()) {
|
|
|
|
throw new BadRequestException("This endpoint is accessible just by REST requests.");
|
|
|
|
}
|
2019-09-25 11:50:54 +02:00
|
|
|
// check if the ID is valid and whether a user setting with the given ID exists
|
|
|
|
if (empty($id) || !is_numeric($id)) {
|
2022-02-19 13:37:10 +01:00
|
|
|
throw new BadRequestException(__('Invalid ID passed.'));
|
2019-09-25 11:50:54 +02:00
|
|
|
}
|
|
|
|
$userSetting = $this->UserSetting->find('first', array(
|
|
|
|
'recursive' => -1,
|
|
|
|
'conditions' => array(
|
|
|
|
'UserSetting.id' => $id
|
|
|
|
),
|
|
|
|
'contain' => array('User.id', 'User.org_id')
|
|
|
|
));
|
2019-09-29 20:21:35 +02:00
|
|
|
if (empty($userSetting)) {
|
|
|
|
throw new NotFoundException(__('Invalid user setting.'));
|
|
|
|
}
|
2019-09-25 11:50:54 +02:00
|
|
|
$checkAccess = $this->UserSetting->checkAccess($this->Auth->user(), $userSetting);
|
2019-09-29 20:21:35 +02:00
|
|
|
if (!$checkAccess) {
|
2019-09-25 11:50:54 +02:00
|
|
|
throw new NotFoundException(__('Invalid user setting.'));
|
|
|
|
}
|
2022-02-19 13:37:10 +01:00
|
|
|
unset($userSetting['User']);
|
|
|
|
return $this->RestResponse->viewData($userSetting, $this->response->type());
|
2019-09-25 11:50:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public function setSetting($user_id = false, $setting = false)
|
|
|
|
{
|
2019-10-10 11:58:26 +02:00
|
|
|
if (!empty($setting)) {
|
2022-02-19 13:40:19 +01:00
|
|
|
if (!$this->UserSetting->checkSettingValidity($setting) || $this->UserSetting->isInternal($setting)) {
|
2019-10-10 11:58:26 +02:00
|
|
|
throw new MethodNotAllowedException(__('Invalid setting.'));
|
|
|
|
}
|
|
|
|
$settingPermCheck = $this->UserSetting->checkSettingAccess($this->Auth->user(), $setting);
|
|
|
|
if ($settingPermCheck !== true) {
|
|
|
|
throw new MethodNotAllowedException(__('This setting is restricted and requires the following permission(s): %s', $settingPermCheck));
|
|
|
|
}
|
|
|
|
}
|
2019-09-25 11:50:54 +02:00
|
|
|
// handle POST requests
|
|
|
|
if ($this->request->is('post')) {
|
|
|
|
// massage the request to allow for unencapsulated POST requests via the API
|
|
|
|
// {"key": "value"} instead of {"UserSetting": {"key": "value"}}
|
|
|
|
if (empty($this->request->data['UserSetting'])) {
|
|
|
|
$this->request->data = array('UserSetting' => $this->request->data);
|
|
|
|
}
|
|
|
|
if (!empty($user_id)) {
|
|
|
|
$this->request->data['UserSetting']['user_id'] = $user_id;
|
|
|
|
}
|
|
|
|
if (!empty($setting)) {
|
|
|
|
$this->request->data['UserSetting']['setting'] = $setting;
|
|
|
|
}
|
2020-03-01 18:05:21 +01:00
|
|
|
$result = $this->UserSetting->setSetting($this->Auth->user(), $this->request->data);
|
2019-09-25 11:50:54 +02:00
|
|
|
if ($result) {
|
|
|
|
// if we've managed to save our setting
|
|
|
|
if ($this->_isRest()) {
|
|
|
|
// if we are dealing with an API request
|
|
|
|
$userSetting = $this->UserSetting->find('first', array(
|
|
|
|
'recursive' => -1,
|
|
|
|
'conditions' => array('UserSetting.id' => $this->UserSetting->id)
|
|
|
|
));
|
|
|
|
return $this->RestResponse->viewData($userSetting, $this->response->type());
|
|
|
|
} else {
|
|
|
|
// if we are dealing with a UI request, redirect the user to the user view with the proper flash message
|
|
|
|
$this->Flash->success(__('Setting saved.'));
|
|
|
|
$this->redirect(array('controller' => 'user_settings', 'action' => 'index', $this->Auth->User('id')));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// if we've failed saving our setting
|
|
|
|
if ($this->_isRest()) {
|
|
|
|
// if we are dealing with an API request
|
|
|
|
return $this->RestResponse->saveFailResponse('UserSettings', 'add', false, $this->UserSetting->validationErrors, $this->response->type());
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* if we are dealing with a UI request, simply set an error in a flash message
|
|
|
|
* and render the view of this endpoint, pre-populated with the submitted values.
|
|
|
|
*/
|
|
|
|
$this->Flash->error(__('Setting could not be saved.'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($this->_isRest()) {
|
|
|
|
// GET request via the API should describe the endpoint
|
2019-09-29 20:21:35 +02:00
|
|
|
return $this->RestResponse->describe('UserSettings', 'setSetting', false, $this->response->type());
|
2022-07-29 17:18:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// load the valid settings from the model
|
|
|
|
if ($this->_isSiteAdmin()) {
|
|
|
|
$users = $this->UserSetting->User->find('list', array(
|
|
|
|
'fields' => array('User.id', 'User.email')
|
|
|
|
));
|
|
|
|
} else if ($this->_isAdmin()) {
|
|
|
|
$users = $this->UserSetting->User->find('list', array(
|
|
|
|
'conditions' => array('User.org_id' => $this->Auth->user('org_id')),
|
|
|
|
'fields' => array('User.id', 'User.email')
|
|
|
|
));
|
2019-09-25 11:50:54 +02:00
|
|
|
} else {
|
2022-07-29 17:18:16 +02:00
|
|
|
$users = array($this->Auth->user('id') => $this->Auth->user('email'));
|
|
|
|
}
|
|
|
|
if (!empty($user_id) && $this->request->is('get')) {
|
|
|
|
$this->request->data['UserSetting']['user_id'] = $user_id;
|
2019-09-25 11:50:54 +02:00
|
|
|
}
|
2022-07-29 17:18:16 +02:00
|
|
|
$this->set('setting', $setting);
|
|
|
|
$this->set('users', $users);
|
|
|
|
$this->set('validSettings', $this->UserSetting->settingPlaceholders($this->Auth->user()));
|
|
|
|
$this->set('title_for_layout', __('Set User Setting'));
|
2019-09-25 11:50:54 +02:00
|
|
|
}
|
|
|
|
|
2021-10-25 21:28:19 +02:00
|
|
|
public function getSetting($userId = null, $setting = null)
|
2019-09-25 11:50:54 +02:00
|
|
|
{
|
2021-10-25 21:28:19 +02:00
|
|
|
if ($this->request->is('post')) {
|
|
|
|
if (empty($this->request->data['setting'])) {
|
2021-10-26 22:22:27 +02:00
|
|
|
throw new BadRequestException("No setting name provided.");
|
2021-10-25 21:28:19 +02:00
|
|
|
}
|
|
|
|
$setting = $this->request->data['setting'];
|
|
|
|
$userId = $this->request->data['user_id'] ?? $this->Auth->user('id');
|
|
|
|
} else {
|
|
|
|
if (empty($userId) || empty($setting)) {
|
|
|
|
throw new BadRequestException("No setting name or user ID provided.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-19 13:40:19 +01:00
|
|
|
if (!$this->UserSetting->checkSettingValidity($setting) || $this->UserSetting->isInternal($setting)) {
|
2021-10-25 21:28:19 +02:00
|
|
|
throw new NotFoundException(__('Invalid setting.'));
|
2019-09-25 11:50:54 +02:00
|
|
|
}
|
2021-10-25 21:28:19 +02:00
|
|
|
|
2019-09-25 11:50:54 +02:00
|
|
|
$userSetting = $this->UserSetting->find('first', array(
|
|
|
|
'recursive' => -1,
|
2021-10-25 21:28:19 +02:00
|
|
|
'conditions' => [
|
|
|
|
'UserSetting.user_id' => $userId,
|
|
|
|
'UserSetting.setting' => $setting,
|
|
|
|
],
|
2019-09-25 11:50:54 +02:00
|
|
|
'contain' => array('User.id', 'User.org_id')
|
|
|
|
));
|
2021-10-25 21:28:19 +02:00
|
|
|
|
|
|
|
if (empty($userSetting)) {
|
|
|
|
throw new NotFoundException(__('Invalid setting.'));
|
2019-09-25 11:50:54 +02:00
|
|
|
}
|
2021-10-25 21:28:19 +02:00
|
|
|
|
|
|
|
$checkAccess = $this->UserSetting->checkAccess($this->Auth->user(), $userSetting, $userId);
|
|
|
|
if (!$checkAccess) {
|
|
|
|
throw new NotFoundException(__('Invalid setting.'));
|
2019-09-25 11:50:54 +02:00
|
|
|
}
|
2021-10-25 21:28:19 +02:00
|
|
|
return $this->RestResponse->viewData($userSetting['UserSetting'], $this->response->type());
|
2019-09-25 11:50:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public function delete($id = false)
|
|
|
|
{
|
|
|
|
if ($this->request->is('get') && $this->_isRest()) {
|
|
|
|
/*
|
|
|
|
* GET request via the API should describe the endpoint
|
|
|
|
* Unlike with the add() endpoint, we want to run this check before doing anything else,
|
|
|
|
* in order to allow us to reach this endpoint without passing a valid ID
|
|
|
|
*/
|
|
|
|
return $this->RestResponse->describe('UserSettings', 'delete', false, $this->response->type());
|
|
|
|
}
|
2021-10-25 20:22:05 +02:00
|
|
|
|
|
|
|
if (!$this->request->is('post') && !$this->request->is('delete')) {
|
|
|
|
throw new MethodNotAllowedException(__('Expecting POST or DELETE request.'));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (empty($id)) {
|
|
|
|
if (empty($this->request->data['setting'])) {
|
|
|
|
throw new BadRequestException("No setting name to delete provided.");
|
|
|
|
}
|
|
|
|
$conditions = ['UserSetting.setting' => $this->request->data['setting']];
|
|
|
|
if (!empty($this->request->data['user_id'])) {
|
|
|
|
$conditions['UserSetting.user_id'] = $this->request->data['user_id'];
|
|
|
|
} else {
|
|
|
|
$conditions['UserSetting.user_id'] = $this->Auth->user('id'); // current user
|
|
|
|
}
|
|
|
|
} else if (is_numeric($id)) {
|
|
|
|
$conditions = ['UserSetting.id' => $id];
|
|
|
|
} else {
|
|
|
|
throw new BadRequestException(__('Invalid ID passed.'));
|
2019-09-25 11:50:54 +02:00
|
|
|
}
|
2021-10-25 20:22:05 +02:00
|
|
|
|
2019-09-25 11:50:54 +02:00
|
|
|
$userSetting = $this->UserSetting->find('first', array(
|
|
|
|
'recursive' => -1,
|
2021-10-25 20:22:05 +02:00
|
|
|
'conditions' => $conditions,
|
2019-09-25 11:50:54 +02:00
|
|
|
'contain' => array('User.id', 'User.org_id')
|
|
|
|
));
|
2019-09-29 20:21:35 +02:00
|
|
|
if (empty($userSetting)) {
|
|
|
|
throw new NotFoundException(__('Invalid user setting.'));
|
|
|
|
}
|
2019-09-25 11:50:54 +02:00
|
|
|
$checkAccess = $this->UserSetting->checkAccess($this->Auth->user(), $userSetting);
|
2019-09-29 20:21:35 +02:00
|
|
|
if (!$checkAccess) {
|
2019-09-25 11:50:54 +02:00
|
|
|
throw new NotFoundException(__('Invalid user setting.'));
|
|
|
|
}
|
2019-10-10 11:58:26 +02:00
|
|
|
$settingPermCheck = $this->UserSetting->checkSettingAccess($this->Auth->user(), $userSetting['UserSetting']['setting']);
|
|
|
|
if ($settingPermCheck !== true) {
|
|
|
|
throw new MethodNotAllowedException(__('This setting is restricted and requires the following permission(s): %s', $settingPermCheck));
|
|
|
|
}
|
2021-10-25 20:22:05 +02:00
|
|
|
// Delete the setting that we were after.
|
|
|
|
$result = $this->UserSetting->delete($userSetting['UserSetting']['id']);
|
|
|
|
if ($result) {
|
|
|
|
// set the response for both the UI and API
|
|
|
|
$message = __('Setting deleted.');
|
|
|
|
if ($this->_isRest()) {
|
|
|
|
return $this->RestResponse->saveSuccessResponse('UserSettings', 'delete', $userSetting['UserSetting']['id'], $this->response->type(), $message);
|
2019-09-25 11:50:54 +02:00
|
|
|
} else {
|
2021-10-25 20:22:05 +02:00
|
|
|
$this->Flash->success($message);
|
2019-09-25 11:50:54 +02:00
|
|
|
}
|
|
|
|
} else {
|
2021-10-25 20:22:05 +02:00
|
|
|
// set the response for both the UI and API
|
|
|
|
$message = __('Setting could not be deleted.');
|
|
|
|
if ($this->_isRest()) {
|
|
|
|
return $this->RestResponse->saveFailResponse('UserSettings', 'delete', $userSetting['UserSetting']['id'], $message, $this->response->type());
|
|
|
|
} else {
|
|
|
|
$this->Flash->error($message);
|
|
|
|
}
|
2019-09-25 11:50:54 +02:00
|
|
|
}
|
2021-10-25 20:22:05 +02:00
|
|
|
/*
|
|
|
|
* The API responses stopped executing this function and returned a serialised response to the user.
|
|
|
|
* For UI users, redirect to where they issued the request from.
|
|
|
|
*/
|
|
|
|
$this->redirect($this->referer());
|
2019-09-25 11:50:54 +02:00
|
|
|
}
|
2020-03-01 18:05:21 +01:00
|
|
|
|
|
|
|
public function setHomePage()
|
|
|
|
{
|
2020-07-14 14:26:11 +02:00
|
|
|
if ($this->request->is('post')) {
|
|
|
|
if (isset($this->request->data['UserSetting'])) {
|
|
|
|
$this->request->data = $this->request->data['UserSetting'];
|
|
|
|
}
|
|
|
|
if (!isset($this->request->data['path'])) {
|
|
|
|
$this->request->data = array('path' => $this->request->data);
|
|
|
|
}
|
|
|
|
if (empty($this->request->data['path'])) {
|
|
|
|
throw new InvalidArgumentException(__('No path POSTed.'));
|
|
|
|
}
|
|
|
|
$setting = array(
|
|
|
|
'UserSetting' => array(
|
|
|
|
'user_id' => $this->Auth->user('id'),
|
|
|
|
'setting' => 'homepage',
|
2022-02-19 13:39:47 +01:00
|
|
|
'value' => ['path' => $this->request->data['path']],
|
2020-07-14 14:26:11 +02:00
|
|
|
)
|
|
|
|
);
|
|
|
|
$result = $this->UserSetting->setSetting($this->Auth->user(), $setting);
|
2020-07-14 17:26:57 +02:00
|
|
|
return $this->RestResponse->saveSuccessResponse('UserSettings', 'setHomePage', false, 'json', 'Homepage set to ' . $this->request->data['path']);
|
2020-07-14 14:26:11 +02:00
|
|
|
} else {
|
|
|
|
$this->layout = false;
|
2020-03-01 18:05:21 +01:00
|
|
|
}
|
|
|
|
}
|
2021-03-20 13:35:58 +01:00
|
|
|
|
|
|
|
public function eventIndexColumnToggle($columnName)
|
|
|
|
{
|
|
|
|
if (!$this->request->is('post')) {
|
|
|
|
throw new MethodNotAllowedException(__('Expecting POST request.'));
|
|
|
|
}
|
|
|
|
|
|
|
|
$hideColumns = $this->UserSetting->getValueForUser($this->Auth->user()['id'], 'event_index_hide_columns');
|
|
|
|
if ($hideColumns === null) {
|
|
|
|
$hideColumns = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (($key = array_search($columnName, $hideColumns, true)) !== false) {
|
|
|
|
unset($hideColumns[$key]);
|
|
|
|
$hideColumns = array_values($hideColumns);
|
|
|
|
} else {
|
|
|
|
$hideColumns[] = $columnName;
|
|
|
|
}
|
|
|
|
|
2022-02-19 13:39:47 +01:00
|
|
|
$setting = [
|
|
|
|
'UserSetting' => [
|
2021-03-20 13:35:58 +01:00
|
|
|
'user_id' => $this->Auth->user()['id'],
|
|
|
|
'setting' => 'event_index_hide_columns',
|
2022-02-19 13:39:47 +01:00
|
|
|
'value' => $hideColumns,
|
|
|
|
]
|
|
|
|
];
|
2021-03-20 13:35:58 +01:00
|
|
|
$this->UserSetting->setSetting($this->Auth->user(), $setting);
|
|
|
|
return $this->RestResponse->saveSuccessResponse('UserSettings', 'eventIndexColumnToggle', false, 'json', 'Column visibility switched');
|
|
|
|
}
|
2019-09-25 11:50:54 +02:00
|
|
|
}
|