new: [analystdata] wip

feature/analyst-data
iglocska 2024-01-04 10:12:47 +01:00
parent e73d1001a0
commit e04c810ae3
No known key found for this signature in database
GPG Key ID: BEA224F1FEF113AC
11 changed files with 542 additions and 22 deletions

View File

@ -0,0 +1,130 @@
<?php
App::uses('AppController', 'Controller');
class AnalystDataController extends AppController
{
public $components = ['Session', 'RequestHandler'];
public $paginate = [
'limit' => 60,
'order' => []
];
public $uses = [
'Opinion',
'Note',
'Relationship'
];
private $__valid_types = [
'Opinion',
'Note',
'Relationship'
];
public $modelSelection = 'Note';
private function _setViewElements()
{
$dropdownData = [];
$this->loadModel('Event');
$dropdownData['distributionLevels'] = $this->Event->distributionLevels;
$this->set('initialDistribution', Configure::read('MISP.default_event_distribution'));
$dropdownData['sgs'] = $this->Event->SharingGroup->fetchAllAuthorised($this->Auth->user(), 'name', 1);
$dropdownData['valid_targets'] = array_combine($this->AnalystData->valid_targets, $this->AnalystData->valid_targets);
$this->set(compact('dropdownData'));
$this->set('modelSelection', $this->modelSelection);
}
public function add($type = 'Note', $object_uuid = null, $object_type = null)
{
$this->__typeSelector($type);
if (!empty($object_uuid)) {
$this->request->data[$this->modelSelection]['object_uuid'] = $object_uuid;
}
if (!empty($object_type)) {
$this->request->data[$this->modelSelection]['object_type'] = $object_type;
}
if (empty($this->request->data[$this->modelSelection]['object_type']) && !empty($this->request->data[$this->modelSelection]['object_uuid'])) {
// Target uuid set, but no type provided, time to figure it out...
$this->request->data[$this->modelSelection]['object_type'] = $this->AnalystData->deduceType($object_uuid);
}
$params = [];
$this->CRUD->add($params);
if ($this->restResponsePayload) {
return $this->restResponsePayload;
}
$this->_setViewElements();
$this->set('menuData', array('menuList' => 'analyst_data', 'menuItem' => 'add'));
$this->render('add');
}
public function edit($type = 'Note', $id)
{
$this->__typeSelector($type);
$this->set('id', $id);
$params = [];
$this->CRUD->edit($id, $params);
if ($this->IndexFilter->isRest()) {
return $this->restResponsePayload;
}
$this->_setViewElements();
$this->set('menuData', array('menuList' => 'analyst_data', 'menuItem' => 'edit'));
$this->render('add');
}
public function delete($type = 'Note', $id)
{
$this->__typeSelector($type);
$this->CRUD->delete($id);
if ($this->IndexFilter->isRest()) {
return $this->restResponsePayload;
}
}
public function view($type = 'Note', $id)
{
$this->__typeSelector($type);
$this->set('menuData', array('menuList' => 'analyst_data', 'menuItem' => 'edit'));
$this->CRUD->view($id);
if ($this->IndexFilter->isRest()) {
return $this->restResponsePayload;
}
$this->set('id', $id);
$this->loadModel('Event');
$this->_setViewElements();
$this->set('distributionLevels', $this->Event->distributionLevels);
$this->render('view');
}
public function index($type = 'Note')
{
$this->__typeSelector($type);
$this->set('menuData', array('menuList' => 'analyst_data', 'menuItem' => 'index'));
$params = [
'filters' => ['uuid', 'target_object', 'uuid'],
'quickFilters' => ['name']
];
$this->CRUD->index($params);
if ($this->IndexFilter->isRest()) {
return $this->restResponsePayload;
}
$this->_setViewElements();
}
private function __typeSelector($type) {
foreach ($this->__valid_types as $vt) {
if ($type === $vt) {
$this->modelSelection = $vt;
$this->AnalystData = $this->{$vt};
$this->modelClass = $vt;
$this->{$vt}->current_user = $this->Auth->user();
return $vt;
}
}
throw new MethodNotAllowedException(__('Invalid type.'));
}
}

60
app/Model/AnalystData.php Normal file
View File

