Merge branch 'develop'
commit
0c320f7d9c
|
@ -22,20 +22,29 @@ class AuthKeysController extends AppController
|
|||
{
|
||||
$currentUser = $this->ACL->getUser();
|
||||
$conditions = [];
|
||||
$userId = $this->request->getQuery('Users_id');
|
||||
if (!empty($userId)) {
|
||||
$conditions['AND']['Users.id'] = $userId;
|
||||
}
|
||||
|
||||
if (empty($currentUser['role']['perm_community_admin'])) {
|
||||
$conditions['Users.organisation_id'] = $currentUser['organisation_id'];
|
||||
if (empty($currentUser['role']['perm_org_admin'])) {
|
||||
$conditions['Users.id'] = $currentUser['id'];
|
||||
}
|
||||
}
|
||||
$this->CRUD->index([
|
||||
$indexOptions = [
|
||||
'filters' => $this->filterFields,
|
||||
'quickFilters' => $this->quickFilterFields,
|
||||
'contain' => $this->containFields,
|
||||
'exclude_fields' => ['authkey'],
|
||||
'conditions' => $conditions,
|
||||
'hidden' => []
|
||||
]);
|
||||
];
|
||||
if (!empty($userId)) {
|
||||
$indexOptions['action_query_strings'] = ['Users.id' => $userId];
|
||||
}
|
||||
$this->CRUD->index($indexOptions);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
return $responsePayload;
|
||||
|
@ -46,13 +55,7 @@ class AuthKeysController extends AppController
|
|||
public function delete($id)
|
||||
{
|
||||
$currentUser = $this->ACL->getUser();
|
||||
$conditions = [];
|
||||
if (empty($currentUser['role']['perm_community_admin'])) {
|
||||
$conditions['Users.organisation_id'] = $currentUser['organisation_id'];
|
||||
if (empty($currentUser['role']['perm_org_admin'])) {
|
||||
$conditions['Users.id'] = $currentUser['id'];
|
||||
}
|
||||
}
|
||||
$conditions = $this->AuthKeys->buildUserConditions($currentUser);
|
||||
$this->CRUD->delete($id, ['conditions' => $conditions, 'contain' => 'Users']);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
|
@ -67,21 +70,14 @@ class AuthKeysController extends AppController
|
|||
$validUsers = [];
|
||||
$userConditions = [];
|
||||
$currentUser = $this->ACL->getUser();
|
||||
if (empty($currentUser['role']['perm_community_admin'])) {
|
||||
if (empty($currentUser['role']['perm_org_admin'])) {
|
||||
$userConditions['id'] = $currentUser['id'];
|
||||
} else {
|
||||
$role_ids = $this->Users->Roles->find()->where(['perm_admin' => 0, 'perm_community_admin', 'perm_org_admin' => 0])->all()->extract('id')->toList();
|
||||
$userConditions['organisation_id'] = $currentUser['organisation_id'];
|
||||
$userConditions['OR'] = [
|
||||
['role_id IN' => $role_ids],
|
||||
['id' => $currentUser['id']],
|
||||
];
|
||||
}
|
||||
}
|
||||
$conditions = $this->AuthKeys->buildUserConditions($currentUser);
|
||||
$userId = $this->request->getQuery('Users_id');
|
||||
$users = $this->Users->find('list');
|
||||
if (!empty($userConditions)) {
|
||||
$users->where($userConditions);
|
||||
if (!empty($conditions)) {
|
||||
$users->where($conditions);
|
||||
}
|
||||
if (!empty($userId)) {
|
||||
$users->where(['Users.id' => $userId]);
|
||||
}
|
||||
$users = $users->order(['username' => 'asc'])->all()->toArray();
|
||||
$this->CRUD->add([
|
||||
|
|
|
@ -363,11 +363,19 @@ class ACLComponent extends Component
|
|||
return true;
|
||||
}
|
||||
|
||||
if ($user['role']['perm_community_admin']) {
|
||||
return false; // org_admins cannot edit admins
|
||||
$this->Roles = TableRegistry::get('Roles');
|
||||
$validRoles = [];
|
||||
if (!$currentUser['role']['perm_community_admin']) {
|
||||
if ($currentUser['role']['perm_group_admin']) {
|
||||
$validRoles = $this->Roles->find('list')->select(['id', 'name'])->order(['name' => 'asc'])->where(['perm_community_admin' => 0, 'perm_group_admin' => 0, 'perm_admin' => 0])->all()->toArray();
|
||||
} else {
|
||||
$validRoles = $this->Roles->find('list')->select(['id', 'name'])->order(['name' => 'asc'])->where(['perm_community_admin' => 0, 'perm_group_admin' => 0, 'perm_org_admin' => 0, 'perm_admin' => 0])->all()->toArray();
|
||||
}
|
||||
} else {
|
||||
$validRoles = $this->Roles->find('list')->order(['name' => 'asc'])->all()->toArray();
|
||||
}
|
||||
if ($currentUser['role']['perm_org_admin'] && $user['role']['perm_group_admin']) {
|
||||
return false; // org_admins cannot edit group_admin
|
||||
if (!in_array($user['role_id'], array_keys($validRoles)) && $currentUser['id'] != $user['id']) {
|
||||
return false;
|
||||
}
|
||||
if ($currentUser['role']['perm_group_admin']) {
|
||||
$this->OrgGroups = TableRegistry::get('OrgGroups');
|
||||
|
@ -378,9 +386,6 @@ class ACLComponent extends Component
|
|||
if (!$currentUser['role']['perm_org_admin']) {
|
||||
return false;
|
||||
} else {
|
||||
if ($currentUser['id'] == $user['id']) {
|
||||
return true;
|
||||
}
|
||||
if ($currentUser['organisation_id'] === $user['organisation_id']) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -272,6 +272,10 @@ class CRUDComponent extends Component
|
|||
$this->Controller->set('model', $this->Table);
|
||||
$this->Controller->set('data', $data);
|
||||
$this->Controller->set('embedInModal', $embedInModal);
|
||||
if (!empty($options['action_query_strings'])) {
|
||||
$this->Controller->set('action_query_strings', $options['action_query_strings']);
|
||||
|
||||
}
|
||||
$this->Controller->set('skipTableToolbar', $skipTableToolbar);
|
||||
}
|
||||
}
|
||||
|
@ -465,51 +469,73 @@ class CRUDComponent extends Component
|
|||
}
|
||||
}
|
||||
$data = $this->Table->patchEntity($data, $input, $patchEntityParams);
|
||||
$break = false;
|
||||
if (isset($params['beforeSave'])) {
|
||||
$data = $params['beforeSave']($data);
|
||||
try {
|
||||
$data = $params['beforeSave']($data);
|
||||
} catch (\Exception $e) {
|
||||
$message = $e->getMessage();
|
||||
$break = true;
|
||||
$this->__raiseErrorToUser(__('Could not save {0}.', $this->ObjectAlias), $message);
|
||||
}
|
||||
if ($data === false) {
|
||||
throw new NotFoundException(__('Could not save {0} due to the input failing to meet expectations. Your input is bad and you should feel bad.', $this->ObjectAlias));
|
||||
$break = true;
|
||||
$this->__raiseErrorToUser(__('Could not save {0} due to the input failing to meet expectations. Your input is bad and you should feel bad.', $this->ObjectAlias));
|
||||
}
|
||||
}
|
||||
$savedData = $this->Table->save($data);
|
||||
if ($savedData !== false) {
|
||||
if (isset($params['afterSave'])) {
|
||||
$params['afterSave']($data);
|
||||
}
|
||||
$message = __('{0} added.', $this->ObjectAlias);
|
||||
if ($this->Controller->ParamHandler->isRest()) {
|
||||
$this->Controller->restResponsePayload = $this->RestResponse->viewData($savedData, 'json');
|
||||
} else if ($this->Controller->ParamHandler->isAjax()) {
|
||||
if (!empty($params['displayOnSuccess'])) {
|
||||
$displayOnSuccess = $this->renderViewInVariable($params['displayOnSuccess'], ['entity' => $data]);
|
||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxSuccessResponse($this->ObjectAlias, 'add', $savedData, $message, ['displayOnSuccess' => $displayOnSuccess]);
|
||||
} else {
|
||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxSuccessResponse($this->ObjectAlias, 'add', $savedData, $message);
|
||||
if (!$break) {
|
||||
$savedData = $this->Table->save($data);
|
||||
if ($savedData !== false) {
|
||||
if (isset($params['afterSave'])) {
|
||||
try {
|
||||
$data = $params['afterSave']($data);
|
||||
} catch (\Exception $e) {
|
||||
$message = $e->getMessage();
|
||||
$break = true;
|
||||
$this->__raiseErrorToUser(__('Saved {0}, but could not execute post-save actions.', $this->ObjectAlias), $message);
|
||||
}
|
||||
if ($data === false) {
|
||||
$break = true;
|
||||
$this->__raiseErrorToUser(__('Saved {0}, but the post-save actons failed.', $this->ObjectAlias));
|
||||
}
|
||||
}
|
||||
if (!$break) {
|
||||
$message = __('{0} added.', $this->ObjectAlias);
|
||||
if ($this->Controller->ParamHandler->isRest()) {
|
||||
$this->Controller->restResponsePayload = $this->RestResponse->viewData($savedData, 'json');
|
||||
} else if ($this->Controller->ParamHandler->isAjax()) {
|
||||
if (!empty($params['displayOnSuccess'])) {
|
||||
$displayOnSuccess = $this->renderViewInVariable($params['displayOnSuccess'], ['entity' => $data]);
|
||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxSuccessResponse($this->ObjectAlias, 'add', $savedData, $message, ['displayOnSuccess' => $displayOnSuccess]);
|
||||
} else {
|
||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxSuccessResponse($this->ObjectAlias, 'add', $savedData, $message);
|
||||
}
|
||||
} else {
|
||||
$this->Controller->Flash->success($message);
|
||||
if (empty($params['redirect'])) {
|
||||
$this->Controller->redirect(['action' => 'view', $data->id]);
|
||||
} else {
|
||||
$this->Controller->redirect($params['redirect']);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->Controller->Flash->success($message);
|
||||
if (empty($params['redirect'])) {
|
||||
$this->Controller->redirect(['action' => 'view', $data->id]);
|
||||
$this->Controller->isFailResponse = true;
|
||||
$validationErrors = $data->getErrors();
|
||||
$validationMessage = $this->prepareValidationMessage($validationErrors);
|
||||
$message = __(
|
||||
'{0} could not be added.{1}',
|
||||
$this->ObjectAlias,
|
||||
empty($validationMessage) ? '' : PHP_EOL . __('Reason: {0}', $validationMessage)
|
||||
);
|
||||
if ($this->Controller->ParamHandler->isRest()) {
|
||||
$this->Controller->restResponsePayload = $this->RestResponse->viewData($message, 'json');
|
||||
} else if ($this->Controller->ParamHandler->isAjax()) {
|
||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxFailResponse($this->ObjectAlias, 'add', $data, $message, $validationErrors);
|
||||
} else {
|
||||
$this->Controller->redirect($params['redirect']);
|
||||
$this->Controller->Flash->error($message);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->Controller->isFailResponse = true;
|
||||
$validationErrors = $data->getErrors();
|
||||
$validationMessage = $this->prepareValidationMessage($validationErrors);
|
||||
$message = __(
|
||||
'{0} could not be added.{1}',
|
||||
$this->ObjectAlias,
|
||||
empty($validationMessage) ? '' : PHP_EOL . __('Reason: {0}', $validationMessage)
|
||||
);
|
||||
if ($this->Controller->ParamHandler->isRest()) {
|
||||
$this->Controller->restResponsePayload = $this->RestResponse->viewData($message, 'json');
|
||||
} else if ($this->Controller->ParamHandler->isAjax()) {
|
||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxFailResponse($this->ObjectAlias, 'add', $data, $message, $validationErrors);
|
||||
} else {
|
||||
$this->Controller->Flash->error($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($params['fields'])) {
|
||||
|
@ -723,6 +749,18 @@ class CRUDComponent extends Component
|
|||
return $input;
|
||||
}
|
||||
|
||||
private function __raiseErrorToUser($title, $message = null)
|
||||
{
|
||||
if ($this->Controller->ParamHandler->isRest()) {
|
||||
$this->Controller->restResponsePayload = $this->RestResponse->viewData($message, 'json');
|
||||
} else if ($this->Controller->ParamHandler->isAjax()) {
|
||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxFailResponse($this->ObjectAlias, 'edit', [], $title, ['Custom checks' => ['Custom checks' => $message]]);
|
||||
} else {
|
||||
$this->Controller->isFailResponse = true;
|
||||
$this->Controller->Flash->error($message);
|
||||
}
|
||||
}
|
||||
|
||||
public function edit(int $id, array $params = []): void
|
||||
{
|
||||
if (empty($id)) {
|
||||
|
@ -800,54 +838,79 @@ class CRUDComponent extends Component
|
|||
}
|
||||
}
|
||||
$data = $this->Table->patchEntity($data, $input, $patchEntityParams);
|
||||
$break = false;
|
||||
if (isset($params['beforeSave'])) {
|
||||
$data = $params['beforeSave']($data);
|
||||
try {
|
||||
$data = $params['beforeSave']($data);
|
||||
} catch (\Exception $e) {
|
||||
$message = $e->getMessage();
|
||||
$break = true;
|
||||
$this->__raiseErrorToUser(__('Could not save {0}.', $this->ObjectAlias), $message);
|
||||
}
|
||||
if ($data === false) {
|
||||
throw new NotFoundException(__('Could not save {0} due to the input failing to meet expectations. Your input is bad and you should feel bad.', $this->ObjectAlias));
|
||||
$break = true;
|
||||
$this->__raiseErrorToUser(__('Could not save {0} due to the input failing to meet expectations.', $this->ObjectAlias), __('Your input is bad and you should feel bad.'));
|
||||
}
|
||||
}
|
||||
$savedData = $this->Table->save($data);
|
||||
if ($savedData !== false) {
|
||||
if ($metaFieldsEnabled && !empty($metaFieldsToDelete)) {
|
||||
foreach ($metaFieldsToDelete as $k => $v) {
|
||||
if ($v === null) {
|
||||
unset($metaFieldsToDelete[$k]);
|
||||
if (!$break) {
|
||||
$savedData = $this->Table->save($data);
|
||||
if ($savedData !== false) {
|
||||
if ($metaFieldsEnabled && !empty($metaFieldsToDelete)) {
|
||||
foreach ($metaFieldsToDelete as $k => $v) {
|
||||
if ($v === null) {
|
||||
unset($metaFieldsToDelete[$k]);
|
||||
}
|
||||
}
|
||||
if (!empty($metaFieldsToDelete)) {
|
||||
$this->Table->MetaFields->unlink($savedData, $metaFieldsToDelete);
|
||||
}
|
||||
}
|
||||
if (!empty($metaFieldsToDelete)) {
|
||||
$this->Table->MetaFields->unlink($savedData, $metaFieldsToDelete);
|
||||
$break = false;
|
||||
if (isset($params['afterSave'])) {
|
||||
if (isset($params['afterSave'])) {
|
||||
try {
|
||||
$data = $params['afterSave']($data);
|
||||
} catch (\Exception $e) {
|
||||
$message = $e->getMessage();
|
||||
$break = true;
|
||||
$this->__raiseErrorToUser(__('Saved {0} `{1}`, but could not execute post-save actions.', $this->ObjectAlias, $savedData->{$this->Table->getDisplayField()}), $message);
|
||||
}
|
||||
if ($data === false) {
|
||||
$break = true;
|
||||
$this->__raiseErrorToUser(__('Saved {0} `{1}`, but the post-save actons failed.', $this->ObjectAlias, $savedData->{$this->Table->getDisplayField()}));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$break) {
|
||||
$message = __('{0} `{1}` updated.', $this->ObjectAlias, $savedData->{$this->Table->getDisplayField()});
|
||||
if ($this->Controller->ParamHandler->isRest()) {
|
||||
$this->Controller->restResponsePayload = $this->RestResponse->viewData($savedData, 'json');
|
||||
} else if ($this->Controller->ParamHandler->isAjax()) {
|
||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxSuccessResponse($this->ObjectAlias, 'edit', $savedData, $message);
|
||||
} else {
|
||||
$this->Controller->Flash->success($message);
|
||||
if (empty($params['redirect'])) {
|
||||
$this->Controller->redirect(['action' => 'view', $id]);
|
||||
} else {
|
||||
$this->Controller->redirect($params['redirect']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($params['afterSave'])) {
|
||||
$params['afterSave']($data);
|
||||
}
|
||||
$message = __('{0} `{1}` updated.', $this->ObjectAlias, $savedData->{$this->Table->getDisplayField()});
|
||||
if ($this->Controller->ParamHandler->isRest()) {
|
||||
$this->Controller->restResponsePayload = $this->RestResponse->viewData($savedData, 'json');
|
||||
} else if ($this->Controller->ParamHandler->isAjax()) {
|
||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxSuccessResponse($this->ObjectAlias, 'edit', $savedData, $message);
|
||||
} else {
|
||||
$this->Controller->Flash->success($message);
|
||||
if (empty($params['redirect'])) {
|
||||
$this->Controller->redirect(['action' => 'view', $id]);
|
||||
$validationErrors = $data->getErrors();
|
||||
$validationMessage = $this->prepareValidationError($data);
|
||||
$message = __(
|
||||
'{0} could not be modified.{1}',
|
||||
$this->ObjectAlias,
|
||||
empty($validationMessage) ? '' : PHP_EOL . __('Reason: {0}', $validationMessage)
|
||||
);
|
||||
if ($this->Controller->ParamHandler->isRest()) {
|
||||
} else if ($this->Controller->ParamHandler->isAjax()) {
|
||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxFailResponse($this->ObjectAlias, 'edit', $data, $message, $validationErrors);
|
||||
} else {
|
||||
$this->Controller->redirect($params['redirect']);
|
||||
$this->Controller->Flash->error($message);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$validationErrors = $data->getErrors();
|
||||
$validationMessage = $this->prepareValidationError($data);
|
||||
$message = __(
|
||||
'{0} could not be modified.{1}',
|
||||
$this->ObjectAlias,
|
||||
empty($validationMessage) ? '' : PHP_EOL . __('Reason: {0}', $validationMessage)
|
||||
);
|
||||
if ($this->Controller->ParamHandler->isRest()) {
|
||||
} else if ($this->Controller->ParamHandler->isAjax()) {
|
||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxFailResponse($this->ObjectAlias, 'edit', $data, $message, $validationErrors);
|
||||
} else {
|
||||
$this->Controller->Flash->error($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($params['fields'])) {
|
||||
|
@ -1106,6 +1169,7 @@ class CRUDComponent extends Component
|
|||
throw new NotFoundException(__('Could not save {0} due to the input failing to meet expectations. Your input is bad and you should feel bad.', $this->ObjectAlias));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$exceptionMessage = $e->getMessage();
|
||||
$entity = false;
|
||||
}
|
||||
}
|
||||
|
@ -1123,7 +1187,7 @@ class CRUDComponent extends Component
|
|||
$isBulk,
|
||||
__('{0} deleted.', $this->ObjectAlias),
|
||||
__('All selected {0} have been deleted.', Inflector::pluralize($this->ObjectAlias)),
|
||||
__('Could not delete {0}.', $this->ObjectAlias),
|
||||
$exceptionMessage ?? __('Could not delete {0}.', $this->ObjectAlias),
|
||||
__(
|
||||
'{0} / {1} {2} have been deleted.',
|
||||
$bulkSuccesses,
|
||||
|
@ -1305,7 +1369,7 @@ class CRUDComponent extends Component
|
|||
if (!empty($additionalData['redirect'])) { // If a redirection occurs, we need to make sure the flash message gets displayed
|
||||
$this->Controller->Flash->error($message);
|
||||
}
|
||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxFailResponse($this->ObjectAlias, $action, $data, $message, !is_null($errors) ? $errors : $data->getErrors());
|
||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxFailResponse($this->ObjectAlias, $action, $data, $message, $errors);
|
||||
} else {
|
||||
$this->Controller->Flash->error($message);
|
||||
$this->Controller->redirect($this->Controller->referer());
|
||||
|
|
|
@ -440,14 +440,19 @@ class RestResponseComponent extends Component
|
|||
return $this->viewData($response);
|
||||
}
|
||||
|
||||
public function ajaxFailResponse($ObjectAlias, $action, $entity, $message, $errors = [])
|
||||
public function ajaxFailResponse($ObjectAlias, $action, $entity = null, $message, $errors = [], $description = '')
|
||||
{
|
||||
$action = $this->__dissectAdminRouting($action);
|
||||
$entity = is_array($entity) ? $entity : $entity->toArray();
|
||||
if (empty($entity)) {
|
||||
$entity = [];
|
||||
} else {
|
||||
$entity = is_array($entity) ? $entity : $entity->toArray();
|
||||
}
|
||||
$response = [
|
||||
'success' => false,
|
||||
'message' => $message,
|
||||
'errors' => $errors,
|
||||
'description' => $description,
|
||||
'url' => !empty($entity['id']) ? $this->__generateURL($action, $ObjectAlias, $entity['id']) : ''
|
||||
];
|
||||
return $this->viewData($response);
|
||||
|
|
|
@ -78,7 +78,15 @@ class RolesController extends AppController
|
|||
|
||||
public function delete($id)
|
||||
{
|
||||
$this->CRUD->delete($id);
|
||||
$this->CRUD->delete($id, [
|
||||
'beforeSave' => function ($data) {
|
||||
$userCount = $this->Roles->Users->find()->where(['role_id' => $data['id']])->count();
|
||||
if ($userCount > 0) {
|
||||
throw new ForbiddenException(__('You cannot delete a role that has users assigned to it.'));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
]);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
return $responsePayload;
|
||||
|
|
|
@ -79,6 +79,10 @@ class UserSettingsController extends AppController
|
|||
if (empty($currentUser['role']['perm_community_admin'])) {
|
||||
$data['user_id'] = $currentUser->id;
|
||||
}
|
||||
$validationResult = $this->UserSettings->validateUserSetting($data, $currentUser);
|
||||
if (!$validationResult !== true) {
|
||||
throw new MethodNotAllowedException(__('You cannot create the given user setting. Reason: {0}', $validationResult));
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
]);
|
||||
|
@ -131,6 +135,10 @@ class UserSettingsController extends AppController
|
|||
if ($data['user_id'] != $entity->user_id) {
|
||||
throw new MethodNotAllowedException(__('You cannot assign the setting to a different user.'));
|
||||
}
|
||||
$validationResult = $this->UserSettings->validateUserSetting($data);
|
||||
if ($validationResult !== true) {
|
||||
throw new MethodNotAllowedException(__('Setting value: {0}', $validationResult));
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
]);
|
||||
|
@ -235,9 +243,10 @@ class UserSettingsController extends AppController
|
|||
public function saveMyBookmark()
|
||||
{
|
||||
if (!$this->request->is('get')) {
|
||||
$result = $this->UserSettings->saveBookmark($this->ACL->getUser(), $this->request->getData());
|
||||
$errors = null;
|
||||
$result = $this->UserSettings->saveBookmark($this->ACL->getUser(), $this->request->getData(), $errors);
|
||||
$success = !empty($result);
|
||||
$message = $success ? __('Bookmark saved') : __('Could not save bookmark');
|
||||
$message = $success ? __('Bookmark saved') : ($errors ?? __('Could not save bookmark'));
|
||||
$this->CRUD->setResponseForController('saveBookmark', $success, $message, $result);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
|
|
|
@ -86,10 +86,10 @@ class UsersController extends AppController
|
|||
$individual_ids = [];
|
||||
if (!$currentUser['role']['perm_community_admin']) {
|
||||
if ($currentUser['role']['perm_group_admin']) {
|
||||
$validRoles = $this->Users->Roles->find('list')->select(['id', 'name'])->order(['name' => 'asc'])->where(['perm_community_admin' => 0, 'perm_group_admin' => 0])->all()->toArray();
|
||||
$validRoles = $this->Users->Roles->find('list')->select(['id', 'name'])->order(['name' => 'asc'])->where(['perm_community_admin' => 0, 'perm_group_admin' => 0, 'perm_admin' => 0])->all()->toArray();
|
||||
$individual_ids = $this->Users->Individuals->find('aligned', ['organisation_id' => $currentUser['organisation_id']])->all()->extract('id')->toArray();
|
||||
} else {
|
||||
$validRoles = $this->Users->Roles->find('list')->select(['id', 'name'])->order(['name' => 'asc'])->where(['perm_community_admin' => 0, 'perm_group_admin' => 0, 'perm_org_admin' => 0])->all()->toArray();
|
||||
$validRoles = $this->Users->Roles->find('list')->select(['id', 'name'])->order(['name' => 'asc'])->where(['perm_community_admin' => 0, 'perm_group_admin' => 0, 'perm_org_admin' => 0, 'perm_admin' => 0])->all()->toArray();
|
||||
|
||||
}
|
||||
if (empty($individual_ids)) {
|
||||
|
@ -247,10 +247,10 @@ class UsersController extends AppController
|
|||
$validOrgIds = [];
|
||||
if (!$currentUser['role']['perm_community_admin']) {
|
||||
if ($currentUser['role']['perm_group_admin']) {
|
||||
$validRoles = $this->Users->Roles->find('list')->select(['id', 'name'])->order(['name' => 'asc'])->where(['perm_community_admin' => 0, 'perm_group_admin' => 0])->all()->toArray();
|
||||
$validRoles = $this->Users->Roles->find('list')->select(['id', 'name'])->order(['name' => 'asc'])->where(['perm_community_admin' => 0, 'perm_group_admin' => 0, 'perm_admin' => 0])->all()->toArray();
|
||||
$validOrgIds = $this->Users->Organisations->OrgGroups->getGroupOrgIdsForUser($currentUser);
|
||||
} else {
|
||||
$validRoles = $this->Users->Roles->find('list')->select(['id', 'name'])->order(['name' => 'asc'])->where(['perm_community_admin' => 0, 'perm_group_admin' => 0, 'perm_org_admin' => 0])->all()->toArray();
|
||||
$validRoles = $this->Users->Roles->find('list')->select(['id', 'name'])->order(['name' => 'asc'])->where(['perm_community_admin' => 0, 'perm_group_admin' => 0, 'perm_org_admin' => 0, 'perm_admin' => 0])->all()->toArray();
|
||||
}
|
||||
} else {
|
||||
$validRoles = $this->Users->Roles->find('list')->order(['name' => 'asc'])->all()->toArray();
|
||||
|
@ -320,10 +320,13 @@ class UsersController extends AppController
|
|||
}
|
||||
return $data;
|
||||
};
|
||||
$params['beforeSave'] = function ($data) use ($currentUser, $validRoles) {
|
||||
$params['beforeSave'] = function ($data) use ($currentUser, $validRoles, $validOrgIds) {
|
||||
if (!in_array($data['role_id'], array_keys($validRoles)) && $this->ACL->getUser()['id'] != $data['id']) {
|
||||
throw new MethodNotAllowedException(__('You cannot assign the chosen role to a user.'));
|
||||
}
|
||||
if (!in_array($data['organisation_id'], $validOrgIds)) {
|
||||
throw new MethodNotAllowedException(__('You cannot assign the chosen organisation to a user.'));
|
||||
}
|
||||
return $data;
|
||||
};
|
||||
}
|
||||
|
@ -487,7 +490,7 @@ class UsersController extends AppController
|
|||
{
|
||||
$editingAnotherUser = false;
|
||||
$currentUser = $this->ACL->getUser();
|
||||
if ((empty($currentUser['role']['perm_community_admin']) && empty($currentUser['role']['perm_group_admin'])) || $user_id == $currentUser->id) {
|
||||
if ((empty($currentUser['role']['perm_community_admin']) && empty($currentUser['role']['perm_group_admin'])) || empty($user_id) || $user_id == $currentUser->id) {
|
||||
$user = $currentUser;
|
||||
} else {
|
||||
$user = $this->Users->get($user_id, [
|
||||
|
|
|
@ -93,4 +93,36 @@ class AuthKeysTable extends AppTable
|
|||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
public function buildUserConditions($currentUser)
|
||||
{
|
||||
$conditions = [];
|
||||
$validOrgs = $this->Users->getValidOrgsForUser($currentUser);
|
||||
if (empty($currentUser['role']['perm_community_admin'])) {
|
||||
$conditions['Users.organisation_id IN'] = $validOrgs;
|
||||
if (empty($currentUser['role']['perm_group_admin'])) {
|
||||
if (empty($currentUser['role']['perm_org_admin'])) {
|
||||
$conditions['Users.id'] = $currentUser['id'];
|
||||
} else {
|
||||
$role_ids = $this->Users->Roles->find()->where(['perm_admin' => 0, 'perm_community_admin' => 0, 'perm_org_admin' => 0, 'perm_group_admin' => 0])->all()->extract('id')->toList();
|
||||
$conditions['Users.organisation_id'] = $currentUser['organisation_id'];
|
||||
$subConditions = [
|
||||
['Users.id' => $currentUser['id']]
|
||||
];
|
||||
if (!empty($role_ids)) {
|
||||
$subConditions[] = ['Users.role_id IN' => $role_ids];
|
||||
}
|
||||
$conditions['OR'] = $subConditions;
|
||||
}
|
||||
} else {
|
||||
$conditions['Users.group_id'] = $currentUser['group_id'];
|
||||
$role_ids = $this->Users->Roles->find()->where(['perm_admin' => 0, 'perm_community_admin' => 0, 'perm_group_admin' => 0])->all()->extract('id')->toList();
|
||||
$conditions['OR'] = [
|
||||
['Users.id' => $currentUser['id']],
|
||||
['Users.role_id IN' => $role_ids]
|
||||
];
|
||||
}
|
||||
}
|
||||
return $conditions;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,18 +163,22 @@ class BaseSettingsProvider
|
|||
$setting['error'] = false;
|
||||
if (!$skipValidation) {
|
||||
$validationResult = true;
|
||||
if (!isset($setting['value'])) {
|
||||
$validationResult = $this->settingValidator->testEmptyBecomesDefault(null, $setting);
|
||||
} else if (isset($setting['test'])) {
|
||||
$setting['value'] = $setting['value'] ?? '';
|
||||
$validationResult = $this->evaluateFunctionForSetting($setting['test'], $setting);
|
||||
}
|
||||
if ($validationResult !== true) {
|
||||
$setting['severity'] = $setting['severity'] ?? 'warning';
|
||||
if (!in_array($setting['severity'], $this->severities)) {
|
||||
$setting['severity'] = 'warning';
|
||||
if (empty($setting['value']) && !empty($setting['empty'])) {
|
||||
$validationResult = true;
|
||||
} else {
|
||||
if (!isset($setting['value'])) {
|
||||
$validationResult = $this->settingValidator->testEmptyBecomesDefault(null, $setting);
|
||||
} else if (isset($setting['test'])) {
|
||||
$setting['value'] = $setting['value'] ?? '';
|
||||
$validationResult = $this->evaluateFunctionForSetting($setting['test'], $setting);
|
||||
}
|
||||
if ($validationResult !== true) {
|
||||
$setting['severity'] = $setting['severity'] ?? 'warning';
|
||||
if (!in_array($setting['severity'], $this->severities)) {
|
||||
$setting['severity'] = 'warning';
|
||||
}
|
||||
$setting['errorMessage'] = $validationResult;
|
||||
}
|
||||
$setting['errorMessage'] = $validationResult;
|
||||
}
|
||||
$setting['error'] = $validationResult !== true ? true : false;
|
||||
}
|
||||
|
|
|
@ -136,15 +136,19 @@ class CerebrateSettingsProvider extends BaseSettingsProvider
|
|||
'Proxy' => [
|
||||
'Proxy.host' => [
|
||||
'name' => __('Host'),
|
||||
'severity' => 'info',
|
||||
'type' => 'string',
|
||||
'description' => __('The hostname of an HTTP proxy for outgoing sync requests. Leave empty to not use a proxy.'),
|
||||
'test' => 'testHostname',
|
||||
'empty' => true
|
||||
],
|
||||
'Proxy.port' => [
|
||||
'name' => __('Port'),
|
||||
'severity' => 'info',
|
||||
'type' => 'integer',
|
||||
'description' => __('The TCP port for the HTTP proxy.'),
|
||||
'test' => 'testForRangeXY',
|
||||
'empty' => true
|
||||
],
|
||||
'Proxy.user' => [
|
||||
'name' => __('User'),
|
||||
|
@ -152,6 +156,7 @@ class CerebrateSettingsProvider extends BaseSettingsProvider
|
|||
'description' => __('The authentication username for the HTTP proxy.'),
|
||||
'default' => 'admin',
|
||||
'dependsOn' => 'proxy.host',
|
||||
'empty' => true
|
||||
],
|
||||
'Proxy.password' => [
|
||||
'name' => __('Password'),
|
||||
|
@ -159,6 +164,7 @@ class CerebrateSettingsProvider extends BaseSettingsProvider
|
|||
'description' => __('The authentication password for the HTTP proxy.'),
|
||||
'default' => '',
|
||||
'dependsOn' => 'proxy.host',
|
||||
'empty' => true
|
||||
],
|
||||
],
|
||||
],
|
||||
|
@ -338,6 +344,17 @@ class CerebrateSettingsProvider extends BaseSettingsProvider
|
|||
],
|
||||
]
|
||||
],
|
||||
'Restrictions' => [
|
||||
'Allowed bookmark domains' => [
|
||||
'security.restrictions.allowed_bookmark_domains' => [
|
||||
'name' => __('Allowed bookmark domains'),
|
||||
'type' => 'string',
|
||||
'severity' => 'info',
|
||||
'description' => __('Comma separated list of allowed bookmark domains. Leave empty to allow all domains.'),
|
||||
'default' => '',
|
||||
],
|
||||
],
|
||||
],
|
||||
'Development' => [
|
||||
'Debugging' => [
|
||||
'debug' => [
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace App\Model\Table;
|
|||
use App\Model\Table\AppTable;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\Validation\Validator;
|
||||
use Cake\Core\Configure;
|
||||
|
||||
require_once(APP . 'Model' . DS . 'Table' . DS . 'SettingProviders' . DS . 'UserSettingsProvider.php');
|
||||
use App\Settings\SettingsProvider\UserSettingsProvider;
|
||||
|
@ -94,14 +95,37 @@ class UserSettingsTable extends AppTable
|
|||
return $savedData;
|
||||
}
|
||||
|
||||
public function saveBookmark($user, $data)
|
||||
public function saveBookmark($user, $data, &$message = null)
|
||||
{
|
||||
$setting = $this->getSettingByName($user, $this->BOOKMARK_SETTING_NAME);
|
||||
$fieldsToCheck = [
|
||||
'bookmark_label' => __('Label'),
|
||||
'bookmark_name' => __('Name'),
|
||||
'bookmark_url' => __('URL')
|
||||
];
|
||||
foreach ($fieldsToCheck as $field => $fieldName) {
|
||||
if (empty($data[$field])) {
|
||||
$message = __('Please fill in all fields, {0} missing.', $fieldName);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (empty($data['bookmark_label']) || empty($data['bookmark_name']) || empty($data['bookmark_url'])) {
|
||||
|
||||
return null;
|
||||
}
|
||||
$bookmarkData = [
|
||||
'label' => $data['bookmark_label'],
|
||||
'name' => $data['bookmark_name'],
|
||||
'url' => $data['bookmark_url'],
|
||||
];
|
||||
$restricted_domains = Configure::read('security.restrictions.allowed_bookmark_domains');
|
||||
if (!empty($restricted_domains)) {
|
||||
$restricted_domains = explode(',', $restricted_domains);
|
||||
$parsed = parse_url($bookmarkData['url']);
|
||||
if (!empty($parsed['host']) && !in_array($parsed['host'], $restricted_domains)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (is_null($setting)) { // setting not found, create it
|
||||
$bookmarksData = json_encode([$bookmarkData]);
|
||||
$result = $this->createSetting($user, $this->BOOKMARK_SETTING_NAME, $bookmarksData);
|
||||
|
@ -153,4 +177,40 @@ class UserSettingsTable extends AppTable
|
|||
}
|
||||
return $isLocalPath || $isValidURL;
|
||||
}
|
||||
|
||||
public function validateUserSetting($data): bool|string
|
||||
{
|
||||
$errors = [];
|
||||
$json_fields = ['ui.bookmarks'];
|
||||
if (in_array($data['name'], $json_fields)) {
|
||||
$decoded = json_decode($data['value'], true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
return __('Invalid JSON data');
|
||||
}
|
||||
$value = $decoded;
|
||||
} else {
|
||||
$value = $data['value'];
|
||||
}
|
||||
if ($data['name'] === 'ui.bookmarks') {
|
||||
if (array_values($value) !== $value) {
|
||||
$value = [$value];
|
||||
}
|
||||
$restricted_domains = Configure::read('security.restrictions.allowed_bookmark_domains');
|
||||
if (!empty($restricted_domains)) {
|
||||
$restricted_domains = explode(',', $restricted_domains);
|
||||
foreach ($restricted_domains as &$rd) {
|
||||
$rd = trim($rd);
|
||||
}
|
||||
}
|
||||
foreach ($value as $bookmark) {
|
||||
if (!empty($restricted_domains)) {
|
||||
$parsed = parse_url($bookmark['url']);
|
||||
if (!in_array($parsed['host'], $restricted_domains)) {
|
||||
return __('Invalid domain for bookmark. The only domains allowed are: {0}', implode(', ', $restricted_domains));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -221,7 +221,9 @@ class UsersTable extends AppTable
|
|||
'perm_admin' => 1,
|
||||
'perm_community_admin' => 1,
|
||||
'perm_org_admin' => 1,
|
||||
'perm_sync' => 1
|
||||
'perm_sync' => 1,
|
||||
'perm_group_admin' => 1,
|
||||
'perm_meta_field_editor' => 1
|
||||
]);
|
||||
$this->Roles->save($role);
|
||||
$this->Organisations = TableRegistry::get('Organisations');
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"version": "1.25",
|
||||
"version": "1.26",
|
||||
"application": "Cerebrate"
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
|||
'data' => [
|
||||
'type' => 'simple',
|
||||
'text' => __('Add authentication key'),
|
||||
'popover_url' => '/authKeys/add',
|
||||
'reload_url' => $this->request->getRequestTarget()
|
||||
'popover_url' => '/authKeys/add' . ($action_query_strings ? '?' . http_build_query($action_query_strings) : ''),
|
||||
'reload_url' => $this->request->getRequestTarget(),
|
||||
]
|
||||
]
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue