mirror of https://github.com/MISP/MISP
fix: [object:fromAttributes] SYNC support for older instances
(duplicate attributes and their contexts)pull/4672/head
parent
8d2c55fa69
commit
fe4740abd9
|
@ -1277,7 +1277,7 @@ class AttributesController extends AppController
|
|||
}
|
||||
if ($this->request->is('ajax')) {
|
||||
if ($this->request->is('post')) {
|
||||
if ($this->__delete($id, $hard)) {
|
||||
if ($this->Attribute->__delete($id, $this->Auth->user(), $hard)) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Attribute deleted.')), 'status'=>200, 'type' => 'json'));
|
||||
} else {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Attribute was not deleted.')), 'status'=>200, 'type' => 'json'));
|
||||
|
@ -1291,7 +1291,7 @@ class AttributesController extends AppController
|
|||
if (!$this->request->is('post') && !$this->_isRest()) {
|
||||
throw new MethodNotAllowedException();
|
||||
}
|
||||
if ($this->__delete($id, $hard)) {
|
||||
if ($this->Attribute->__delete($id, $this->Auth->user(), $hard)) {
|
||||
if ($this->_isRest() || $this->response->type() === 'application/json') {
|
||||
$this->set('message', 'Attribute deleted.');
|
||||
$this->set('_serialize', array('message'));
|
||||
|
@ -1360,77 +1360,6 @@ class AttributesController extends AppController
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// unification of the actual delete for the multi-select
|
||||
private function __delete($id, $hard = false)
|
||||
{
|
||||
$this->Attribute->id = $id;
|
||||
if (!$this->Attribute->exists()) {
|
||||
return false;
|
||||
}
|
||||
$result = $this->Attribute->find('first', array(
|
||||
'conditions' => array('Attribute.id' => $id),
|
||||
'fields' => array('Attribute.*'),
|
||||
'contain' => array('Event' => array(
|
||||
'fields' => array('Event.*')
|
||||
)),
|
||||
));
|
||||
if (empty($result)) {
|
||||
throw new MethodNotAllowedException(__('Attribute not found or not authorised.'));
|
||||
}
|
||||
|
||||
// check for permissions
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
if ($result['Event']['locked']) {
|
||||
if ($this->Auth->user('org_id') != $result['Event']['org_id'] || !$this->userRole['perm_sync']) {
|
||||
throw new MethodNotAllowedException(__('Attribute not found or not authorised.'));
|
||||
}
|
||||
} else {
|
||||
if ($this->Auth->user('org_id') != $result['Event']['orgc_id']) {
|
||||
throw new MethodNotAllowedException(__('Attribute not found or not authorised.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
$date = new DateTime();
|
||||
if ($hard) {
|
||||
$save = $this->Attribute->delete($id);
|
||||
} else {
|
||||
if (Configure::read('Security.sanitise_attribute_on_delete')) {
|
||||
$result['Attribute']['category'] = 'Other';
|
||||
$result['Attribute']['type'] = 'comment';
|
||||
$result['Attribute']['value'] = 'deleted';
|
||||
$result['Attribute']['comment'] = '';
|
||||
$result['Attribute']['to_ids'] = 0;
|
||||
}
|
||||
$result['Attribute']['deleted'] = 1;
|
||||
$result['Attribute']['timestamp'] = $date->getTimestamp();
|
||||
$save = $this->Attribute->save($result);
|
||||
$object_refs = $this->Attribute->Object->ObjectReference->find('all', array(
|
||||
'conditions' => array(
|
||||
'ObjectReference.referenced_type' => 0,
|
||||
'ObjectReference.referenced_id' => $id,
|
||||
),
|
||||
'recursive' => -1
|
||||
));
|
||||
foreach ($object_refs as $ref) {
|
||||
$ref['ObjectReference']['deleted'] = 1;
|
||||
$this->Attribute->Object->ObjectReference->save($ref);
|
||||
}
|
||||
}
|
||||
// attachment will be deleted with the beforeDelete() function in the Model
|
||||
if ($save) {
|
||||
// We have just deleted the attribute, let's also check if there are any shadow attributes that were attached to it and delete them
|
||||
$this->loadModel('ShadowAttribute');
|
||||
$this->ShadowAttribute->deleteAll(array('ShadowAttribute.old_id' => $id), false);
|
||||
|
||||
// remove the published flag from the event
|
||||
$this->Attribute->Event->unpublishEvent($result['Event']['id']);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteSelected($id = false, $hard = false)
|
||||
{
|
||||
if (!$this->request->is('post')) {
|
||||
|
@ -1497,11 +1426,11 @@ class AttributesController extends AppController
|
|||
$successes = array();
|
||||
foreach ($attributes as $a) {
|
||||
if ($hard) {
|
||||
if ($this->__delete($a['Attribute']['id'], true)) {
|
||||
if ($this->Attribute->__delete($a['Attribute']['id'], true)) {
|
||||
$successes[] = $a['Attribute']['id'];
|
||||
}
|
||||
} else {
|
||||
if ($this->__delete($a['Attribute']['id'], $a['Attribute']['deleted'] == 1 ? true : false)) {
|
||||
if ($this->Attribute->__delete($a['Attribute']['id'], $a['Attribute']['deleted'] == 1 ? true : false)) {
|
||||
$successes[] = $a['Attribute']['id'];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1053,25 +1053,15 @@ class ObjectsController extends AppController
|
|||
} else {
|
||||
$sharing_group_id = 0;
|
||||
}
|
||||
$object = array('Object' => array(
|
||||
'distribution' => $distribution,
|
||||
'sharing_group_id' => $sharing_group_id,
|
||||
'comment' => $comment
|
||||
));
|
||||
$temp = $this->MispObject->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => array(
|
||||
'Attribute.id' => $selected_attribute_ids,
|
||||
'Attribute.event_id' => $event_id,
|
||||
'Attribute.object_id' => 0
|
||||
)));
|
||||
foreach ($temp as $i => $attribute) {
|
||||
if (isset($selected_object_relation_mapping[$attribute['Attribute']['id']])) {
|
||||
$object_relation = $selected_object_relation_mapping[$attribute['Attribute']['id']];
|
||||
$attribute['Attribute']['object_relation'] = $object_relation;
|
||||
$object['Attribute'][$i] = $attribute['Attribute'];
|
||||
unset($object['Attribute'][$i]['timestamp']);
|
||||
}
|
||||
}
|
||||
$result = $this->MispObject->saveObject($object, $event_id, $template, $this->Auth->user());
|
||||
$object = array(
|
||||
'Object' => array(
|
||||
'distribution' => $distribution,
|
||||
'sharing_group_id' => $sharing_group_id,
|
||||
'comment' => $comment,
|
||||
),
|
||||
'Attribute' => array()
|
||||
);
|
||||
$result = $this->MispObject->groupAttributesIntoObject($this->Auth->user(), $event_id, $object, $template, $selected_attribute_ids, $selected_object_relation_mapping);
|
||||
if (is_numeric($result)) {
|
||||
$this->MispObject->Event->unpublishEvent($event_id);
|
||||
return $this->RestResponse->saveSuccessResponse('Objects', 'Created from Attributes', $result, $this->response->type());
|
||||
|
|
|
@ -3768,14 +3768,7 @@ class Attribute extends AppModel
|
|||
));
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
if (count($existingAttribute)) {
|
||||
if (
|
||||
$existingAttribute['Attribute']['event_id'] != $eventId ||
|
||||
(
|
||||
$existingAttribute['Attribute']['object_id'] != $objectId &&
|
||||
// Still take into account the attribute if it was merged into an object
|
||||
$existingAttribute['Attribute']['object_id'] != 0
|
||||
)
|
||||
) {
|
||||
if ($existingAttribute['Attribute']['event_id'] != $eventId || $existingAttribute['Attribute']['object_id'] != $objectId) {
|
||||
$this->Log->create();
|
||||
$result = $this->Log->save(array(
|
||||
'org' => $user['Organisation']['name'],
|
||||
|
@ -3912,6 +3905,74 @@ class Attribute extends AppModel
|
|||
return true;
|
||||
}
|
||||
|
||||
public function __delete($id, $user, $hard = false)
|
||||
{
|
||||
$this->id = $id;
|
||||
if (!$this->exists()) {
|
||||
return false;
|
||||
}
|
||||
$result = $this->find('first', array(
|
||||
'conditions' => array('Attribute.id' => $id),
|
||||
'fields' => array('Attribute.*'),
|
||||
'contain' => array('Event' => array(
|
||||
'fields' => array('Event.*')
|
||||
)),
|
||||
));
|
||||
if (empty($result)) {
|
||||
throw new MethodNotAllowedException(__('Attribute not found or not authorised.'));
|
||||
}
|
||||
|
||||
// check for permissions
|
||||
if (!$user['Role']['perm_site_admin']) {
|
||||
if ($result['Event']['locked']) {
|
||||
if ($user['org_id'] != $result['Event']['org_id'] || !$user['Role']['perm_sync']) {
|
||||
throw new MethodNotAllowedException(__('Attribute not found or not authorised.'));
|
||||
}
|
||||
} else {
|
||||
if ($user['org_id'] != $result['Event']['orgc_id']) {
|
||||
throw new MethodNotAllowedException(__('Attribute not found or not authorised.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
$date = new DateTime();
|
||||
if ($hard) {
|
||||
$save = $this->delete($id);
|
||||
} else {
|
||||
if (Configure::read('Security.sanitise_attribute_on_delete')) {
|
||||
$result['Attribute']['category'] = 'Other';
|
||||
$result['Attribute']['type'] = 'comment';
|
||||
$result['Attribute']['value'] = 'deleted';
|
||||
$result['Attribute']['comment'] = '';
|
||||
$result['Attribute']['to_ids'] = 0;
|
||||
}
|
||||
$result['Attribute']['deleted'] = 1;
|
||||
$result['Attribute']['timestamp'] = $date->getTimestamp();
|
||||
$save = $this->save($result);
|
||||
$object_refs = $this->Object->ObjectReference->find('all', array(
|
||||
'conditions' => array(
|
||||
'ObjectReference.referenced_type' => 0,
|
||||
'ObjectReference.referenced_id' => $id,
|
||||
),
|
||||
'recursive' => -1
|
||||
));
|
||||
foreach ($object_refs as $ref) {
|
||||
$ref['ObjectReference']['deleted'] = 1;
|
||||
$this->Object->ObjectReference->save($ref);
|
||||
}
|
||||
}
|
||||
// attachment will be deleted with the beforeDelete() function in the Model
|
||||
if ($save) {
|
||||
// We have just deleted the attribute, let's also check if there are any shadow attributes that were attached to it and delete them
|
||||
$this->Event->ShadowAttribute->deleteAll(array('ShadowAttribute.old_id' => $id), false);
|
||||
|
||||
// remove the published flag from the event
|
||||
$this->Event->unpublishEvent($result['Event']['id']);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function attachValidationWarnings($adata)
|
||||
{
|
||||
if (!$this->__fTool) {
|
||||
|
|
|
@ -595,15 +595,7 @@ class MispObject extends AppModel
|
|||
$objectId = $this->id;
|
||||
$partialFails = array();
|
||||
foreach ($object['Object']['Attribute'] as $attribute) {
|
||||
$existing_attribute = $this->Attribute->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('uuid' => $attribute['uuid'])
|
||||
));
|
||||
if (empty($existing_attribute)) {
|
||||
$this->Attribute->captureAttribute($attribute, $eventId, $user, $objectId, $log);
|
||||
} else { // The attribute may just have been grouped into an object
|
||||
$this->Attribute->editAttribute($attribute, $eventId, $user, $objectId, $log);
|
||||
}
|
||||
$this->Attribute->captureAttribute($attribute, $eventId, $user, $objectId, $log);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
|
@ -826,4 +818,54 @@ class MispObject extends AppModel
|
|||
}
|
||||
return array('templates' => $templates, 'types' => $attribute_types);
|
||||
}
|
||||
|
||||
public function groupAttributesIntoObject($user, $event_id, $object, $template, $selected_attribute_ids, $selected_object_relation_mapping)
|
||||
{
|
||||
$saved_object_id = $this->saveObject($object, $event_id, $template, $user);
|
||||
|
||||
if (!is_numeric($saved_object_id)) {
|
||||
return $saved_object_id;
|
||||
}
|
||||
|
||||
$saved_object = $this->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('Object.id' => $saved_object_id)
|
||||
));
|
||||
|
||||
$existing_attributes = $this->Attribute->fetchAttributes($user, array('conditions' => array(
|
||||
'Attribute.id' => $selected_attribute_ids,
|
||||
'Attribute.event_id' => $event_id,
|
||||
'Attribute.object_id' => 0
|
||||
)));
|
||||
|
||||
if (empty($existing_attributes)) {
|
||||
return __('Selected Attributes do not exist.');
|
||||
}
|
||||
$event = array('Event' => $existing_attributes[0]['Event']);
|
||||
|
||||
// Duplicate the attribute and its context, otherwise connected instance will drop the duplicated UUID
|
||||
foreach ($existing_attributes as $i => $existing_attribute) {
|
||||
if (isset($selected_object_relation_mapping[$existing_attribute['Attribute']['id']])) {
|
||||
$sightings = $this->Event->Sighting->attachToEvent($event, $user, $existing_attribute['Attribute']['id']);
|
||||
$object_relation = $selected_object_relation_mapping[$existing_attribute['Attribute']['id']];
|
||||
$created_attribute = $existing_attribute['Attribute'];
|
||||
unset($created_attribute['timestamp']);
|
||||
unset($created_attribute['id']);
|
||||
unset($created_attribute['uuid']);
|
||||
$created_attribute['object_relation'] = $object_relation;
|
||||
$created_attribute['object_id'] = $saved_object['Object']['id'];
|
||||
if (isset($existing_attribute['AttributeTag'])) {
|
||||
$created_attribute['AttributeTag'] = $existing_attribute['AttributeTag'];
|
||||
}
|
||||
if (!empty($sightings)) {
|
||||
$created_attribute['Sighting'] = $sightings;
|
||||
}
|
||||
$saved_object['Attribute'][$i] = $created_attribute;
|
||||
$this->Attribute->captureAttribute($created_attribute, $event_id, $user, $saved_object['Object']['id']);
|
||||
$this->Attribute->__delete($existing_attribute['Attribute']['id'], $user);
|
||||
}
|
||||
}
|
||||
return $saved_object['Object']['id'];
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue