diff --git a/thehive/app/org/thp/thehive/controllers/v0/ObservableCtrl.scala b/thehive/app/org/thp/thehive/controllers/v0/ObservableCtrl.scala index 5283de1908..836b4aee55 100644 --- a/thehive/app/org/thp/thehive/controllers/v0/ObservableCtrl.scala +++ b/thehive/app/org/thp/thehive/controllers/v0/ObservableCtrl.scala @@ -417,7 +417,7 @@ class PublicObservable( ) .property("message", UMapping.string)(_.field.updatable) .property("tlp", UMapping.int)(_.field.updatable) - .property("dataType", UMapping.string)(_.field.readonly) + .property("dataType", UMapping.string)(_.field.updatable) .property("data", UMapping.string.optional)(_.field.readonly) .property("attachment.name", UMapping.string.optional)(_.select(_.attachments.value(_.name)).readonly) .property("attachment.hashes", UMapping.hash.sequence)(_.select(_.attachments.value(_.hashes)).readonly) diff --git a/thehive/app/org/thp/thehive/controllers/v1/Properties.scala b/thehive/app/org/thp/thehive/controllers/v1/Properties.scala index b5a94d8fea..05b5efcc0d 100644 --- a/thehive/app/org/thp/thehive/controllers/v1/Properties.scala +++ b/thehive/app/org/thp/thehive/controllers/v1/Properties.scala @@ -442,7 +442,7 @@ class Properties( ) .property("message", UMapping.string)(_.field.updatable) .property("tlp", UMapping.int)(_.field.updatable) - .property("dataType", UMapping.string)(_.field.readonly) + .property("dataType", UMapping.string)(_.field.updatable) .property("data", UMapping.string.optional)(_.field.readonly) .property("attachment.name", UMapping.string.optional)(_.select(_.attachments.value(_.name)).readonly) .property("attachment.hashes", UMapping.hash.sequence)(_.select(_.attachments.value(_.hashes)).readonly) diff --git a/thehive/app/org/thp/thehive/services/ObservableSrv.scala b/thehive/app/org/thp/thehive/services/ObservableSrv.scala index ef8299344f..7985d280e6 100644 --- a/thehive/app/org/thp/thehive/services/ObservableSrv.scala +++ b/thehive/app/org/thp/thehive/services/ObservableSrv.scala @@ -3,7 +3,7 @@ package org.thp.thehive.services import org.apache.tinkerpop.gremlin.process.traversal.P import org.apache.tinkerpop.gremlin.structure.Vertex import org.thp.scalligraph.auth.{AuthContext, Permission} -import org.thp.scalligraph.controllers.FFile +import org.thp.scalligraph.controllers.{FFile, FPath} import org.thp.scalligraph.models.{Database, Entity, UMapping} import org.thp.scalligraph.query.PropertyUpdater import org.thp.scalligraph.services._ @@ -173,14 +173,30 @@ class ObservableSrv( override def update( traversal: Traversal.V[Observable], propertyUpdaters: Seq[PropertyUpdater] - )(implicit graph: Graph, authContext: AuthContext): Try[(Traversal.V[Observable], JsObject)] = - auditSrv.mergeAudits(super.update(traversal, propertyUpdaters)) { - case (observableSteps, updatedFields) => - observableSteps - .clone() - .getOrFail("Observable") - .flatMap(observable => auditSrv.observable.update(observable, updatedFields)) + )(implicit graph: Graph, authContext: AuthContext): Try[(Traversal.V[Observable], JsObject)] = { + + val canUpdateDataType = propertyUpdaters.find(_.path == FPath("dataType")) match { + case Some(newDataTypeProp) => + for { + obs <- traversal.clone().getOrFail("Observable") + currentDatatype <- observableTypeSrv.getByName(obs.dataType).getOrFail("ObservableType") + newDataType <- observableTypeSrv.getByName(newDataTypeProp.value.toString).getOrFail("ObservableType") + isSameType = currentDatatype.isAttachment == newDataType.isAttachment + _ <- if (isSameType) Success(()) else Failure(BadRequestError("Can not update dataType: isAttachment does not match")) + } yield () + case None => Success(()) } + + canUpdateDataType.flatMap { _ => + auditSrv.mergeAudits(super.update(traversal, propertyUpdaters)) { + case (observableSteps, updatedFields) => + observableSteps + .clone() + .getOrFail("Observable") + .flatMap(observable => auditSrv.observable.update(observable, updatedFields)) + } + } + } } trait ObservableOpsNoDeps { _: TheHiveOpsNoDeps =>