Merge branch 'develop' into add-integration-tests
commit
f48c1a5a17
Binary file not shown.
Binary file not shown.
|
@ -10,22 +10,22 @@ class TagSystem extends AbstractMigration
|
|||
$tags = $this->table('tags_tags');
|
||||
$tags->addColumn('namespace', 'string', [
|
||||
'default' => null,
|
||||
'limit' => 255,
|
||||
'limit' => 191,
|
||||
'null' => true,
|
||||
])
|
||||
->addColumn('predicate', 'string', [
|
||||
'default' => null,
|
||||
'limit' => 255,
|
||||
'limit' => 191,
|
||||
'null' => true,
|
||||
])
|
||||
->addColumn('value', 'string', [
|
||||
'default' => null,
|
||||
'limit' => 255,
|
||||
'limit' => 191,
|
||||
'null' => true,
|
||||
])
|
||||
->addColumn('name', 'string', [
|
||||
'default' => null,
|
||||
'limit' => 255,
|
||||
'limit' => 191,
|
||||
'null' => false,
|
||||
])
|
||||
->addColumn('colour', 'string', [
|
||||
|
@ -66,7 +66,7 @@ class TagSystem extends AbstractMigration
|
|||
])
|
||||
->addColumn('fk_model', 'string', [
|
||||
'default' => null,
|
||||
'limit' => 255,
|
||||
'limit' => 191,
|
||||
'null' => false,
|
||||
'comment' => 'The model name of the entity being tagged'
|
||||
])
|
||||
|
@ -86,4 +86,4 @@ class TagSystem extends AbstractMigration
|
|||
$tagged->addIndex(['tag_id', 'fk_id', 'fk_model'], ['unique' => true])
|
||||
->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,10 +46,10 @@ class TagBehavior extends Behavior
|
|||
$config = $this->getConfig();
|
||||
$tagsAssoc = $config['tagsAssoc'];
|
||||
$taggedAssoc = $config['taggedAssoc'];
|
||||
|
||||
|
||||
$table = $this->_table;
|
||||
$tableAlias = $this->_table->getAlias();
|
||||
|
||||
|
||||
$assocConditions = ['Tagged.fk_model' => $tableAlias];
|
||||
|
||||
if (!$table->hasAssociation('Tagged')) {
|
||||
|
@ -114,7 +114,6 @@ class TagBehavior extends Behavior
|
|||
$property = $this->getConfig('tagsAssoc.propertyName');
|
||||
$options['accessibleFields'][$property] = true;
|
||||
$options['associated']['Tags']['accessibleFields']['id'] = true;
|
||||
|
||||
if (isset($data['tags'])) {
|
||||
if (!empty($data['tags'])) {
|
||||
$data[$property] = $this->normalizeTags($data['tags']);
|
||||
|
@ -131,7 +130,6 @@ class TagBehavior extends Behavior
|
|||
if (!$tag->isNew()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$existingTag = $this->getExistingTag($tag->name);
|
||||
if (!$existingTag) {
|
||||
continue;
|
||||
|
@ -176,15 +174,14 @@ class TagBehavior extends Behavior
|
|||
$result[] = array_merge($common, ['id' => $existingTag->id]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$result[] = array_merge(
|
||||
$common,
|
||||
[
|
||||
'name' => $tagIdentifier,
|
||||
'colour' => '#924da6'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -312,7 +309,7 @@ class TagBehavior extends Behavior
|
|||
$key = 'Tags.' . $finderField;
|
||||
$taggedAlias = 'Tagged';
|
||||
$foreignKey = $this->getConfig('tagsAssoc.foreignKey');
|
||||
|
||||
|
||||
if (!empty($filterValue['AND'])) {
|
||||
$subQuery = $this->buildQuerySnippet($filterValue['AND'], $finderField, $OperatorAND);
|
||||
$modelAlias = $this->_table->getAlias();
|
||||
|
@ -352,4 +349,4 @@ class TagBehavior extends Behavior
|
|||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,6 @@ class AppController extends Controller
|
|||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
|
||||
$this->loadComponent('RequestHandler');
|
||||
$this->loadComponent('Flash');
|
||||
$this->loadComponent('RestResponse');
|
||||
|
|
|
@ -64,8 +64,30 @@ class AuthKeysController extends AppController
|
|||
public function add()
|
||||
{
|
||||
$this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate');
|
||||
$validUsers = [];
|
||||
$userConditions = [];
|
||||
$currentUser = $this->ACL->getUser();
|
||||
if (empty($currentUser['role']['perm_admin'])) {
|
||||
if (empty($currentUser['role']['perm_org_admin'])) {
|
||||
$userConditions['id'] = $currentUser['id'];
|
||||
} else {
|
||||
$role_ids = $this->Users->Roles->find()->where(['perm_admin' => 0])->all()->extract('id')->toList();
|
||||
$userConditions['role_id IN'] = $role_ids;
|
||||
}
|
||||
}
|
||||
$users = $this->Users->find('list');
|
||||
if (!empty($userConditions)) {
|
||||
$users->where($userConditions);
|
||||
}
|
||||
$users = $users->order(['username' => 'asc'])->all()->toList();
|
||||
$this->CRUD->add([
|
||||
'displayOnSuccess' => 'authkey_display'
|
||||
'displayOnSuccess' => 'authkey_display',
|
||||
'beforeSave' => function($data) use ($users) {
|
||||
if (!in_array($data['user_id'], array_keys($users))) {
|
||||
return false;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
]);
|
||||
$responsePayload = $this->CRUD->getResponsePayload([
|
||||
'displayOnSuccess' => 'authkey_display'
|
||||
|
@ -75,9 +97,7 @@ class AuthKeysController extends AppController
|
|||
}
|
||||
$this->loadModel('Users');
|
||||
$dropdownData = [
|
||||
'user' => $this->Users->find('list', [
|
||||
'sort' => ['username' => 'asc']
|
||||
])
|
||||
'user' => $users
|
||||
];
|
||||
$this->set(compact('dropdownData'));
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ class ACLComponent extends Component
|
|||
'view' => ['perm_admin']
|
||||
],
|
||||
'EncryptionKeys' => [
|
||||
'view' => ['*'],
|
||||
'add' => ['*'],
|
||||
'edit' => ['*'],
|
||||
'delete' => ['*'],
|
||||
|
@ -109,7 +110,7 @@ class ACLComponent extends Component
|
|||
'batchAction' => ['perm_admin'],
|
||||
'broodTools' => ['perm_admin'],
|
||||
'connectionRequest' => ['perm_admin'],
|
||||
'connectLocal' => ['perm_admin'],
|
||||
// 'connectLocal' => ['perm_admin'],
|
||||
'delete' => ['perm_admin'],
|
||||
'edit' => ['perm_admin'],
|
||||
'exposedTools' => ['OR' => ['perm_admin', 'perm_sync']],
|
||||
|
|
|
@ -175,6 +175,9 @@ class CRUDComponent extends Component
|
|||
$data = $this->Table->patchEntity($data, $input, $patchEntityParams);
|
||||
if (isset($params['beforeSave'])) {
|
||||
$data = $params['beforeSave']($data);
|
||||
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));
|
||||
}
|
||||
}
|
||||
$savedData = $this->Table->save($data);
|
||||
if ($savedData !== false) {
|
||||
|
|
|
@ -39,7 +39,15 @@ class EncryptionKeysController extends AppController
|
|||
|
||||
public function delete($id)
|
||||
{
|
||||
$this->CRUD->delete($id);
|
||||
$orgConditions = [];
|
||||
$individualConditions = [];
|
||||
$dropdownData = [];
|
||||
$currentUser = $this->ACL->getUser();
|
||||
$params = [];
|
||||
if (empty($currentUser['role']['perm_admin'])) {
|
||||
$params = $this->buildBeforeSave($params, $currentUser, $orgConditions, $individualConditions, $dropdownData);
|
||||
}
|
||||
$this->CRUD->delete($id, $params);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
return $responsePayload;
|
||||
|
@ -47,49 +55,38 @@ class EncryptionKeysController extends AppController
|
|||
$this->set('metaGroup', 'ContactDB');
|
||||
}
|
||||
|
||||
public function add()
|
||||
private function buildBeforeSave(array $params, $currentUser, array &$orgConditions, array &$individualConditions, array &$dropdownData): array
|
||||
{
|
||||
$orgConditions = [];
|
||||
$individualConditions = [];
|
||||
$currentUser = $this->ACL->getUser();
|
||||
$params = ['redirect' => $this->referer()];
|
||||
if (empty($currentUser['role']['perm_admin'])) {
|
||||
$orgConditions = [
|
||||
'id' => $currentUser['organisation_id']
|
||||
$orgConditions = [
|
||||
'id' => $currentUser['organisation_id']
|
||||
];
|
||||
if (empty($currentUser['role']['perm_org_admin'])) {
|
||||
$individualConditions = [
|
||||
'id' => $currentUser['individual_id']
|
||||
];
|
||||
if (empty($currentUser['role']['perm_org_admin'])) {
|
||||
$individualConditions = [
|
||||
'id' => $currentUser['individual_id']
|
||||
];
|
||||
}
|
||||
$params['beforeSave'] = function($entity) use($currentUser) {
|
||||
if ($entity['owner_model'] === 'organisation') {
|
||||
$entity['owner_id'] = $currentUser['organisation_id'];
|
||||
}
|
||||
$params['beforeSave'] = function($entity) use($currentUser) {
|
||||
if ($entity['owner_model'] === 'organisation') {
|
||||
$entity['owner_id'] = $currentUser['organisation_id'];
|
||||
} else {
|
||||
if ($currentUser['role']['perm_org_admin']) {
|
||||
$this->loadModel('Alignments');
|
||||
$validIndividuals = $this->Alignments->find('list', [
|
||||
'keyField' => 'individual_id',
|
||||
'valueField' => 'id',
|
||||
'conditions' => ['organisation_id' => $currentUser['organisation_id']]
|
||||
])->toArray();
|
||||
if (!isset($validIndividuals[$entity['owner_id']])) {
|
||||
throw new MethodNotAllowedException(__('Selected individual cannot be linked by the current user.'));
|
||||
}
|
||||
} else {
|
||||
if ($currentUser['role']['perm_org_admin']) {
|
||||
$this->loadModel('Alignments');
|
||||
$validIndividuals = $this->Alignments->find('list', [
|
||||
'keyField' => 'individual_id',
|
||||
'valueField' => 'id',
|
||||
'conditions' => ['organisation_id' => $currentUser['organisation_id']]
|
||||
])->toArray();
|
||||
if (!isset($validIndividuals[$entity['owner_id']])) {
|
||||
throw new MethodNotAllowedException(__('Selected individual cannot be linked by the current user.'));
|
||||
}
|
||||
} else {
|
||||
if ($entity['owner_id'] !== $currentUser['id']) {
|
||||
throw new MethodNotAllowedException(__('Selected individual cannot be linked by the current user.'));
|
||||
}
|
||||
if ($entity['owner_id'] !== $currentUser['id']) {
|
||||
throw new MethodNotAllowedException(__('Selected individual cannot be linked by the current user.'));
|
||||
}
|
||||
}
|
||||
return $entity;
|
||||
};
|
||||
}
|
||||
$this->CRUD->add($params);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
return $responsePayload;
|
||||
}
|
||||
}
|
||||
return $entity;
|
||||
};
|
||||
$this->loadModel('Organisations');
|
||||
$this->loadModel('Individuals');
|
||||
$dropdownData = [
|
||||
|
@ -102,13 +99,35 @@ class EncryptionKeysController extends AppController
|
|||
'conditions' => $individualConditions
|
||||
])
|
||||
];
|
||||
return $params;
|
||||
}
|
||||
|
||||
public function add()
|
||||
{
|
||||
$orgConditions = [];
|
||||
$individualConditions = [];
|
||||
$dropdownData = [];
|
||||
$currentUser = $this->ACL->getUser();
|
||||
$params = [
|
||||
'redirect' => $this->referer()
|
||||
];
|
||||
if (empty($currentUser['role']['perm_admin'])) {
|
||||
$params = $this->buildBeforeSave($params, $currentUser, $orgConditions, $individualConditions, $dropdownData);
|
||||
}
|
||||
$this->CRUD->add($params);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
return $responsePayload;
|
||||
}
|
||||
$this->set(compact('dropdownData'));
|
||||
$this->set('metaGroup', 'ContactDB');
|
||||
}
|
||||
|
||||
public function edit($id = false)
|
||||
{
|
||||
$conditions = [];
|
||||
$orgConditions = [];
|
||||
$individualConditions = [];
|
||||
$dropdownData = [];
|
||||
$currentUser = $this->ACL->getUser();
|
||||
$params = [
|
||||
'fields' => [
|
||||
|
@ -117,9 +136,7 @@ class EncryptionKeysController extends AppController
|
|||
'redirect' => $this->referer()
|
||||
];
|
||||
if (empty($currentUser['role']['perm_admin'])) {
|
||||
if (empty($currentUser['role']['perm_org_admin'])) {
|
||||
|
||||
}
|
||||
$params = $this->buildBeforeSave($params, $currentUser, $orgConditions, $individualConditions, $dropdownData);
|
||||
}
|
||||
$this->CRUD->edit($id, $params);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
|
@ -130,4 +147,16 @@ class EncryptionKeysController extends AppController
|
|||
$this->set('metaGroup', 'ContactDB');
|
||||
$this->render('add');
|
||||
}
|
||||
|
||||
public function view($id = false)
|
||||
{
|
||||
$this->CRUD->view($id, [
|
||||
'contain' => ['Individuals', 'Organisations']
|
||||
]);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
return $responsePayload;
|
||||
}
|
||||
$this->set('metaGroup', 'ContactDB');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,12 @@ class InstanceController extends AppController
|
|||
usort($status, function($a, $b) {
|
||||
return strcmp($b['id'], $a['id']);
|
||||
});
|
||||
if ($this->ParamHandler->isRest()) {
|
||||
return $this->RestResponse->viewData([
|
||||
'status' => $status,
|
||||
'updateAvailables' => $migrationStatus['updateAvailables'],
|
||||
], 'json');
|
||||
}
|
||||
$this->set('status', $status);
|
||||
$this->set('updateAvailables', $migrationStatus['updateAvailables']);
|
||||
}
|
||||
|
@ -140,6 +146,14 @@ class InstanceController extends AppController
|
|||
{
|
||||
$this->Settings = $this->getTableLocator()->get('Settings');
|
||||
$all = $this->Settings->getSettings(true);
|
||||
if ($this->ParamHandler->isRest()) {
|
||||
return $this->RestResponse->viewData([
|
||||
'settingsProvider' => $all['settingsProvider'],
|
||||
'settings' => $all['settings'],
|
||||
'settingsFlattened' => $all['settingsFlattened'],
|
||||
'notices' => $all['notices'],
|
||||
], 'json');
|
||||
}
|
||||
$this->set('settingsProvider', $all['settingsProvider']);
|
||||
$this->set('settings', $all['settings']);
|
||||
$this->set('settingsFlattened', $all['settingsFlattened']);
|
||||
|
|
|
@ -340,6 +340,7 @@ class LocalToolsController extends AppController
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public function connectLocal($local_tool_id)
|
||||
{
|
||||
$params = [
|
||||
|
@ -355,10 +356,8 @@ class LocalToolsController extends AppController
|
|||
$params['target_tool_id'] = $postParams['target_tool_id'];
|
||||
$result = $this->LocalTools->encodeLocalConnection($params);
|
||||
// Send message to remote inbox
|
||||
debug($result);
|
||||
} else {
|
||||
$target_tools = $this->LocalTools->findConnectable($local_tool);
|
||||
debug($target_tools);
|
||||
if (empty($target_tools)) {
|
||||
throw new NotFoundException(__('No tools found to connect.'));
|
||||
}
|
||||
|
@ -369,4 +368,5 @@ class LocalToolsController extends AppController
|
|||
]);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ use \Cake\Database\Expression\QueryExpression;
|
|||
use Cake\Http\Exception\NotFoundException;
|
||||
use Cake\Http\Exception\MethodNotAllowedException;
|
||||
use Cake\Http\Exception\ForbiddenException;
|
||||
use Cake\Http\Exception\UnauthorizedException;
|
||||
|
||||
|
||||
class UserSettingsController extends AppController
|
||||
{
|
||||
|
@ -19,8 +21,12 @@ class UserSettingsController extends AppController
|
|||
public function index()
|
||||
{
|
||||
$conditions = [];
|
||||
$currentUser = $this->ACL->getUser();
|
||||
if (empty($currentUser['role']['perm_admin'])) {
|
||||
$conditions['user_id'] = $currentUser->id;
|
||||
}
|
||||
$this->CRUD->index([
|
||||
'conditions' => [],
|
||||
'conditions' => $conditions,
|
||||
'contain' => $this->containFields,
|
||||
'filters' => $this->filterFields,
|
||||
'quickFilters' => $this->quickFilterFields,
|
||||
|
@ -39,6 +45,9 @@ class UserSettingsController extends AppController
|
|||
|
||||
public function view($id)
|
||||
{
|
||||
if (!$this->isLoggedUserAllowedToEdit($id)) {
|
||||
throw new NotFoundException(__('Invalid {0}.', 'user setting'));
|
||||
}
|
||||
$this->CRUD->view($id, [
|
||||
'contain' => ['Users']
|
||||
]);
|
||||
|
@ -50,10 +59,13 @@ class UserSettingsController extends AppController
|
|||
|
||||
public function add($user_id = false)
|
||||
{
|
||||
$currentUser = $this->ACL->getUser();
|
||||
$this->CRUD->add([
|
||||
'redirect' => ['action' => 'index', $user_id],
|
||||
'beforeSave' => function($data) use ($user_id) {
|
||||
$data['user_id'] = $user_id;
|
||||
'beforeSave' => function ($data) use ($currentUser) {
|
||||
if (empty($currentUser['role']['perm_admin'])) {
|
||||
$data['user_id'] = $currentUser->id;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
]);
|
||||
|
@ -61,10 +73,13 @@ class UserSettingsController extends AppController
|
|||
if (!empty($responsePayload)) {
|
||||
return $responsePayload;
|
||||
}
|
||||
$allUsers = $this->UserSettings->Users->find('list', ['keyField' => 'id', 'valueField' => 'username'])->order(['username' => 'ASC']);
|
||||
if (empty($currentUser['role']['perm_admin'])) {
|
||||
$allUsers->where(['id' => $currentUser->id]);
|
||||
$user_id = $currentUser->id;
|
||||
}
|
||||
$dropdownData = [
|
||||
'user' => $this->UserSettings->Users->find('list', [
|
||||
'sort' => ['username' => 'asc']
|
||||
]),
|
||||
'user' => $allUsers->all()->toArray(),
|
||||
];
|
||||
$this->set(compact('dropdownData'));
|
||||
$this->set('user_id', $user_id);
|
||||
|
@ -75,6 +90,11 @@ class UserSettingsController extends AppController
|
|||
$entity = $this->UserSettings->find()->where([
|
||||
'id' => $id
|
||||
])->first();
|
||||
|
||||
if (!$this->isLoggedUserAllowedToEdit($entity)) {
|
||||
throw new NotFoundException(__('Invalid {0}.', 'user setting'));
|
||||
}
|
||||
|
||||
$entity = $this->CRUD->edit($id, [
|
||||
'redirect' => ['action' => 'index', $entity->user_id]
|
||||
]);
|
||||
|
@ -94,6 +114,9 @@ class UserSettingsController extends AppController
|
|||
|
||||
public function delete($id)
|
||||
{
|
||||
if (!$this->isLoggedUserAllowedToEdit($id)) {
|
||||
throw new NotFoundException(__('Invalid {0}.', 'user setting'));
|
||||
}
|
||||
$this->CRUD->delete($id);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
|
@ -160,7 +183,7 @@ class UserSettingsController extends AppController
|
|||
}
|
||||
}
|
||||
|
||||
public function getBookmarks($forSidebar=false)
|
||||
public function getBookmarks($forSidebar = false)
|
||||
{
|
||||
$bookmarks = $this->UserSettings->getSettingByName($this->ACL->getUser(), $this->UserSettings->BOOKMARK_SETTING_NAME);
|
||||
$bookmarks = json_decode($bookmarks['value'], true);
|
||||
|
@ -200,4 +223,29 @@ class UserSettingsController extends AppController
|
|||
$this->set('user_id', $this->ACL->getUser()->id);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* isLoggedUserAllowedToEdit
|
||||
*
|
||||
* @param int|\App\Model\Entity\UserSetting $setting
|
||||
* @return boolean
|
||||
*/
|
||||
private function isLoggedUserAllowedToEdit($setting): bool
|
||||
{
|
||||
$currentUser = $this->ACL->getUser();
|
||||
$isAllowed = false;
|
||||
if (!empty($currentUser['role']['perm_admin'])) {
|
||||
$isAllowed = true;
|
||||
} else {
|
||||
if (is_numeric($setting)) {
|
||||
$setting = $this->UserSettings->find()->where([
|
||||
'id' => $setting
|
||||
])->first();
|
||||
if (empty($setting)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$isAllowed = $setting->user_id == $currentUser->id;
|
||||
}
|
||||
return $isAllowed;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,8 +97,16 @@ class UsersController extends AppController
|
|||
public function edit($id = false)
|
||||
{
|
||||
$currentUser = $this->ACL->getUser();
|
||||
if (empty($id) || (empty($currentUser['role']['perm_org_admin']) && empty($currentUser['role']['perm_site_admin']))) {
|
||||
if (empty($id)) {
|
||||
$id = $currentUser['id'];
|
||||
} else {
|
||||
if ((empty($currentUser['role']['perm_org_admin']) && empty($currentUser['role']['perm_admin']))) {
|
||||
if ($id !== $currentUser['id']) {
|
||||
throw new MethodNotAllowedException(__('You are not authorised to edit that user.'));
|
||||
} else {
|
||||
$id = $currentUser['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$params = [
|
||||
|
@ -111,12 +119,15 @@ class UsersController extends AppController
|
|||
'password'
|
||||
],
|
||||
'fields' => [
|
||||
'id', 'individual_id', 'username', 'disabled', 'password', 'confirm_password'
|
||||
'password', 'confirm_password'
|
||||
]
|
||||
];
|
||||
if (!empty($this->ACL->getUser()['role']['perm_admin'])) {
|
||||
$params['fields'][] = 'individual_id';
|
||||
$params['fields'][] = 'username';
|
||||
$params['fields'][] = 'role_id';
|
||||
$params['fields'][] = 'organisation_id';
|
||||
$params['fields'][] = 'disabled';
|
||||
}
|
||||
$this->CRUD->edit($id, $params);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace CommonConnectorTools;
|
||||
use Cake\ORM\Locator\LocatorAwareTrait;
|
||||
use Cake\Log\Log;
|
||||
use Cake\Log\Engine\FileLog;
|
||||
|
||||
class CommonConnectorTools
|
||||
{
|
||||
|
@ -20,6 +22,35 @@ class CommonConnectorTools
|
|||
const STATE_CANCELLED = 'Request cancelled';
|
||||
const STATE_DECLINED = 'Request declined by remote';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
Log::setConfig("LocalToolDebug", [
|
||||
'className' => FileLog::class,
|
||||
'path' => LOGS,
|
||||
'file' => "{$this->connectorName}-debug",
|
||||
'scopes' => [$this->connectorName],
|
||||
'levels' => ['notice', 'info', 'debug'],
|
||||
]);
|
||||
Log::setConfig("LocalToolError", [
|
||||
'className' => FileLog::class,
|
||||
'path' => LOGS,
|
||||
'file' => "{$this->connectorName}-error",
|
||||
'scopes' => [$this->connectorName],
|
||||
'levels' => ['warning', 'error', 'critical', 'alert', 'emergency'],
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
protected function logDebug($message)
|
||||
{
|
||||
Log::debug($message, [$this->connectorName]);
|
||||
}
|
||||
|
||||
protected function logError($message, $scope=[])
|
||||
{
|
||||
Log::error($message, [$this->connectorName]);
|
||||
}
|
||||
|
||||
public function addExposedFunction(string $functionName): void
|
||||
{
|
||||
$this->exposedFunctions[] = $functionName;
|
||||
|
|
|
@ -122,6 +122,11 @@ class MispConnector extends CommonConnectorTools
|
|||
'type' => 'boolean'
|
||||
],
|
||||
];
|
||||
public $settingsPlaceholder = [
|
||||
'url' => 'https://your.misp.intance',
|
||||
'authkey' => '',
|
||||
'skip_ssl' => '0',
|
||||
];
|
||||
|
||||
public function addSettingValidatorRules($validator)
|
||||
{
|
||||
|
@ -183,6 +188,7 @@ class MispConnector extends CommonConnectorTools
|
|||
$settings = json_decode($connection->settings, true);
|
||||
$http = $this->genHTTPClient($connection, $options);
|
||||
$url = sprintf('%s%s', $settings['url'], $relativeURL);
|
||||
$this->logDebug(sprintf('%s %s %s', __('Posting data') . PHP_EOL, "POST {$url}" . PHP_EOL, json_encode($data)));
|
||||
return $http->post($url, $data, $options);
|
||||
}
|
||||
|
||||
|
@ -234,14 +240,18 @@ class MispConnector extends CommonConnectorTools
|
|||
if (!empty($params['softError'])) {
|
||||
return $response;
|
||||
}
|
||||
throw new NotFoundException(__('Could not retrieve the requested resource.'));
|
||||
$errorMsg = __('Could not post to the requested resource for `{0}`. Remote returned:', $url) . PHP_EOL . $response->getStringBody();
|
||||
$this->logError($errorMsg);
|
||||
throw new NotFoundException($errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
private function postData(string $url, array $params): Response
|
||||
{
|
||||
if (empty($params['connection'])) {
|
||||
throw new NotFoundException(__('No connection object received.'));
|
||||
$errorMsg = __('No connection object received.');
|
||||
$this->logError($errorMsg);
|
||||
throw new NotFoundException($errorMsg);
|
||||
}
|
||||
$url = $this->urlAppendParams($url, $params);
|
||||
if (!is_string($params['body'])) {
|
||||
|
@ -251,7 +261,9 @@ class MispConnector extends CommonConnectorTools
|
|||
if ($response->isOk()) {
|
||||
return $response;
|
||||
} else {
|
||||
throw new NotFoundException(__('Could not post to the requested resource. Remote returned:') . PHP_EOL . $response->getStringBody());
|
||||
$errorMsg = __('Could not post to the requested resource for `{0}`. Remote returned:', $url) . PHP_EOL . $response->getStringBody();
|
||||
$this->logError($errorMsg);
|
||||
throw new NotFoundException($errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,22 @@ class SkeletonConnector extends CommonConnectorTools
|
|||
'redirect' => 'serverSettingsAction'
|
||||
]
|
||||
];
|
||||
public $settings = [
|
||||
'url' => [
|
||||
'type' => 'text'
|
||||
],
|
||||
'authkey' => [
|
||||
'type' => 'text'
|
||||
],
|
||||
'skip_ssl' => [
|
||||
'type' => 'boolean'
|
||||
],
|
||||
];
|
||||
public $settingsPlaceholder = [
|
||||
'url' => 'https://your.url',
|
||||
'authkey' => '',
|
||||
'skip_ssl' => '0',
|
||||
];
|
||||
|
||||
public function health(Object $connection): array
|
||||
{
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace App\Model\Entity;
|
||||
|
||||
use App\Model\Entity\AppModel;
|
||||
use Cake\ORM\Entity;
|
||||
|
||||
class Outbox extends AppModel
|
||||
{
|
||||
|
||||
}
|
|
@ -143,7 +143,8 @@ class LocalToolsTable extends AppTable
|
|||
'connector' => $connector_type,
|
||||
'connector_version' => $connector_class->version,
|
||||
'connector_description' => $connector_class->description,
|
||||
'connector_settings' => $connector_class->settings ?? []
|
||||
'connector_settings' => $connector_class->settings ?? [],
|
||||
'connector_settings_placeholder' => $connector_class->settingsPlaceholder ?? [],
|
||||
];
|
||||
if ($includeConnections) {
|
||||
$connector['connections'] = $this->healthCheck($connector_type, $connector_class);
|
||||
|
@ -288,6 +289,7 @@ class LocalToolsTable extends AppTable
|
|||
return $jsonReply;
|
||||
}
|
||||
|
||||
/*
|
||||
public function findConnectable($local_tool): array
|
||||
{
|
||||
$connectors = $this->getInterconnectors($local_tool['connector']);
|
||||
|
@ -297,8 +299,8 @@ class LocalToolsTable extends AppTable
|
|||
$validTargets[$connector['connects'][1]] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
public function fetchConnection($id): object
|
||||
{
|
||||
|
|
|
@ -11,7 +11,7 @@ use App\Settings\SettingsProvider\UserSettingsProvider;
|
|||
|
||||
class UserSettingsTable extends AppTable
|
||||
{
|
||||
protected $BOOKMARK_SETTING_NAME = 'ui.bookmarks';
|
||||
public $BOOKMARK_SETTING_NAME = 'ui.bookmarks';
|
||||
|
||||
public function initialize(array $config): void
|
||||
{
|
||||
|
|
|
@ -637,13 +637,13 @@ class BoostrapTable extends BootstrapGeneric {
|
|||
],
|
||||
]);
|
||||
foreach ($this->items as $i => $row) {
|
||||
$body .= $this->genRow($row);
|
||||
$body .= $this->genRow($row, $i);
|
||||
}
|
||||
$body .= $this->closeNode('tbody');
|
||||
return $body;
|
||||
}
|
||||
|
||||
private function genRow($row)
|
||||
private function genRow($row, $rowIndex)
|
||||
{
|
||||
$html = $this->openNode('tr',[
|
||||
'class' => [
|
||||
|
@ -658,21 +658,21 @@ class BoostrapTable extends BootstrapGeneric {
|
|||
$key = $field;
|
||||
}
|
||||
$cellValue = Hash::get($row, $key);
|
||||
$html .= $this->genCell($cellValue, $field, $row, $i);
|
||||
$html .= $this->genCell($cellValue, $field, $row, $rowIndex);
|
||||
}
|
||||
} else { // indexed array
|
||||
foreach ($row as $cellValue) {
|
||||
$html .= $this->genCell($cellValue, $field, $row, $i);
|
||||
foreach ($row as $i => $cellValue) {
|
||||
$html .= $this->genCell($cellValue, 'index', $row, $rowIndex);
|
||||
}
|
||||
}
|
||||
$html .= $this->closeNode('tr');
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function genCell($value, $field=[], $row=[], $i=0)
|
||||
private function genCell($value, $field=[], $row=[], $rowIndex=0)
|
||||
{
|
||||
if (isset($field['formatter'])) {
|
||||
$cellContent = $field['formatter']($value, $row, $i);
|
||||
$cellContent = $field['formatter']($value, $row, $rowIndex);
|
||||
} else if (isset($field['element'])) {
|
||||
$cellContent = $this->btHelper->getView()->element($field['element'], [
|
||||
'data' => [$value],
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
echo $this->element(
|
||||
'/genericElements/SingleViews/single_view',
|
||||
[
|
||||
'data' => $entity,
|
||||
'fields' => [
|
||||
[
|
||||
'key' => __('ID'),
|
||||
'path' => 'id'
|
||||
],
|
||||
[
|
||||
'key' => __('Type'),
|
||||
'path' => 'type'
|
||||
],
|
||||
[
|
||||
'key' => __('Owner'),
|
||||
'path' => 'owner_id',
|
||||
'owner_model_path' => 'owner_model',
|
||||
'type' => 'owner'
|
||||
],
|
||||
[
|
||||
'key' => __('Revoked'),
|
||||
'path' => 'revoked'
|
||||
],
|
||||
|
||||
[
|
||||
'key' => __('Key'),
|
||||
'path' => 'encryption_key'
|
||||
]
|
||||
]
|
||||
]
|
||||
);
|
|
@ -23,7 +23,8 @@
|
|||
),
|
||||
array(
|
||||
'field' => 'tag_list',
|
||||
'type' => 'tags'
|
||||
'type' => 'tags',
|
||||
'requirements' => $this->request->getParam('action') === 'edit'
|
||||
),
|
||||
),
|
||||
'metaTemplates' => empty($metaTemplates) ? [] : $metaTemplates,
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
'codemirror' => [
|
||||
'height' => '10rem',
|
||||
'hints' => $connectors[0]['connector_settings']
|
||||
]
|
||||
],
|
||||
'placeholder' => json_encode($connectors[0]['connector_settings_placeholder'], JSON_FORCE_OBJECT | JSON_PRETTY_PRINT)
|
||||
],
|
||||
[
|
||||
'field' => 'description',
|
||||
|
|
|
@ -89,12 +89,14 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
|||
'url_params_data_paths' => ['id'],
|
||||
'icon' => 'eye'
|
||||
],
|
||||
/*
|
||||
[
|
||||
'open_modal' => '/localTools/connectLocal/[onclick_params_data_path]',
|
||||
'modal_params_data_path' => 'id',
|
||||
'reload_url' => sprintf('/localTools/connectorIndex/%s', h($connectorName)),
|
||||
'icon' => 'plug'
|
||||
],
|
||||
*/
|
||||
[
|
||||
'open_modal' => '/localTools/edit/[onclick_params_data_path]',
|
||||
'modal_params_data_path' => 'id',
|
||||
|
|
|
@ -7,17 +7,13 @@
|
|||
array(
|
||||
'field' => 'name'
|
||||
),
|
||||
array(
|
||||
'field' => 'description',
|
||||
'type' => 'textarea'
|
||||
),
|
||||
array(
|
||||
'field' => 'uuid',
|
||||
'label' => 'UUID',
|
||||
'type' => 'uuid'
|
||||
),
|
||||
array(
|
||||
'field' => 'URL'
|
||||
'field' => 'url'
|
||||
),
|
||||
array(
|
||||
'field' => 'nationality'
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
echo $this->element('/genericElements/IndexTable/Fields/owner', [
|
||||
'field' => $field,
|
||||
'row' => $data
|
||||
]);
|
||||
?>
|
|
@ -52,6 +52,7 @@ $sidebarOpen = $loggedUser->user_settings_by_name_with_fallback['ui.sidebar.expa
|
|||
<?= $this->Html->script('CodeMirror/addon/lint/json-lint') ?>
|
||||
<?= $this->Html->script('CodeMirror/addon/edit/matchbrackets') ?>
|
||||
<?= $this->Html->script('CodeMirror/addon/edit/closebrackets') ?>
|
||||
<?= $this->Html->script('CodeMirror/addon/display/placeholder') ?>
|
||||
<?= $this->Html->css('CodeMirror/codemirror') ?>
|
||||
<?= $this->Html->css('CodeMirror/codemirror-additional') ?>
|
||||
<?= $this->Html->css('CodeMirror/addon/hint/show-hint') ?>
|
||||
|
|
|
@ -26,4 +26,8 @@
|
|||
|
||||
.CodeMirror-hints {
|
||||
z-index: 1060 !important; /* Make sure hint is above modal */
|
||||
}
|
||||
|
||||
.CodeMirror pre.CodeMirror-placeholder {
|
||||
color: #999;
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||
|
||||
(function (mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function (CodeMirror) {
|
||||
CodeMirror.defineOption("placeholder", "", function (cm, val, old) {
|
||||
var prev = old && old != CodeMirror.Init;
|
||||
if (val && !prev) {
|
||||
cm.on("blur", onBlur);
|
||||
cm.on("change", onChange);
|
||||
cm.on("swapDoc", onChange);
|
||||
CodeMirror.on(cm.getInputField(), "compositionupdate", cm.state.placeholderCompose = function () { onComposition(cm) })
|
||||
onChange(cm);
|
||||
} else if (!val && prev) {
|
||||
cm.off("blur", onBlur);
|
||||
cm.off("change", onChange);
|
||||
cm.off("swapDoc", onChange);
|
||||
CodeMirror.off(cm.getInputField(), "compositionupdate", cm.state.placeholderCompose)
|
||||
clearPlaceholder(cm);
|
||||
var wrapper = cm.getWrapperElement();
|
||||
wrapper.className = wrapper.className.replace(" CodeMirror-empty", "");
|
||||
}
|
||||
|
||||
if (val && !cm.hasFocus()) onBlur(cm);
|
||||
});
|
||||
|
||||
function clearPlaceholder(cm) {
|
||||
if (cm.state.placeholder) {
|
||||
cm.state.placeholder.parentNode.removeChild(cm.state.placeholder);
|
||||
cm.state.placeholder = null;
|
||||
}
|
||||
}
|
||||
function setPlaceholder(cm) {
|
||||
clearPlaceholder(cm);
|
||||
var elt = cm.state.placeholder = document.createElement("pre");
|
||||
elt.style.cssText = "height: 0; overflow: visible";
|
||||
elt.style.direction = cm.getOption("direction");
|
||||
elt.className = "CodeMirror-placeholder CodeMirror-line-like";
|
||||
var placeHolder = cm.getOption("placeholder")
|
||||
if (typeof placeHolder == "string") placeHolder = document.createTextNode(placeHolder)
|
||||
elt.appendChild(placeHolder)
|
||||
cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild);
|
||||
}
|
||||
|
||||
function onComposition(cm) {
|
||||
setTimeout(function () {
|
||||
var empty = false
|
||||
if (cm.lineCount() == 1) {
|
||||
var input = cm.getInputField()
|
||||
empty = input.nodeName == "TEXTAREA" ? !cm.getLine(0).length
|
||||
: !/[^\u200b]/.test(input.querySelector(".CodeMirror-line").textContent)
|
||||
}
|
||||
if (empty) setPlaceholder(cm)
|
||||
else clearPlaceholder(cm)
|
||||
}, 20)
|
||||
}
|
||||
|
||||
function onBlur(cm) {
|
||||
if (isEmpty(cm)) setPlaceholder(cm);
|
||||
}
|
||||
function onChange(cm) {
|
||||
var wrapper = cm.getWrapperElement(), empty = isEmpty(cm);
|
||||
wrapper.className = wrapper.className.replace(" CodeMirror-empty", "") + (empty ? " CodeMirror-empty" : "");
|
||||
|
||||
if (empty) setPlaceholder(cm);
|
||||
else clearPlaceholder(cm);
|
||||
}
|
||||
|
||||
function isEmpty(cm) {
|
||||
return (cm.lineCount() === 1) && (cm.getLine(0) === "");
|
||||
}
|
||||
});
|
Loading…
Reference in New Issue