Skip to content

Commit

Permalink
#1483 Refactoring of properties and queries
Browse files Browse the repository at this point in the history
  • Loading branch information
To-om committed Sep 7, 2020
1 parent 1628ecb commit ee07bc9
Show file tree
Hide file tree
Showing 54 changed files with 1,681 additions and 1,612 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package org.thp.thehive.connector.cortex.controllers.v0
import javax.inject.{Inject, Named, Singleton}
import org.thp.scalligraph.auth.AuthContext
import org.thp.scalligraph.controllers.{Entrypoint, FieldsParser}
import org.thp.scalligraph.models.{Database, Entity, Schema}
import org.thp.scalligraph.query.{ParamQuery, PublicProperty, Query, SubType}
import org.thp.scalligraph.models.{Database, Entity, UMapping}
import org.thp.scalligraph.query._
import org.thp.scalligraph.traversal.TraversalOps._
import org.thp.scalligraph.traversal.{IteratorOutput, Traversal}
import org.thp.thehive.connector.cortex.controllers.v0.Conversion._
Expand All @@ -13,46 +13,71 @@ import org.thp.thehive.connector.cortex.models.{Action, ActionContext, RichActio
import org.thp.thehive.connector.cortex.services.ActionOps._
import org.thp.thehive.connector.cortex.services.{ActionSrv, EntityHelper}
import org.thp.thehive.controllers.v0.Conversion.{toObjectType, _}
import org.thp.thehive.controllers.v0.{AuditRenderer, IdOrName, OutputParam, QueryableCtrl}
import org.thp.thehive.controllers.v0._
import org.thp.thehive.models._
import org.thp.thehive.services._
import play.api.libs.json.{JsObject, Json, OWrites}
import play.api.mvc.{AnyContent, Results, Action => PlayAction}

import scala.concurrent.{ExecutionContext, Future}
import scala.reflect.runtime.{universe => ru}

@Singleton
class ActionCtrl @Inject() (
entrypoint: Entrypoint,
@Named("with-thehive-schema") db: Database,
properties: Properties,
override val entrypoint: Entrypoint,
@Named("with-thehive-schema") override val db: Database,
actionSrv: ActionSrv,
entityHelper: EntityHelper,
caseSrv: CaseSrv,
taskSrv: TaskSrv,
observableSrv: ObservableSrv,
logSrv: LogSrv,
alertSrv: AlertSrv,
schema: Schema,
implicit val executionContext: ExecutionContext
) extends QueryableCtrl
with AuditRenderer {
implicit val executionContext: ExecutionContext,
override val queryExecutor: QueryExecutor,
override val publicData: PublicAction
) extends AuditRenderer
with QueryCtrl {

implicit val entityWrites: OWrites[Entity] = OWrites[Entity] { entity =>
db.roTransaction { implicit graph =>
entity match {
case c: Case => caseToJson(caseSrv.get(c)).getOrFail("Case")
case t: Task => taskToJson(taskSrv.get(t)).getOrFail("Task")
case o: Observable => observableToJson(observableSrv.get(o)).getOrFail("Observable")
case l: Log => logToJson(logSrv.get(l)).getOrFail("Log")
case a: Alert => alertToJson(alertSrv.get(a)).getOrFail("Alert")
}
entity match {
case c: Case => caseToJson(caseSrv.get(c)).getOrFail("Case")
case t: Task => taskToJson(taskSrv.get(t)).getOrFail("Task")
case o: Observable => observableToJson(observableSrv.get(o)).getOrFail("Observable")
case l: Log => logToJson(logSrv.get(l)).getOrFail("Log")
case a: Alert => alertToJson(alertSrv.get(a)).getOrFail("Alert")
}
.getOrElse(Json.obj("_type" -> entity._label, "_id" -> entity._id))
}.getOrElse(Json.obj("_type" -> entity._label, "_id" -> entity._id))
}

override val entityName: String = "action"
override val publicProperties: List[PublicProperty[_, _]] = properties.action
def create: PlayAction[AnyContent] =
entrypoint("create action")
.extract("action", FieldsParser[InputAction])
.asyncAuth { implicit request =>
val action: InputAction = request.body("action")
val tryEntity = db.roTransaction { implicit graph =>
entityHelper.get(toObjectType(action.objectType), action.objectId, Permissions.manageAction)
}
for {
entity <- Future.fromTry(tryEntity)
action <- actionSrv.execute(entity, action.cortexId, action.responderId, action.parameters.getOrElse(JsObject.empty))
} yield Results.Ok(action.toJson)
}

def getByEntity(objectType: String, objectId: String): PlayAction[AnyContent] =
entrypoint("get by entity")
.authRoTransaction(db) { implicit request => implicit graph =>
for {
entity <- entityHelper.get(toObjectType(objectType), objectId, Permissions.manageAction)
} yield Results.Ok(actionSrv.listForEntity(entity._id).toJson)
}
}

@Singleton
class PublicAction @Inject() (actionSrv: ActionSrv) extends PublicData {

override val entityName: String = "action"
override val initialQuery: Query =
Query.init[Traversal.V[Action]]("listAction", (graph, authContext) => actionSrv.startTraversal(graph).visible(authContext))
override val getQuery: ParamQuery[IdOrName] = Query.initWithParam[IdOrName, Traversal.V[Action]](
Expand All @@ -66,7 +91,6 @@ class ActionCtrl @Inject() (
(range, actionSteps, _) => actionSteps.richPage(range.from, range.to, withTotal = true)(_.richAction)
)
override val outputQuery: Query = Query.output[RichAction, Traversal.V[Action]](_.richAction)

val actionsQuery: Query = new Query {
override val name: String = "actions"
override def checkFrom(t: ru.Type): Boolean =
Expand All @@ -81,26 +105,15 @@ class ActionCtrl @Inject() (
}

override val extraQueries: Seq[ParamQuery[_]] = Seq(actionsQuery)

def create: PlayAction[AnyContent] =
entrypoint("create action")
.extract("action", FieldsParser[InputAction])
.asyncAuth { implicit request =>
val action: InputAction = request.body("action")
val tryEntity = db.roTransaction { implicit graph =>
entityHelper.get(toObjectType(action.objectType), action.objectId, Permissions.manageAction)
}
for {
entity <- Future.fromTry(tryEntity)
action <- actionSrv.execute(entity, action.cortexId, action.responderId, action.parameters.getOrElse(JsObject.empty))
} yield Results.Ok(action.toJson)
}

def getByEntity(objectType: String, objectId: String): PlayAction[AnyContent] =
entrypoint("get by entity")
.authRoTransaction(db) { implicit request => implicit graph =>
for {
entity <- entityHelper.get(toObjectType(objectType), objectId, Permissions.manageAction)
} yield Results.Ok(actionSrv.listForEntity(entity._id).toJson)
}
override val publicProperties: PublicProperties =
PublicPropertyListBuilder[Action]
.property("responderId", UMapping.string)(_.field.readonly)
.property("objectType", UMapping.string)(_.select(_.context.domainMap(o => fromObjectType(o._label))).readonly)
.property("status", UMapping.string)(_.field.readonly)
.property("startDate", UMapping.date)(_.field.readonly)
.property("objectId", UMapping.id)(_.select(_.out[ActionContext]._id).readonly)
.property("responderName", UMapping.string.optional)(_.field.readonly)
.property("cortexId", UMapping.string.optional)(_.field.readonly)
.property("tlp", UMapping.int.optional)(_.field.readonly)
.build
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,30 @@ import java.util.zip.ZipFile
import com.google.inject.name.Named
import javax.inject.{Inject, Singleton}
import org.thp.scalligraph.controllers.{Entrypoint, FFile, FieldsParser}
import org.thp.scalligraph.models.{Database, Entity}
import org.thp.scalligraph.query.{ParamQuery, PropertyUpdater, PublicProperty, Query}
import org.thp.scalligraph.models.{Database, Entity, UMapping}
import org.thp.scalligraph.query._
import org.thp.scalligraph.traversal.TraversalOps._
import org.thp.scalligraph.traversal.{IteratorOutput, Traversal}
import org.thp.thehive.connector.cortex.controllers.v0.Conversion._
import org.thp.thehive.connector.cortex.dto.v0.InputAnalyzerTemplate
import org.thp.thehive.connector.cortex.models.AnalyzerTemplate
import org.thp.thehive.connector.cortex.services.AnalyzerTemplateSrv
import org.thp.thehive.controllers.v0.Conversion._
import org.thp.thehive.controllers.v0.{IdOrName, OutputParam, QueryableCtrl}
import org.thp.thehive.controllers.v0.{IdOrName, OutputParam, PublicData, QueryCtrl}
import org.thp.thehive.models.Permissions
import play.api.Logger
import play.api.libs.json.{JsFalse, JsObject, JsTrue}
import play.api.mvc.{Action, AnyContent, Results}

import scala.util.{Failure, Success}

@Singleton
class AnalyzerTemplateCtrl @Inject() (
entrypoint: Entrypoint,
@Named("with-thehive-cortex-schema") db: Database,
properties: Properties,
analyzerTemplateSrv: AnalyzerTemplateSrv
) extends QueryableCtrl {

lazy val logger: Logger = Logger(getClass)
override val entityName: String = "analyzerTemplate"
override val publicProperties: List[PublicProperty[_, _]] = properties.analyzerTemplate
override val initialQuery: Query =
Query.init[Traversal.V[AnalyzerTemplate]]("listAnalyzerTemplate", (graph, _) => analyzerTemplateSrv.startTraversal(graph))
override val getQuery: ParamQuery[IdOrName] = Query.initWithParam[IdOrName, Traversal.V[AnalyzerTemplate]](
"getReportTemplace",
FieldsParser[IdOrName],
(param, graph, _) => analyzerTemplateSrv.get(param.idOrName)(graph)
)
override val pageQuery: ParamQuery[OutputParam] =
Query.withParam[OutputParam, Traversal.V[AnalyzerTemplate], IteratorOutput](
"page",
FieldsParser[OutputParam],
(range, analyzerTemplateTraversal, _) => analyzerTemplateTraversal.page(range.from, range.to, withTotal = true)
)
override val outputQuery: Query = Query.output[AnalyzerTemplate with Entity]
override val entrypoint: Entrypoint,
@Named("with-thehive-cortex-schema") override val db: Database,
analyzerTemplateSrv: AnalyzerTemplateSrv,
override val queryExecutor: QueryExecutor,
override val publicData: PublicAnalyzerTemplate
) extends QueryCtrl {

def get(id: String): Action[AnyContent] =
entrypoint("get content")
Expand Down Expand Up @@ -97,7 +79,7 @@ class AnalyzerTemplateCtrl @Inject() (

def update(id: String): Action[AnyContent] =
entrypoint("update template")
.extract("template", FieldsParser.update("template", properties.analyzerTemplate))
.extract("template", FieldsParser.update("template", publicData.publicProperties))
.authPermittedTransaction(db, Permissions.manageAnalyzerTemplate) { implicit request => implicit graph =>
val propertyUpdaters: Seq[PropertyUpdater] = request.body("template")

Expand All @@ -108,3 +90,27 @@ class AnalyzerTemplateCtrl @Inject() (

}
}

@Singleton
class PublicAnalyzerTemplate @Inject() (analyzerTemplateSrv: AnalyzerTemplateSrv) extends PublicData {
override val entityName: String = "analyzerTemplate"
override val initialQuery: Query =
Query.init[Traversal.V[AnalyzerTemplate]]("listAnalyzerTemplate", (graph, _) => analyzerTemplateSrv.startTraversal(graph))
override val getQuery: ParamQuery[IdOrName] = Query.initWithParam[IdOrName, Traversal.V[AnalyzerTemplate]](
"getReportTemplate",
FieldsParser[IdOrName],
(param, graph, _) => analyzerTemplateSrv.get(param.idOrName)(graph)
)
override val pageQuery: ParamQuery[OutputParam] =
Query.withParam[OutputParam, Traversal.V[AnalyzerTemplate], IteratorOutput](
"page",
FieldsParser[OutputParam],
(range, analyzerTemplateTraversal, _) => analyzerTemplateTraversal.page(range.from, range.to, withTotal = true)
)
override val outputQuery: Query = Query.output[AnalyzerTemplate with Entity]
override val publicProperties: PublicProperties = PublicPropertyListBuilder[AnalyzerTemplate]
.property("analyzerId", UMapping.string)(_.rename("workerId").readonly)
.property("reportType", UMapping.string)(_.field.readonly)
.property("content", UMapping.string)(_.field.updatable)
.build
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,15 @@ import scala.reflect.runtime.{universe => ru}

@Singleton
class CortexQueryExecutor @Inject() (
queryCtrlBuilder: QueryCtrlBuilder,
@Named("with-thehive-cortex-schema") implicit val db: Database,
jobCtrl: JobCtrl,
reportCtrl: AnalyzerTemplateCtrl,
actionCtrl: ActionCtrl,
analyzerTemplateCtrl: AnalyzerTemplateCtrl
@Named("with-thehive-cortex-schema") implicit override val db: Database,
job: PublicJob,
report: PublicAnalyzerTemplate,
action: PublicAction,
analyzerTemplate: PublicAnalyzerTemplate
) extends QueryExecutor {
lazy val controllers: List[QueryableCtrl] = actionCtrl :: reportCtrl :: jobCtrl :: analyzerTemplateCtrl :: Nil
lazy val controllers: List[PublicData] = action :: report :: job :: analyzerTemplate :: Nil

override lazy val publicProperties: List[PublicProperty[_, _]] = controllers.flatMap(_.publicProperties)
override lazy val publicProperties: PublicProperties = controllers.map(_.publicProperties).reduce(_ ++ _)

override lazy val queries: Seq[ParamQuery[_]] =
controllers.map(_.initialQuery) :::
Expand Down Expand Up @@ -56,17 +55,12 @@ class CortexQueryExecutor @Inject() (
}

override val version: (Int, Int) = 0 -> 1

val job: QueryCtrl = queryCtrlBuilder(jobCtrl, this)
val report: QueryCtrl = queryCtrlBuilder(analyzerTemplateCtrl, this)
val action: QueryCtrl = queryCtrlBuilder(actionCtrl, this)
val analyzerTemplate: QueryCtrl = queryCtrlBuilder(analyzerTemplateCtrl, this)
}

class CortexParentIdInputFilter(parentId: String) extends InputQuery[Traversal.Unk, Traversal.Unk] {
override def apply(
db: Database,
publicProperties: List[PublicProperty[_, _]],
publicProperties: PublicProperties,
traversalType: ru.Type,
traversal: Traversal.Unk,
authContext: AuthContext
Expand All @@ -84,7 +78,7 @@ class CortexParentIdInputFilter(parentId: String) extends InputQuery[Traversal.U
class CortexParentQueryInputFilter(parentFilter: InputQuery[Traversal.Unk, Traversal.Unk]) extends InputQuery[Traversal.Unk, Traversal.Unk] {
override def apply(
db: Database,
publicProperties: List[PublicProperty[_, _]],
publicProperties: PublicProperties,
traversalType: ru.Type,
traversal: Traversal.Unk,
authContext: AuthContext
Expand All @@ -106,7 +100,7 @@ class CortexChildQueryInputFilter(childType: String, childFilter: InputQuery[Tra
extends InputQuery[Traversal.Unk, Traversal.Unk] {
override def apply(
db: Database,
publicProperties: List[PublicProperty[_, _]],
publicProperties: PublicProperties,
traversalType: ru.Type,
traversal: Traversal.Unk,
authContext: AuthContext
Expand Down
Loading

0 comments on commit ee07bc9

Please sign in to comment.