aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/xyz/driver/pdsuidomain/formats/json/user
diff options
context:
space:
mode:
authorvlad <vlad@driver.xyz>2017-06-27 17:13:02 -0700
committervlad <vlad@driver.xyz>2017-06-27 17:13:02 -0700
commit5832f63b84d7388441d1200f2442dc1e9de0225c (patch)
tree32f63acdc920c14effc3d0d2822c05c125ad49e4 /src/main/scala/xyz/driver/pdsuidomain/formats/json/user
parent9dd50590d4c8f8b9442d7c21ddd1def9dd453d5e (diff)
downloadrest-query-5832f63b84d7388441d1200f2442dc1e9de0225c.tar.gz
rest-query-5832f63b84d7388441d1200f2442dc1e9de0225c.tar.bz2
rest-query-5832f63b84d7388441d1200f2442dc1e9de0225c.zip
All PDS UI domain models, API case classes, service traits and necessary utils moved to pdsui-commonv0.1.11
Diffstat (limited to 'src/main/scala/xyz/driver/pdsuidomain/formats/json/user')
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala83
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiUser.scala32
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/user/UserRole.scala33
3 files changed, 148 insertions, 0 deletions
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala
new file mode 100644
index 0000000..977934b
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala
@@ -0,0 +1,83 @@
+package xyz.driver.pdsuidomain.formats.json.user
+
+import java.math.BigInteger
+import java.security.SecureRandom
+
+import xyz.driver.pdsuicommon.domain.{Email, LongId, PasswordHash, User}
+import play.api.data.validation._
+import play.api.libs.functional.syntax._
+import play.api.libs.json._
+
+import scala.collection._
+import scala.util.Try
+import ApiPartialUser._
+import xyz.driver.pdsuicommon.json.JsonValidationException
+import xyz.driver.pdsuicommon.validation.{AdditionalConstraints, JsonValidationErrors}
+
+final case class ApiPartialUser(email: Option[String],
+ name: Option[String],
+ roleId: Option[String]) {
+
+ def applyTo(orig: User): Try[User] = Try {
+ val validation = Map(
+ JsPath \ "name" -> AdditionalConstraints.optionNonEmptyConstraint(name)
+ )
+
+ val validationErrors: JsonValidationErrors = validation.collect({
+ case (fieldName, e: Invalid) => (fieldName, e.errors)
+ })(breakOut)
+
+ if (validationErrors.isEmpty) {
+ orig.copy(name = name.get)
+ } else {
+ throw new JsonValidationException(validationErrors)
+ }
+ }
+
+ def toDomain(id: LongId[User] = LongId(0L)): Try[User] = Try {
+ val validation = Map(
+ JsPath \ "email" -> AdditionalConstraints.optionNonEmptyConstraint(email),
+ JsPath \ "name" -> AdditionalConstraints.optionNonEmptyConstraint(name),
+ JsPath \ "roleId" -> AdditionalConstraints.optionNonEmptyConstraint(roleId)
+ )
+
+ val validationErrors: JsonValidationErrors = validation.collect({
+ case (fieldName, e: Invalid) => (fieldName, e.errors)
+ })(breakOut)
+
+ if (validationErrors.isEmpty) {
+ val userEmail = email.map(x => Email(x.toLowerCase)).get
+ User(
+ id = id,
+ email = userEmail,
+ name = name.get,
+ role = roleId.map(UserRole.roleFromString).get,
+ passwordHash = PasswordHash(createPassword),
+ latestActivity = None,
+ deleted = None
+ )
+ } else {
+ throw new JsonValidationException(validationErrors)
+ }
+ }
+}
+
+object ApiPartialUser {
+
+ // SecureRandom is thread-safe, see the implementation
+ private val random = new SecureRandom()
+
+ def createPassword: String = new BigInteger(240, random).toString(32)
+
+ implicit val format: Format[ApiPartialUser] = (
+ (JsPath \ "email").formatNullable[String](Format(Reads.email, Writes.StringWrites)) and
+ (JsPath \ "name").formatNullable[String](Format(
+ Reads.filterNot[String](ValidationError("Username is too long (max length is 255 chars)", 255))(_.length > 255),
+ Writes.StringWrites
+ )) and
+ (JsPath \ "roleId").formatNullable[String](Format(Reads.of[String].filter(ValidationError("unknown role"))({
+ case x if UserRole.roleFromString.isDefinedAt(x) => true
+ case _ => false
+ }), Writes.of[String]))
+ ) (ApiPartialUser.apply, unlift(ApiPartialUser.unapply))
+}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiUser.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiUser.scala
new file mode 100644
index 0000000..c2653ec
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiUser.scala
@@ -0,0 +1,32 @@
+package xyz.driver.pdsuidomain.formats.json.user
+
+import java.time.{ZoneId, ZonedDateTime}
+
+import xyz.driver.pdsuicommon.domain.User
+import play.api.data.validation.ValidationError
+import play.api.libs.functional.syntax._
+import play.api.libs.json._
+
+final case class ApiUser(id: Long, email: String, name: String, roleId: String, latestActivity: Option[ZonedDateTime])
+
+object ApiUser {
+
+ implicit val format: Format[ApiUser] = (
+ (JsPath \ "id").format[Long] and
+ (JsPath \ "email").format[String](Reads.email) and
+ (JsPath \ "name").format[String] and
+ (JsPath \ "roleId").format[String](Format(Reads.of[String].filter(ValidationError("unknown role"))({
+ case x if UserRole.roleFromString.isDefinedAt(x) => true
+ case _ => false
+ }), Writes.of[String])) and
+ (JsPath \ "latestActivity").formatNullable[ZonedDateTime]
+ ) (ApiUser.apply, unlift(ApiUser.unapply))
+
+ def fromDomain(user: User) = ApiUser(
+ user.id.id,
+ user.email.value,
+ user.name,
+ UserRole.roleToString(user.role),
+ user.latestActivity.map(ZonedDateTime.of(_, ZoneId.of("Z")))
+ )
+}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/UserRole.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/UserRole.scala
new file mode 100644
index 0000000..74acb81
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/UserRole.scala
@@ -0,0 +1,33 @@
+package xyz.driver.pdsuidomain.formats.json.user
+
+import xyz.driver.pdsuicommon.domain.User.Role
+
+object UserRole {
+
+ val roleFromString: PartialFunction[String, Role] = {
+ case "Cleaner" => Role.RecordCleaner
+ case "Organizer" => Role.RecordOrganizer
+ case "Extractor" => Role.DocumentExtractor
+ case "RecordAdmin" => Role.RecordAdmin
+ case "TrialSummarizer" => Role.TrialSummarizer
+ case "CriteriaCurator" => Role.CriteriaCurator
+ case "TrialAdmin" => Role.TrialAdmin
+ case "EligibilityVerifier" => Role.EligibilityVerifier
+ case "TreatmentMatchingAdmin" => Role.TreatmentMatchingAdmin
+ case "RoutesCurator" => Role.RoutesCurator
+ // No Mixed at this time
+ }
+
+ def roleToString(x: Role): String = x match {
+ case Role.RecordCleaner => "Cleaner"
+ case Role.RecordOrganizer => "Organizer"
+ case Role.DocumentExtractor => "Extractor"
+ case Role.RecordAdmin => "RecordAdmin"
+ case Role.TrialSummarizer => "TrialSummarizer"
+ case Role.CriteriaCurator => "CriteriaCurator"
+ case Role.TrialAdmin => "TrialAdmin"
+ case Role.EligibilityVerifier => "EligibilityVerifier"
+ case Role.TreatmentMatchingAdmin => "TreatmentMatchingAdmin"
+ case Role.RoutesCurator => "RoutesCurator"
+ }
+}