From 14a678caf5bfdc25cae125f2ca96182797ea3319 Mon Sep 17 00:00:00 2001 From: Nabil Adouani Date: Thu, 4 Mar 2021 22:15:58 +0100 Subject: [PATCH] #1815 Add a platform status page --- frontend/app/index.html | 2 + frontend/app/scripts/app.js | 15 ++ .../admin/platform/PlatformStatusCtrl.js | 78 +++++++++ .../app/scripts/services/api/PlatformSrv.js | 23 +++ frontend/app/styles/flex-table.css | 95 +++++++++- .../views/components/header.component.html | 11 +- .../views/partials/admin/platform/status.html | 165 ++++++++++++++++++ 7 files changed, 383 insertions(+), 6 deletions(-) create mode 100644 frontend/app/scripts/controllers/admin/platform/PlatformStatusCtrl.js create mode 100644 frontend/app/scripts/services/api/PlatformSrv.js create mode 100644 frontend/app/views/partials/admin/platform/status.html diff --git a/frontend/app/index.html b/frontend/app/index.html index a918dc80a9..a69b9fbf07 100644 --- a/frontend/app/index.html +++ b/frontend/app/index.html @@ -170,6 +170,7 @@ + @@ -306,6 +307,7 @@ + diff --git a/frontend/app/scripts/app.js b/frontend/app/scripts/app.js index b9225fd461..0f6ebe764c 100644 --- a/frontend/app/scripts/app.js +++ b/frontend/app/scripts/app.js @@ -205,6 +205,21 @@ angular.module('thehive', [ url: 'administration', template: '' }) + .state('app.administration.platform', { + url: '/platform', + templateUrl: 'views/partials/admin/platform/status.html', + controller: 'PlatformStatusCtrl', + controllerAs: '$vm', + title: 'Platform administration', + resolve: { + appConfig: function(VersionSrv) { + return VersionSrv.get(); + } + }, + guard: { + permissions: ['managePlatform'] + } + }) .state('app.administration.profiles', { url: '/profiles', templateUrl: 'views/partials/admin/profile/list.html', diff --git a/frontend/app/scripts/controllers/admin/platform/PlatformStatusCtrl.js b/frontend/app/scripts/controllers/admin/platform/PlatformStatusCtrl.js new file mode 100644 index 0000000000..b2e799213e --- /dev/null +++ b/frontend/app/scripts/controllers/admin/platform/PlatformStatusCtrl.js @@ -0,0 +1,78 @@ +(function() { + 'use strict'; + + angular.module('theHiveControllers').controller('PlatformStatusCtrl', function(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; + }); + } + + 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 + }; + + // 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) { + PlatformSrv.runReindex(indexName) + .then(function(response) { + NotificationSrv.log('Reindexing of ' + indexName + ' started sucessfully', 'success'); + }); + }; + + this.checkControl = function(checkName) { + PlatformSrv.runCheck(checkName) + .then(function(response) { + NotificationSrv.log('Integrity check of ' + checkName + ' started sucessfully', 'success'); + }); + } + + }); +})(); diff --git a/frontend/app/scripts/services/api/PlatformSrv.js b/frontend/app/scripts/services/api/PlatformSrv.js new file mode 100644 index 0000000000..bd3451ec11 --- /dev/null +++ b/frontend/app/scripts/services/api/PlatformSrv.js @@ -0,0 +1,23 @@ +(function() { + 'use strict'; + angular.module('theHiveServices') + .service('PlatformSrv', function($http) { + + 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.getCheckStats = function() { + return $http.get('./api/v1/admin/check/stats') + } + + this.runCheck = function(checkName) { + return $http.get('./api/v1/admin/check/'+checkName+'/trigger'); + } + + }); +})(); diff --git a/frontend/app/styles/flex-table.css b/frontend/app/styles/flex-table.css index 441a0c5967..bd3d83110a 100644 --- a/frontend/app/styles/flex-table.css +++ b/frontend/app/styles/flex-table.css @@ -1,4 +1,4 @@ -div.flex-header { +/* div.flex-header { background-color: #fff; border-bottom: 2px solid #ecf0f5; font-size: 16px; @@ -114,4 +114,97 @@ div.flex-header > div.flex-col.flex-icon { div.flex-row > div.flex-col.flex-icon i, div.flex-header > div.flex-col.flex-icon i { margin-right: 5px; +} */ + +div.flex-header { + background-color: #fff; + border-bottom: 2px solid #ecf0f5; + font-size: 16px; + padding-top: 8px; + padding-bottom: 8px; +} +div.flex-row:hover { + border: 1px dotted #3c8dbc !important; +} +div.flex-row, div.flex-header { + display: flex; + justify-content: space-between; + align-items: stretch; +} +div.flex-row:nth-child(odd), div.flex-header:nth-child(odd) { + background: #f9f9f9; + border: 1px dotted #f9f9f9; +} +div.flex-row:nth-child(even), div.flex-header:nth-child(even) { + background: #ecf0f5; + border: 1px dotted #ecf0f5; +} +div.flex-row > div.flex-col, div.flex-header > div.flex-col { + margin: 0 5px; + padding: 4px; +} +div.flex-row > div.flex-col .label.label-lg, div.flex-header > div.flex-col .label.label-lg { + font-size: 13px; + font-weight: normal; + line-height: 1; +} +div.flex-row > div.flex-col > *, div.flex-header > div.flex-col > * { + flex: 1; +} +div.flex-row > div.flex-col > span.label, div.flex-header > div.flex-col > span.label { + flex: none; +} +div.flex-row > div.flex-col.vertical, div.flex-header > div.flex-col.vertical { + display: flex; + align-items: center; +} +div.flex-row > div.flex-col.vertical.centered, div.flex-header > div.flex-col.vertical.centered { + justify-content: center; +} +div.flex-row > div.flex-col:first-child, div.flex-header > div.flex-col:first-child { + margin-left: 0; +} +div.flex-row > div.flex-col:last-child, div.flex-header > div.flex-col:last-child { + margin-right: 0; +} +div.flex-row > div.flex-col.flex-1, div.flex-header > div.flex-col.flex-1 { + flex: 1; +} +div.flex-row > div.flex-col.flex-2, div.flex-header > div.flex-col.flex-2 { + flex: 2; +} +div.flex-row > div.flex-col.flex-3, div.flex-header > div.flex-col.flex-3 { + flex: 3; +} +div.flex-row > div.flex-col.flex-4, div.flex-header > div.flex-col.flex-4 { + flex: 4; +} +div.flex-row > div.flex-col.flex-5, div.flex-header > div.flex-col.flex-5 { + flex: 5; +} +div.flex-row > div.flex-col.flex-w-80, div.flex-header > div.flex-col.flex-w-80 { + width: 80px; +} +div.flex-row > div.flex-col.flex-w-100, div.flex-header > div.flex-col.flex-w-100 { + width: 100px; +} +div.flex-row > div.flex-col.flex-w-120, div.flex-header > div.flex-col.flex-w-120 { + width: 120px; +} +div.flex-row > div.flex-col.flex-w-150, div.flex-header > div.flex-col.flex-w-150 { + width: 150px; +} +div.flex-row > div.flex-col.flex-w-200, div.flex-header > div.flex-col.flex-w-200 { + width: 200px; +} +div.flex-row > div.flex-col.flex-icon, div.flex-header > div.flex-col.flex-icon { + padding-left: 10px; + padding-right: 10px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; +} +div.flex-row > div.flex-col.flex-icon i, div.flex-header > div.flex-col.flex-icon i { + margin-right: 5px; } diff --git a/frontend/app/views/components/header.component.html b/frontend/app/views/components/header.component.html index fed26cd57f..2b99662bee 100644 --- a/frontend/app/views/components/header.component.html +++ b/frontend/app/views/components/header.component.html @@ -123,12 +123,13 @@ ATT&CK Patterns - + diff --git a/frontend/app/views/partials/admin/platform/status.html b/frontend/app/views/partials/admin/platform/status.html new file mode 100644 index 0000000000..f433fe64c1 --- /dev/null +++ b/frontend/app/views/partials/admin/platform/status.html @@ -0,0 +1,165 @@ +
+
+
+
+

