aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/xyz/driver/core/auth.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/xyz/driver/core/auth.scala')
-rw-r--r--src/main/scala/xyz/driver/core/auth.scala120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/main/scala/xyz/driver/core/auth.scala b/src/main/scala/xyz/driver/core/auth.scala
new file mode 100644
index 0000000..0b30bc0
--- /dev/null
+++ b/src/main/scala/xyz/driver/core/auth.scala
@@ -0,0 +1,120 @@
+package xyz.driver.core
+
+import akka.http.scaladsl.model.headers.HttpChallenges
+import akka.http.scaladsl.server.AuthenticationFailedRejection.CredentialsRejected
+import xyz.driver.core.rest.ServiceRequestContext
+
+import scala.concurrent.Future
+import scala.util.{Failure, Success}
+import scalaz.OptionT
+
+object auth {
+
+ 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 CanReviewReport extends Permission
+ case object CanEditReviewingReport extends Permission
+ case object CanSignOutReport extends Permission
+ case object CanAmendReport extends Permission
+ case object CanShareReportWithPatient extends Permission
+ case object CanAssignRoles extends Permission
+
+ trait Role {
+ val id: Id[Role]
+ val name: Name[Role]
+ val permissions: Set[Permission]
+
+ def hasPermission(permission: Permission): Boolean = permissions.contains(permission)
+ }
+
+ case object ObserverRole extends Role {
+ val id = Id("1")
+ val name = Name("observer")
+ val permissions = Set[Permission](CanSeeUser, CanSeeAssay, CanSeeReport)
+ }
+
+ case object PatientRole extends Role {
+ val id = Id("2")
+ val name = Name("patient")
+ val permissions = Set.empty[Permission]
+ }
+
+ case object CuratorRole extends Role {
+ val id = Id("3")
+ val name = Name("curator")
+ val permissions = ObserverRole.permissions ++ Set[Permission](CanEditReport, CanReviewReport)
+ }
+
+ case object PathologistRole extends Role {
+ val id = Id("4")
+ val name = Name("pathologist")
+ val permissions = ObserverRole.permissions ++
+ Set[Permission](CanEditReport, CanSignOutReport, CanAmendReport, CanEditReviewingReport)
+ }
+
+ case object AdministratorRole extends Role {
+ val id = Id("5")
+ val name = Name("administrator")
+ val permissions = CuratorRole.permissions ++
+ Set[Permission](CanCreateReport, CanShareReportWithPatient, CanAssignRoles)
+ }
+
+ case object PhysicianRole extends Role {
+ val id = Id("6")
+ val name = Name("physician")
+ val permissions = Set[Permission]()
+ }
+
+ case object RelativeRole extends Role {
+ val id = Id("7")
+ val name = Name("relative")
+ val permissions = Set[Permission]()
+ }
+
+ trait User {
+ def id: Id[User]
+ def roles: Set[Role]
+ def permissions: Set[Permission] = roles.flatMap(_.permissions)
+ }
+
+ final case class AuthToken(value: String)
+
+ final case class PasswordHash(value: String)
+
+ object AuthService {
+ val AuthenticationTokenHeader = rest.ContextHeaders.AuthenticationTokenHeader
+ val SetAuthenticationTokenHeader = "set-authorization"
+ }
+
+ trait AuthService[U <: User] {
+
+ import akka.http.scaladsl.server._
+ import Directives._
+
+ protected def authStatus(context: ServiceRequestContext): OptionT[Future, U]
+
+ def authorize(permissions: Permission*): Directive1[U] = {
+ rest.serviceContext flatMap { ctx =>
+ onComplete(authStatus(ctx).run).flatMap {
+ case Success(Some(user)) =>
+ if (permissions.forall(user.permissions.contains)) provide(user)
+ else {
+ val challenge =
+ HttpChallenges.basic(s"User does not have the required permissions: ${permissions.mkString(", ")}")
+ reject(AuthenticationFailedRejection(CredentialsRejected, challenge))
+ }
+
+ case Success(None) =>
+ reject(ValidationRejection(s"Wasn't able to find authenticated user for the token provided"))
+
+ case Failure(t) =>
+ reject(ValidationRejection(s"Wasn't able to verify token for authenticated user", Some(t)))
+ }
+ }
+ }
+ }
+}