commit 067448ce7cccc440f9a71552bbf217c0ba0bfdbd
parent 057f40d6179c3cfdba1089de77fd6af85f2afdd5
Author: Antoine A <>
Date: Wed, 2 Sep 2026 14:02:05 +0200
common: port recent kotlin fixes and port more tests
Diffstat:
14 files changed, 605 insertions(+), 366 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -3,16 +3,10 @@
version = 4
[[package]]
-name = "adler2"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
-
-[[package]]
name = "aho-corasick"
-version = "1.1.4"
+version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
+checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba"
dependencies = [
"memchr",
]
@@ -25,9 +19,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "android_system_properties"
-version = "0.1.5"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc"
dependencies = [
"libc",
]
@@ -176,9 +170,9 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
[[package]]
name = "aws-lc-rs"
-version = "1.17.3"
+version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00bdb5da18dac48ca2cc7cd4a98e533e8635a58e2361d13a1a4ee3888e0d72f1"
+checksum = "ce2b2dcc879c3bae0d371e77c99f2238400ef24ec001394befa67b6e543add9e"
dependencies = [
"aws-lc-sys",
"untrusted 0.7.1",
@@ -187,9 +181,9 @@ dependencies = [
[[package]]
name = "aws-lc-sys"
-version = "0.43.0"
+version = "0.44.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43103168cc76fe62678a375e722fc9cb3a0146159ac5828bc4f0dfd755c2224c"
+checksum = "f09fae7be8bb3174e05c6afdb34199e6dc0c7c04ba9fa237b1967adfbde27483"
dependencies = [
"cc",
"cmake",
@@ -274,9 +268,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "base64"
-version = "0.23.0"
+version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b25655df2c3cdd83c5e5b293b88acd880332b2ddadd7c30ac43144fdc0033da9"
+checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5"
[[package]]
name = "base64ct"
@@ -290,7 +284,7 @@ version = "0.19.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0cd0bd35a28836d528d2b58ad499bc3c5641d59379421b1be9eeb0c2f2b912a"
dependencies = [
- "base64 0.23.0",
+ "base64 0.23.1",
"blowfish",
"getrandom 0.4.3",
"subtle",
@@ -342,9 +336,9 @@ dependencies = [
[[package]]
name = "bstr"
-version = "1.13.0"
+version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f7dc094d718f2e1c1559ad110e27eeaae14a5465d3d56dd6dbd793079fbd530"
+checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f"
dependencies = [
"memchr",
"serde_core",
@@ -396,9 +390,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.4.0"
+version = "1.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9"
+checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273"
dependencies = [
"find-msvc-tools",
"jobserver",
@@ -420,12 +414,12 @@ checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527"
[[package]]
name = "chacha20"
-version = "0.10.1"
+version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81"
+checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06"
dependencies = [
"cfg-if",
- "cpufeatures 0.3.0",
+ "cpufeatures 0.3.1",
"rand_core 0.10.1",
]
@@ -453,9 +447,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.6.4"
+version = "4.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d91e0c145792ef73a6ad36d27c75ac09f1832222a3c209689d90f534685ee5b7"
+checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca"
dependencies = [
"clap_builder",
"clap_derive",
@@ -463,9 +457,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.6.2"
+version = "4.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f09628afdcc538b57f3c6341e9c8e9970f18e4a481690a64974d7023bd33548b"
+checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889"
dependencies = [
"anstream",
"anstyle",
@@ -482,7 +476,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn 3.0.4",
]
[[package]]
@@ -517,9 +511,9 @@ checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
[[package]]
name = "combine"
-version = "4.6.7"
+version = "4.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
+checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e"
dependencies = [
"bytes",
"memchr",
@@ -626,9 +620,9 @@ dependencies = [
[[package]]
name = "cpufeatures"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
+checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566"
dependencies = [
"libc",
]
@@ -650,9 +644,9 @@ checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853"
[[package]]
name = "crc32fast"
-version = "1.5.0"
+version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
+checksum = "8498c871161e1742aaa9d52551b2d6ebdd4c3d45a3be423e3728f33b955be550"
dependencies = [
"cfg-if",
]
@@ -769,9 +763,9 @@ dependencies = [
[[package]]
name = "data-encoding"
-version = "2.11.0"
+version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8"
+checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06"
[[package]]
name = "debug_unsafe"
@@ -901,7 +895,7 @@ checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn 3.0.4",
]
[[package]]
@@ -927,9 +921,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "either"
-version = "1.17.0"
+version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d"
+checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34"
dependencies = [
"serde",
]
@@ -988,9 +982,9 @@ dependencies = [
[[package]]
name = "fast-float2"
-version = "0.2.3"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8eb564c5c7423d25c886fb561d1e4ee69f72354d16918afa32c08811f6b6a55"
+checksum = "c6e8948ce679d00a02a94739ea185595dca7118ed04feb991127e443bd3d761f"
[[package]]
name = "fastrand"
@@ -1011,17 +1005,16 @@ dependencies = [
[[package]]
name = "find-msvc-tools"
-version = "0.1.9"
+version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
+checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890"
[[package]]
name = "flate2"
-version = "1.1.9"
+version = "1.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
+checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb"
dependencies = [
- "miniz_oxide",
"zlib-rs",
]
@@ -1065,9 +1058,9 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]]
name = "futures"
-version = "0.3.33"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a88cf1f829d945f548cf8fec32c61b1f202b6d93b45848602fc02af4b12ad218"
+checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3"
dependencies = [
"futures-channel",
"futures-core",
@@ -1080,9 +1073,9 @@ dependencies = [
[[package]]
name = "futures-channel"
-version = "0.3.33"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae"
+checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4"
dependencies = [
"futures-core",
"futures-sink",
@@ -1090,15 +1083,15 @@ dependencies = [
[[package]]
name = "futures-core"
-version = "0.3.33"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7"
+checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e"
[[package]]
name = "futures-executor"
-version = "0.3.33"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6754879cc9f2c66f88c6e5c35344bb0bdb0708b0352b1201815667c7eabc7458"
+checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432"
dependencies = [
"futures-core",
"futures-task",
@@ -1118,38 +1111,38 @@ dependencies = [
[[package]]
name = "futures-io"
-version = "0.3.33"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a"
+checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed"
[[package]]
name = "futures-macro"
-version = "0.3.33"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b"
+checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.119",
+ "syn 3.0.4",
]
[[package]]
name = "futures-sink"
-version = "0.3.33"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e34418ac499d6305c2fb5ad0ed2f6ac998c5f8ca209b4510f7f94242c647e307"
+checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d"
[[package]]
name = "futures-task"
-version = "0.3.33"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109"
+checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd"
[[package]]
name = "futures-util"
-version = "0.3.33"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa"
+checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc"
dependencies = [
"futures-channel",
"futures-core",
@@ -1219,9 +1212,9 @@ checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b"
[[package]]
name = "globset"
-version = "0.4.19"
+version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e47d37d2ae4464254884b60ab7071be2b876a9c35b696bd018ddcc76847309cd"
+checksum = "07c34a9410465b45bd9787443bc7370f37735bad04b0f0cd57ff1a3186c98988"
dependencies = [
"aho-corasick",
"bstr",
@@ -1232,9 +1225,9 @@ dependencies = [
[[package]]
name = "h2"
-version = "0.4.15"
+version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155"
+checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16"
dependencies = [
"atomic-waker",
"bytes",
@@ -1342,9 +1335,9 @@ dependencies = [
[[package]]
name = "http-body-util"
-version = "0.1.4"
+version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2"
+checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c"
dependencies = [
"bytes",
"futures-core",
@@ -1356,7 +1349,7 @@ dependencies = [
[[package]]
name = "http-client"
version = "1.5.0"
-source = "git+git://git.taler.net/taler-rust.git/#f8078cd31e1046e7ffd587b8ac6bf27793590f99"
+source = "git+git://git.taler.net/taler-rust.git/#48c40c365ac671cbbe1ac2fb359e1a5cf7e165a3"
dependencies = [
"compact_str",
"futures-util",
@@ -1407,9 +1400,9 @@ dependencies = [
[[package]]
name = "hyper"
-version = "1.11.0"
+version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72"
+checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43"
dependencies = [
"atomic-waker",
"bytes",
@@ -1494,9 +1487,9 @@ dependencies = [
[[package]]
name = "icu_collections"
-version = "2.2.0"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c"
+checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513"
dependencies = [
"displaydoc",
"potential_utf",
@@ -1508,9 +1501,9 @@ dependencies = [
[[package]]
name = "icu_locale_core"
-version = "2.2.0"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29"
+checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb"
dependencies = [
"displaydoc",
"litemap",
@@ -1521,9 +1514,9 @@ dependencies = [
[[package]]
name = "icu_normalizer"
-version = "2.2.0"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4"
+checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f"
dependencies = [
"icu_collections",
"icu_normalizer_data",
@@ -1535,16 +1528,17 @@ dependencies = [
[[package]]
name = "icu_normalizer_data"
-version = "2.2.0"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38"
+checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0"
[[package]]
name = "icu_properties"
-version = "2.2.0"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de"
+checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148"
dependencies = [
+ "displaydoc",
"icu_collections",
"icu_locale_core",
"icu_properties_data",
@@ -1555,15 +1549,15 @@ dependencies = [
[[package]]
name = "icu_properties_data"
-version = "2.2.0"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14"
+checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa"
[[package]]
name = "icu_provider"
-version = "2.2.0"
+version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421"
+checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73"
dependencies = [
"displaydoc",
"icu_locale_core",
@@ -1603,9 +1597,9 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "2.14.0"
+version = "2.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
+checksum = "07aa2048142242915a31d35844fb311e0e53fcca590c3a0a40dcf1b841fa09eb"
dependencies = [
"equivalent",
"hashbrown 0.17.1",
@@ -1622,9 +1616,9 @@ dependencies = [
[[package]]
name = "ipnet"
-version = "2.12.0"
+version = "2.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2"
+checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78"
[[package]]
name = "is_terminal_polyfill"
@@ -1744,9 +1738,9 @@ dependencies = [
[[package]]
name = "js-sys"
-version = "0.3.103"
+version = "0.3.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102"
+checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a"
dependencies = [
"cfg-if",
"futures-util",
@@ -1808,7 +1802,7 @@ dependencies = [
"taler-macros",
"taler-test-utils",
"tokio",
- "tower-http 0.7.0",
+ "tower-http 0.7.1",
"tracing",
"url",
"uuid",
@@ -1874,7 +1868,7 @@ dependencies = [
"taler-test-utils",
"thiserror",
"tokio",
- "tower-http 0.7.0",
+ "tower-http 0.7.1",
"tracing",
"zip",
]
@@ -1923,14 +1917,14 @@ dependencies = [
[[package]]
name = "libredox"
-version = "0.1.18"
+version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652"
+checksum = "d7955dfc218a8afb29dfeffd540e3a6e96baeb94fe7138228dd7cc6937fbbf96"
dependencies = [
"bitflags 2.13.1",
"libc",
"plain",
- "redox_syscall 0.9.1",
+ "redox_syscall 0.9.3",
]
[[package]]
@@ -1962,9 +1956,9 @@ dependencies = [
[[package]]
name = "litemap"
-version = "0.8.2"
+version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0"
+checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae"
[[package]]
name = "litrs"
@@ -1983,9 +1977,9 @@ dependencies = [
[[package]]
name = "log"
-version = "0.4.33"
+version = "0.4.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
+checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
[[package]]
name = "lru-slab"
@@ -2047,16 +2041,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
-name = "miniz_oxide"
-version = "0.8.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
-dependencies = [
- "adler2",
- "simd-adler32",
-]
-
-[[package]]
name = "mio"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2137,7 +2121,7 @@ dependencies = [
"num-integer",
"num-iter",
"num-traits",
- "rand 0.8.7",
+ "rand 0.8.8",
"smallvec",
"zeroize",
]
@@ -2150,9 +2134,9 @@ checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441"
[[package]]
name = "num-integer"
-version = "0.1.46"
+version = "0.1.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
+checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b"
dependencies = [
"num-traits",
]
@@ -2206,9 +2190,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
[[package]]
name = "owo-colors"
-version = "4.3.0"
+version = "4.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d"
+checksum = "13c45bb4a6ae1280ec0803b1ef9d3455eb50f01efbbe1447ab020f1d54fba9d8"
[[package]]
name = "parking"
@@ -2253,11 +2237,11 @@ dependencies = [
[[package]]
name = "pem"
-version = "3.0.6"
+version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be"
+checksum = "d354a98a3d1251555de99e8fdd8afda05573c31b82f59063a7b0a29b5527f120"
dependencies = [
- "base64 0.22.1",
+ "base64 0.23.1",
"serde_core",
]
@@ -2305,9 +2289,9 @@ dependencies = [
[[package]]
name = "pkg-config"
-version = "0.3.33"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
+checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
[[package]]
name = "plain"
@@ -2317,9 +2301,9 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
[[package]]
name = "portable-atomic"
-version = "1.14.0"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3"
+checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85"
[[package]]
name = "portable-atomic-util"
@@ -2332,9 +2316,9 @@ dependencies = [
[[package]]
name = "potential_utf"
-version = "0.1.5"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564"
+checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661"
dependencies = [
"zerovec",
]
@@ -2405,9 +2389,9 @@ dependencies = [
[[package]]
name = "quinn-proto"
-version = "0.11.16"
+version = "0.11.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560"
+checksum = "04759210543be93709136e28212294a659ef5001836ff4eab4d663e4529bba83"
dependencies = [
"aws-lc-rs",
"bytes",
@@ -2463,9 +2447,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
[[package]]
name = "rand"
-version = "0.8.7"
+version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a"
+checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c"
dependencies = [
"libc",
"rand_chacha 0.3.1",
@@ -2548,9 +2532,9 @@ dependencies = [
[[package]]
name = "rcgen"
-version = "0.14.8"
+version = "0.14.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57f6d249aad744e274e682777a50283a225a32705394ee6d5fcc01efa25e4055"
+checksum = "8774e05a7d0de114588e6a28fe7e71694b82614ed569d86d8b389dfbc98b8ad8"
dependencies = [
"aws-lc-rs",
"pem",
@@ -2571,9 +2555,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
-version = "0.9.1"
+version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07507be7b4a5f9f26eeb41eeaebb1f5a7ff29dfb29739facc21d35bf8b11c21e"
+checksum = "d678d17679829e73d371e96880897e98fee2ded7acc0a50bdf8af2affa4b2fe5"
dependencies = [
"bitflags 2.13.1",
]
@@ -2612,9 +2596,9 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.4.16"
+version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad"
+checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2"
dependencies = [
"aho-corasick",
"memchr",
@@ -2829,9 +2813,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
[[package]]
name = "rustls-webpki"
-version = "0.103.13"
+version = "0.103.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
+checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2"
dependencies = [
"aws-lc-rs",
"ring",
@@ -2931,7 +2915,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn 3.0.4",
]
[[package]]
@@ -2972,9 +2956,9 @@ dependencies = [
[[package]]
name = "serde_with"
-version = "3.21.0"
+version = "3.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c"
+checksum = "ee78f1fbe43ac4a0e47aadb3dbd357b69eb0d3793e948624cd03dd2750ab1c0a"
dependencies = [
"serde_core",
"serde_with_macros",
@@ -2982,9 +2966,9 @@ dependencies = [
[[package]]
name = "serde_with_macros"
-version = "3.21.0"
+version = "3.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660"
+checksum = "8705578779c2b6bd90d84d66eb2e206b708b1a4d7b9f17641b293545bf1c7e46"
dependencies = [
"darling",
"proc-macro2",
@@ -3259,7 +3243,7 @@ dependencies = [
"memchr",
"once_cell",
"percent-encoding",
- "rand 0.8.7",
+ "rand 0.8.8",
"rsa",
"serde",
"sha1",
@@ -3298,7 +3282,7 @@ dependencies = [
"md-5",
"memchr",
"once_cell",
- "rand 0.8.7",
+ "rand 0.8.8",
"serde",
"serde_json",
"sha2",
@@ -3414,9 +3398,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "3.0.3"
+version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
+checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f"
dependencies = [
"proc-macro2",
"quote",
@@ -3467,7 +3451,7 @@ dependencies = [
[[package]]
name = "taler-api"
version = "1.5.0"
-source = "git+git://git.taler.net/taler-rust.git/#f8078cd31e1046e7ffd587b8ac6bf27793590f99"
+source = "git+git://git.taler.net/taler-rust.git/#48c40c365ac671cbbe1ac2fb359e1a5cf7e165a3"
dependencies = [
"aws-lc-rs",
"axum",
@@ -3486,7 +3470,7 @@ dependencies = [
"taler-common",
"thiserror",
"tokio",
- "tower-http 0.7.0",
+ "tower-http 0.7.1",
"tracing",
"url",
"zlib-rs",
@@ -3495,12 +3479,12 @@ dependencies = [
[[package]]
name = "taler-build"
version = "1.5.0"
-source = "git+git://git.taler.net/taler-rust.git/#f8078cd31e1046e7ffd587b8ac6bf27793590f99"
+source = "git+git://git.taler.net/taler-rust.git/#48c40c365ac671cbbe1ac2fb359e1a5cf7e165a3"
[[package]]
name = "taler-common"
version = "1.5.0"
-source = "git+git://git.taler.net/taler-rust.git/#f8078cd31e1046e7ffd587b8ac6bf27793590f99"
+source = "git+git://git.taler.net/taler-rust.git/#48c40c365ac671cbbe1ac2fb359e1a5cf7e165a3"
dependencies = [
"anyhow",
"aws-lc-rs",
@@ -3530,17 +3514,17 @@ dependencies = [
[[package]]
name = "taler-macros"
version = "1.5.0"
-source = "git+git://git.taler.net/taler-rust.git/#f8078cd31e1046e7ffd587b8ac6bf27793590f99"
+source = "git+git://git.taler.net/taler-rust.git/#48c40c365ac671cbbe1ac2fb359e1a5cf7e165a3"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn 3.0.4",
]
[[package]]
name = "taler-test-utils"
version = "1.5.0"
-source = "git+git://git.taler.net/taler-rust.git/#f8078cd31e1046e7ffd587b8ac6bf27793590f99"
+source = "git+git://git.taler.net/taler-rust.git/#48c40c365ac671cbbe1ac2fb359e1a5cf7e165a3"
dependencies = [
"aws-lc-rs",
"axum",
@@ -3608,22 +3592,22 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "2.0.19"
+version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9"
+checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "2.0.19"
+version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd"
+checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn 3.0.4",
]
[[package]]
@@ -3637,9 +3621,9 @@ dependencies = [
[[package]]
name = "time"
-version = "0.3.54"
+version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e1d5e639ff6bab73cb6885cc7e7b1de96c3f32c68ec55f3952614bec1092244"
+checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134"
dependencies = [
"deranged",
"num-conv",
@@ -3667,9 +3651,9 @@ dependencies = [
[[package]]
name = "tinystr"
-version = "0.8.3"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d"
+checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643"
dependencies = [
"displaydoc",
"zerovec",
@@ -3714,7 +3698,7 @@ checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn 3.0.4",
]
[[package]]
@@ -3801,9 +3785,9 @@ dependencies = [
[[package]]
name = "tower-http"
-version = "0.7.0"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b11f75e912b0c2be01b63d8cf8057b8c3f97cf34abb3d431a3a4c8675498e233"
+checksum = "08a05a66a4fdd61cbbe0a1d755ffe0ca6aba159dd4820936a0ff8a8278245b9c"
dependencies = [
"bitflags 2.13.1",
"bytes",
@@ -4041,9 +4025,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
-version = "1.24.0"
+version = "1.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239"
+checksum = "b5772d71c9be8a8a6ac2117d949c5b224c1b72241bb611d9a3012edcf8af7812"
dependencies = [
"getrandom 0.4.3",
"js-sys",
@@ -4121,9 +4105,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
[[package]]
name = "wasm-bindgen"
-version = "0.2.126"
+version = "0.2.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4"
+checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70"
dependencies = [
"cfg-if",
"once_cell",
@@ -4134,9 +4118,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
-version = "0.4.76"
+version = "0.4.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d"
+checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -4144,9 +4128,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.126"
+version = "0.2.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1"
+checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -4154,9 +4138,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.126"
+version = "0.2.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e"
+checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284"
dependencies = [
"bumpalo",
"proc-macro2",
@@ -4167,18 +4151,18 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.126"
+version = "0.2.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24"
+checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf"
dependencies = [
"unicode-ident",
]
[[package]]
name = "web-sys"
-version = "0.3.103"
+version = "0.3.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141"
+checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -4497,9 +4481,9 @@ checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
[[package]]
name = "writeable"
-version = "0.6.3"
+version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4"
+checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc"
[[package]]
name = "x509-parser"
@@ -4560,18 +4544,18 @@ dependencies = [
[[package]]
name = "zerocopy"
-version = "0.8.55"
+version = "0.8.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb"
+checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
-version = "0.8.55"
+version = "0.8.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb"
+checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1"
dependencies = [
"proc-macro2",
"quote",
@@ -4607,9 +4591,9 @@ checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
[[package]]
name = "zerotrie"
-version = "0.2.4"
+version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf"
+checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f"
dependencies = [
"displaydoc",
"yoke",
@@ -4618,9 +4602,9 @@ dependencies = [
[[package]]
name = "zerovec"
-version = "0.11.6"
+version = "0.11.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239"
+checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8"
dependencies = [
"yoke",
"zerofrom",
@@ -4629,13 +4613,13 @@ dependencies = [
[[package]]
name = "zerovec-derive"
-version = "0.11.3"
+version = "0.11.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555"
+checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.119",
+ "syn 3.0.4",
]
[[package]]
@@ -4654,9 +4638,9 @@ dependencies = [
[[package]]
name = "zlib-rs"
-version = "0.6.6"
+version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b142a20ec14a91d5bc708c1dc21b080c550113d8aa77afa29635673a65dd02c5"
+checksum = "34b31d188d9d685a4f9c7b46d6e36631b07058d2cfe190267adce54dc230bf12"
[[package]]
name = "zmij"
diff --git a/build.gradle b/build.gradle
@@ -1,82 +0,0 @@
-// This file is in the public domain.
-
-plugins {
- id("org.jetbrains.kotlin.jvm") version "2.4.0"
- id("org.jetbrains.dokka") version "2.2.0"
- id("idea")
- id("java-library")
-}
-
-group = "tech.libeufin"
-apply from: 'build-system/version.gradle'
-
-if (!JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)){
- throw new GradleException(
- "This build must be run with java 17 " +
- "or later (your version is java ${JavaVersion.current()})")
-}
-
-allprojects {
- ext {
- set("kotlin_version", "2.4.0")
- set("ktor_version", "3.5.0")
- set("clikt_version", "5.1.0")
- set("coroutines_version", "1.11.0")
- set("postgres_version", "42.7.11")
- set("junixsocket_version", "2.10.1")
- set("shadow_version", "9.4.3")
- set("prometheus_version", "1.6.1")
- }
-
- repositories {
- mavenCentral()
- }
-}
-
-subprojects {
- apply plugin: 'org.jetbrains.dokka'
-
- tasks.withType(Test) {
- // Invalidate tests cache when editing SQL logic
- inputs.dir("$rootDir/database-versioning").withPathSensitivity(PathSensitivity.RELATIVE)
- // Or when editing ISO20022 test samples
- inputs.dir("$rootDir/libeufin-nexus/sample").withPathSensitivity(PathSensitivity.RELATIVE)
- inputs.dir("$rootDir/testbench/sample").withPathSensitivity(PathSensitivity.RELATIVE)
-
- def failedTests = []
-
- afterTest { desc, result ->
- if (result.resultType == TestResult.ResultType.FAILURE) {
- failedTests << "${desc.className}.${desc.name}"
- }
- }
-
- afterSuite { desc, result ->
- if (desc.parent == null && !failedTests.isEmpty()) {
- logger.lifecycle("")
- logger.lifecycle("==== FAILED TESTS ====")
- failedTests.each { logger.lifecycle(it) }
- logger.lifecycle("======================")
- }
- }
-
- testLogging {
- events "failed"
- exceptionFormat = 'full'
- }
- }
-}
-
-task libeufinVersion {
- doLast {
- println project.version
- }
-}
-
-dependencies {
- dokka(project(":libeufin-common:"))
- dokka(project(":libeufin-bank:"))
- dokka(project(":libeufin-nexus:"))
- dokka(project(":libeufin-ebics:"))
- dokka(project(":libeufin-ebisync:"))
-}
diff --git a/database-versioning/libeufin-bank-procedures.sql b/database-versioning/libeufin-bank-procedures.sql
@@ -1508,12 +1508,11 @@ SELECT
amount_local.val, amount_local.frac,
out_missing_amount,
out_amount_differs
- FROM taler_withdrawal_operations AS op
- WHERE op.withdrawal_uuid=in_withdrawal_uuid
- -- Prepared-transfer withdrawals are intentionally unbound until the
- -- first confirmation; ordinary withdrawals are bound at creation.
- AND (op.wallet_bank_account IS NULL
- OR op.wallet_bank_account=wallet_bank_account_local);
+ FROM taler_withdrawal_operations
+ WHERE withdrawal_uuid=in_withdrawal_uuid
+ -- Prepared-transfer withdrawals are intentionally unbound until the
+ -- first confirmation; ordinary withdrawals are bound at creation.
+ AND (wallet_bank_account IS NULL OR wallet_bank_account=wallet_bank_account_local);
out_no_op=NOT FOUND;
IF out_no_op OR already_confirmed OR out_aborted OR out_not_selected OR out_missing_amount OR out_amount_differs OR out_tan_required THEN
RETURN;
@@ -1545,8 +1544,8 @@ END IF;
-- Confirm operation and update amount
UPDATE taler_withdrawal_operations
SET amount=amount_local,
- wallet_bank_account=COALESCE(wallet_bank_account, wallet_bank_account_local),
- confirmation_done=true
+ confirmation_done=true,
+ wallet_bank_account=COALESCE(wallet_bank_account, wallet_bank_account_local)
WHERE withdrawal_uuid=in_withdrawal_uuid;
-- Notify status change
@@ -1703,7 +1702,7 @@ SELECT bank_account_id
-- Check for idempotence and conflict
SELECT (amount_debit != in_amount_debit
OR amount_credit != in_amount_credit
- OR subject != in_subject
+ OR subject != in_subject
OR bank_account != account_id)
, cashout_id
INTO out_request_uid_reuse, out_cashout_id
diff --git a/libeufin-bank/src/api.rs b/libeufin-bank/src/api.rs
@@ -279,7 +279,7 @@ pub mod test {
use crate::{
CONFIG_SOURCE,
api::{
- BankState, MonitorResponse,
+ BankState,
account::{
AccountData, Balance, CreditDebitInfo, create_admin_account, rand_iban_payto,
},
@@ -941,6 +941,7 @@ pub mod test {
#[tokio::test]
async fn corebank() {
+ use crate::api::MonitorResponse;
let ctx = bank_setup().await;
ctx.auth_routine(Method::GET, "/monitor", Auth::Admin).await;
diff --git a/libeufin-bank/src/api/prepared.rs b/libeufin-bank/src/api/prepared.rs
@@ -130,13 +130,17 @@ mod test {
use taler_common::{
api::{
EddsaPublicKey, EddsaSignature,
- prepared::{PublicKeyAlg, RegistrationRequest, TransferType},
+ prepared::{
+ PublicKeyAlg, RegistrationRequest, RegistrationResponse, TransferSubject,
+ TransferType,
+ },
},
db::IncomingType,
error_code::ErrorCode,
types::amount::{Amount, Currency},
};
use taler_test_utils::{
+ json,
routine::{Status, registration_routine},
server::TestServer as _,
};
@@ -147,26 +151,26 @@ mod test {
async fn registration() {
let ctx = bank_setup().await;
- let key_pair1 = Ed25519KeyPair::generate().unwrap();
- let auth_pub1 = EddsaPublicKey::try_from(key_pair1.public_key().as_ref()).unwrap();
+ let key_pair = Ed25519KeyPair::generate().unwrap();
+ let auth_pub = EddsaPublicKey::try_from(key_pair.public_key().as_ref()).unwrap();
let req = RegistrationRequest {
credit_account: ctx.exchange_payto.as_uri(),
r#type: TransferType::reserve,
recurrent: false,
- credit_amount: Amount::new(&Currency::KUDOS, 120, 0),
+ credit_amount: Amount::new(&Currency::KUDOS, 1, 0),
alg: PublicKeyAlg::EdDSA,
- account_pub: auth_pub1,
- authorization_pub: auth_pub1,
+ account_pub: auth_pub,
+ authorization_pub: auth_pub,
authorization_sig: EddsaSignature::ZEROED,
}
- .signed(&key_pair1);
+ .signed(&key_pair);
ctx.post("/taler-prepared-transfer/registration")
.json(
RegistrationRequest {
credit_account: ctx.customer_payto.as_uri(),
..req.clone()
}
- .signed(&key_pair1),
+ .signed(&key_pair),
)
.await
.assert_error(ErrorCode::BANK_ACCOUNT_IS_NOT_EXCHANGE);
@@ -176,7 +180,7 @@ mod test {
credit_account: ctx.unknown_payto.as_uri(),
..req.clone()
}
- .signed(&key_pair1),
+ .signed(&key_pair),
)
.await
.assert_error(ErrorCode::BANK_UNKNOWN_CREDITOR);
@@ -229,37 +233,56 @@ mod test {
)
.await;
- /*
- *
- * // Non recurrent no URI
- client.post("/taler-prepared-transfer/registration") {
- json(valid_req) {
- "type" to "reserve"
- }
- }.assertOkJson<SubjectResult> {
- val uuid = (it.subjects[0] as? TransferSubject.Uri)!!.uri.substringAfterLast('/')
- client.postA("/accounts/customer/withdrawals/$uuid/confirm").assertNoContent() // reserve
- tx("customer", "KUDOS:1", "exchange", "Taler MAP:$pub") // bounce
- tx("customer", "KUDOS:1", "exchange", "Taler MAP:$pub") // bounce
- assertBalance("customer", "-KUDOS:1")
- assertBalance("exchange", "+KUDOS:1")
- }
- * // Withdrawal is aborted on completion
- client.post("/taler-prepared-transfer/registration") {
- json(valid_req) {
- "type" to "kyc"
- }
- }.assertOkJson<SubjectResult> {
- val uuid = (it.subjects[0] as? TransferSubject.Uri)!!.uri.substringAfterLast('/')
- println("UUID $uuid")
- tx("customer", "KUDOS:1", "exchange", "Taler MAP:$pub") // kyc
- tx("customer", "KUDOS:1", "exchange", "Taler MAP:$pub") // bounce
- client.postA("/accounts/customer/withdrawals/$uuid/confirm")
- .assertConflict(TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT) // aborted
- assertBalance("customer", "-KUDOS:2")
- assertBalance("exchange", "+KUDOS:2")
- }
+ ctx.assert_balance("customer", "-504").await;
+ ctx.assert_balance("exchange", "504").await;
+ let subject = &format!("Taler MAP:{auth_pub}");
+
+ // Non recurrent accept on then bounce
+ let res = ctx
+ .post("/taler-prepared-transfer/registration")
+ .json(&req)
+ .await
+ .assert_ok_json::<RegistrationResponse>();
+ let uuid = match &res.subjects[0] {
+ TransferSubject::Uri { uri, .. } => uri.as_str().rsplit('/').next().unwrap(),
+ _ => unreachable!(),
+ };
+ ctx.posta(format!("/accounts/customer/withdrawals/{uuid}/confirm"))
+ .json(json!({}))
+ .await
+ .assert_no_content(); // reserve
+ ctx.posta(format!("/accounts/merchant/withdrawals/{uuid}/confirm"))
+ .json(json!({}))
+ .await
+ .assert_error(ErrorCode::BANK_TRANSACTION_NOT_FOUND);
+ ctx.tx_s("customer", "1", "exchange", subject).await; // bounce
+ ctx.tx_s("customer", "1", "exchange", subject).await; // bounce
+ ctx.assert_balance("customer", "-505").await;
+ ctx.assert_balance("exchange", "505").await;
- */
+ // Withdrawal is aborted on completion
+ let res = ctx
+ .post("/taler-prepared-transfer/registration")
+ .json(
+ RegistrationRequest {
+ r#type: TransferType::kyc,
+ ..req.clone()
+ }
+ .signed(&key_pair),
+ )
+ .await
+ .assert_ok_json::<RegistrationResponse>();
+ let uuid = match &res.subjects[0] {
+ TransferSubject::Uri { uri, .. } => uri.as_str().rsplit('/').next().unwrap(),
+ _ => unreachable!(),
+ };
+ ctx.tx_s("customer", "1", "exchange", subject).await; // kyc
+ ctx.tx_s("customer", "1", "exchange", subject).await; // bounce
+ ctx.posta(format!("/accounts/customer/withdrawals/{uuid}/confirm"))
+ .json(json!({}))
+ .await
+ .assert_error(ErrorCode::BANK_CONFIRM_ABORT_CONFLICT); // Aborted
+ ctx.assert_balance("customer", "-506").await;
+ ctx.assert_balance("exchange", "506").await;
}
}
diff --git a/libeufin-bank/src/api/token.rs b/libeufin-bank/src/api/token.rs
@@ -45,7 +45,7 @@ use crate::{
auth::{TOKEN_PREFIX, TokenScope, UserAuth, UserRAuth, UserRWAuth},
db::{
self,
- token::{TokenCreationResult, access, create},
+ token::{TokenCreationResult, access, create, refresh},
},
mfa::{MfaReq, TokenOp},
};
@@ -84,6 +84,7 @@ pub struct TokenSuccessResponse {
}
pub const TOKEN_DEFAULT_DURATION: Duration = Duration::from_hours(24);
+pub const TOKEN_REFRESH_OVERLAP: Duration = Duration::from_mins(5);
pub fn token_api() -> Router<Arc<BankState>> {
Router::new()
@@ -122,19 +123,36 @@ pub fn token_api() -> Router<Arc<BankState>> {
)?)
}
};
- match create(
- &state.db,
- &auth.username,
- new.as_ref(),
- &creation,
- &expiration,
- &req.scope,
- req.refreshable,
- req.description.as_deref(),
- auth.is_admin() || mfa.is_2fa(),
- )
- .await?
- {
+
+ let res = if let Some(existing) = &auth.token {
+ refresh(
+ &state.db,
+ &auth.username,
+ existing,
+ new.as_ref(),
+ &creation,
+ &expiration,
+ &(creation + TOKEN_REFRESH_OVERLAP),
+ &req.scope,
+ req.refreshable,
+ req.description.as_deref(),
+ )
+ .await?
+ } else {
+ create(
+ &state.db,
+ &auth.username,
+ new.as_ref(),
+ &creation,
+ &expiration,
+ &req.scope,
+ req.refreshable,
+ req.description.as_deref(),
+ auth.is_admin() || mfa.is_2fa(),
+ )
+ .await?
+ };
+ match res {
TokenCreationResult::Success(token_id) => Ok(Json(TokenSuccessResponse {
access_token: format!("{TOKEN_PREFIX}{new}"),
expiration,
@@ -195,10 +213,11 @@ pub fn token_api() -> Router<Arc<BankState>> {
#[cfg(test)]
pub mod test {
- use std::str::FromStr;
+ use std::{str::FromStr, time::Duration};
use axum::http::{Method, header::AUTHORIZATION};
use jiff::Timestamp;
+ use taler_api::db::TypeHelper;
use taler_common::{
api::ErrorDetail,
error_code::ErrorCode,
@@ -410,6 +429,63 @@ pub mod test {
.await
.assert_error(ErrorCode::GENERIC_TOKEN_UNKNOWN);
+ // Refresh overlap is fixed and non sliding
+ let TokenSuccessResponse {
+ access_token: source,
+ expiration: _,
+ token_id: source_id,
+ } = ctx
+ .postpw("/accounts/merchant/token")
+ .json(json!({
+ "scope": "readonly",
+ "refreshable" : true,
+ "duration" : { "d_us" : 86_400_000_000u64 },
+ "description" : "refresh source"
+ }))
+ .await
+ .assert_ok_json::<TokenSuccessResponse>();
+ let before_refresh = Timestamp::now();
+ for i in 0..2 {
+ ctx.post("/accounts/merchant/token")
+ .header(AUTHORIZATION, format!("Bearer {source}"))
+ .json(json!({
+ "scope": "readonly",
+ "description": format!("replacement-{i}")
+ }))
+ .await
+ .assert_ok();
+ }
+ let first_deadline: Timestamp =
+ sqlx::query("SELECT expiration_time FROM bearer_tokens WHERE bearer_token_id=$1")
+ .bind(source_id as i64)
+ .try_map(|it| it.try_get_timestamp(0))
+ .fetch_one(&ctx.state.db)
+ .await
+ .unwrap();
+ assert!(first_deadline > before_refresh + Duration::from_mins(5));
+ assert!(first_deadline < Timestamp::now() + Duration::from_mins(5));
+ // A retry after a lost response may create another replacement, but
+ // must not extend the original token's overlap deadline
+ ctx.post("/accounts/merchant/token")
+ .header(AUTHORIZATION, format!("Bearer {source}"))
+ .json(json!({
+ "scope": "readonly",
+ "description": "replacement-lost-response-retry"
+ }))
+ .await
+ .assert_ok();
+
+ assert!(
+ sqlx::query_scalar::<_, bool>(
+ "SELECT expiration_time=$2 FROM bearer_tokens WHERE bearer_token_id=$1"
+ )
+ .bind(source_id as i64)
+ .bind(first_deadline.as_microsecond())
+ .fetch_one(&ctx.state.db)
+ .await
+ .unwrap()
+ );
+
// 2FA
{
// Setup a known phone 2FA
diff --git a/libeufin-bank/src/api/tx.rs b/libeufin-bank/src/api/tx.rs
@@ -41,7 +41,7 @@ use taler_common::{
use crate::{
api::BankState,
- auth::UserRAuth,
+ auth::{UserOptRAuth, UserRAuth},
db::tx::{TxResult, create, get_by_id, pool_history},
mfa::{BankTxOp, MfaReq},
payto::{BankPayto, FullBankPayto, LibeufinId},
@@ -149,19 +149,20 @@ pub fn tx_api() -> Router<Arc<BankState>> {
},
)
.get(
- async |mut auth: UserRAuth,
+ async |mut auth: UserOptRAuth,
Query(params): Query<HistoryParams>,
State(state): State<Arc<BankState>>| {
let params = params.check()?;
+ let info = auth
+ .bank_info_auth_or_public(&state.db, &state.cfg.ctx)
+ .await?;
let transactions = pool_history(
&state.db,
&state.cfg.ctx,
&state.cfg.regional_currency,
&state.tx_channel,
¶ms,
- auth.bank_info(&state.db, &state.cfg.ctx)
- .await?
- .bank_account_id,
+ info.bank_account_id,
)
.await?;
if transactions.is_empty() {
@@ -412,6 +413,23 @@ pub mod test {
ctx.assert_balance("merchant", "3").await;
ctx.assert_balance("exchange", "-3").await;
+ // Public history is public
+ ctx.patch_admin("/accounts/merchant")
+ .json(json!({ "is_public": true}))
+ .await
+ .assert_no_content();
+ ctx.get("/accounts/merchant/transactions").await.assert_ok();
+ ctx.get("/accounts/customer/transactions")
+ .await
+ .assert_error(ErrorCode::BANK_UNKNOWN_ACCOUNT);
+ ctx.patch_admin("/accounts/merchant")
+ .json(json!({ "is_public": false}))
+ .await
+ .assert_no_content();
+ ctx.get("/accounts/merchant/transactions")
+ .await
+ .assert_error(ErrorCode::BANK_UNKNOWN_ACCOUNT);
+
// Check 2fa
ctx.fill_tan_info("merchant").await;
ctx.assert_balance("merchant", "3").await;
diff --git a/libeufin-bank/src/api/wire.rs b/libeufin-bank/src/api/wire.rs
@@ -670,7 +670,7 @@ pub mod test {
let path = format!("/accounts/exchange/taler-wire-gateway/admin/add-{path}");
ctx.auth_routine(Method::POST, &path, Auth::Admin).await;
let req = json!({
- "amount": format!("KUDOS:44"),
+ "amount": "KUDOS:44",
"debit_account": ctx.customer_payto,
key: EddsaPublicKey::rand(),
});
@@ -688,7 +688,7 @@ pub mod test {
if *ty != IncomingType::map {
ctx.post_admin(&path)
.json(json!(req + {
- "amount": format!("KUDOS:44"),
+ "amount": "KUDOS:44",
}))
.await
.assert_error(ErrorCode::BANK_UNALLOWED_DEBIT);
diff --git a/libeufin-bank/src/api/withdrawal.rs b/libeufin-bank/src/api/withdrawal.rs
@@ -565,7 +565,7 @@ mod test {
async {
tokio::time::sleep(Duration::from_millis(100)).await;
ctx.posta(format!(
- "/accounts/customer/withdrawals/{confirmed}/confirm"
+ "/accounts/merchant/withdrawals/{confirmed}/confirm"
))
.json(json!({}))
.await
@@ -986,6 +986,23 @@ mod test {
.await
.assert_error(ErrorCode::BANK_AMOUNT_DIFFERS);
+ // A selected operation is bound to the account that created it.
+ let uuid = ctx
+ .posta("/accounts/merchant/withdrawals")
+ .json(json!({ "amount": "KUDOS:1" }))
+ .await
+ .assert_ok_json::<BankAccountCreateWithdrawalResponse>()
+ .withdrawal_id;
+ ctx.withdraw_select(uuid).await;
+ ctx.posta(format!("/accounts/customer/withdrawals/{uuid}/confirm"))
+ .json(json!({}))
+ .await
+ .assert_error(ErrorCode::BANK_TRANSACTION_NOT_FOUND);
+ ctx.posta(format!("/accounts/merchant/withdrawals/{uuid}/abort"))
+ .json(json!({}))
+ .await
+ .assert_no_content();
+
// Confirm with amount
let uuid = ctx
.posta("/accounts/merchant/withdrawals")
@@ -1101,7 +1118,7 @@ mod test {
// 2FA without body
ctx.fill_tan_info("merchant").await;
- ctx.assert_balance("merchant", "-6.2").await;
+ ctx.assert_balance("merchant", "-6.48").await;
let uuid = ctx
.posta("/accounts/merchant/withdrawals")
.json(json!({ "amount": "KUDOS:1" }))
@@ -1112,12 +1129,14 @@ mod test {
ctx.posta(format!("/accounts/merchant/withdrawals/{uuid}/confirm"))
.json(json!({}))
.await
- .assert_challenge_check(&ctx, async |_| ctx.assert_balance("merchant", "-6.2").await)
+ .assert_challenge_check(&ctx, async |_| {
+ ctx.assert_balance("merchant", "-6.48").await
+ })
.await
.assert_no_content();
// 2FA with body
- ctx.assert_balance("merchant", "-7.3").await;
+ ctx.assert_balance("merchant", "-7.58").await;
let uuid = ctx
.posta("/accounts/merchant/withdrawals")
.json(json!({}))
@@ -1128,9 +1147,11 @@ mod test {
ctx.posta(format!("/accounts/merchant/withdrawals/{uuid}/confirm"))
.json(json!({ "amount": "KUDOS:1" }))
.await
- .assert_challenge_check(&ctx, async |_| ctx.assert_balance("merchant", "-7.3").await)
+ .assert_challenge_check(&ctx, async |_| {
+ ctx.assert_balance("merchant", "-7.58").await
+ })
.await
.assert_no_content();
- ctx.assert_balance("merchant", "-8.4").await;
+ ctx.assert_balance("merchant", "-8.68").await;
}
}
diff --git a/libeufin-bank/src/auth.rs b/libeufin-bank/src/auth.rs
@@ -264,6 +264,7 @@ impl<S: UserAuthScope> FromRequestParts<Arc<BankState>> for UserAuth<S> {
pub struct UserOptAuth<S> {
pub username: CompactString,
auth_info: Option<BankInfo>,
+ user_info: Option<BankInfo>,
scope: PhantomData<S>,
}
@@ -271,6 +272,33 @@ impl<S> UserOptAuth<S> {
pub fn is_authenticated(&self) -> bool {
self.auth_info.is_some()
}
+
+ /** Retrieve the bank account info for the selected username if authenticated or if public */
+ pub async fn bank_info_auth_or_public(
+ &mut self,
+ db: &PgPool,
+ ctx: &PaytoCtx,
+ ) -> ApiResult<&BankInfo> {
+ if self.user_info.is_none() {
+ if let Some(info) = &self.auth_info
+ && info.username == self.username
+ {
+ return Ok(info);
+ }
+ let info = super::db::account::bank_info(db, ctx, &self.username).await?;
+
+ let Some(info) = info else {
+ todo!("Unknown account")
+ };
+ self.user_info = Some(info);
+ }
+ let info = self.user_info.as_ref().unwrap();
+ if !info.is_public && !self.is_authenticated() {
+ Err(failure_code(ErrorCode::BANK_UNKNOWN_ACCOUNT))
+ } else {
+ Ok(info)
+ }
+ }
}
impl<S: UserAuthScope> FromRequestParts<Arc<BankState>> for UserOptAuth<S> {
@@ -285,6 +313,7 @@ impl<S: UserAuthScope> FromRequestParts<Arc<BankState>> for UserOptAuth<S> {
Ok(Self {
username: auth.username,
auth_info: Some(auth.auth_info),
+ user_info: None,
scope: PhantomData,
})
} else {
@@ -292,6 +321,7 @@ impl<S: UserAuthScope> FromRequestParts<Arc<BankState>> for UserOptAuth<S> {
Ok(Self {
username: username.into(),
auth_info: None,
+ user_info: None,
scope: PhantomData,
})
}
diff --git a/libeufin-bank/src/db.rs b/libeufin-bank/src/db.rs
@@ -230,16 +230,28 @@ pub async fn monitor(
#[cfg(test)]
mod test {
+ use std::time::Duration;
+
+ use jiff::Timestamp;
use taler_common::{
error_code::ErrorCode::BANK_UNALLOWED_DEBIT,
- types::amount::{Currency, Decimal, MAX_VALUE, decimal},
+ types::{
+ amount::{Currency, Decimal, MAX_VALUE, decimal},
+ base32::Base32,
+ },
};
use taler_test_utils::json;
-
- use crate::api::{
- Timeframe,
- conversion::RoundingMode::{self, nearest, up, zero},
- test::bank_setup,
+ use uuid::Uuid;
+
+ use crate::{
+ TanChannel,
+ api::{
+ Timeframe,
+ conversion::RoundingMode::{self, nearest, up, zero},
+ test::bank_setup,
+ },
+ db::tan::{self, SendResult, SolveResult, mark_sent, send, solve},
+ mfa::Operation,
};
#[tokio::test]
@@ -758,4 +770,96 @@ mod test {
monitor_cashin(3, "KUDOS:55.94", "EUR:70").await;
monitor_cashout(3, "KUDOS:22.9", "EUR:28.85").await;
}
+
+ #[tokio::test]
+ async fn tan_challenge() {
+ const VALIDITY_PERIOD: Duration = Duration::from_hours(1);
+ const RETRANSMISSION_PERIOD: Duration = Duration::from_mins(1);
+ const RETRY_COUNTER: u16 = 3;
+
+ let ctx = bank_setup().await;
+
+ let create = async |code: &str, now: &Timestamp| -> Uuid {
+ tan::new(
+ &ctx.state.db,
+ "customer",
+ Operation::withdrawal,
+ &Base32::rand(),
+ &Base32::rand(),
+ code,
+ now,
+ RETRY_COUNTER,
+ VALIDITY_PERIOD,
+ TanChannel::sms,
+ "+88",
+ )
+ .await
+ .unwrap()
+ };
+ let mark_sent = async |id: &Uuid, now: &Timestamp| {
+ mark_sent(&ctx.state.db, id, &(*now + RETRANSMISSION_PERIOD))
+ .await
+ .unwrap()
+ };
+ let send = async |id: &Uuid, now: &Timestamp| -> SendResult {
+ send(&ctx.state.db, id, now, 10).await.unwrap()
+ };
+ let solve = async |id: &Uuid, code: &str, now: &Timestamp| -> SolveResult {
+ solve(&ctx.state.db, id, code, now).await.unwrap()
+ };
+
+ let now = Timestamp::now();
+ let expired = now + VALIDITY_PERIOD;
+ let retransmit = now + RETRANSMISSION_PERIOD;
+
+ const GOOD: &str = "good-code";
+ const BAD: &str = "bad-code";
+
+ // Check basic
+ let id = create(GOOD, &now).await;
+ // Bad code
+ assert_eq!(solve(&id, BAD, &now).await, SolveResult::BadCode);
+ // Good code
+ assert!(matches!(
+ solve(&id, GOOD, &now).await,
+ SolveResult::Success { .. }
+ ));
+ // Never resend a confirmed challenge
+ assert_eq!(send(&id, &now).await, SendResult::Solved);
+ // Confirmed challenge always ok
+ assert!(matches!(
+ solve(&id, GOOD, &now).await,
+ SolveResult::Success { .. }
+ ));
+
+ // Check retry
+ let id = create(GOOD, &now).await;
+ mark_sent(&id, &now).await;
+ // Bad code
+ for _ in 0..RETRY_COUNTER - 1 {
+ assert_eq!(solve(&id, BAD, &now).await, SolveResult::BadCode);
+ }
+ assert_eq!(solve(&id, BAD, &now).await, SolveResult::NoRetry);
+ // Good code fail
+ assert_eq!(solve(&id, GOOD, &now).await, SolveResult::NoRetry);
+ // Exhausted challenge IDs are terminal and cannot be resent
+ assert_eq!(send(&id, &now).await, SendResult::Expired);
+
+ // Check retransmission
+ let id = create(GOOD, &now).await;
+ // Failed to send retransmit
+ assert!(matches!(send(&id, &now).await, SendResult::Send { .. }));
+ // Code successfully sent and still valid
+ mark_sent(&id, &now).await;
+ assert!(matches!(send(&id, &now).await, SendResult::Success { .. }));
+ // Code is still valid but should be resent
+ assert!(matches!(
+ send(&id, &retransmit).await,
+ SendResult::Send { .. }
+ ));
+ // Good code fail because expired
+ assert_eq!(solve(&id, GOOD, &expired).await, SolveResult::Expired);
+ // Expired challenge IDs are terminal and cannot be resent
+ assert_eq!(send(&id, &expired).await, SendResult::Expired);
+ }
}
diff --git a/libeufin-bank/src/db/account.rs b/libeufin-bank/src/db/account.rs
@@ -580,6 +580,7 @@ pub async fn check_password(
bank_account_id,
internal_payto,
is_taler_exchange,
+ is_public,
name,
tan_channels,
email,
@@ -596,6 +597,7 @@ pub async fn check_password(
payto: sql_bank_payto(&r, ctx, "internal_payto", "name")?,
bank_account_id: r.try_get_u64("bank_account_id")?,
is_exchange: r.try_get("is_taler_exchange")?,
+ is_public: r.try_get("is_public")?,
phone: r.try_get("phone")?,
email: r.try_get("email")?,
channels: r.try_get("tan_channels")?,
@@ -645,6 +647,7 @@ pub struct BankInfo {
pub payto: FullBankPayto,
pub bank_account_id: u64,
pub is_exchange: bool,
+ pub is_public: bool,
pub phone: Option<CompactString>,
pub email: Option<CompactString>,
pub channels: Vec<TanChannel>,
@@ -684,6 +687,7 @@ pub async fn bank_info(
internal_payto,
name,
is_taler_exchange,
+ is_public,
tan_channels,
email,
phone
@@ -699,6 +703,7 @@ pub async fn bank_info(
payto: sql_bank_payto(&r, ctx, "internal_payto", "name")?,
bank_account_id: r.try_get_u64("bank_account_id")?,
is_exchange: r.try_get("is_taler_exchange")?,
+ is_public: r.try_get("is_public")?,
phone: r.try_get("phone")?,
email: r.try_get("email")?,
channels: r.try_get("tan_channels")?,
diff --git a/libeufin-bank/src/db/tan.rs b/libeufin-bank/src/db/tan.rs
@@ -92,6 +92,7 @@ pub async fn new(
}
/** Result of TAN challenge transmission */
+#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SendResult {
Send {
info: CompactString,
@@ -125,6 +126,7 @@ pub async fn send(
,code
,tan_channel
,tan_info
+ ,retry_counter
-- If this is the first time we submit this challenge check there is not too many active challenges
,(retransmission_date = 0 AND (
SELECT count(*) >= $1
@@ -143,14 +145,16 @@ pub async fn send(
.try_map(|r: PgRow| Ok(
if r.try_get("solved")? {
SendResult::Solved
+ } else if r.try_get::<i32, _>("retry_counter")? <= 0 {
+ SendResult::Expired
} else if r.try_get("too_many")? {
SendResult::TooMany
} else {
- let retransmission = r.try_get_timestamp ("retransmission_date")?;
+ let retransmission = r.try_get_timestamp("retransmission_date")?;
let expiration = r.try_get_timestamp("expiration_date")?;
- if expiration < *now {
+ if expiration <= *now {
SendResult::Expired
- } else if retransmission < *now {
+ } else if retransmission <= *now {
SendResult::Send {
info: r.try_get("tan_info")?,
channel: r.try_get("tan_channel")?,
@@ -181,6 +185,7 @@ pub async fn mark_sent(db: &PgPool, uuid: &Uuid, retransmission: &Timestamp) ->
}
/** Result of TAN challenge solution */
+#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SolveResult {
Success {
op: Operation,
diff --git a/libeufin-bank/src/db/token.rs b/libeufin-bank/src/db/token.rs
@@ -83,6 +83,59 @@ pub async fn create(
)
}
+/** Create new token for [username] */
+pub async fn refresh(
+ db: &PgPool,
+ username: &str,
+ source: &[u8],
+ content: &[u8],
+ creation: &Timestamp,
+ expiration: &TalerTimestamp,
+ source_expiration_cap: &Timestamp,
+ scope: &TokenScope,
+ is_refreshable: bool,
+ description: Option<&str>,
+) -> sqlx::Result<TokenCreationResult> {
+ serialized!(
+ sqlx::query(
+ "
+ WITH source_token AS (
+ UPDATE bearer_tokens
+ SET expiration_time=LEAST(expiration_time, $1)
+ WHERE content=$2
+ AND bank_customer=(
+ SELECT customer_id FROM customers
+ WHERE username=$3 AND deleted_at IS NULL
+ )
+ RETURNING bank_customer
+ )
+ INSERT INTO bearer_tokens (
+ content, creation_time, expiration_time, scope, bank_customer,
+ is_refreshable, description, last_access
+ )
+ SELECT $4, $5, $6, $7, bank_customer, $8, $9, $5
+ FROM source_token
+ RETURNING bearer_token_id
+ "
+ )
+ .bind_timestamp(source_expiration_cap)
+ .bind(source)
+ .bind(username)
+ .bind(content)
+ .bind_timestamp(creation)
+ .bind(expiration)
+ .bind(scope)
+ .bind(is_refreshable)
+ .bind(description)
+ .try_map(|r: PgRow| {
+ Ok(TokenCreationResult::Success(
+ r.try_get_u64("bearer_token_id")?,
+ ))
+ })
+ .fetch_one(db)
+ )
+}
+
/** Get info for [token] */
pub async fn access(
db: &PgPool,
@@ -139,6 +192,7 @@ pub async fn access_info(
is_refreshable,
username,
is_taler_exchange,
+ is_public,
bank_account_id,
internal_payto,
name,
@@ -162,6 +216,7 @@ pub async fn access_info(
payto: sql_bank_payto(&r, ctx, "internal_payto", "name")?,
bank_account_id: r.try_get_u64("bank_account_id")?,
is_exchange: r.try_get("is_taler_exchange")?,
+ is_public: r.try_get("is_public")?,
phone: r.try_get("phone")?,
email: r.try_get("email")?,
channels: r.try_get("tan_channels")?,