Platform Status

+
+ +
+
+
+ +
+
+ +

Index status Reload

+
Loading index status...
+
+
+
Status
+
Index name
+
Mixed count
+
Composite
+
+
+
+
+
+ {{data.status}} +
+
+

+ {{indexName}} +

+
+ +
+ {{data.mixedCount}} +
+
+ {{data.compositeCount}} +
+ +
+
+
+ + +

Integrity control status Reload

+
Loading integrity control stats...
+
+
+
Status
+
Control name
+
Global Stats
+
Duplicate Stats
+
+
+
+
+
+ {{data.needCheck ? 'Yes': + 'No'}} +
+
+

+ {{checkName}} +

+
+ +
+
+
+ Iterations: + {{data.globalStats.global.iterations}} + Duplicate: + {{data.globalStats.global.duplicate}} + Duration: + {{data.globalStats.global.duration}} +
+
+
+
+ Last execution: {{data.globalStats.lastDate | shortDate}} +
+
+
+ +
+
+
+ Iterations: + {{data.duplicateStats.global.iterations}} + Duplicate: + {{data.duplicateStats.global.duplicate}} + Duration: + {{data.duplicateStats.global.duration}} +
+
+
+
+ Last execution: {{data.duplicateStats.lastDate | shortDate}} +
+
+
+ + +
+
+
+ +

Database Schema status

+
+
+
Status
+
Schema name
+
Current Version
+
Expected Version
+
+
+
+
+ {{schema.error === null ? 'OK' : + 'Error'}} +
+
+

+ {{schema.name}} +

+
+ {{schema.error}} +
+
+ +
+ {{schema.currentVersion}} +
+
+ {{schema.expectedVersion}} +
+
+
+
+
+
+
+