From 5832f63b84d7388441d1200f2442dc1e9de0225c Mon Sep 17 00:00:00 2001 From: vlad Date: Tue, 27 Jun 2017 17:13:02 -0700 Subject: All PDS UI domain models, API case classes, service traits and necessary utils moved to pdsui-common --- .../formats/json/user/ApiPartialUser.scala | 83 ++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala (limited to 'src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala') 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)) +} -- cgit v1.2.3