aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlad <vlad@drivergrp.com>2016-08-03 19:58:45 -0700
committervlad <vlad@drivergrp.com>2016-08-03 19:58:45 -0700
commit350f0bd10e65c3d60dfab546d3a375ff3990a614 (patch)
treea4eb07869489ab523a33347c13f4b324f52e1cea
parentf97ab65634b5b88e3e42e10f9f4b0923d88a192b (diff)
downloaddriver-core-350f0bd10e65c3d60dfab546d3a375ff3990a614.tar.gz
driver-core-350f0bd10e65c3d60dfab546d3a375ff3990a614.tar.bz2
driver-core-350f0bd10e65c3d60dfab546d3a375ff3990a614.zip
Finer grained permission-control
-rw-r--r--src/main/scala/com/drivergrp/core/auth.scala76
-rw-r--r--src/main/scala/com/drivergrp/core/database.scala4
-rw-r--r--src/main/scala/com/drivergrp/core/rest.scala6
3 files changed, 66 insertions, 20 deletions
diff --git a/src/main/scala/com/drivergrp/core/auth.scala b/src/main/scala/com/drivergrp/core/auth.scala
index 8722d6a..eed40ef 100644
--- a/src/main/scala/com/drivergrp/core/auth.scala
+++ b/src/main/scala/com/drivergrp/core/auth.scala
@@ -2,7 +2,16 @@ package com.drivergrp.core
object auth {
- trait Permission
+ sealed trait Permission
+ case object CanSeeUser extends Permission
+ case object CanSeeAssay extends Permission
+ case object CanSeeReport extends Permission
+ case object CanCreateReport extends Permission
+ case object CanEditReport extends Permission
+ case object CanEditReviewingReport extends Permission
+ case object CanSignOutReport extends Permission
+ case object CanShareReportWithPatient extends Permission
+ case object CanAssignRoles extends Permission
trait Role {
val id: Id[Role]
@@ -11,6 +20,43 @@ object auth {
def hasPermission(permission: Permission): Boolean = false
}
+ case object ObserverRole extends Role {
+ val id = Id(1L)
+ val name = Name("observer")
+
+ override def hasPermission(permission: Permission): Boolean =
+ Set[Permission](CanSeeUser, CanSeeAssay, CanSeeReport).contains(permission)
+ }
+
+ case object PatientRole extends Role {
+ val id = Id(2L)
+ val name = Name("patient")
+ }
+
+ case object CuratorRole extends Role {
+ val id = Id(3L)
+ val name = Name("curator")
+
+ override def hasPermission(permission: Permission): Boolean =
+ Set[Permission](CanSeeUser, CanSeeAssay, CanSeeReport, CanEditReport).contains(permission)
+ }
+
+ case object PathologistRole extends Role {
+ val id = Id(4L)
+ val name = Name("pathologist")
+
+ override def hasPermission(permission: Permission): Boolean =
+ Set[Permission](CanSeeUser, CanSeeAssay, CanSeeReport, CanEditReport, CanSignOutReport, CanEditReviewingReport)
+ .contains(permission)
+ }
+
+ case object AdministratorRole extends Role {
+ val id = Id(5L)
+ val name = Name("administrator")
+
+ override def hasPermission(permission: Permission): Boolean = true
+ }
+
trait User {
def id: Id[User]
def roles: Set[Role]
@@ -22,31 +68,27 @@ object auth {
final case class AuthToken(value: Base64[Macaroon])
+ def extractUser(authToken: AuthToken): User = {
+ new User() {
+ override def id: Id[User] = Id[User](1L)
+ override def roles: Set[Role] = Set(PathologistRole)
+ }
+
+ // TODO: or reject(ValidationRejection(s"Wasn't able to extract user for the token provided")) if none
+ }
+
object directives {
import akka.http.scaladsl.server._
import Directives._
val AuthenticationTokenHeader = "WWW-Authenticate"
- type UserExtractor = AuthToken => Option[User]
-
- def authorize(role: Role)(implicit userExtractor: UserExtractor): Directive1[Id[User]] = {
+ def authorize(permission: Permission): Directive1[AuthToken] = {
headerValueByName(AuthenticationTokenHeader).flatMap { tokenValue =>
val token = AuthToken(Base64[Macaroon](tokenValue))
- userExtractor(token) match {
- case Some(user) =>
- if (user.roles.contains(role)) provide(user.id: Id[User])
- else reject(ValidationRejection(s"User does not have the required ${role.name} role"))
- case None =>
- reject(ValidationRejection(s"Wasn't able to extract user for the token provided"))
- }
- }
- }
-
- def extractToken: Directive1[AuthToken] = {
- headerValueByName(AuthenticationTokenHeader).flatMap { token =>
- provide(AuthToken(Base64[Macaroon](token)))
+ if (extractUser(token).roles.exists(_.hasPermission(permission))) provide(token)
+ else reject(ValidationRejection(s"User does not have the required permission $permission"))
}
}
}
diff --git a/src/main/scala/com/drivergrp/core/database.scala b/src/main/scala/com/drivergrp/core/database.scala
index beabbff..581c5de 100644
--- a/src/main/scala/com/drivergrp/core/database.scala
+++ b/src/main/scala/com/drivergrp/core/database.scala
@@ -1,5 +1,7 @@
package com.drivergrp.core
+import com.drivergrp.core.time.Time
+
import scala.concurrent.Future
import slick.backend.DatabaseConfig
import slick.driver.JdbcProfile
@@ -33,6 +35,8 @@ object database {
implicit def nameColumnType[T] =
MappedColumnType.base[Name[T], String](name => name: String, Name[T](_))
+
+ implicit val timeColumnType = MappedColumnType.base[Time, Long](time => time.millis, Time(_))
}
trait DatabaseObject extends IdColumnTypes {
diff --git a/src/main/scala/com/drivergrp/core/rest.scala b/src/main/scala/com/drivergrp/core/rest.scala
index ebb2640..a08dc73 100644
--- a/src/main/scala/com/drivergrp/core/rest.scala
+++ b/src/main/scala/com/drivergrp/core/rest.scala
@@ -30,16 +30,16 @@ object rest {
this.majorVersion === otherVersion.majorVersion
}
- type Service = AnyRef
+ trait Service
trait ServiceTransport {
def sendRequest(authToken: AuthToken)(requestStub: HttpRequest): Future[Unmarshal[ResponseEntity]]
}
- trait ServiceDiscovery[T <: Service] {
+ trait ServiceDiscovery {
- def discover(serviceName: Name[Service], version: ServiceVersion): T
+ def discover[T <: Service](serviceName: Name[Service], version: ServiceVersion): T
}
class HttpRestServiceTransport(actorSystem: ActorSystem, executionContext: ExecutionContext,