rabbah closed pull request #3371: Make AuthKey parsing leaner. URL: https://github.com/apache/incubator-openwhisk/pull/3371
This is a PR merged from a forked repository. As GitHub hides the original diff on merge, it is displayed below for the sake of provenance: As this is a foreign pull request (from a fork), the diff is supplied below (as it won't show otherwise due to GitHub magic): diff --git a/common/scala/src/main/scala/whisk/core/entity/AuthKey.scala b/common/scala/src/main/scala/whisk/core/entity/AuthKey.scala index 55aa96beb8..bd1a24c9f3 100644 --- a/common/scala/src/main/scala/whisk/core/entity/AuthKey.scala +++ b/common/scala/src/main/scala/whisk/core/entity/AuthKey.scala @@ -17,12 +17,8 @@ package whisk.core.entity -import scala.util.Try - -import spray.json.JsString -import spray.json.JsValue -import spray.json.RootJsonFormat -import spray.json.deserializationError +import spray.json._ +import spray.json.DefaultJsonProtocol._ /** * Authentication key, consisting of a UUID and Secret. @@ -31,14 +27,14 @@ import spray.json.deserializationError * The constructor is private so that argument requirements are checked and normalized * before creating a new instance. * - * @param (uuid, key) the uuid and key, assured to be non-null because both types are values + * @param k (uuid, key) the uuid and key, assured to be non-null because both types are values */ protected[core] class AuthKey private (private val k: (UUID, Secret)) extends AnyVal { - def uuid = k._1 - def key = k._2 + def uuid: UUID = k._1 + def key: Secret = k._2 def revoke = new AuthKey(uuid, Secret()) - def compact = s"$uuid:$key" - override def toString = uuid.toString + def compact: String = s"$uuid:$key" + override def toString: String = uuid.toString } protected[core] object AuthKey { @@ -64,37 +60,22 @@ protected[core] object AuthKey { * the first two hence "k:v*" produces ("k","v"). * * @param str the string containing uuid and key separated by colon - * @return AuthKey if argument is properly formated + * @return AuthKey if argument is properly formatted * @throws IllegalArgumentException if argument is not well formed */ @throws[IllegalArgumentException] protected[core] def apply(str: String): AuthKey = { - val (k, v) = split(str) - new AuthKey(UUID(k), Secret(v)) - } + val (uuid, secret) = str.split(':').toList match { + case k :: v :: _ => (k, v) + case k :: Nil => (k, "") + case Nil => ("", "") + } - /** - * Makes a tuple from a string where the values are separated by a colon. - * If the string contains more than one colon, all values are ignored except for - * the first two hence "k:v*" produces the tuple ("k","v") and "::*" produces ("",""). - * - * @param string to create pair from - * @return (key, value) where both are null, value is null, or neither is null - */ - private def split(str: String): (String, String) = { - val parts = if (str != null && str.nonEmpty) str.split(":") else Array[String]() - val k = if (parts.size >= 1) parts(0).trim else null - val v = if (parts.size == 2) parts(1).trim else null - (k, v) + new AuthKey(UUID(uuid.trim), Secret(secret.trim)) } - protected[core] implicit val serdes = new RootJsonFormat[AuthKey] { + protected[core] implicit val serdes: RootJsonFormat[AuthKey] = new RootJsonFormat[AuthKey] { def write(k: AuthKey) = JsString(k.compact) - - def read(value: JsValue) = - Try { - val JsString(s) = value - AuthKey(s) - } getOrElse deserializationError("authorization key malformed") + def read(value: JsValue) = AuthKey(value.convertTo[String]) } } diff --git a/common/scala/src/main/scala/whisk/core/entity/Secret.scala b/common/scala/src/main/scala/whisk/core/entity/Secret.scala index db902ae7fc..aac4e7f7e8 100644 --- a/common/scala/src/main/scala/whisk/core/entity/Secret.scala +++ b/common/scala/src/main/scala/whisk/core/entity/Secret.scala @@ -17,11 +17,8 @@ package whisk.core.entity -import scala.util.Try -import spray.json.JsValue -import spray.json.RootJsonFormat -import spray.json.JsString -import spray.json.deserializationError +import spray.json._ +import spray.json.DefaultJsonProtocol._ /** * Secret, a cryptographic string such as a key used for authentication. @@ -33,12 +30,12 @@ import spray.json.deserializationError * @param key the secret key, required not null or empty */ protected[core] class Secret private (val key: String) extends AnyVal { - protected[core] def asString = toString - protected[entity] def toJson = JsString(toString) - override def toString = key + protected[core] def asString: String = toString + protected[entity] def toJson: JsString = JsString(toString) + override def toString: String = key } -protected[core] object Secret extends ArgNormalizer[Secret] { +protected[core] object Secret { /** Minimum secret length */ private val MIN_LENGTH = 64 @@ -54,7 +51,7 @@ protected[core] object Secret extends ArgNormalizer[Secret] { * @throws IllegalArgumentException is argument is not a valid Secret */ @throws[IllegalArgumentException] - override protected[entity] def factory(str: String): Secret = { + protected[core] def apply(str: String): Secret = { require(str.length >= MIN_LENGTH, s"secret must be at least $MIN_LENGTH characters") require(str.length <= MAX_LENGTH, s"secret must be at most $MAX_LENGTH characters") new Secret(str) @@ -69,14 +66,9 @@ protected[core] object Secret extends ArgNormalizer[Secret] { Secret(rand.alphanumeric.take(MIN_LENGTH).mkString) } - implicit val serdes = new RootJsonFormat[Secret] { - def write(s: Secret) = s.toJson - - def read(value: JsValue) = - Try { - val JsString(s) = value - Secret(s) - } getOrElse deserializationError("secret malformed") + implicit val serdes: RootJsonFormat[Secret] = new RootJsonFormat[Secret] { + def write(s: Secret): JsValue = s.toJson + def read(value: JsValue): Secret = Secret(value.convertTo[String]) } private val rand = new scala.util.Random(new java.security.SecureRandom()) diff --git a/common/scala/src/main/scala/whisk/core/entity/UUID.scala b/common/scala/src/main/scala/whisk/core/entity/UUID.scala index 3518077c97..cce8e29ff9 100644 --- a/common/scala/src/main/scala/whisk/core/entity/UUID.scala +++ b/common/scala/src/main/scala/whisk/core/entity/UUID.scala @@ -21,57 +21,38 @@ import java.security.SecureRandom import com.fasterxml.uuid.Generators -import scala.util.Try -import spray.json.JsString -import spray.json.JsValue -import spray.json.RootJsonFormat -import spray.json.deserializationError +import spray.json._ +import spray.json.DefaultJsonProtocol._ /** - * Wrapper for java.util.UUID. + * Represents a user's username and/or a namespace identifier (generally looks like UUIDs) * * It is a value type (hence == is .equals, immutable and cannot be assigned null). * The constructor is private so that argument requirements are checked and normalized * before creating a new instance. * - * @param uuid the uuid, required not null + * @param asString the uuid in string representation */ -protected[core] class UUID private (private val uuid: java.util.UUID) extends AnyVal { - protected[core] def asString = toString - protected[core] def snippet = toString.substring(0, 8) - protected[entity] def toJson = JsString(toString) - override def toString = uuid.toString +protected[core] class UUID private (val asString: String) extends AnyVal { + protected[core] def snippet: String = asString.substring(0, 8) + protected[entity] def toJson: JsString = JsString(asString) + override def toString: String = asString } -protected[core] object UUID extends ArgNormalizer[UUID] { - - /** - * Creates a UUID from a string. The string must be a valid UUID. - * - * @param str the uuid as string - * @return UUID instance - * @throws IllegalArgumentException is argument is not a valid UUID - */ - @throws[IllegalArgumentException] - override protected[entity] def factory(str: String): UUID = { - new UUID(java.util.UUID.fromString(str)) - } +protected[core] object UUID { /** * Generates a random UUID using java.util.UUID factory. * * @return new UUID */ - protected[core] def apply(): UUID = new UUID(UUIDs.randomUUID()) + protected[core] def apply(): UUID = new UUID(UUIDs.randomUUID().toString) - implicit val serdes = new RootJsonFormat[UUID] { - def write(u: UUID) = u.toJson + protected[core] def apply(str: String): UUID = new UUID(str) - def read(value: JsValue) = - Try { - val JsString(u) = value - UUID(u) - } getOrElse deserializationError("uuid malformed") + implicit val serdes: RootJsonFormat[UUID] = new RootJsonFormat[UUID] { + def write(u: UUID): JsValue = u.toJson + def read(value: JsValue): UUID = new UUID(value.convertTo[String]) } } diff --git a/tests/src/test/scala/whisk/core/entity/test/SchemaTests.scala b/tests/src/test/scala/whisk/core/entity/test/SchemaTests.scala index b5cb9f4014..864d3fc7a1 100644 --- a/tests/src/test/scala/whisk/core/entity/test/SchemaTests.scala +++ b/tests/src/test/scala/whisk/core/entity/test/SchemaTests.scala @@ -56,7 +56,7 @@ class SchemaTests extends FlatSpec with BeforeAndAfter with ExecHelpers with Mat } it should "reject malformed ids" in { - Seq(null, "", " ", ":", " : ", " :", ": ", "a:b").foreach { i => + Seq("", " ", ":", " : ", " :", ": ", "a:b").foreach { i => an[IllegalArgumentException] should be thrownBy AuthKey(i) } } ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org With regards, Apache Git Services