new: [object] Allows updating from an unknown object templates

pull/7024/head
mokaddem 2021-02-16 10:59:18 +01:00
parent b6f5844350
commit a7834a291b
No known key found for this signature in database
GPG Key ID: 164C473F627A06FA
3 changed files with 97 additions and 56 deletions

View File

@ -376,13 +376,14 @@ class ObjectsController extends AppController
'ObjectTemplateElement'
)
));
if (empty($template) && !$this->_isRest()) {
$this->Flash->error('Object cannot be edited, no valid template found.');
if (empty($template) && !$this->_isRest() && !$update_template_available) {
$this->Flash->error('Object cannot be edited, no valid template found. ', ['params' => ['url' => sprintf('/objects/edit/%s/1/0', $id), 'urlName' => __('Force update anyway')]]);
$this->redirect(array('controller' => 'events', 'action' => 'view', $object['Object']['event_id']));
}
$templateData = $this->MispObject->resolveUpdatedTemplate($template, $object, $update_template_available);
$this->set('updateable_attribute', $templateData['updateable_attribute']);
$this->set('not_updateable_attribute', $templateData['not_updateable_attribute']);
$this->set('original_template_unkown', $templateData['original_template_unkown']);
if (!empty($this->Session->read('object_being_created')) && !empty($this->params['named']['cur_object_tmp_uuid'])) {
$revisedObjectData = $this->Session->read('object_being_created');
if ($this->params['named']['cur_object_tmp_uuid'] == $revisedObjectData['cur_object_tmp_uuid']) { // ensure that the passed session data is for the correct object

View File

@ -1233,64 +1233,90 @@ class MispObject extends AppModel
'updateable_attribute' => false,
'not_updateable_attribute' => false,
'newer_template_version' => false,
'original_template_unkown' => false,
'template' => $template
);
if (!empty($template)) {
$newer_template = $this->ObjectTemplate->find('first', array(
'conditions' => array(
'ObjectTemplate.uuid' => $object['Object']['template_uuid'],
'ObjectTemplate.version >' => $object['Object']['template_version'],
),
'recursive' => -1,
'contain' => array(
'ObjectTemplateElement'
),
'order' => array('ObjectTemplate.version DESC')
));
if (!empty($newer_template)) {
$toReturn['newer_template_version'] = $newer_template['ObjectTemplate']['version'];
// ignore IDs for comparison
$cur_template_temp = Hash::remove(Hash::remove($template['ObjectTemplateElement'], '{n}.id'), '{n}.object_template_id');
$newer_template_temp = Hash::remove(Hash::remove($newer_template['ObjectTemplateElement'], '{n}.id'), '{n}.object_template_id');
$newer_template = $this->ObjectTemplate->find('first', array(
'conditions' => array(
'ObjectTemplate.uuid' => $object['Object']['template_uuid'],
'ObjectTemplate.version >' => $object['Object']['template_version'],
),
'recursive' => -1,
'contain' => array(
'ObjectTemplateElement'
),
'order' => array('ObjectTemplate.version DESC')
));
$template_difference = array();
if (!empty($newer_template)) {
$toReturn['newer_template_version'] = !$newer_template['ObjectTemplate']['version'];
$newer_template_temp = Hash::remove(Hash::remove($newer_template['ObjectTemplateElement'], '{n}.id'), '{n}.object_template_id');
if (!empty($template)) {
// ignore IDs for comparison
$cur_template_temp = Hash::remove(Hash::remove($template['ObjectTemplateElement'], '{n}.id'), '{n}.object_template_id');
$template_difference = array();
// check how current template is included in the newer
foreach ($cur_template_temp as $cur_obj_rel) {
$flag_sim = false;
foreach ($newer_template_temp as $newer_obj_rel) {
$tmp = Hash::diff($cur_obj_rel, $newer_obj_rel);
if (count($tmp) == 0) {
$flag_sim = true;
break;
}
}
if (!$flag_sim) {
$template_difference[] = $cur_obj_rel;
}
}
$toReturn['updateable_attribute'] = $object['Attribute'];
$toReturn['not_updateable_attribute'] = array();
} else {
$toReturn['newer_template_version'] = false;
}
if (!empty($template_difference)) { // older template not completely embeded in newer
foreach ($template_difference as $temp_diff_element) {
foreach ($object['Attribute'] as $i => $attribute) {
if (
$attribute['object_relation'] == $temp_diff_element['object_relation']
&& $attribute['type'] == $temp_diff_element['type']
) { // This attribute cannot be merged automatically
$attribute['merge-possible'] = false;
$toReturn['not_updateable_attribute'][] = $attribute;
unset($toReturn['updateable_attribute'][$i]);
// check how current template is included in the newer
foreach ($cur_template_temp as $cur_obj_rel) {
$flag_sim = false;
foreach ($newer_template_temp as $newer_obj_rel) {
$tmp = Hash::diff($cur_obj_rel, $newer_obj_rel);
if (count($tmp) == 0) {
$flag_sim = true;
break;
}
}
if (!$flag_sim) {
$template_difference[] = $cur_obj_rel;
}
}
} else { // original template unkown
$toReturn['original_template_unkown'] = true;
$unmatched_attributes = array();
foreach ($object['Attribute'] as $i => $attribute) {
$flag_match = false;
foreach ($newer_template_temp as $newer_obj_rel) {
if (
$newer_obj_rel['object_relation'] == $attribute['object_relation'] &&
$newer_obj_rel['type'] == $attribute['type']
) {
$flag_match = true;
break;
}
}
if (!$flag_match) {
$unmatched_attributes[] = $attribute;
}
}
// simulate unkown template from the attribute
foreach ($unmatched_attributes as $unmatched_attribute) {
$template_difference[] = [
'object_relation' => $unmatched_attribute['object_relation'],
'type' => $unmatched_attribute['type']
];
}
}
$toReturn['updateable_attribute'] = $object['Attribute'];
$toReturn['not_updateable_attribute'] = array();
} else {
$toReturn['newer_template_version'] = false;
}
if (!empty($template_difference)) { // older template not completely embeded in newer
foreach ($template_difference as $temp_diff_element) {
foreach ($object['Attribute'] as $i => $attribute) {
if (
$attribute['object_relation'] == $temp_diff_element['object_relation']
&& $attribute['type'] == $temp_diff_element['type']
) { // This attribute cannot be merged automatically
$attribute['merge-possible'] = false;
$toReturn['not_updateable_attribute'][] = $attribute;
unset($toReturn['updateable_attribute'][$i]);
}
}
}
if ($update_template_available) { // template version bump requested
$toReturn['template'] = $newer_template; // bump the template version
}
}
if ($update_template_available) { // template version bump requested
$toReturn['template'] = $newer_template; // bump the template version
}
return $toReturn;
}

View File

@ -208,7 +208,7 @@
<span style="margin-left: 5px; display: inline-block; font-size: large;"><?php echo __('Current Object state on older template version'); ?></span>
</div>
<div class="row" style="max-height: 800px; max-width: 800px; overflow: auto; padding: 15px;">
<div style="border: 1px solid #3465a4 ; border-radius: 5px; overflow: hidden;" class="span5">
<div style="border: 1px solid #3465a4 ; border-radius: 5px; overflow: auto;" class="span5">
<div class="blueElement" style="padding: 4px 5px;">
<div>
<span class="bold"><?php echo __('ID') . ':'; ?></span>
@ -229,9 +229,22 @@
<div style="background-color: #fcf8e3; color: black; padding: 2px; border-radius: 3px;">
<span class="bold"><?php echo __('Template version') . ':'; ?></span>
<span><?php echo h($object['Object']['template_version']); ?></span>
<?php if ($original_template_unkown): ?>
<span class="label label-important" title="<?= __('The original object\'s template is unkown and some attributes might be lost. Please review carefully'); ?>">
<?= __('Unkown original template'); ?>
</span>
<?php endif; ?>
</div>
</div>
<table class="table table-striped table-condensed" style="margin-bottom: 0px;">
<thead>
<tr>
<th><?= __('Obj. rel.') ?></th>
<th><?= __('Categ.') ?></th>
<th><?= __('Type') ?></th>
<th><?= __('Value') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($not_updateable_attribute as $attribute): ?>
<tr class="error" title="<?php echo __('Can not be merged automatically'); ?>">
@ -245,7 +258,7 @@
</td>
<td><?php echo h($attribute['category']); ?></td>
<td><?php echo h($attribute['type']); ?></td>
<td><?php echo h($attribute['value']); ?></td>
<td style="max-width:100px;" class="ellipsis-overflow"><?php echo h($attribute['value']); ?></td>
</tr>
<?php if (!$attribute['merge-possible']): ?>
<?php
@ -275,7 +288,7 @@
<td style="white-space: nowrap;"><?php echo h($attribute['object_relation']); ?></td>
<td><?php echo h($attribute['category']); ?></td>
<td><?php echo h($attribute['type']); ?></td>
<td><?php echo h($attribute['value']); ?></td>
<td style="max-width:100px;" class="ellipsis-overflow"><?php echo h($attribute['value']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
@ -401,6 +414,7 @@
$value_field.val(revised_value);
$clicked.removeClass('fa-sign-in-alt fa-flip-horizontal').addClass('fa-trash-restore');
}
$matching_row.find('input[type="checkbox"][name$="[save]').first().prop('checked', true).prop('disabled', false)
$matching_row[0].scrollIntoView(false);
$matching_row.children().effect('highlight', { queue: false, color: $value_field.val() === selected_value ? '#468847' : '#b94a48' }, 2500, function() { $(this).css('background-color', 'unset'); });
}