Skip to content

Commit

Permalink
#2010 Add query to list linked cases
Browse files Browse the repository at this point in the history
  • Loading branch information
To-om committed May 28, 2021
1 parent 0ea02cf commit d2f5153
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 20 deletions.
47 changes: 31 additions & 16 deletions thehive/app/org/thp/thehive/controllers/v0/CaseCtrl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import org.apache.tinkerpop.gremlin.process.traversal.P
import org.thp.scalligraph._
import org.thp.scalligraph.controllers.{Entrypoint, FPathElem, FPathEmpty, FieldsParser}
import org.thp.scalligraph.models.{Database, UMapping}
import org.thp.scalligraph.query._
import org.thp.scalligraph.query.PredicateOps._
import org.thp.scalligraph.query._
import org.thp.scalligraph.traversal.TraversalOps._
import org.thp.scalligraph.traversal.{IteratorOutput, Traversal}
import org.thp.scalligraph.traversal.{Converter, IteratorOutput, Traversal}
import org.thp.thehive.controllers.v0.Conversion._
import org.thp.thehive.dto.v0.{InputCase, InputTask}
import org.thp.thehive.dto.v1.InputCustomFieldValue
Expand All @@ -24,6 +24,7 @@ import org.thp.thehive.services._
import play.api.libs.json._
import play.api.mvc.{Action, AnyContent, Results}

import java.util.{Map => JMap}
import javax.inject.{Inject, Named, Singleton}
import scala.util.{Failure, Success}

Expand Down Expand Up @@ -158,19 +159,21 @@ class CaseCtrl @Inject() (

def linkedCases(caseIdOrNumber: String): Action[AnyContent] =
entrypoint("case link")
.authRoTransaction(db) { implicit request => implicit graph =>
val relatedCases = caseSrv
.get(EntityIdOrName(caseIdOrNumber))
.visible(organisationSrv)
.linkedCases
.map {
case (c, o) =>
c.toJson.as[JsObject] +
("linkedWith" -> o.toJson) +
("linksCount" -> JsNumber(o.size))
}

Success(Results.Ok(JsArray(relatedCases)))
.auth { implicit request =>
val src = db.source { implicit graph =>
caseSrv
.get(EntityIdOrName(caseIdOrNumber))
.visible(organisationSrv)
.linkedCases
.domainMap {
case (c, o) =>
c.toJson.as[JsObject] +
("linkedWith" -> o.toJson) +
("linksCount" -> JsNumber(o.size))
}
.toIterator
}
Success(Results.Ok.chunked(src.map(_.toString).intersperse("[", ",", "]"), Some("application/json")))
}
}

Expand Down Expand Up @@ -221,7 +224,19 @@ class PublicCase @Inject() (
),
Query[Traversal.V[Case], Traversal.V[User]]("assignableUsers", (caseSteps, authContext) => caseSteps.assignableUsers(authContext)),
Query[Traversal.V[Case], Traversal.V[Organisation]]("organisations", (caseSteps, authContext) => caseSteps.organisations.visible(authContext)),
Query[Traversal.V[Case], Traversal.V[Alert]]("alerts", (caseSteps, authContext) => caseSteps.alert.visible(organisationSrv)(authContext))
Query[Traversal.V[Case], Traversal.V[Alert]]("alerts", (caseSteps, authContext) => caseSteps.alert.visible(organisationSrv)(authContext)),
Query[Traversal.V[Case], Traversal[JsObject, JMap[String, Any], Converter[JsObject, JMap[String, Any]]]](
"linkedCases",
(caseSteps, authContext) =>
caseSteps
.linkedCases(authContext)
.domainMap {
case (c, o) =>
c.toJson.as[JsObject] +
("linkedWith" -> o.toJson) +
("linksCount" -> JsNumber(o.size))
}
)
)
override val publicProperties: PublicProperties =
PublicPropertyListBuilder[Case]
Expand Down
18 changes: 16 additions & 2 deletions thehive/app/org/thp/thehive/controllers/v1/CaseCtrl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import org.thp.scalligraph.models.Database
import org.thp.scalligraph.query.{ParamQuery, PropertyUpdater, PublicProperties, Query}
import org.thp.scalligraph.services.config.{ApplicationConfig, ConfigItem}
import org.thp.scalligraph.traversal.TraversalOps._
import org.thp.scalligraph.traversal.{IteratorOutput, Traversal}
import org.thp.scalligraph.traversal.{Converter, IteratorOutput, Traversal}
import org.thp.scalligraph.{EntityIdOrName, RichOptionTry, RichSeq}
import org.thp.thehive.controllers.v1.Conversion._
import org.thp.thehive.dto.v1.{InputCase, InputTask}
Expand All @@ -20,8 +20,10 @@ import org.thp.thehive.services.ShareOps._
import org.thp.thehive.services.TaskOps._
import org.thp.thehive.services.UserOps._
import org.thp.thehive.services._
import play.api.libs.json.{JsNumber, JsObject}
import play.api.mvc.{Action, AnyContent, Results}

import java.util.{Map => JMap}
import javax.inject.{Inject, Singleton}

@Singleton
Expand Down Expand Up @@ -88,7 +90,19 @@ class CaseCtrl @Inject() (
alertSrv.startTraversal(caseSteps.graph).has(_.caseId, P.within(caseSteps._id.toSeq: _*)).visible(organisationSrv)(authContext)
),
Query[Traversal.V[Case], Traversal.V[Share]]("shares", (caseSteps, authContext) => caseSteps.shares.visible(authContext)),
Query[Traversal.V[Case], Traversal.V[Procedure]]("procedures", (caseSteps, _) => caseSteps.procedure)
Query[Traversal.V[Case], Traversal.V[Procedure]]("procedures", (caseSteps, _) => caseSteps.procedure),
Query[Traversal.V[Case], Traversal[JsObject, JMap[String, Any], Converter[JsObject, JMap[String, Any]]]](
"linkedCases",
(caseSteps, authContext) =>
caseSteps
.linkedCases(authContext)
.domainMap {
case (c, o) =>
c.toJson.as[JsObject] +
("linkedWith" -> o.toJson) +
("linksCount" -> JsNumber(o.size))
}
)
)

def create: Action[AnyContent] =
Expand Down
5 changes: 3 additions & 2 deletions thehive/app/org/thp/thehive/services/CaseSrv.scala
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,9 @@ object CaseOps {
// .in[AuditContext]
// .v[Audit]

def linkedCases(implicit authContext: AuthContext): Seq[(RichCase, Seq[RichObservable])] = {
def linkedCases(implicit
authContext: AuthContext
): Traversal[(RichCase, Seq[RichObservable]), JMap[String, Any], Converter[(RichCase, Seq[RichObservable]), JMap[String, Any]]] = {
val originCaseLabel = StepLabel.v[Case]
val observableLabel = StepLabel.v[Observable] // TODO add similarity on attachment
traversal
Expand All @@ -608,7 +610,6 @@ object CaseOps {
.group(_.by, _.by(_.select(observableLabel).richObservable.fold))
.unfold
.project(_.by(_.selectKeys.richCase).by(_.selectValues))
.toSeq
}

def isShared: Traversal[Boolean, Boolean, Identity[Boolean]] =
Expand Down

0 comments on commit d2f5153

Please sign in to comment.