diff options
-rw-r--r-- | src/main/scala/xyz/driver/core/auth.scala | 3 | ||||
-rw-r--r-- | src/main/scala/xyz/driver/core/domain.scala | 12 | ||||
-rw-r--r-- | src/main/scala/xyz/driver/core/json.scala | 28 | ||||
-rw-r--r-- | src/test/scala/xyz/driver/core/JsonTest.scala | 29 |
4 files changed, 66 insertions, 6 deletions
diff --git a/src/main/scala/xyz/driver/core/auth.scala b/src/main/scala/xyz/driver/core/auth.scala index 87b576c..896bd89 100644 --- a/src/main/scala/xyz/driver/core/auth.scala +++ b/src/main/scala/xyz/driver/core/auth.scala @@ -2,7 +2,6 @@ package xyz.driver.core import xyz.driver.core.domain.Email import xyz.driver.core.time.Time - import scalaz.Equal object auth { @@ -40,5 +39,5 @@ object auth { final case class PasswordHash(value: String) - final case class AuthCredentials(email: Email, password: String) + final case class AuthCredentials(identifier: String, password: String) } diff --git a/src/main/scala/xyz/driver/core/domain.scala b/src/main/scala/xyz/driver/core/domain.scala index 7731345..fa3b5c4 100644 --- a/src/main/scala/xyz/driver/core/domain.scala +++ b/src/main/scala/xyz/driver/core/domain.scala @@ -32,9 +32,15 @@ object domain { private val phoneUtil = PhoneNumberUtil.getInstance() def parse(phoneNumber: String): Option[PhoneNumber] = { - val phone = phoneUtil.parseAndKeepRawInput(phoneNumber, "US") - if (!phoneUtil.isValidNumber(phone)) None - else Some(PhoneNumber(phone.getCountryCode.toString, phone.getNationalNumber.toString)) + val phone = scala.util.Try(phoneUtil.parseAndKeepRawInput(phoneNumber, "US")).toOption + + val validated = phone match { + case None => None + case Some(pn) => + if (!phoneUtil.isValidNumber(pn)) None + else Some(pn) + } + validated.map(pn => PhoneNumber(pn.getCountryCode.toString, pn.getNationalNumber.toString)) } } } diff --git a/src/main/scala/xyz/driver/core/json.scala b/src/main/scala/xyz/driver/core/json.scala index aeb3453..c1c5862 100644 --- a/src/main/scala/xyz/driver/core/json.scala +++ b/src/main/scala/xyz/driver/core/json.scala @@ -187,7 +187,33 @@ object json { implicit val phoneNumberFormat = jsonFormat2(PhoneNumber.apply) - implicit val authCredentialsFormat = jsonFormat2(AuthCredentials) + implicit val authCredentialsFormat = new RootJsonFormat[AuthCredentials] { + override def read(json: JsValue): AuthCredentials = { + json match { + case JsObject(fields) => + val emailField = fields.get("email") + val identifierField = fields.get("identifier") + val passwordField = fields.get("password") + + (emailField, identifierField, passwordField) match { + case (_, _, None) => + deserializationError("password field must be set") + case (Some(JsString(em)), _, Some(JsString(pw))) => + val email = Email.parse(em).getOrElse(throw deserializationError(s"failed to parse email $em")) + AuthCredentials(email.toString, pw) + case (_, Some(JsString(id)), Some(JsString(pw))) => AuthCredentials(id.toString, pw.toString) + case (None, None, _) => deserializationError("identifier must be provided") + case _ => deserializationError(s"failed to deserialize ${json.prettyPrint}") + } + case _ => deserializationError(s"failed to deserialize ${json.prettyPrint}") + } + } + + override def write(obj: AuthCredentials): JsValue = JsObject( + "identifier" -> JsString(obj.identifier), + "password" -> JsString(obj.password) + ) + } implicit object inetAddressFormat extends JsonFormat[InetAddress] { override def read(json: JsValue): InetAddress = json match { diff --git a/src/test/scala/xyz/driver/core/JsonTest.scala b/src/test/scala/xyz/driver/core/JsonTest.scala index b845a44..fed2a9d 100644 --- a/src/test/scala/xyz/driver/core/JsonTest.scala +++ b/src/test/scala/xyz/driver/core/JsonTest.scala @@ -11,6 +11,7 @@ import xyz.driver.core.json._ import xyz.driver.core.time.provider.SystemTimeProvider import spray.json._ import xyz.driver.core.TestTypes.CustomGADT +import xyz.driver.core.auth.AuthCredentials import xyz.driver.core.domain.{Email, PhoneNumber} import xyz.driver.core.json.enumeratum.HasJsonFormat import xyz.driver.core.tagging.Taggable @@ -311,4 +312,32 @@ class JsonTest extends FlatSpec with Matchers { inetAddressFormat.read(invalidAddress) } } + + "AuthCredentials format" should "read and write correct JSON" in { + val email = Email("someone", "noehere.com") + val phoneId = PhoneNumber.parse("1 207 8675309") + val password = "nopassword" + + phoneId.isDefined should be(true) // test this real quick + + val emailAuth = AuthCredentials(email.toString, password) + val pnAuth = AuthCredentials(phoneId.get.toString, password) + + val emailWritten = authCredentialsFormat.write(emailAuth) + emailWritten should be("""{"identifier":"someone@noehere.com","password":"nopassword"}""".parseJson) + + val phoneWritten = authCredentialsFormat.write(pnAuth) + phoneWritten should be("""{"identifier":"+1 2078675309","password":"nopassword"}""".parseJson) + + val identifierEmailParsed = + authCredentialsFormat.read("""{"identifier":"someone@nowhere.com","password":"nopassword"}""".parseJson) + var written = authCredentialsFormat.write(identifierEmailParsed) + written should be("{\"identifier\":\"someone@nowhere.com\",\"password\":\"nopassword\"}".parseJson) + + val emailEmailParsed = + authCredentialsFormat.read("""{"email":"someone@nowhere.com","password":"nopassword"}""".parseJson) + written = authCredentialsFormat.write(emailEmailParsed) + written should be("{\"identifier\":\"someone@nowhere.com\",\"password\":\"nopassword\"}".parseJson) + + } } |