@ -0,0 +1,60 @@
<?php
App::uses('AppModel', 'Model');
class AnalystData extends AppModel
{
public $recursive = -1;
public $actsAs = array(
'Containable'
);
public $valid_targets = [
'Attribute',
'Event',
'GalaxyCluster',
'Galaxy',
'Object',
'Note',
'Opinion',
'Relationship',
'Organisation',
'SharingGroup'
];
public $current_user = null;
public function beforeValidate($options = array())
{
parent::beforeValidate();
if (empty($this->id) && empty($this->data[$this->current_type]['uuid'])) {
$this->data[$this->current_type]['uuid'] = CakeText::uuid();
}
if (empty($this->id)) {
if (empty($this->data[$this->current_type]['orgc_uuid']) || empty($this->current_user['Role']['perm_sync'])) {
$this->data[$this->current_type]['orgc_uuid'] = $this->current_user['Organisation']['uuid'];
}
$this->data[$this->current_type]['org_uuid'] = $this->current_user['Organisation']['uuid'];
$this->data[$this->current_type]['authors'] = $this->current_user['email'];
}
debug($this->data);
return true;
}
public function deduceType(string $uuid)
{
foreach ($this->valid_targets as $valid_target) {
$this->{$valid_target} = ClassRegistry::init($valid_target);
$result = $this->$valid_target->find('first', [
'conditions' => [$valid_target.'.uuid' => $uuid],
'recursive' => -1
]);
if (!empty($result)) {
return $valid_target;
}
}
throw new NotFoundException(__('Invalid UUID'));
}
}

View File

