Merge branch 'develop' of github.com:cerebrate-project/cerebrate into develop
commit
f0ba0d8316
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Migrations\AbstractMigration;
|
||||||
|
use Phinx\Db\Adapter\MysqlAdapter;
|
||||||
|
|
||||||
|
final class SGExtend extends AbstractMigration
|
||||||
|
{
|
||||||
|
public $autoId = false; // turn off automatic `id` column create. We want it to be `int(10) unsigned`
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change Method.
|
||||||
|
*
|
||||||
|
* Write your reversible migrations using this method.
|
||||||
|
*
|
||||||
|
* More information on writing migrations is available here:
|
||||||
|
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
|
||||||
|
*
|
||||||
|
* Remember to call "create()" or "update()" and NOT "save()" when working
|
||||||
|
* with the Table class.
|
||||||
|
*/
|
||||||
|
public function change(): void
|
||||||
|
{
|
||||||
|
$table = $this->table('sgo');
|
||||||
|
$exists = $table->hasColumn('extend');
|
||||||
|
if (!$exists) {
|
||||||
|
$table
|
||||||
|
->addColumn('extend', 'boolean', [
|
||||||
|
'default' => 0,
|
||||||
|
'null' => false,
|
||||||
|
])->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ use Cake\Utility\Text;
|
||||||
use \Cake\Database\Expression\QueryExpression;
|
use \Cake\Database\Expression\QueryExpression;
|
||||||
use Cake\Error\Debugger;
|
use Cake\Error\Debugger;
|
||||||
use Cake\Http\Exception\NotFoundException;
|
use Cake\Http\Exception\NotFoundException;
|
||||||
|
use Cake\ORM\TableRegistry;
|
||||||
|
|
||||||
class SharingGroupsController extends AppController
|
class SharingGroupsController extends AppController
|
||||||
{
|
{
|
||||||
|
@ -171,9 +172,13 @@ class SharingGroupsController extends AppController
|
||||||
$input['organisation_id'] = [$input['organisation_id']];
|
$input['organisation_id'] = [$input['organisation_id']];
|
||||||
}
|
}
|
||||||
$result = true;
|
$result = true;
|
||||||
|
$this->SGO = TableRegistry::getTableLocator()->get('SGOs');
|
||||||
foreach ($input['organisation_id'] as $org_id) {
|
foreach ($input['organisation_id'] as $org_id) {
|
||||||
$org = $this->SharingGroups->SharingGroupOrgs->get($org_id);
|
$additional_data = [];
|
||||||
$result &= (bool)$this->SharingGroups->SharingGroupOrgs->link($sharingGroup, [$org]);
|
if (!empty($input['extend'])) {
|
||||||
|
$additional_data['extend'] = $input['extend'];
|
||||||
|
}
|
||||||
|
$result &= $this->SGO->attach($sharingGroup['id'], $org_id, $additional_data);
|
||||||
}
|
}
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$message = __('Organisation(s) added to the sharing group.');
|
$message = __('Organisation(s) added to the sharing group.');
|
||||||
|
@ -216,8 +221,8 @@ class SharingGroupsController extends AppController
|
||||||
throw new NotFoundException(__('Invalid SharingGroup.'));
|
throw new NotFoundException(__('Invalid SharingGroup.'));
|
||||||
}
|
}
|
||||||
if ($this->request->is('post')) {
|
if ($this->request->is('post')) {
|
||||||
$org = $this->SharingGroups->SharingGroupOrgs->get($org_id);
|
$this->SGO = TableRegistry::getTableLocator()->get('SGOs');
|
||||||
$result = (bool)$this->SharingGroups->SharingGroupOrgs->unlink($sharingGroup, [$org]);
|
$result = (bool)$this->SharingGroups->SharingGroupOrgs->unlink($sharingGroup['id'], $org_id);
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$message = __('Organisation(s) removed from the sharing group.');
|
$message = __('Organisation(s) removed from the sharing group.');
|
||||||
} else {
|
} else {
|
||||||
|
@ -253,9 +258,10 @@ class SharingGroupsController extends AppController
|
||||||
|
|
||||||
public function listOrgs($id)
|
public function listOrgs($id)
|
||||||
{
|
{
|
||||||
$sharingGroup = $this->SharingGroups->get($id, [
|
$sharingGroup = $this->SharingGroups->find()->where(['id' => $id])->contain(['SharingGroupOrgs'])->first();
|
||||||
'contain' => 'SharingGroupOrgs'
|
foreach ($sharingGroup['sharing_group_orgs'] as $k => $org) {
|
||||||
]);
|
$sharingGroup['sharing_group_orgs'][$k]['extend'] = $org['_joinData']['extend'];
|
||||||
|
}
|
||||||
$params = $this->ParamHandler->harvestParams(['quickFilter']);
|
$params = $this->ParamHandler->harvestParams(['quickFilter']);
|
||||||
if (!empty($params['quickFilter'])) {
|
if (!empty($params['quickFilter'])) {
|
||||||
foreach ($sharingGroup['sharing_group_orgs'] as $k => $org) {
|
foreach ($sharingGroup['sharing_group_orgs'] as $k => $org) {
|
||||||
|
|
|
@ -104,6 +104,16 @@ class CommonConnectorTools
|
||||||
return $orgs;
|
return $orgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSharingGroups(): array
|
||||||
|
{
|
||||||
|
$sgs = \Cake\ORM\TableRegistry::getTableLocator()->get('SharingGroups');
|
||||||
|
$sgs = $sgs->find()
|
||||||
|
->contain(['Organisations' => ['fields' => ['uuid']], 'SharingGroupOrgs' => ['fields' => ['uuid']]])
|
||||||
|
->disableHydration()
|
||||||
|
->toArray();
|
||||||
|
return $sgs;
|
||||||
|
}
|
||||||
|
|
||||||
public function getFilteredOrganisations($filters, $returnObjects = false): array
|
public function getFilteredOrganisations($filters, $returnObjects = false): array
|
||||||
{
|
{
|
||||||
$organisations = \Cake\ORM\TableRegistry::getTableLocator()->get('Organisations');
|
$organisations = \Cake\ORM\TableRegistry::getTableLocator()->get('Organisations');
|
||||||
|
@ -219,6 +229,11 @@ class CommonConnectorTools
|
||||||
$this->remoteToolConnectionStatus($params, self::STATE_CONNECTED);
|
$this->remoteToolConnectionStatus($params, self::STATE_CONNECTED);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function diagnostics(array $params): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -15,6 +15,12 @@ class MispConnector extends CommonConnectorTools
|
||||||
public $name = 'MISP';
|
public $name = 'MISP';
|
||||||
|
|
||||||
public $exposedFunctions = [
|
public $exposedFunctions = [
|
||||||
|
'diagnosticsAction' => [
|
||||||
|
'type' => 'index',
|
||||||
|
'scope' => 'child',
|
||||||
|
'params' => [
|
||||||
|
]
|
||||||
|
],
|
||||||
'serverSettingsAction' => [
|
'serverSettingsAction' => [
|
||||||
'type' => 'index',
|
'type' => 'index',
|
||||||
'scope' => 'child',
|
'scope' => 'child',
|
||||||
|
@ -48,6 +54,11 @@ class MispConnector extends CommonConnectorTools
|
||||||
'direction'
|
'direction'
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
'restartWorkersAction' => [
|
||||||
|
'type' => 'formAction',
|
||||||
|
'scope' => 'childAction',
|
||||||
|
'redirect' => 'diagnosticsAction'
|
||||||
|
],
|
||||||
'fetchOrganisationAction' => [
|
'fetchOrganisationAction' => [
|
||||||
'type' => 'formAction',
|
'type' => 'formAction',
|
||||||
'scope' => 'childAction',
|
'scope' => 'childAction',
|
||||||
|
@ -132,7 +143,7 @@ class MispConnector extends CommonConnectorTools
|
||||||
'icon' => 'terminal',
|
'icon' => 'terminal',
|
||||||
'variant' => 'primary',
|
'variant' => 'primary',
|
||||||
]
|
]
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
public $version = '0.1';
|
public $version = '0.1';
|
||||||
public $settings = [
|
public $settings = [
|
||||||
|
@ -261,7 +272,7 @@ class MispConnector extends CommonConnectorTools
|
||||||
if (!empty($params['softError'])) {
|
if (!empty($params['softError'])) {
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
$errorMsg = __('Could not post to the requested resource for `{0}`. Remote returned:', $url) . PHP_EOL . $response->getStringBody();
|
$errorMsg = __('Could not GET from the requested resource for `{0}`. Remote returned:', $url) . PHP_EOL . $response->getStringBody();
|
||||||
$this->logError($errorMsg);
|
$this->logError($errorMsg);
|
||||||
throw new NotFoundException($errorMsg);
|
throw new NotFoundException($errorMsg);
|
||||||
}
|
}
|
||||||
|
@ -312,10 +323,183 @@ class MispConnector extends CommonConnectorTools
|
||||||
return $url;
|
return $url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function diagnostics(array $params): array
|
||||||
|
{
|
||||||
|
$urlParams = h($params['connection']['id']) . '/serverSettingsAction';
|
||||||
|
$response = $this->getData('/servers/serverSettings', $params);
|
||||||
|
if (!$response->isOk()) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$data = $response->getJson();
|
||||||
|
$issues = [];
|
||||||
|
if ($data['version']['upToDate'] !== 'same') {
|
||||||
|
$issues['version'] = [
|
||||||
|
'type' => 'danger',
|
||||||
|
'message' => __('Outdated ({0}).', $data['version']['current']),
|
||||||
|
'remediation' => [
|
||||||
|
'icon' => 'fa-sync',
|
||||||
|
'title' => __('Update MISP'),
|
||||||
|
'url' => '/localTools/action/' . h($params['connection']['id']) . '/updateMISP'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if ($data['phpSettings']['memory_limit']['value'] < $data['phpSettings']['memory_limit']['recommended']) {
|
||||||
|
$issues['php_memory'] = [
|
||||||
|
'type' => 'warning',
|
||||||
|
'message' => __('Low PHP memory ({0}M).', $data['phpSettings']['memory_limit']['value'])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$worker_issues = [];
|
||||||
|
foreach ($data['workers'] as $queue => $worker_data) {
|
||||||
|
if (in_array($queue, ['proc_accessible', 'scheduler', 'controls'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (empty($worker_data['ok'])) {
|
||||||
|
$worker_issues['down'][] = $queue;
|
||||||
|
}
|
||||||
|
if ($worker_data['jobCount'] > 100) {
|
||||||
|
$worker_issues['stalled'][] = $queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($worker_issues['down'])) {
|
||||||
|
$issues['workers_down'] = [
|
||||||
|
'type' => 'danger',
|
||||||
|
'message' => __('Worker(s) down: {0}', implode(', ', $worker_issues['down'])),
|
||||||
|
'remediation' => [
|
||||||
|
'icon' => 'fa-sync',
|
||||||
|
'title' => __('Restart workers'),
|
||||||
|
'url' => '/localTools/action/' . h($params['connection']['id']) . '/restartWorkersAction'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($worker_issues['stalled'])) {
|
||||||
|
$issues['workers_stalled'] = [
|
||||||
|
'type' => 'warning',
|
||||||
|
'message' => __('Worker(s) stalled: {0}', implode(', ', $worker_issues['stalled'])),
|
||||||
|
'remediation' => [
|
||||||
|
'icon' => 'fa-sync',
|
||||||
|
'title' => __('Restart workers'),
|
||||||
|
'url' => '/localTools/action/' . h($params['connection']['id']) . '/restartWorkersAction'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if (!empty($data['dbConfiguration'])) {
|
||||||
|
foreach ($data['dbConfiguration'] as $dbConfig) {
|
||||||
|
if ($dbConfig['name'] === 'innodb_buffer_pool_size' && $dbConfig['value'] < $dbConfig['recommended']) {
|
||||||
|
$issues['innodb_buffer_pool_size'] = [
|
||||||
|
'type' => 'warning',
|
||||||
|
'message' => __('InnoDB buffer pool size is low ({0}M).', (round($dbConfig['value']/1024/1024)))
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($data['dbSchemaDiagnostics'])) {
|
||||||
|
if ($data['dbSchemaDiagnostics']['expected_db_version'] > $data['dbSchemaDiagnostics']['actual_db_version'])
|
||||||
|
$issues['schema_version'] = [
|
||||||
|
'type' => 'danger',
|
||||||
|
'message' => __('DB schame outdated.'),
|
||||||
|
'remediation' => [
|
||||||
|
'icon' => 'fa-sync',
|
||||||
|
'title' => __('Update DB schema'),
|
||||||
|
'url' => '/localTools/action/' . h($params['connection']['id']) . '/updateSchemaAction'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $issues;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function restartWorkersAction(array $params): array
|
||||||
|
{
|
||||||
|
if ($params['request']->is(['get'])) {
|
||||||
|
return [
|
||||||
|
'data' => [
|
||||||
|
'title' => __('Restart workers'),
|
||||||
|
'description' => __('Would you like to trigger a restart of all attached workers?'),
|
||||||
|
'submit' => [
|
||||||
|
'action' => $params['request']->getParam('action')
|
||||||
|
],
|
||||||
|
'url' => ['controller' => 'localTools', 'action' => 'action', $params['connection']['id'], 'restartWorkersAction']
|
||||||
|
]
|
||||||
|
];
|
||||||
|
} elseif ($params['request']->is(['post'])) {
|
||||||
|
$response = $this->postData('/servers/restartWorkers', $params);
|
||||||
|
if ($response->isOk()) {
|
||||||
|
return ['success' => 1, 'message' => __('Workers restarted.')];
|
||||||
|
} else {
|
||||||
|
return ['success' => 0, 'message' => __('Could not restart workers.')];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$response = $this->postData('/servers/restartWorkers', $params);
|
||||||
|
if ($response->isOk()) {
|
||||||
|
return [
|
||||||
|
'type' => 'success',
|
||||||
|
'message' => __('Workers restarted.')
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
return [
|
||||||
|
'type' => 'danger',
|
||||||
|
'message' => __('Something went wrong.')
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function diagnosticsAction(array $params): array
|
public function diagnosticsAction(array $params): array
|
||||||
{
|
{
|
||||||
|
$diagnostics = $this->diagnostics($params);
|
||||||
|
$data = [];
|
||||||
|
foreach ($diagnostics as $error => $error_data) {
|
||||||
|
$data[] = [
|
||||||
|
'error' => $error,
|
||||||
|
'type' => $error_data['type'],
|
||||||
|
'message' => $error_data['message'],
|
||||||
|
'remediation' => $error_data['remediation'] ?? false
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
'type' => 'index',
|
||||||
|
'data' => [
|
||||||
|
'data' => $data,
|
||||||
|
'skip_pagination' => 1,
|
||||||
|
'top_bar' => [
|
||||||
|
'children' => []
|
||||||
|
],
|
||||||
|
'fields' => [
|
||||||
|
[
|
||||||
|
'name' => 'error',
|
||||||
|
'data_path' => 'error',
|
||||||
|
'name' => __('Error'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'message',
|
||||||
|
'data_path' => 'message',
|
||||||
|
'name' => __('Message'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => __('Remediation'),
|
||||||
|
'element' => 'function',
|
||||||
|
'function' => function($row, $context) {
|
||||||
|
$remediation = $context->Hash->extract($row, 'remediation');
|
||||||
|
if (!empty($remediation['title'])) {
|
||||||
|
echo sprintf(
|
||||||
|
'<a href="%s" class="btn btn-primary btn-sm" title="%s"><i class="fa %s"></i></a>',
|
||||||
|
h($remediation['url']),
|
||||||
|
h($remediation['title']),
|
||||||
|
h($remediation['icon'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'title' => false,
|
||||||
|
'description' => false,
|
||||||
|
'pull' => 'right'
|
||||||
|
]
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function serverSettingsAction(array $params): array
|
public function serverSettingsAction(array $params): array
|
||||||
|
@ -576,6 +760,56 @@ class MispConnector extends CommonConnectorTools
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function __compareOrgs(array $data, array $existingOrgs): array
|
||||||
|
{
|
||||||
|
foreach ($data as $k => $v) {
|
||||||
|
$data[$k]['Organisation']['local_copy'] = false;
|
||||||
|
if (!empty($existingOrgs[$v['Organisation']['uuid']])) {
|
||||||
|
$remoteOrg = $existingOrgs[$v['Organisation']['uuid']];
|
||||||
|
$localOrg = $v['Organisation'];
|
||||||
|
$same = true;
|
||||||
|
$fieldsToCheck = [
|
||||||
|
'nationality', 'sector', 'type', 'name'
|
||||||
|
];
|
||||||
|
foreach (['nationality', 'sector', 'type', 'name'] as $fieldToCheck) {
|
||||||
|
if ($remoteOrg[$fieldToCheck] != $localOrg[$fieldToCheck]) {
|
||||||
|
$same = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$data[$k]['Organisation']['local_copy'] = $same ? 'same' : 'different';
|
||||||
|
} else {
|
||||||
|
$data[$k]['Organisation']['local_copy'] = 'not_found';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function __compareSgs(array $data, array $existingSgs): array
|
||||||
|
{
|
||||||
|
debug($data);
|
||||||
|
debug($existingSgs);
|
||||||
|
foreach ($data as $k => $v) {
|
||||||
|
$data[$k]['SharingGroup']['local_copy'] = false;
|
||||||
|
if (!empty($existingOrgs[$v['SharingGroup']['uuid']])) {
|
||||||
|
$remoteOrg = $existingOrgs[$v['SharingGroup']['uuid']];
|
||||||
|
$localOrg = $v['SharingGroup'];
|
||||||
|
$same = true;
|
||||||
|
$fieldsToCheck = [
|
||||||
|
'nationality', 'sector', 'type', 'name'
|
||||||
|
];
|
||||||
|
foreach (['nationality', 'sector', 'type', 'name'] as $fieldToCheck) {
|
||||||
|
if ($remoteOrg[$fieldToCheck] != $localOrg[$fieldToCheck]) {
|
||||||
|
$same = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$data[$k]['SharingGroup']['local_copy'] = $same ? 'same' : 'different';
|
||||||
|
} else {
|
||||||
|
$data[$k]['SharingGroup']['local_copy'] = 'not_found';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function organisationsAction(array $params): array
|
public function organisationsAction(array $params): array
|
||||||
{
|
{
|
||||||
|
@ -610,25 +844,7 @@ class MispConnector extends CommonConnectorTools
|
||||||
'icon' => 'exclamation-triangle'
|
'icon' => 'exclamation-triangle'
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
foreach ($data as $k => $v) {
|
$data = $this->__compareOrgs($data, $existingOrgs);
|
||||||
$data[$k]['Organisation']['local_copy'] = false;
|
|
||||||
if (!empty($existingOrgs[$v['Organisation']['uuid']])) {
|
|
||||||
$remoteOrg = $existingOrgs[$v['Organisation']['uuid']];
|
|
||||||
$localOrg = $v['Organisation'];
|
|
||||||
$same = true;
|
|
||||||
$fieldsToCheck = [
|
|
||||||
'nationality', 'sector', 'type', 'name'
|
|
||||||
];
|
|
||||||
foreach (['nationality', 'sector', 'type', 'name'] as $fieldToCheck) {
|
|
||||||
if ($remoteOrg[$fieldToCheck] != $localOrg[$fieldToCheck]) {
|
|
||||||
$same = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$data[$k]['Organisation']['local_copy'] = $same ? 'same' : 'different';
|
|
||||||
} else {
|
|
||||||
$data[$k]['Organisation']['local_copy'] = 'not_found';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!empty($data)) {
|
if (!empty($data)) {
|
||||||
return [
|
return [
|
||||||
'type' => 'index',
|
'type' => 'index',
|
||||||
|
@ -764,6 +980,35 @@ class MispConnector extends CommonConnectorTools
|
||||||
$urlParams = h($params['connection']['id']) . '/sharingGroupsAction';
|
$urlParams = h($params['connection']['id']) . '/sharingGroupsAction';
|
||||||
$response = $this->getData('/sharing_groups/index', $params);
|
$response = $this->getData('/sharing_groups/index', $params);
|
||||||
$data = $response->getJson();
|
$data = $response->getJson();
|
||||||
|
$temp = $this->getSharingGroups();
|
||||||
|
$existingOrgs = [];
|
||||||
|
foreach ($temp as $k => $v) {
|
||||||
|
$existingSGs[$v['uuid']] = $v;
|
||||||
|
unset($temp[$k]);
|
||||||
|
}
|
||||||
|
$data = $this->__compareSgs($data, $existingSGs);
|
||||||
|
$existingSGs = [];
|
||||||
|
foreach ($temp as $k => $v) {
|
||||||
|
$existingSGs[$v['uuid']] = $v;
|
||||||
|
unset($temp[$k]);
|
||||||
|
}
|
||||||
|
$statusLevels = [
|
||||||
|
'same' => [
|
||||||
|
'colour' => 'success',
|
||||||
|
'message' => __('Remote sharing group is the same as local copy'),
|
||||||
|
'icon' => 'check-circle'
|
||||||
|
],
|
||||||
|
'different' => [
|
||||||
|
'colour' => 'warning',
|
||||||
|
'message' => __('Local and remote versions of the sharing groups are different.'),
|
||||||
|
'icon' => 'exclamation-circle'
|
||||||
|
],
|
||||||
|
'not_found' => [
|
||||||
|
'colour' => 'danger',
|
||||||
|
'message' => __('Local sharing group not found'),
|
||||||
|
'icon' => 'exclamation-triangle'
|
||||||
|
]
|
||||||
|
];
|
||||||
if (!empty($data)) {
|
if (!empty($data)) {
|
||||||
return [
|
return [
|
||||||
'type' => 'index',
|
'type' => 'index',
|
||||||
|
@ -773,21 +1018,48 @@ class MispConnector extends CommonConnectorTools
|
||||||
'top_bar' => [
|
'top_bar' => [
|
||||||
'children' => [
|
'children' => [
|
||||||
[
|
[
|
||||||
'type' => 'search',
|
'type' => 'simple',
|
||||||
'button' => __('Search'),
|
'children' => [
|
||||||
'placeholder' => __('Enter value to search'),
|
[
|
||||||
'data' => '',
|
'class' => 'hidden mass-select',
|
||||||
'searchKey' => 'value',
|
'text' => __('Fetch selected sharing groups'),
|
||||||
'additionalUrlParams' => $urlParams
|
'html' => '<i class="fas fa-download"></i> ',
|
||||||
|
'reload_url' => '/localTools/action/' . h($params['connection']['id']) . '/sharingGroupsAction',
|
||||||
|
'popover_url' => '/localTools/action/' . h($params['connection']['id']) . '/fetchSelectedSharingGroupsAction'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'text' => __('Push sharing groups'),
|
||||||
|
'html' => '<i class="fas fa-upload"></i> ',
|
||||||
|
'class' => 'btn btn-primary',
|
||||||
|
'reload_url' => '/localTools/action/' . h($params['connection']['id']) . '/SharingGroupsAction',
|
||||||
|
'popover_url' => '/localTools/action/' . h($params['connection']['id']) . '/pushSharingGroupsAction'
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
]
|
||||||
|
],
|
||||||
'fields' => [
|
'fields' => [
|
||||||
|
[
|
||||||
|
'element' => 'selector',
|
||||||
|
'class' => 'short',
|
||||||
|
'data' => [
|
||||||
|
'id' => [
|
||||||
|
'value_path' => 'SharingGroup.uuid'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'name' => 'Name',
|
'name' => 'Name',
|
||||||
'sort' => 'SharingGroup.name',
|
'sort' => 'SharingGroup.name',
|
||||||
'data_path' => 'SharingGroup.name',
|
'data_path' => 'SharingGroup.name',
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Status',
|
||||||
|
'sort' => 'SharingGroup.local_copy',
|
||||||
|
'data_path' => 'SharingGroup.local_copy',
|
||||||
|
'element' => 'status',
|
||||||
|
'status_levels' => $statusLevels
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'name' => 'uuid',
|
'name' => 'uuid',
|
||||||
'sort' => 'SharingGroup.uuid',
|
'sort' => 'SharingGroup.uuid',
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Model\Entity;
|
||||||
|
|
||||||
|
use App\Model\Entity\AppModel;
|
||||||
|
use Cake\ORM\Entity;
|
||||||
|
|
||||||
|
class SGO extends AppModel
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -249,7 +249,7 @@ class InstanceTable extends AppTable
|
||||||
}
|
}
|
||||||
$data = [
|
$data = [
|
||||||
'broods' => $broods,
|
'broods' => $broods,
|
||||||
'tools' => $LocalToolsModel->extractMeta($connectors, true)
|
'tools' => $connections
|
||||||
];
|
];
|
||||||
if ($mermaid) {
|
if ($mermaid) {
|
||||||
return $this->generateTopologyMermaid($data);
|
return $this->generateTopologyMermaid($data);
|
||||||
|
@ -319,8 +319,19 @@ class InstanceTable extends AppTable
|
||||||
h($tool['name'])
|
h($tool['name'])
|
||||||
);
|
);
|
||||||
foreach ($tool['connections'] as $k2 => $connection) {
|
foreach ($tool['connections'] as $k2 => $connection) {
|
||||||
|
$diagnostic_output = '';
|
||||||
|
if (!empty($connection['diagnostics'])) {
|
||||||
|
foreach ($connection['diagnostics'] as $diagnostic => $diagnostic_data) {
|
||||||
|
$diagnostic_output .= sprintf(
|
||||||
|
"%s: <span class='text-%s'>%s</span><br />",
|
||||||
|
h($diagnostic),
|
||||||
|
h($diagnostic_data['type']),
|
||||||
|
h($diagnostic_data['message'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
$tools .= sprintf(
|
$tools .= sprintf(
|
||||||
" connection%s[%s<br />%s<br />%s]" . PHP_EOL,
|
" connection%s[\"%s<br />%s<br />%s%s\"]" . PHP_EOL,
|
||||||
h($k2),
|
h($k2),
|
||||||
h($connection['name']),
|
h($connection['name']),
|
||||||
sprintf(
|
sprintf(
|
||||||
|
@ -329,6 +340,7 @@ class InstanceTable extends AppTable
|
||||||
$connection['health'] === 1 ? 'text-success' : 'text-danger',
|
$connection['health'] === 1 ? 'text-success' : 'text-danger',
|
||||||
$connection['health'] === 1 ? 'fas:fa-check' : 'fas:fa-times'
|
$connection['health'] === 1 ? 'fas:fa-check' : 'fas:fa-times'
|
||||||
),
|
),
|
||||||
|
empty($diagnostic_data) ? '' : 'Diagnostics:<br />' . $diagnostic_output,
|
||||||
sprintf(
|
sprintf(
|
||||||
"<a href='%s'>fas:fa-eye</a>",
|
"<a href='%s'>fas:fa-eye</a>",
|
||||||
h($connection['url'])
|
h($connection['url'])
|
||||||
|
|
|
@ -147,14 +147,14 @@ class LocalToolsTable extends AppTable
|
||||||
'connector_settings_placeholder' => $connector_class->settingsPlaceholder ?? [],
|
'connector_settings_placeholder' => $connector_class->settingsPlaceholder ?? [],
|
||||||
];
|
];
|
||||||
if ($includeConnections) {
|
if ($includeConnections) {
|
||||||
$connector['connections'] = $this->healthCheck($connector_type, $connector_class);
|
$connector['connections'] = $this->healthCheck($connector_type, $connector_class, true);
|
||||||
}
|
}
|
||||||
$connectors[] = $connector;
|
$connectors[] = $connector;
|
||||||
}
|
}
|
||||||
return $connectors;
|
return $connectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function healthCheck(string $connector_type, Object $connector_class): array
|
public function healthCheck(string $connector_type, Object $connector_class, bool $includeDiagnostics = false): array
|
||||||
{
|
{
|
||||||
$query = $this->find();
|
$query = $this->find();
|
||||||
$query->where([
|
$query->where([
|
||||||
|
@ -162,11 +162,28 @@ class LocalToolsTable extends AppTable
|
||||||
]);
|
]);
|
||||||
$connections = $query->all()->toList();
|
$connections = $query->all()->toList();
|
||||||
foreach ($connections as &$connection) {
|
foreach ($connections as &$connection) {
|
||||||
$connection = $this->healthCheckIndividual($connection);
|
$temp = $this->healthCheckIndividual($connection);
|
||||||
|
if ($includeDiagnostics && !empty($temp['health']) && $temp['health'] === 1) {
|
||||||
|
$temp['diagnostics'] = $this->diagnosticCheckIndividual($connection);
|
||||||
|
}
|
||||||
|
$connection = $temp;
|
||||||
}
|
}
|
||||||
return $connections;
|
return $connections;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function diagnosticCheckIndividual(Object $connection): array
|
||||||
|
{
|
||||||
|
$connector_class = $this->getConnectors($connection->connector);
|
||||||
|
if (empty($connector_class[$connection->connector])) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$connector_class = $connector_class[$connection->connector];
|
||||||
|
return $connector_class->diagnostics([
|
||||||
|
'connection' => $connection,
|
||||||
|
'softError' => 1
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public function healthCheckIndividual(Object $connection): array
|
public function healthCheckIndividual(Object $connection): array
|
||||||
{
|
{
|
||||||
$connector_class = $this->getConnectors($connection->connector);
|
$connector_class = $this->getConnectors($connection->connector);
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Model\Table;
|
||||||
|
|
||||||
|
use App\Model\Table\AppTable;
|
||||||
|
use Cake\ORM\Table;
|
||||||
|
use Cake\Validation\Validator;
|
||||||
|
use Cake\ORM\RulesChecker;
|
||||||
|
use Cake\ORM\TableRegistry;
|
||||||
|
|
||||||
|
class SGOsTable extends AppTable
|
||||||
|
{
|
||||||
|
public function initialize(array $config): void
|
||||||
|
{
|
||||||
|
$this->setTable('sgo');
|
||||||
|
parent::initialize($config);
|
||||||
|
$this->belongsTo('SharingGroups');
|
||||||
|
$this->belongsTo('Organisations');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function attach(int $sg_id, int $org_id, array $additional_data = []): bool
|
||||||
|
{
|
||||||
|
$sgo = $this->find()->where([
|
||||||
|
'sharing_group_id' => $sg_id,
|
||||||
|
'organisation_id' => $org_id
|
||||||
|
])->first();
|
||||||
|
if (empty($sgo)) {
|
||||||
|
$sgo = $this->newEmptyEntity();
|
||||||
|
$sgo->sharing_group_id = $sg_id;
|
||||||
|
$sgo->organisation_id = $org_id;
|
||||||
|
}
|
||||||
|
$sgo->extend = empty($additional_data['extend']) ? 0 : 1;
|
||||||
|
if ($this->save($sgo)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function detach(): bool
|
||||||
|
{
|
||||||
|
$sgo = $this->find()->where([
|
||||||
|
'sharing_group_id' => $sg_id,
|
||||||
|
'organisation_id' => $org_id
|
||||||
|
])->first();
|
||||||
|
if (!empty($sgo)) {
|
||||||
|
if (!$this->delete($sgo)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,11 +25,11 @@ class SharingGroupsTable extends AppTable
|
||||||
$this->belongsToMany(
|
$this->belongsToMany(
|
||||||
'SharingGroupOrgs',
|
'SharingGroupOrgs',
|
||||||
[
|
[
|
||||||
|
'through' => 'SGOs',
|
||||||
'className' => 'Organisations',
|
'className' => 'Organisations',
|
||||||
'foreignKey' => 'sharing_group_id',
|
'foreignKey' => 'sharing_group_id',
|
||||||
'joinTable' => 'sgo',
|
|
||||||
'targetForeignKey' => 'organisation_id'
|
'targetForeignKey' => 'organisation_id'
|
||||||
]
|
],
|
||||||
);
|
);
|
||||||
$this->setDisplayField('name');
|
$this->setDisplayField('name');
|
||||||
}
|
}
|
||||||
|
@ -77,11 +77,14 @@ class SharingGroupsTable extends AppTable
|
||||||
|
|
||||||
public function postCaptureActions($savedEntity, $input): void
|
public function postCaptureActions($savedEntity, $input): void
|
||||||
{
|
{
|
||||||
$orgs = [];
|
$additional_data = [];
|
||||||
|
if (!empty($input['extend'])) {
|
||||||
|
$additional_data['extend'] = $input['extend'];
|
||||||
|
}
|
||||||
|
$this->SGO = TableRegistry::getTableLocator()->get('SGOs');
|
||||||
foreach ($input['sharing_group_orgs'] as $sgo) {
|
foreach ($input['sharing_group_orgs'] as $sgo) {
|
||||||
$organisation_id = $this->Organisations->captureOrg($sgo);
|
$organisation_id = $this->Organisations->captureOrg($sgo);
|
||||||
$orgs[] = $this->SharingGroupOrgs->get($organisation_id);
|
$this->SGO->attach($savedEntity->id, $organisation_id, $additional_data);
|
||||||
}
|
}
|
||||||
$this->SharingGroupOrgs->link($savedEntity, $orgs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,11 @@
|
||||||
'label' => __('Owner organisation'),
|
'label' => __('Owner organisation'),
|
||||||
'options' => $dropdownData['organisation']
|
'options' => $dropdownData['organisation']
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'field' => 'extend',
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'label' => __('Can extend/administer')
|
||||||
|
],
|
||||||
],
|
],
|
||||||
'submit' => [
|
'submit' => [
|
||||||
'action' => $this->request->getParam('action')
|
'action' => $this->request->getParam('action')
|
||||||
|
|
|
@ -42,6 +42,13 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
||||||
'sort' => 'uuid',
|
'sort' => 'uuid',
|
||||||
'class' => 'short',
|
'class' => 'short',
|
||||||
'data_path' => 'uuid',
|
'data_path' => 'uuid',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => __('Can extend/administer'),
|
||||||
|
'sort' => 'extend',
|
||||||
|
'element' => 'boolean',
|
||||||
|
'class' => 'short',
|
||||||
|
'data_path' => 'extend',
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'pull' => 'right',
|
'pull' => 'right',
|
||||||
|
|
Loading…
Reference in New Issue