diff --git a/ui/app/index.html b/ui/app/index.html index 4a88b497dd..1360eff69f 100644 --- a/ui/app/index.html +++ b/ui/app/index.html @@ -182,6 +182,7 @@ + diff --git a/ui/app/scripts/controllers/admin/AdminReportTemplatesCtrl.js b/ui/app/scripts/controllers/admin/AdminReportTemplatesCtrl.js index 0df79d8165..6e6029d4e3 100644 --- a/ui/app/scripts/controllers/admin/AdminReportTemplatesCtrl.js +++ b/ui/app/scripts/controllers/admin/AdminReportTemplatesCtrl.js @@ -16,16 +16,12 @@ this.load = function() { $q.all([ ReportTemplateSrv.list(), - AnalyzerSrv.query({ - range: 'all' - }).$promise + AnalyzerSrv.query() ]).then(function (response) { self.templates = response[0].data; self.analyzers = response[1]; - - var map = _.indexBy(self.analyzers, 'id'); - - return $q.resolve(map); + + return $q.resolve(self.analyzers); }).then(function (analyzersMap) { _.each(self.templates, function (tpl) { _.each(tpl.analyzers, function (analyzerId) { @@ -62,7 +58,7 @@ this.load(); }; - function AdminReportTemplateDialogCtrl($modalInstance, reportTemplate, ReportTemplateSrv, analyzer) { + function AdminReportTemplateDialogCtrl($modalInstance, reportTemplate, ReportTemplateSrv, AlertSrv, analyzer) { this.reportTemplate = reportTemplate; this.analyzer = analyzer; this.reportTypes = ['short', 'long']; diff --git a/ui/app/scripts/controllers/case/CaseObservablesCtrl.js b/ui/app/scripts/controllers/case/CaseObservablesCtrl.js index 5048eb79ae..81df7d0259 100644 --- a/ui/app/scripts/controllers/case/CaseObservablesCtrl.js +++ b/ui/app/scripts/controllers/case/CaseObservablesCtrl.js @@ -151,18 +151,19 @@ }; $scope.initAnalyzersList = function() { - $scope.analyzersList.analyzers = AnalyzerSrv.query({ - range: 'all' - }); - $scope.analyzersList.active = {}; - $scope.analyzersList.datatypes = {}; - angular.forEach($scope.analyzersList.analyzers, function(analyzer) { - $scope.analyzersList.active[analyzer.id] = false; - }); - $scope.analyzersList.selected = {}; - angular.forEach($scope.analyzersList.analyzers, function(analyzer) { - $scope.analyzersList.selected[analyzer.id] = false; - }); + AnalyzerSrv.query() + .then(function(analyzers) { + $scope.analyzersList.analyzers = analyzers; + $scope.analyzersList.active = {}; + $scope.analyzersList.datatypes = {}; + angular.forEach($scope.analyzersList.analyzers, function(analyzer) { + $scope.analyzersList.active[analyzer.id] = false; + }); + $scope.analyzersList.selected = {}; + angular.forEach($scope.analyzersList.analyzers, function(analyzer) { + $scope.analyzersList.selected[analyzer.id] = false; + }); + }); }; $scope.initSelection($scope.selection); diff --git a/ui/app/scripts/controllers/case/CaseObservablesItemCtrl.js b/ui/app/scripts/controllers/case/CaseObservablesItemCtrl.js index 8a7858d911..b45514d3f7 100644 --- a/ui/app/scripts/controllers/case/CaseObservablesItemCtrl.js +++ b/ui/app/scripts/controllers/case/CaseObservablesItemCtrl.js @@ -1,14 +1,15 @@ -(function() { +(function () { 'use strict'; angular.module('theHiveControllers').controller('CaseObservablesItemCtrl', - function($scope, $state, $stateParams, CaseTabsSrv, CaseArtifactSrv, PSearchSrv, AnalyzerSrv, AnalyzerInfoSrv, JobSrv, AlertSrv) { + function ($scope, $state, $stateParams, CaseTabsSrv, CaseArtifactSrv, CortexSrv, PSearchSrv, AnalyzerSrv, JobSrv, AlertSrv) { var observableId = $stateParams.itemId, observableName = 'observable-' + observableId; $scope.caseId = $stateParams.caseId; - $scope.getAnalyzerInfo = AnalyzerInfoSrv; $scope.report = {}; $scope.analyzers = {}; + $scope.analyzerJobs = {}; + $scope.jobs = {}; $scope.state = { 'editing': false, 'isCollapsed': false, @@ -30,7 +31,7 @@ CaseArtifactSrv.api().get({ 'artifactId': observableId - }, function(observable) { + }, function (observable) { // Add tab CaseTabsSrv.addTab(observableName, { @@ -49,21 +50,51 @@ // Prepare the scope data $scope.initScope(observable); - // Prepare the jobs data - $scope.initJobs(); - - }, function(response) { + }, function (response) { AlertSrv.error('artifactDetails', response.data, response.status); CaseTabsSrv.activateTab('observables'); }); - $scope.initScope = function(data) { - $scope.artifactAnalyzers = data.analyzers; - $scope.artifact = data.artifact; + $scope.initScope = function (artifact) { + $scope.artifact = artifact; + + // Get analyzers available for the observable's datatype + AnalyzerSrv.forDataType(artifact.dataType) + .then(function (analyzers) { + return $scope.analyzers = analyzers; + }) + .then(function (analyzers) { + console.log(analyzers); + + $scope.jobs = CortexSrv.list($scope.caseId, observableId, $scope.onJobsChange); + }); + + }; + + $scope.onJobsChange = function () { + $scope.analyzerJobs = {}; - angular.forEach($scope.artifactAnalyzers, function(analyzer) { - analyzer.active = true; - $scope.analyzers[analyzer.id] = analyzer; + angular.forEach($scope.analyzers, function (analyzer, analyzerId) { + $scope.analyzerJobs[analyzerId] = []; + }); + + angular.forEach($scope.jobs.values, function (job) { + if (job.analyzerId in $scope.analyzerJobs) { + $scope.analyzerJobs[job.analyzerId].push(job); + } else { + $scope.analyzerJobs[job.analyzerId] = [job]; + + AnalyzerSrv.get(job.analyzerId) + .then(function (data) { + $scope.analyzers[data.analyzerId] = { + active: false, + showRows: false + }; + }, + function (response) { + AlertSrv.error('artifactDetails', response.data, response.status); + }); + } }); }; @@ -71,82 +102,42 @@ 'artifactId': observableId }); - $scope.initJobs = function() { - var jobs = PSearchSrv($scope.caseId, 'case_artifact_job', { - 'filter': { - '_parent': { - '_type': 'case_artifact', - '_query': { - '_id': $scope.id - } - } - }, - 'pageSize': 200, - 'sort': '-startDate', - 'onUpdate': function() { - $scope.analyzerJobs = {}; - angular.forEach($scope.analyzers, function(analyzer, analyzerId) { - $scope.analyzerJobs[analyzerId] = []; - }); - angular.forEach(jobs.values, function(job) { - if (job.analyzerId in $scope.analyzerJobs) { - $scope.analyzerJobs[job.analyzerId].push(job); - } else { - $scope.analyzerJobs[job.analyzerId] = [job]; - - console.log('AnalyzerSrv.get(' + job.analyzerId + ')'); - - AnalyzerSrv.get({ - 'analyzerId': job.analyzerId - }, function(data) { - $scope.analyzers[data.analyzerId] = { - active: false, - showRows: false - }; - }, function(response) { - AlertSrv.error('artifactDetails', response.data, response.status); - }); - } - }); - } - }); - }; - $scope.openArtifact = function(a) { + $scope.openArtifact = function (a) { $state.go('app.case.observables-item', { caseId: a["case"].id, itemId: a.id }); }; - $scope.getLabels = function(selection) { + $scope.getLabels = function (selection) { var labels = []; - angular.forEach(selection, function(label) { + angular.forEach(selection, function (label) { labels.push(label.text); }); return labels; }; - $scope.updateField = function(fieldName, newValue) { + $scope.updateField = function (fieldName, newValue) { var field = {}; field[fieldName] = newValue; console.log('update artifact field ' + fieldName + ':' + field[fieldName]); return CaseArtifactSrv.api().update({ artifactId: $scope.artifact.id - }, field, function() {}, function(response) { + }, field, function () {}, function (response) { AlertSrv.error('artifactDetails', response.data, response.status); }); }; - $scope.runAnalyzer = function(analyzerId) { + $scope.runAnalyzer = function (analyzerId) { console.log('running analyzer ' + analyzerId + ' on artifact ' + $scope.artifact.id); - return JobSrv.save({ - 'artifactId': $scope.artifact.id - }, { - 'analyzerId': analyzerId - }, function() {}, function(response) { + return CortexSrv.createJob({ + cortexId: 'local', + artifactId: $scope.artifact.id, + analyzerId: analyzerId + }, function () {}, function (response) { AlertSrv.error('artifactDetails', response.data, response.status); }); }; diff --git a/ui/app/scripts/directives/report.js b/ui/app/scripts/directives/report.js index b9ea7d54af..85ce4f313a 100644 --- a/ui/app/scripts/directives/report.js +++ b/ui/app/scripts/directives/report.js @@ -4,6 +4,7 @@ .directive('report', function($templateRequest, $compile) { function updateReport(a, b, scope) { console.log('update report ' + scope.name); + if (!angular.isDefined(scope.content) || !angular.isDefined(scope.name)) { console.log('no data, don\'t show anything'); scope.element.html(''); @@ -11,12 +12,19 @@ } // find report template - $templateRequest( - '/api/analyzer/' + scope.name + '/report/' + scope.status.toLowerCase() + '_' + scope.flavor, true) + //$templateRequest('/api/analyzer/' + scope.name + '/report/' + scope.status.toLowerCase() + '_' + scope.flavor, true) + $templateRequest('/api/connector/cortex/report/template/content/' + scope.name + '/' + scope.flavor, true) .then(function(tmpl) { scope.element.html($compile(tmpl)(scope)); - }, function() { - scope.element.html('Analyzer not found !'); + }, function(response) { + if(response.status === 404) { + console.log('Use default template'); + return $templateRequest('/views/reports/' + scope.flavor + '.html', true) + } else { + scope.element.html('Analyzer not found !'); + } + }).then(null, function(tmpl) { + scope.element.html($compile(tmpl)(scope)); }); } return { diff --git a/ui/app/scripts/services/AnalyzerSrv.js b/ui/app/scripts/services/AnalyzerSrv.js index 97629be901..e5bd6acf09 100644 --- a/ui/app/scripts/services/AnalyzerSrv.js +++ b/ui/app/scripts/services/AnalyzerSrv.js @@ -1,16 +1,86 @@ -(function() { +(function () { 'use strict'; angular.module('theHiveServices') - .factory('AnalyzerSrv', function($resource) { - return $resource('/api/connector/cortex/analyzer/:analyzerId', {}, { - query: { - method: 'GET', - url: '/api/connector/cortex/analyzer', - isArray: true + .factory('AnalyzerSrv', function ($resource, $q) { + var analyzers = null, + resource = $resource('/api/connector/cortex/analyzer/:analyzerId', {}, { + query: { + method: 'GET', + url: '/api/connector/cortex/analyzer', + isArray: true + }, + get: { + isArray: true + }, + update: { + method: 'PATCH' + } + }); + + var factory = { + clearCache: function () { + analyzers = null; }, - update: { - method: 'PATCH' + query: function () { + var deferred = $q.defer(); + + if (analyzers === null) { + + resource.query({ + range: 'all' + }, {}, function (response) { + analyzers = _.indexBy(response, 'id'); + + deferred.resolve(analyzers); + }, function (rejection) { + deferred.reject(rejection); + }) + + } else { + deferred.resolve(analyzers); + } + + return deferred.promise; + }, + + get: function(analyzerId) { + var deferred = $q.defer(); + + if(analyzers !== null && analyzers[analyzerId]) { + deferred.resolve(analyzers[analyzerId]); + } else { + resource.get({ + 'analyzerId': analyzerId + }, function (data) { + deferred.resolve(data); + }, function (rejection) { + deferred.reject(rejection); + }); + } + + return deferred.promise; + }, + + forDataType: function(dataType) { + var deferred = $q.defer(); + + factory.query() + .then(function(all) { + var filtered = {}; + _.each(all, function(value, key) { + if(value.dataTypeList && value.dataTypeList.indexOf(dataType) !== -1) { + filtered[key] = angular.copy(value); + filtered[key].active = true; + } + }); + + deferred.resolve(filtered); + }); + + return deferred.promise; } - }); + }; + + return factory; }); })(); diff --git a/ui/app/scripts/services/CortexSrv.js b/ui/app/scripts/services/CortexSrv.js new file mode 100644 index 0000000000..5fa2838ee7 --- /dev/null +++ b/ui/app/scripts/services/CortexSrv.js @@ -0,0 +1,39 @@ +(function () { + 'use strict'; + angular.module('theHiveServices') + .factory('CortexSrv', function ($q, $http, $rootScope, StatSrv, StreamSrv, PSearchSrv) { + + var baseUrl = '/api/connector/cortex'; + + var factory = { + list: function (caseId, observableId, callback) { + return PSearchSrv(undefined, 'connector/cortex/job', { + sort: '-startDate', + loadAll: false, + pageSize: 200, + onUpdate: callback || angular.noop, + streamObjectType: 'job', + filter: { + _parent: { + _type: 'case_artifact', + _query: { + _id: observableId + } + } + } + }); + }, + + getJob: function (jobId) { + return $http.get(baseUrl + '/job/' + jobId); + }, + + createJob: function (job) { + return $http.post(baseUrl + '/job', job); + } + }; + + return factory; + }); + +})(); diff --git a/ui/app/scripts/services/ReportTemplateSrv.js b/ui/app/scripts/services/ReportTemplateSrv.js index b7884747a8..80788e98cc 100644 --- a/ui/app/scripts/services/ReportTemplateSrv.js +++ b/ui/app/scripts/services/ReportTemplateSrv.js @@ -8,15 +8,6 @@ method: 'POST', url: baseUrl + '/_search', isArray: true - }, - update: { - method: 'PATCH' - }, - create: { - method: 'POST' - }, - save: { - method: 'PUT' } }); @@ -32,8 +23,8 @@ }, save: function(tpl) { - if(tpl.id) { - return $http.put(baseUrl + '/' + tpl.id, tpl, {}); + if(tpl.id) { + return $http.patch(baseUrl + '/' + tpl.id, _.omit(tpl, 'id'), {}); } else { return $http.post(baseUrl, tpl, {}); } diff --git a/ui/app/views/partials/observables/details/artifact-details-analysers.html b/ui/app/views/partials/observables/details/artifact-details-analysers.html index 6f979a4551..e059fe441e 100644 --- a/ui/app/views/partials/observables/details/artifact-details-analysers.html +++ b/ui/app/views/partials/observables/details/artifact-details-analysers.html @@ -1,28 +1,46 @@ - -
-
-

- Analyzer -

-
-
-

- Last analysis -

-
-
-

- Job status -

-
-
-

- Action -

-
-
+ + + + + + + + + + + + + +
AnalyzerLast analysisAction
+ {{::analyzerId}}
+ {{::analyzers[analyzerId] | getField: 'description'}} +
+ + + + + + + +
- +
diff --git a/ui/app/views/reports/long.html b/ui/app/views/reports/long.html new file mode 100644 index 0000000000..78570c3961 --- /dev/null +++ b/ui/app/views/reports/long.html @@ -0,0 +1 @@ +Default Long Tpl \ No newline at end of file diff --git a/ui/app/views/reports/short.html b/ui/app/views/reports/short.html new file mode 100644 index 0000000000..edcfd31b9a --- /dev/null +++ b/ui/app/views/reports/short.html @@ -0,0 +1 @@ +Default Short Tpl \ No newline at end of file diff --git a/ui/test/karma.conf.js b/ui/test/karma.conf.js index 4c6288ad13..57d7237d2d 100644 --- a/ui/test/karma.conf.js +++ b/ui/test/karma.conf.js @@ -64,6 +64,7 @@ module.exports = function(config) { 'bower_components/angular-marked/dist/angular-marked.js', 'bower_components/bootstrap-markdown/js/bootstrap-markdown.js', 'bower_components/angular-markdown-editor-ghiscoding/src/angular-markdown-editor.js', + 'bower_components/angular-ui-ace/ui-ace.js', 'bower_components/angular-mocks/angular-mocks.js', // endbower "bower_components/cryptojslib/components/core-min.js",