new: Progress on the Objects

- Fixed UI elements in the event view
- Added object-aware filtering to the event view
- Objects can now be deleted and viewed once deleted
  - object sanitisation if the setting is set is implemented
- Edit objects directly from the interface (if the template exists)
- Various other fixes
pull/2489/head
iglocska 2017-08-06 18:23:24 +02:00
parent 6f7529ef92
commit 8f6b53ee24
14 changed files with 336 additions and 170 deletions

View File

@ -435,6 +435,7 @@ CREATE TABLE IF NOT EXISTS objects (
`distribution` tinyint(4) NOT NULL DEFAULT 0,
`sharing_group_id` int(11),
`comment` text COLLATE utf8_bin NOT NULL,
`deleted` TINYINT NOT NULL DEFAULT 0,
PRIMARY KEY (id),
INDEX `name` (`name`),
INDEX `template_uuid` (`template_uuid`),
@ -457,10 +458,12 @@ CREATE TABLE IF NOT EXISTS object_references (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uuid` varchar(40) COLLATE utf8_bin DEFAULT NULL,
`timestamp` int(11) NOT NULL DEFAULT 0,
`referenced_uuid` varchar(40) COLLATE utf8_bin DEFAULT NULL,
`object_id` int(11) NOT NULL,
`referenced_id` int(11) NOT NULL,
`referenced_type` int(11) NOT NULL DEFAULT 0,
`relationship_type` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci,
`comment` text COLLATE utf8_bin NOT NULL,
`deleted` TINYINT NOT NULL DEFAULT 0,
PRIMARY KEY (id),
INDEX `uuid` (`uuid`),
INDEX `timestamp` (`timestamp`),

View File

@ -117,7 +117,7 @@ class ObjectsController extends AppController {
public function edit($id) {
if (!$this->userRole['perm_modify']) {
throw new MethodNotAllowedException('You don\'t have permissions to create objects.');
throw new MethodNotAllowedException('You don\'t have permissions to edit objects.');
}
$object = $this->MispObject->find('first', array(
'conditions' => array('Object.id' => $id),
@ -182,7 +182,7 @@ class ObjectsController extends AppController {
}
} else {
$this->Session->setFlash('Object saved.');
$this->redirect(array('controller' => 'events', 'action' => 'view', $object['Object']['id']));
$this->redirect(array('controller' => 'events', 'action' => 'view', $object['Object']['event_id']));
}
}
} else {
@ -220,31 +220,165 @@ class ObjectsController extends AppController {
$this->render('add');
}
public function delete($id) {
public function delete($id, $hard = false) {
if (!$this->userRole['perm_modify']) {
throw new MethodNotAllowedException('You don\'t have permissions to delete objects.');
}
if (Validation::uuid($eventId)) {
if (Validation::uuid($id)) {
$lookupField = 'uuid';
} else if (!is_numeric($eventId)) {
} else if (!is_numeric($id)) {
$lookupField = 'id';
throw new NotFoundException('Invalid event.');
throw new NotFoundException('Invalid object.');
}
$event = $this->MispObject->Event->find('first', array(
$object = $this->MispObject->find('first', array(
'recursive' => -1,
'fields' => array('Event.id', 'Event.uuid', 'Event.orgc_id'),
'conditions' => array('Event.id' => $eventId)
'fields' => array('Object.id', 'Object.event_id', 'Event.id', 'Event.uuid', 'Event.orgc_id'),
'conditions' => array('Object.id' => $id),
'contain' => array(
'Event'
)
));
if (empty($event)) {
if (empty($object)) {
throw new NotFoundException('Invalid event.');
}
$eventId = $event['Event']['id'];
if (!$this->_isSiteAdmin() && ($event['Event']['orgc_id'] != $this->Auth->user('org_id') || !$this->userRole['perm_modify'])) {
$eventId = $object['Event']['id'];
if (!$this->_isSiteAdmin() && ($object['Event']['orgc_id'] != $this->Auth->user('org_id') || !$this->userRole['perm_modify'])) {
throw new UnauthorizedException('You do not have permission to do that.');
}
$this->MispObject->delete($id);
if ($this->request->is('post')) {
if ($this->__delete($id, $hard)) {
$message = 'Object deleted.';
if ($this->request->is('ajax')) {
return new CakeResponse(
array(
'body'=> json_encode(
array(
'saved' => true,
'success' => $message
)
),
'status'=>200
)
);
} else if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse(
'Objects',
'delete',
$id,
$this->response->type()
);
} else {
$this->Session->setFlash($message);
$this->redirect(array('controller' => 'events', 'action' => 'view', $object['Event']['id']));
}
} else {
$message = 'Object could not be deleted.';
if ($this->request->is('ajax')) {
return new CakeResponse(
array(
'body'=> json_encode(
array(
'saved' => false,
'errors' => $message
)
),
'status'=>200)
);
} else if ($this->_isRest()) {
return $this->RestResponse->saveFailResponse(
'Objects',
'delete',
false,
$this->MispObject->validationErrors,
$this->response->type()
);
} else {
$this->Session->setFlash($message);
$this->redirect(array('controller' => 'events', 'action' => 'view', $object['Event']['id']));
}
}
} else {
if ($this->request->is('ajax') && $this->request->is('get')) {
$this->set('hard', $hard);
$this->set('id', $id);
$this->set('event_id', $object['Event']['id']);
$this->render('ajax/delete');
}
}
}
private function __delete($id, $hard) {
$this->MispObject->id = $id;
if (!$this->MispObject->exists()) {
return false;
}
$object = $this->MispObject->find('first', array(
'conditions' => array('Object.id' => $id),
'fields' => array('Object.*'),
'contain' => array(
'Event' => array(
'fields' => array('Event.*')
),
'Attribute' => array(
'fields' => array('Attribute.*')
)
),
));
if (empty($object)) throw new MethodNotAllowedException('Object not found or not authorised.');
// check for permissions
if (!$this->_isSiteAdmin()) {
if ($object['Event']['locked']) {
if ($this->Auth->user('org_id') != $object['Event']['org_id'] || !$this->userRole['perm_sync']) {
throw new MethodNotAllowedException('Object not found or not authorised.');
}
} else {
if ($this->Auth->user('org_id') != $object['Event']['orgc_id']) {
throw new MethodNotAllowedException('Object not found or not authorised.');
}
}
}
$date = new DateTime();
if ($hard) {
// For a hard delete, simply run the delete, it will cascade
$this->MispObject->delete($id);
return true;
} else {
// For soft deletes, sanitise the object first if the setting is enabled
if (Configure::read('Security.sanitise_attribute_on_delete')) {
$object['Object']['name'] = 'N/A';
$object['Object']['category'] = 'N/A';
$object['Object']['description'] = 'N/A';
$object['Object']['template_uuid'] = 'N/A';
$object['Object']['template_version'] = 0;
$object['Object']['comment'] = '';
}
$object['Object']['deleted'] = 1;
$object['Object']['timestamp'] = $date->getTimestamp();
$this->MispObject->save($object);
foreach ($object['Attribute'] as $attribute) {
if (Configure::read('Security.sanitise_attribute_on_delete')) {
$attribute['category'] = 'Other';
$attribute['type'] = 'comment';
$attribute['value'] = 'deleted';
$attribute['comment'] = '';
$attribute['to_ids'] = 0;
}
$attribute['deleted'] = 1;
$attribute['timestamp'] = $date->getTimestamp();
$this->MispObject->Attribute->save(array('Attribute' => $attribute));
$this->MispObject->Event->ShadowAttribute->deleteAll(
array('ShadowAttribute.old_id' => $attribute['id']),
false
);
}
$object['Event']['timestamp'] = $date->getTimestamp();
$object['Event']['published'] = 0;
$this->MispObject->Event->save($object, array('fieldList' => array('published', 'timestamp', 'info')));
return true;
}
}
public function view($id) {
if ($this->_isRest()) {
$objects = $this->MispObject->fetchObjects($this->Auth->user(), array('conditions' => array('Object.id' => $id)));

View File

@ -716,6 +716,7 @@ class AppModel extends Model {
`distribution` tinyint(4) NOT NULL DEFAULT 0,
`sharing_group_id` int(11),
`comment` text COLLATE utf8_bin NOT NULL,
`deleted` TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
INDEX `name` (`name`),
INDEX `template_uuid` (`template_uuid`),
@ -732,10 +733,12 @@ class AppModel extends Model {
`id` int(11) NOT NULL AUTO_INCREMENT,
`uuid` varchar(40) COLLATE utf8_bin DEFAULT NULL,
`timestamp` int(11) NOT NULL DEFAULT 0,
`referenced_uuid` varchar(40) COLLATE utf8_bin DEFAULT NULL,
`object_id` int(11) NOT NULL,
`referenced_id` int(11) NOT NULL,
`referenced_type` int(11) NOT NULL DEFAULT 0,
`relationship_type` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci,
`comment` text COLLATE utf8_bin NOT NULL,
`deleted` TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
INDEX `uuid` (`uuid`),
INDEX `timestamp` (`timestamp`),

View File

@ -1338,7 +1338,7 @@ class Event extends AppModel {
if ($options['sharing_group_id']) {
$conditions['AND'][] = array('Event.sharing_group_id' => $options['sharing_group_id']);
$conditionsAttributes['AND'][] = array('Attribute.sharing_group_id' => $options['sharing_group_id']);
$conditionsObject['AND'][] = array('Object.sharing_group_id' => $options['sharing_group_id']);
$conditionsObjects['AND'][] = array('Object.sharing_group_id' => $options['sharing_group_id']);
}
if ($options['from']) $conditions['AND'][] = array('Event.date >=' => $options['from']);
if ($options['to']) $conditions['AND'][] = array('Event.date <=' => $options['to']);
@ -1361,7 +1361,7 @@ class Event extends AppModel {
}
} else {
$conditionsAttributes['AND']['Attribute.deleted'] = 0;
$conditionsObject['AND']['Object.deleted'] = 0;
$conditionsObjects['AND']['Object.deleted'] = 0;
}
if ($options['idList'] && !$options['tags']) {
@ -3126,7 +3126,7 @@ class Event extends AppModel {
$correlatedAttributes,
$correlatedShadowAttributes,
$filterType = false,
$eventWarnings,
&$eventWarnings,
$warningLists
) {
$attribute['objectType'] = 'attribute';
@ -3148,15 +3148,18 @@ class Event extends AppModel {
$result = $this->__prepareProposalForView(
$proposal,
$correlatedShadowAttributes,
false,
$filterType,
$eventWarnings,
$warningLists
);
$temp[] = $result['data'];
if ($result['include']) $temp[] = $result['data'];
}
$attribute['ShadowAttribute'] = $temp;
}
$attribute = $this->__prepareGenericForView($attribute, $eventWarnings, $warningLists);
if ($filterType === 'warning') {
if (empty($attribute['warnings'])) $include = false;
}
return array('include' => $include, 'data' => $attribute);
}
@ -3164,7 +3167,7 @@ class Event extends AppModel {
$proposal,
$correlatedShadowAttributes,
$filterType = false,
$eventWarnings,
&$eventWarnings,
$warningLists
) {
if ($proposal['proposal_to_delete']) {
@ -3178,11 +3181,14 @@ class Event extends AppModel {
$include = false;
}
if ($filterType && !in_array($filterType, array('proposal', 'correlation', 'warning'))) {
if (!in_array($attribute['type'], $this->Attribute->typeGroupings[$filterType])) {
if (!in_array($proposal['type'], $this->Attribute->typeGroupings[$filterType])) {
$include = false;
}
}
$proposal = $this->__prepareGenericForView($proposal, $eventWarnings, $warningLists);
if ($filterType === 'warning') {
if (empty($proposal['warnings'])) $include = false;
}
return array('include' => $include, 'data' => $proposal);
}
@ -3191,13 +3197,16 @@ class Event extends AppModel {
$correlatedAttributes,
$correlatedShadowAttributes,
$filterType = false,
$eventWarnings,
&$eventWarnings,
$warningLists
) {
$object['category'] = $object['meta-category'];
$proposal['objectType'] = 'object';
// filters depend on child objects
$include = empty($filterType) || $filterType == 'object';
$include = empty($filterType) || $filterType == 'object' || $object['meta-category'] === $filterType;
if ($filterType === 'correlation' || $filterType === 'proposal') {
$include = $this->__checkObjectByFilter($object, $filterType, $correlatedAttributes, $correlatedShadowAttributes);
}
if (!empty($object['Attribute'])) {
$temp = array();
foreach ($object['Attribute'] as $k => $proposal) {
@ -3205,21 +3214,72 @@ class Event extends AppModel {
$proposal,
$correlatedAttributes,
$correlatedShadowAttributes,
$filterType,
false,
$eventWarnings,
$warningLists
);
$include = $include || $object['include'];
$temp[] = $result['data'];
if ($result['include']) $temp[] = $result['data'];
}
$object['Attribute'] = $temp;
}
if ($filterType === 'warning') {
$include = $this->__checkObjectByFilter($object, $filterType, $correlatedAttributes, $correlatedShadowAttributes);
}
return array('include' => $include, 'data' => $object);
}
private function __checkObjectByFilter($object, $filterType, $correlatedAttributes, $correlatedShadowAttributes) {
$include = false;
switch($filterType) {
case 'warning':
if (!empty($object['Attribute'])) {
foreach ($object['Attribute'] as $k => $attribute) {
if (!empty($attribute['warnings'])) {
$include = true;
}
if (!empty($attribute['ShadowAttribute'])) {
foreach ($attribute['ShadowAttribute'] as $shadowAttribute) {
if (!empty($shadowAttribute['warnings'])) {
$include = true;
}
}
}
}
}
break;
case 'correlation':
if (!empty($object['Attribute'])) {
foreach ($object['Attribute'] as $k => $attribute) {
if (in_array($attribute['id'], $correlatedAttributes)) {
$include = true;
} else {
if (!empty($attribute['ShadowAttribute'])) {
foreach ($attribute['ShadowAttribute'] as $k => $shadowAttribute) {
if (in_array($shadowAttribute['id'], $correlatedShadowAttributes)) {
$include = true;
}
}
}
}
}
}
break;
case 'proposal':
if (!empty($object['Attribute'])) {
foreach ($object['Attribute'] as $k => $attribute) {
if (!empty($attribute['ShadowAttribute'])) {
$include = true;
}
}
}
break;
}
return $include;
}
private function __prepareGenericForView(
$object,
$eventWarnings,
&$eventWarnings,
$warningLists
) {
if (!$this->__fTool) {
@ -3236,7 +3296,7 @@ class Event extends AppModel {
}
}
}
$this->Warninglist->checkForWarning($object, $eventWarnings, $warningLists);
$object = $this->Warninglist->checkForWarning($object, $eventWarnings, $warningLists);
return $object;
}
@ -3271,7 +3331,7 @@ class Event extends AppModel {
$eventWarnings,
$warningLists
);
$event['objects'][] = $result['data'];
if ($result['include']) $event['objects'][] = $result['data'];
}
unset($event['Attribute']);
if (!empty($event['ShadowAttribute'])) {
@ -3293,11 +3353,11 @@ class Event extends AppModel {
$object,
$correlatedAttributes,
$correlatedShadowAttributes,
false,
$filterType,
$eventWarnings,
$warningLists
);
$event['objects'][] = $result['data'];
if ($result['include']) $event['objects'][] = $result['data'];
}
}
unset($event['Object']);
@ -3307,6 +3367,7 @@ class Event extends AppModel {
if ($all) $passedArgs['page'] = 0;
$params = $customPagination->applyRulesOnArray($event['objects'], $passedArgs, 'events', 'category');
$params['total_elements'] = count($event['objects']);
$event['Event']['warnings'] = $eventWarnings;
return $params;
}

View File

@ -42,6 +42,7 @@ class MispObject extends AppModel {
'ObjectReference' => array(
'className' => 'ObjectReference',
'dependent' => true,
'foreignKey' => 'object_id'
),
);

View File

@ -2,7 +2,7 @@
App::uses('AppModel', 'Model');
class Object extends AppModel {
class ObjectReference extends AppModel {
public $actsAs = array(
'Containable',
'SysLogLogable.SysLogLogable' => array( // TODO Audit, logable

View File

@ -2,9 +2,6 @@
$tr_class = '';
$linkClass = 'white';
$otherColour = 'blue';
if (isset($object['deleted']) && $object['deleted']) {
$tr_class .= ' background-light-red';
}
if (!empty($child)) {
if ($child === 'last' && empty($object['ShadowAttribute'])) {
$tr_class .= ' tableHighlightBorderBottom borderBlue';
@ -20,6 +17,9 @@
$tr_class .= ' tableHighlightBorderTop borderOrange';
}
}
if (!empty($object['deleted'])) {
$tr_class .= ' deleted-attribute';
}
?>
<tr id = "Attribute_<?php echo h($object['id']); ?>_tr" class="<?php echo $tr_class; ?>">
<?php
@ -64,7 +64,7 @@
<div id = "Attribute_<?php echo $object['id']; ?>_value_solid" class="inline-field-solid" <?php echo $editable; ?>>
<span <?php if (Configure::read('Plugin.Enrichment_hover_enable') && isset($modules) && isset($modules['hover_type'][$object['type']])) echo 'class="eventViewAttributeHover" data-object-type="Attribute" data-object-id="' . h($object['id']) . '"'?>>
<?php
echo $this->element('/Events/View/value_field', array('object' => $object));
echo $this->element('/Events/View/value_field', array('object' => $object, 'linkClass' => $linkClass));
?>
</span>
<?php

View File

@ -2,11 +2,25 @@
$tr_class = '';
$linkClass = 'white';
$currentType = 'denyForm';
$tr_class = 'tableHighlightBorderTop borderBlue blueRow';
$tr_class = 'tableHighlightBorderTop borderBlue';
if ($object['deleted']) $tr_class .= ' lightBlueRow';
else $tr_class .= ' blueRow';
?>
<tr id = "Object_<?php echo $object['id']; ?>_tr" class="<?php echo $tr_class; ?>">
<td style="width:10px;" data-position="<?php echo h($object['objectType']) . '_' . h($object['id']); ?>">
<input id = "select_object_<?php echo $object['id']; ?>" class="select_object row_checkbox" type="checkbox" data-id="<?php echo $object['id'];?>" />
<?php
if ($mayModify):
?>
<td style="width:10px;" data-position="<?php echo h($object['objectType']) . '_' . h($object['id']); ?>">
<input id = "select_object_<?php echo $object['id']; ?>" class="select_object row_checkbox" type="checkbox" data-id="<?php echo $object['id'];?>" />
</td>
<?php
endif;
?>
<td class="short context hidden">
<?php echo h($object['id']); ?>
</td>
<td class="short context hidden">
<?php echo h($object['uuid']); ?>
</td>
<td class="short" colspan="2">
<?php echo date('Y-m-d', $object['timestamp']); ?>
@ -44,6 +58,18 @@
<td>&nbsp;</td>
<td>&nbsp;</td>
<td class="short action-links">
<?php
if ($mayModify && empty($object['deleted'])):
?>
<a href="<?php echo $baseurl;?>/objects/edit/<?php echo $object['id']; ?>" title="Edit" class="icon-edit icon-white useCursorPointer"></a>
<span class="icon-trash icon-white useCursorPointer" title="Delete object" role="button" tabindex="0" aria-label="Delete attribute" onClick="deleteObject('objects', 'delete', '<?php echo h($object['id']); ?>', '<?php echo h($event['Event']['id']); ?>');"></span>
<?php
elseif ($mayModify):
?>
<span class="icon-trash icon-white useCursorPointer" title="Delete object" role="button" tabindex="0" aria-label="Delete attribute" onClick="deleteObject('objects', 'delete', '<?php echo h($object['id']) . '/true'; ?>', '<?php echo h($event['Event']['id']); ?>');"></span>
<?php
endif;
?>
</td>
</tr>
<?php

View File

@ -85,65 +85,9 @@
?>
<div id = "<?php echo $currentType; ?>_<?php echo $object['id']; ?>_value_solid" class="inline-field-solid" <?php echo $editable; ?>>
<span <?php if (Configure::read('Plugin.Enrichment_hover_enable') && isset($modules) && isset($modules['hover_type'][$object['type']])) echo 'class="eventViewAttributeHover" data-object-type="' . h($currentType) . '" data-object-id="' . h($object['id']) . '"'?>>
<?php
$sigDisplay = $object['value'];
if ('attachment' == $object['type'] || 'malware-sample' == $object['type'] ) {
if ($object['type'] == 'attachment' && isset($object['image'])) {
$extension = explode('.', $object['value']);
$extension = end($extension);
$uri = 'data:image/' . strtolower(h($extension)) . ';base64,' . h($object['image']);
echo '<img class="screenshot screenshot-collapsed useCursorPointer" src="' . $uri . '" title="' . h($object['value']) . '" />';
} else {
$t = ($object['objectType'] == 0 ? 'attributes' : 'shadow_attributes');
$filenameHash = explode('|', nl2br(h($object['value'])));
if (strrpos($filenameHash[0], '\\')) {
$filepath = substr($filenameHash[0], 0, strrpos($filenameHash[0], '\\'));
$filename = substr($filenameHash[0], strrpos($filenameHash[0], '\\'));
echo h($filepath);
echo '<a href="' . $baseurl . '/' . h($t) . '/download/' . h($object['id']) . '" class="' . $linkClass . '">' . h($filename) . '</a>';
} else {
echo '<a href="' . $baseurl . '/' . h($t) . '/download/' . h($object['id']) . '" class="' . $linkClass . '">' . h($filenameHash[0]) . '</a>';
}
if (isset($filenameHash[1])) echo '<br />' . $filenameHash[1];
}
} else if (strpos($object['type'], '|') !== false) {
$filenameHash = explode('|', $object['value']);
echo h($filenameHash[0]);
if (isset($filenameHash[1])) {
$separator = '<br />';
if (in_array($object['type'], array('ip-dst|port', 'ip-src|port'))) {
$separator = ':';
}
echo $separator . h($filenameHash[1]);
}
} else if ('vulnerability' == $object['type']) {
if (! is_null(Configure::read('MISP.cveurl'))) {
$cveUrl = Configure::read('MISP.cveurl');
} else {
$cveUrl = "http://www.google.com/search?q=";
}
echo $this->Html->link($sigDisplay, $cveUrl . $sigDisplay, array('target' => '_blank', 'class' => $linkClass));
} else if ('link' == $object['type']) {
echo $this->Html->link($sigDisplay, $sigDisplay, array('class' => $linkClass));
} else if ('cortex' == $object['type']) {
echo '<div class="cortex-json" data-cortex-json="' . h($object['value']) . '">Cortex object</div>';
} else if ('text' == $object['type']) {
if ($object['category'] == 'External analysis' && preg_match('/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/i', $object['value'])) {
echo '<a href="' . $baseurl . '/events/view/' . h($object['value']) . '" class="' . $linkClass . '">' . h($object['value']) . '</a>';
} else {
$sigDisplay = str_replace("\r", '', h($sigDisplay));
$sigDisplay = str_replace(" ", '&nbsp;', $sigDisplay);
echo nl2br($sigDisplay);
}
} else if ('hex' == $object['type']) {
$sigDisplay = str_replace("\r", '', $sigDisplay);
echo '<span class="hex-value" title="Hexadecimal representation">' . nl2br(h($sigDisplay)) . '</span>&nbsp;<span role="button" tabindex="0" aria-label="Switch to binary representation" class="icon-repeat hex-value-convert useCursorPointer" title="Switch to binary representation"></span>';
} else {
$sigDisplay = str_replace("\r", '', $sigDisplay);
echo nl2br(h($sigDisplay));
}
if (isset($object['validationIssue'])) echo ' <span class="icon-warning-sign" title="Warning, this doesn\'t seem to be a legitimage ' . strtoupper(h($object['type'])) . ' value">&nbsp;</span>';
?>
<?php
echo $this->element('/Events/View/value_field', array('object' => $object, 'linkClass' => $linkClass));
?>
</span>
<?php
if (isset($object['warnings'])) {
@ -155,7 +99,7 @@
foreach ($object['warnings'][$component] as $warning) $temp .= '<span class=\'bold\'>' . h($valueParts[$valuePart]) . '</span>: <span class=\'red\'>' . h($warning) . '</span><br />';
}
}
echo ' <span class="icon-warning-sign" data-placement="right" data-toggle="popover" data-content="' . h($temp) . '" data-trigger="hover">&nbsp;</span>';
echo ' <span class="icon-warning-sign icon-white" data-placement="right" data-toggle="popover" data-content="' . h($temp) . '" data-trigger="hover">&nbsp;</span>';
}
?>
</div>
@ -185,28 +129,16 @@
<td class="shortish">
<ul class="inline" style="margin:0px;">
<?php
if ($object['objectType'] == 0) {
$relatedObject = 'Attribute';
$otherColour = !empty($object['ShadowAttribute']) ? 'blue' : 'white';
} else {
$relatedObject = 'ShadowAttribute';
$otherColour = 'white';
}
$relatedObject = $object['objectType'] == 0 ? 'Attribute' : 'ShadowAttribute';
if (!empty($event['Related' . $relatedObject][$object['id']])) {
foreach ($event['Related' . $relatedObject][$object['id']] as $relatedAttribute) {
if (!empty($event['RelatedShadowAttribute'][$object['id']])) {
foreach ($event['RelatedShadowAttribute'][$object['id']] as $relatedAttribute) {
$relatedData = array('Event info' => $relatedAttribute['info'], 'Correlating Value' => $relatedAttribute['value'], 'date' => isset($relatedAttribute['date']) ? $relatedAttribute['date'] : 'N/A');
$popover = '';
foreach ($relatedData as $k => $v) {
$popover .= '<span class=\'bold black\'>' . h($k) . '</span>: <span class="blue">' . h($v) . '</span><br />';
}
echo '<li style="padding-right: 0px; padding-left:0px;" data-toggle="popover" data-content="' . h($popover) . '" data-trigger="hover"><span>';
if ($relatedAttribute['org_id'] == $me['org_id']) {
echo $this->Html->link($relatedAttribute['id'], array('controller' => 'events', 'action' => 'view', $relatedAttribute['id'], true, $event['Event']['id']), array('class' => 'red'));
} else {
echo $this->Html->link($relatedAttribute['id'], array('controller' => 'events', 'action' => 'view', $relatedAttribute['id'], true, $event['Event']['id']), array('class' => $otherColour));
}
$correlationClass = 'white' . ($relatedAttribute['org_id'] == $me['org_id'] ? ' bold' : '');
echo $this->Html->link($relatedAttribute['id'], array('controller' => 'events', 'action' => 'view', $relatedAttribute['id'], true, $event['Event']['id']), array('class' => $correlationClass));
echo "</span></li>";
echo ' ';
}
@ -255,45 +187,8 @@
<?php
if (Configure::read('Plugin.Sightings_enable') !== false):
?>
<td class="shortish">
<span id="sightingForm_<?php echo h($object['id']);?>">
<?php
if ($object['objectType'] == 0):
echo $this->Form->create('Sighting', array('id' => 'Sighting_' . $object['id'], 'url' => '/sightings/add/' . $object['id'], 'style' => 'display:none;'));
echo $this->Form->input('type', array('label' => false, 'id' => 'Sighting_' . $object['id'] . '_type'));
echo $this->Form->end();
?>
</span>
<?php
$temp = array();
if (isset($sightingsData['csv'][$object['id']])) {
$temp = $sightingsData['csv'][$object['id']];
}
?>
<span class="icon-thumbs-up useCursorPointer" title="Add sighting" role="button" tabindex="0" aria-label="Add sighting" onClick="addSighting('0', '<?php echo h($object['id']); ?>', '<?php echo h($event['Event']['id']);?>', '<?php echo h($page); ?>');">&nbsp;</span>
<span class="icon-thumbs-down useCursorPointer" title="Mark as false-positive" role="button" tabindex="0" aria-label="Mark as false-positive" onClick="addSighting('1', '<?php echo h($object['id']); ?>', '<?php echo h($event['Event']['id']);?>', '<?php echo h($page); ?>');">&nbsp;</span>
<span class="icon-wrench useCursorPointer sightings_advanced_add" title="Advanced sightings" role="button" tabindex="0" aria-label="Advanced sightings" data-object-id="<?php echo h($object['id']); ?>" data-object-context="attribute">&nbsp;</span>
<span id="sightingCount_<?php echo h($object['id']); ?>" class="bold sightingsCounter_<?php echo h($object['id']); ?>" data-placement="top" data-toggle="popover" data-trigger="hover" data-content="<?php echo isset($sightingsData['data'][$object['id']]['html']) ? $sightingsData['data'][$object['id']]['html'] : ''; ?>">
<?php
$s = (!empty($sightingsData['data'][$object['id']]['sighting']['count']) ? $sightingsData['data'][$object['id']]['sighting']['count'] : 0);
$f = (!empty($sightingsData['data'][$object['id']]['false-positive']['count']) ? $sightingsData['data'][$object['id']]['false-positive']['count'] : 0);
$e = (!empty($sightingsData['data'][$object['id']]['expiration']['count']) ? $sightingsData['data'][$object['id']]['expiration']['count'] : 0);
?>
</span>
<span id="ownSightingCount_<?php echo h($object['id']); ?>" class="bold sightingsCounter_<?php echo h($object['id']); ?>" data-placement="top" data-toggle="popover" data-trigger="hover" data-content="<?php echo isset($sightingsData['data'][$object['id']]['html']) ? $sightingsData['data'][$object['id']]['html'] : ''; ?>">
<?php echo '(<span class="green">' . h($s) . '</span>/<span class="red">' . h($f) . '</span>/<span class="orange">' . h($e) . '</span>)'; ?>
</span>
<?php
endif;
?>
</td>
<td class="short">
<?php
if ($object['objectType'] == 0 && !empty($temp)) {
echo $this->element('sparkline', array('id' => $object['id'], 'csv' => $temp));
}
?>
</td>
<td class="shortish">&nbsp;</td>
<td class="short">&nbsp;</td>
<?php
endif;
?>
@ -303,12 +198,12 @@
echo $this->Form->create('Shadow_Attribute', array('id' => 'ShadowAttribute_' . $object['id'] . '_accept', 'url' => '/shadow_attributes/accept/' . $object['id'], 'style' => 'display:none;'));
echo $this->Form->end();
?>
<span class="icon-ok useCursorPointer" title="Accept Proposal" role="button" tabindex="0" aria-label="Accept proposal" onClick="acceptObject('shadow_attributes', '<?php echo $object['id']; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
<span class="icon-ok icon-white useCursorPointer" title="Accept Proposal" role="button" tabindex="0" aria-label="Accept proposal" onClick="acceptObject('shadow_attributes', '<?php echo $object['id']; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
<?php
}
if (($event['Orgc']['id'] == $me['org_id'] && $mayModify) || $isSiteAdmin || ($object['org_id'] == $me['org_id'])) {
?>
<span class="icon-trash useCursorPointer" title="Discard proposal" role="button" tabindex="0" aria-label="Discard proposal" onClick="deleteObject('shadow_attributes', 'discard' ,'<?php echo $object['id']; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
<span class="icon-trash icon-white useCursorPointer" title="Discard proposal" role="button" tabindex="0" aria-label="Discard proposal" onClick="deleteObject('shadow_attributes', 'discard' ,'<?php echo $object['id']; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
<?php
}
?>

View File

@ -30,16 +30,25 @@
}
?>
<tr id = "<?php echo $currentType . '_' . $object['id'] . '_tr'; ?>" class="<?php echo $tr_class; ?>">
<?php if ($mayModify): ?>
<td style="width:10px;" data-position="<?php echo h($object['objectType']) . '_' . h($object['id']); ?>">
<?php if ($object['objectType'] == 0): ?>
<input id = "select_<?php echo $object['id']; ?>" class="select_attribute row_checkbox" type="checkbox" data-id="<?php echo $object['id'];?>" />
<?php else: ?>
<input id = "select_proposal_<?php echo $object['id']; ?>" class="select_proposal row_checkbox" type="checkbox" data-id="<?php echo $object['id'];?>" />
<?php endif; ?>
</td>
<?php endif;
<?php
if ($mayModify):
?>
<td style="width:10px;" data-position="<?php echo h($object['objectType']) . '_' . h($object['id']); ?>">
<?php if ($object['objectType'] == 0): ?>
<input id = "select_<?php echo $object['id']; ?>" class="select_attribute row_checkbox" type="checkbox" data-id="<?php echo $object['id'];?>" />
<?php else: ?>
<input id = "select_proposal_<?php echo $object['id']; ?>" class="select_proposal row_checkbox" type="checkbox" data-id="<?php echo $object['id'];?>" />
<?php endif; ?>
</td>
<?php
endif;
?>
<td class="short context hidden">
<?php echo h($object['id']); ?>
</td>
<td class="short context hidden">
<?php echo h($object['uuid']); ?>
</td>
<td colspan="<?php echo $fieldCount; ?>" style="font-weight:bold;text-align:left;width:100%;">DELETE</td>
<td class="short action-links">
<?php
@ -47,12 +56,12 @@
echo $this->Form->create('Shadow_Attribute', array('id' => 'ShadowAttribute_' . $object['id'] . '_accept', 'url' => '/shadow_attributes/accept/' . $object['id'], 'style' => 'display:none;'));
echo $this->Form->end();
?>
<span class="icon-ok useCursorPointer" title="Accept Proposal" role="button" tabindex="0" aria-label="Accept proposal" onClick="acceptObject('shadow_attributes', '<?php echo $object['id']; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
<span class="icon-ok icon-white useCursorPointer" title="Accept Proposal" role="button" tabindex="0" aria-label="Accept proposal" onClick="acceptObject('shadow_attributes', '<?php echo $object['id']; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
<?php
}
if (($event['Orgc']['id'] == $me['org_id'] && $mayModify) || $isSiteAdmin || ($object['org_id'] == $me['org_id'])) {
?>
<span class="icon-trash useCursorPointer" title="Discard proposal" role="button" tabindex="0" aria-label="Discard proposal" onClick="deleteObject('shadow_attributes', 'discard' ,'<?php echo $object['id']; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
<span class="icon-trash icon-white useCursorPointer" title="Discard proposal" role="button" tabindex="0" aria-label="Discard proposal" onClick="deleteObject('shadow_attributes', 'discard' ,'<?php echo $object['id']; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
<?php
}
?>

View File

@ -119,7 +119,7 @@
</div>
<div class="tabMenu tabMenuFiltersBlock noPrint" style="padding-right:0px !important;">
<span id="filter_header" class="attribute_filter_header">Filters: </span>
<div id="filter_all" title="Show all attributes" role="button" tabindex="0" aria-label="Show all attributes" class="attribute_filter_text<?php if ($attributeFilter == 'all') echo '_active'; ?>" onClick="filterAttributes('all', '<?php echo h($event['Event']['id']); ?>');">All (<?php echo h($this->Paginator->params()['total_elements']); ?>)</div>
<div id="filter_all" title="Show all attributes" role="button" tabindex="0" aria-label="Show all attributes" class="attribute_filter_text<?php if ($attributeFilter == 'all') echo '_active'; ?>" onClick="filterAttributes('all', '<?php echo h($event['Event']['id']); ?>');">All</div>
<?php foreach ($typeGroups as $group): ?>
<div id="filter_<?php echo h($group); ?>" title="Only show <?php echo $group; ?> related attributes" role="button" tabindex="0" aria-label="Only show <?php echo h($group); ?> related attributes" class="attribute_filter_text<?php if ($attributeFilter == $group) echo '_active'; ?>" onClick="filterAttributes('<?php echo $group; ?>', '<?php echo h($event['Event']['id']); ?>');"><?php echo ucfirst($group); ?></div>
<?php endforeach; ?>

View File

@ -0,0 +1,25 @@
<div class="confirmation">
<?php
echo $this->Form->create('Object', array('style' => 'margin:0px;', 'id' => 'PromptForm'));
if ($hard) $hard = '/true';
?>
<legend>Object Deletion</legend>
<div style="padding-left:5px;padding-right:5px;padding-bottom:5px;">
<p>Are you sure you want to <?php if ($hard) echo 'hard-'; ?>delete Object #<?php echo $id?>?<?php if ($hard) echo ' The Object will be permanently deleted and unrecoverable. Also, this will prevent the deletion to be propagated to other instances.'; ?></p>
<table>
<tr>
<td style="vertical-align:top">
<span id="PromptYesButton" title="Delete" role="button" tabindex="0" aria-label="Delete" class="btn btn-primary" onClick="submitDeletion(<?php echo $event_id; ?>, 'delete', 'objects', '<?php echo $id . $hard;?>')">Yes</span>
</td>
<td style="width:540px;">
</td>
<td style="vertical-align:top;">
<span class="btn btn-inverse" title="Cancel" role="button" tabindex="0" aria-label="Cancel" id="PromptNoButton" onClick="cancelPrompt();">No</span>
</td>
</tr>
</table>
</div>
<?php
echo $this->Form->end();
?>
</div>

View File

@ -1511,6 +1511,10 @@ a.proposal_link_red:hover {
color: white !important;
}
tr.deleted-attribute td {
background-color: #d3d7cf !important;
}
.background-deleted {
background: repeating-linear-gradient(
45deg,
@ -1845,6 +1849,11 @@ tr.blueRow td, .blueElement {
border-top:0px !important;
}
tr.lightBlueRow td, .lightBlueElement {
background-color: #729fcf !important;
border-top:0px !important;
}
tr.redRow td, .redElement {
background-color: #cc0000 !important;
color: #ffffff;

View File

@ -4,7 +4,7 @@ String.prototype.ucfirst = function() {
function deleteObject(type, action, id, event) {
var destination = 'attributes';
var alternateDestinations = ['shadow_attributes', 'template_elements', 'taxonomies'];
var alternateDestinations = ['shadow_attributes', 'template_elements', 'taxonomies', 'objects'];
if (alternateDestinations.indexOf(type) > -1) destination = type;
url = "/" + destination + "/" + action + "/" + id;
$.get(url, function(data) {