From 786ac8cb72c75beb931b2a74409cf5c4b77ef348 Mon Sep 17 00:00:00 2001 From: To-om Date: Mon, 21 Sep 2020 13:44:41 +0200 Subject: [PATCH] #1501 Fix coalesce converter problem --- ScalliGraph | 2 +- .../controllers/v0/AuditRenderer.scala | 4 +- .../thp/thehive/controllers/v0/CaseCtrl.scala | 2 +- .../thehive/controllers/v0/CaseRenderer.scala | 6 +-- .../controllers/v0/ObservableRenderer.scala | 8 ++-- .../controllers/v1/ObservableRenderer.scala | 2 +- .../org/thp/thehive/services/AuditSrv.scala | 40 +++++++++---------- .../org/thp/thehive/services/CaseSrv.scala | 17 ++++---- .../notification/notifiers/Webhook.scala | 39 +++++++++--------- .../thehive/services/th3/Aggregation.scala | 8 ++-- 10 files changed, 65 insertions(+), 63 deletions(-) diff --git a/ScalliGraph b/ScalliGraph index 812a43e5c8..183ce24956 160000 --- a/ScalliGraph +++ b/ScalliGraph @@ -1 +1 @@ -Subproject commit 812a43e5c8053ba05bfbf313e241077133b4ead0 +Subproject commit 183ce2495694013a277cef83ab7f30280be7e137 diff --git a/thehive/app/org/thp/thehive/controllers/v0/AuditRenderer.scala b/thehive/app/org/thp/thehive/controllers/v0/AuditRenderer.scala index 21bbe67c58..218047efbc 100644 --- a/thehive/app/org/thp/thehive/controllers/v0/AuditRenderer.scala +++ b/thehive/app/org/thp/thehive/controllers/v0/AuditRenderer.scala @@ -42,7 +42,7 @@ trait AuditRenderer { def observableToJson: Traversal.V[Observable] => Traversal[JsObject, JMap[String, Any], Converter[JsObject, JMap[String, Any]]] = _.project( _.by(_.richObservable.domainMap(_.toJson)) - .by(_.coalesce(o => caseToJson(o.`case`), o => alertToJson(o.alert))) + .by(_.coalesceMulti(o => caseToJson(o.`case`), o => alertToJson(o.alert))) ).domainMap { case (obs, caseOrAlert) => obs.as[JsObject] + ((caseOrAlert \ "_type").asOpt[String].getOrElse("") -> caseOrAlert) } @@ -83,7 +83,7 @@ trait AuditRenderer { def auditRenderer: Traversal.V[Audit] => Traversal[JsObject, JMap[String, Any], Converter[JsObject, JMap[String, Any]]] = (_: Traversal.V[Audit]) - .coalesce(_.`object`, _.identity.setConverter[Vertex, IdentityConverter[Vertex]](Converter.identity[Vertex])) + .coalesceIdent[Vertex](_.`object`, _.identity) .choose( _.on(_.label) .option("Case", t => caseToJson(t.v[Case])) diff --git a/thehive/app/org/thp/thehive/controllers/v0/CaseCtrl.scala b/thehive/app/org/thp/thehive/controllers/v0/CaseCtrl.scala index 40c288c4ea..dcd27bd6ba 100644 --- a/thehive/app/org/thp/thehive/controllers/v0/CaseCtrl.scala +++ b/thehive/app/org/thp/thehive/controllers/v0/CaseCtrl.scala @@ -345,7 +345,7 @@ class PublicCase @Inject() ( .sack((_: Long) - (_: JLong), _.by(_.value(_.startDate).graphMap[Long, JLong, Converter[Long, JLong]](_.getTime, Converter.long))) .sack((_: Long) / (_: Long), _.by(_.constant(3600000L))) .sack[Long], - _.constant(0L) + 0L ) ).readonly ) diff --git a/thehive/app/org/thp/thehive/controllers/v0/CaseRenderer.scala b/thehive/app/org/thp/thehive/controllers/v0/CaseRenderer.scala index 5b56c2f48e..631b7ce686 100644 --- a/thehive/app/org/thp/thehive/controllers/v0/CaseRenderer.scala +++ b/thehive/app/org/thp/thehive/controllers/v0/CaseRenderer.scala @@ -58,8 +58,8 @@ trait CaseRenderer { def isOwnerStats(implicit authContext: AuthContext): Traversal.V[Case] => Traversal[Boolean, String, Converter[Boolean, String]] = _.origin.value(_.name).domainMap(_ == authContext.organisation) - def caseStatsRenderer( - implicit authContext: AuthContext + def caseStatsRenderer(implicit + authContext: AuthContext ): Traversal.V[Case] => Traversal[JsObject, JMap[String, Any], Converter[JsObject, JMap[String, Any]]] = _.project( _.by( @@ -68,7 +68,7 @@ trait CaseRenderer { _.by(taskStats) .by(observableStats) ), - _.constant2[(JsObject, JsObject), JMap[String, Any]](JsObject.empty -> JsObject.empty) + JsObject.empty -> JsObject.empty ) ).by(alertStats) .by(mergeFromStats) diff --git a/thehive/app/org/thp/thehive/controllers/v0/ObservableRenderer.scala b/thehive/app/org/thp/thehive/controllers/v0/ObservableRenderer.scala index ddbc076830..6589aa9d9b 100644 --- a/thehive/app/org/thp/thehive/controllers/v0/ObservableRenderer.scala +++ b/thehive/app/org/thp/thehive/controllers/v0/ObservableRenderer.scala @@ -16,8 +16,8 @@ import play.api.libs.json.{JsObject, Json} trait ObservableRenderer { - def observableStatsRenderer( - implicit authContext: AuthContext + def observableStatsRenderer(implicit + authContext: AuthContext ): Traversal.V[Observable] => Traversal[JsObject, JMap[JBoolean, JLong], Converter[JsObject, JMap[JBoolean, JLong]]] = _.similar .visible @@ -32,8 +32,8 @@ trait ObservableRenderer { } def observableLinkRenderer: V[Observable] => Traversal[JsObject, JMap[String, Any], Converter[JsObject, JMap[String, Any]]] = - _.coalesce( - _.alert.richAlert.domainMap(a => Json.obj("alert" -> a.toJson)), + _.coalesceMulti( + _.alert.richAlert.domainMap(a => Json.obj("alert" -> a.toJson)), _.`case`.richCaseWithoutPerms.domainMap(c => Json.obj("case" -> c.toJson)) ) } diff --git a/thehive/app/org/thp/thehive/controllers/v1/ObservableRenderer.scala b/thehive/app/org/thp/thehive/controllers/v1/ObservableRenderer.scala index ae88526ba2..9f69cf6185 100644 --- a/thehive/app/org/thp/thehive/controllers/v1/ObservableRenderer.scala +++ b/thehive/app/org/thp/thehive/controllers/v1/ObservableRenderer.scala @@ -43,7 +43,7 @@ trait ObservableRenderer { _.origin.has("name", authContext.organisation).fold.domainMap(l => JsBoolean(l.nonEmpty)) def observableLinks: Traversal.V[Observable] => Traversal[JsObject, JMap[String, Any], Converter[JsObject, JMap[String, Any]]] = - _.coalesce( + _.coalesceMulti( _.alert.richAlert.domainMap(a => Json.obj("alert" -> a.toJson)), _.`case`.richCaseWithoutPerms.domainMap(c => Json.obj("case" -> c.toJson)) ) diff --git a/thehive/app/org/thp/thehive/services/AuditSrv.scala b/thehive/app/org/thp/thehive/services/AuditSrv.scala index 46c7bb43f6..ba3256f75e 100644 --- a/thehive/app/org/thp/thehive/services/AuditSrv.scala +++ b/thehive/app/org/thp/thehive/services/AuditSrv.scala @@ -107,8 +107,8 @@ class AuditSrv @Inject() ( } } - private def createFromPending(tx: AnyRef, audit: Audit, context: Option[Product with Entity], `object`: Option[Product with Entity])( - implicit graph: Graph, + private def createFromPending(tx: AnyRef, audit: Audit, context: Option[Product with Entity], `object`: Option[Product with Entity])(implicit + graph: Graph, authContext: AuthContext ): Try[Unit] = { logger.debug(s"Store audit entity: $audit") @@ -123,8 +123,8 @@ class AuditSrv @Inject() ( } } - def create(audit: Audit, context: Option[Product with Entity], `object`: Option[Product with Entity])( - implicit graph: Graph, + def create(audit: Audit, context: Option[Product with Entity], `object`: Option[Product with Entity])(implicit + graph: Graph, authContext: AuthContext ): Try[Unit] = { def setupCallbacks(tx: AnyRef): Try[Unit] = { @@ -190,8 +190,8 @@ class AuditSrv @Inject() ( class UserAudit extends SelfContextObjectAudit[User] { - def changeProfile(user: User with Entity, organisation: Organisation, profile: Profile)( - implicit graph: Graph, + def changeProfile(user: User with Entity, organisation: Organisation, profile: Profile)(implicit + graph: Graph, authContext: AuthContext ): Try[Unit] = auditSrv.create( @@ -200,8 +200,8 @@ class AuditSrv @Inject() ( Some(user) ) - def delete(user: User with Entity, organisation: Organisation with Entity)( - implicit graph: Graph, + def delete(user: User with Entity, organisation: Organisation with Entity)(implicit + graph: Graph, authContext: AuthContext ): Try[Unit] = auditSrv.create( @@ -213,8 +213,8 @@ class AuditSrv @Inject() ( class ShareAudit { - def shareCase(`case`: Case with Entity, organisation: Organisation with Entity, profile: Profile with Entity)( - implicit graph: Graph, + def shareCase(`case`: Case with Entity, organisation: Organisation with Entity, profile: Profile with Entity)(implicit + graph: Graph, authContext: AuthContext ): Try[Unit] = auditSrv.create( @@ -223,8 +223,8 @@ class AuditSrv @Inject() ( Some(`case`) ) - def shareTask(task: Task with Entity, `case`: Case with Entity, organisation: Organisation with Entity)( - implicit graph: Graph, + def shareTask(task: Task with Entity, `case`: Case with Entity, organisation: Organisation with Entity)(implicit + graph: Graph, authContext: AuthContext ): Try[Unit] = auditSrv.create( @@ -233,8 +233,8 @@ class AuditSrv @Inject() ( Some(`case`) ) - def shareObservable(observable: Observable with Entity, `case`: Case with Entity, organisation: Organisation with Entity)( - implicit graph: Graph, + def shareObservable(observable: Observable with Entity, `case`: Case with Entity, organisation: Organisation with Entity)(implicit + graph: Graph, authContext: AuthContext ): Try[Unit] = auditSrv.create( @@ -250,8 +250,8 @@ class AuditSrv @Inject() ( Some(`case`) ) - def unshareTask(task: Task with Entity, `case`: Case with Entity, organisation: Organisation with Entity)( - implicit graph: Graph, + def unshareTask(task: Task with Entity, `case`: Case with Entity, organisation: Organisation with Entity)(implicit + graph: Graph, authContext: AuthContext ): Try[Unit] = auditSrv.create( @@ -260,8 +260,8 @@ class AuditSrv @Inject() ( Some(`case`) ) - def unshareObservable(observable: Observable with Entity, `case`: Case with Entity, organisation: Organisation with Entity)( - implicit graph: Graph, + def unshareObservable(observable: Observable with Entity, `case`: Case with Entity, organisation: Organisation with Entity)(implicit + graph: Graph, authContext: AuthContext ): Try[Unit] = auditSrv.create( @@ -329,14 +329,14 @@ object AuditOps { def `case`: Traversal.V[Case] = traversal .out[AuditContext] - .coalesce(_.in().hasLabel("Share"), _.hasLabel("Share")) + .coalesceIdent[Vertex](_.in().hasLabel("Share"), _.hasLabel("Share")) .out[ShareCase] .v[Case] def organisation: Traversal.V[Organisation] = traversal .out[AuditContext] - .coalesce( + .coalesceIdent[Vertex]( _.hasLabel("Organisation"), _.in().hasLabel("Share").in[OrganisationShare], _.both().hasLabel("Organisation") diff --git a/thehive/app/org/thp/thehive/services/CaseSrv.scala b/thehive/app/org/thp/thehive/services/CaseSrv.scala index 8cb6192f2d..a37a10bcbc 100644 --- a/thehive/app/org/thp/thehive/services/CaseSrv.scala +++ b/thehive/app/org/thp/thehive/services/CaseSrv.scala @@ -75,9 +75,10 @@ class CaseSrv @Inject() ( case (task, owner) => taskSrv.create(task, owner) } _ <- createdTasks.toTry(t => shareSrv.shareTask(t, createdCase, organisation)) - caseTemplateCustomFields = caseTemplate - .fold[Seq[RichCustomField]](Nil)(_.customFields) - .map(cf => (cf.name, cf.value, cf.order)) + caseTemplateCustomFields = + caseTemplate + .fold[Seq[RichCustomField]](Nil)(_.customFields) + .map(cf => (cf.name, cf.value, cf.order)) cfs <- (caseTemplateCustomFields ++ customFields).toTry { case (name, value, order) => createCustomField(createdCase, name, value, order) } caseTemplateTags = caseTemplate.fold[Seq[Tag with Entity]](Nil)(_.tags) allTags = tags ++ caseTemplateTags @@ -152,8 +153,8 @@ class CaseSrv @Inject() ( } yield () } - def addObservable(`case`: Case with Entity, richObservable: RichObservable)( - implicit graph: Graph, + def addObservable(`case`: Case with Entity, richObservable: RichObservable)(implicit + graph: Graph, authContext: AuthContext ): Try[Unit] = { val alreadyExistInThatCase = observableSrv @@ -206,8 +207,8 @@ class CaseSrv @Inject() ( .map(_ => ()) } - def setOrCreateCustomField(`case`: Case with Entity, customFieldName: String, value: Option[Any], order: Option[Int])( - implicit graph: Graph, + def setOrCreateCustomField(`case`: Case with Entity, customFieldName: String, value: Option[Any], order: Option[Int])(implicit + graph: Graph, authContext: AuthContext ): Try[Unit] = { val cfv = get(`case`).customFields(customFieldName) @@ -373,7 +374,7 @@ object CaseOps { def richCaseWithCustomRenderer[D, G, C <: Converter[D, G]]( entityRenderer: Traversal.V[Case] => Traversal[D, G, C] - )(implicit authContext: AuthContext) = + )(implicit authContext: AuthContext): Traversal[(RichCase, D), JMap[String, Any], Converter[(RichCase, D), JMap[String, Any]]] = traversal .project( _.by diff --git a/thehive/app/org/thp/thehive/services/notification/notifiers/Webhook.scala b/thehive/app/org/thp/thehive/services/notification/notifiers/Webhook.scala index d004645668..ad21bf9974 100644 --- a/thehive/app/org/thp/thehive/services/notification/notifiers/Webhook.scala +++ b/thehive/app/org/thp/thehive/services/notification/notifiers/Webhook.scala @@ -64,10 +64,11 @@ class WebhookProvider @Inject() ( override def apply(config: Configuration): Try[Notifier] = for { name <- config.getOrFail[String]("endpoint") - config <- webhookConfigs - .get - .find(_.name == name) - .fold[Try[WebhookNotification]](Failure(BadConfigurationError(s"Webhook configuration `$name` not found`")))(Success.apply) + config <- + webhookConfigs + .get + .find(_.name == name) + .fold[Try[WebhookNotification]](Failure(BadConfigurationError(s"Webhook configuration `$name` not found`")))(Success.apply) } yield new Webhook(config, auditSrv, customFieldSrv, mat, ec) } @@ -111,7 +112,7 @@ class Webhook( def observableToJson: Traversal.V[Observable] => Traversal[JsObject, JMap[String, Any], Converter[JsObject, JMap[String, Any]]] = _.project( _.by(_.richObservable.domainMap(_.toJson)) - .by(_.coalesce(o => caseToJson(o.`case`), o => alertToJson(o.alert))) + .by(_.coalesceMulti(o => caseToJson(o.`case`), o => alertToJson(o.alert))) ).domainMap { case (obs, caseOrAlert) => obs.as[JsObject] + ((caseOrAlert \ "_type").asOpt[String].getOrElse("") -> caseOrAlert) } @@ -134,20 +135,20 @@ class Webhook( ).domainMap { case (vertex, _) => JsObject( - UMapping.string.optional.getProperty(vertex, "workerId").map(v => "analyzerId" -> JsString(v)).toList ::: - UMapping.string.optional.getProperty(vertex, "workerName").map(v => "analyzerName" -> JsString(v)).toList ::: + UMapping.string.optional.getProperty(vertex, "workerId").map(v => "analyzerId" -> JsString(v)).toList ::: + UMapping.string.optional.getProperty(vertex, "workerName").map(v => "analyzerName" -> JsString(v)).toList ::: UMapping.string.optional.getProperty(vertex, "workerDefinition").map(v => "analyzerDefinition" -> JsString(v)).toList ::: - UMapping.string.optional.getProperty(vertex, "status").map(v => "status" -> JsString(v)).toList ::: - UMapping.date.optional.getProperty(vertex, "startDate").map(v => "startDate" -> JsNumber(v.getTime)).toList ::: - UMapping.date.optional.getProperty(vertex, "endDate").map(v => "endDate" -> JsNumber(v.getTime)).toList ::: - UMapping.string.optional.getProperty(vertex, "cortexId").map(v => "cortexId" -> JsString(v)).toList ::: - UMapping.string.optional.getProperty(vertex, "cortexJobId").map(v => "cortexJobId" -> JsString(v)).toList ::: - UMapping.string.optional.getProperty(vertex, "_createdBy").map(v => "_createdBy" -> JsString(v)).toList ::: - UMapping.date.optional.getProperty(vertex, "_createdAt").map(v => "_createdAt" -> JsNumber(v.getTime)).toList ::: - UMapping.string.optional.getProperty(vertex, "_updatedBy").map(v => "_updatedBy" -> JsString(v)).toList ::: - UMapping.date.optional.getProperty(vertex, "_updatedAt").map(v => "_updatedAt" -> JsNumber(v.getTime)).toList ::: - UMapping.string.optional.getProperty(vertex, "_type").map(v => "_type" -> JsString(v)).toList ::: - UMapping.string.optional.getProperty(vertex, "_id").map(v => "_id" -> JsString(v)).toList + UMapping.string.optional.getProperty(vertex, "status").map(v => "status" -> JsString(v)).toList ::: + UMapping.date.optional.getProperty(vertex, "startDate").map(v => "startDate" -> JsNumber(v.getTime)).toList ::: + UMapping.date.optional.getProperty(vertex, "endDate").map(v => "endDate" -> JsNumber(v.getTime)).toList ::: + UMapping.string.optional.getProperty(vertex, "cortexId").map(v => "cortexId" -> JsString(v)).toList ::: + UMapping.string.optional.getProperty(vertex, "cortexJobId").map(v => "cortexJobId" -> JsString(v)).toList ::: + UMapping.string.optional.getProperty(vertex, "_createdBy").map(v => "_createdBy" -> JsString(v)).toList ::: + UMapping.date.optional.getProperty(vertex, "_createdAt").map(v => "_createdAt" -> JsNumber(v.getTime)).toList ::: + UMapping.string.optional.getProperty(vertex, "_updatedBy").map(v => "_updatedBy" -> JsString(v)).toList ::: + UMapping.date.optional.getProperty(vertex, "_updatedAt").map(v => "_updatedAt" -> JsNumber(v.getTime)).toList ::: + UMapping.string.optional.getProperty(vertex, "_type").map(v => "_type" -> JsString(v)).toList ::: + UMapping.string.optional.getProperty(vertex, "_id").map(v => "_id" -> JsString(v)).toList ) } @@ -165,7 +166,7 @@ class Webhook( .option("Job", jobToJson) .none(_.constant2[JsObject, JMap[String, Any]](JsObject.empty)) ), - _.constant2[JsObject, JMap[String, Any]](JsObject.empty) + JsObject.empty ) } diff --git a/thehive/app/org/thp/thehive/services/th3/Aggregation.scala b/thehive/app/org/thp/thehive/services/th3/Aggregation.scala index 9842199ed2..00209b1289 100644 --- a/thehive/app/org/thp/thehive/services/th3/Aggregation.scala +++ b/thehive/app/org/thp/thehive/services/th3/Aggregation.scala @@ -165,7 +165,7 @@ case class AggSum(aggName: Option[String], fieldName: String) extends Aggregatio .sum .domainMap(sum => Output(Json.obj(name -> JsNumber(BigDecimal(sum.toString))))) .castDomain[Output[_]], - _.constant2(Output(Json.obj(name -> JsNull))) + Output(Json.obj(name -> JsNull)) ) } } @@ -187,7 +187,7 @@ case class AggAvg(aggName: Option[String], fieldName: String) extends Aggregatio .select(fieldPath, t) .mean .domainMap(avg => Output(Json.obj(name -> avg.asInstanceOf[Double]))), - _.constant2(Output(Json.obj(name -> JsNull))) + Output(Json.obj(name -> JsNull)) ) } } @@ -210,7 +210,7 @@ case class AggMin(aggName: Option[String], fieldName: String) extends Aggregatio .select(fieldPath, t) .min .domainMap(min => Output(Json.obj(name -> property.mapping.selectRenderer.toJson(min)))), - _.constant2(Output(Json.obj(name -> JsNull))) + Output(Json.obj(name -> JsNull)) ) } } @@ -233,7 +233,7 @@ case class AggMax(aggName: Option[String], fieldName: String) extends Aggregatio .select(fieldPath, t) .max .domainMap(max => Output(Json.obj(name -> property.mapping.selectRenderer.toJson(max)))), - _.constant2(Output(Json.obj(name -> JsNull))) + Output(Json.obj(name -> JsNull)) ) } }