Several issues resolved

- fixed an issue where pushing a single event would fail

- both event and attribute edits via the API work without providing a timestamp. The current timestamp is instead attached

- both event and attribute edits fill the required fields from the data in the database if not supplied (as long as the uuid is found)
pull/652/head
Iglocska 2015-09-07 14:25:24 +02:00
parent 291ebc8393
commit 2142bf87c3
4 changed files with 48 additions and 79 deletions

View File

@ -660,22 +660,27 @@ class AttributesController extends AppController {
} else {
$existingAttribute = $this->Attribute->findByUuid($uuid);
}
// check if the attribute has a timestamp already set (from a previous instance that is trying to edit via synchronisation)
// check which attribute is newer
if (count($existingAttribute)) {
$this->request->data['Attribute']['id'] = $existingAttribute['Attribute']['id'];
}
// check if the attribute has a timestamp already set (from a previous instance that is trying to edit via synchronisation)
if (isset($this->request->data['Attribute']['timestamp'])) {
// check which attribute is newer
if (count($existingAttribute)) {
if ($this->request->data['Attribute']['timestamp'] > $existingAttribute['Attribute']['timestamp']) {
// carry on with adding this attribute - Don't forget! if orgc!=user org, create shadow attribute, not attribute!
} else {
// the old one is newer or the same, replace the request's attribute with the old one
$this->request->data['Attribute'] = $existingAttribute['Attribute'];
}
$dateObj = new DateTime();
if (!isset($this->request->data['Attribute']['timestamp'])) $this->request->data['Attribute']['timestamp'] = $dateObj->getTimestamp();
if ($this->request->data['Attribute']['timestamp'] > $existingAttribute['Attribute']['timestamp']) {
$recoverFields = array('value', 'to_ids', 'distribution', 'category', 'type', 'comment');
foreach ($recoverFields as $rF) if (!isset($this->request->data['Attribute'][$rF])) $this->request->data['Attribute'][$rF] = $existingAttribute['Attribute'][$rF];
// carry on with adding this attribute - Don't forget! if orgc!=user org, create shadow attribute, not attribute!
} else {
// the old one is newer or the same, replace the request's attribute with the old one
throw new MethodNotAllowedException('Attribute could not be saved: Attribute in the request not newer than the local copy.');
}
} else {
$this->request->data['Attribute']['timestamp'] = $date->getTimestamp();
if ($this->_isRest() || $this->response->type() === 'application/json') {
throw new NotFoundException('Invalid attribute.');
} else {
$this->Session->setFlash(__('Invalid attribute.'));
$this->redirect(array('controller' => 'events', 'action' => 'index'));
}
}
$fieldList = array('category', 'type', 'value1', 'value2', 'to_ids', 'distribution', 'value', 'timestamp', 'comment');
$this->loadModel('Event');

View File

@ -1168,46 +1168,6 @@ class EventsController extends AppController {
}
}
public function _edit(&$data, $id) {
$this->Event->read(null, $id);
if (!isset ($data['Event']['orgc'])) $data['Event']['orgc'] = $data['Event']['org'];
if ($this->Event->data['Event']['timestamp'] < $data['Event']['timestamp']) {
} else {
return 'Event exists and is the same or newer.';
}
if (!$this->Event->data['Event']['locked']) {
return 'Event originated on this instance, any changes to it have to be done locally.';
}
$fieldList = array(
'Event' => array('date', 'threat_level_id', 'analysis', 'info', 'published', 'uuid', 'from', 'distribution', 'timestamp'),
'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'revision', 'distribution', 'timestamp')
);
$data['Event']['id'] = $this->Event->data['Event']['id'];
if (isset($data['Event']['Attribute'])) {
foreach ($data['Event']['Attribute'] as $k => &$attribute) {
$existingAttribute = $this->__searchUuidInAttributeArray($attribute['uuid'], $this->Event->data);
if (count($existingAttribute)) {
$data['Event']['Attribute'][$k]['id'] = $existingAttribute['Attribute']['id'];
// Check if the attribute's timestamp is bigger than the one that already exists.
// If yes, it means that it's newer, so insert it. If no, it means that it's the same attribute or older - don't insert it, insert the old attribute.
// Alternatively, we could unset this attribute from the request, but that could lead with issues if we decide that we want to start deleting attributes that don't exist in a pushed event.
if ($data['Event']['Attribute'][$k]['timestamp'] > $existingAttribute['Attribute']['timestamp']) {
} else {
unset($data['Event']['Attribute'][$k]);
}
} else {
unset($data['Event']['Attribute'][$k]['id']);
}
}
}
$this->Event->cleanupEventArrayFromXML($data);
$saveResult = $this->Event->saveAssociated($data, array('validate' => true, 'fieldList' => $fieldList));
if ($saveResult) return 'success';
else return 'Saving the event has failed.';
}
private function __searchUuidInAttributeArray($uuid, &$attr_array) {
foreach ($attr_array['Attribute'] as &$attr) {
if ($attr['uuid'] == $uuid) return array('Attribute' => $attr);
@ -1258,12 +1218,15 @@ class EventsController extends AppController {
// reposition to get the event.id with given uuid
$existingEvent = $this->Event->findByUuid($this->request->data['Event']['uuid']);
// If the event exists...
$dateObj = new DateTime();
$date = $dateObj->getTimestamp();
if (count($existingEvent)) {
$this->request->data['Event']['id'] = $existingEvent['Event']['id'];
// Conditions affecting all:
// user.org == event.org
// edit timestamp newer than existing event timestamp
if (isset($this->request->data['Event']['timestamp']) && $this->request->data['Event']['timestamp'] > $existingEvent['Event']['timestamp']) {
if (!isset($this->request->data['Event']['timestamp'])) $this->request->data['Event']['timestamp'] = $date;
if ($this->request->data['Event']['timestamp'] > $existingEvent['Event']['timestamp']) {
// If the above is true, we have two more options:
// For users that are of the creating org of the event, always allow the edit
// For users that are sync users, only allow the edit if the event is locked
@ -1272,14 +1235,16 @@ class EventsController extends AppController {
// Only allow an edit if this is true!
$saveEvent = true;
} else throw new MethodNotAllowedException('Event could not be saved: The user used to edit the event is not authorised to do so. This can be caused by the user not being of the same organisation as the original creator of the event whilst also not being a site administrator.');
} else throw new MethodNotAllowedException('Event could not be saved: No timestamp on the pushed edit or event in the request not newer than the local copy.');
} else throw new MethodNotAllowedException('Event could not be saved: Event in the request not newer than the local copy.');
// If a field is not set in the request, just reuse the old value
$recoverFields = array('analysis', 'threat_level_id', 'info', 'distribution', 'date');
foreach ($recoverFields as $rF) if (!isset($this->request->data['Event'][$rF])) $this->request->data['Event'][$rF] = $existingEvent['Event'][$rF];
} else throw new MethodNotAllowedException('Event could not be saved: Could not find the local event.');
$fieldList = array(
'Event' => array('date', 'threat_level_id', 'analysis', 'info', 'published', 'uuid', 'from', 'distribution', 'timestamp'),
'Event' => array('date', 'threat_level_id', 'analysis', 'info', 'published', 'uuid', 'distribution', 'timestamp'),
'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'revision', 'distribution', 'timestamp', 'comment'),
'ShadowAttribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'org', 'event_org', 'comment', 'event_uuid', 'deleted', 'to_ids', 'uuid')
);
$c = 0;
if (isset($this->request->data['Attribute'])) {
foreach ($this->request->data['Attribute'] as $attribute) {
@ -1299,17 +1264,18 @@ class EventsController extends AppController {
'change' => 'An attribute was blocked from being saved due to a duplicate UUID. The uuid in question is: ' . $attribute['uuid'],
));
unset($this->request->data['Attribute'][$c]);
}
else {
} else {
// If a field is not set in the request, just reuse the old value
$recoverFields = array('value', 'to_ids', 'distribution', 'category', 'type', 'comment');
foreach ($recoverFields as $rF) if (!isset($attribute[$rF])) $this->request->data['Attribute'][$c][$rF] = $existingAttribute['Attribute'][$rF];
$this->request->data['Attribute'][$c]['id'] = $existingAttribute['Attribute']['id'];
// Check if the attribute's timestamp is bigger than the one that already exists.
// If yes, it means that it's newer, so insert it. If no, it means that it's the same attribute or older - don't insert it, insert the old attribute.
// Alternatively, we could unset this attribute from the request, but that could lead with issues if we decide that we want to start deleting attributes that don't exist in a pushed event.
if ($this->request->data['Attribute'][$c]['timestamp'] > $existingAttribute['Attribute']['timestamp']) {
if (isset($this->request->data['Attribute'][$c]['timestamp'])) {
if ($this->request->data['Attribute'][$c]['timestamp'] <= $existingAttribute['Attribute']['timestamp']) unset($this->request->data['Attribute'][$c]);
} else {
unset($this->request->data['Attribute'][$c]);
//$this->request->data['Attribute'][$c] = $existingAttribute['Attribute'];
$this->request->data['Event']['timestamp'] = $date;
}
}
}

View File

@ -66,7 +66,7 @@ class ServersController extends AppController {
// force check userid and orgname to be from yourself
$this->request->data['Server']['org'] = $this->Auth->user('org');
if ($this->Server->save($this->request->data)) {
if (isset($this->request->data['Server']['submitted_cert'])) {
if ($this->request->data['Server']['submitted_cert']['error'] == 0) {
$this->__saveCert($this->request->data, $this->Server->id);
}
$this->Session->setFlash(__('The server has been saved'));
@ -267,7 +267,7 @@ class ServersController extends AppController {
$file = new File($server['Server']['submitted_cert']['name']);
$ext = $file->ext();
if (($ext != 'pem') || !$server['Server']['submitted_cert']['size'] > 0) {
$this->Session->setFlash('Incorrect extension of empty file.');
$this->Session->setFlash('Incorrect extension or empty file.');
$this->redirect(array('action' => 'index'));
}
$pemData = fread(fopen($server['Server']['submitted_cert']['tmp_name'], "r"),

View File

@ -957,27 +957,25 @@ class Server extends AppModel {
$eventid_conditions_key = 'Event.id >';
$eventid_conditions_value = $this->data['Server']['lastpushedid'];
} elseif (true == $technique) {
$eventIds[] = array('Event' => array ('id' => intval($technique)));
$eventid_conditions_key = 'Event.id';
$eventid_conditions_value = intval($technique);
} else {
$this->redirect(array('action' => 'index'));
}
if (!isset($eventIds)) {
$findParams = array(
'conditions' => array(
$eventid_conditions_key => $eventid_conditions_value,
'Event.distribution >' => 0,
'Event.published' => 1,
'Event.attribute_count >' => 0
), //array of conditions
'recursive' => -1, //int
'fields' => array('Event.id', 'Event.timestamp', 'Event.uuid'), //array of field names
);
$eventIds = $eventModel->find('all', $findParams);
}
$findParams = array(
'conditions' => array(
$eventid_conditions_key => $eventid_conditions_value,
'Event.distribution >' => 0,
'Event.published' => 1,
'Event.attribute_count >' => 0
), //array of conditions
'recursive' => -1, //int
'fields' => array('Event.id', 'Event.timestamp', 'Event.uuid'), //array of field names
);
$eventIds = $eventModel->find('all', $findParams);
$eventUUIDsFiltered = $this->filterEventIdsForPush($id, $HttpSocket, $eventIds);
if ($eventUUIDsFiltered === false) $pushFailed = true;
if (!empty($eventUUIDsFiltered)) {
$eventCount = count($eventUUIDsFiltered);
//debug($eventIds);
// now process the $eventIds to pull each of the events sequentially