aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/com/drivergrp/core/auth.scala
diff options
context:
space:
mode:
authorvlad <vlad@drivergrp.com>2016-08-02 10:54:00 -0700
committervlad <vlad@drivergrp.com>2016-08-02 10:54:00 -0700
commit3008753cf543caaecb7d0e325c9f4473ad8a0322 (patch)
treeb6ae10a3370ddc03c3bbbf58254fe6cd0e5b7d9e /src/main/scala/com/drivergrp/core/auth.scala
parentdbe1579308b71b407393019103dd93c7fe6936c2 (diff)
downloaddriver-core-3008753cf543caaecb7d0e325c9f4473ad8a0322.tar.gz
driver-core-3008753cf543caaecb7d0e325c9f4473ad8a0322.tar.bz2
driver-core-3008753cf543caaecb7d0e325c9f4473ad8a0322.zip
Domain model responsible for auth is in core + Akka-http auth directives + More specific REST service API
Diffstat (limited to 'src/main/scala/com/drivergrp/core/auth.scala')
-rw-r--r--src/main/scala/com/drivergrp/core/auth.scala100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/main/scala/com/drivergrp/core/auth.scala b/src/main/scala/com/drivergrp/core/auth.scala
new file mode 100644
index 0000000..84d943d
--- /dev/null
+++ b/src/main/scala/com/drivergrp/core/auth.scala
@@ -0,0 +1,100 @@
+package com.drivergrp.core
+
+object auth {
+
+ final case class FullName[+T](firstName: Name[T], middleName: Name[T], lastName: Name[T])
+
+ final case class Email(username: String, domain: String) {
+ override def toString = username + "@" + domain
+ }
+
+ trait Role {
+ val id: Id[Role]
+ val name: Name[Role]
+
+ def canEditReport: Boolean = false
+ def canSignOffReport: Boolean = false
+ def canAssignRoles: Boolean = false
+ }
+
+ case object ObserverRole extends Role {
+ val id = Id(1L)
+ val name = Name("observer")
+ }
+
+ 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 canEditReport: Boolean = true
+ }
+
+ case object PathologistRole extends Role {
+ val id = Id(4L)
+ val name = Name("pathologist")
+
+ override def canEditReport: Boolean = true
+ override def canSignOffReport: Boolean = true
+ }
+
+ case object AdministratorRole extends Role {
+ val id = Id(5L)
+ val name = Name("administrator")
+
+ override def canEditReport: Boolean = true
+ override def canSignOffReport: Boolean = true
+ override def canAssignRoles: Boolean = true
+ }
+
+ final case class Avatar(id: Id[Avatar], name: Name[Avatar])
+
+ final case class User(id: Id[User], name: FullName[User], email: Email, avatar: Option[Avatar], roles: Set[Role])
+
+ val TestUser = User(Id[User](1L),
+ FullName[User](Name("James"), Name("Dewey"), Name("Watson")),
+ Email("j.watson", "uchicago.edu"),
+ Some(Avatar(Id[Avatar](1L), Name[Avatar]("Coolface"))),
+ Set(PathologistRole))
+
+ final case class Macaroon(value: String)
+
+ final case class Base64[T](value: String)
+
+ final case class AuthToken(value: Base64[Macaroon])
+
+ object directives {
+ import akka.http.scaladsl.server._
+ import Directives._
+
+ val AuthenticationTokenHeader = "WWW-Authenticate"
+
+ def authorize(role: Role): Directive1[Id[User]] = {
+ headerValueByName(AuthenticationTokenHeader).flatMap { tokenValue =>
+ val token = AuthToken(Base64[Macaroon](tokenValue))
+
+ extractUser(token) match {
+ case Some(user) =>
+ if (user.roles.contains(role)) provide(user.id)
+ 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)))
+ }
+ }
+
+ def extractUser(authToken: AuthToken): Option[User] = {
+ Some(TestUser)
+ }
+ }
+}