Skip to content

Commit

Permalink
Merge branch 'release/3.3.0-RC6'
Browse files Browse the repository at this point in the history
  • Loading branch information
To-om committed Mar 7, 2019
2 parents c91802b + 55adc90 commit 63d694a
Show file tree
Hide file tree
Showing 18 changed files with 283 additions and 14 deletions.
19 changes: 18 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
# Change Log

## [3.3.0-RC5](https://github.com/TheHive-Project/TheHive/tree/HEAD) (2019-02-24)
## [3.3.0-RC6](https://github.com/TheHive-Project/TheHive/tree/3.3.0-RC6) (2019-02-07)

[Full Changelog](https://github.com/TheHive-Project/TheHive/compare/3.3.0-RC5...3.3.0-RC6)

**Implemented enhancements:**

- Add Tags to an Alert with Responder [\#912](https://github.com/TheHive-Project/TheHive/issues/912)
- Dashboards - Add text widget [\#908](https://github.com/TheHive-Project/TheHive/issues/908)
- Empty case still available when disabled [\#901](https://github.com/TheHive-Project/TheHive/issues/901)
- Support for filtering Tags by prefix \(using asterisk, % or something\) in search dialog [\#666](https://github.com/TheHive-Project/TheHive/issues/666)

**Closed issues:**

- Dynamic \(auto-refresh\) of cases is break in 3.3.0-RC5 [\#907](https://github.com/TheHive-Project/TheHive/issues/907)
- Hostname Artifact [\#900](https://github.com/TheHive-Project/TheHive/issues/900)
- DOS issue: Firefox crashing TheHive [\#899](https://github.com/TheHive-Project/TheHive/issues/899)

## [3.3.0-RC5](https://github.com/TheHive-Project/TheHive/tree/3.3.0-RC5) (2019-02-23)
[Full Changelog](https://github.com/TheHive-Project/TheHive/compare/3.3.0-RC4...3.3.0-RC5)

**Implemented enhancements:**
Expand Down
2 changes: 1 addition & 1 deletion project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ object Dependencies {

val reflections = "org.reflections" % "reflections" % "0.9.11"
val zip4j = "net.lingala.zip4j" % "zip4j" % "1.3.2"
val elastic4play = "org.thehive-project" %% "elastic4play" % "1.8.0-1"
val elastic4play = "org.thehive-project" %% "elastic4play" % "1.9.0"
val akkaCluster = "com.typesafe.akka" %% "akka-cluster" % "2.5.19"
val akkaClusterTools = "com.typesafe.akka" %% "akka-cluster-tools" % "2.5.19"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ case class AddLogToTask(content: String, owner: Option[String], status: ActionOp
override def updateStatus(newStatus: Type, newMessage: String): ActionOperation = copy(status = newStatus, message = newMessage)
}

case class AddTagToAlert(tag: String, status: ActionOperationStatus.Type = ActionOperationStatus.Waiting, message: String = "") extends ActionOperation {
override def updateStatus(newStatus: ActionOperationStatus.Type, newMessage: String): AddTagToAlert = copy(status = newStatus, message = newMessage)
}

object ActionOperation {
val addTagToCaseWrites = Json.writes[AddTagToCase]
val addTagToArtifactWrites = Json.writes[AddTagToArtifact]
Expand All @@ -69,6 +73,7 @@ object ActionOperation {
val closeTaskWrites = Json.writes[CloseTask]
val markAlertAsReadWrites = Json.writes[MarkAlertAsRead]
val addLogToTaskWrites = Json.writes[AddLogToTask]
val addTagToAlertWrites = Json.writes[AddTagToAlert]
implicit val actionOperationReads: Reads[ActionOperation] = Reads[ActionOperation](json
(json \ "type").asOpt[String].fold[JsResult[ActionOperation]](JsError("type is missing in action operation")) {
case "AddTagToCase" (json \ "tag").validate[String].map(tag AddTagToCase(tag))
Expand All @@ -85,6 +90,7 @@ object ActionOperation {
content (json \ "content").validate[String]
owner (json \ "owner").validateOpt[String]
} yield AddLogToTask(content, owner)
case "AddTagToAlert" => (json \ "tag").validate[String].map(tag AddTagToAlert(tag))
case other JsError(s"Unknown operation $other")
})
implicit val actionOperationWrites: Writes[ActionOperation] = Writes[ActionOperation] {
Expand All @@ -95,6 +101,7 @@ object ActionOperation {
case a: CloseTask closeTaskWrites.writes(a)
case a: MarkAlertAsRead markAlertAsReadWrites.writes(a)
case a: AddLogToTask addLogToTaskWrites.writes(a)
case a: AddTagToAlert addTagToAlertWrites.writes(a)
case a Json.obj("unsupported operation" a.toString)
}
}
Expand Down Expand Up @@ -198,6 +205,15 @@ class ActionOperationSrv @Inject() (
task findTaskEntity(entity)
_ logSrv.create(task, Fields.empty.set("message", content).set("owner", owner.map(JsString)))
} yield operation.updateStatus(ActionOperationStatus.Success, "")
case AddTagToAlert(tag, _, _) =>
entity match {
case initialAlert: Alert
for {
alert alertSrv.get(initialAlert.id)
_ alertSrv.update(alert.id, Fields.empty.set("tags", Json.toJson((alert.tags() :+ tag).distinct)), ModifyConfig(retryOnConflict = 0, version = Some(alert.version)))
} yield operation.updateStatus(ActionOperationStatus.Success, "")
case _ Future.failed(BadRequestError("Alert not found"))
}
case o Future.successful(operation.updateStatus(ActionOperationStatus.Failure, s"Operation $o not supported"))
}
}
Expand Down
1 change: 1 addition & 0 deletions ui/app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@
<script src="scripts/directives/dashboard/item.js"></script>
<script src="scripts/directives/dashboard/line.js"></script>
<script src="scripts/directives/dashboard/multiline.js"></script>
<script src="scripts/directives/dashboard/text.js"></script>
<script src="scripts/directives/dateTimePicker.js"></script>
<script src="scripts/directives/dt-picker.js"></script>
<script src="scripts/directives/entityLink.js"></script>
Expand Down
9 changes: 5 additions & 4 deletions ui/app/scripts/controllers/dashboard/DashboardViewCtrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@
this.canEditDashboard = function() {
return (this.createdBy === this.currentUser.id) ||
(this.dashboardStatus = 'Shared' && AuthenticationSrv.isAdmin(this.currentUser));
}
};

this.options = {
dashboardAllowedTypes: ['container'],
containerAllowedTypes: ['bar', 'line', 'donut', 'counter', 'multiline'],
containerAllowedTypes: ['bar', 'line', 'donut', 'counter', 'text', 'multiline'],
maxColumns: 3,
cls: DashboardSrv.typeClasses,
labels: {
Expand All @@ -70,6 +70,7 @@
donut: 'Donut',
line: 'Line',
counter: 'Counter',
text: 'Text',
multiline: 'Multi Lines'
},
editLayout: !_.find(this.definition.items, function(row) {
Expand Down Expand Up @@ -132,9 +133,9 @@
}, 0);
});

}
};

this.itemInserted = function(item, rows, rowIndex, index) {
this.itemInserted = function(item, rows/*, rowIndex, index*/) {
if(!item.id){
item.id = UtilsSrv.guid();
}
Expand Down
4 changes: 2 additions & 2 deletions ui/app/scripts/directives/dashboard/multiline.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
}

return s;
}
};

scope.buildSerie = function(serie, q, index) {
return {
Expand Down Expand Up @@ -166,7 +166,7 @@
};

scope.chart = chart;
}, function(err) {
}, function(/*err*/) {
scope.error = true;
NotificationSrv.log('Failed to fetch data, please edit the widget definition', 'error');
});
Expand Down
99 changes: 99 additions & 0 deletions ui/app/scripts/directives/dashboard/text.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
(function() {
'use strict';
angular.module('theHiveDirectives').directive('dashboardText', function($q, $http, $state, DashboardSrv, GlobalSearchSrv, NotificationSrv) {
return {
restrict: 'E',
scope: {
filter: '=?',
options: '=',
entity: '=',
autoload: '=',
mode: '=',
refreshOn: '@',
resizeOn: '@',
metadata: '='
},
templateUrl: 'views/directives/dashboard/text/view.html',
link: function(scope, elem) {

scope.error = false;
scope.data = null;
scope.globalQuery = null;

scope.load = function() {
if(!scope.options.series || scope.options.series.length === 0) {
scope.error = true;
return;
}

var query = DashboardSrv.buildChartQuery(scope.filter, scope.options.query);
scope.globalQuery = query;

var stats = {
stats: _.map(scope.options.series || [], function(serie, index) {
var s = {
_agg: serie.agg,
_name: serie.name || 'agg_' + (index + 1),
_query: serie.query || {}
};

if(serie.agg !== 'count') {
s._field = serie.field;
}

return {
model: serie.entity,
query: query,
stats: [s]
};
})
};

var statsPromise = $http.post('./api/_stats', stats);

statsPromise.then(function(response) {
scope.error = false;
scope.data = response.data;

var template = scope.options.template;
Object.keys(scope.data).forEach(function(key){
var regex = new RegExp('{{' + key + '}}', 'gi');

template = template.replace(regex, scope.data[key]);
});

scope.content = template;

}, function(/*err*/) {
scope.error = true;

NotificationSrv.log('Failed to fetch data, please edit the widget definition', 'error');
});
};

scope.copyHTML = function() {
var html = elem[0].querySelector('.widget-content').innerHTML;
function listener(e) {
e.clipboardData.setData('text/html', html);
e.clipboardData.setData('text/plain', html);
e.preventDefault();
}
document.addEventListener('copy', listener);
document.execCommand('copy');
document.removeEventListener('copy', listener);
}

if (scope.autoload === true) {
scope.load();
}

if (!_.isEmpty(scope.refreshOn)) {
scope.$on(scope.refreshOn, function(event, filter) {
scope.filter = filter;
scope.load();
});
}
}
};
});
})();
12 changes: 11 additions & 1 deletion ui/app/scripts/services/DashboardSrv.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@
donut: 'fa-pie-chart',
line: 'fa-line-chart',
multiline: 'fa-area-chart',
counter: 'fa-calculator'
counter: 'fa-calculator',
text: 'fa-file'
};

this.sortOptions = [{
Expand Down Expand Up @@ -113,6 +114,14 @@
entity: null
}
},
{
type: 'text',
options: {
title: null,
template: null,
entity: null
}
},
{
type: 'donut',
options: {
Expand Down Expand Up @@ -234,6 +243,7 @@
this.hasMinimalConfiguration = function(component) {
switch (component.type) {
case 'multiline':
case 'text':
return component.options.series.length === _.without(_.pluck(component.options.series, 'entity'), undefined).length;
default:
return !!component.options.entity;
Expand Down
10 changes: 9 additions & 1 deletion ui/app/views/directives/dashboard/item.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">
<i class="mr-xxs fa" ng-class="typeClasses[component.type]"></i>{{component.options.title || 'No title'}} {{mode}}
<i class="mr-xxs fa" ng-class="typeClasses[component.type]"></i>{{component.options.title || 'No title'}}
</h3>

<div class="box-tools pull-right">
Expand Down Expand Up @@ -56,6 +56,14 @@ <h3 class="box-title">
resize-on="{{resizeOn}}"
mode="mode"></dashboard-multiline>

<dashboard-text ng-switch-when="text"
entity="metadata[component.options.entity]"
options="component.options"
filter="filter"
autoload="autoload"
refresh-on="{{refreshOn}}"
mode="mode"></dashboard-text>

<dashboard-counter ng-switch-when="counter"
entity="metadata[component.options.entity]"
options="component.options"
Expand Down
17 changes: 17 additions & 0 deletions ui/app/views/directives/dashboard/text/basic.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<div class="form-group">
<label>Title</label>
<input type="text" class="form-control" placeholder="Ex: Summary" ng-model="component.options.title">
</div>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<label>Template</label>
<textarea class="content-box" name="template"
placeholder="Close summary" markdown-editor="{
'fullscreen': {enable: false},
'iconlibrary': 'fa',
addExtraButtons: true,
resize: 'vertical'}" rows="6" ng-model="component.options.template" required></textarea>
</div>
</div>
</div>
14 changes: 14 additions & 0 deletions ui/app/views/directives/dashboard/text/edit.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<uib-tabset class="nav-tabs-custom" active="layout.activeTab">
<uib-tab index="0">
<uib-tab-heading>
<i class="fa fa-bars"></i> Basic
</uib-tab-heading>
<ng-include src="'views/directives/dashboard/text/basic.html'"></ng-include>
</uib-tab>
<uib-tab index="1">
<uib-tab-heading>
<i class="fa fa-sort"></i> Series
</uib-tab-heading>
<ng-include src="'views/directives/dashboard/text/series.html'"></ng-include>
</uib-tab>
</uib-tabset>
25 changes: 25 additions & 0 deletions ui/app/views/directives/dashboard/text/serie.filters.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<div ng-if="serie.filters.length > 0">
<strong>Serie's filter</strong>
</div>
<div class="row mb-xxxs" ng-repeat="filter in serie.filters track by $index">
<div class="col-sm-4">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button" ng-click="removeSerieFilter(serie, $index)">
<i class="fa fa-times text-danger"></i>
</button>
</span>
<select class="form-control" ng-model="filter.field"
ng-options="item.name as item.name for (key, item) in metadata[serie.entity].attributes"
ng-change="setFilterField(filter, serie.entity)"></select>
</div>
</div>
<div class="col-sm-8">
<filter-editor metadata="metadata" filter="filter" entity="serie.entity"></filter-editor>
</div>
</div>
<div class="mt-xxs">
<a href ng-click="addSerieFilter(serie)">
<i class="fa fa-plus"></i> Add a filter
</a>
</div>
Loading

0 comments on commit 63d694a

Please sign in to comment.