From b29c0ccacad62b53828790dac2c01afae4962a41 Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Fri, 29 Jul 2022 17:18:16 +0200 Subject: [PATCH 001/111] fix: [UI] Handling non exists user setting --- app/Controller/UserSettingsController.php | 41 ++++++++++++----------- app/View/UserSettings/set_setting.ctp | 17 ++++++---- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/app/Controller/UserSettingsController.php b/app/Controller/UserSettingsController.php index f589706ff..6f3578cf0 100644 --- a/app/Controller/UserSettingsController.php +++ b/app/Controller/UserSettingsController.php @@ -213,27 +213,28 @@ class UserSettingsController extends AppController if ($this->_isRest()) { // GET request via the API should describe the endpoint return $this->RestResponse->describe('UserSettings', 'setSetting', false, $this->response->type()); - } else { - // load the valid settings from the model - if ($this->_isSiteAdmin()) { - $users = $this->UserSetting->User->find('list', array( - 'fields' => array('User.id', 'User.email') - )); - } else if ($this->_isAdmin()) { - $users = $this->UserSetting->User->find('list', array( - 'conditions' => array('User.org_id' => $this->Auth->user('org_id')), - 'fields' => array('User.id', 'User.email') - )); - } else { - $users = array($this->Auth->user('id') => $this->Auth->user('email')); - } - if (!empty($user_id) && $this->request->is('get')) { - $this->request->data['UserSetting']['user_id'] = $user_id; - } - $this->set('setting', $setting); - $this->set('users', $users); - $this->set('validSettings', $this->UserSetting->settingPlaceholders($this->Auth->user())); } + + // load the valid settings from the model + if ($this->_isSiteAdmin()) { + $users = $this->UserSetting->User->find('list', array( + 'fields' => array('User.id', 'User.email') + )); + } else if ($this->_isAdmin()) { + $users = $this->UserSetting->User->find('list', array( + 'conditions' => array('User.org_id' => $this->Auth->user('org_id')), + 'fields' => array('User.id', 'User.email') + )); + } else { + $users = array($this->Auth->user('id') => $this->Auth->user('email')); + } + if (!empty($user_id) && $this->request->is('get')) { + $this->request->data['UserSetting']['user_id'] = $user_id; + } + $this->set('setting', $setting); + $this->set('users', $users); + $this->set('validSettings', $this->UserSetting->settingPlaceholders($this->Auth->user())); + $this->set('title_for_layout', __('Set User Setting')); } public function getSetting($userId = null, $setting = null) diff --git a/app/View/UserSettings/set_setting.ctp b/app/View/UserSettings/set_setting.ctp index 3031b18e7..a12f2c4d2 100644 --- a/app/View/UserSettings/set_setting.ctp +++ b/app/View/UserSettings/set_setting.ctp @@ -10,7 +10,7 @@ array( 'div' => 'clear', 'class' => 'input input-xxlarge', - 'options' => array($users), + 'options' => $users, 'disabled' => count($users) === 1 ) ), @@ -40,18 +40,16 @@ ?> From 4611a3b4b86ae6828bc27dc87d0cb017041c8751 Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Fri, 23 Sep 2022 12:04:55 +0200 Subject: [PATCH 102/111] chg: [UI] Scroll to object if not visible after adding attribute --- app/webroot/js/misp.js | 51 +++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/app/webroot/js/misp.js b/app/webroot/js/misp.js index 6e4cf8cf8..5892c990e 100644 --- a/app/webroot/js/misp.js +++ b/app/webroot/js/misp.js @@ -427,7 +427,7 @@ function eventUnpublish() { $('.notPublished').show(); } -function updateIndex(id, context) { +function updateIndex(id, context, callback) { var url, div; if (context === 'event') { if (typeof currentUri == 'undefined') { @@ -442,8 +442,12 @@ function updateIndex(id, context) { } xhr({ dataType: "html", - success:function (data) { + success: function (data) { $(div).html(data); + if (typeof callback !== "undefined") { + callback("success"); + } + if (typeof genericPopupCallback !== "undefined") { genericPopupCallback("success"); } else { @@ -1277,10 +1281,8 @@ function submitPopoverForm(context_id, referer, update_context_id, modal, popove $.get(baseurl + "/sightings/listSightings/" + id + "/attribute", function(data) { $("#sightingsData").html(data); }).fail(xhrFailCallback); - $('.sightingsToggle').removeClass('btn-primary'); - $('.sightingsToggle').addClass('btn-inverse'); - $('#sightingsListAllToggle').removeClass('btn-inverse'); - $('#sightingsListAllToggle').addClass('btn-primary'); + $('.sightingsToggle').removeClass('btn-primary').addClass('btn-inverse'); + $('#sightingsListAllToggle').removeClass('btn-inverse').addClass('btn-primary'); } if (referer === 'addEventReport' && typeof window.reloadEventReportTable === 'function') { reloadEventReportTable() @@ -1288,8 +1290,8 @@ function submitPopoverForm(context_id, referer, update_context_id, modal, popove } if ( ( - context == 'event' && - (referer == 'add' || referer == 'massEdit' || referer == 'replaceAttributes' || referer == 'addObjectReference' || referer == 'quickAddAttributeForm') + context === 'event' && + (referer === 'add' || referer === 'massEdit' || referer === 'replaceAttributes' || referer === 'addObjectReference' || referer === 'quickAddAttributeForm') ) ){ eventUnpublish(); @@ -1342,10 +1344,15 @@ function handleAjaxModalResponse(response, context_id, url, referer, context, co function handleAjaxPopoverResponse(response, context_id, url, referer, context, contextNamingConvention) { responseArray = response; - var message = null; var result = "fail"; if (responseArray.saved) { - updateIndex(context_id, context); + var callback = function() { + // Scroll to edited object after index is updated + if (referer === 'quickAddAttributeForm') { + scrollToElementIfNotVisible($("#Object_" + context_id + "_tr")); + } + } + updateIndex(context_id, context, callback); if (responseArray.success) { showMessage("success", responseArray.success); result = "success"; @@ -1356,8 +1363,8 @@ function handleAjaxPopoverResponse(response, context_id, url, referer, context, } else { var savedArray = saveValuesForPersistance(); $.ajax({ - dataType:"html", - success:function (data, textStatus) { + dataType: "html", + success: function (data, textStatus) { $("#popover_form").html(data); openPopup("#popover_form"); var error_context = context.charAt(0).toUpperCase() + context.slice(1); @@ -1371,7 +1378,7 @@ function handleAjaxPopoverResponse(response, context_id, url, referer, context, recoverValuesFromPersistance(savedArray); $(".loading").hide(); }, - url:url + url: url }); } return result; @@ -3668,6 +3675,24 @@ function pivotObjectReferences(url, uuid) { fetchAttributes(currentUri, {"focus": uuid}); } +function scrollToElementIfNotVisible($el) { + var isInViewport = function($el) { + var elementTop = $el.offset().top; + var elementBottom = elementTop + $el.outerHeight(); + + var viewportTop = $(window).scrollTop(); + var viewportBottom = viewportTop + $(window).height(); + + return elementBottom > viewportTop && elementTop < viewportBottom; + }; + + if ($el.length && !isInViewport($el)) { + $([document.documentElement, document.body]).animate({ + scrollTop: $el.offset().top - 45, // 42px is #topBar size, so make little bit more space + }); + } +} + // Attribute filtering function filterAttributes(filter) { var data; From fc0ceb820630c3bab7c0f88e621a9efab41751cf Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Fri, 23 Sep 2022 13:49:04 +0200 Subject: [PATCH 103/111] chg: [internal] Mark AppModel::convert_to_memory_limit_to_mb method as protected --- app/Model/AppModel.php | 2 +- app/Model/Event.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Model/AppModel.php b/app/Model/AppModel.php index 105e4f0a9..7de42bdeb 100644 --- a/app/Model/AppModel.php +++ b/app/Model/AppModel.php @@ -3257,7 +3257,7 @@ class AppModel extends Model return $filter; } - public function convert_to_memory_limit_to_mb($val) + protected function convert_to_memory_limit_to_mb($val) { $val = trim($val); if ($val == -1) { diff --git a/app/Model/Event.php b/app/Model/Event.php index 1d08d5c31..84f34bcbf 100755 --- a/app/Model/Event.php +++ b/app/Model/Event.php @@ -7029,7 +7029,7 @@ class Event extends AppModel */ private function __clusterEventIds($exportTool, $eventIds) { - $memory_in_mb = $this->Attribute->convert_to_memory_limit_to_mb(ini_get('memory_limit')); + $memory_in_mb = $this->convert_to_memory_limit_to_mb(ini_get('memory_limit')); $default_attribute_memory_coefficient = Configure::check('MISP.default_attribute_memory_coefficient') ? Configure::read('MISP.default_attribute_memory_coefficient') : 80; $default_event_memory_divisor = Configure::check('MISP.default_event_memory_multiplier') ? Configure::read('MISP.default_event_memory_divisor') : 3; $memory_scaling_factor = isset($exportTool->memory_scaling_factor) ? $exportTool->memory_scaling_factor : $default_attribute_memory_coefficient; From dca9803865b6f88779aea176df5aab9c5ac9b401 Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Fri, 23 Sep 2022 14:48:25 +0200 Subject: [PATCH 104/111] chg: [UI] Add object reference cleanup --- app/Controller/ObjectReferencesController.php | 114 +++++++++--------- app/Model/ObjectTemplateElement.php | 2 +- app/View/ObjectReferences/ajax/add.ctp | 8 +- app/webroot/js/misp.js | 43 ++++--- 4 files changed, 86 insertions(+), 81 deletions(-) diff --git a/app/Controller/ObjectReferencesController.php b/app/Controller/ObjectReferencesController.php index 3ef8956c0..73402f1fc 100644 --- a/app/Controller/ObjectReferencesController.php +++ b/app/Controller/ObjectReferencesController.php @@ -9,10 +9,10 @@ class ObjectReferencesController extends AppController public $components = array('RequestHandler', 'Session'); public $paginate = array( - 'limit' => 20, - 'order' => array( - 'ObjectReference.id' => 'desc' - ), + 'limit' => 20, + 'order' => array( + 'ObjectReference.id' => 'desc' + ), ); public function add($objectId = false) @@ -23,7 +23,7 @@ class ObjectReferencesController extends AppController } } if (empty($objectId)) { - throw new MethodNotAllowedException('No object defined.'); + throw new NotFoundException('No object defined.'); } if (Validation::uuid($objectId)) { $conditions = ['Object.uuid' => $objectId]; @@ -91,65 +91,63 @@ class ObjectReferencesController extends AppController } else { if ($this->_isRest()) { return $this->RestResponse->describe('ObjectReferences', 'add', false, $this->response->type()); - } else { - $events = $this->ObjectReference->Object->Event->find('all', array( - 'conditions' => array( - 'OR' => array( - 'Event.id' => $object['Event']['id'], - 'AND' => array( - 'Event.uuid' => $object['Event']['extends_uuid'], - $this->ObjectReference->Object->Event->createEventConditions($this->Auth->user()) - ) - ), + } + + $events = $this->ObjectReference->Object->Event->find('all', array( + 'conditions' => array( + 'OR' => array( + 'Event.id' => $object['Event']['id'], + 'AND' => array( + 'Event.uuid' => $object['Event']['extends_uuid'], + $this->ObjectReference->Object->Event->createEventConditions($this->Auth->user()) + ) ), - 'recursive' => -1, - 'fields' => array('Event.id'), - 'contain' => array( + ), + 'recursive' => -1, + 'fields' => array('Event.id'), + 'contain' => array( + 'Attribute' => array( + 'conditions' => array('Attribute.deleted' => 0, 'Attribute.object_id' => 0), + 'fields' => array('Attribute.id', 'Attribute.uuid', 'Attribute.type', 'Attribute.category', 'Attribute.value', 'Attribute.to_ids') + ), + 'Object' => array( + 'conditions' => array('NOT' => array('Object.id' => $object['Object']['id']), 'Object.deleted' => 0), + 'fields' => array('Object.id', 'Object.uuid', 'Object.name', 'Object.meta-category'), 'Attribute' => array( - 'conditions' => array('Attribute.deleted' => 0, 'Attribute.object_id' => 0), + 'conditions' => array('Attribute.deleted' => 0), 'fields' => array('Attribute.id', 'Attribute.uuid', 'Attribute.type', 'Attribute.category', 'Attribute.value', 'Attribute.to_ids') - ), - 'Object' => array( - 'conditions' => array('NOT' => array('Object.id' => $object['Object']['id']), 'Object.deleted' => 0), - 'fields' => array('Object.id', 'Object.uuid', 'Object.name', 'Object.meta-category'), - 'Attribute' => array( - 'conditions' => array('Attribute.deleted' => 0), - 'fields' => array('Attribute.id', 'Attribute.uuid', 'Attribute.type', 'Attribute.category', 'Attribute.value', 'Attribute.to_ids') - ) ) ) - )); - if (!empty($events)) { - $event = $events[0]; - } - for ($i=1; $i < count($events); $i++) { - $event['Attribute'] = array_merge($event['Attribute'], $events[$i]['Attribute']); - $event['Object'] = array_merge($event['Object'], $events[$i]['Object']); - } - $toRearrange = array('Attribute', 'Object'); - foreach ($toRearrange as $d) { - if (!empty($event[$d])) { - $temp = array(); - foreach ($event[$d] as $data) { - $temp[$data['uuid']] = $data; - } - $event[$d] = $temp; - } - } - $this->loadModel('ObjectRelationship'); - $relationships = $this->ObjectRelationship->find('column', array( - 'recursive' => -1, - 'fields' => ['name'], - )); - $relationships = array_combine($relationships, $relationships); - $relationships['custom'] = 'custom'; - ksort($relationships); - $this->set('relationships', $relationships); - $this->set('event', $event); - $this->set('objectId', $object['Object']['id']); - $this->layout = false; - $this->render('ajax/add'); + ) + )); + $event = $events[0]; + for ($i = 1; $i < count($events); $i++) { + $event['Attribute'] = array_merge($event['Attribute'], $events[$i]['Attribute']); + $event['Object'] = array_merge($event['Object'], $events[$i]['Object']); } + $toRearrange = array('Attribute', 'Object'); + foreach ($toRearrange as $d) { + if (!empty($event[$d])) { + $temp = array(); + foreach ($event[$d] as $data) { + $temp[$data['uuid']] = $data; + } + $event[$d] = $temp; + } + } + $this->loadModel('ObjectRelationship'); + $relationships = $this->ObjectRelationship->find('column', array( + 'recursive' => -1, + 'fields' => ['name'], + )); + $relationships = array_combine($relationships, $relationships); + $relationships['custom'] = 'custom'; + ksort($relationships); + $this->set('relationships', $relationships); + $this->set('event', $event); + $this->set('objectId', $object['Object']['id']); + $this->layout = false; + $this->render('ajax/add'); } } diff --git a/app/Model/ObjectTemplateElement.php b/app/Model/ObjectTemplateElement.php index 0da789ee2..2e1913bb2 100644 --- a/app/Model/ObjectTemplateElement.php +++ b/app/Model/ObjectTemplateElement.php @@ -30,7 +30,7 @@ class ObjectTemplateElement extends AppModel } $json_fields = array('categories', 'values_list', 'sane_default'); foreach ($json_fields as $field) { - $this->data['ObjectTemplateElement'][$field] = empty($this->data['ObjectTemplateElement'][$field]) ? '[]' : json_encode($this->data['ObjectTemplateElement'][$field]); + $this->data['ObjectTemplateElement'][$field] = empty($this->data['ObjectTemplateElement'][$field]) ? '[]' : JsonTool::encode($this->data['ObjectTemplateElement'][$field]); } return true; } diff --git a/app/View/ObjectReferences/ajax/add.ctp b/app/View/ObjectReferences/ajax/add.ctp index 6faa13cf2..3036347c0 100644 --- a/app/View/ObjectReferences/ajax/add.ctp +++ b/app/View/ObjectReferences/ajax/add.ctp @@ -13,7 +13,7 @@ 'div' => false )); ?> - '); - $('#' + uuid + '_' + k + '_key').text(k); - $('#' + uuid + '_' + k + '_data').text(targetEvent[type][uuid][k]); + $targetData.append('
' + keys[k] + ': ' + escapeHtml(targetEvent[type][uuid][k]) + '
'); } } } else { - $('#targetData').html(""); + $targetData.html(""); for (var k in targetEvent[type][uuid]) { - if (k == 'Attribute') { - $('#targetData').append('
Attributes:'); - for (attribute in targetEvent[type][uuid]['Attribute']) { - for (k2 in targetEvent[type][uuid]['Attribute'][attribute]) { + if (k === 'Attribute') { + $targetData.append('
Attributes:'); + for (var attribute in targetEvent[type][uuid]['Attribute']) { + for (var k2 in targetEvent[type][uuid]['Attribute'][attribute]) { if ($.inArray(k2, ['category', 'type', 'value', 'to_ids']) !== -1) { - $('#targetData').append('
:
'); - $('#' + targetEvent[type][uuid]['Attribute'][attribute]['uuid'] + '_' + k2 + '_key').text(k2); - $('#' + targetEvent[type][uuid]['Attribute'][attribute]['uuid'] + '_' + k2 + '_data').text(targetEvent[type][uuid]['Attribute'][attribute][k2]); + $targetData.append('
' + keys[k2] + ': ' + escapeHtml(targetEvent[type][uuid]['Attribute'][attribute][k2]) + '
'); } } - $('#targetData').append('
'); + $targetData.append('
'); } } else { if ($.inArray(k, ['name', 'uuid', 'meta-category']) !== -1) { - $('#targetData').append('
:
'); - $('#' + uuid + '_' + k + '_key').text(k); - $('#' + uuid + '_' + k + '_data').text(targetEvent[type][uuid][k]); + $targetData.append('
' + keys[k] + ': ' + escapeHtml(targetEvent[type][uuid][k]) + '
'); } } } From 05a9bbb1b6d53f4351ee8b26b6b81e35dce9c83d Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Fri, 23 Sep 2022 15:03:46 +0200 Subject: [PATCH 105/111] chg: [internal] Code cleanup for object edit --- app/Controller/ObjectsController.php | 41 +++++++++--------- app/Model/MispObject.php | 62 +++++++++++++++------------- 2 files changed, 53 insertions(+), 50 deletions(-) diff --git a/app/Controller/ObjectsController.php b/app/Controller/ObjectsController.php index 96ab541fe..cac5bd4a0 100644 --- a/app/Controller/ObjectsController.php +++ b/app/Controller/ObjectsController.php @@ -356,19 +356,20 @@ class ObjectsController extends AppController public function edit($id, $update_template_available=false, $onlyAddNewAttribute=false) { - $object = $this->MispObject->fetchObjects($this->Auth->user(), array( + $user = $this->Auth->user(); + $object = $this->MispObject->fetchObjects($user, array( 'conditions' => $this->__objectIdToConditions($id), )); if (empty($object)) { throw new NotFoundException(__('Invalid object.')); } $object = $object[0]; - $event = $this->MispObject->Event->fetchSimpleEvent($this->Auth->user(), $object['Event']['id']); + $event = $this->MispObject->Event->fetchSimpleEvent($user, $object['Event']['id']); if (!$this->__canModifyEvent($event)) { throw new ForbiddenException(__('Insufficient permissions to edit this object.')); } if (!$this->_isRest()) { - $this->MispObject->Event->insertLock($this->Auth->user(), $object['Event']['id']); + $this->MispObject->Event->insertLock($user, $object['Event']['id']); } if (!empty($object['Object']['template_uuid']) && !empty($object['Object']['template_version'])) { $template = $this->MispObject->ObjectTemplate->find('first', array( @@ -425,7 +426,7 @@ class ObjectsController extends AppController unset($this->request->data['Object']); } $objectToSave = $this->MispObject->attributeCleanup($this->request->data); - $objectToSave = $this->MispObject->deltaMerge($object, $objectToSave, $onlyAddNewAttribute, $this->Auth->user()); + $objectToSave = $this->MispObject->deltaMerge($object, $objectToSave, $onlyAddNewAttribute, $user); $error_message = __('Object could not be saved.'); $savedObject = array(); if (!is_numeric($objectToSave)) { @@ -435,10 +436,10 @@ class ObjectsController extends AppController } $error_message = __('Object could not be saved.') . PHP_EOL . implode(PHP_EOL, $object_validation_errors); } else { - $savedObject = $this->MispObject->fetchObjects($this->Auth->user(), array('conditions' => array('Object.id' => $object['Object']['id']))); + $savedObject = $this->MispObject->fetchObjects($user, array('conditions' => array('Object.id' => $object['Object']['id']))); if (isset($this->request->data['deleted']) && $this->request->data['deleted']) { $this->MispObject->deleteObject($savedObject[0], $hard=false, $unpublish=false); - $savedObject = $this->MispObject->fetchObjects($this->Auth->user(), array('conditions' => array('Object.id' => $object['Object']['id']))); // make sure the object is deleted + $savedObject = $this->MispObject->fetchObjects($user, array('conditions' => array('Object.id' => $object['Object']['id']))); // make sure the object is deleted } } // we pre-validate the attributes before we create an object at this point @@ -480,15 +481,15 @@ class ObjectsController extends AppController $enabledRows = array(); $this->request->data['Object'] = $object['Object']; foreach ($template['ObjectTemplateElement'] as $k => $element) { - foreach ($object['Attribute'] as $k2 => $attribute) { - if ($attribute['object_relation'] == $element['object_relation']) { + foreach ($object['Attribute'] as $attribute) { + if ($attribute['object_relation'] === $element['object_relation']) { $enabledRows[] = $k; $this->request->data['Attribute'][$k] = $attribute; if (!empty($element['values_list'])) { $this->request->data['Attribute'][$k]['value_select'] = $attribute['value']; } else { if (!empty($element['sane_default'])) { - if (in_array($attribute['value'], $element['sane_default'])) { + if (in_array($attribute['value'], $element['sane_default'], true)) { $this->request->data['Attribute'][$k]['value_select'] = $attribute['value']; } else { $this->request->data['Attribute'][$k]['value_select'] = 'Enter value manually'; @@ -500,7 +501,7 @@ class ObjectsController extends AppController } } $this->set('enabledRows', $enabledRows); - $distributionData = $this->MispObject->Event->Attribute->fetchDistributionData($this->Auth->user()); + $distributionData = $this->MispObject->Event->Attribute->fetchDistributionData($user); $this->set('distributionData', $distributionData); $this->set('event', $event); $this->set('ajax', false); @@ -646,10 +647,9 @@ class ObjectsController extends AppController // Construct a template with valid object attributes to add to an object public function quickFetchTemplateWithValidObjectAttributes($id) { - $fields = array('template_uuid', 'template_version', 'id'); $params = array( 'conditions' => array('Object.id' => $id), - 'fields' => $fields, + 'fields' => array('template_uuid', 'template_version', 'id'), 'flatten' => 1, ); // fetchObjects restrict access based on user @@ -664,11 +664,10 @@ class ObjectsController extends AppController $object = $object[0]; } // get object attributes already set - $objectRelation = array(); - foreach($object['Attribute'] as $attr) { - $objectRelation[$attr['object_relation']] = 1; + $existsObjectRelation = array(); + foreach ($object['Attribute'] as $attr) { + $existsObjectRelation[$attr['object_relation']] = true; } - $objectRelation = array_keys($objectRelation); // get object attribute defined in the object's template $template = $this->MispObject->ObjectTemplate->find('first', array( 'conditions' => array( @@ -687,8 +686,8 @@ class ObjectsController extends AppController } } // unset object invalid object attribute - foreach($template['ObjectTemplateElement'] as $i => $objAttr) { - if (in_array($objAttr['object_relation'], $objectRelation) && !$objAttr['multiple']) { + foreach ($template['ObjectTemplateElement'] as $i => $objAttr) { + if (isset($existsObjectRelation[$objAttr['object_relation']]) && !$objAttr['multiple']) { unset($template['ObjectTemplateElement'][$i]); } } @@ -762,13 +761,13 @@ class ObjectsController extends AppController throw new NotFoundException(__('Invalid template')); } if (empty($template['ObjectTemplateElement'])) { - throw new NotFoundException(__('Invalid fields') . ' `' . h($fieldName) . '`'); + throw new NotFoundException(__('Invalid field `%s`', h($fieldName))); } // check if fields can be added - foreach($object['Attribute'] as $objAttr) { + foreach ($object['Attribute'] as $objAttr) { $objectAttrFromTemplate = $template['ObjectTemplateElement'][0]; - if ($objAttr['object_relation'] == $fieldName && !$objectAttrFromTemplate['multiple']) { + if ($objAttr['object_relation'] === $fieldName && !$objectAttrFromTemplate['multiple']) { throw new NotFoundException(__('Invalid field')); } } diff --git a/app/Model/MispObject.php b/app/Model/MispObject.php index 84cc233a8..f38a4a4cf 100644 --- a/app/Model/MispObject.php +++ b/app/Model/MispObject.php @@ -537,7 +537,6 @@ class MispObject extends AppModel $params = array( 'conditions' => $this->buildConditions($user), 'fields' => array(), - 'recursive' => -1 ); if (isset($options['conditions'])) { $params['conditions']['AND'][] = $options['conditions']; @@ -691,12 +690,14 @@ class MispObject extends AppModel return $results; } - /* + /** * Prepare the template form view's data, setting defaults, sorting elements + * @param array $template + * @param array $request + * @return array */ - public function prepareTemplate($template, $request = array()) + public function prepareTemplate(array $template, array $request = array()) { - $temp = array(); usort($template['ObjectTemplateElement'], function ($a, $b) { return $a['ui-priority'] < $b['ui-priority']; }); @@ -708,26 +709,28 @@ class MispObject extends AppModel $request_rearranged[$attribute['object_relation']][] = $attribute; } } - foreach ($template_object_elements as $k => $v) { + $typeDefinitions = $this->Event->Attribute->typeDefinitions; + $categoryDefinitions = $this->Event->Attribute->categoryDefinitions; + foreach ($template_object_elements as $v) { if (empty($request_rearranged[$v['object_relation']])) { - if (isset($this->Event->Attribute->typeDefinitions[$v['type']])) { - $v['default_category'] = $this->Event->Attribute->typeDefinitions[$v['type']]['default_category']; - $v['to_ids'] = $this->Event->Attribute->typeDefinitions[$v['type']]['to_ids']; + if (isset($typeDefinitions[$v['type']])) { + $v['default_category'] = $typeDefinitions[$v['type']]['default_category']; + $v['to_ids'] = $typeDefinitions[$v['type']]['to_ids']; if (empty($v['categories'])) { $v['categories'] = array(); - foreach ($this->Event->Attribute->categoryDefinitions as $catk => $catv) { - if (in_array($v['type'], $catv['types'])) { + foreach ($categoryDefinitions as $catk => $catv) { + if (in_array($v['type'], $catv['types'], true)) { $v['categories'][] = $catk; } } } $template['ObjectTemplateElement'][] = $v; } else { - $template['warnings'][] = 'Missing attribute type "' . $v['type'] . '" found. Omitted template element ("' . $template_object_elements[$k]['object_relation'] . '") that would not pass validation due to this.'; + $template['warnings'][] = 'Missing attribute type "' . $v['type'] . '" found. Omitted template element ("' . $v['object_relation'] . '") that would not pass validation due to this.'; } } else { foreach ($request_rearranged[$v['object_relation']] as $request_item) { - if (isset($this->Event->Attribute->typeDefinitions[$v['type']])) { + if (isset($typeDefinitions[$v['type']])) { $v['default_category'] = $request_item['category']; $v['value'] = $request_item['value']; $v['to_ids'] = $request_item['to_ids']; @@ -740,8 +743,8 @@ class MispObject extends AppModel } if (empty($v['categories'])) { $v['categories'] = array(); - foreach ($this->Event->Attribute->categoryDefinitions as $catk => $catv) { - if (in_array($v['type'], $catv['types'])) { + foreach ($categoryDefinitions as $catk => $catv) { + if (in_array($v['type'], $catv['types'], true)) { $v['categories'][] = $catk; } } @@ -750,7 +753,7 @@ class MispObject extends AppModel $template['ObjectTemplateElement'][] = $v; unset($v['uuid']); // force creating a new attribute if template element entry gets reused } else { - $template['warnings'][] = 'Missing attribute type "' . $v['type'] . '" found. Omitted template element ("' . $template_object_elements[$k]['object_relation'] . '") that would not pass validation due to this.'; + $template['warnings'][] = 'Missing attribute type "' . $v['type'] . '" found. Omitted template element ("' . $v['object_relation'] . '") that would not pass validation due to this.'; } } } @@ -1389,30 +1392,31 @@ class MispObject extends AppModel } $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 (!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 } return $toReturn; } - public function reviseObject($revised_object, $object, $template) { + public function reviseObject($revised_object, $object, $template) + { $revised_object_both = array('mergeable' => array(), 'notMergeable' => array()); // Loop through attributes to inject and perform the correct action From 51a399248ce8757dd79b458196c55a7d4dc6c01c Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Fri, 23 Sep 2022 15:07:50 +0200 Subject: [PATCH 106/111] chg: [schema] Add missing index for object_template_elements:object_template_id column --- app/Model/AppModel.php | 5 ++++- db_schema.json | 5 +++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/Model/AppModel.php b/app/Model/AppModel.php index 7de42bdeb..f5a0bee0f 100644 --- a/app/Model/AppModel.php +++ b/app/Model/AppModel.php @@ -84,7 +84,7 @@ class AppModel extends Model 75 => false, 76 => true, 77 => false, 78 => false, 79 => false, 80 => false, 81 => false, 82 => false, 83 => false, 84 => false, 85 => false, 86 => false, 87 => false, 88 => false, 89 => false, 90 => false, 91 => false, 92 => false, - 93 => false, 94 => false, 95 => true, 96 => false, 97 => true, + 93 => false, 94 => false, 95 => true, 96 => false, 97 => true, 98 => false, ); const ADVANCED_UPDATES_DESCRIPTION = array( @@ -1874,6 +1874,9 @@ class AppModel extends Model ADD COLUMN `notification_monthly` tinyint(1) NOT NULL DEFAULT 0 ;"; break; + case 98: + $this->__addIndex('object_template_elements', 'object_template_id'); + break; case 'fixNonEmptySharingGroupID': $sqlArray[] = 'UPDATE `events` SET `sharing_group_id` = 0 WHERE `distribution` != 4;'; $sqlArray[] = 'UPDATE `attributes` SET `sharing_group_id` = 0 WHERE `distribution` != 4;'; diff --git a/db_schema.json b/db_schema.json index 7377a5f4c..b96d0c2c6 100644 --- a/db_schema.json +++ b/db_schema.json @@ -8938,7 +8938,8 @@ "object_template_elements": { "id": true, "object_relation": false, - "type": false + "type": false, + "object_template_id": false }, "organisations": { "id": true, @@ -9149,5 +9150,5 @@ "uuid": false } }, - "db_version": "97" + "db_version": "98" } From bfe07a2ae3581d683a3db1edd8f60e4b6a979bc2 Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Sun, 25 Sep 2022 16:31:10 +0200 Subject: [PATCH 107/111] fix: [internal] Throw exception when trying import invalid taxonomy --- app/Model/Taxonomy.php | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/app/Model/Taxonomy.php b/app/Model/Taxonomy.php index 29ea0bf8c..4b69b7a27 100644 --- a/app/Model/Taxonomy.php +++ b/app/Model/Taxonomy.php @@ -126,6 +126,9 @@ class Taxonomy extends AppModel return (int)$result; } + /** + * @throws Exception + */ private function __updateVocab(array $vocab, array $current) { $enabled = 0; @@ -149,6 +152,9 @@ class Taxonomy extends AppModel } if (!empty($vocab['values'])) { foreach ($vocab['values'] as $value) { + if (!isset($predicateLookup[$value['predicate']])) { + throw new Exception("Invalid taxonomy `{$vocab['namespace']}` provided. Predicate `{$value['predicate']}` is missing."); + } $predicatePosition = $predicateLookup[$value['predicate']]; if (empty($taxonomy['Taxonomy']['TaxonomyPredicate'][$predicatePosition]['TaxonomyEntry'])) { $taxonomy['Taxonomy']['TaxonomyPredicate'][$predicatePosition]['TaxonomyEntry'] = $value['entry']; @@ -194,30 +200,34 @@ class Taxonomy extends AppModel foreach ($taxonomy['TaxonomyPredicate'] as $predicate) { if (isset($predicate['TaxonomyEntry']) && !empty($predicate['TaxonomyEntry'])) { foreach ($predicate['TaxonomyEntry'] as $entry) { - $temp = array('tag' => $taxonomy['Taxonomy']['namespace'] . ':' . $predicate['value'] . '="' . $entry['value'] . '"'); - $temp['expanded'] = (!empty($predicate['expanded']) ? $predicate['expanded'] : $predicate['value']) . ': ' . (!empty($entry['expanded']) ? $entry['expanded'] : $entry['value']); - if (isset($entry['description']) && !empty($entry['description'])) { + $temp = [ + 'tag' => $taxonomy['Taxonomy']['namespace'] . ':' . $predicate['value'] . '="' . $entry['value'] . '"', + 'expanded' => (!empty($predicate['expanded']) ? $predicate['expanded'] : $predicate['value']) . ': ' . (!empty($entry['expanded']) ? $entry['expanded'] : $entry['value']), + 'exclusive_predicate' => $predicate['exclusive'], + ]; + if (!empty($entry['description'])) { $temp['description'] = $entry['description']; } - if (isset($entry['colour']) && !empty($entry['colour'])) { + if (!empty($entry['colour'])) { $temp['colour'] = $entry['colour']; } - if (isset($entry['numerical_value']) && $entry['numerical_value'] !== null) { + if (isset($entry['numerical_value'])) { $temp['numerical_value'] = $entry['numerical_value']; } - $temp['exclusive_predicate'] = $predicate['exclusive']; $entries[] = $temp; } } else { - $temp = array('tag' => $taxonomy['Taxonomy']['namespace'] . ':' . $predicate['value']); - $temp['expanded'] = !empty($predicate['expanded']) ? $predicate['expanded'] : $predicate['value']; - if (isset($predicate['description']) && !empty($predicate['description'])) { + $temp = [ + 'tag' => $taxonomy['Taxonomy']['namespace'] . ':' . $predicate['value'], + 'expanded' => !empty($predicate['expanded']) ? $predicate['expanded'] : $predicate['value'] + ]; + if (!empty($predicate['description'])) { $temp['description'] = $predicate['description']; } - if (isset($predicate['colour']) && !empty($predicate['colour'])) { + if (!empty($predicate['colour'])) { $temp['colour'] = $predicate['colour']; } - if (isset($predicate['numerical_value']) && $predicate['numerical_value'] !== null) { + if (isset($predicate['numerical_value'])) { $temp['numerical_value'] = $predicate['numerical_value']; } $entries[] = $temp; From e0137002fda8e624d0bc9d099f250ccb744205af Mon Sep 17 00:00:00 2001 From: Alexandre Dulaunoy Date: Sun, 25 Sep 2022 16:59:19 +0200 Subject: [PATCH 108/111] chg: [warning-lists] updated to the latest version --- app/files/warninglists | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/files/warninglists b/app/files/warninglists index 81d122e2d..1b026ee51 160000 --- a/app/files/warninglists +++ b/app/files/warninglists @@ -1 +1 @@ -Subproject commit 81d122e2df112888f93fd07f7a006e1ee432532b +Subproject commit 1b026ee5115e5a6c7fda4cb7a6032c01e6f69a9c From ae0c99b8ad9c184026df2715b7dcf7e1cded8e5c Mon Sep 17 00:00:00 2001 From: Alexandre Dulaunoy Date: Sun, 25 Sep 2022 17:12:45 +0200 Subject: [PATCH 109/111] chg: [taxonomies] updated --- app/files/taxonomies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/files/taxonomies b/app/files/taxonomies index c7a13ea0b..57b125782 160000 --- a/app/files/taxonomies +++ b/app/files/taxonomies @@ -1 +1 @@ -Subproject commit c7a13ea0bc9d648b360f53864234917e78bc0fc1 +Subproject commit 57b125782cd372c8a762db7ce34f8a405752c6c1 From 893be74ac4c731d2ef5facf18e8dec4cfa5919c6 Mon Sep 17 00:00:00 2001 From: Alexandre Dulaunoy Date: Mon, 26 Sep 2022 11:02:26 +0200 Subject: [PATCH 110/111] chg: [misp-galaxy] updated to the latest version --- app/files/misp-galaxy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/files/misp-galaxy b/app/files/misp-galaxy index 258515f9a..eacab6ca2 160000 --- a/app/files/misp-galaxy +++ b/app/files/misp-galaxy @@ -1 +1 @@ -Subproject commit 258515f9a8836ce7f49f00242f45d987fac43b24 +Subproject commit eacab6ca27e1d1996bb28b7c617943052a41e3fd From eae483d7764da6298334115ff9aed87721dac85e Mon Sep 17 00:00:00 2001 From: iglocska Date: Mon, 26 Sep 2022 13:10:24 +0200 Subject: [PATCH 111/111] chg: [version] bump --- VERSION.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.json b/VERSION.json index 81197f320..7b299cceb 100644 --- a/VERSION.json +++ b/VERSION.json @@ -1 +1 @@ -{"major":2, "minor":4, "hotfix":162} +{"major":2, "minor":4, "hotfix":163}