@ -2017,7 +2017,7 @@ class AppModel extends Model
`distribution` tinyint(4) NOT NULL,
`sharing_group_id` int(10) unsigned,
`note` mediumtext,
`language` varchar(16) DEFAULT 'en'
`language` varchar(16) DEFAULT 'en',
PRIMARY KEY (`id`),
UNIQUE KEY `uuid` (`uuid`),
KEY `object_uuid` (`object_uuid`),
@ -2041,7 +2041,7 @@ class AppModel extends Model
`distribution` tinyint(4) NOT NULL,
`sharing_group_id` int(10) unsigned,
`opinion` int(10) unsigned,
`comment` text
`comment` text,
PRIMARY KEY (`id`),
UNIQUE KEY `uuid` (`uuid`),
KEY `object_uuid` (`object_uuid`),
@ -2050,7 +2050,7 @@ class AppModel extends Model
KEY `orgc_uuid` (`orgc_uuid`),
KEY `distribution` (`distribution`),
KEY `sharing_group_id` (`sharing_group_id`),
KEY `opinion`
KEY `opinion` (`opinion`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;";
$sqlArray[] = "CREATE TABLE `relationships` (

View File

@ -0,0 +1,17 @@
<?php
/**
* Common functions for the 3 analyst objects
*/
class AnalystDataBehavior extends ModelBehavior
{
public function fetchForUuid()
{
}
public function checkACL()
{
}
}

24
app/Model/Note.php Normal file
View File

@ -0,0 +1,24 @@
<?php
App::uses('AppModel', 'Model');
App::uses('AnalystData', 'Model');
class Note extends AnalystData
{
public $recursive = -1;
public $actsAs = array(
'Containable',
'AnalystData'
);
public $current_type = 'Note';
public $validate = array(
);
public function beforeValidate($options = array())
{
parent::beforeValidate();
return true;
}
}

23
app/Model/Opinion.php Normal file
View File

@ -0,0 +1,23 @@
<?php
App::uses('AppModel', 'Model');
class Opinion extends AppModel
{
public $recursive = -1;
public $actsAs = array(
'Containable',
'AnalystData'
);
public $current_type = 'Opinion';
public $validate = array(
);
public function beforeValidate($options = array())
{
parent::beforeValidate();
return true;
}
}

View File

@ -0,0 +1,17 @@
<?php
App::uses('AppModel', 'Model');
class Relationship extends AnalystData
{
public $recursive = -1;
public $actsAs = array(
'Containable',
'AnalystData'
);
public $current_type = 'Relationship';
public $validate = array(
);
}

View File

@ -0,0 +1,70 @@
<?php
$edit = $this->request->params['action'] === 'edit' ? true : false;
$fields = [
[
'field' => 'object_type',
'class' => 'span2',
'disabled' => !empty($this->data[$modelSelection]['object_type']),
'default' => empty($this->data[$modelSelection]['object_type']) ? null : $this->data[$modelSelection]['object_type'],
'options' => $dropdownData['valid_targets'],
'type' => 'dropdown',
'stayInLine' => 1
],
[
'field' => 'object_uuid',
'class' => 'span4',
'disabled' => !empty($this->data[$modelSelection]['object_uuid']),
'default' => empty($this->data[$modelSelection]['object_uuid']) ? null : $this->data[$modelSelection]['object_uuid']
],
[
'field' => 'distribution',
'class' => 'input',
'options' => $dropdownData['distributionLevels'],
'default' => isset($attribute['Attribute']['distribution']) ? $attribute['Attribute']['distribution'] : $initialDistribution,
'stayInLine' => 1,
'type' => 'dropdown'
],
[
'field' => 'sharing_group_id',
'class' => 'input',
'options' => $dropdownData['sgs'],
'label' => __("Sharing Group"),
'type' => 'dropdown'
]
];
if ($modelSelection === 'Note') {
$fields = array_merge($fields,
[
[
'field' => 'language',
'class' => 'span3'
],
[
'field' => 'note',
'type' => 'textarea',
'class' => 'input span6'
]
]
);
} else if ($modelSelection === 'Opinion') {
} else if ($modelSelection === 'Relationship') {
}
echo $this->element('genericElements/Form/genericForm', [
'data' => [
'description' => false,
'model' => $modelSelection,
'title' => $edit ? __('Edit %s', $modelSelection) : __('Add new %s', $modelSelection),
'fields' => $fields,
'submit' => [
'action' => $this->request->params['action'],
'ajaxSubmit' => 'submitGenericFormInPlace();'
]
]
]);
if (!$ajax) {
echo $this->element('/genericElements/SideMenu/side_menu', $menuData);
}

View File

@ -0,0 +1,105 @@
<?php
$fields = [
[
'name' => __('Id'),
'sort' => $modelSelection . '.id',
'data_path' => $modelSelection . '.id'
],
[
'name' => __('UUID'),
'data_path' => $modelSelection . '.uuid'
],
[
'name' => __('Target Object'),
'sort' => $modelSelection . '.object_type',
'data_path' => $modelSelection . '.object_uuid'
],
[
'name' => __('Creator org'),
'data_path' => $modelSelection . '.orgc_id'
],
[
'name' => __('Created'),
'sort' => $modelSelection . '.created',
'data_path' => $modelSelection . '.created'
],
[
'name' => __('Modified'),
'sort' => $modelSelection . '.modified',
'data_path' => $modelSelection . '.modified'
],
[
'name' => __('Distribution'),
'sort' => $modelSelection . '.distribution',
'data_path' => $modelSelection . '.distribution'
]
];
if ($modelSelection === 'Note') {
$fields = array_merge($fields,
[
[
'name' => __('Language'),
'sort' => $modelSelection . '.language',
'data_path' => $modelSelection . '.language'
],
[
'name' => __('Note'),
'sort' => $modelSelection . '.note',
'data_path' => $modelSelection . '.note'
]
]
);
} else if ($modelSelection === 'Opinion') {
} else if ($modelSelection === 'Relationship') {
}
echo $this->element('genericElements/IndexTable/scaffold', [
'scaffold_data' => [
'data' => [
'data' => $data,
'top_bar' => [
'pull' => 'right',
'children' => [
[
'type' => 'search',
'button' => __('Filter'),
'placeholder' => __('Enter value to search'),
'data' => '',
'searchKey' => 'quickFilter'
]
]
],
'fields' => $fields,
'title' => empty($ajax) ? __('%s index', Inflector::pluralize($modelSelection)) : false,
'actions' => [
[
'url' => $baseurl . '/analystData/view/' . $modelSelection . '/',
'url_params_data_paths' => [$modelSelection . '.id'],
'icon' => 'eye'
],
[
'onclick' => sprintf(
'openGenericModal(\'%s/analystData/edit/' . $modelSelection . '/[onclick_params_data_path]\');',
$baseurl
),
'onclick_params_data_path' => $modelSelection . '.id',
'title' => __('Edit %s', $modelSelection),
'icon' => 'edit'
],
[
'onclick' => sprintf(
'openGenericModal(\'%s/analystData/edit/' . $modelSelection . '/[onclick_params_data_path]\');',
$baseurl
),
'onclick_params_data_path' => $modelSelection . '.id',
'icon' => 'trash'
]
]
]
]
]);
?>

View File

@ -0,0 +1,72 @@
<?php
echo $this->element(
'genericElements/SingleViews/single_view',
[
'title' => __('Note view'),
'data' => $data,
'fields' => [
[
'key' => __('ID'),
'path' => $modelSelection . '.id'
],
[
'key' => __('UUID'),
'path' => $modelSelection . '.uuid'
],
[
'key' => __('Target Object'),
'type' => 'custom',
'function' => function (array $row) use ($baseurl) {
$path = Inflector::pluralize(strtolower($row['Note']['object_type']));
return sprintf(
'<span class="bold">%s</span>: <a href="%s/%s/view/%s">%s</a>',
h($row['Note']['object_type']),
h($baseurl),
h($path),
h($row['Note']['object_uuid']),
h($row['Note']['object_uuid'])
);
}
],
[
'key' => __('Creator org'),
'path' => $modelSelection . '.orgc_uuid',
'pathName' => $modelSelection . '.orgc_uuid',
'type' => 'model',
'model' => 'organisations'
],
[
'key' => __('Owner org'),
'path' => $modelSelection . '.org_uuid',
'pathName' => $modelSelection . '.org_uuid',
'type' => 'model',
'model' => 'organisations'
],
[
'key' => __('Created'),
'path' => $modelSelection . '.created'
],
[
'key' => __('Modified'),
'path' => $modelSelection . '.modified'
],
[
'key' => __('Distribution'),
'path' => $modelSelection . '.distribution',
'event_id_path' => $modelSelection . '.id',
'disable_distribution_graph' => true,
'sg_path' => $modelSelection . '.sharing_group_id',
'type' => 'distribution'
],
[
'key' => __('Language'),
'path' => $modelSelection . '.language'
],
[
'key' => __('Note'),
'path' => $modelSelection . '.note'
]
]
]
);

View File

@ -24,25 +24,27 @@ if ($distribution == 4) {
}
$eventDistributionGraph = '';
if (!($distribution == 4 && empty($sg))) {
$eventDistributionGraph = sprintf(
'%s %s %s',
sprintf(
'<span id="distribution_graph_bar" style="margin-left: 5px;" data-object-id="%s" data-object-context="event"></span>',
h($event_id_path)
),
sprintf(
'<it class="%s" data-object-id="%s" data-object-context="event" data-shown="false"></it><div style="display: none">%s</div>',
'useCursorPointer fa fa-info-circle distribution_graph',
h($event_id_path),
$this->element('view_event_distribution_graph')
),
sprintf(
'<it type="button" id="showAdvancedSharingButton" title="%s" class="%s" aria-hidden="true" style="margin-left: 5px;"></it>',
__('Toggle advanced sharing network viewer'),
'fa fa-share-alt useCursorPointer'
)
);
if (empty($field['disable_distribution_graph'])) {
if (!($distribution == 4 && empty($sg))) {
$eventDistributionGraph = sprintf(
'%s %s %s',
sprintf(
'<span id="distribution_graph_bar" style="margin-left: 5px;" data-object-id="%s" data-object-context="event"></span>',
h($event_id_path)
),
sprintf(
'<it class="%s" data-object-id="%s" data-object-context="event" data-shown="false"></it><div style="display: none">%s</div>',
'useCursorPointer fa fa-info-circle distribution_graph',
h($event_id_path),
$this->element('view_event_distribution_graph')
),
sprintf(
'<it type="button" id="showAdvancedSharingButton" title="%s" class="%s" aria-hidden="true" style="margin-left: 5px;"></it>',
__('Toggle advanced sharing network viewer'),
'fa fa-share-alt useCursorPointer'
)
);
}
}
echo sprintf(