diff options
author | vlad <vlad@driver.xyz> | 2017-06-27 17:13:02 -0700 |
---|---|---|
committer | vlad <vlad@driver.xyz> | 2017-06-27 17:13:02 -0700 |
commit | 5832f63b84d7388441d1200f2442dc1e9de0225c (patch) | |
tree | 32f63acdc920c14effc3d0d2822c05c125ad49e4 /src/main/scala/xyz/driver/pdsuidomain/formats/json/user | |
parent | 9dd50590d4c8f8b9442d7c21ddd1def9dd453d5e (diff) | |
download | rest-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')
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" + } +} |