From 7625676ca2136a6243ca677f53faa82f57487845 Mon Sep 17 00:00:00 2001 From: Nabil Adouani Date: Wed, 6 Oct 2021 07:55:53 +0200 Subject: [PATCH] #2125 Allow observable datatype update in bullk edit modal --- .../controllers/case/CaseObservablesCtrl.js | 8 +- .../controllers/case/ObservableUpdateCtrl.js | 142 +++++++++++------- .../observables/observable.update.html | 87 +++++++---- 3 files changed, 156 insertions(+), 81 deletions(-) diff --git a/frontend/app/scripts/controllers/case/CaseObservablesCtrl.js b/frontend/app/scripts/controllers/case/CaseObservablesCtrl.js index 95d3b631fb..c86a5fe39f 100644 --- a/frontend/app/scripts/controllers/case/CaseObservablesCtrl.js +++ b/frontend/app/scripts/controllers/case/CaseObservablesCtrl.js @@ -1,7 +1,7 @@ (function () { 'use strict'; angular.module('theHiveControllers').controller('CaseObservablesCtrl', - function ($scope, $q, $state, $stateParams, $filter, $uibModal, SecuritySrv, ModalUtilsSrv, FilteringSrv, StreamSrv, CaseTabsSrv, PaginatedQuerySrv, CaseArtifactSrv, NotificationSrv, AnalyzerSrv, CortexSrv, VersionSrv) { + function ($scope, $q, $state, $stateParams, $filter, $uibModal, SecuritySrv, ModalUtilsSrv, FilteringSrv, StreamSrv, CaseTabsSrv, PaginatedQuerySrv, ObservableTypeSrv, CaseArtifactSrv, NotificationSrv, AnalyzerSrv, CortexSrv, VersionSrv) { CaseTabsSrv.activateTab($state.current.data.tab); @@ -241,6 +241,12 @@ resolve: { selection: function () { return $scope.selection.artifacts; + }, + dataTypes: function () { + return ObservableTypeSrv.list() + .then(function (response) { + return response.data; + }); } } }); diff --git a/frontend/app/scripts/controllers/case/ObservableUpdateCtrl.js b/frontend/app/scripts/controllers/case/ObservableUpdateCtrl.js index f596796264..04691a77aa 100644 --- a/frontend/app/scripts/controllers/case/ObservableUpdateCtrl.js +++ b/frontend/app/scripts/controllers/case/ObservableUpdateCtrl.js @@ -1,34 +1,49 @@ -(function() { +(function () { 'use strict'; angular.module('theHiveControllers').controller('ObservableUpdateCtrl', - function($scope, $uibModalInstance, TagSrv, TaxonomyCacheSrv, selection) { + function ($scope, $uibModalInstance, TagSrv, TaxonomyCacheSrv, selection, dataTypes) { var self = this; this.selection = selection; - this.state = { - all: false, - enableTlp: false, - enableIoc: false, - enableSighted: false, - enableIgnoreSimilarity: false, - enableAddTags: false, - enableRemoveTags: false - }; + this.dataTypes = _.pluck(_.filter(dataTypes, function (item) { + return !item.isAttachment + }), 'name').sort(); + + this.$onInit = function () { + this.state = { + all: false, + enableDataType: false, + enableTlp: false, + enableIoc: false, + enableSighted: false, + enableIgnoreSimilarity: false, + enableAddTags: false, + enableRemoveTags: false + }; - this.activeTlp = 'active'; - this.params = { - ioc: false, - sighted: false, - ignoreSimilarity: false, - tlp: 2, - addTagNames: '', - removeTagNames: '' - }; + this.activeTlp = 'active'; + this.params = { + dataType: null, + ioc: false, + sighted: false, + ignoreSimilarity: false, + tlp: 2, + addTagNames: '', + removeTagNames: '' + }; + + var selectionTypes = _.unique(_.pluck(this.selection, 'dataType')); - this.toggleAll = function() { + this.canUpdateDataType = selectionTypes.length === 1 && this.dataTypes.indexOf(selectionTypes[0]) !== -1; + }; + this.toggleAll = function () { this.state.all = !this.state.all; + if (this.canUpdateDataType) { + this.state.enableDataType = this.state.all; + } + this.state.enableTlp = this.state.all; this.state.enableIoc = this.state.all; this.state.enableSighted = this.state.all; @@ -37,14 +52,14 @@ this.state.enableRemoveTags = this.state.all; }; - this.categorizeObservables = function() { + this.categorizeObservables = function () { var data = { withTags: [], withoutTags: [] }; - _.each(this.selection, function(item) { - if(item.tags.length > 0) { + _.each(this.selection, function (item) { + if (item.tags.length > 0) { data.withTags.push(item); } else { data.withoutTags.push(item); @@ -54,11 +69,17 @@ return data; }; - this.buildOperations = function(postData) { - var flags = _.pick(postData, 'ioc', 'sighted', 'ignoreSimilarity', 'tlp'); + this.buildOperations = function (postData) { + var flags = {}; + + if (this.canUpdateDataType) { + flags = _.pick(postData, 'dataType', 'ioc', 'sighted', 'ignoreSimilarity', 'tlp'); + } else { + flags = _.pick(postData, 'ioc', 'sighted', 'ignoreSimilarity', 'tlp'); + } // Handle updates without tag changes - if(!postData.addTags && !postData.removeTags) { + if (!postData.addTags && !postData.removeTags) { return [ { ids: _.pluck(this.selection, '_id'), @@ -70,28 +91,28 @@ // Handle update with tag changes var input = this.categorizeObservables(); var operations = []; - if(input.withoutTags.length > 0) { - var tags = (postData.addTags || []).filter(function(i) { + if (input.withoutTags.length > 0) { + var tags = (postData.addTags || []).filter(function (i) { return (postData.removeTags || []).indexOf(i) === -1; }); operations.push({ ids: _.pluck(input.withoutTags, '_id'), - patch: _.extend({}, flags ,{ + patch: _.extend({}, flags, { tags: _.unique(tags) }) }); } - if(input.withTags.length > 0) { - _.each(input.withTags, function(observable) { - tags = observable.tags.concat(postData.addTags || []).filter(function(i) { + if (input.withTags.length > 0) { + _.each(input.withTags, function (observable) { + tags = observable.tags.concat(postData.addTags || []).filter(function (i) { return (postData.removeTags || []).indexOf(i) === -1; }); operations.push({ ids: [observable._id], - patch: _.extend({}, flags ,{ + patch: _.extend({}, flags, { tags: _.unique(tags) }) }); @@ -101,49 +122,53 @@ return operations; }; - this.save = function() { + this.save = function () { var postData = {}; - if(this.state.enableIoc) { + if (this.state.enableDataType && this.canUpdateDataType) { + postData.dataType = this.params.dataType; + } + + if (this.state.enableIoc) { postData.ioc = this.params.ioc; } - if(this.state.enableSighted) { + if (this.state.enableSighted) { postData.sighted = this.params.sighted; } - if(this.state.enableIgnoreSimilarity) { + if (this.state.enableIgnoreSimilarity) { postData.ignoreSimilarity = this.params.ignoreSimilarity; } - if(this.state.enableTlp) { + if (this.state.enableTlp) { postData.tlp = this.params.tlp; } - if(this.state.enableAddTags) { + if (this.state.enableAddTags) { postData.addTags = _.pluck(this.params.addTags, 'text'); } - if(this.state.enableRemoveTags) { + if (this.state.enableRemoveTags) { postData.removeTags = _.pluck(this.params.removeTags, 'text'); } $uibModalInstance.close(this.buildOperations(postData)); }; - this.cancel = function() { + this.cancel = function () { $uibModalInstance.dismiss(); }; - this.getTags = function(query) { + this.getTags = function (query) { return TagSrv.autoComplete(query); }; - self.fromTagLibrary = function(field) { + self.fromTagLibrary = function (field) { TaxonomyCacheSrv.openTagLibrary() - .then(function(tags){ - if(field === 'add') { + .then(function (tags) { + if (field === 'add') { self.params.addTags = (self.params.addTags || []).concat(tags); self.toggleAddTags(); } else if (field === 'remove') { @@ -153,40 +178,49 @@ }) }; - this.toogleIoc = function() { + this.toggleDataType = function () { + if (!this.params.dataType || this.params.dataType.length === 0) { + this.params.dataType = null; + this.state.enableDataType = false; + } else { + this.state.enableDataType = true; + } + }; + + this.toogleIoc = function () { this.params.ioc = !this.params.ioc; this.state.enableIoc = true; }; - this.toogleSighted = function() { + this.toogleSighted = function () { this.params.sighted = !this.params.sighted; this.state.enableSighted = true; }; - this.toogleIgnoreSimilarity = function() { + this.toogleIgnoreSimilarity = function () { this.params.ignoreSimilarity = !this.params.ignoreSimilarity; this.state.enableIgnoreSimilarity = true; }; - this.toggleTlp = function(value) { + this.toggleTlp = function (value) { this.params.tlp = value; this.activeTlp = 'active'; this.state.enableTlp = true; }; - this.toggleAddTags = function() { + this.toggleAddTags = function () { this.state.enableAddTags = true; }; - this.toggleRemoveTags = function() { + this.toggleRemoveTags = function () { this.state.enableRemoveTags = true; }; - $scope.$watchCollection('$dialog.params.addTags', function(value) { + $scope.$watchCollection('$dialog.params.addTags', function (value) { self.params.addTagNames = _.pluck(value, 'text').join(','); }); - $scope.$watchCollection('$dialog.params.removeTags', function(value) { + $scope.$watchCollection('$dialog.params.removeTags', function (value) { self.params.removeTagNames = _.pluck(value, 'text').join(','); }); } diff --git a/frontend/app/views/partials/observables/observable.update.html b/frontend/app/views/partials/observables/observable.update.html index ebb3dc5bf1..1a7aac2b46 100644 --- a/frontend/app/views/partials/observables/observable.update.html +++ b/frontend/app/views/partials/observables/observable.update.html @@ -5,67 +5,94 @@