Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(agent): define the OAS for CredentialIssuerEndpoints [WIP] #909

Closed
wants to merge 42 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
c35103b
feat(agent): define the OAS for CredentialIssuerEndpoints
yshyn-iohk Feb 28, 2024
c983d4c
feat(agent): implement Nonce stub endpoint for OIDC credential issuer
yshyn-iohk Mar 4, 2024
276865f
feat(agent): add CredentialIssuerService mock and get walletId by pri…
yshyn-iohk Mar 6, 2024
347fe55
feat(agent): implement the VC issuance flow with the dummy data
yshyn-iohk Mar 11, 2024
d387df2
feat(agent): implement the VC issuance flow with the dummy data
yshyn-iohk Mar 14, 2024
a7919fe
feat: credential offer endpoint and keycloak plugin wip (#935)
Mar 19, 2024
e648e25
feat(agent): add IssuanceSession and NonceService
yshyn-iohk Mar 20, 2024
104731b
docs: add example instruction how to run
Mar 21, 2024
a6c4a25
fix: integrate oidc4vc CredentialOffer to IssuanceSession (#943)
Mar 22, 2024
16d11bd
doc(agent): add the details to the readme.md and change the port of t…
yshyn-iohk Mar 25, 2024
6a83797
chore: resolve rebase conflict
Apr 18, 2024
441d474
chore: resolve rebase conflict
Apr 18, 2024
ec586be
chore: resolve merge compilation conflict
Apr 23, 2024
c5de8f2
feat: oidc4vc issuer metadata and credential configuration CRUD (#977)
Apr 23, 2024
d2b462b
test: fix test layer make it pass
Apr 24, 2024
9085dca
chore: resolve rename conflicts
Apr 26, 2024
a91b8e7
chore: resolve rename conflicts
Apr 26, 2024
7d2c82f
chore: clean duplicate imports
Apr 26, 2024
829d3a6
Merge branch 'main' into oidc
May 2, 2024
5922023
Merge branch 'main' into oidc
May 6, 2024
2e55c6e
Merge branch 'main' into oidc
May 7, 2024
9a0a690
Merge branch 'main' into oidc
May 8, 2024
28e2a0e
feat: oid4vci credential configuration and metadata endpoints (#1021)
May 8, 2024
26cf243
Merge branch 'main' into oidc
May 9, 2024
ba4374e
test: add tests for oid4vci credential configuration CRUD (#1027)
May 10, 2024
c30a244
chore: update OID4VCI example script to use issuer metadata (#1036)
May 13, 2024
f28a86a
Merge branch main into oidc
May 21, 2024
160d451
Merge branch 'main' into oidc
May 23, 2024
4eda59a
fix: integrate issuer metadata in oid4vci credential endpoint (#1105)
May 27, 2024
0eff8cb
ci: fix linter warnings (#1109)
May 28, 2024
ce577fd
Merge branch 'main' into oidc
May 31, 2024
5e34d91
Resolve merge conflicts
May 31, 2024
94fa370
fix: re-number migration
May 31, 2024
f22f1e8
Merge branch 'main' into oidc
Jun 3, 2024
a639d94
fix: make oidc local script work (#1131)
Jun 3, 2024
1c6fd95
feat: authentication for oid4vci credential and nonce endpoint (#1148)
Jun 6, 2024
096b746
fix: update issuer auth server model parity (#1154)
Jun 7, 2024
22883c7
feat(agent): validate JWT proof in the credential request, update dem…
yshyn-iohk Jun 10, 2024
a692122
feat: add claims to the VC (#1176)
yshyn-iohk Jun 12, 2024
28c30ba
chore: migrate oid4vci example to published keycloak plugin (#1174)
Jun 12, 2024
da190a3
fix: add claims validation when creating oid4vci credential offer (#1…
Jun 13, 2024
1818686
feat: use kid in the jwt proof header of OID4VCI CredentialIssue request
yshyn-iohk Jun 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions .mega-linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,19 @@ DISABLE_LINTERS:
- CPP_CPPLINT # For pollux/lib/anoncreds/src/main/c
- JAVA_CHECKSTYLE # For pollux/lib/anoncreds/src/main/java
- GHERKIN_GHERKIN_LINT
- OPENAPI_SPECTRAL
# For python, disable all except PYTHON_BLACK linter
- PYTHON_PYLINT
- PYTHON_FLAKE8
- PYTHON_ISORT
- PYTHON_BANDIT
- PYTHON_MYPY
- PYTHON_PYRIGHT
- PYTHON_RUFF

DISABLE_ERRORS_LINTERS:
- KOTLIN_KTLINT
- PROTOBUF_PROTOLINT
- OPENAPI_SPECTRAL
- MARKDOWN_MARKDOWN_LINK_CHECK

DISABLE: [COPYPASTE, SPELL, CREDENTIALS]
Expand All @@ -45,10 +53,12 @@ PRE_COMMANDS:
cwd: "workspace"

# Linter customisation
MARKDOWN_MARKDOWN_LINK_CHECK_FILTER_REGEX_EXCLUDE: "CHANGELOG.md"
MARKDOWN_MARKDOWNLINT_FILTER_REGEX_EXCLUDE: "CHANGELOG.md"
MARKDOWN_MARKDOWN_LINK_CHECK_FILTER_REGEX_EXCLUDE: CHANGELOG\.md|DEPENDENCIES\.md
MARKDOWN_MARKDOWNLINT_FILTER_REGEX_EXCLUDE: CHANGELOG\.md|DEPENDENCIES\.md
MARKDOWN_MARKDOWN_TABLE_FORMATTER_FILTER_REGEX_EXCLUDE: CHANGELOG\.md|DEPENDENCIES\.md
SQL_SQL_LINT_ARGUMENTS: -d postgres --ignore-errors=postgres-invalid-alter-option,postgres-invalid-create-option,postgres-invalid-drop-option
YAML_YAMLLINT_FILTER_REGEX_EXCLUDE: "infrastructure/charts/agent/*|cloud-agent/service/api/http/*"
YAML_PRETTIER_FILTER_REGEX_EXCLUDE: "infrastructure/charts/agent/*|cloud-agent/service/api/http/*"
YAML_YAMLLINT_FILTER_REGEX_EXCLUDE: "infrastructure/charts/agent/*|cloud-agent/service/api/http/*|examples/*"
YAML_PRETTIER_FILTER_REGEX_EXCLUDE: "infrastructure/charts/agent/*|cloud-agent/service/api/http/*|examples/*"
YAML_V8R_FILTER_REGEX_EXCLUDE: "infrastructure/charts/agent/*"
JAVASCRIPT_STANDARD_FILTER_REGEX_EXCLUDE: "tests/performance-tests/agent-performance-tests-k6/src/k6chaijs.js"
BASH_SHELLCHECK_FILTER_REGEX_EXCLUDE: "infrastructure/*"
2 changes: 1 addition & 1 deletion .scala-steward.conf
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ updates.limit = 5
# If set, Scala Steward will use this message template for the commit messages and PR titles.
# Supported variables: ${artifactName}, ${currentVersion}, ${nextVersion} and ${default}
# Default: "${default}" which is equivalent to "Update ${artifactName} to ${nextVersion}"
commits.message = "${default}\n\nSigned-off-by: Hyperledger Bot <[email protected]>"
commits.message = "${default}\n\nSigned-off-by: Hyperledger Bot <[email protected]>"
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,7 @@ lazy val cloudAgentServer = project
eventNotification
)
.dependsOn(sharedTest % "test->test")
.dependsOn(polluxCore % "compile->compile;test->test")

// ############################
// #### Release process #####
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,63 @@
package org.hyperledger.identus.castor.core.model.did

import scala.collection.immutable.ListMap

final case class DIDUrl(
did: DID,
path: Seq[String],
parameters: Map[String, Seq[String]],
parameters: ListMap[String, Seq[String]],
fragment: Option[String]
)
) {

override def toString: String = {
val pathString = if (path.isEmpty) "" else path.mkString("/", "/", "")
val queryString =
if (parameters.isEmpty) ""
else parameters.map { case (key, values) => s"$key=${values.mkString(",")}" }.mkString("?", "&", "")
val fragmentString = fragment.map("#" + _).getOrElse("")

s"did:${did.method}:${did.methodSpecificId}$pathString$queryString$fragmentString"
}
}

object DIDUrl {
def fromString(url: String): Either[String, DIDUrl] = {
val DIDUrlPattern = """^(did:[^/?#&]*)(/[^?#]*)?(\?[^#]*)?(#.*)?""".r

url match {
case DIDUrlPattern(did, path, query, fragment) =>
for {
parsedDID <- DID.fromString(did)
} yield {
DIDUrl(
did = parsedDID,
path = Option(path).map(_.stripPrefix("/").split("/").toSeq).getOrElse(Seq.empty),
parameters = Option(query).map(parseQuery).getOrElse(ListMap.empty),
fragment = Option(fragment).map(_.stripPrefix("#"))
)
}
}
}

// This method preserves the order of the query parameters to return absolutely the same result as the original query string for testing purposes
private def parseQuery(query: String): ListMap[String, Seq[String]] = {
val params = query
.stripPrefix("?")
.split("&")
.toSeq
.map { param =>
param.split("=", 2) match {
case Array(key, value) => key -> value
case Array(key) => key -> ""
}
}

var listMap = ListMap.empty[String, Seq[String]]

params.foreach { case (key, value) =>
listMap = listMap.updated(key, listMap.getOrElse(key, Seq.empty) :+ value)
}

listMap
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,20 @@ package object error {
final case class ValidationError(cause: OperationValidationError) extends DIDOperationError
}

sealed trait DIDResolutionError
sealed trait DIDResolutionError {
def message: String
}

object DIDResolutionError {
final case class DLTProxyError(cause: Throwable) extends DIDResolutionError
final case class UnexpectedDLTResult(msg: String) extends DIDResolutionError
final case class ValidationError(cause: OperationValidationError) extends DIDResolutionError
final case class DLTProxyError(cause: Throwable) extends DIDResolutionError {
override def message: String = cause.getMessage
}
final case class UnexpectedDLTResult(msg: String) extends DIDResolutionError {
override def message: String = msg
}
final case class ValidationError(cause: OperationValidationError) extends DIDResolutionError {
override def message: String = cause.toString
}
}

sealed trait OperationValidationError
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package org.hyperledger.identus.castor.core.model.did

import org.hyperledger.identus.castor.core.util.GenUtils
import zio.*
import zio.test.*
import zio.test.assert
import zio.test.Assertion.*
import zio.test.Assertion.isLeft

object DIDUrlSpec extends ZIOSpecDefault {
override def spec = suite("DIDUrl")(fromStringSpec)

/*
* Getting test inputs
*
* git clone https://github.com/w3c/did-test-suite.git
* cd did-test-suite
* cd packages/did-core-test-server/suites/implementations
* find . -name 'did-*.json' -exec bash -c "cat {} | jq '.dids' | grep 'did:'" \;
*/
val DIDTestSuite = Seq(
"did:3:kjzl6cwe1jw145m7jxh4jpa6iw1ps3jcjordpo81e0w04krcpz8knxvg5ygiabd",
"did:algo:56da1708-eead-4e2d-9558-f53d684003fd",
"did:art:enq:f045c5c7d50145b65ca2702c38b4e2d46658293c",
"did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1JXfUY7oVWkY",
"did:ebsi:znHeZWvhAK2FK2Dk1jXNe7m",
"did:elem:ropsten:EiBVk9F3eLf2u9xwLJ91-vTIXD-B7Q4m3iGhCbB2OyRiwQ",
"did:ethr:0x26bf14321004e770e7a8b080b7a526d8eed8b388",
"did:example:123",
"did:ion:EiCUAQbYJzzCY1zL8KYmTu8MxCkFwG_cjRcZI2bRpwDQkQ:eyJkZWx0YSI6eyJwYXRjaGVzIjpbeyJhY3Rpb24iOiJyZXBsYWNlIiwiZG9jdW1lbnQiOnsicHVibGljS2V5cyI6W3siaWQiOiJzaWdfMDY0YmViY2MiLCJwdWJsaWNLZXlKd2siOnsiY3J2Ijoic2VjcDI1NmsxIiwia3R5IjoiRUMiLCJ4IjoibHV2TG1tbEc0NFZmcWx1aFh3SWpTdVQxVEwxc0VfMTFnQ0RlazJQbXVpbyIsInkiOiJ0WURKWmFpWDdBN2tydmNhcEFnS0pGNjd6ejVKUzF3bjRGdWNqa09kUUVvIn0sInB1cnBvc2VzIjpbImF1dGhlbnRpY2F0aW9uIiwiYXNzZXJ0aW9uTWV0aG9kIl0sInR5cGUiOiJFY2RzYVNlY3AyNTZrMVZlcmlmaWNhdGlvbktleTIwMTkifV0sInNlcnZpY2VzIjpbeyJpZCI6ImxpbmtlZGRvbWFpbnMiLCJzZXJ2aWNlRW5kcG9pbnQiOnsib3JpZ2lucyI6WyJodHRwczovL2FkbWluLXRlc3RzLWRvbWFpbi5jb20vIl19LCJ0eXBlIjoiTGlua2VkRG9tYWlucyJ9XX19XSwidXBkYXRlQ29tbWl0bWVudCI6IkVpQi13MlVfbW5aRUVRWmRoNUNsVWszMERBdjZrTXNMT05TSWdxaGp5WEluLUEifSwic3VmZml4RGF0YSI6eyJkZWx0YUhhc2giOiJFaURyNk1nVWtSSm9maGVqTW96VXVoSXBSX0tFa3J1WlZGaDlheHVzS2I5cnFRIiwicmVjb3ZlcnlDb21taXRtZW50IjoiRWlBS1VxUmJTTkJKSHFUQTljbXJ1MnBtQkVvd2tIVVFVLW9CS3Q3NWQ3QU8wQSJ9fQ",
"did:is:PMW1Ks7h4brpN8FdDVLwhPDKJ7LdA7mVdd",
"did:jnctn:187c4af8932a444a9e9503fb96cb672f",
"did:key:z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7",
"did:key:z5TcCQtximJCYYLLmpUhydMUfyppwqQFveNQcrmLxYqbCvDrrcu9rVrHwNZEN37CWMUBRd8xgEyPighrGMMmX8NWTnSPUuWPPeFyUhLmkgA1Vqgm3eQYHF4ye7WrkB7jYcWoa68oHQNuSzw6ezgebFtt27uvJG4yjdat8Wj1e2qPMjsR63xQbmNdDTQ4zi8GDz8EwVAgu",
"did:key:z6LSn9Ah7d33uokFv2pg66BMN5UY72WtPE6eFjGXrA4mPcCp",
"did:key:z6MkjPrEBMHGuJubLZ5HWf2jBreAuh7onKCA6BknWXYHLxjS",
"did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH",
"did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH",
"did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH",
"did:key:z6MktZw8HgaRUoG8S9asnmDKQL458uEhuuNT9U2UK5cT6Tmh",
"did:key:z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9",
"did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169",
"did:key:zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv",
"did:key:zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme",
"did:key:zQ3shwNhfEjorJrrKpqvBvNRV35NfGmVWdx2rNmQCRR58Sfpf",
"did:key:zUC7LbYAQUjoTVSJyieL3cxpbdA1QjWdqqtFMDoMRg4qkZtQWRrrd4LLVCboCd5xbxET3gNM6ALinG57wBZo5VoQ3AokhE9qpJehX4SHdsDJUGa9u3z22PEGLd1fBwzzLhTkJmV",
"did:kilt:04siJtc4dYq2gPre8Xj6KJcSjVAdi1gmjctUzjf3AwrtNnhvy",
"did:kilt:14siJtc4dYq2gPre8Xj6KJcSjVAdi1gmjctUzjf3AwrtNnhvy",
"did:lit:AEZ87t1bi5bRxmVh3ksMUi",
"did:monid:1fb352353ff51248c5104b407f9c04c3666627fcf5a167d693c9fc84b75964e2",
"did:nft:eip155.1_erc721.0xb300a43751601bd54ffee7de35929537b28e1488_2",
"did:onion:fscst5exmlmr262byztwz4kzhggjlzumvc2ndvgytzoucr2tkgxf7mid",
"did:orb:bafkreiazah4qrybzyapmrmk2dhldz24vfmavethcrgcoq7qhic63zz55ru:EiAag4cmgxAE2isL5HG3mxjS7WRq4l-xyyTgULCAcEHQQQ",
"did:orb:bafkreibcsubh3ifub7gletz27hcdyhwvrhlh5mwfth2m5fbasqua6yalay:EiA2ZtZqXjKZt-yf19ersmaCYm-gJEnlixrfk0Mi61ETTg",
"did:orb:bafkreihp4inweep4py7gw4j7hej5mqlbwa7br4u7mtrfxr5khfwpu3qu3m:EiB2tmdM_oWwjXj6AmVLm0RFa_8XKZHipOpNGpEODIVN8Q",
"did:orb:interim:EiAQ1HmY03Cx4OMhiuYHl8q-B1JYlkT1Wns-dhhccUIl5g:eyJkZWx0YSI6eyJwYXRjaGVzIjpbeyJhY3Rpb24iOiJhZGQtcHVibGljLWtleXMiLCJwdWJsaWNLZXlzIjpbeyJpZCI6ImNyZWF0ZUtleSIsInB1YmxpY0tleUp3ayI6eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6InJILURtZmNkRVZERi1vNm80ellxdjl2YlhPcFFFcDd3RC1XUHFDbl9ELXciLCJ5IjoidnBiRGNQX2YwS1JoRW02Sm93Y0oxbWlNTldJRXo2YWVnRHFDek80WXNxSSJ9LCJwdXJwb3NlcyI6WyJhdXRoZW50aWNhdGlvbiJdLCJ0eXBlIjoiSnNvbldlYktleTIwMjAifSx7ImlkIjoiYXV0aCIsInB1YmxpY0tleUp3ayI6eyJjcnYiOiJFZDI1NTE5Iiwia3R5IjoiT0tQIiwieCI6IjEzNkZDRjJTSEZNMUZ6aWlJYXJwNEI1RzkxUVNnNHB1dGFhSWg1VEdXREEiLCJ5IjoiIn0sInB1cnBvc2VzIjpbImFzc2VydGlvbk1ldGhvZCJdLCJ0eXBlIjoiRWQyNTUxOVZlcmlmaWNhdGlvbktleTIwMTgifV19LHsiYWN0aW9uIjoiYWRkLXNlcnZpY2VzIiwic2VydmljZXMiOlt7ImlkIjoiZGlkY29tbSIsInByaW9yaXR5IjowLCJyZWNpcGllbnRLZXlzIjpbIjZLWjZLQkZLZDQ3d3FEMlhnelJwTDZ0RGlxQkNnQzg1eEttbzhVRHExZjVSIl0sInJvdXRpbmdLZXlzIjpbIjhrNUY0bXVQN0s3NmVtZHdQNWlDOHJlRVlWb1NiWmdMM2FudmFXOTdUTm1yIl0sInNlcnZpY2VFbmRwb2ludCI6Imh0dHBzOi8vaHViLmV4YW1wbGUuY29tLy5pZGVudGl0eS9kaWQ6ZXhhbXBsZTowMTIzNDU2Nzg5YWJjZGVmLyIsInR5cGUiOiJkaWQtY29tbXVuaWNhdGlvbiJ9XX1dLCJ1cGRhdGVDb21taXRtZW50IjoiRWlEVXVaSFEwOENXRGVBTmJyc3VSeHh3M2V5bXNucFdNbzJ0TXQ3QUNlUUNIUSJ9LCJzdWZmaXhEYXRhIjp7ImFuY2hvck9yaWdpbiI6Imh0dHBzOi8vb3JiLmRvbWFpbjEuY29tL3NlcnZpY2VzL29yYiIsImRlbHRhSGFzaCI6IkVpQUluS05tb0d1WDJVajI1aGFCNDdGQlF4aGpmb0lJYzc3Y2h6N0p0enJXdVEiLCJyZWNvdmVyeUNvbW1pdG1lbnQiOiJFaUNIOWF3WHZQUFZZdVBneEw2WUFQX3FaeUktMzdxclcwQkdFT2o5cnJWbHd3In19",
"did:orb:interim:EiCYgffdSsqLTXT6PRYLPr6vvgn9PVecJ5nFUGh9hXgOxQ",
"did:orb:interim:EiDHdXhNm7LuCqxo4JvAwKYKiFmpf85YFswAovxTxI_y4Q",
"did:orb:ipfs:QmS4ZME5uEPtQ2DFDwhSZYtLxzFxCYjJ6kC7o3ypwanzFm:EiACG5GI9dK1fjnCMYMA6ZFhtP75HVhunEuqW-XDCAU7Ew",
"did:orb:ipfs:QmfJFePqcopDUYttpvWgec9LKeJhnwh4UjhwUJz5ZcRUqM:EiDwFxa7ooPvKDTqpemH-R-H0pNX9VzUEUzk8AZsMCf9pg",
"did:orb:ipfs:QmfX6CHk7AC43Xq9iFK9XzgH3a7kJeAn3ewWZxEcqur2wE:EiCnmXoUEEP-04kELpPiF7Ss5GesCCedfTgRPA30SJO5KQ",
"did:orb:ipfs:bafkreiacr3ga6zilvzatpcixq5mz4uvgld7yedutgcssvnmql44o6rc7yy:EiB2k0ytmo-qi_M7jGocxvj4P9D6VQJGl6gRy4f6-UUpTw",
"did:orb:webcas:testnet.orb.local:bafkreihdnftiso5b7bzmhhi65nzsutbcuv6mtrmuquzoqlrk7joyer45uq:EiARiEOCLK3GnRVHA_yF92tX3aoSJAVqW1bh7Enre1iDXw",
"did:photon:EiDS68FUZqv0da57WLI_t9Gl5TYGNxvWR3PGgRk9oXx85Q",
"did:pkh:btc:128Lkh3S7CkDTBZ8W7BbpsN3YYizJMp8p6",
"did:pkh:celo:0xa0ae58da58dfa46fa55c3b86545e7065f90ff011",
"did:pkh:doge:DH5yaieqoZN36fDVciNyRueRGvGLR3mr7L",
"did:pkh:eth:0xb9c5714089478a327f09197987f16f9e5d936e8a",
"did:pkh:sol:CKg5d12Jhpej1JqtmxLJgaFqqeYjxgPqToJ4LBdvG9Ev",
"did:pkh:tz:tz1YwA1FwpgLtc1G8DKbbZ6e6PTb1dQMRn5x",
"did:polygon:0xBCFdE12C425E4CbDb45226Fe51F89F2d99667d3E",
"did:schema:public-ipfs:xsd:QmUQAxKQ5sbWWrcBZzwkThktfUGZvuPQyTrqMzb3mZnLE5",
"did:sov:mattr-dev:3WhAjtBidfhGbiAyNQBxPP",
"did:ssb:ed25519:f_6sQ6d2CMxRUhLpspgGIulDxDCwYD7DzFzPNr7u5AU",
"did:trust:tc:dev:id:GvMM3dpmWH6mRhGK88Ykdh",
"did:tz:delphinet:tz1WvvbEGpBXGeTVbLiR6DYBe1izmgiYuZbq",
"did:tz:tz1YwA1FwpgLtc1G8DKbbZ6e6PTb1dQMRn5x",
"did:tz:tz2BFTyPeYRzxd5aiBchbXN3WCZhx7BqbMBq",
"did:tz:tz3agP9LGe2cXmKQyYn6T68BHKjjktDbbSWX",
"did:unisot:test:mtF5XVLJvXEeffY8fo2eUfpXqs9CqQzpj7",
"did:v1:nym:z6Mkh18zyRvTikTTYwi3p4S8kQNqLkExDamQHERxeB34AMvL",
"did:vaa:2H9XwzRXZ1o5ZwSoYDEZn24eHXcQ",
"did:web:demo.spruceid.com:2021:07:08",
"did:web:did.actor:healthcare:doctor:robert",
"did:web:did.actor:mike",
"did:web:did.actor:mike",
"did:web:evernym.com",
"did:web:kyledenhartog.com",
"did:web:or13.github.io:deno-did-pm",
"did:webkey:ssh:demo.spruceid.com:2021:07:14:keys",
)

val numberOfSamples = 1000

private val fromStringSpec = suite("DIDUrl.fromString")(
test("parse any valid long-form or canonical form PRISM DID Url") {
check(GenUtils.prismDIDUrlGen) { prismDIDRUrl =>
val parsed = DIDUrl.fromString(prismDIDRUrl)
assert(parsed.map(_.toString))(isRight(equalTo(prismDIDRUrl)))
}
} @@ TestAspect.samples(numberOfSamples),
test("parse all DIDs from https://github.com/w3c/did-test-suite.git as DIDUrl") {
check(Gen.fromIterable(DIDTestSuite)) { didUrl =>
val parsed = DIDUrl.fromString(didUrl)
assert(parsed.map(_.toString))(isRight(equalTo(didUrl)))
}
} @@ TestAspect.samples(numberOfSamples),
test("parse all DIDs from https://github.com/w3c/did-test-suite.git with path, query and fragment as DIDUrl") {
check(GenUtils.inputDIDUrlGen(DIDTestSuite)) { didUrl =>
val parsed = DIDUrl.fromString(didUrl)
assert(parsed.map(_.toString))(isRight(equalTo(didUrl)))
}
} @@ TestAspect.samples(numberOfSamples)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import org.hyperledger.identus.shared.models.Base64UrlString
import zio.*
import zio.test.Gen

import java.net.URI
import scala.language.implicitConversions

object GenUtils {
Expand Down Expand Up @@ -82,6 +83,11 @@ object GenUtils {
} yield PrismDIDOperation.Create(keys, services, contexts)
}

val longFormPrismDIDGen: Gen[Any, LongFormPrismDID] = createOperation.map(PrismDID.buildLongFormFromOperation)
val canonicalPrismDIDGen: Gen[Any, CanonicalPrismDID] = createOperation.map(_.did)
val rawPrismDIDGen: Gen[Any, String] =
Gen.oneOf(longFormPrismDIDGen.map(_.toString), canonicalPrismDIDGen.map(_.toString))

val didData: Gen[Any, DIDData] = {
for {
op <- createOperation
Expand All @@ -94,4 +100,48 @@ object GenUtils {
)
}

val pathGen: Gen[Any, String] = for {
numSegments <- Gen.int(1, 5)
segments <- Gen.listOfN(numSegments)(Gen.alphaNumericStringBounded(1, 10))
} yield segments.mkString("/", "/", "")

val queryGen: Gen[Any, String] = for {
numParams <- Gen.int(1, 5)
params <- Gen
.listOfN(numParams)(
for {
key <- Gen.alphaNumericStringBounded(1, 10)
value <- Gen.alphaNumericStringBounded(1, 10)
} yield key -> value
)
.map(_.toMap.map { case (k, v) => s"$k=$v" })

} yield params.mkString("?", "&", "")

val fragmentGen: Gen[Any, String] = Gen.alphaNumericStringBounded(1, 10).map("#" + _)

val prismDIDUrlGen: Gen[Any, String] = for {
did <- rawPrismDIDGen
path <- Gen.option(pathGen)
query <- Gen.option(queryGen)
fragment <- Gen.option(fragmentGen)
} yield {
val pathPart = path.getOrElse("")
val queryPart = query.getOrElse("")
val fragmentPart = fragment.getOrElse("")
s"$did$pathPart$queryPart$fragmentPart"
}

def inputDIDUrlGen(input: Seq[String]): Gen[Any, String] = for {
did <- Gen.fromIterable(input)
path <- Gen.option(pathGen)
query <- Gen.option(queryGen)
fragment <- Gen.option(fragmentGen)
} yield {
val pathPart = path.getOrElse("")
val queryPart = query.getOrElse("")
val fragmentPart = fragment.getOrElse("")
s"$did$pathPart$queryPart$fragmentPart"
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import org.hyperledger.identus.iam.entity.http.EntityServerEndpoints
import org.hyperledger.identus.iam.wallet.http.WalletManagementServerEndpoints
import org.hyperledger.identus.issue.controller.IssueServerEndpoints
import org.hyperledger.identus.mercury.{DidOps, HttpClient}
import org.hyperledger.identus.oid4vci.CredentialIssuerServerEndpoints
import org.hyperledger.identus.pollux.core.service.{CredentialService, PresentationService}
import org.hyperledger.identus.pollux.credentialdefinition.CredentialDefinitionRegistryServerEndpoints
import org.hyperledger.identus.pollux.credentialschema.{
Expand Down Expand Up @@ -135,6 +136,7 @@ object AgentHttpServer {
allEntityEndpoints <- EntityServerEndpoints.all
allWalletManagementEndpoints <- WalletManagementServerEndpoints.all
allEventEndpoints <- EventServerEndpoints.all
allOIDCEndpoints <- CredentialIssuerServerEndpoints.all
} yield allCredentialDefinitionRegistryEndpoints ++
allSchemaRegistryEndpoints ++
allVerificationPolicyEndpoints ++
Expand All @@ -148,7 +150,8 @@ object AgentHttpServer {
allSystemEndpoints ++
allEntityEndpoints ++
allWalletManagementEndpoints ++
allEventEndpoints
allEventEndpoints ++
allOIDCEndpoints
def run =
for {
allEndpoints <- agentRESTServiceEndpoints
Expand Down
Loading