Skip to content

Commit

Permalink
fix: migrate to regex parsing instead of sdk 1.4
Browse files Browse the repository at this point in the history
  • Loading branch information
Pat Losoponkul committed Jul 3, 2023
1 parent 8ba16d5 commit 86a0481
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,37 +1,63 @@
package io.iohk.atala.castor.core.model.did

import io.iohk.atala.prism.identity as prismIdentity
import scala.util.matching.Regex

import scala.util.Try

final case class DIDMethod private[did] (value: String) {
override def toString: String = value
}
opaque type DIDMethod = String

object DIDMethod {
def fromString(s: String): Try[DIDMethod] = {
Try(DIDMethod(prismIdentity.DidMethod.Companion.fromString(s).toString))

private val DID_METHOD_REGEX: Regex = """^[a-z0-9]+$""".r

extension (method: DIDMethod) {
def toString: String = method
}
}

final case class DIDMethodSpecificId private[did] (value: String) {
override def toString: String = value
def fromStringUnsafe(s: String): DIDMethod = s

def fromString(s: String): Either[String, DIDMethod] =
DID_METHOD_REGEX
.findFirstMatchIn(s)
.toRight(s"The DID method $s does not conform to the syntax")
.map(_ => s)

}

opaque type DIDMethodSpecificId = String

object DIDMethodSpecificId {
def fromString(s: String): Try[DIDMethodSpecificId] = {
Try(DIDMethodSpecificId(prismIdentity.DidMethodSpecificId.Companion.fromString(s).toString))

private val DID_METHOD_ID_REGEX: Regex =
"""^(([A-Za-z0-9_\-\.]|(%[0-9A-F]{2}))*:)*([A-Za-z0-9_\-\.]|(%[0-9A-F]{2}))+$""".r

extension (id: DIDMethodSpecificId) {
def toString: String = id
}

def fromStringUnsafe(s: String): DIDMethodSpecificId = s

def fromString(s: String): Either[String, DIDMethodSpecificId] =
DID_METHOD_ID_REGEX
.findFirstMatchIn(s)
.toRight(s"The DID method specific id $s does not conform to the syntax")
.map(_ => s)

}

final case class DID(
method: DIDMethod,
methodSpecificId: DIDMethodSpecificId
) {
override def toString: String = s"did:${method.value}:${methodSpecificId.value}"
override def toString: String = s"did:$method:$methodSpecificId"
}

object DID {
// TODO: implement
def fromString(s: String): Either[String, DID] = ???
def fromString(s: String): Either[String, DID] = {
for {
_ <- Either.cond(s.startsWith("did:"), (), "DID syntax must start with 'did:' prefix")
methodRaw = s.drop("did:".length).takeWhile(_ != ':')
methodSpecificIdRaw = s.drop("did:".length).dropWhile(_ != ':').drop(1)
method <- DIDMethod.fromString(methodRaw)
methodSpecificId <- DIDMethodSpecificId.fromString(methodSpecificIdRaw)
} yield DID(method, methodSpecificId)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import io.iohk.atala.prism.protos.node_models
import io.iohk.atala.prism.protos.node_models.AtalaOperation.Operation
import io.iohk.atala.shared.models.Base64UrlString
import io.iohk.atala.shared.models.HexString

import scala.util.Try
import scala.util.matching.Regex

Expand All @@ -26,7 +25,7 @@ sealed trait PrismDID {
}

object PrismDID extends ProtoModelHelper {
val PRISM_METHOD: DIDMethod = DIDMethod("prism")
val PRISM_METHOD: DIDMethod = DIDMethod.fromStringUnsafe("prism")
val CANONICAL_SUFFIX_REGEX: Regex = "^([0-9a-f]{64}$)".r
val LONG_FORM_SUFFIX_REGEX: Regex = "^([0-9a-f]{64}):([A-Za-z0-9_-]+$)".r

Expand Down Expand Up @@ -56,10 +55,11 @@ object PrismDID extends ProtoModelHelper {
}

def fromString(s: String): Either[String, PrismDID] = {
DID.fromString(s)
DID
.fromString(s)
.flatMap { did =>
if (did.method.toString == PRISM_METHOD.value) Right(did)
else Left(s"Expected DID to have method ${PRISM_METHOD.value}, but got \"${did.method.toString}\" instead")
if (did.method == PRISM_METHOD) Right(did)
else Left(s"Expected DID to have method $PRISM_METHOD, but got \"${did.method.toString}\" instead")
}
.flatMap { did =>
val canonicalMatchGroups = CANONICAL_SUFFIX_REGEX.findAllMatchIn(did.methodSpecificId.toString).toList
Expand Down Expand Up @@ -102,7 +102,7 @@ object PrismDID extends ProtoModelHelper {
}

final case class CanonicalPrismDID private[did] (stateHash: HexString) extends PrismDID {
override val suffix: DIDMethodSpecificId = DIDMethodSpecificId.fromString(stateHash.toString).get
override val suffix: DIDMethodSpecificId = DIDMethodSpecificId.fromStringUnsafe(stateHash.toString)
}

final case class LongFormPrismDID private[did] (atalaOperation: node_models.AtalaOperation) extends PrismDID {
Expand All @@ -114,7 +114,7 @@ final case class LongFormPrismDID private[did] (atalaOperation: node_models.Atal

override val suffix: DIDMethodSpecificId = {
val encodedState = Base64UrlString.fromByteArray(atalaOperation.toByteArray).toStringNoPadding
DIDMethodSpecificId.fromString(s"${stateHash.toString}:${encodedState}").get
DIDMethodSpecificId.fromStringUnsafe(s"${stateHash.toString}:${encodedState}")
}

def createOperation: Either[String, PrismDIDOperation.Create] = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.iohk.atala.castor.core.model.did

import zio.*
import zio.test.*
import zio.test.Assertion.*

object DIDSpec extends ZIOSpecDefault {

override def spec = suite("DID")(fromStringSpec)

// TODO: check this https://github.com/w3c/did-test-suite
private val fromStringSpec = suite("DID.fromString")(
test("parse valid PRISM did") {
// val did = "did:prism:c191d4dfe2806d59df4632f78d38f80dfbfbd88187804783717e29116ffb"
// did:prism:c191d4dfe2806d59df4632f78d38f80dfbfbd88187804783717e29116ffb:Cu0CCuoCEjoKBmF1dGgtMRAESi4KCXNlY3AyNTZrMRIhAz3656yBEIzdpZuG3yYn8Npoty3_qQhIbpOC8QmdVnpeEj8KC2Fzc2VydGlvbi0xEAJKLgoJc2VjcDI1NmsxEiECbZrA1SxPTpIEl9VBY4a6hGqaPJbJE7v8U5b236bCbWUSOwoHbWFzdGVyMBABSi4KCXNlY3AyNTZrMRIhA0BNFWJYhLqaVji9EYfIvdi
val did =
"did:prism:c191d4dfe2806d59df4632f78d38f80dfbfbd88187804783717e29116ffb:Cu0CCuoCEjoKBmF1dGgtMRAESi4KCXNlY3AyNTZrMRIhAz3656yBEIzdpZuG3yYn8Npoty3_qQhIbpOC8QmdVnpeEj8KC2Fzc2VydGlvbi0xEAJKLgoJc2VjcDI1NmsxEiECbZrA1SxPTpIEl9VBY4a6hGqaPJbJE7v8U5b236bCbWUSOwoHbWFzdGVyMBABSi4KCXNlY3AyNTZrMRIhA0BNFWJYhLqaVji9EYfIvdi"
val parsed = DID.fromString(did)
println(parsed)
println(parsed.map(_.method))
println(parsed.map(_.methodSpecificId))
assert(parsed)(isRight(anything))
}
) @@ TestAspect.tag("dev")

}

0 comments on commit 86a0481

Please sign in to comment.