mirror of https://github.com/MISP/MISP
chg: [UI] Inline attribute detaching
parent
d3770295cc
commit
270080bce4
|
@ -547,100 +547,30 @@ class GalaxyClustersController extends AppController
|
|||
|
||||
public function detach($target_id, $target_type, $tag_id)
|
||||
{
|
||||
$this->loadModel('Event');
|
||||
if ($target_type == 'attribute') {
|
||||
$attribute = $this->Event->Attribute->find('first', array(
|
||||
'recursive' => -1,
|
||||
'fields' => array('id', 'event_id'),
|
||||
'conditions' => array('Attribute.id' => $target_id)
|
||||
));
|
||||
if (empty($attribute)) {
|
||||
throw new MethodNotAllowedException('Invalid Attribute.');
|
||||
}
|
||||
$event_id = $attribute['Attribute']['event_id'];
|
||||
} elseif ($target_type == 'event') {
|
||||
$event_id = $target_id;
|
||||
} elseif ($target_type === 'tag_collection') {
|
||||
// pass
|
||||
} else {
|
||||
throw new MethodNotAllowedException('Invalid options');
|
||||
if ($this->request->is("ajax") && $this->request->is("get")) {
|
||||
$this->set("url", $this->request->url);
|
||||
return $this->render("/Elements/emtpyForm", false);
|
||||
}
|
||||
|
||||
if ($target_type === 'tag_collection') {
|
||||
$tag_collection = $this->GalaxyCluster->Tag->TagCollectionTag->TagCollection->fetchTagCollection($this->Auth->user(), array(
|
||||
'conditions' => array('TagCollection.id' => $target_id),
|
||||
'contain' => array('Organisation', 'TagCollectionTag' => array('Tag'))
|
||||
));
|
||||
if (empty($tag_collection)) {
|
||||
throw new MethodNotAllowedException('Invalid Tag Collection');
|
||||
}
|
||||
$tag_collection = $tag_collection[0];
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
if (!$this->userRole['perm_tag_editor'] || $this->Auth->user('org_id') !== $tag_collection['TagCollection']['org_id']) {
|
||||
throw new MethodNotAllowedException('Invalid Tag Collection');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->Event->id = $event_id;
|
||||
$this->Event->recursive = -1;
|
||||
$event = $this->Event->read(array(), $event_id);
|
||||
if (empty($event)) {
|
||||
throw new MethodNotAllowedException('Invalid Event.');
|
||||
}
|
||||
if (!$this->_isSiteAdmin() && !$this->userRole['perm_sync']) {
|
||||
if (!$this->userRole['perm_tagger'] || ($this->Auth->user('org_id') !== $event['Event']['org_id'] && $this->Auth->user('org_id') !== $event['Event']['orgc_id'])) {
|
||||
throw new MethodNotAllowedException('Invalid Event.');
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->request->allowMethod(["post"]);
|
||||
|
||||
if ($target_type == 'attribute') {
|
||||
$existingTargetTag = $this->Event->Attribute->AttributeTag->find('first', array(
|
||||
'conditions' => array('AttributeTag.tag_id' => $tag_id, 'AttributeTag.attribute_id' => $target_id),
|
||||
'recursive' => -1,
|
||||
'contain' => array('Tag')
|
||||
));
|
||||
} elseif ($target_type == 'event') {
|
||||
$existingTargetTag = $this->Event->EventTag->find('first', array(
|
||||
'conditions' => array('EventTag.tag_id' => $tag_id, 'EventTag.event_id' => $target_id),
|
||||
'recursive' => -1,
|
||||
'contain' => array('Tag')
|
||||
));
|
||||
} elseif ($target_type == 'tag_collection') {
|
||||
$existingTargetTag = $this->GalaxyCluster->Tag->TagCollectionTag->find('first', array(
|
||||
'conditions' => array('TagCollectionTag.tag_id' => $tag_id, 'TagCollectionTag.tag_collection_id' => $target_id),
|
||||
'recursive' => -1,
|
||||
'contain' => array('Tag')
|
||||
));
|
||||
}
|
||||
|
||||
if (empty($existingTargetTag)) {
|
||||
$this->Flash->error('Galaxy not attached.');
|
||||
} else {
|
||||
$cluster = $this->GalaxyCluster->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('GalaxyCluster.tag_name' => $existingTargetTag['Tag']['name'])
|
||||
));
|
||||
if ($target_type == 'event') {
|
||||
$result = $this->Event->EventTag->delete($existingTargetTag['EventTag']['id']);
|
||||
} elseif ($target_type == 'attribute') {
|
||||
$result = $this->Event->Attribute->AttributeTag->delete($existingTargetTag['AttributeTag']['id']);
|
||||
} elseif ($target_type == 'tag_collection') {
|
||||
$result = $this->GalaxyCluster->Tag->TagCollectionTag->delete($existingTargetTag['TagCollectionTag']['id']);
|
||||
}
|
||||
if ($result) {
|
||||
$event['Event']['published'] = 0;
|
||||
$date = new DateTime();
|
||||
$event['Event']['timestamp'] = $date->getTimestamp();
|
||||
$this->Event->save($event);
|
||||
$this->Flash->success('Galaxy successfully detached.');
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$logTitle = 'Detached ' . $cluster['GalaxyCluster']['value'] . ' (' . $cluster['GalaxyCluster']['id'] . ') from ' . $target_type . ' (' . $target_id . ')';
|
||||
$this->Log->createLogEntry($this->Auth->user(), 'galaxy', ucfirst($target_type), $target_id, $logTitle);
|
||||
try {
|
||||
$this->GalaxyCluster->Galaxy->detachClusterByTagId($this->Auth->user(), $target_id, $target_type, $tag_id);
|
||||
} catch (NotFoundException $e) {
|
||||
if (!$this->request->is("ajax")) {
|
||||
$this->Flash->error($e->getMessage());
|
||||
} else {
|
||||
$this->Flash->error('Could not detach galaxy from event.');
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
$message = __('Galaxy successfully detached.');
|
||||
|
||||
if ($this->request->is("ajax")) {
|
||||
return $this->RestResponse->viewData(["saved" => true, "check_publish" => true, "success" => $message], "json");
|
||||
}
|
||||
|
||||
$this->Flash->success($message);
|
||||
$this->redirect($this->referer());
|
||||
}
|
||||
|
||||
|
|
|
@ -544,6 +544,111 @@ class Galaxy extends AppModel
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $user
|
||||
* @param int $targetId
|
||||
* @param string $targetType
|
||||
* @param int $tagId
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function detachClusterByTagId(array $user, $targetId, $targetType, $tagId)
|
||||
{
|
||||
if ($targetType === 'attribute') {
|
||||
$attribute = $this->GalaxyCluster->Tag->EventTag->Event->Attribute->find('first', array(
|
||||
'recursive' => -1,
|
||||
'fields' => array('id', 'event_id'),
|
||||
'conditions' => array('Attribute.id' => $targetId)
|
||||
));
|
||||
if (empty($attribute)) {
|
||||
throw new NotFoundException('Invalid Attribute.');
|
||||
}
|
||||
$event_id = $attribute['Attribute']['event_id'];
|
||||
} elseif ($targetType === 'event') {
|
||||
$event_id = $targetId;
|
||||
} elseif ($targetType !== 'tag_collection') {
|
||||
throw new NotFoundException('Invalid options');
|
||||
}
|
||||
|
||||
if ($targetType === 'tag_collection') {
|
||||
$tag_collection = $this->GalaxyCluster->Tag->TagCollectionTag->TagCollection->fetchTagCollection($user, array(
|
||||
'conditions' => array('TagCollection.id' => $targetId),
|
||||
'recusive' => -1,
|
||||
));
|
||||
if (empty($tag_collection)) {
|
||||
throw new NotFoundException('Invalid Tag Collection');
|
||||
}
|
||||
$tag_collection = $tag_collection[0];
|
||||
if (!$user["Role"]["perm_site_admin"]) {
|
||||
if (!$user["Role"]['perm_tag_editor'] || $user['org_id'] !== $tag_collection['TagCollection']['org_id']) {
|
||||
throw new NotFoundException('Invalid Tag Collection');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$event = $this->GalaxyCluster->Tag->EventTag->Event->fetchSimpleEvent($user, $event_id);
|
||||
if (empty($event)) {
|
||||
throw new NotFoundException('Invalid Event.');
|
||||
}
|
||||
if (!$user["Role"]["perm_site_admin"] && !$user["Role"]['perm_sync']) {
|
||||
if (!$user["Role"]['perm_tagger'] || ($user['org_id'] !== $event['Event']['org_id'] && $user['org_id'] !== $event['Event']['orgc_id'])) {
|
||||
throw new NotFoundException('Invalid Event.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($targetType === 'attribute') {
|
||||
$existingTargetTag = $this->GalaxyCluster->Tag->AttributeTag->find('first', array(
|
||||
'conditions' => array('AttributeTag.tag_id' => $tagId, 'AttributeTag.attribute_id' => $targetId),
|
||||
'recursive' => -1,
|
||||
'contain' => array('Tag')
|
||||
));
|
||||
} elseif ($targetType === 'event') {
|
||||
$existingTargetTag = $this->GalaxyCluster->Tag->EventTag->find('first', array(
|
||||
'conditions' => array('EventTag.tag_id' => $tagId, 'EventTag.event_id' => $targetId),
|
||||
'recursive' => -1,
|
||||
'contain' => array('Tag')
|
||||
));
|
||||
} elseif ($targetType === 'tag_collection') {
|
||||
$existingTargetTag = $this->GalaxyCluster->Tag->TagCollectionTag->find('first', array(
|
||||
'conditions' => array('TagCollectionTag.tag_id' => $tagId, 'TagCollectionTag.tag_collection_id' => $targetId),
|
||||
'recursive' => -1,
|
||||
'contain' => array('Tag')
|
||||
));
|
||||
}
|
||||
|
||||
if (empty($existingTargetTag)) {
|
||||
throw new NotFoundException('Galaxy not attached.');
|
||||
}
|
||||
|
||||
$cluster = $this->GalaxyCluster->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('GalaxyCluster.tag_name' => $existingTargetTag['Tag']['name'])
|
||||
));
|
||||
if (empty($cluster)) {
|
||||
throw new NotFoundException("Tag is not cluster");
|
||||
}
|
||||
|
||||
if ($targetType === 'event') {
|
||||
$result = $this->GalaxyCluster->Tag->EventTag->delete($existingTargetTag['EventTag']['id']);
|
||||
} elseif ($targetType === 'attribute') {
|
||||
$result = $this->GalaxyCluster->Tag->AttributeTag->delete($existingTargetTag['AttributeTag']['id']);
|
||||
} elseif ($targetType === 'tag_collection') {
|
||||
$result = $this->GalaxyCluster->Tag->TagCollectionTag->delete($existingTargetTag['TagCollectionTag']['id']);
|
||||
}
|
||||
if (!$result) {
|
||||
throw new RuntimeException('Could not detach galaxy from event.');
|
||||
}
|
||||
|
||||
if ($targetType !== 'tag_collection') {
|
||||
$event['Event']['published'] = 0;
|
||||
$event['Event']['timestamp'] = time();
|
||||
$this->GalaxyCluster->Tag->EventTag->Event->save($event);
|
||||
}
|
||||
|
||||
$logTitle = 'Detached ' . $cluster['GalaxyCluster']['value'] . ' (' . $cluster['GalaxyCluster']['id'] . ') from ' . $targetType . ' (' . $targetId . ')';
|
||||
$this->loadLog()->createLogEntry($user, 'galaxy', ucfirst($targetType), $targetId, $logTitle);
|
||||
}
|
||||
|
||||
public function getMitreAttackGalaxyId($type="mitre-attack-pattern", $namespace="mitre-attack")
|
||||
{
|
||||
$galaxy = $this->find('first', array(
|
||||
|
|
|
@ -4,6 +4,7 @@ App::uses('TmpFileTool', 'Tools');
|
|||
|
||||
/**
|
||||
* @property Tag $Tag
|
||||
* @property Galaxy $Galaxy
|
||||
* @property GalaxyClusterRelation $GalaxyClusterRelation
|
||||
* @property GalaxyElement $GalaxyElement
|
||||
*/
|
||||
|
|
|
@ -114,7 +114,6 @@
|
|||
// Generate tooltip information
|
||||
//
|
||||
var formInfoValues = new Array();
|
||||
var fieldsArrayAttribute = new Array('AttributeDistribution', 'AttributeComment', 'AttributeToIds');
|
||||
<?php
|
||||
foreach ($distributionDescriptions as $type => $def) {
|
||||
$info = isset($def['formdesc']) ? $def['formdesc'] : $def['desc'];
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<?php
|
||||
echo $this->Form->create(false, ['id' => false, 'url' => $url]);
|
||||
echo $this->Form->end();
|
|
@ -58,7 +58,7 @@ $generatePopover = function (array $cluster) use ($normalizeKey) {
|
|||
}
|
||||
$popover = '<h4 class="blue" style="white-space: nowrap">' . h($cluster['value']) . '</h4>';
|
||||
foreach ($clusterFields as $clusterField) {
|
||||
$key = '<span class="blue bold">' . h($normalizeKey($clusterField['key'])) . '</span>';
|
||||
$key = '<b class="blue">' . h($normalizeKey($clusterField['key'])) . '</b>';
|
||||
if (is_array($clusterField['value'])) {
|
||||
if ($clusterField['key'] === 'country') {
|
||||
$value = [];
|
||||
|
@ -102,18 +102,16 @@ $generatePopover = function (array $cluster) use ($normalizeKey) {
|
|||
<a href="<?= $baseurl ?>/events/index/searchtag:<?= h($cluster['tag_id']) ?>" class="black fa fa-list" title="<?= __('View all events containing this cluster') ?>" aria-label="<?= __('View all events containing this cluster') ?>"></a>
|
||||
<?php endif ;?>
|
||||
<?php if ($editButtonsEnabled || ($editButtonsLocalEnabled && $cluster['local'])) {
|
||||
echo $this->Form->create(false, [
|
||||
'id' => false, // prevent duplicate ids
|
||||
'url' => $baseurl . '/galaxy_clusters/detach/' . ucfirst(h($target_id)) . '/' . h($target_type) . '/' . $cluster['tag_id'],
|
||||
'style' => 'display: inline-block; margin: 0px;'
|
||||
]);
|
||||
echo sprintf(
|
||||
'<a href="#" class="black fa fa-trash useCursorPointer" role="button" tabindex="0" aria-label="%s" title="%s" onclick="popoverConfirm(this);"></a>',
|
||||
__('Detach'),
|
||||
__('Are you sure you want to detach %s from this event?', h($cluster['value']))
|
||||
);
|
||||
echo $this->Form->end();
|
||||
}
|
||||
$url = $baseurl . '/galaxy_clusters/detach/' . intval($target_id) . '/' . h($target_type) . '/' . $cluster['tag_id'];
|
||||
echo sprintf(
|
||||
'<a href="%s" class="black fa fa-trash" role="button" tabindex="0" aria-label="%s" title="%s" onclick="confirmClusterDetach(this, \'%s\', %s);"></a>',
|
||||
$url,
|
||||
__('Detach'),
|
||||
__('Are you sure you want to detach %s from this event?', h($cluster['value'])),
|
||||
h($target_type),
|
||||
intval($target_id)
|
||||
);
|
||||
}
|
||||
?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
|
|
|
@ -1064,10 +1064,10 @@ function loadGalaxies(id, scope) {
|
|||
$.ajax({
|
||||
dataType:"html",
|
||||
cache: false,
|
||||
success:function (data) {
|
||||
if (scope == 'event') {
|
||||
success: function (data) {
|
||||
if (scope === 'event') {
|
||||
$("#galaxies_div").html(data);
|
||||
} else if (scope == 'attribute') {
|
||||
} else if (scope === 'attribute') {
|
||||
$("#attribute_" + id + "_galaxy").html(data);
|
||||
}
|
||||
},
|
||||
|
@ -1816,56 +1816,65 @@ function popoverPopupNew(clicked, url) {
|
|||
});
|
||||
}
|
||||
|
||||
function confirmClusterDetach(clicked, target_type, target_id) {
|
||||
popoverConfirm(clicked, undefined, undefined, function (data) {
|
||||
handleGenericAjaxResponse(data);
|
||||
if (target_type === "event") {
|
||||
loadGalaxies(target_id, 'event');
|
||||
} else if (target_type === "attribute") {
|
||||
loadGalaxies(target_id, 'attribute');
|
||||
} else {
|
||||
location.reload();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// create a confirm popover on the clicked html node.
|
||||
function popoverConfirm(clicked, message, placement) {
|
||||
function popoverConfirm(clicked, message, placement, callback) {
|
||||
event.preventDefault();
|
||||
|
||||
var $clicked = $(clicked);
|
||||
var popoverContent = '<div>';
|
||||
popoverContent += message === undefined ? '' : '<p>' + message + '</p>';
|
||||
popoverContent += '<button id="popoverConfirmOK" class="btn btn-primary" style="margin-right: 5px;" onclick=submitPopover(this)>Yes</button>';
|
||||
popoverContent += '<button class="btn btn-inverse" style="float: right;" onclick=cancelPrompt()>Cancel</button>';
|
||||
popoverContent += '<button id="popoverConfirmOK" class="btn btn-primary" style="margin-right: 5px;">Yes</button>';
|
||||
popoverContent += '<button class="btn btn-inverse" style="float: right;" onclick="cancelPrompt()">Cancel</button>';
|
||||
popoverContent += '</div>';
|
||||
openPopover($clicked, popoverContent, undefined, placement);
|
||||
|
||||
$("#popoverConfirmOK")
|
||||
.focus()
|
||||
.bind("keydown", function(e) {
|
||||
if (e.ctrlKey && (e.keyCode == 13 || e.keyCode == 10)) {
|
||||
$(this).click();
|
||||
}
|
||||
if(e.keyCode == 27) { // ESC
|
||||
} else if (e.keyCode == 27) { // ESC
|
||||
$clicked.popover('destroy');
|
||||
}
|
||||
}).click(function() {
|
||||
var href = $clicked.attr("href");
|
||||
// Load form to get new token
|
||||
fetchFormDataAjax(href, function (form) {
|
||||
var $form = $(form);
|
||||
xhr({
|
||||
data: $form.serialize(),
|
||||
success: function (data) {
|
||||
if (callback !== undefined) {
|
||||
callback(data);
|
||||
} else {
|
||||
location.reload();
|
||||
}
|
||||
},
|
||||
complete: function() {
|
||||
$(".loading").hide();
|
||||
$("#popover_form").fadeOut();
|
||||
$("#gray_out").fadeOut();
|
||||
},
|
||||
type: "post",
|
||||
url: $form.attr('action')
|
||||
});
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function submitPopover(clicked) {
|
||||
var $clicked = $(clicked);
|
||||
var $form = $clicked.closest('form');
|
||||
if ($form.length === 0) { // popover container is body, submit from original node
|
||||
var dismissid = $clicked.closest('div.popover').attr('data-dismissid');
|
||||
$form = $('[data-dismissid="' + dismissid + '"]').closest('form');
|
||||
}
|
||||
if ($form.data('ajax')) {
|
||||
xhr({
|
||||
data: $form.serialize(),
|
||||
success:function () {
|
||||
location.reload();
|
||||
},
|
||||
complete:function() {
|
||||
$(".loading").hide();
|
||||
$("#popover_form").fadeOut();
|
||||
$("#gray_out").fadeOut();
|
||||
$('#temp').remove();
|
||||
},
|
||||
type:"post",
|
||||
url: $form.attr('action')
|
||||
});
|
||||
} else {
|
||||
$form.submit();
|
||||
}
|
||||
}
|
||||
|
||||
function simplePopup(url, requestType, data) {
|
||||
requestType = requestType === undefined ? 'GET' : requestType
|
||||
data = data === undefined ? [] : data
|
||||
|
|
Loading…
Reference in New Issue