From aacd19a31807d1950153bc5b416df59f41906dc5 Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Fri, 14 Oct 2022 12:58:08 +0200 Subject: [PATCH 1/4] fix: [UI] Submit form on CTRL+ENTER on select --- app/Controller/AppController.php | 2 +- app/View/Tags/modify_tag_relationship.ctp | 9 +-------- app/View/genericTemplates/confirm.ctp | 9 +-------- app/View/genericTemplates/delete.ctp | 11 ++--------- app/View/genericTemplates/select.ctp | 9 +-------- app/webroot/js/misp.js | 4 ++-- 6 files changed, 8 insertions(+), 36 deletions(-) diff --git a/app/Controller/AppController.php b/app/Controller/AppController.php index 2e30cb613..7d4b7c723 100755 --- a/app/Controller/AppController.php +++ b/app/Controller/AppController.php @@ -35,7 +35,7 @@ class AppController extends Controller public $helpers = array('OrgImg', 'FontAwesome', 'UserName'); - private $__queryVersion = '145'; + private $__queryVersion = '146'; public $pyMispVersion = '2.4.162'; public $phpmin = '7.2'; public $phprec = '7.4'; diff --git a/app/View/Tags/modify_tag_relationship.ctp b/app/View/Tags/modify_tag_relationship.ctp index 3405910dc..193c35cd3 100644 --- a/app/View/Tags/modify_tag_relationship.ctp +++ b/app/View/Tags/modify_tag_relationship.ctp @@ -12,16 +12,9 @@ Form->postLink( h($actionName), $this->request->here(), - ['class' => 'btn btn-primary button-execute'] + ['class' => 'btn btn-primary'] ) ?> - diff --git a/app/View/genericTemplates/confirm.ctp b/app/View/genericTemplates/confirm.ctp index 3405910dc..193c35cd3 100644 --- a/app/View/genericTemplates/confirm.ctp +++ b/app/View/genericTemplates/confirm.ctp @@ -12,16 +12,9 @@ Form->postLink( h($actionName), $this->request->here(), - ['class' => 'btn btn-primary button-execute'] + ['class' => 'btn btn-primary'] ) ?> - diff --git a/app/View/genericTemplates/delete.ctp b/app/View/genericTemplates/delete.ctp index 1ea0482f5..b31186695 100644 --- a/app/View/genericTemplates/delete.ctp +++ b/app/View/genericTemplates/delete.ctp @@ -23,17 +23,10 @@ $title = Inflector::singularize(Inflector::humanize(Inflector::underscore($this- Form->postLink( 'Delete', $this->request->here(), - ['class' => 'btn btn-primary button-execute'] + ['class' => 'btn btn-primary'] ) ?> - - + \ No newline at end of file diff --git a/app/View/genericTemplates/select.ctp b/app/View/genericTemplates/select.ctp index c94de9ac8..6f9acbd35 100644 --- a/app/View/genericTemplates/select.ctp +++ b/app/View/genericTemplates/select.ctp @@ -18,14 +18,7 @@ ?> - diff --git a/app/webroot/js/misp.js b/app/webroot/js/misp.js index 10b89952e..7dbb74a09 100644 --- a/app/webroot/js/misp.js +++ b/app/webroot/js/misp.js @@ -4849,8 +4849,8 @@ $(document.body).on('keyup', '#quickFilterField', function(e) { } }); -// Send textarea form on CMD+ENTER or CTRL+ENTER -$(document.body).on('keydown', 'textarea', function(e) { +// Send textarea or select form on CMD+ENTER or CTRL+ENTER +$(document.body).on('keydown', 'textarea, select', function(e) { if (e.keyCode === 13 && (e.metaKey || e.ctrlKey)) { // CMD+ENTER or CTRL+ENTER key if (e.target.form) { $(e.target.form).submit(); From 4be480f4e0dbab4882efd5fadbf1ce4f93eb8f4b Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Fri, 14 Oct 2022 13:50:54 +0200 Subject: [PATCH 2/4] chg: [api] Return REST responses for modifyTagRelationship --- .../Component/RestResponseComponent.php | 26 +++++++++++++++++++ app/Controller/TagsController.php | 22 ++++++++++++---- app/View/genericTemplates/select.ctp | 3 ++- 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/app/Controller/Component/RestResponseComponent.php b/app/Controller/Component/RestResponseComponent.php index 0285e4a9d..7d4eff929 100644 --- a/app/Controller/Component/RestResponseComponent.php +++ b/app/Controller/Component/RestResponseComponent.php @@ -488,6 +488,7 @@ class RestResponseComponent extends Component * @param mixed $data * @return CakeResponse * @throws Exception + * @deprecated Use failResponse instead */ public function saveFailResponse($controller, $action, $id, $validationErrors, $format = false, $data = null) { @@ -514,6 +515,18 @@ class RestResponseComponent extends Component return $this->__sendResponse($response, 403, $format); } + /** + * @param int|null $id + * @param array|string $validationErrors + * @param mixed $additionalData + * @return CakeResponse|CakeResponseFile + * @throws Exception + */ + public function failResponse($id = null, $validationErrors = null, $additionalData = null) + { + return $this->saveFailResponse($this->Controller->name, $this->Controller->action, $id, $validationErrors, 'json', $additionalData); + } + /** * @param string $controller * @param string $action @@ -523,6 +536,7 @@ class RestResponseComponent extends Component * @param mixed $data * @return CakeResponse * @throws Exception + * @deprecated Use successResponse instead */ public function saveSuccessResponse($controller, $action, $id = false, $format = false, $message = false, $data = null) { @@ -546,6 +560,18 @@ class RestResponseComponent extends Component return $this->__sendResponse($response, 200, $format); } + /** + * @param int|null $id + * @param string|null $message + * @param mixed $additionalData + * @return CakeResponse|CakeResponseFile + * @throws Exception + */ + public function successResponse($id = null, $message = null, $additionalData = null) + { + return $this->saveSuccessResponse($this->Controller->name, $this->Controller->action, $id, 'json', $message, $additionalData); + } + /** * @param mixed $response * @param int $code diff --git a/app/Controller/TagsController.php b/app/Controller/TagsController.php index 9ee777668..4c98b8892 100644 --- a/app/Controller/TagsController.php +++ b/app/Controller/TagsController.php @@ -1064,9 +1064,10 @@ class TagsController extends AppController return $this->RestResponse->viewData($tags, $this->response->type()); } - public function modifyTagRelationship($scope, $id) { + public function modifyTagRelationship($scope, $id) + { $validScopes = ['event', 'attribute']; - if (!in_array($scope, $validScopes)) { + if (!in_array($scope, $validScopes, true)) { throw new InvalidArgumentException(__('Invalid scope. Valid options: %s', implode(', ', $validScopes))); } $model_name = Inflector::classify($scope) . 'Tag'; @@ -1075,17 +1076,27 @@ class TagsController extends AppController 'recursive' => -1, 'contain' => 'Tag' ]); + if (empty($tagConnector)) { + throw new NotFoundException(__('Tag not found.')); + } + $event = $this->Tag->EventTag->Event->fetchSimpleEvent($this->Auth->user(), $tagConnector[$model_name]['event_id']); + if (empty($event)) { + throw new NotFoundException(__('Event not found.')); + } + if (!$this->__canModifyTag($event, $tagConnector[$model_name]['local'])) { + throw new ForbiddenException(__('You dont have permission to modify this tag.')); + } if ($this->request->is('post')) { if (isset($this->request->data['Tag']['relationship_type'])) { $tagConnector[$model_name]['relationship_type'] = $this->request->data['Tag']['relationship_type']; } else { $tagConnector[$model_name]['relationship_type'] = ''; } - $result = $this->Tag->$model_name->save($tagConnector); + $result = $this->Tag->$model_name->save($tagConnector, true, ['relationship_type']); if ($result) { $message = __('Relationship updated.'); if ($this->_isRest()) { - + return $this->RestResponse->successResponse($id, $message); } else { $this->Flash->success($message); $this->redirect($this->referer()); @@ -1093,7 +1104,7 @@ class TagsController extends AppController } else { $message = __('Relationship could not be updated.'); if ($this->_isRest()) { - + return $this->RestResponse->failResponse($id, $this->Tag->$model_name->validationErrors); } else { $this->Flash->error($message); $this->redirect($this->referer()); @@ -1110,6 +1121,7 @@ class TagsController extends AppController $relationships['custom'] = 'custom'; $relationships[null] = 'Unspecified'; ksort($relationships); + $this->set('title', __('Modify Tag Relationship')); $this->set( 'description', diff --git a/app/View/genericTemplates/select.ctp b/app/View/genericTemplates/select.ctp index 6f9acbd35..8d2ce9b11 100644 --- a/app/View/genericTemplates/select.ctp +++ b/app/View/genericTemplates/select.ctp @@ -12,7 +12,8 @@ echo $this->Form->create($model, ['id' => $randomNumber . 'Form']); echo $this->Form->input('relationship_type', [ 'type' => 'select', - 'options' => $options + 'options' => $options, + 'default' => $default ?? null, ]); echo $this->Form->end(); ?> From 5a643f4bbbc2720f1273ae04ebe0e5e35e6dd61c Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Fri, 14 Oct 2022 15:49:24 +0200 Subject: [PATCH 3/4] fix: [UI] Reload just tags part when modifying tag relationship --- app/Controller/TagsController.php | 1 + app/View/Elements/ajaxTags.ctp | 8 +++----- app/View/genericTemplates/select.ctp | 2 +- app/webroot/js/misp.js | 25 +++++++++++++++++++++++-- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/app/Controller/TagsController.php b/app/Controller/TagsController.php index 4c98b8892..d28164c7a 100644 --- a/app/Controller/TagsController.php +++ b/app/Controller/TagsController.php @@ -1136,6 +1136,7 @@ class TagsController extends AppController $this->set('options', $relationships); $this->set('default', $tagConnector[$model_name]['relationship_type']); $this->set('model', 'Tag'); + $this->set('onsubmit', 'modifyTagRelationship'); $this->set('field', 'relationship_type'); $this->layout = false; $this->render('/genericTemplates/select'); diff --git a/app/View/Elements/ajaxTags.ctp b/app/View/Elements/ajaxTags.ctp index 9d20ca9da..0c583a6ee 100644 --- a/app/View/Elements/ajaxTags.ctp +++ b/app/View/Elements/ajaxTags.ctp @@ -89,14 +89,12 @@ $span_relationship = ''; if ($full || ($fullLocal && $tag['Tag']['local'])) { $span_relationship = sprintf( - '', - 'black-white tag useCursorPointer noPrint', + '', + 'black-white tag useCursorPointer noPrint modal-open', __('Modify Tag Relationship'), - "button", - "0", __('Modify relationship for tag %s', h($tag['Tag']['name'])), sprintf( - 'openGenericModal(\'%s/tags/modifyTagRelationship/%s/%s\');', + '%s/tags/modifyTagRelationship/%s/%s', $baseurl, h($scope), h($tag['id']) diff --git a/app/View/genericTemplates/select.ctp b/app/View/genericTemplates/select.ctp index 8d2ce9b11..8eb256ccd 100644 --- a/app/View/genericTemplates/select.ctp +++ b/app/View/genericTemplates/select.ctp @@ -9,7 +9,7 @@

Form->create($model, ['id' => $randomNumber . 'Form']); + echo $this->Form->create($model, ['id' => $randomNumber . 'Form', 'onsubmit' => $onsubmit ?? null]); echo $this->Form->input('relationship_type', [ 'type' => 'select', 'options' => $options, diff --git a/app/webroot/js/misp.js b/app/webroot/js/misp.js index 7dbb74a09..e86510153 100644 --- a/app/webroot/js/misp.js +++ b/app/webroot/js/misp.js @@ -799,6 +799,27 @@ function refreshTagCollectionRow(tag_collection_id) { }); } +function modifyTagRelationship() { + var $form = $(this); + var action = $form.attr("action"); + + $.ajax({ + type: "post", + url: action, + data: $form.serialize(), + error: xhrFailCallback, + success: function () { + $('#genericModal').modal('hide'); + var id = action.split("/").pop(); + if ("/attribute/" in action) { + loadAttributeTags(id); + } else { + loadEventTags(id); + } + } + }); +} + function handleAjaxEditResponse($td, data, type, id, field) { var responseArray = data; if (type === 'Attribute') { @@ -1084,9 +1105,9 @@ function getSelectedTaxonomyNames() { function loadEventTags(id) { $.ajax({ - dataType:"html", + dataType: "html", cache: false, - success:function (data) { + success: function (data) { $(".eventTagContainer").html(data); }, url: baseurl + "/tags/showEventTag/" + id, From 3496eec83addaa544514ac952f29f2571f9bff7a Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Fri, 14 Oct 2022 16:08:50 +0200 Subject: [PATCH 4/4] fix: [UI] Undefined index attribute_tag_id --- app/Controller/TagsController.php | 10 +++++----- app/Model/Event.php | 15 ++++++++++++--- app/View/Elements/ajaxTags.ctp | 2 +- app/View/genericTemplates/select.ctp | 7 +++---- app/webroot/css/main.css | 4 ++++ app/webroot/js/misp.js | 24 ++++++++++++++++-------- 6 files changed, 41 insertions(+), 21 deletions(-) diff --git a/app/Controller/TagsController.php b/app/Controller/TagsController.php index d28164c7a..1138d2733 100644 --- a/app/Controller/TagsController.php +++ b/app/Controller/TagsController.php @@ -1074,7 +1074,7 @@ class TagsController extends AppController $tagConnector = $this->Tag->$model_name->find('first', [ 'conditions' => [$model_name . '.id' => $id], 'recursive' => -1, - 'contain' => 'Tag' + 'contain' => ['Tag'], ]); if (empty($tagConnector)) { throw new NotFoundException(__('Tag not found.')); @@ -1095,15 +1095,15 @@ class TagsController extends AppController $result = $this->Tag->$model_name->save($tagConnector, true, ['relationship_type']); if ($result) { $message = __('Relationship updated.'); - if ($this->_isRest()) { - return $this->RestResponse->successResponse($id, $message); + if ($this->_isRest() || $this->request->is('ajax')) { + return $this->RestResponse->successResponse($id, $message, ["{$scope}_id" => $tagConnector[$model_name]["{$scope}_id"]]); } else { $this->Flash->success($message); $this->redirect($this->referer()); } } else { $message = __('Relationship could not be updated.'); - if ($this->_isRest()) { + if ($this->_isRest() || $this->request->is('ajax')) { return $this->RestResponse->failResponse($id, $this->Tag->$model_name->validationErrors); } else { $this->Flash->error($message); @@ -1136,7 +1136,7 @@ class TagsController extends AppController $this->set('options', $relationships); $this->set('default', $tagConnector[$model_name]['relationship_type']); $this->set('model', 'Tag'); - $this->set('onsubmit', 'modifyTagRelationship'); + $this->set('onsubmit', 'modifyTagRelationship()'); $this->set('field', 'relationship_type'); $this->layout = false; $this->render('/genericTemplates/select'); diff --git a/app/Model/Event.php b/app/Model/Event.php index 0be9d9f8c..a0ebc2f5d 100755 --- a/app/Model/Event.php +++ b/app/Model/Event.php @@ -5951,7 +5951,15 @@ class Event extends AppModel return $attributes_added; } - public function massageTags($user, $data, $dataType = 'Event', $excludeGalaxy = false, $cullGalaxyTags = false) + /** + * @param array $user + * @param array $data + * @param string $dataType + * @param bool $excludeGalaxy + * @param bool $cullGalaxyTags + * @return array + */ + public function massageTags(array $user, array $data, $dataType = 'Event', $excludeGalaxy = false, $cullGalaxyTags = false) { $data['Galaxy'] = array(); @@ -5971,14 +5979,15 @@ class Event extends AppModel $cluster = $this->GalaxyCluster->getCluster($dataTag['Tag']['name'], $user); if ($cluster) { $found = false; - $cluster['GalaxyCluster']['local'] = isset($dataTag['local']) ? $dataTag['local'] : false; + $cluster['GalaxyCluster']['local'] = $dataTag['local'] ?? false; + $cluster['GalaxyCluster'][strtolower($dataType) . '_tag_id'] = $dataTag['id']; foreach ($data['Galaxy'] as $j => $galaxy) { if ($galaxy['id'] == $cluster['GalaxyCluster']['Galaxy']['id']) { $found = true; $temp = $cluster; unset($temp['GalaxyCluster']['Galaxy']); $data['Galaxy'][$j]['GalaxyCluster'][] = $temp['GalaxyCluster']; - continue; + break; } } if (!$found) { diff --git a/app/View/Elements/ajaxTags.ctp b/app/View/Elements/ajaxTags.ctp index 0c583a6ee..67949af49 100644 --- a/app/View/Elements/ajaxTags.ctp +++ b/app/View/Elements/ajaxTags.ctp @@ -90,7 +90,7 @@ if ($full || ($fullLocal && $tag['Tag']['local'])) { $span_relationship = sprintf( '', - 'black-white tag useCursorPointer noPrint modal-open', + 'black-white tag noPrint modal-open', __('Modify Tag Relationship'), __('Modify relationship for tag %s', h($tag['Tag']['name'])), sprintf( diff --git a/app/View/genericTemplates/select.ctp b/app/View/genericTemplates/select.ctp index 8eb256ccd..4ecd5b508 100644 --- a/app/View/genericTemplates/select.ctp +++ b/app/View/genericTemplates/select.ctp @@ -5,21 +5,20 @@

+ Form->create($model, ['onsubmit' => $onsubmit ?? null, 'style' => 'margin:0']) ?> + Form->end() ?> diff --git a/app/webroot/css/main.css b/app/webroot/css/main.css index 7cd87da3a..8f82c4e29 100644 --- a/app/webroot/css/main.css +++ b/app/webroot/css/main.css @@ -867,6 +867,10 @@ a.proposal_link_red:hover { color:white; } +a.black-white:hover { + color: white; +} + .tagFirstHalf { display: inline-block; padding: 2px 4px; diff --git a/app/webroot/js/misp.js b/app/webroot/js/misp.js index e86510153..21afd293a 100644 --- a/app/webroot/js/misp.js +++ b/app/webroot/js/misp.js @@ -800,7 +800,8 @@ function refreshTagCollectionRow(tag_collection_id) { } function modifyTagRelationship() { - var $form = $(this); + event.preventDefault(); + var $form = $(event.target); var action = $form.attr("action"); $.ajax({ @@ -808,16 +809,23 @@ function modifyTagRelationship() { url: action, data: $form.serialize(), error: xhrFailCallback, - success: function () { - $('#genericModal').modal('hide'); - var id = action.split("/").pop(); - if ("/attribute/" in action) { - loadAttributeTags(id); - } else { - loadEventTags(id); + success: function (data) { + if (data.saved) { + $('#genericModal').modal('hide'); + if ("attribute_id" in data.data) { + var attribute_id = data.data.attribute_id; + loadAttributeTags(attribute_id); + loadGalaxies(attribute_id, 'attribute'); + } else { + var event_id = data.data.event_id; + loadEventTags(event_id); + loadGalaxies(event_id, 'event'); + } } } }); + + return false; } function handleAjaxEditResponse($td, data, type, id, field) {