Skip to content

Commit

Permalink
#1316 Include organisation list in current user API
Browse files Browse the repository at this point in the history
  • Loading branch information
To-om committed May 12, 2020
1 parent d78b29a commit 50c9893
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 6 deletions.
2 changes: 1 addition & 1 deletion ScalliGraph
Submodule ScalliGraph updated 1 files
+2 −0 build.sbt
8 changes: 7 additions & 1 deletion dto/src/main/scala/org/thp/thehive/dto/v1/User.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ object InputUser {
implicit val writes: Writes[InputUser] = Json.writes[InputUser]
}

case class OutputOrganisationRole(organisation: String, role: String)
object OutputOrganisationRole {
implicit val format: OFormat[OutputOrganisationRole] = Json.format[OutputOrganisationRole]
}

case class OutputUser(
_id: String,
_createdBy: String,
Expand All @@ -27,7 +32,8 @@ case class OutputUser(
profile: String,
permissions: Set[String],
organisation: String,
avatar: Option[String]
avatar: Option[String],
organisations: Seq[OutputOrganisationRole]
)

object OutputUser {
Expand Down
15 changes: 13 additions & 2 deletions thehive/app/org/thp/thehive/controllers/v1/Conversion.scala
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,23 @@ object Conversion {
_.into[OutputUser]
.withFieldComputed(_.permissions, _.permissions.asInstanceOf[Set[String]])
.withFieldComputed(_.hasKey, _.apikey.isDefined)
// .withFieldComputed(_.permissions, _.permissions)
// .withFieldConst(_.permissions, Set.empty[String]
.withFieldConst(_.organisations, Nil)
.withFieldComputed(_.avatar, user => user.avatar.map(avatar => s"/api/v1/user/${user._id}/avatar/$avatar"))
.transform
)

implicit val userWithOrganisationOutput: Outputer.Aux[(RichUser, Seq[(String, String)]), OutputUser] =
Outputer[(RichUser, Seq[(String, String)]), OutputUser] { userWithOrganisations =>
val (user, organisations) = userWithOrganisations
user
.into[OutputUser]
.withFieldComputed(_.permissions, _.permissions.asInstanceOf[Set[String]])
.withFieldComputed(_.hasKey, _.apikey.isDefined)
.withFieldConst(_.organisations, organisations.map { case (org, role) => OutputOrganisationRole(org, role) })
.withFieldComputed(_.avatar, user => user.avatar.map(avatar => s"/api/v1/user/${user._id}/avatar/$avatar"))
.transform
}

implicit val profileOutput: Outputer.Aux[Profile with Entity, OutputProfile] = Outputer[Profile with Entity, OutputProfile](profile =>
profile
.asInstanceOf[Profile]
Expand Down
3 changes: 2 additions & 1 deletion thehive/app/org/thp/thehive/controllers/v1/UserCtrl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import play.api.http.HttpEntity
import play.api.libs.json.{JsNull, JsObject, Json}
import play.api.mvc._

import scala.collection.JavaConverters._
import scala.concurrent.ExecutionContext
import scala.util.{Failure, Success, Try}

Expand Down Expand Up @@ -63,7 +64,7 @@ class UserCtrl @Inject() (
.authRoTransaction(db) { implicit request => implicit graph =>
userSrv
.current
.richUser(request.organisation)
.richUserWithCustomRenderer(request.organisation, _.organisationWithRole.map(_.asScala.toSeq))
.getOrFail()
.map(user => Results.Ok(user.toJson))
}
Expand Down
39 changes: 38 additions & 1 deletion thehive/app/org/thp/thehive/services/UserSrv.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.thp.thehive.services

import java.util.{List => JList}
import java.util.regex.Pattern

import gremlin.scala._
Expand All @@ -10,7 +11,7 @@ import org.thp.scalligraph.models._
import org.thp.scalligraph.query.PropertyUpdater
import org.thp.scalligraph.services._
import org.thp.scalligraph.steps.StepsOps._
import org.thp.scalligraph.steps.{Traversal, VertexSteps}
import org.thp.scalligraph.steps.{Traversal, TraversalLike, VertexSteps}
import org.thp.scalligraph.{BadRequestError, EntitySteps, RichOptionTry}
import org.thp.thehive.controllers.v1.Conversion._
import org.thp.thehive.models._
Expand Down Expand Up @@ -190,6 +191,15 @@ class UserSteps(raw: GremlinScala[Vertex])(implicit db: Database, graph: Graph)
else organisations0(requiredPermission)
}

def organisationWithRole: Traversal[JList[(String, String)], JList[(String, String)]] =
this
.outTo[UserRole]
.project(
_.apply(By(__[Vertex].outTo[RoleOrganisation].value[String]("name")))
.and(By(__[Vertex].outTo[RoleProfile].value[String]("name")))
)
.fold

def config: ConfigSteps = new ConfigSteps(raw.outTo[UserConfig])

def getAuthContext(requestId: String, organisation: Option[String]): Traversal[AuthContext, AuthContext] = {
Expand Down Expand Up @@ -251,6 +261,33 @@ class UserSteps(raw: GremlinScala[Vertex])(implicit db: Database, graph: Graph)
RichUser(user.as[User], avatar, "", Set.empty, organisation)
}

def richUserWithCustomRenderer[A](organisation: String, entityRenderer: UserSteps => TraversalLike[_, A])(
implicit authContext: AuthContext
): Traversal[(RichUser, A), (RichUser, A)] =
this
.project(
_.apply(By[Vertex]())
.and(
By(
__[Vertex].coalesce(
_.outTo[UserRole].filter(_.outTo[RoleOrganisation].has(Key("name") of organisation)).outTo[RoleProfile].fold(),
_.constant(List.empty[Vertex].asJava)
)
)
)
.and(By(__[Vertex].outTo[UserAttachment].fold()))
.and(By(entityRenderer(newInstance(__[Vertex])).raw))
)
.collect {
case (user, profiles, attachment, renderedEntity) if profiles.size() == 1 =>
val profile = profiles.get(0).as[Profile]
val avatar = atMostOneOf[Vertex](attachment).map(_.as[Attachment].attachmentId)
RichUser(user.as[User], avatar, profile.name, profile.permissions, organisation) -> renderedEntity
case (user, _, attachment, renderedEntity) =>
val avatar = atMostOneOf[Vertex](attachment).map(_.as[Attachment].attachmentId)
RichUser(user.as[User], avatar, "", Set.empty, organisation) -> renderedEntity
}

def role: RoleSteps = new RoleSteps(raw.outTo[UserRole])

def avatar: AttachmentSteps = new AttachmentSteps(raw.outTo[UserAttachment])
Expand Down

0 comments on commit 50c9893

Please sign in to comment.