diff --git a/CHANGELOG.md b/CHANGELOG.md index a1d82dbef3..0a8caaba86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Change Log +## [4.1.9](https://github.com/TheHive-Project/TheHive/milestone/78) (2021-07-23) + +**Implemented enhancements:** + +- [Enhancement] Add button for index rebuilding [\#2144](https://github.com/TheHive-Project/TheHive/issues/2144) + +**Fixed bugs:** + +- [Bug] MISP sync delete existing observables when updating existing Alert [\#2134](https://github.com/TheHive-Project/TheHive/issues/2134) +- [Bug] Livestream emptied of audit logs after TheHive reboot [\#2135](https://github.com/TheHive-Project/TheHive/issues/2135) +- [Bug] AddTagToCase operation does not work [\#2136](https://github.com/TheHive-Project/TheHive/issues/2136) + ## [4.1.8](https://github.com/TheHive-Project/TheHive/milestone/77) (2021-07-19) **Implemented enhancements:** diff --git a/build.sbt b/build.sbt index 0bf7efbc1c..6ddcfd53cc 100644 --- a/build.sbt +++ b/build.sbt @@ -2,7 +2,7 @@ import Dependencies._ import com.typesafe.sbt.packager.Keys.bashScriptDefines import org.thp.ghcl.Milestone -val thehiveVersion = "4.1.8-1" +val thehiveVersion = "4.1.9-1" val scala212 = "2.12.13" val scala213 = "2.13.1" val supportedScalaVersions = List(scala212, scala213) diff --git a/cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/services/ActionSrv.scala b/cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/services/ActionSrv.scala index 093b9686d6..1ee8097ba2 100644 --- a/cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/services/ActionSrv.scala +++ b/cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/services/ActionSrv.scala @@ -195,13 +195,13 @@ class ActionSrv @Inject() ( */ def relatedCase(id: EntityId)(implicit graph: Graph): Option[Case with Entity] = for { - richAction <- startTraversal.getByIds(id).richAction.getOrFail("Action").toOption + richAction <- startTraversal.getByIds(id).richAction.headOption relatedCase <- entityHelper.parentCase(richAction.context) } yield relatedCase def relatedTask(id: EntityId)(implicit graph: Graph): Option[Task with Entity] = for { - richAction <- startTraversal.getByIds(id).richAction.getOrFail("Action").toOption + richAction <- startTraversal.getByIds(id).richAction.headOption relatedTask <- entityHelper.parentTask(richAction.context) } yield relatedTask diff --git a/cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/services/EntityHelper.scala b/cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/services/EntityHelper.scala index af6bc89409..dcc31f761c 100644 --- a/cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/services/EntityHelper.scala +++ b/cortex/connector/src/main/scala/org/thp/thehive/connector/cortex/services/EntityHelper.scala @@ -60,11 +60,12 @@ class EntityHelper @Inject() ( */ def parentCase(entity: Entity)(implicit graph: Graph): Option[Case with Entity] = entity._label match { - case "Task" => taskSrv.get(entity).`case`.headOption - case "Case" => caseSrv.get(entity).headOption - case "Log" => logSrv.get(entity).`case`.headOption - case "Alert" => None - case _ => None + case "Task" => taskSrv.get(entity).`case`.headOption + case "Case" => caseSrv.get(entity).headOption + case "Observable" => observableSrv.get(entity).`case`.headOption + case "Log" => logSrv.get(entity).`case`.headOption + case "Alert" => None + case _ => None } /** diff --git a/frontend/app/scripts/controllers/admin/platform/PlatformStatusCtrl.js b/frontend/app/scripts/controllers/admin/platform/PlatformStatusCtrl.js index 3718916b33..a0ed8a01b8 100644 --- a/frontend/app/scripts/controllers/admin/platform/PlatformStatusCtrl.js +++ b/frontend/app/scripts/controllers/admin/platform/PlatformStatusCtrl.js @@ -1,107 +1,131 @@ -(function() { +(function () { 'use strict'; - angular.module('theHiveControllers').controller('PlatformStatusCtrl', function(ModalSrv, PlatformSrv, NotificationSrv, appConfig) { - var self = this; + angular.module('theHiveControllers').controller('PlatformStatusCtrl', function (ModalSrv, PlatformSrv, NotificationSrv, appConfig) { + var self = this; - self.appConfig = appConfig; - self.indexStatus = {}; - self.checkStats = {}; - - self.loading = { - index: false, - check: false - } - - this.loadIndexStatus = function() { - self.indexStatus = {}; - self.loading.index = true; - - PlatformSrv.getIndexStatus() - .then(function(response) { - self.indexStatus = response.data; - self.loading.index = false; - }); - } + self.appConfig = appConfig; + self.indexStatus = {}; + self.checkStats = {}; - this.loadCheckStats = function() { - self.loading.check = true; + self.loading = { + index: false, + check: false + } - PlatformSrv.getCheckStats() - .then(function(response) { - self.checkStats = response.data; - self.loading.check = false; - }) - } + this.loadIndexStatus = function () { + self.indexStatus = {}; + self.loading.index = true; - this.$onInit = function() { - self.loadIndexStatus(); - self.loadCheckStats(); + PlatformSrv.getIndexStatus() + .then(function (response) { + self.indexStatus = response.data; + self.loading.index = false; + }); + } + + this.loadCheckStats = function () { + self.loading.check = true; + + PlatformSrv.getCheckStats() + .then(function (response) { + self.checkStats = response.data; + self.loading.check = false; + }) + } + + this.$onInit = function () { + self.loadIndexStatus(); + self.loadCheckStats(); + }; + + this.exportReport = function () { + var date = new moment().format('YYYYMMDD-HH:mmZ'); + var fileName = 'Platform-Status-Report-' + date + '.json'; + + var content = { + indexStatus: self.indexStatus, + checkStatus: self.checkStats, + schemaStatus: self.appConfig.schemaStatus }; - this.exportReport = function() { - var date = new moment().format('YYYYMMDD-HH:mmZ'); - var fileName = 'Platform-Status-Report-'+date+'.json'; - - var content = { - indexStatus: self.indexStatus, - checkStatus: self.checkStats, - schemaStatus: self.appConfig.schemaStatus - }; - - // Create a blob of the data - var fileToSave = new Blob([JSON.stringify(content)], { - type: 'application/json', - name: fileName + // Create a blob of the data + var fileToSave = new Blob([JSON.stringify(content)], { + type: 'application/json', + name: fileName + }); + + // Save the file + saveAs(fileToSave, fileName); + } + + this.reindex = function (indexName) { + var modalInstance = ModalSrv.confirm( + 'Reindex', + 'Are you sure you want to trigger ' + indexName + ' data reindex', { + okText: 'Yes, reindex it' + } + ); + + modalInstance.result + .then(function () { + PlatformSrv.runReindex(indexName); + }) + .then(function (/*response*/) { + NotificationSrv.success('Reindexing of ' + indexName + ' data started sucessfully'); + }) + .catch(function (err) { + if (!_.isString(err)) { + NotificationSrv.error('Platform status', err.data, err.status); + } }); - - // Save the file - saveAs(fileToSave, fileName); + }; + + this.rebuildIndex = function (indexName) { + var modalInstance = ModalSrv.confirm( + 'Drop & Rebuild Index', + 'Are you sure you want to delete and rebuild ' + indexName + ' data reindex. ' + + 'This operation will drop your existing data index and create a new one.', { + okText: 'Yes, rebuild it', + flavor: 'danger' } - - this.reindex = function(indexName) { - var modalInstance = ModalSrv.confirm( - 'Reindex', - 'Are you sure you want to trigger ' + indexName + ' data reindex', { - okText: 'Yes, reindex it' + ); + + modalInstance.result + .then(function () { + PlatformSrv.runRebuildIndex(indexName); + }) + .then(function (/*response*/) { + NotificationSrv.success('Rebuild of ' + indexName + ' data started sucessfully'); + }) + .catch(function (err) { + if (!_.isString(err)) { + NotificationSrv.error('Platform status', err.data, err.status); } - ); - - modalInstance.result - .then(function() { - PlatformSrv.runReindex(indexName); - }) - .then(function(/*response*/) { - NotificationSrv.success('Reindexing of ' + indexName + ' data started sucessfully'); - }) - .catch(function(err) { - if (!_.isString(err)) { - NotificationSrv.error('Platform status', err.data, err.status); - } - }); - }; + }); + }; - this.checkControl = function(checkName) { - var modalInstance = ModalSrv.confirm( - 'Data health check', - 'Are you sure you want to trigger ' + checkName + ' health check', { - okText: 'Yes, trigger it' - } - ); - - modalInstance.result - .then(function() { - PlatformSrv.runCheck(checkName); - }) - .then(function(/*response*/) { - NotificationSrv.success('Data health check of ' + checkName + ' started sucessfully'); - }) - .catch(function(err) { - if (!_.isString(err)) { - NotificationSrv.error('Platform status', err.data, err.status); - } - }); + this.checkControl = function (checkName) { + var modalInstance = ModalSrv.confirm( + 'Data health check', + 'Are you sure you want to trigger ' + checkName + ' health check', { + okText: 'Yes, trigger it' } + ); + + modalInstance.result + .then(function () { + PlatformSrv.runCheck(checkName); + }) + .then(function (/*response*/) { + NotificationSrv.success('Data health check of ' + checkName + ' started sucessfully'); + }) + .catch(function (err) { + if (!_.isString(err)) { + NotificationSrv.error('Platform status', err.data, err.status); + } + }); + } - }); + }); })(); diff --git a/frontend/app/scripts/services/api/PlatformSrv.js b/frontend/app/scripts/services/api/PlatformSrv.js index bd3451ec11..2aa910b1fc 100644 --- a/frontend/app/scripts/services/api/PlatformSrv.js +++ b/frontend/app/scripts/services/api/PlatformSrv.js @@ -1,22 +1,26 @@ -(function() { +(function () { 'use strict'; angular.module('theHiveServices') - .service('PlatformSrv', function($http) { + .service('PlatformSrv', function ($http) { - this.getIndexStatus = function() { + this.getIndexStatus = function () { return $http.get('./api/v1/admin/index/status') } - this.runReindex = function(indexName) { - return $http.get('./api/v1/admin/index/'+indexName+'/reindex'); + this.runReindex = function (indexName) { + return $http.post('./api/v1/admin/index/' + indexName + '/reindex'); } - this.getCheckStats = function() { + this.runRebuildIndex = function (indexName) { + return $http.post('./api/v1/admin/index/' + indexName + '/rebuild'); + } + + this.getCheckStats = function () { return $http.get('./api/v1/admin/check/stats') } - this.runCheck = function(checkName) { - return $http.get('./api/v1/admin/check/'+checkName+'/trigger'); + this.runCheck = function (checkName) { + return $http.get('./api/v1/admin/check/' + checkName + '/trigger'); } }); diff --git a/frontend/app/views/partials/admin/platform/status.html b/frontend/app/views/partials/admin/platform/status.html index 12b4c23851..6a25e82efd 100644 --- a/frontend/app/views/partials/admin/platform/status.html +++ b/frontend/app/views/partials/admin/platform/status.html @@ -55,16 +55,22 @@