diff --git a/thehive/app/org/thp/thehive/controllers/v0/CaseCtrl.scala b/thehive/app/org/thp/thehive/controllers/v0/CaseCtrl.scala index 5dd56482af..705cb35e95 100644 --- a/thehive/app/org/thp/thehive/controllers/v0/CaseCtrl.scala +++ b/thehive/app/org/thp/thehive/controllers/v0/CaseCtrl.scala @@ -5,6 +5,7 @@ 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.traversal.TraversalOps._ import org.thp.scalligraph.traversal.{IteratorOutput, Traversal} import org.thp.thehive.controllers.v0.Conversion._ @@ -307,10 +308,30 @@ class PublicCase @Inject() ( .property("computed.handlingDurationInHours", UMapping.long)(_.select(_.handlingDuration.math("_ / 3600000").domainMap(_.toLong)).readonly) .property("computed.handlingDurationInDays", UMapping.long)(_.select(_.handlingDuration.math("_ / 86400000").domainMap(_.toLong)).readonly) .property("viewingOrganisation", UMapping.string)( - _.authSelect((cases, authContext) => cases.organisations.visible(authContext).value(_.name)).readonly + _.select(t => t.value(_.organisationIds).domainMap(organisationSrv.getName(_)(t.graph))) + .filter[String] { + case (_, caseTraversal, _, Right(orgNamePredicate)) => + val organisationId = orgNamePredicate.mapValue(o => organisationSrv.getId(EntityIdOrName(o))(caseTraversal.graph)) + caseTraversal.has(_.organisationIds, organisationId) + case (_, caseTraversal, _, Left(true)) => + caseTraversal + case (_, caseTraversal, _, Left(false)) => + caseTraversal.empty + } + .readonly ) .property("owningOrganisation", UMapping.string)( - _.authSelect((cases, authContext) => cases.origin.visible(authContext).value(_.name)).readonly + _.select(t => t.value(_.owningOrganisation).domainMap(organisationSrv.getName(_)(t.graph))) + .filter[String] { + case (_, caseTraversal, _, Right(orgNamePredicate)) => + val organisationId = orgNamePredicate.mapValue(o => organisationSrv.getId(EntityIdOrName(o))(caseTraversal.graph)) + caseTraversal.has(_.owningOrganisation, organisationId) + case (_, caseTraversal, _, Left(true)) => + caseTraversal + case (_, caseTraversal, _, Left(false)) => + caseTraversal.empty + } + .readonly ) .property("patternId", UMapping.string.sequence)(_.select(_.procedure.pattern.value(_.patternId)).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 8b11e044c4..1284e3a45a 100644 --- a/thehive/app/org/thp/thehive/controllers/v1/Properties.scala +++ b/thehive/app/org/thp/thehive/controllers/v1/Properties.scala @@ -239,10 +239,30 @@ class Properties @Inject() ( .property("computed.handlingDurationInHours", UMapping.long)(_.select(_.handlingDuration.math("_ / 3600000").domainMap(_.toLong)).readonly) .property("computed.handlingDurationInDays", UMapping.long)(_.select(_.handlingDuration.math("_ / 86400000").domainMap(_.toLong)).readonly) .property("viewingOrganisation", UMapping.string)( - _.authSelect((cases, authContext) => cases.organisations.visible(authContext).value(_.name)).readonly + _.select(t => t.value(_.organisationIds).domainMap(organisationSrv.getName(_)(t.graph))) + .filter[String] { + case (_, caseTraversal, _, Right(orgNamePredicate)) => + val organisationId = orgNamePredicate.mapValue(o => organisationSrv.getId(EntityIdOrName(o))(caseTraversal.graph)) + caseTraversal.has(_.organisationIds, organisationId) + case (_, caseTraversal, _, Left(true)) => + caseTraversal + case (_, caseTraversal, _, Left(false)) => + caseTraversal.empty + } + .readonly ) .property("owningOrganisation", UMapping.string)( - _.authSelect((cases, authContext) => cases.origin.visible(authContext).value(_.name)).readonly + _.select(t => t.value(_.owningOrganisation).domainMap(organisationSrv.getName(_)(t.graph))) + .filter[String] { + case (_, caseTraversal, _, Right(orgNamePredicate)) => + val organisationId = orgNamePredicate.mapValue(o => organisationSrv.getId(EntityIdOrName(o))(caseTraversal.graph)) + caseTraversal.has(_.owningOrganisation, organisationId) + case (_, caseTraversal, _, Left(true)) => + caseTraversal + case (_, caseTraversal, _, Left(false)) => + caseTraversal.empty + } + .readonly ) .property("patternId", UMapping.string.sequence)(_.select(_.procedure.pattern.value(_.patternId)).readonly) .build diff --git a/thehive/app/org/thp/thehive/models/Case.scala b/thehive/app/org/thp/thehive/models/Case.scala index 2d12f92754..19e0511c7f 100644 --- a/thehive/app/org/thp/thehive/models/Case.scala +++ b/thehive/app/org/thp/thehive/models/Case.scala @@ -116,7 +116,8 @@ case class Case( assignee: Option[String] = None, number: Int = 0, organisationIds: Set[EntityId] = Set.empty, - caseTemplate: Option[String] = None + caseTemplate: Option[String] = None, + owningOrganisation: EntityId = EntityId.empty ) case class RichCase( diff --git a/thehive/app/org/thp/thehive/models/TheHiveSchemaDefinition.scala b/thehive/app/org/thp/thehive/models/TheHiveSchemaDefinition.scala index 8b5ce6c2e4..32ae88ec67 100644 --- a/thehive/app/org/thp/thehive/models/TheHiveSchemaDefinition.scala +++ b/thehive/app/org/thp/thehive/models/TheHiveSchemaDefinition.scala @@ -486,6 +486,20 @@ class TheHiveSchemaDefinition @Inject() extends Schema with UpdatableSchema { Success(()) } .removeIndex("Data", IndexType.unique, "data") + //=====[release 4.1.4]===== + .addProperty[EntityId]("Case", "owningOrganisation") + .updateGraph("Add owning organisation in case", "Case") { traversal => + traversal + .project( + _.by + .by(_.in("ShareCase").unsafeHas("owner", true).in("OrganisationShare")._id.option) + ) + .foreach { + case (vertex, owningOrganisation) => + owningOrganisation.foreach(id => vertex.property("owningOrganisation", id.value)) + } + Success(()) + } val reflectionClasses = new Reflections( new ConfigurationBuilder() diff --git a/thehive/app/org/thp/thehive/services/CaseSrv.scala b/thehive/app/org/thp/thehive/services/CaseSrv.scala index 0a57502e48..df81f20d61 100644 --- a/thehive/app/org/thp/thehive/services/CaseSrv.scala +++ b/thehive/app/org/thp/thehive/services/CaseSrv.scala @@ -88,7 +88,8 @@ class CaseSrv @Inject() ( caseTemplate = caseTemplate.map(_.name), impactStatus = None, resolutionStatus = None, - tags = tagNames + tags = tagNames, + owningOrganisation = organisationSrv.currentId ) ) _ <- assignee.map(u => caseUserSrv.create(CaseUser(), createdCase, u)).flip diff --git a/thehive/app/org/thp/thehive/services/OrganisationSrv.scala b/thehive/app/org/thp/thehive/services/OrganisationSrv.scala index 0086d8d29a..f94815b8ec 100644 --- a/thehive/app/org/thp/thehive/services/OrganisationSrv.scala +++ b/thehive/app/org/thp/thehive/services/OrganisationSrv.scala @@ -64,7 +64,26 @@ class OrganisationSrv @Inject() ( getId(authContext.organisation) def getId(organisationIdOrName: EntityIdOrName)(implicit graph: Graph): EntityId = - organisationIdOrName.fold(identity, oid => cache.getOrElseUpdate(s"organisation-$oid")(getByName(oid)._id.getOrFail("Organisation").get)) + organisationIdOrName.fold( + identity, + name => + cache.getOrElseUpdate(s"organisation-id-$name") { + val oid = getByName(name)._id.getOrFail("Organisation").get + cache.set(s"organisation-name-$oid", name) + oid + } + ) + + def getName(organisationIdOrName: EntityIdOrName)(implicit graph: Graph): String = + organisationIdOrName.fold( + oid => + cache.getOrElseUpdate(s"organisation-name-$oid") { + val name = getByIds(oid).value(_.name).getOrFail("Organisation").get + cache.set(s"organisation-id-$name", oid) + name + }, + identity + ) def visibleOrganisation(implicit graph: Graph, authContext: AuthContext): Traversal.V[Organisation] = userSrv.current.organisations.visibleOrganisationsFrom