mirror of https://github.com/MISP/MISP
chg: [object:fromAttributes] Greatly improved UI - WiP
parent
a90ac883aa
commit
5798a73462
|
@ -1006,8 +1006,8 @@ class ObjectsController extends AppController
|
|||
return 1;
|
||||
} else if (!is_array($a['ObjectTemplate']['compatibility']) && is_array($b['ObjectTemplate']['compatibility'])) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
} else { // sort based on invalidTypes count
|
||||
return count($a['ObjectTemplate']['invalidTypes']) > count($b['ObjectTemplate']['invalidTypes']) ? 1 : -1;
|
||||
}
|
||||
});
|
||||
$this->set('potential_templates', $potential_templates);
|
||||
|
@ -1018,7 +1018,7 @@ class ObjectsController extends AppController
|
|||
{
|
||||
if ($this->request->is('post')) {
|
||||
$event_id = $object['Event']['id'];
|
||||
$event = $this->Object->Event->find('first', array(
|
||||
$event = $this->MispObject->Event->find('first', array(
|
||||
'recursive' => -1,
|
||||
'fields' => array('Event.id', 'Event.uuid', 'Event.orgc_id'),
|
||||
'conditions' => array('Event.id' => $event_id)
|
||||
|
@ -1026,22 +1026,36 @@ class ObjectsController extends AppController
|
|||
if (empty($event) || (!$this->_isSiteAdmin() && $event['Event']['orgc_id'] != $this->Auth->user('org_id'))) {
|
||||
throw new NotFoundException(__('Invalid event.'));
|
||||
}
|
||||
$template = $this->Object->ObjectTemplate->find('first', array(
|
||||
$template = $this->MispObject->ObjectTemplate->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('ObjectTemplate.id' => $selected_template, 'ObjectTemplate.active' => true)
|
||||
));
|
||||
if (empty($template)) {
|
||||
throw new NotFoundException(__('Invalid event.'));
|
||||
throw new NotFoundException(__('Invalid template.'));
|
||||
}
|
||||
} else {
|
||||
// TODO: validate
|
||||
$selected_attribute_ids = json_decode($selected_attribute_ids, true);
|
||||
$template = $this->MispObject->ObjectTemplate->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('ObjectTemplate.id' => $selected_template, 'ObjectTemplate.active' => true),
|
||||
'contain' => array('ObjectTemplateElement' => array('fields' => array('ObjectTemplateElement.object_relation', 'ObjectTemplateElement.type')))
|
||||
));
|
||||
if (empty($template)) {
|
||||
throw new NotFoundException(__('Invalid template.'));
|
||||
}
|
||||
$object_relations = array();
|
||||
foreach ($template['ObjectTemplateElement'] as $template_element) {
|
||||
$object_relations[$template_element['type']][] = $template_element['object_relation'];
|
||||
}
|
||||
$distributionData = $this->MispObject->Event->Attribute->fetchDistributionData($this->Auth->user());
|
||||
$this->set('distributionData', $distributionData);
|
||||
$this->set('distributionLevels', $this->MispObject->Attribute->distributionLevels);
|
||||
$this->set('selectedTemplateTd', $selected_template);
|
||||
$this->set('selectedAttributeIds', $selected_attribute_ids);
|
||||
$selected_attributes = $this->MispObject->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => array('Attribute.id' => $selected_attribute_ids)));
|
||||
$this->set('template', $template);
|
||||
$this->set('object_relations', $object_relations);
|
||||
$this->set('attributes', $selected_attributes);
|
||||
|
||||
}
|
||||
|
|
|
@ -732,26 +732,78 @@ class MispObject extends AppModel
|
|||
array(
|
||||
'conditions' => array(
|
||||
'id' => $selected,
|
||||
'event_id' => $event_id
|
||||
'event_id' => $event_id,
|
||||
'object_id' => 0
|
||||
),
|
||||
)
|
||||
);
|
||||
// $attribute_types = array_keys(Hash::combine($attributes, '{n}.Attribute.type'));
|
||||
if (empty($attributes)) {
|
||||
return array();
|
||||
}
|
||||
$attribute_types = array();
|
||||
foreach ($attributes as $i => $attribute) {
|
||||
$attribute_types[$attribute['Attribute']['type']] = 1;
|
||||
$attributes[$i]['Attribute']['object_relation'] = $attribute['Attribute']['type'];
|
||||
}
|
||||
$attribute_types = array_keys($attribute_types);
|
||||
array_walk($attribute_types, function(&$value) { $value = '"' . $value . '"'; });
|
||||
$db = $this->getDataSource();
|
||||
$potential_templates = $db->fetchAll(
|
||||
'SELECT object_templates.id, object_templates.name, count(object_template_elements.type) as type_count FROM object_templates '
|
||||
.'RIGHT JOIN object_template_elements ON object_templates.id = object_template_elements.object_template_id '
|
||||
.'WHERE object_templates.active=1 AND object_template_elements.type IN (' . implode(',', $attribute_types) . ') '
|
||||
.'GROUP BY object_templates.name ORDER BY type_count DESC;'
|
||||
);
|
||||
$potential_template_ids = Hash::extract($potential_templates, '{n}.object_templates.id');
|
||||
// # TEST 1
|
||||
// array_walk($attribute_types, function(&$value) { $value = '"' . $value . '"'; });
|
||||
// $potential_templates = $db->fetchAll(
|
||||
// 'SELECT object_templates.id, object_templates.name, count(object_template_elements.type) as type_count FROM object_templates '
|
||||
// .'RIGHT JOIN object_template_elements ON object_templates.id = object_template_elements.object_template_id '
|
||||
// .'WHERE object_templates.active=1 AND object_template_elements.type IN (' . implode(',', $attribute_types) . ') '
|
||||
// .'GROUP BY object_templates.name ORDER BY type_count DESC;'
|
||||
// );
|
||||
// $potential_template_ids = Hash::extract($potential_templates, '{n}.object_templates.id');
|
||||
|
||||
// TEST 2
|
||||
// $potential_templates = $this->ObjectTemplate->find('all', array(
|
||||
// 'recursive' => -1,
|
||||
// 'fields' => array(
|
||||
// 'ObjectTemplate.id',
|
||||
// 'ObjectTemplate.name',
|
||||
// 'COUNT(ObjectTemplateElement.type) as type_count'
|
||||
// ),
|
||||
// 'conditions' => array(
|
||||
// 'ObjectTemplate.active' => true,
|
||||
// ),
|
||||
// 'contain' => array(
|
||||
// 'ObjectTemplateElement' => array(
|
||||
// 'fields' => array('ObjectTemplateElement.object_relation', 'ObjectTemplateElement.type'),
|
||||
// 'conditions' => array('ObjectTemplateElement.type' => $attribute_types)
|
||||
// )
|
||||
// ),
|
||||
// 'group' => 'ObjectTemplate.name',
|
||||
// 'order' => 'type_count DESC'
|
||||
// ));
|
||||
|
||||
$potential_templates = $this->ObjectTemplate->find('all', array(
|
||||
'recursive' => -1,
|
||||
'fields' => array(
|
||||
'ObjectTemplate.id',
|
||||
'ObjectTemplate.name',
|
||||
'COUNT(ObjectTemplateElement.type) as type_count'
|
||||
),
|
||||
'conditions' => array(
|
||||
'ObjectTemplate.active' => true,
|
||||
'ObjectTemplateElement.type' => $attribute_types
|
||||
),
|
||||
'joins' => array(
|
||||
array(
|
||||
'table' => $db->fullTableName($this->ObjectTemplate->ObjectTemplateElement),
|
||||
'alias' => 'ObjectTemplateElement',
|
||||
'type' => 'RIGHT',
|
||||
'fields' => array('ObjectTemplateElement.object_relation', 'ObjectTemplateElement.type'),
|
||||
'conditions' => array('ObjectTemplate.id = ObjectTemplateElement.object_template_id')
|
||||
)
|
||||
),
|
||||
'group' => 'ObjectTemplate.name',
|
||||
'order' => 'type_count DESC'
|
||||
));
|
||||
|
||||
$potential_template_ids = Hash::extract($potential_templates, '{n}.ObjectTemplate.id');
|
||||
$templates = $this->ObjectTemplate->find('all', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('id' => $potential_template_ids),
|
||||
|
@ -759,7 +811,10 @@ class MispObject extends AppModel
|
|||
));
|
||||
|
||||
foreach ($templates as $i => $template) {
|
||||
$templates[$i]['ObjectTemplate']['compatibility'] = $this->ObjectTemplate->checkTemplateConformityBasedOnTypes($template, $attributes);
|
||||
$res = $this->ObjectTemplate->checkTemplateConformityBasedOnTypes($template, $attributes);
|
||||
$templates[$i]['ObjectTemplate']['compatibility'] = $res['valid'] ? true : $res['missingTypes'];
|
||||
$templates[$i]['ObjectTemplate']['invalidTypes'] = $res['invalidTypes'];
|
||||
$templates[$i]['ObjectTemplate']['invalidTypesMultiple'] = $res['invalidTypesMultiple'];
|
||||
}
|
||||
return $templates;
|
||||
}
|
||||
|
|
|
@ -206,6 +206,7 @@ class ObjectTemplate extends AppModel
|
|||
|
||||
public function checkTemplateConformityBasedOnTypes($template, $attributes)
|
||||
{
|
||||
$to_return = array('valid' => true, 'missingTypes' => array());
|
||||
if (!empty($template['ObjectTemplate']['requirements'])) {
|
||||
// check for all required attributes
|
||||
if (!empty($template['ObjectTemplate']['requirements']['required'])) {
|
||||
|
@ -218,7 +219,7 @@ class ObjectTemplate extends AppModel
|
|||
}
|
||||
}
|
||||
if (!$found) {
|
||||
return array($requiredType);
|
||||
$to_return = array('valid' => false, 'missingTypes' => array($requiredType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -236,12 +237,38 @@ class ObjectTemplate extends AppModel
|
|||
}
|
||||
}
|
||||
if (!$found) {
|
||||
return $all_required_type;
|
||||
$to_return = array('valid' => false, 'missingTypes' => $all_required_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
// multiple flag ignored. Will be taken care of in client view. For now?
|
||||
return true;
|
||||
|
||||
// at this point, an object can be created; checking if all attribute are valids
|
||||
$valid_types = array();
|
||||
$to_return['invalidTypes'] = array();
|
||||
$to_return['invalidTypesMultiple'] = array();
|
||||
foreach ($template['ObjectTemplateElement'] as $templateElement) {
|
||||
$valid_types[$templateElement['type']] = $templateElement['multiple'];
|
||||
}
|
||||
$check_for_multiple_type = array();
|
||||
foreach ($attributes as $attribute) {
|
||||
if (isset($valid_types[$attribute['Attribute']['type']])) {
|
||||
if (!$valid_types[$attribute['Attribute']['type']]) { // is not multiple
|
||||
if (isset($check_for_multiple_type[$attribute['Attribute']['type']])) {
|
||||
$to_return['invalidTypesMultiple'][] = $attribute['Attribute']['type'];
|
||||
} else {
|
||||
$check_for_multiple_type[$attribute['Attribute']['type']] = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$to_return['invalidTypes'][] = $attribute['Attribute']['type'];
|
||||
}
|
||||
}
|
||||
$to_return['invalidTypes'] = array_unique($to_return['invalidTypes']);
|
||||
$to_return['invalidTypesMultiple'] = array_unique($to_return['invalidTypesMultiple']);
|
||||
if (!empty($to_return['invalidTypesMultiple'])) {
|
||||
$to_return['valid'] = false;
|
||||
}
|
||||
return $to_return;
|
||||
}
|
||||
|
||||
// simple test to see if there are any object templates - if not trigger update
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
<button class="btn btn-inverse" onclick="showObjectProposition()"><i class="fas fa-chevron-left"></i></button>
|
||||
<?php
|
||||
echo $this->Form->create('Object');
|
||||
?>
|
||||
<dl style="margin-top: 10px;">
|
||||
<dt><?php echo __('Object Template');?></dt>
|
||||
<dd><a href="<?php echo $baseurl . '/ObjectTemplates/view/' . h($template['ObjectTemplate']['id']) ?>"><?php echo Inflector::humanize(h($template['ObjectTemplate']['name'])) . ' v' . h($template['ObjectTemplate']['version']); ?></a></dd>
|
||||
<dt><?php echo __('Description');?></dt>
|
||||
<dd><?php echo h($template['ObjectTemplate']['description']); ?></dd>
|
||||
<dt><?php echo __('Meta category');?></dt>
|
||||
<dd><?php echo h($template['ObjectTemplate']['meta-category']); ?></dd>
|
||||
<dt><?php echo __('Distribution');?></dt>
|
||||
<dd>
|
||||
<?php echo $this->Form->input('Object.distribution', array(
|
||||
'class' => 'Object_distribution_select',
|
||||
'options' => $distributionData['levels'],
|
||||
'default' => $distributionData['initial'],
|
||||
'label' => false,
|
||||
'style' => 'margin-bottom:5px;',
|
||||
'div' => false
|
||||
)); ?>
|
||||
<?php echo $this->Form->input('Object.sharing_group_id', array(
|
||||
'class' => 'Object_sharing_group_id_select',
|
||||
'options' => $distributionData['sgs'],
|
||||
'label' => false,
|
||||
'div' => false,
|
||||
'style' => 'display:none;margin-bottom:5px;'
|
||||
)); ?>
|
||||
<dt><?php echo __('Comment');?></dt>
|
||||
<dd>
|
||||
<?php echo $this->Form->input('Object.comment', array(
|
||||
'type' => 'textarea',
|
||||
'style' => 'height:20px;width:400px;',
|
||||
'required' => false,
|
||||
'allowEmpty' => true,
|
||||
'label' => false,
|
||||
'div' => false
|
||||
)); ?>
|
||||
<div class="hidden">
|
||||
<?php
|
||||
echo $this->Form->input('selectedTemplateId', array('hiddenField' => false, 'value' => $selectedTemplateTd));
|
||||
echo $this->Form->input('selectedAttributeIds', array('hiddenField' => false, 'value' => $selectedAttributeIds));
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
<div style="border: 2px solid #3465a4 ; border-radius: 3px; overflow: hidden;">
|
||||
<table class="table table-striped table-condensed" style="margin-bottom: 0px;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php echo __('ID'); ?></th>
|
||||
<th><?php echo __('Type'); ?></th>
|
||||
<th><?php echo __('Date'); ?></th>
|
||||
<th><?php echo __('Category'); ?></th>
|
||||
<th><?php echo __('Value'); ?></th>
|
||||
<th><?php echo __('Distribution'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($attributes as $attribute): ?>
|
||||
<tr>
|
||||
<td><?php echo h($attribute['Attribute']['id']); ?></td>
|
||||
<td>
|
||||
<select>
|
||||
<?php foreach ($object_relations[$attribute['Attribute']['type']] as $object_relation): ?>
|
||||
<option value="<?php echo h($object_relation); ?>"><?php echo h($object_relation); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
:: <?php echo h($attribute['Attribute']['type']); ?>
|
||||
</td>
|
||||
<td><?php echo h(date('Y-m-d', $attribute['Attribute']['timestamp'])); ?></td>
|
||||
<td><?php echo h($attribute['Attribute']['category']); ?></td>
|
||||
<td><?php echo h($attribute['Attribute']['value']); ?></td>
|
||||
<td><?php echo h($distributionLevels[$attribute['Attribute']['distribution']]); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 15px; text-align: center;">
|
||||
<button class="btn btn-primary">Merge Selected Attribute into an Object</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(".Object_distribution_select").change(function() {
|
||||
checkAndEnable($(this).parent().find('.Object_sharing_group_id_select'), $(this).val() == 4);
|
||||
});
|
||||
</script>
|
|
@ -1,4 +1,7 @@
|
|||
<div style="max-width: 1000px; max-height: 800px; overflow-y: auto;">
|
||||
<?php if (empty($potential_templates)): ?>
|
||||
<?php echo __('No matching Object.'); ?>
|
||||
<?php else: ?>
|
||||
<table id="tableGroupAttributeIntoObject" class="table table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -11,7 +14,7 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($potential_templates as $i => $potential_template): ?>
|
||||
<tr class="useCursorPointer" data-objecttemplateid="<?php echo h($potential_template['ObjectTemplate']['id']); ?>">
|
||||
<tr class="useCursorPointer" style="<?php echo $potential_template['ObjectTemplate']['compatibility'] === true ? '' : 'cursor: not-allowed;' ?>" data-objecttemplateid="<?php echo h($potential_template['ObjectTemplate']['id']); ?>" data-enabled="<?php echo $potential_template['ObjectTemplate']['compatibility'] === true ? 'true' : 'false'; ?>">
|
||||
<td class="ignoreSelection">
|
||||
<a href="<?php echo $baseurl . '/ObjectTemplates/view/' . h($potential_template['ObjectTemplate']['id']) ?>"><?php echo h($potential_template['ObjectTemplate']['id']); ?></a>
|
||||
</td>
|
||||
|
@ -25,30 +28,41 @@
|
|||
<?php echo $v; ?>
|
||||
</td>
|
||||
<?php if ($potential_template['ObjectTemplate']['compatibility'] === true): ?>
|
||||
<td><i class="fa fa-check"></i></td>
|
||||
<td>
|
||||
<i class="fa fa-check"></i>
|
||||
<?php if (!empty($potential_template['ObjectTemplate']['invalidTypes'])): ?>
|
||||
<?php foreach ($potential_template['ObjectTemplate']['invalidTypes'] as $type): ?>
|
||||
<span class="label label-warning" title="<?php echo __('This Attribute type cannot be part of this Object template. If you merge the selected Attributes into this object, all Attribute having this type will be ignored.'); ?>"><?php echo h($type); ?></span>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<?php else: ?>
|
||||
<td style="max-width: 500px;">
|
||||
<?php foreach ($potential_template['ObjectTemplate']['compatibility'] as $type): ?>
|
||||
<span class="label label-important" title="<?php echo __('This Attribute type is missing from the selection. Add it to the selection to be able to merge the selected Attributes into this Object.'); ?>"><?php echo h($type); ?></span>
|
||||
<?php endforeach; ?>
|
||||
<?php foreach ($potential_template['ObjectTemplate']['invalidTypesMultiple'] as $type): ?>
|
||||
<span class="label" title="<?php echo __('This Attribute type is not allowed to be present multiple time in this Object. Consider only picking one.'); ?>"><?php echo h($type); ?></span>
|
||||
<?php endforeach; ?>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<div id="resultPreview" style="height: 100%;"></div>
|
||||
<div id="resultPreview" class="hidden" style="height: 100%;"></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$('#tableGroupAttributeIntoObject > tbody > tr > td:not(.ignoreSelection)').click(function() {
|
||||
$('#tableGroupAttributeIntoObject > tbody > tr[data-enabled="true"] > td:not(.ignoreSelection)').click(function() {
|
||||
var object_template_id = $(this).parent().data('objecttemplateid');
|
||||
if (object_template_id !== undefined) {
|
||||
var $parentDIV = $('#tableGroupAttributeIntoObject').parent();
|
||||
var bb = $parentDIV[0].getBoundingClientRect();
|
||||
$parentDIV.css({height: bb.height, width: bb.width});
|
||||
$('#tableGroupAttributeIntoObject').toggle('slide');
|
||||
$('#resultPreview').html('<div style="align-items: center; justify-content: center; display: flex; height: 100%; width: 100%"><i class="fas fa-spinner fa-spin" style="font-size: xx-large;"></i></div>');
|
||||
$('#resultPreview').show().html('<div style="align-items: center; justify-content: center; display: flex; height: 100%; width: 100%"><i class="fas fa-spinner fa-spin" style="font-size: xx-large;"></i></div>');
|
||||
$.get('<?php echo $baseurl . '/objects/mergeObjectsFromAttributes/' . h($event_id) . '/' ?>' + object_template_id + '/' + getSelected(), function(data) {
|
||||
$('#resultPreview').html(data);
|
||||
});
|
||||
|
@ -60,5 +74,6 @@
|
|||
$('#tableGroupAttributeIntoObject').toggle('slide', {
|
||||
direction: 'left',
|
||||
});
|
||||
$('#resultPreview').hide();
|
||||
}
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue