From 58e6190bf81620e342dc2f5518d9f67b6088a576 Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Fri, 23 Apr 2021 12:05:50 +0200 Subject: [PATCH 1/8] chg: [UI] Link to proposal limited view from proposal event index --- app/Controller/EventsController.php | 51 ++++++++++++------------ app/View/Events/proposal_event_index.ctp | 51 ++++++++++-------------- 2 files changed, 45 insertions(+), 57 deletions(-) diff --git a/app/Controller/EventsController.php b/app/Controller/EventsController.php index 6da960ff4..fd0e0ba73 100644 --- a/app/Controller/EventsController.php +++ b/app/Controller/EventsController.php @@ -3280,41 +3280,40 @@ class EventsController extends AppController public function proposalEventIndex() { $this->loadModel('ShadowAttribute'); - $this->ShadowAttribute->recursive = -1; $conditions = array('ShadowAttribute.deleted' => 0); if (!$this->_isSiteAdmin()) { $conditions[] = array('ShadowAttribute.event_org_id' => $this->Auth->user('org_id')); } - $result = $this->ShadowAttribute->find('all', array( - 'fields' => array('event_id'), - 'group' => array('event_id', 'id'), - 'conditions' => $conditions - )); + $result = $this->ShadowAttribute->find('column', [ + 'fields' => ['event_id'], + 'conditions' => $conditions, + 'unique' => true, + ]); $this->Event->recursive = -1; - $conditions = array(); - foreach ($result as $eventId) { - $conditions['OR'][] = array('Event.id =' => $eventId['ShadowAttribute']['event_id']); - } + if (empty($result)) { - $conditions['OR'][] = array('Event.id =' => -1); + $conditions = array('Event.id' => -1); + } else { + $conditions = array('Event.id' => $result); } $this->paginate = array( - 'fields' => array('Event.id', 'Event.org_id', 'Event.orgc_id', 'Event.publish_timestamp', 'Event.distribution', 'Event.info', 'Event.date', 'Event.published'), - 'conditions' => $conditions, - 'contain' => array( - 'User' => array( - 'fields' => array( - 'User.email' - )), - 'ShadowAttribute'=> array( - 'fields' => array( - 'ShadowAttribute.id', 'ShadowAttribute.org_id', 'ShadowAttribute.event_id' - ), - 'conditions' => array( - 'ShadowAttribute.deleted' => 0 - ), + 'fields' => array('Event.id', 'Event.org_id', 'Event.orgc_id', 'Event.publish_timestamp', 'Event.distribution', 'Event.info', 'Event.date', 'Event.published'), + 'conditions' => $conditions, + 'contain' => array( + 'User' => array( + 'fields' => array( + 'User.email' + )), + 'ShadowAttribute'=> array( + 'fields' => array( + 'ShadowAttribute.id', 'ShadowAttribute.org_id', 'ShadowAttribute.event_id' ), - )); + 'conditions' => array( + 'ShadowAttribute.deleted' => 0 + ), + ), + ) + ); $events = $this->paginate(); $orgIds = array(); foreach ($events as $k => $event) { diff --git a/app/View/Events/proposal_event_index.ctp b/app/View/Events/proposal_event_index.ctp index a8b983a9f..36e9cb6c1 100755 --- a/app/View/Events/proposal_event_index.ctp +++ b/app/View/Events/proposal_event_index.ctp @@ -1,5 +1,5 @@
-

+

-element('/genericElements/SideMenu/side_menu', array('menuList' => 'event-collection', 'menuItem' => 'viewProposalIndex')); +element('/genericElements/SideMenu/side_menu', array('menuList' => 'event-collection', 'menuItem' => 'viewProposalIndex')); From 178d10b7097916dbead9bd06638a7fec371a3e96 Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Thu, 29 Apr 2021 12:18:48 +0200 Subject: [PATCH 2/8] fix: [db_schema] Update to version 68 --- db_schema.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/db_schema.json b/db_schema.json index 2ab2ffe0c..c8ff7461a 100644 --- a/db_schema.json +++ b/db_schema.json @@ -890,6 +890,17 @@ "column_default": null, "extra": "" }, + { + "column_name": "comment", + "is_nullable": "NO", + "data_type": "text", + "character_maximum_length": "65535", + "numeric_precision": null, + "collation_name": "utf8mb4_unicode_ci", + "column_type": "text", + "column_default": null, + "extra": "" + }, { "column_name": "from_json", "is_nullable": "YES", @@ -7986,5 +7997,5 @@ "id": true } }, - "db_version": "67" + "db_version": "68" } From f894109b265a65ea339f6045d87e984728282f1a Mon Sep 17 00:00:00 2001 From: mokaddem Date: Thu, 29 Apr 2021 13:29:59 +0200 Subject: [PATCH 3/8] fix: [files:defaut_feeds] Added trailing slash Fix #7022 --- app/files/feed-metadata/defaults.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/files/feed-metadata/defaults.json b/app/files/feed-metadata/defaults.json index 4c16df1e4..89a16b8ef 100644 --- a/app/files/feed-metadata/defaults.json +++ b/app/files/feed-metadata/defaults.json @@ -3,7 +3,7 @@ "Feed": { "name": "CIRCL OSINT Feed", "provider": "CIRCL", - "url": "https://www.circl.lu/doc/misp/feed-osint", + "url": "https://www.circl.lu/doc/misp/feed-osint/", "rules": "{\"tags\":{\"OR\":[],\"NOT\":[]},\"orgs\":{\"OR\":[],\"NOT\":[]}}", "enabled": true, "distribution": "3", From 475cd2563d561dd0d30f0dbf8f10aa3110c1843e Mon Sep 17 00:00:00 2001 From: mokaddem Date: Fri, 30 Apr 2021 10:06:49 +0200 Subject: [PATCH 4/8] new: [event:alert] Re-publishing ban feature based on configurable threshold --- app/Model/Event.php | 62 ++++++++++++++++++++++++++++++++++++++++++++ app/Model/Server.php | 18 +++++++++++++ 2 files changed, 80 insertions(+) diff --git a/app/Model/Event.php b/app/Model/Event.php index a4d0fe734..50212b1a4 100755 --- a/app/Model/Event.php +++ b/app/Model/Event.php @@ -3154,6 +3154,21 @@ class Event extends AppModel )); return true; } + $banStatus = $this->getEventRepublishBanStatus($id); + if ($banStatus['active']) { + $this->Log = ClassRegistry::init('Log'); + $this->Log->create(); + $this->Log->save(array( + 'org' => 'SYSTEM', + 'model' => 'Event', + 'model_id' => $id, + 'email' => $user['email'], + 'action' => 'publish', + 'title' => __('E-mail alerts not sent out during publishing'), + 'change' => $banStatus['message'], + )); + return !$banStatus['error']; + } if (Configure::read('MISP.background_jobs')) { $job = ClassRegistry::init('Job'); $job->create(); @@ -7304,4 +7319,51 @@ class Event extends AppModel } return []; } + + public function getEventRepublishBanStatus($eventID) + { + $banStatus = [ + 'error' => false, + 'active' => false, + 'message' => __('Event publish is not banned') + ]; + if (Configure::read('MISP.event_alert_republish_ban')) { + $event = $this->find('first', array( + 'conditions' => array('Event.id' => $eventID), + 'recursive' => -1, + 'fields' => array('Event.uuid') + )); + if (empty($event)) { + $banStatus['error'] = true; + $banStatus['active'] = true; + $banStatus['message'] = __('Event not found'); + return $banStatus; + } + $banThresholdMinutes = intval(Configure::read('MISP.event_alert_republish_ban_threshold')); + $banThresholdSeconds = 60 * $banThresholdMinutes; + $redis = $this->setupRedis(); + if ($redis === false) { + $banStatus['error'] = true; + $banStatus['active'] = true; + $banStatus['message'] = __('Reason: Could not reach redis to chech republish ban.'); + return $banStatus; + } + $redisKey = "misp:event_alert_republish_ban:{$event['Event']['uuid']}"; + $banLiftTimestamp = $redis->get($redisKey); + if (!empty($banLiftTimestamp)) { + $remainingMinutes = (intval($banLiftTimestamp) - time()) / 60; + $banStatus['active'] = true; + $banStatus['message'] = __('Reason: Event is banned from publishing. Ban will be lifted in %smin %ssec.', floor($remainingMinutes), $remainingMinutes % 60); + return $banStatus; + } else { + $redis->multi(Redis::PIPELINE) + ->set($redisKey, time() + $banThresholdSeconds) + ->expire($redisKey, $banThresholdSeconds) + ->exec(); + return $banStatus; + } + } + $banStatus['message'] = __('Republishing ban setting is not enabled'); + return $banStatus; + } } diff --git a/app/Model/Server.php b/app/Model/Server.php index 7d1cf8c0a..e4668e267 100644 --- a/app/Model/Server.php +++ b/app/Model/Server.php @@ -5331,6 +5331,24 @@ class Server extends AppModel 'type' => 'string', 'null' => false, ), + 'event_alert_republish_ban' => array( + 'level' => 1, + 'description' => __('Enable this setting to start blocking alert e-mails for events that have already been publish since a specified amount of time. This threshold is defined by MISP.event_alert_republish_ban_threshold'), + 'value' => false, + 'errorMessage' => '', + 'test' => 'testBool', + 'type' => 'boolean', + 'null' => false, + ), + 'event_alert_republish_ban_threshold' => array( + 'level' => 1, + 'description' => __('If the MISP.event_alert_republish_ban setting is set, this setting will control how long no alerting by email will be done. Expected format: integer, in minutes'), + 'value' => 5, + 'errorMessage' => '', + 'test' => 'testForNumeric', + 'type' => 'numeric', + 'null' => false, + ), 'org_alert_threshold' => array( 'level' => 1, 'description' => __('Set a value to limit the number of email alerts that events can generate per creator organisation (for example, if an organisation pushes out 2000 events in one shot, only alert on the first 20).'), From 132f4850ca825f49fede22be5cd824deccf34bc6 Mon Sep 17 00:00:00 2001 From: mokaddem Date: Fri, 30 Apr 2021 10:12:42 +0200 Subject: [PATCH 5/8] fix: [server:settings] Typo --- app/Model/Server.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Model/Server.php b/app/Model/Server.php index e4668e267..760ebe5ba 100644 --- a/app/Model/Server.php +++ b/app/Model/Server.php @@ -5333,7 +5333,7 @@ class Server extends AppModel ), 'event_alert_republish_ban' => array( 'level' => 1, - 'description' => __('Enable this setting to start blocking alert e-mails for events that have already been publish since a specified amount of time. This threshold is defined by MISP.event_alert_republish_ban_threshold'), + 'description' => __('Enable this setting to start blocking alert e-mails for events that have already been published since a specified amount of time. This threshold is defined by MISP.event_alert_republish_ban_threshold'), 'value' => false, 'errorMessage' => '', 'test' => 'testBool', From 80792c0a15c33615f36696dc2389a50dd8061a64 Mon Sep 17 00:00:00 2001 From: mokaddem Date: Fri, 30 Apr 2021 10:19:47 +0200 Subject: [PATCH 6/8] chg: [event:getEventRepublishBanStatus] Improved wording --- app/Model/Event.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Model/Event.php b/app/Model/Event.php index 50212b1a4..5a2416da5 100755 --- a/app/Model/Event.php +++ b/app/Model/Event.php @@ -7345,7 +7345,7 @@ class Event extends AppModel if ($redis === false) { $banStatus['error'] = true; $banStatus['active'] = true; - $banStatus['message'] = __('Reason: Could not reach redis to chech republish ban.'); + $banStatus['message'] = __('Reason: Could not reach redis to chech republish emailing ban status.'); return $banStatus; } $redisKey = "misp:event_alert_republish_ban:{$event['Event']['uuid']}"; @@ -7353,7 +7353,7 @@ class Event extends AppModel if (!empty($banLiftTimestamp)) { $remainingMinutes = (intval($banLiftTimestamp) - time()) / 60; $banStatus['active'] = true; - $banStatus['message'] = __('Reason: Event is banned from publishing. Ban will be lifted in %smin %ssec.', floor($remainingMinutes), $remainingMinutes % 60); + $banStatus['message'] = __('Reason: Event is banned from sending out emails. Ban will be lifted in %smin %ssec.', floor($remainingMinutes), $remainingMinutes % 60); return $banStatus; } else { $redis->multi(Redis::PIPELINE) @@ -7363,7 +7363,7 @@ class Event extends AppModel return $banStatus; } } - $banStatus['message'] = __('Republishing ban setting is not enabled'); + $banStatus['message'] = __('Emailing republishing ban setting is not enabled'); return $banStatus; } } From c9227bc8ded83b99f18d77fcb31eb24eaded614e Mon Sep 17 00:00:00 2001 From: mokaddem Date: Fri, 30 Apr 2021 15:00:08 +0200 Subject: [PATCH 7/8] chg: [event:alert] Added option to refresh to ban --- app/Model/Event.php | 10 +++++++++- app/Model/Server.php | 9 +++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/app/Model/Event.php b/app/Model/Event.php index 5a2416da5..17198dee4 100755 --- a/app/Model/Event.php +++ b/app/Model/Event.php @@ -7353,7 +7353,15 @@ class Event extends AppModel if (!empty($banLiftTimestamp)) { $remainingMinutes = (intval($banLiftTimestamp) - time()) / 60; $banStatus['active'] = true; - $banStatus['message'] = __('Reason: Event is banned from sending out emails. Ban will be lifted in %smin %ssec.', floor($remainingMinutes), $remainingMinutes % 60); + if (Configure::read('MISP.event_alert_republish_ban_refresh_on_retry')) { + $redis->multi(Redis::PIPELINE) + ->set($redisKey, time() + $banThresholdSeconds) + ->expire($redisKey, $banThresholdSeconds) + ->exec(); + $banStatus['message'] = __('Reason: Event is banned from sending out emails. Ban has been refreshed and will be lifted in %smin', $banThresholdMinutes); + } else { + $banStatus['message'] = __('Reason: Event is banned from sending out emails. Ban will be lifted in %smin %ssec.', floor($remainingMinutes), $remainingMinutes % 60); + } return $banStatus; } else { $redis->multi(Redis::PIPELINE) diff --git a/app/Model/Server.php b/app/Model/Server.php index 760ebe5ba..69a9b46b2 100644 --- a/app/Model/Server.php +++ b/app/Model/Server.php @@ -5349,6 +5349,15 @@ class Server extends AppModel 'type' => 'numeric', 'null' => false, ), + 'event_alert_republish_ban_refresh_on_retry' => array( + 'level' => 1, + 'description' => __('If the MISP.event_alert_republish_ban setting is set, this setting will control if a ban time should be reset if emails are tried to be sent during the ban.'), + 'value' => false, + 'errorMessage' => '', + 'test' => 'testBool', + 'type' => 'boolean', + 'null' => false, + ), 'org_alert_threshold' => array( 'level' => 1, 'description' => __('Set a value to limit the number of email alerts that events can generate per creator organisation (for example, if an organisation pushes out 2000 events in one shot, only alert on the first 20).'), From 122f9cddd70b5b0284880eb046561fc6f7dc9748 Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Fri, 30 Apr 2021 16:04:33 +0200 Subject: [PATCH 8/8] fix: [UI] Warning message for event modification warning --- app/Controller/EventsController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Controller/EventsController.php b/app/Controller/EventsController.php index 3cc506c16..b48aacfb2 100644 --- a/app/Controller/EventsController.php +++ b/app/Controller/EventsController.php @@ -5455,10 +5455,10 @@ class EventsController extends AppController $editors = array_unique($editors); if ($event['Event']['timestamp'] > $timestamp && empty($editors)) { - $message = __('Warning: This event view is outdated. Please reload page to see latest changes.'); + $message = __('Warning: This event view is outdated. Please reload page to see latest changes.'); $this->set('class', 'alert'); } else if ($event['Event']['timestamp'] > $timestamp) { - $message = __('Warning: This event view is outdated, because is currently being edited by: %s. Please reload page to see latest changes.', h(implode(', ', $editors))); + $message = __('Warning: This event view is outdated, because is currently being edited by: %s. Please reload page to see latest changes.', h(implode(', ', $editors))); $this->set('class', 'alert'); } else if (empty($editors)) { return new CakeResponse(['status' => 204]);