diff --git a/Cargo.lock b/Cargo.lock index 9a809bd9..e987bf93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1093,9 +1093,9 @@ dependencies = [ [[package]] name = "bls12_381_plus" -version = "0.8.15" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcdcbc984ce4bbbba587f9415ecfd5ed15c59b33defe276482c517b26a6a6716" +checksum = "68ed5f583bb45888c562e1f117f7f20ce86a640f1163c38fe665ac7a71190861" dependencies = [ "arrayref", "elliptic-curve 0.13.8", @@ -1436,7 +1436,6 @@ checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" [[package]] name = "consumer" version = "0.1.0" -source = "git+https://git@github.com/impierce/did-manager.git?tag=v1.0.0-beta.3#3ad5e3dba7bc76df8d6cb4a4fd2df2238d88710b" dependencies = [ "did_iota", "did_jwk", @@ -1966,7 +1965,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.9.9", - "x25519-dalek", + "x25519-dalek 1.1.1", ] [[package]] @@ -2002,9 +2001,8 @@ dependencies = [ [[package]] name = "did_iota" version = "0.1.0" -source = "git+https://git@github.com/impierce/did-manager.git?tag=v1.0.0-beta.3#3ad5e3dba7bc76df8d6cb4a4fd2df2238d88710b" dependencies = [ - "bls12_381_plus 0.8.15", + "bls12_381_plus 0.8.17", "identity_iota", "identity_stronghold", "iota-sdk", @@ -2016,7 +2014,6 @@ dependencies = [ [[package]] name = "did_jwk" version = "0.1.0" -source = "git+https://git@github.com/impierce/did-manager.git?tag=v1.0.0-beta.3#3ad5e3dba7bc76df8d6cb4a4fd2df2238d88710b" dependencies = [ "did-jwk", "identity_iota", @@ -2033,7 +2030,6 @@ dependencies = [ [[package]] name = "did_key" version = "0.1.0" -source = "git+https://git@github.com/impierce/did-manager.git?tag=v1.0.0-beta.3#3ad5e3dba7bc76df8d6cb4a4fd2df2238d88710b" dependencies = [ "did-method-key", "identity_iota", @@ -2051,7 +2047,6 @@ dependencies = [ [[package]] name = "did_manager" version = "0.1.0" -source = "git+https://git@github.com/impierce/did-manager.git?tag=v1.0.0-beta.3#3ad5e3dba7bc76df8d6cb4a4fd2df2238d88710b" dependencies = [ "consumer", "producer", @@ -2079,7 +2074,6 @@ dependencies = [ [[package]] name = "did_web" version = "0.1.0" -source = "git+https://git@github.com/impierce/did-manager.git?tag=v1.0.0-beta.3#3ad5e3dba7bc76df8d6cb4a4fd2df2238d88710b" dependencies = [ "did-web", "identity_iota", @@ -2098,11 +2092,10 @@ dependencies = [ [[package]] name = "dif-presentation-exchange" version = "0.1.0" -source = "git+https://git@github.com/impierce/openid4vc.git?rev=12fed14#12fed1411ff3c0e1797090f386e44694f7a279b8" dependencies = [ "getset", "jsonpath_lib", - "jsonschema", + "jsonschema 0.17.1", "jsonwebtoken", "serde", "serde_json", @@ -2444,6 +2437,17 @@ dependencies = [ "regex", ] +[[package]] +name = "fancy-regex" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "531e46835a22af56d1e3b66f04844bed63158bc094a628bec1d321d9b4c44bf2" +dependencies = [ + "bit-set", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", +] + [[package]] name = "fastrand" version = "1.9.0" @@ -2557,6 +2561,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2576,6 +2595,16 @@ dependencies = [ "num", ] +[[package]] +name = "fraction" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f158e3ff0a1b334408dc9fb811cd99b446986f4d8b741bb08f9df1604085ae7" +dependencies = [ + "lazy_static", + "num", +] + [[package]] name = "funty" version = "2.0.0" @@ -3293,10 +3322,7 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "identity_core" version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee35f34cfc61310309a2cec6695e325676c425bfabc0b8fed9c42427d1ee6607" dependencies = [ - "iota-crypto", "js-sys", "multibase 0.9.1", "serde", @@ -3311,19 +3337,22 @@ dependencies = [ [[package]] name = "identity_credential" version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d0cf0ed8a8f1280ba518eed2990472d6d097bc430a62a81b3fcd7949054782" dependencies = [ + "anyhow", "async-trait", "flate2", + "futures", "identity_core", "identity_did", "identity_document", "identity_verification", "indexmap 2.5.0", "itertools 0.11.0", + "jsonschema 0.19.1", "once_cell", "roaring", + "sd-jwt-payload 0.2.1", + "sd-jwt-payload 0.3.0", "serde", "serde-aux", "serde_json", @@ -3336,12 +3365,11 @@ dependencies = [ [[package]] name = "identity_did" version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a054fe2898b1d4e29260c128ecd3bb65fbb00846000b17713f2d28cf6b2da7c0" dependencies = [ "did_url_parser", "form_urlencoded", "identity_core", + "identity_jose", "serde", "strum 0.25.0", "thiserror", @@ -3350,8 +3378,6 @@ dependencies = [ [[package]] name = "identity_document" version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76e59fe2e4b2c4843ef9e9cc37b70e864eff6021d42d982f596ce9949587dd7c" dependencies = [ "did_url_parser", "identity_core", @@ -3366,8 +3392,6 @@ dependencies = [ [[package]] name = "identity_iota" version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6820c32c06bccb53b804aebbc15879f79395632c99e1add4b7e2f1b662611960" dependencies = [ "identity_core", "identity_credential", @@ -3382,8 +3406,6 @@ dependencies = [ [[package]] name = "identity_iota_core" version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd8d4dec00632808f79bf7d85256f808abae7c8552ef6e102ea7350112900bf" dependencies = [ "async-trait", "futures", @@ -3406,10 +3428,8 @@ dependencies = [ [[package]] name = "identity_jose" version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a2bf6a6eeeb41729d65bdca82c9cdb3cc52847b8cc277892a60d68d008ba5b3" dependencies = [ - "bls12_381_plus 0.8.15", + "bls12_381_plus 0.8.17", "identity_core", "iota-crypto", "json-proof-token", @@ -3423,16 +3443,15 @@ dependencies = [ [[package]] name = "identity_resolver" version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616265a5de38f03867d3d5ce269e723a8cf6d6d5ee90d5b19a5b9879ed14e821" dependencies = [ + "anyhow", "async-trait", "futures", "identity_core", - "identity_credential", "identity_did", "identity_document", "identity_iota_core", + "iota-sdk", "serde", "strum 0.25.0", "thiserror", @@ -3441,8 +3460,6 @@ dependencies = [ [[package]] name = "identity_storage" version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee676abc86697f2ca52c86d3d34b1ae8558e62706623b470937be4fb93c169f" dependencies = [ "anyhow", "async-trait", @@ -3462,8 +3479,6 @@ dependencies = [ [[package]] name = "identity_stronghold" version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84cee4d8723ebf1605ca3cd848a21494a7e2e5e44c1610a43bb8ebf3114b5916" dependencies = [ "async-trait", "identity_storage", @@ -3479,7 +3494,6 @@ dependencies = [ [[package]] name = "identity_stronghold_ext" version = "0.1.0" -source = "git+https://git@github.com/impierce/did-manager.git?tag=v1.0.0-beta.3#3ad5e3dba7bc76df8d6cb4a4fd2df2238d88710b" dependencies = [ "async-trait", "elliptic-curve 0.13.8", @@ -3498,8 +3512,6 @@ dependencies = [ [[package]] name = "identity_verification" version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949c048132a35d0337540958bdae866aedebbfaadb588d4604475355fe9646db" dependencies = [ "identity_core", "identity_did", @@ -3606,9 +3618,9 @@ dependencies = [ [[package]] name = "iota-crypto" -version = "0.23.1" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5db0e2d85e258d6d0db66f4a6bf1e8bdf5b10c3353aa87d98b168778d13fdc1" +checksum = "98a38db844c910d78825e173c083f2ef416b69cb091bba8ac1055763c6db065b" dependencies = [ "aead", "aes", @@ -3618,7 +3630,7 @@ dependencies = [ "blake2", "chacha20poly1305", "cipher", - "curve25519-dalek 3.2.0", + "curve25519-dalek 4.1.3", "digest 0.10.7", "ed25519-zebra", "generic-array", @@ -3635,7 +3647,7 @@ dependencies = [ "sha2 0.10.8", "tiny-keccak", "unicode-normalization", - "x25519-dalek", + "x25519-dalek 2.0.1", "zeroize", ] @@ -3809,6 +3821,24 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "josekit" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b85e2125819afc4fd2ae57416207e792c7e12797858e5db2a6c6f24a166829" +dependencies = [ + "anyhow", + "base64 0.22.1", + "flate2", + "once_cell", + "openssl", + "regex", + "serde", + "serde_json", + "thiserror", + "time", +] + [[package]] name = "js-sys" version = "0.3.69" @@ -3969,6 +3999,15 @@ dependencies = [ "treediff", ] +[[package]] +name = "json-pointer" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fe841b94e719a482213cee19dd04927cf412f26d8dc84c5a446c081e49c2997" +dependencies = [ + "serde_json", +] + [[package]] name = "json-proof-token" version = "0.3.5" @@ -4048,8 +4087,8 @@ dependencies = [ "base64 0.21.7", "bytecount", "clap 4.5.7", - "fancy-regex", - "fraction", + "fancy-regex 0.11.0", + "fraction 0.13.1", "getrandom 0.2.15", "iso8601", "itoa", @@ -4067,6 +4106,34 @@ dependencies = [ "uuid", ] +[[package]] +name = "jsonschema" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14a655181740aa66dfcb182daca1bc8109fda5c7c0399c4f30dcb155ab0d32a6" +dependencies = [ + "ahash 0.8.11", + "anyhow", + "base64 0.22.1", + "bytecount", + "fancy-regex 0.13.0", + "fraction 0.15.3", + "getrandom 0.2.15", + "iso8601", + "itoa", + "memchr", + "num-cmp", + "once_cell", + "parking_lot 0.12.3", + "percent-encoding", + "regex", + "serde", + "serde_json", + "time", + "url", + "uuid-simd", +] + [[package]] name = "jsonwebkey" version = "0.3.5" @@ -4752,7 +4819,6 @@ dependencies = [ [[package]] name = "oid4vc-core" version = "0.1.0" -source = "git+https://git@github.com/impierce/openid4vc.git?rev=12fed14#12fed1411ff3c0e1797090f386e44694f7a279b8" dependencies = [ "anyhow", "async-trait", @@ -4776,7 +4842,6 @@ dependencies = [ [[package]] name = "oid4vc-manager" version = "0.1.0" -source = "git+https://git@github.com/impierce/openid4vc.git?rev=12fed14#12fed1411ff3c0e1797090f386e44694f7a279b8" dependencies = [ "anyhow", "async-trait", @@ -4808,7 +4873,6 @@ dependencies = [ [[package]] name = "oid4vci" version = "0.1.0" -source = "git+https://git@github.com/impierce/openid4vc.git?rev=12fed14#12fed1411ff3c0e1797090f386e44694f7a279b8" dependencies = [ "anyhow", "derivative", @@ -4826,12 +4890,12 @@ dependencies = [ "serde_urlencoded", "serde_with 3.8.1", "tokio", + "tracing", ] [[package]] name = "oid4vp" version = "0.1.0" -source = "git+https://git@github.com/impierce/openid4vc.git?rev=12fed14#12fed1411ff3c0e1797090f386e44694f7a279b8" dependencies = [ "anyhow", "chrono", @@ -4867,12 +4931,50 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.67", +] + [[package]] name = "openssl-probe" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "ordered-multimap" version = "0.6.0" @@ -4889,6 +4991,12 @@ version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" +[[package]] +name = "outref" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a" + [[package]] name = "overload" version = "0.1.1" @@ -5456,7 +5564,6 @@ dependencies = [ [[package]] name = "producer" version = "0.1.0" -source = "git+https://git@github.com/impierce/did-manager.git?tag=v1.0.0-beta.3#3ad5e3dba7bc76df8d6cb4a4fd2df2238d88710b" dependencies = [ "did_iota", "did_jwk", @@ -6277,6 +6384,44 @@ dependencies = [ "untrusted", ] +[[package]] +name = "sd-jwt-payload" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f96560f8ef0ef51808661b53f49e640cf854d64339d204c33fec3528d9451da7" +dependencies = [ + "iota-crypto", + "itertools 0.12.1", + "json-pointer", + "multibase 0.9.1", + "rand 0.8.5", + "serde", + "serde_json", + "serde_with 3.8.1", + "strum 0.26.3", + "thiserror", +] + +[[package]] +name = "sd-jwt-payload" +version = "0.3.0" +source = "git+https://github.com/iotaledger/sd-jwt-payload.git?branch=feat/sd-jwt-v11#ebc05f660ac90f0ffaf14c347ebbfb4efc669f88" +dependencies = [ + "anyhow", + "async-trait", + "iota-crypto", + "itertools 0.12.1", + "josekit", + "json-pointer", + "multibase 0.9.1", + "rand 0.8.5", + "serde", + "serde_json", + "serde_with 3.8.1", + "strum 0.26.3", + "thiserror", +] + [[package]] name = "sdd" version = "0.2.0" @@ -6393,12 +6538,13 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "indexmap 2.5.0", "itoa", + "memchr", "ryu", "serde", ] @@ -6618,7 +6764,6 @@ dependencies = [ [[package]] name = "shared" version = "0.1.0" -source = "git+https://git@github.com/impierce/did-manager.git?tag=v1.0.0-beta.3#3ad5e3dba7bc76df8d6cb4a4fd2df2238d88710b" dependencies = [ "identity_iota", "identity_storage", @@ -6694,7 +6839,6 @@ dependencies = [ [[package]] name = "siopv2" version = "0.1.0" -source = "git+https://git@github.com/impierce/openid4vc.git?rev=12fed14#12fed1411ff3c0e1797090f386e44694f7a279b8" dependencies = [ "anyhow", "async-trait", @@ -8142,6 +8286,17 @@ dependencies = [ "serde", ] +[[package]] +name = "uuid-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b082222b4f6619906941c17eb2297fff4c2fb96cb60164170522942a200bd8" +dependencies = [ + "outref", + "uuid", + "vsimd", +] + [[package]] name = "valuable" version = "0.1.0" @@ -8166,6 +8321,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + [[package]] name = "waker-fn" version = "1.2.0" @@ -8639,6 +8800,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "x25519-dalek" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" +dependencies = [ + "curve25519-dalek 4.1.3", + "rand_core 0.6.4", + "zeroize", +] + [[package]] name = "xattr" version = "1.3.1" @@ -8723,7 +8895,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c734c171ed591a19dc1127351eb1b4d91864d3e53b2b6e9992bffcb7febf364a" dependencies = [ - "bls12_381_plus 0.8.15", + "bls12_381_plus 0.8.17", "cargo-license", "digest 0.10.7", "dotenv", diff --git a/Cargo.toml b/Cargo.toml index 0c2a1829..db0e7435 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,28 +19,37 @@ edition = "2021" rust-version = "1.76.0" [workspace.dependencies] -did_manager = { git = "https://git@github.com/impierce/did-manager.git", tag = "v1.0.0-beta.3" } -siopv2 = { git = "https://git@github.com/impierce/openid4vc.git", rev = "12fed14" } -oid4vci = { git = "https://git@github.com/impierce/openid4vc.git", rev = "12fed14" } -oid4vc-core = { git = "https://git@github.com/impierce/openid4vc.git", rev = "12fed14" } -oid4vc-manager = { git = "https://git@github.com/impierce/openid4vc.git", rev = "12fed14" } -oid4vp = { git = "https://git@github.com/impierce/openid4vc.git", rev = "12fed14" } +did_manager = { path = "../did-manager" } +# did_manager = { git = "https://git@github.com/impierce/did-manager.git", tag = "v1.0.0-beta.3" } +siopv2 = { path = "../openid4vc/siopv2" } +oid4vci = { path = "../openid4vc/oid4vci" } +oid4vc-core = { path = "../openid4vc/oid4vc-core" } +oid4vc-manager = { path = "../openid4vc/oid4vc-manager" } +oid4vp = { path = "../openid4vc/oid4vp" } +# siopv2 = { git = "https://git@github.com/impierce/openid4vc.git", rev = "12fed14" } +# oid4vci = { git = "https://git@github.com/impierce/openid4vc.git", rev = "12fed14" } +# oid4vc-core = { git = "https://git@github.com/impierce/openid4vc.git", rev = "12fed14" } +# oid4vc-manager = { git = "https://git@github.com/impierce/openid4vc.git", rev = "12fed14" } +# oid4vp = { git = "https://git@github.com/impierce/openid4vc.git", rev = "12fed14" } async-trait = "0.1" axum = { version = "0.7", features = ["tracing"] } base64 = "0.22" cqrs-es = "0.4.2" futures = "0.3" -identity_core = "1.3" -identity_credential = { version = "1.3", default-features = false, features = [ +identity_core = { path = "../identity.rs/identity_core" } +identity_credential = { path = "../identity.rs/identity_credential", default-features = false, features = [ "validator", "credential", "presentation", "domain-linkage", + "sd-jwt-vc" ] } -identity_did = { version = "1.3" } -identity_iota = { version = "1.3" } -identity_verification = { version = "1.3", default-features = false } + +identity_did = { path = "../identity.rs/identity_did" } +identity_document = { path = "../identity.rs/identity_document" } +identity_iota = { path = "../identity.rs/identity_iota" } +identity_verification = { path = "../identity.rs/identity_verification", default-features = false } jsonwebtoken = "9.3" lazy_static = "1.4" mime = { version = "0.3" } diff --git a/agent_api_rest/postman/ssi-agent.postman_collection.json b/agent_api_rest/postman/ssi-agent.postman_collection.json index 827da636..c98e48ba 100644 --- a/agent_api_rest/postman/ssi-agent.postman_collection.json +++ b/agent_api_rest/postman/ssi-agent.postman_collection.json @@ -800,13 +800,18 @@ "exec": [ "const jsonData = JSON.parse(responseBody);", "", - "if (jsonData && typeof jsonData === 'object') {", - " const receivedOfferId = Object.keys(jsonData)[0];", + "if (Array.isArray(jsonData) && jsonData.length > 0) {", + " const firstItem = jsonData[0];", "", - " if (receivedOfferId) {", - " pm.collectionVariables.set(\"RECEIVED_OFFER_ID\", receivedOfferId);", + " if (firstItem && typeof firstItem === 'object') {", + " const receivedOfferId = firstItem.received_offer_id;", + "", + " if (receivedOfferId) {", + " pm.collectionVariables.set(\"RECEIVED_OFFER_ID\", receivedOfferId);", + " }", " }", - "}" + "}", + "" ], "type": "text/javascript", "packages": {} @@ -911,13 +916,18 @@ "exec": [ "const jsonData = JSON.parse(responseBody);", "", - "if (jsonData && typeof jsonData === 'object') {", - " const holderCredentialId = Object.keys(jsonData)[0];", + "if (Array.isArray(jsonData) && jsonData.length > 0) {", + " const firstItem = jsonData[0];", + "", + " if (firstItem && typeof firstItem === 'object') {", + " const holderCredentialId = firstItem.holder_credential_id;", "", - " if (holderCredentialId) {", - " pm.collectionVariables.set(\"HOLDER_CREDENTIAL_ID\", holderCredentialId);", + " if (holderCredentialId) {", + " pm.collectionVariables.set(\"HOLDER_CREDENTIAL_ID\", holderCredentialId);", + " }", " }", - "}" + "}", + "" ], "type": "text/javascript", "packages": {} @@ -926,8 +936,11 @@ { "listen": "prerequest", "script": { - "exec": [], - "type": "text/javascript" + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} } } ], @@ -977,13 +990,18 @@ "exec": [ "const jsonData = JSON.parse(responseBody);", "", - "if (jsonData && typeof jsonData === 'object') {", - " const presentationId = Object.keys(jsonData)[0];", + "if (Array.isArray(jsonData) && jsonData.length > 0) {", + " const firstItem = jsonData[0];", + "", + " if (firstItem && typeof firstItem === 'object') {", + " const presentationId = firstItem.presentation_id;", "", - " if (presentationId) {", - " pm.collectionVariables.set(\"PRESENTATION_ID\", presentationId);", + " if (presentationId) {", + " pm.collectionVariables.set(\"PRESENTATION_ID\", presentationId);", + " }", " }", - "}" + "}", + "" ], "type": "text/javascript", "packages": {} @@ -992,8 +1010,11 @@ { "listen": "prerequest", "script": { - "exec": [], - "type": "text/javascript" + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} } } ], @@ -1125,13 +1146,18 @@ "exec": [ "const jsonData = JSON.parse(responseBody);", "", - "if (jsonData && typeof jsonData === 'object') {", - " const connectionId = Object.keys(jsonData)[0];", + "if (Array.isArray(jsonData) && jsonData.length > 0) {", + " const firstItem = jsonData[0];", + "", + " if (firstItem && typeof firstItem === 'object') {", + " const connectionId = firstItem.connection_id;", "", - " if (connectionId) {", - " pm.collectionVariables.set(\"CONNECTION_ID\", connectionId);", + " if (connectionId) {", + " pm.collectionVariables.set(\"CONNECTION_ID\", connectionId);", + " }", " }", - "}" + "}", + "" ], "type": "text/javascript", "packages": {} @@ -1173,13 +1199,18 @@ "exec": [ "const jsonData = JSON.parse(responseBody);", "", - "if (jsonData && typeof jsonData === 'object') {", - " const connectionId = Object.keys(jsonData)[0];", + "if (Array.isArray(jsonData) && jsonData.length > 0) {", + " const firstItem = jsonData[0];", "", - " if (connectionId) {", - " pm.collectionVariables.set(\"CONNECTION_ID\", connectionId);", + " if (firstItem && typeof firstItem === 'object') {", + " const connectionId = firstItem.connection_id;", + "", + " if (connectionId) {", + " pm.collectionVariables.set(\"CONNECTION_ID\", connectionId);", + " }", " }", - "}" + "}", + "" ], "type": "text/javascript", "packages": {} @@ -1227,13 +1258,18 @@ "exec": [ "const jsonData = JSON.parse(responseBody);", "", - "if (jsonData && typeof jsonData === 'object') {", - " const connectionId = Object.keys(jsonData)[0];", + "if (Array.isArray(jsonData) && jsonData.length > 0) {", + " const firstItem = jsonData[0];", + "", + " if (firstItem && typeof firstItem === 'object') {", + " const connectionId = firstItem.connection_id;", "", - " if (connectionId) {", - " pm.collectionVariables.set(\"CONNECTION_ID\", connectionId);", + " if (connectionId) {", + " pm.collectionVariables.set(\"CONNECTION_ID\", connectionId);", + " }", " }", - "}" + "}", + "" ], "type": "text/javascript", "packages": {} diff --git a/agent_api_rest/src/holder/holder/credentials/mod.rs b/agent_api_rest/src/holder/holder/credentials/mod.rs index ce4cafae..8fa7f1c3 100644 --- a/agent_api_rest/src/holder/holder/credentials/mod.rs +++ b/agent_api_rest/src/holder/holder/credentials/mod.rs @@ -11,7 +11,15 @@ use serde_json::json; #[axum_macros::debug_handler] pub(crate) async fn credentials(State(state): State) -> Response { match query_handler("all_holder_credentials", &state.query.all_holder_credentials).await { - Ok(Some(all_credentials_view)) => (StatusCode::OK, Json(all_credentials_view)).into_response(), + Ok(Some(all_credentials_view)) => { + let all_credentials = all_credentials_view + .credentials + .into_iter() + .map(|(_, credential_view)| credential_view) + .collect::>(); + + (StatusCode::OK, Json(all_credentials)).into_response() + } Ok(None) => (StatusCode::OK, Json(json!({}))).into_response(), _ => StatusCode::INTERNAL_SERVER_ERROR.into_response(), } diff --git a/agent_api_rest/src/holder/holder/offers/accept.rs b/agent_api_rest/src/holder/holder/offers/accept.rs index ead0e36a..83b734ff 100644 --- a/agent_api_rest/src/holder/holder/offers/accept.rs +++ b/agent_api_rest/src/holder/holder/offers/accept.rs @@ -12,20 +12,23 @@ use axum::{ use hyper::StatusCode; #[axum_macros::debug_handler] -pub(crate) async fn accept(State(state): State, Path(offer_id): Path) -> Response { +pub(crate) async fn accept(State(state): State, Path(received_offer_id): Path) -> Response { // TODO: General note that also applies to other endpoints: currently we are using Application Layer logic in the // REST API. This is not ideal and should be changed. The REST API should only be responsible for handling HTTP // Requests and Responses. // Furthermore, the Application Layer (not implemented yet) should be kept very thin as well. See: https://github.com/impierce/ssi-agent/issues/114 // Accept the Credential Offer if it exists - match query_handler(&offer_id, &state.query.received_offer).await { + match query_handler(&received_offer_id, &state.query.received_offer).await { Ok(Some(ReceivedOfferView { .. })) => { let command = OfferCommand::AcceptCredentialOffer { - offer_id: offer_id.clone(), + received_offer_id: received_offer_id.clone(), }; - if command_handler(&offer_id, &state.command.offer, command).await.is_err() { + if command_handler(&received_offer_id, &state.command.offer, command) + .await + .is_err() + { // TODO: add better Error responses. This needs to be done properly in all endpoints once // https://github.com/impierce/openid4vc/issues/78 is fixed. return StatusCode::INTERNAL_SERVER_ERROR.into_response(); @@ -36,34 +39,37 @@ pub(crate) async fn accept(State(state): State, Path(offer_id): Pat } let command = OfferCommand::SendCredentialRequest { - offer_id: offer_id.clone(), + received_offer_id: received_offer_id.clone(), }; // Send the Credential Request - if command_handler(&offer_id, &state.command.offer, command).await.is_err() { + if command_handler(&received_offer_id, &state.command.offer, command) + .await + .is_err() + { // TODO: add better Error responses. This needs to be done properly in all endpoints once // https://github.com/impierce/openid4vc/issues/78 is fixed. return StatusCode::INTERNAL_SERVER_ERROR.into_response(); } - let credentials = match query_handler(&offer_id, &state.query.received_offer).await { + let credentials = match query_handler(&received_offer_id, &state.query.received_offer).await { Ok(Some(ReceivedOfferView { credentials, .. })) => credentials, _ => return StatusCode::INTERNAL_SERVER_ERROR.into_response(), }; for OfferCredential { - credential_id, + holder_credential_id, credential, } in credentials { let command = CredentialCommand::AddCredential { - credential_id: credential_id.clone(), - offer_id: offer_id.clone(), + holder_credential_id: holder_credential_id.clone(), + received_offer_id: received_offer_id.clone(), credential, }; // Add the Credential to the state. - if command_handler(&credential_id, &state.command.credential, command) + if command_handler(&holder_credential_id, &state.command.credential, command) .await .is_err() { @@ -71,7 +77,7 @@ pub(crate) async fn accept(State(state): State, Path(offer_id): Pat } } - match query_handler(&offer_id, &state.query.received_offer).await { + match query_handler(&received_offer_id, &state.query.received_offer).await { Ok(Some(received_offer_view)) => (StatusCode::OK, Json(received_offer_view)).into_response(), Ok(None) => StatusCode::NOT_FOUND.into_response(), _ => StatusCode::INTERNAL_SERVER_ERROR.into_response(), diff --git a/agent_api_rest/src/holder/holder/offers/mod.rs b/agent_api_rest/src/holder/holder/offers/mod.rs index f6ac177d..431130be 100644 --- a/agent_api_rest/src/holder/holder/offers/mod.rs +++ b/agent_api_rest/src/holder/holder/offers/mod.rs @@ -14,7 +14,15 @@ use serde_json::json; #[axum_macros::debug_handler] pub(crate) async fn offers(State(state): State) -> Response { match query_handler("all_received_offers", &state.query.all_received_offers).await { - Ok(Some(all_offers_view)) => (StatusCode::OK, Json(all_offers_view)).into_response(), + Ok(Some(all_received_offers_view)) => { + let all_received_offers = all_received_offers_view + .received_offers + .into_iter() + .map(|(_, credential_view)| credential_view) + .collect::>(); + + (StatusCode::OK, Json(all_received_offers)).into_response() + } Ok(None) => (StatusCode::OK, Json(json!({}))).into_response(), _ => StatusCode::INTERNAL_SERVER_ERROR.into_response(), } diff --git a/agent_api_rest/src/holder/holder/offers/reject.rs b/agent_api_rest/src/holder/holder/offers/reject.rs index eb0ffe17..ce31ce7f 100644 --- a/agent_api_rest/src/holder/holder/offers/reject.rs +++ b/agent_api_rest/src/holder/holder/offers/reject.rs @@ -7,13 +7,16 @@ use axum::{ use hyper::StatusCode; #[axum_macros::debug_handler] -pub(crate) async fn reject(State(state): State, Path(offer_id): Path) -> Response { +pub(crate) async fn reject(State(state): State, Path(received_offer_id): Path) -> Response { let command = OfferCommand::RejectCredentialOffer { - offer_id: offer_id.clone(), + received_offer_id: received_offer_id.clone(), }; // Remove the Credential Offer from the state. - if command_handler(&offer_id, &state.command.offer, command).await.is_err() { + if command_handler(&received_offer_id, &state.command.offer, command) + .await + .is_err() + { // TODO: add better Error responses. This needs to be done properly in all endpoints once // https://github.com/impierce/openid4vc/issues/78 is fixed. return StatusCode::INTERNAL_SERVER_ERROR.into_response(); diff --git a/agent_api_rest/src/holder/holder/presentations/mod.rs b/agent_api_rest/src/holder/holder/presentations/mod.rs index 7fb4db28..85ec5506 100644 --- a/agent_api_rest/src/holder/holder/presentations/mod.rs +++ b/agent_api_rest/src/holder/holder/presentations/mod.rs @@ -17,7 +17,15 @@ use tracing::info; #[axum_macros::debug_handler] pub(crate) async fn get_presentations(State(state): State) -> Response { match query_handler("all_presentations", &state.query.all_presentations).await { - Ok(Some(all_presentations_view)) => (StatusCode::OK, Json(all_presentations_view)).into_response(), + Ok(Some(all_presentations_view)) => { + let all_presentations = all_presentations_view + .presentations + .into_iter() + .map(|(_, credential_view)| credential_view) + .collect::>(); + + (StatusCode::OK, Json(all_presentations)).into_response() + } Ok(None) => (StatusCode::OK, Json(json!({}))).into_response(), _ => StatusCode::INTERNAL_SERVER_ERROR.into_response(), } diff --git a/agent_api_rest/src/holder/openid4vci/mod.rs b/agent_api_rest/src/holder/openid4vci/mod.rs index 95145b61..18686d6b 100644 --- a/agent_api_rest/src/holder/openid4vci/mod.rs +++ b/agent_api_rest/src/holder/openid4vci/mod.rs @@ -24,15 +24,15 @@ pub(crate) async fn offers(State(state): State, Json(payload): Json return (StatusCode::BAD_REQUEST, "invalid payload").into_response(); }; - let offer_id = uuid::Uuid::new_v4().to_string(); + let received_offer_id = uuid::Uuid::new_v4().to_string(); let command = OfferCommand::ReceiveCredentialOffer { - offer_id: offer_id.clone(), + received_offer_id: received_offer_id.clone(), credential_offer, }; // Add the Credential Offer to the state. - match command_handler(&offer_id, &state.command.offer, command).await { + match command_handler(&received_offer_id, &state.command.offer, command).await { Ok(_) => StatusCode::OK.into_response(), // TODO: add better Error responses. This needs to be done properly in all endpoints once // https://github.com/impierce/openid4vc/issues/78 is fixed. diff --git a/agent_api_rest/src/identity/connections/mod.rs b/agent_api_rest/src/identity/connections/mod.rs index 3665e5da..a8cf12ea 100644 --- a/agent_api_rest/src/identity/connections/mod.rs +++ b/agent_api_rest/src/identity/connections/mod.rs @@ -11,7 +11,6 @@ use identity_core::common::Url; use identity_did::DIDUrl; use serde::{Deserialize, Serialize}; use serde_json::json; -use std::collections::HashMap; use tracing::info; #[derive(Deserialize, Serialize)] @@ -91,14 +90,15 @@ pub(crate) async fn get_connections( match query_handler("all_connections", &state.query.all_connections).await { Ok(Some(all_connections_view)) => { - let filtered_connections: HashMap<_, _> = all_connections_view + let filtered_connections: Vec<_> = all_connections_view .connections .into_iter() - .filter(|(_, connection)| { - domain + .filter_map(|(_, connection)| { + (domain .as_ref() .map_or(true, |domain| connection.domain.as_ref() == Some(domain)) - && did.as_ref().map_or(true, |did| connection.dids.contains(did)) + && did.as_ref().map_or(true, |did| connection.dids.contains(did))) + .then_some(connection) }) .collect(); diff --git a/agent_api_rest/src/identity/services/mod.rs b/agent_api_rest/src/identity/services/mod.rs index d18000ff..843ce6a8 100644 --- a/agent_api_rest/src/identity/services/mod.rs +++ b/agent_api_rest/src/identity/services/mod.rs @@ -13,7 +13,15 @@ use serde_json::json; #[axum_macros::debug_handler] pub(crate) async fn services(State(state): State) -> Response { match query_handler("all_services", &state.query.all_services).await { - Ok(Some(all_services_view)) => (StatusCode::OK, Json(all_services_view)).into_response(), + Ok(Some(all_services_view)) => { + let all_services = all_services_view + .services + .into_iter() + .map(|(_, credential_view)| credential_view) + .collect::>(); + + (StatusCode::OK, Json(all_services)).into_response() + } Ok(None) => (StatusCode::OK, Json(json!({}))).into_response(), _ => StatusCode::INTERNAL_SERVER_ERROR.into_response(), } diff --git a/agent_api_rest/src/issuance/credential_issuer/credential.rs b/agent_api_rest/src/issuance/credential_issuer/credential.rs index 2cb7f32c..b9e2376d 100644 --- a/agent_api_rest/src/issuance/credential_issuer/credential.rs +++ b/agent_api_rest/src/issuance/credential_issuer/credential.rs @@ -97,6 +97,7 @@ pub(crate) async fn credential( let mut signed_credentials = vec![]; for credential_id in credential_ids { let command = CredentialCommand::SignCredential { + credential_id: credential_id.clone(), subject_id: subject_id.clone(), overwrite: false, }; diff --git a/agent_api_rest/src/issuance/credentials.rs b/agent_api_rest/src/issuance/credentials.rs index acdf457d..3e86dad1 100644 --- a/agent_api_rest/src/issuance/credentials.rs +++ b/agent_api_rest/src/issuance/credentials.rs @@ -87,10 +87,12 @@ pub(crate) async fn credentials( let command = if is_signed { CredentialCommand::CreateSignedCredential { + credential_id: credential_id.clone(), signed_credential: data, } } else { CredentialCommand::CreateUnsignedCredential { + credential_id: credential_id.clone(), data: Data { raw: data }, credential_configuration, } @@ -161,7 +163,15 @@ pub(crate) async fn credentials( #[axum_macros::debug_handler] pub(crate) async fn all_credentials(State(state): State) -> Response { match query_handler("all_credentials", &state.query.all_credentials).await { - Ok(Some(all_credentials_view)) => (StatusCode::OK, Json(all_credentials_view)).into_response(), + Ok(Some(all_credentials_view)) => { + let all_credentials = all_credentials_view + .credentials + .into_iter() + .map(|(_, credential_view)| credential_view) + .collect::>(); + + (StatusCode::OK, Json(all_credentials)).into_response() + } Ok(None) => (StatusCode::OK, Json(json!({}))).into_response(), _ => StatusCode::INTERNAL_SERVER_ERROR.into_response(), } diff --git a/agent_api_rest/src/issuance/offers/mod.rs b/agent_api_rest/src/issuance/offers/mod.rs index 4f415132..582a575c 100644 --- a/agent_api_rest/src/issuance/offers/mod.rs +++ b/agent_api_rest/src/issuance/offers/mod.rs @@ -85,7 +85,15 @@ pub(crate) async fn offers(State(state): State, Json(payload): Js #[axum_macros::debug_handler] pub(crate) async fn all_offers(State(state): State) -> Response { match query_handler("all_offers", &state.query.all_offers).await { - Ok(Some(all_offers_view)) => (StatusCode::OK, Json(all_offers_view)).into_response(), + Ok(Some(all_offers_view)) => { + let all_offers = all_offers_view + .offers + .into_iter() + .map(|(_, offer_view)| offer_view) + .collect::>(); + + (StatusCode::OK, Json(all_offers)).into_response() + } Ok(None) => (StatusCode::OK, Json(json!({}))).into_response(), _ => StatusCode::INTERNAL_SERVER_ERROR.into_response(), } diff --git a/agent_api_rest/src/verification/authorization_requests.rs b/agent_api_rest/src/verification/authorization_requests.rs index 8c3c6824..fb17104a 100644 --- a/agent_api_rest/src/verification/authorization_requests.rs +++ b/agent_api_rest/src/verification/authorization_requests.rs @@ -23,7 +23,13 @@ use tracing::info; pub(crate) async fn all_authorization_requests(State(state): State) -> Response { match query_handler("all_authorization_requests", &state.query.all_authorization_requests).await { Ok(Some(all_authorization_requests_view)) => { - (StatusCode::OK, Json(all_authorization_requests_view)).into_response() + let all_authorization_requests = all_authorization_requests_view + .authorization_requests + .into_iter() + .map(|(_, authorization_request_view)| authorization_request_view) + .collect::>(); + + (StatusCode::OK, Json(all_authorization_requests)).into_response() } Ok(None) => (StatusCode::OK, Json(json!({}))).into_response(), _ => StatusCode::INTERNAL_SERVER_ERROR.into_response(), diff --git a/agent_holder/src/credential/aggregate.rs b/agent_holder/src/credential/aggregate.rs index 9981d3db..5c438743 100644 --- a/agent_holder/src/credential/aggregate.rs +++ b/agent_holder/src/credential/aggregate.rs @@ -17,8 +17,8 @@ pub struct Data { #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct Credential { - pub credential_id: Option, - pub offer_id: Option, + pub holder_credential_id: String, + pub received_offer_id: Option, pub signed: Option, pub data: Option, } @@ -47,8 +47,8 @@ impl Aggregate for Credential { match command { AddCredential { - credential_id, - offer_id, + holder_credential_id, + received_offer_id, credential, } => { let raw = get_unverified_jwt_claims(&serde_json::json!(credential))? @@ -57,8 +57,8 @@ impl Aggregate for Credential { .ok_or(CredentialDecodingError)?; Ok(vec![CredentialAdded { - credential_id, - offer_id, + holder_credential_id, + received_offer_id, credential, data: Data { raw }, }]) @@ -73,13 +73,13 @@ impl Aggregate for Credential { match event { CredentialAdded { - credential_id, - offer_id, + holder_credential_id, + received_offer_id, credential, data, } => { - self.credential_id = Some(credential_id); - self.offer_id = Some(offer_id); + self.holder_credential_id = holder_credential_id; + self.received_offer_id = Some(received_offer_id); self.signed = Some(credential); self.data = Some(data); } @@ -107,7 +107,7 @@ pub mod credential_tests { use super::*; use crate::credential::aggregate::Credential; use crate::credential::event::CredentialEvent; - use crate::offer::aggregate::test_utils::offer_id; + use crate::offer::aggregate::test_utils::received_offer_id; use agent_issuance::credential::aggregate::test_utils::OPENBADGE_VERIFIABLE_CREDENTIAL_JWT; use agent_secret_manager::service::Service; use cqrs_es::test::TestFramework; @@ -117,17 +117,17 @@ pub mod credential_tests { #[rstest] #[serial_test::serial] - fn test_add_credential(credential_id: String, offer_id: String) { + fn test_add_credential(holder_credential_id: String, received_offer_id: String) { CredentialTestFramework::with(Service::default()) .given_no_previous_events() .when(CredentialCommand::AddCredential { - credential_id: credential_id.clone(), - offer_id: offer_id.clone(), + holder_credential_id: holder_credential_id.clone(), + received_offer_id: received_offer_id.clone(), credential: Jwt::from(OPENBADGE_VERIFIABLE_CREDENTIAL_JWT.to_string()), }) .then_expect_events(vec![CredentialEvent::CredentialAdded { - credential_id, - offer_id, + holder_credential_id, + received_offer_id, credential: Jwt::from(OPENBADGE_VERIFIABLE_CREDENTIAL_JWT.to_string()), data: Data { raw: get_unverified_jwt_claims(&serde_json::json!(OPENBADGE_VERIFIABLE_CREDENTIAL_JWT)).unwrap() @@ -144,7 +144,7 @@ pub mod test_utils { use rstest::*; #[fixture] - pub fn credential_id() -> String { + pub fn holder_credential_id() -> String { generate_random_string() } } diff --git a/agent_holder/src/credential/command.rs b/agent_holder/src/credential/command.rs index 97d83718..33f4e93c 100644 --- a/agent_holder/src/credential/command.rs +++ b/agent_holder/src/credential/command.rs @@ -5,8 +5,8 @@ use serde::Deserialize; #[serde(untagged)] pub enum CredentialCommand { AddCredential { - credential_id: String, - offer_id: String, + holder_credential_id: String, + received_offer_id: String, credential: Jwt, }, } diff --git a/agent_holder/src/credential/event.rs b/agent_holder/src/credential/event.rs index 9a41dcb7..262f8afe 100644 --- a/agent_holder/src/credential/event.rs +++ b/agent_holder/src/credential/event.rs @@ -7,8 +7,8 @@ use super::aggregate::Data; #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] pub enum CredentialEvent { CredentialAdded { - credential_id: String, - offer_id: String, + holder_credential_id: String, + received_offer_id: String, credential: Jwt, data: Data, }, diff --git a/agent_holder/src/credential/queries/mod.rs b/agent_holder/src/credential/queries/mod.rs index fa5d5560..a76470dc 100644 --- a/agent_holder/src/credential/queries/mod.rs +++ b/agent_holder/src/credential/queries/mod.rs @@ -12,13 +12,13 @@ impl View for Credential { match &event.payload { CredentialAdded { - credential_id, - offer_id, + holder_credential_id, + received_offer_id: offer_id, credential, data, } => { - self.credential_id.replace(credential_id.clone()); - self.offer_id.replace(offer_id.clone()); + self.holder_credential_id.clone_from(holder_credential_id); + self.received_offer_id.replace(offer_id.clone()); self.signed.replace(credential.clone()); self.data.replace(data.clone()); } diff --git a/agent_holder/src/offer/aggregate.rs b/agent_holder/src/offer/aggregate.rs index 30d84c04..eec261d5 100644 --- a/agent_holder/src/offer/aggregate.rs +++ b/agent_holder/src/offer/aggregate.rs @@ -26,12 +26,13 @@ pub enum Status { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct OfferCredential { - pub credential_id: String, + pub holder_credential_id: String, pub credential: Jwt, } #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct Offer { + pub received_offer_id: String, pub credential_offer: Option, pub status: Status, pub credential_configurations: Option>, @@ -62,7 +63,7 @@ impl Aggregate for Offer { match command { ReceiveCredentialOffer { - offer_id, + received_offer_id, credential_offer, } => { let wallet = &services.wallet; @@ -94,16 +95,16 @@ impl Aggregate for Offer { .collect(); Ok(vec![CredentialOfferReceived { - offer_id, + received_offer_id, credential_offer: Box::new(credential_offer), credential_configurations, }]) } - AcceptCredentialOffer { offer_id } => { + AcceptCredentialOffer { received_offer_id } => { // TODO: reconsider business logic: can an offer be accepted multiple times? if not, should an error be thrown to the user? if self.status != Status::Pending { warn!( - "Accepting Offer with ID: {offer_id} while its current status is: {:?}", + "Accepting Offer with ID: {received_offer_id} while its current status is: {:?}", self.status ); } @@ -149,16 +150,16 @@ impl Aggregate for Offer { Ok(vec![ CredentialOfferAccepted { - offer_id: offer_id.clone(), + received_offer_id: received_offer_id.clone(), status: Status::Accepted, }, TokenResponseReceived { - offer_id, + received_offer_id, token_response, }, ]) } - SendCredentialRequest { offer_id } => { + SendCredentialRequest { received_offer_id } => { if self.status != Status::Accepted { return Err(CredentialOfferStatusNotAcceptedError); } @@ -190,10 +191,14 @@ impl Aggregate for Offer { 1 => { let credential_configuration_id = &credential_configuration_ids[0]; + info!("TEMP: credential_configuration_id: {:?}", credential_configuration_id); + let credential_configuration = credential_configurations .get(credential_configuration_id) .ok_or(MissingCredentialConfigurationError)?; + info!("TEMP: credential_configuration: {:?}", credential_configuration); + // Get the credential. let credential_response = wallet .get_credential(credential_issuer_metadata, &token_response, credential_configuration) @@ -210,12 +215,12 @@ impl Aggregate for Offer { }; #[cfg(not(feature = "test_utils"))] - let credential_id = uuid::Uuid::new_v4().to_string(); + let holder_credential_id = uuid::Uuid::new_v4().to_string(); #[cfg(feature = "test_utils")] - let credential_id = test_utils::credential_id(); + let holder_credential_id = test_utils::holder_credential_id(); vec![OfferCredential { - credential_id, + holder_credential_id, credential, }] } @@ -227,19 +232,19 @@ impl Aggregate for Offer { info!("credentials: {:?}", credentials); Ok(vec![CredentialResponseReceived { - offer_id, + received_offer_id, status: Status::CredentialsReceived, credentials, }]) } - RejectCredentialOffer { offer_id } => { + RejectCredentialOffer { received_offer_id } => { // TODO: should we 'do nothing' or log a `warn!` message instead of returning an error? if self.status != Status::Pending { return Err(CredentialOfferStatusNotPendingError); } Ok(vec![CredentialOfferRejected { - offer_id, + received_offer_id, status: Status::Rejected, }]) } @@ -311,7 +316,7 @@ pub mod tests { let issuance_state = in_memory::issuance_state(Service::default(), Default::default()).await; initialize(&issuance_state, startup_commands(issuer_url.parse().unwrap())).await; - let offer_id = generate_random_string(); + let received_offer_id = generate_random_string(); let mut app = issuance::router(issuance_state); @@ -323,7 +328,7 @@ pub mod tests { .header(http::header::CONTENT_TYPE, mime::APPLICATION_JSON.as_ref()) .body(Body::from( serde_json::to_vec(&json!({ - "offerId": offer_id, + "offerId": received_offer_id, "credential": { "credentialSubject": { "first_name": "Ferris", @@ -349,7 +354,7 @@ pub mod tests { .header(http::header::CONTENT_TYPE, mime::APPLICATION_JSON.as_ref()) .body(Body::from( serde_json::to_vec(&json!({ - "offerId": offer_id + "offerId": received_offer_id })) .unwrap(), )) @@ -383,19 +388,19 @@ pub mod tests { #[serial_test::serial] #[tokio::test] async fn test_receive_credential_offer( - offer_id: String, + received_offer_id: String, #[future(awt)] credential_offer_parameters: Box, credential_configurations_supported: HashMap, ) { OfferTestFramework::with(Service::default()) .given_no_previous_events() .when_async(OfferCommand::ReceiveCredentialOffer { - offer_id: offer_id.clone(), + received_offer_id: received_offer_id.clone(), credential_offer: CredentialOffer::CredentialOffer(credential_offer_parameters.clone()), }) .await .then_expect_events(vec![OfferEvent::CredentialOfferReceived { - offer_id, + received_offer_id, credential_offer: credential_offer_parameters, credential_configurations: credential_configurations_supported, }]); @@ -405,28 +410,28 @@ pub mod tests { #[serial_test::serial] #[tokio::test] async fn test_accept_credential_offer( - offer_id: String, + received_offer_id: String, #[future(awt)] credential_offer_parameters: Box, #[future(awt)] token_response: TokenResponse, credential_configurations_supported: HashMap, ) { OfferTestFramework::with(Service::default()) .given(vec![OfferEvent::CredentialOfferReceived { - offer_id: offer_id.clone(), + received_offer_id: received_offer_id.clone(), credential_offer: credential_offer_parameters, credential_configurations: credential_configurations_supported, }]) .when_async(OfferCommand::AcceptCredentialOffer { - offer_id: offer_id.clone(), + received_offer_id: received_offer_id.clone(), }) .await .then_expect_events(vec![ OfferEvent::CredentialOfferAccepted { - offer_id: offer_id.clone(), + received_offer_id: received_offer_id.clone(), status: Status::Accepted, }, OfferEvent::TokenResponseReceived { - offer_id, + received_offer_id, token_response, }, ]); @@ -436,7 +441,7 @@ pub mod tests { #[serial_test::serial] #[tokio::test] async fn test_send_credential_request( - offer_id: String, + received_offer_id: String, #[future(awt)] credential_offer_parameters: Box, #[future(awt)] token_response: TokenResponse, credential_configurations_supported: HashMap, @@ -445,25 +450,25 @@ pub mod tests { OfferTestFramework::with(Service::default()) .given(vec![ OfferEvent::CredentialOfferReceived { - offer_id: offer_id.clone(), + received_offer_id: received_offer_id.clone(), credential_offer: credential_offer_parameters, credential_configurations: credential_configurations_supported, }, OfferEvent::CredentialOfferAccepted { - offer_id: offer_id.clone(), + received_offer_id: received_offer_id.clone(), status: Status::Accepted, }, OfferEvent::TokenResponseReceived { - offer_id: offer_id.clone(), + received_offer_id: received_offer_id.clone(), token_response, }, ]) .when_async(OfferCommand::SendCredentialRequest { - offer_id: offer_id.clone(), + received_offer_id: received_offer_id.clone(), }) .await .then_expect_events(vec![OfferEvent::CredentialResponseReceived { - offer_id: offer_id.clone(), + received_offer_id: received_offer_id.clone(), status: Status::CredentialsReceived, credentials: signed_credentials, }]); @@ -473,22 +478,22 @@ pub mod tests { #[serial_test::serial] #[tokio::test] async fn test_reject_credential_offer( - offer_id: String, + received_offer_id: String, #[future(awt)] credential_offer_parameters: Box, credential_configurations_supported: HashMap, ) { OfferTestFramework::with(Service::default()) .given(vec![OfferEvent::CredentialOfferReceived { - offer_id: offer_id.clone(), + received_offer_id: received_offer_id.clone(), credential_offer: credential_offer_parameters, credential_configurations: credential_configurations_supported, }]) .when_async(OfferCommand::RejectCredentialOffer { - offer_id: offer_id.clone(), + received_offer_id: received_offer_id.clone(), }) .await .then_expect_events(vec![OfferEvent::CredentialOfferRejected { - offer_id: offer_id.clone(), + received_offer_id: received_offer_id.clone(), status: Status::Rejected, }]); } @@ -502,17 +507,17 @@ pub mod test_utils { use rstest::*; #[fixture] - pub fn offer_id() -> String { + pub fn received_offer_id() -> String { generate_random_string() } #[fixture] - pub fn credential_id() -> String { - "credential_id".to_string() + pub fn holder_credential_id() -> String { + "holder_credential_id".to_string() } #[fixture] - pub fn signed_credentials(credential_id: String) -> Vec { - vec![OfferCredential { credential_id, credential: Jwt::from("eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa2dFODROQ01wTWVBeDlqSzljZjVXNEc4Z2NaOXh1d0p2RzFlN3dOazhLQ2d0I3o2TWtnRTg0TkNNcE1lQXg5aks5Y2Y1VzRHOGdjWjl4dXdKdkcxZTd3Tms4S0NndCJ9.eyJpc3MiOiJkaWQ6a2V5Ono2TWtnRTg0TkNNcE1lQXg5aks5Y2Y1VzRHOGdjWjl4dXdKdkcxZTd3Tms4S0NndCIsInN1YiI6ImRpZDprZXk6ejZNa2dFODROQ01wTWVBeDlqSzljZjVXNEc4Z2NaOXh1d0p2RzFlN3dOazhLQ2d0IiwiZXhwIjo5OTk5OTk5OTk5LCJpYXQiOjAsInZjIjp7IkBjb250ZXh0IjoiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIl0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImlkIjoiZGlkOmtleTp6Nk1rZ0U4NE5DTXBNZUF4OWpLOWNmNVc0RzhnY1o5eHV3SnZHMWU3d05rOEtDZ3QiLCJkZWdyZWUiOnsidHlwZSI6Ik1hc3RlckRlZ3JlZSIsIm5hbWUiOiJNYXN0ZXIgb2YgT2NlYW5vZ3JhcGh5In0sImZpcnN0X25hbWUiOiJGZXJyaXMiLCJsYXN0X25hbWUiOiJSdXN0YWNlYW4ifSwiaXNzdWVyIjoiZGlkOmtleTp6Nk1rZ0U4NE5DTXBNZUF4OWpLOWNmNVc0RzhnY1o5eHV3SnZHMWU3d05rOEtDZ3QiLCJpc3N1YW5jZURhdGUiOiIyMDEwLTAxLTAxVDAwOjAwOjAwWiJ9fQ.jQEpI7DhjOcmyhPEpfGARwcRyzor_fUvynb43-eqD9175FBoshENX0S-8qlloQ7vbT5gat8TjvcDlGDN720ZBw".to_string())}] + pub fn signed_credentials(holder_credential_id: String) -> Vec { + vec![OfferCredential { holder_credential_id, credential: Jwt::from("eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa2dFODROQ01wTWVBeDlqSzljZjVXNEc4Z2NaOXh1d0p2RzFlN3dOazhLQ2d0I3o2TWtnRTg0TkNNcE1lQXg5aks5Y2Y1VzRHOGdjWjl4dXdKdkcxZTd3Tms4S0NndCJ9.eyJpc3MiOiJkaWQ6a2V5Ono2TWtnRTg0TkNNcE1lQXg5aks5Y2Y1VzRHOGdjWjl4dXdKdkcxZTd3Tms4S0NndCIsInN1YiI6ImRpZDprZXk6ejZNa2dFODROQ01wTWVBeDlqSzljZjVXNEc4Z2NaOXh1d0p2RzFlN3dOazhLQ2d0IiwiZXhwIjo5OTk5OTk5OTk5LCJpYXQiOjAsInZjIjp7IkBjb250ZXh0IjoiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIl0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImlkIjoiZGlkOmtleTp6Nk1rZ0U4NE5DTXBNZUF4OWpLOWNmNVc0RzhnY1o5eHV3SnZHMWU3d05rOEtDZ3QiLCJkZWdyZWUiOnsidHlwZSI6Ik1hc3RlckRlZ3JlZSIsIm5hbWUiOiJNYXN0ZXIgb2YgT2NlYW5vZ3JhcGh5In0sImZpcnN0X25hbWUiOiJGZXJyaXMiLCJsYXN0X25hbWUiOiJSdXN0YWNlYW4ifSwiaXNzdWVyIjoiZGlkOmtleTp6Nk1rZ0U4NE5DTXBNZUF4OWpLOWNmNVc0RzhnY1o5eHV3SnZHMWU3d05rOEtDZ3QiLCJpc3N1YW5jZURhdGUiOiIyMDEwLTAxLTAxVDAwOjAwOjAwWiJ9fQ.jQEpI7DhjOcmyhPEpfGARwcRyzor_fUvynb43-eqD9175FBoshENX0S-8qlloQ7vbT5gat8TjvcDlGDN720ZBw".to_string())}] } } diff --git a/agent_holder/src/offer/command.rs b/agent_holder/src/offer/command.rs index b62b6d36..129dd09c 100644 --- a/agent_holder/src/offer/command.rs +++ b/agent_holder/src/offer/command.rs @@ -5,16 +5,16 @@ use serde::Deserialize; #[serde(untagged)] pub enum OfferCommand { ReceiveCredentialOffer { - offer_id: String, + received_offer_id: String, credential_offer: CredentialOffer, }, AcceptCredentialOffer { - offer_id: String, + received_offer_id: String, }, SendCredentialRequest { - offer_id: String, + received_offer_id: String, }, RejectCredentialOffer { - offer_id: String, + received_offer_id: String, }, } diff --git a/agent_holder/src/offer/event.rs b/agent_holder/src/offer/event.rs index a3f9da8f..74e2ea29 100644 --- a/agent_holder/src/offer/event.rs +++ b/agent_holder/src/offer/event.rs @@ -10,25 +10,25 @@ use std::collections::HashMap; #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] pub enum OfferEvent { CredentialOfferReceived { - offer_id: String, + received_offer_id: String, credential_offer: Box, credential_configurations: HashMap, }, CredentialOfferAccepted { - offer_id: String, + received_offer_id: String, status: Status, }, TokenResponseReceived { - offer_id: String, + received_offer_id: String, token_response: TokenResponse, }, CredentialResponseReceived { - offer_id: String, + received_offer_id: String, status: Status, credentials: Vec, }, CredentialOfferRejected { - offer_id: String, + received_offer_id: String, status: Status, }, } diff --git a/agent_holder/src/offer/queries/all_offers.rs b/agent_holder/src/offer/queries/all_offers.rs index 5c32922a..11b29918 100644 --- a/agent_holder/src/offer/queries/all_offers.rs +++ b/agent_holder/src/offer/queries/all_offers.rs @@ -7,12 +7,12 @@ use std::collections::HashMap; #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub struct AllReceivedOffersView { #[serde(flatten)] - pub offers: HashMap, + pub received_offers: HashMap, } impl View for AllReceivedOffersView { fn update(&mut self, event: &EventEnvelope) { - self.offers + self.received_offers // Get the entry for the aggregate_id .entry(event.aggregate_id.clone()) // or insert a new one if it doesn't exist diff --git a/agent_holder/src/offer/queries/mod.rs b/agent_holder/src/offer/queries/mod.rs index 82f53fdf..4283d5ff 100644 --- a/agent_holder/src/offer/queries/mod.rs +++ b/agent_holder/src/offer/queries/mod.rs @@ -11,10 +11,11 @@ impl View for Offer { match &event.payload { CredentialOfferReceived { + received_offer_id, credential_offer, credential_configurations, - .. } => { + self.received_offer_id.clone_from(received_offer_id); self.credential_offer.replace(*credential_offer.clone()); self.credential_configurations .replace(credential_configurations.clone()); diff --git a/agent_identity/Cargo.toml b/agent_identity/Cargo.toml index 37156612..2a92fbbb 100644 --- a/agent_identity/Cargo.toml +++ b/agent_identity/Cargo.toml @@ -16,7 +16,7 @@ did_manager.workspace = true identity_credential.workspace = true identity_core.workspace = true identity_did.workspace = true -identity_document = { version = "1.3" } +identity_document.workspace = true jsonwebtoken.workspace = true oid4vc-core.workspace = true serde.workspace = true diff --git a/agent_identity/src/service/aggregate.rs b/agent_identity/src/service/aggregate.rs index d10a2327..2bbfa588 100644 --- a/agent_identity/src/service/aggregate.rs +++ b/agent_identity/src/service/aggregate.rs @@ -32,7 +32,7 @@ pub enum ServiceResource { #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct Service { - pub id: String, + pub service_id: String, pub service: Option, pub resource: Option, } @@ -215,12 +215,12 @@ impl Aggregate for Service { service, resource, } => { - self.id = service_id; + self.service_id = service_id; self.service.replace(service); self.resource.replace(resource); } LinkedVerifiablePresentationServiceCreated { service_id, service } => { - self.id = service_id; + self.service_id = service_id; self.service.replace(service); } } diff --git a/agent_identity/src/service/views/mod.rs b/agent_identity/src/service/views/mod.rs index ca6e6df0..89820a70 100644 --- a/agent_identity/src/service/views/mod.rs +++ b/agent_identity/src/service/views/mod.rs @@ -14,12 +14,12 @@ impl View for Service { service, resource, } => { - self.id.clone_from(service_id); + self.service_id.clone_from(service_id); self.service.replace(service.clone()); self.resource.replace(resource.clone()); } LinkedVerifiablePresentationServiceCreated { service_id, service } => { - self.id.clone_from(service_id); + self.service_id.clone_from(service_id); self.service.replace(service.clone()); } } diff --git a/agent_issuance/src/credential/aggregate.rs b/agent_issuance/src/credential/aggregate.rs index f3777d8c..651e1a17 100644 --- a/agent_issuance/src/credential/aggregate.rs +++ b/agent_issuance/src/credential/aggregate.rs @@ -38,6 +38,7 @@ pub enum Status { #[derive(Debug, Clone, Serialize, Deserialize, Default, Derivative)] #[derivative(PartialEq)] pub struct Credential { + pub credential_id: String, pub data: Option, pub credential_configuration: CredentialConfigurationsSupportedObject, pub signed: Option, @@ -64,6 +65,7 @@ impl Aggregate for Credential { match command { CreateUnsignedCredential { + credential_id, data, credential_configuration, } => match &credential_configuration.credential_format { @@ -127,6 +129,7 @@ impl Aggregate for Credential { raw["type"] = json!(type_); return Ok(vec![UnsignedCredentialCreated { + credential_id, data: Data { raw }, credential_configuration, }]); @@ -163,6 +166,7 @@ impl Aggregate for Credential { .map_err(InvalidVerifiableCredentialError)?; return Ok(vec![UnsignedCredentialCreated { + credential_id, data: Data { raw: json!(credential) }, credential_configuration, }]); @@ -175,8 +179,18 @@ impl Aggregate for Credential { } _ => Err(UnsupportedCredentialFormat), }, - CreateSignedCredential { signed_credential } => Ok(vec![SignedCredentialCreated { signed_credential }]), - SignCredential { subject_id, overwrite } => { + CreateSignedCredential { + credential_id, + signed_credential, + } => Ok(vec![SignedCredentialCreated { + credential_id, + signed_credential, + }]), + SignCredential { + credential_id, + subject_id, + overwrite, + } => { if self.signed.is_some() && !overwrite { return Ok(vec![]); } @@ -246,6 +260,7 @@ impl Aggregate for Credential { }; Ok(vec![CredentialSigned { + credential_id, signed_credential, status: Status::Issued, }]) @@ -260,19 +275,27 @@ impl Aggregate for Credential { match event { UnsignedCredentialCreated { + credential_id, data, credential_configuration, } => { + self.credential_id = credential_id; self.data.replace(data); self.credential_configuration = credential_configuration; } - SignedCredentialCreated { signed_credential } => { + SignedCredentialCreated { + credential_id, + signed_credential, + } => { + self.credential_id = credential_id; self.signed.replace(signed_credential); } CredentialSigned { + credential_id, signed_credential, status, } => { + self.credential_id = credential_id; self.signed.replace(signed_credential); self.status = status; } @@ -315,16 +338,19 @@ pub mod credential_tests { #[case] credential_subject: serde_json::Value, #[case] credential_configuration: CredentialConfigurationsSupportedObject, #[case] unsigned_credential: serde_json::Value, + credential_id: String, ) { CredentialTestFramework::with(Service::default()) .given_no_previous_events() .when(CredentialCommand::CreateUnsignedCredential { + credential_id: credential_id.clone(), data: Data { raw: credential_subject, }, credential_configuration: credential_configuration.clone(), }) .then_expect_events(vec![CredentialEvent::UnsignedCredentialCreated { + credential_id, data: Data { raw: unsigned_credential, }, @@ -348,19 +374,23 @@ pub mod credential_tests { #[case] unsigned_credential: serde_json::Value, #[case] credential_configuration: CredentialConfigurationsSupportedObject, #[case] verifiable_credential_jwt: String, + credential_id: String, ) { CredentialTestFramework::with(Service::default()) .given(vec![CredentialEvent::UnsignedCredentialCreated { + credential_id: credential_id.clone(), data: Data { raw: unsigned_credential, }, credential_configuration, }]) .when(CredentialCommand::SignCredential { + credential_id: credential_id.clone(), subject_id: SUBJECT_KEY_DID.identifier("did:key", Algorithm::EdDSA).await.unwrap(), overwrite: false, }) .then_expect_events(vec![CredentialEvent::CredentialSigned { + credential_id, signed_credential: json!(verifiable_credential_jwt), status: Status::Issued, }]) @@ -379,6 +409,7 @@ pub mod test_utils { proof::KeyProofMetadata, ProofType, }; + use rstest::fixture; use serde_json::json; use std::collections::HashMap; @@ -386,6 +417,11 @@ pub mod test_utils { pub const W3C_VC_VERIFIABLE_CREDENTIAL_JWT: &str = "eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa2dFODROQ01wTWVBeDlqSzljZjVXNEc4Z2NaOXh1d0p2RzFlN3dOazhLQ2d0I3o2TWtnRTg0TkNNcE1lQXg5aks5Y2Y1VzRHOGdjWjl4dXdKdkcxZTd3Tms4S0NndCJ9.eyJpc3MiOiJkaWQ6a2V5Ono2TWtnRTg0TkNNcE1lQXg5aks5Y2Y1VzRHOGdjWjl4dXdKdkcxZTd3Tms4S0NndCIsInN1YiI6ImRpZDprZXk6ejZNa2dFODROQ01wTWVBeDlqSzljZjVXNEc4Z2NaOXh1d0p2RzFlN3dOazhLQ2d0IiwiZXhwIjo5OTk5OTk5OTk5LCJpYXQiOjAsInZjIjp7IkBjb250ZXh0IjoiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIl0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImlkIjoiZGlkOmtleTp6Nk1rZ0U4NE5DTXBNZUF4OWpLOWNmNVc0RzhnY1o5eHV3SnZHMWU3d05rOEtDZ3QiLCJmaXJzdF9uYW1lIjoiRmVycmlzIiwibGFzdF9uYW1lIjoiUnVzdGFjZWFuIiwiZGVncmVlIjp7InR5cGUiOiJNYXN0ZXJEZWdyZWUiLCJuYW1lIjoiTWFzdGVyIG9mIE9jZWFub2dyYXBoeSJ9fSwiaXNzdWVyIjoiZGlkOmtleTp6Nk1rZ0U4NE5DTXBNZUF4OWpLOWNmNVc0RzhnY1o5eHV3SnZHMWU3d05rOEtDZ3QiLCJpc3N1YW5jZURhdGUiOiIyMDEwLTAxLTAxVDAwOjAwOjAwWiJ9fQ.MUDBbPJfXe0G9sjVTF3RuR6ukRM0d4N57iMGNFcIKMFPIEdig12v-YFB0qfnSghGcQo8hUw3jzxZXTSJATEgBg"; + #[fixture] + pub fn credential_id() -> String { + "credential_id".to_string() + } + lazy_static! { pub static ref OPENBADGE_CREDENTIAL_CONFIGURATION: CredentialConfigurationsSupportedObject = CredentialConfigurationsSupportedObject { diff --git a/agent_issuance/src/credential/command.rs b/agent_issuance/src/credential/command.rs index f4234d56..6c3a8735 100644 --- a/agent_issuance/src/credential/command.rs +++ b/agent_issuance/src/credential/command.rs @@ -7,13 +7,16 @@ use super::entity::Data; #[serde(untagged)] pub enum CredentialCommand { CreateUnsignedCredential { + credential_id: String, data: Data, credential_configuration: CredentialConfigurationsSupportedObject, }, CreateSignedCredential { + credential_id: String, signed_credential: serde_json::Value, }, SignCredential { + credential_id: String, subject_id: String, // When true, a credential will be re-signed if it already exists. overwrite: bool, diff --git a/agent_issuance/src/credential/event.rs b/agent_issuance/src/credential/event.rs index 001caea1..6d1d1808 100644 --- a/agent_issuance/src/credential/event.rs +++ b/agent_issuance/src/credential/event.rs @@ -8,13 +8,16 @@ use super::{aggregate::Status, entity::Data}; pub enum CredentialEvent { // TODO: rename to `DataCredentialCreated`? UnsignedCredentialCreated { + credential_id: String, data: Data, credential_configuration: CredentialConfigurationsSupportedObject, }, SignedCredentialCreated { + credential_id: String, signed_credential: serde_json::Value, }, CredentialSigned { + credential_id: String, signed_credential: serde_json::Value, status: Status, }, diff --git a/agent_issuance/src/credential/views/mod.rs b/agent_issuance/src/credential/views/mod.rs index 45bbbddf..1e21e94f 100644 --- a/agent_issuance/src/credential/views/mod.rs +++ b/agent_issuance/src/credential/views/mod.rs @@ -10,19 +10,27 @@ impl View for Credential { fn update(&mut self, event: &EventEnvelope) { match &event.payload { CredentialEvent::UnsignedCredentialCreated { + credential_id, data, credential_configuration, } => { + self.credential_id.clone_from(credential_id); self.data.replace(data.clone()); self.credential_configuration = credential_configuration.clone(); } - CredentialEvent::SignedCredentialCreated { signed_credential } => { + CredentialEvent::SignedCredentialCreated { + credential_id, + signed_credential, + } => { + self.credential_id.clone_from(credential_id); self.signed.replace(signed_credential.clone()); } CredentialEvent::CredentialSigned { + credential_id, signed_credential, status, } => { + self.credential_id.clone_from(credential_id); self.signed.replace(signed_credential.clone()); self.status.clone_from(status); } diff --git a/agent_issuance/src/offer/aggregate.rs b/agent_issuance/src/offer/aggregate.rs index 6ae337de..83188339 100644 --- a/agent_issuance/src/offer/aggregate.rs +++ b/agent_issuance/src/offer/aggregate.rs @@ -25,6 +25,7 @@ pub enum Status { #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct Offer { + pub offer_id: String, pub credential_offer: Option, pub subject_id: Option, pub credential_ids: Vec, @@ -215,23 +216,31 @@ impl Aggregate for Offer { match event { CredentialOfferCreated { + offer_id, pre_authorized_code, access_token, credential_offer, - .. } => { + self.offer_id = offer_id; self.pre_authorized_code = pre_authorized_code; self.access_token = access_token; self.credential_offer.replace(credential_offer); } - CredentialsAdded { credential_ids, .. } => { + CredentialsAdded { + offer_id, + credential_ids, + } => { + self.offer_id = offer_id; self.credential_ids = credential_ids; } FormUrlEncodedCredentialOfferCreated { + offer_id, form_url_encoded_credential_offer, - .. + status, } => { + self.offer_id = offer_id; self.form_url_encoded_credential_offer = form_url_encoded_credential_offer; + self.status = status; } CredentialOfferSent { .. } => {} CredentialRequestVerified { subject_id, .. } => { diff --git a/agent_issuance/src/offer/views/mod.rs b/agent_issuance/src/offer/views/mod.rs index bc975c3b..0bcff058 100644 --- a/agent_issuance/src/offer/views/mod.rs +++ b/agent_issuance/src/offer/views/mod.rs @@ -11,10 +11,12 @@ impl View for Offer { match &event.payload { CredentialOfferCreated { + offer_id, pre_authorized_code, access_token, .. } => { + self.offer_id.clone_from(offer_id); self.pre_authorized_code.clone_from(pre_authorized_code); self.access_token.clone_from(access_token) }