From 8f1028a63eabf28711cedac2d758e59a1fde102f Mon Sep 17 00:00:00 2001 From: To-om Date: Thu, 7 Jan 2021 09:26:53 +0100 Subject: [PATCH] #1734 Add handlingDuration properties in alert --- ScalliGraph | 2 +- .../org/thp/thehive/controllers/v0/AlertCtrl.scala | 10 +++++++--- .../org/thp/thehive/controllers/v1/Properties.scala | 9 +++++++-- thehive/app/org/thp/thehive/services/AlertSrv.scala | 12 ++++++++++++ 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/ScalliGraph b/ScalliGraph index 2426d2e5f1..e9b3180098 160000 --- a/ScalliGraph +++ b/ScalliGraph @@ -1 +1 @@ -Subproject commit 2426d2e5f19ae24ed7c114d5ebd3c902027a6679 +Subproject commit e9b31800985bc83dd8cda20496f42a96d5236f21 diff --git a/thehive/app/org/thp/thehive/controllers/v0/AlertCtrl.scala b/thehive/app/org/thp/thehive/controllers/v0/AlertCtrl.scala index b09d0bbabe..c7331860b7 100644 --- a/thehive/app/org/thp/thehive/controllers/v0/AlertCtrl.scala +++ b/thehive/app/org/thp/thehive/controllers/v0/AlertCtrl.scala @@ -1,9 +1,6 @@ package org.thp.thehive.controllers.v0 -import java.util.{Base64, List => JList, Map => JMap} - import io.scalaland.chimney.dsl._ -import javax.inject.{Inject, Named, Singleton} import org.apache.tinkerpop.gremlin.structure.Graph import org.thp.scalligraph.auth.AuthContext import org.thp.scalligraph.controllers._ @@ -27,6 +24,8 @@ import org.thp.thehive.services._ import play.api.libs.json.{JsArray, JsObject, Json} import play.api.mvc.{Action, AnyContent, Results} +import java.util.{Base64, List => JList, Map => JMap} +import javax.inject.{Inject, Named, Singleton} import scala.util.{Failure, Success, Try} @Singleton @@ -451,5 +450,10 @@ class PublicAlert @Inject() ( }) .property("case", db.idMapping)(_.select(_.`case`._id).readonly) .property("importDate", UMapping.date.optional)(_.select(_.importDate).readonly) + .property("computed.handlingDuration", UMapping.long)(_.select(_.handlingDuration).readonly) + .property("computed.handlingDurationInSeconds", UMapping.long)(_.select(_.handlingDuration.math("_ / 1000").domainMap(_.toLong)).readonly) + .property("computed.handlingDurationInMinutes", UMapping.long)(_.select(_.handlingDuration.math("_ / 60000").domainMap(_.toLong)).readonly) + .property("computed.handlingDurationInHours", UMapping.long)(_.select(_.handlingDuration.math("_ / 3600000").domainMap(_.toLong)).readonly) + .property("computed.handlingDurationInDays", UMapping.long)(_.select(_.handlingDuration.math("_ / 86400000").domainMap(_.toLong)).readonly) .build } diff --git a/thehive/app/org/thp/thehive/controllers/v1/Properties.scala b/thehive/app/org/thp/thehive/controllers/v1/Properties.scala index 7bfa9cf7db..8295730f8a 100644 --- a/thehive/app/org/thp/thehive/controllers/v1/Properties.scala +++ b/thehive/app/org/thp/thehive/controllers/v1/Properties.scala @@ -125,7 +125,7 @@ class Properties @Inject() ( case CustomFieldType.integer => new Converter[Any, JsValue] { def apply(x: JsValue): Any = x.as[Long] } case CustomFieldType.string => new Converter[Any, JsValue] { def apply(x: JsValue): Any = x.as[String] } } - .getOrElse(new Converter[Any, JsValue] { def apply(x: JsValue): Any = x }) + .getOrElse((x: JsValue) => x) case _ => (x: JsValue) => x } .custom { @@ -143,6 +143,11 @@ class Properties @Inject() ( case _ => Failure(BadRequestError("Invalid custom fields format")) }) .property("importDate", UMapping.date.optional)(_.select(_.importDate).readonly) + .property("computed.handlingDuration", UMapping.long)(_.select(_.handlingDuration).readonly) + .property("computed.handlingDurationInSeconds", UMapping.long)(_.select(_.handlingDuration.math("_ / 1000").domainMap(_.toLong)).readonly) + .property("computed.handlingDurationInMinutes", UMapping.long)(_.select(_.handlingDuration.math("_ / 60000").domainMap(_.toLong)).readonly) + .property("computed.handlingDurationInHours", UMapping.long)(_.select(_.handlingDuration.math("_ / 3600000").domainMap(_.toLong)).readonly) + .property("computed.handlingDurationInDays", UMapping.long)(_.select(_.handlingDuration.math("_ / 86400000").domainMap(_.toLong)).readonly) .build lazy val audit: PublicProperties = @@ -259,7 +264,7 @@ class Properties @Inject() ( case CustomFieldType.integer => new Converter[Any, JsValue] { def apply(x: JsValue): Any = x.as[Long] } case CustomFieldType.string => new Converter[Any, JsValue] { def apply(x: JsValue): Any = x.as[String] } } - .getOrElse(new Converter[Any, JsValue] { def apply(x: JsValue): Any = x }) + .getOrElse((x: JsValue) => x) case _ => (x: JsValue) => x } .custom { diff --git a/thehive/app/org/thp/thehive/services/AlertSrv.scala b/thehive/app/org/thp/thehive/services/AlertSrv.scala index 7a9af761eb..082fa64ee6 100644 --- a/thehive/app/org/thp/thehive/services/AlertSrv.scala +++ b/thehive/app/org/thp/thehive/services/AlertSrv.scala @@ -403,6 +403,18 @@ object AlertOps { def importDate: Traversal[Date, Date, Converter[Date, Date]] = traversal.outE[AlertCase].value(_._createdAt) + def handlingDuration: Traversal[Long, Long, IdentityConverter[Long]] = + traversal.coalesceIdent( + _.filter(_.outE[AlertCase]) + .sack( + (_: JLong, importDate: JLong) => importDate, + _.by(_.importDate.graphMap[Long, JLong, Converter[Long, JLong]](_.getTime, Converter.long)) + ) + .sack((_: Long) - (_: JLong), _.by(_._createdAt.graphMap[Long, JLong, Converter[Long, JLong]](_.getTime, Converter.long))) + .sack[Long], + _.constant(0L) + ) + def similarCases(maybeCaseFilter: Option[Traversal.V[Case] => Traversal.V[Case]])(implicit authContext: AuthContext ): Traversal[(RichCase, SimilarStats), JMap[String, Any], Converter[(RichCase, SimilarStats), JMap[String, Any]]] = {