Fix compatbilité de version sur projet neuf
EBO <eric.bouhana@softalys.com> committé le 2026-07-31 19:01
46318ea11d5058d6d99869a702bc4d744cb63eab
1 parent(s)
16 fichiers modifiés
+826
-297
M
Cargo.lock
+247
-254
@@ -34,7 +34,7 @@ dependencies = [
| 34 | 34 | "rsa", |
| 35 | 35 | "serde", |
| 36 | 36 | "serde_json", |
| 37 | - "sha2", | |
| 37 | + "sha2 0.10.9", | |
| 38 | 38 | "thiserror 2.0.18", |
| 39 | 39 | "tokio", |
| 40 | 40 | "tower", |
@@ -64,7 +64,7 @@ version = "0.5.2"
| 64 | 64 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 65 | 65 | checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" |
| 66 | 66 | dependencies = [ |
| 67 | - "crypto-common", | |
| 67 | + "crypto-common 0.1.7", | |
| 68 | 68 | "generic-array", |
| 69 | 69 | ] |
| 70 | 70 |
@@ -76,7 +76,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
| 76 | 76 | dependencies = [ |
| 77 | 77 | "cfg-if", |
| 78 | 78 | "cipher", |
| 79 | - "cpufeatures", | |
| 79 | + "cpufeatures 0.2.17", | |
| 80 | 80 | ] |
| 81 | 81 | |
| 82 | 82 | [[package]] |
@@ -725,6 +725,15 @@ dependencies = [
| 725 | 725 | ] |
| 726 | 726 | |
| 727 | 727 | [[package]] |
| 728 | +name = "block-buffer" | |
| 729 | +version = "0.12.1" | |
| 730 | +source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 731 | +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" | |
| 732 | +dependencies = [ | |
| 733 | + "hybrid-array", | |
| 734 | +] | |
| 735 | + | |
| 736 | +[[package]] | |
| 728 | 737 | name = "blowfish" |
| 729 | 738 | version = "0.9.1" |
| 730 | 739 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -848,6 +857,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
| 848 | 857 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" |
| 849 | 858 | |
| 850 | 859 | [[package]] |
| 860 | +name = "chacha20" | |
| 861 | +version = "0.10.1" | |
| 862 | +source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 863 | +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" | |
| 864 | +dependencies = [ | |
| 865 | + "cfg-if", | |
| 866 | + "cpufeatures 0.3.0", | |
| 867 | + "rand_core 0.10.1", | |
| 868 | +] | |
| 869 | + | |
| 870 | +[[package]] | |
| 851 | 871 | name = "chrono" |
| 852 | 872 | version = "0.4.44" |
| 853 | 873 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -867,7 +887,7 @@ version = "0.4.4"
| 867 | 887 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 868 | 888 | checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" |
| 869 | 889 | dependencies = [ |
| 870 | - "crypto-common", | |
| 890 | + "crypto-common 0.1.7", | |
| 871 | 891 | "inout", |
| 872 | 892 | ] |
| 873 | 893 |
@@ -912,6 +932,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
| 912 | 932 | checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" |
| 913 | 933 | |
| 914 | 934 | [[package]] |
| 935 | +name = "cmov" | |
| 936 | +version = "0.5.4" | |
| 937 | +source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 938 | +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" | |
| 939 | + | |
| 940 | +[[package]] | |
| 915 | 941 | name = "colorchoice" |
| 916 | 942 | version = "1.0.4" |
| 917 | 943 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1024,6 +1050,15 @@ dependencies = [
| 1024 | 1050 | ] |
| 1025 | 1051 | |
| 1026 | 1052 | [[package]] |
| 1053 | +name = "cpufeatures" | |
| 1054 | +version = "0.3.0" | |
| 1055 | +source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1056 | +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" | |
| 1057 | +dependencies = [ | |
| 1058 | + "libc", | |
| 1059 | +] | |
| 1060 | + | |
| 1061 | +[[package]] | |
| 1027 | 1062 | name = "crc" |
| 1028 | 1063 | version = "3.4.0" |
| 1029 | 1064 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1116,6 +1151,15 @@ dependencies = [
| 1116 | 1151 | ] |
| 1117 | 1152 | |
| 1118 | 1153 | [[package]] |
| 1154 | +name = "crypto-common" | |
| 1155 | +version = "0.2.2" | |
| 1156 | +source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1157 | +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" | |
| 1158 | +dependencies = [ | |
| 1159 | + "hybrid-array", | |
| 1160 | +] | |
| 1161 | + | |
| 1162 | +[[package]] | |
| 1119 | 1163 | name = "cssparser" |
| 1120 | 1164 | version = "0.35.0" |
| 1121 | 1165 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1148,15 +1192,24 @@ dependencies = [
| 1148 | 1192 | ] |
| 1149 | 1193 | |
| 1150 | 1194 | [[package]] |
| 1195 | +name = "ctutils" | |
| 1196 | +version = "0.4.2" | |
| 1197 | +source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1198 | +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" | |
| 1199 | +dependencies = [ | |
| 1200 | + "cmov", | |
| 1201 | +] | |
| 1202 | + | |
| 1203 | +[[package]] | |
| 1151 | 1204 | name = "curve25519-dalek" |
| 1152 | 1205 | version = "4.1.3" |
| 1153 | 1206 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1154 | 1207 | checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" |
| 1155 | 1208 | dependencies = [ |
| 1156 | 1209 | "cfg-if", |
| 1157 | - "cpufeatures", | |
| 1210 | + "cpufeatures 0.2.17", | |
| 1158 | 1211 | "curve25519-dalek-derive", |
| 1159 | - "digest", | |
| 1212 | + "digest 0.10.7", | |
| 1160 | 1213 | "fiat-crypto", |
| 1161 | 1214 | "rustc_version", |
| 1162 | 1215 | "subtle", |
@@ -1298,6 +1351,17 @@ dependencies = [
| 1298 | 1351 | ] |
| 1299 | 1352 | |
| 1300 | 1353 | [[package]] |
| 1354 | +name = "derive-where" | |
| 1355 | +version = "1.6.1" | |
| 1356 | +source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1357 | +checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534" | |
| 1358 | +dependencies = [ | |
| 1359 | + "proc-macro2", | |
| 1360 | + "quote", | |
| 1361 | + "syn 2.0.117", | |
| 1362 | +] | |
| 1363 | + | |
| 1364 | +[[package]] | |
| 1301 | 1365 | name = "derive_builder" |
| 1302 | 1366 | version = "0.20.2" |
| 1303 | 1367 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1370,13 +1434,24 @@ version = "0.10.7"
| 1370 | 1434 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1371 | 1435 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" |
| 1372 | 1436 | dependencies = [ |
| 1373 | - "block-buffer", | |
| 1437 | + "block-buffer 0.10.4", | |
| 1374 | 1438 | "const-oid", |
| 1375 | - "crypto-common", | |
| 1439 | + "crypto-common 0.1.7", | |
| 1376 | 1440 | "subtle", |
| 1377 | 1441 | ] |
| 1378 | 1442 | |
| 1379 | 1443 | [[package]] |
| 1444 | +name = "digest" | |
| 1445 | +version = "0.11.3" | |
| 1446 | +source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1447 | +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" | |
| 1448 | +dependencies = [ | |
| 1449 | + "block-buffer 0.12.1", | |
| 1450 | + "crypto-common 0.2.2", | |
| 1451 | + "ctutils", | |
| 1452 | +] | |
| 1453 | + | |
| 1454 | +[[package]] | |
| 1380 | 1455 | name = "displaydoc" |
| 1381 | 1456 | version = "0.2.5" |
| 1382 | 1457 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1421,7 +1496,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
| 1421 | 1496 | checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" |
| 1422 | 1497 | dependencies = [ |
| 1423 | 1498 | "der", |
| 1424 | - "digest", | |
| 1499 | + "digest 0.10.7", | |
| 1425 | 1500 | "elliptic-curve", |
| 1426 | 1501 | "rfc6979", |
| 1427 | 1502 | "signature", |
@@ -1447,7 +1522,7 @@ dependencies = [
| 1447 | 1522 | "curve25519-dalek", |
| 1448 | 1523 | "ed25519", |
| 1449 | 1524 | "serde", |
| 1450 | - "sha2", | |
| 1525 | + "sha2 0.10.9", | |
| 1451 | 1526 | "subtle", |
| 1452 | 1527 | "zeroize", |
| 1453 | 1528 | ] |
@@ -1469,11 +1544,11 @@ checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
| 1469 | 1544 | dependencies = [ |
| 1470 | 1545 | "base16ct", |
| 1471 | 1546 | "crypto-bigint", |
| 1472 | - "digest", | |
| 1547 | + "digest 0.10.7", | |
| 1473 | 1548 | "ff", |
| 1474 | 1549 | "generic-array", |
| 1475 | 1550 | "group", |
| 1476 | - "hkdf", | |
| 1551 | + "hkdf 0.12.4", | |
| 1477 | 1552 | "pem-rfc7468", |
| 1478 | 1553 | "pkcs8", |
| 1479 | 1554 | "rand_core 0.6.4", |
@@ -1555,13 +1630,12 @@ dependencies = [
| 1555 | 1630 | |
| 1556 | 1631 | [[package]] |
| 1557 | 1632 | name = "etcetera" |
| 1558 | -version = "0.8.0" | |
| 1633 | +version = "0.11.0" | |
| 1559 | 1634 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1560 | -checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" | |
| 1635 | +checksum = "de48cc4d1c1d97a20fd819def54b890cadde72ed3ad0c614822a0a433361be96" | |
| 1561 | 1636 | dependencies = [ |
| 1562 | 1637 | "cfg-if", |
| 1563 | - "home", | |
| 1564 | - "windows-sys 0.48.0", | |
| 1638 | + "windows-sys 0.61.2", | |
| 1565 | 1639 | ] |
| 1566 | 1640 | |
| 1567 | 1641 | [[package]] |
@@ -1643,9 +1717,9 @@ dependencies = [
| 1643 | 1717 | |
| 1644 | 1718 | [[package]] |
| 1645 | 1719 | name = "flume" |
| 1646 | -version = "0.11.1" | |
| 1720 | +version = "0.12.0" | |
| 1647 | 1721 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1648 | -checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" | |
| 1722 | +checksum = "5e139bc46ca777eb5efaf62df0ab8cc5fd400866427e56c68b22e414e53bd3be" | |
| 1649 | 1723 | dependencies = [ |
| 1650 | 1724 | "futures-core", |
| 1651 | 1725 | "futures-sink", |
@@ -1903,6 +1977,7 @@ dependencies = [
| 1903 | 1977 | "cfg-if", |
| 1904 | 1978 | "libc", |
| 1905 | 1979 | "r-efi 6.0.0", |
| 1980 | + "rand_core 0.10.1", | |
| 1906 | 1981 | "wasip2", |
| 1907 | 1982 | "wasip3", |
| 1908 | 1983 | ] |
@@ -1986,8 +2061,6 @@ version = "0.15.5"
| 1986 | 2061 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1987 | 2062 | checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" |
| 1988 | 2063 | dependencies = [ |
| 1989 | - "allocator-api2", | |
| 1990 | - "equivalent", | |
| 1991 | 2064 | "foldhash 0.1.5", |
| 1992 | 2065 | ] |
| 1993 | 2066 |
@@ -1997,20 +2070,13 @@ version = "0.16.1"
| 1997 | 2070 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1998 | 2071 | checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" |
| 1999 | 2072 | dependencies = [ |
| 2073 | + "allocator-api2", | |
| 2074 | + "equivalent", | |
| 2000 | 2075 | "foldhash 0.2.0", |
| 2001 | 2076 | ] |
| 2002 | 2077 | |
| 2003 | 2078 | [[package]] |
| 2004 | 2079 | name = "hashlink" |
| 2005 | -version = "0.10.0" | |
| 2006 | -source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 2007 | -checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" | |
| 2008 | -dependencies = [ | |
| 2009 | - "hashbrown 0.15.5", | |
| 2010 | -] | |
| 2011 | - | |
| 2012 | -[[package]] | |
| 2013 | -name = "hashlink" | |
| 2014 | 2080 | version = "0.11.0" |
| 2015 | 2081 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2016 | 2082 | checksum = "ea0b22561a9c04a7cb1a302c013e0259cd3b4bb619f145b32f72b8b4bcbed230" |
@@ -2048,7 +2114,16 @@ version = "0.12.4"
| 2048 | 2114 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2049 | 2115 | checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" |
| 2050 | 2116 | dependencies = [ |
| 2051 | - "hmac", | |
| 2117 | + "hmac 0.12.1", | |
| 2118 | +] | |
| 2119 | + | |
| 2120 | +[[package]] | |
| 2121 | +name = "hkdf" | |
| 2122 | +version = "0.13.0" | |
| 2123 | +source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 2124 | +checksum = "4aaa26c720c68b866f2c96ef5c1264b3e6f473fe5d4ce61cd44bbe913e553018" | |
| 2125 | +dependencies = [ | |
| 2126 | + "hmac 0.13.0", | |
| 2052 | 2127 | ] |
| 2053 | 2128 | |
| 2054 | 2129 | [[package]] |
@@ -2057,16 +2132,16 @@ version = "0.12.1"
| 2057 | 2132 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2058 | 2133 | checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" |
| 2059 | 2134 | dependencies = [ |
| 2060 | - "digest", | |
| 2135 | + "digest 0.10.7", | |
| 2061 | 2136 | ] |
| 2062 | 2137 | |
| 2063 | 2138 | [[package]] |
| 2064 | -name = "home" | |
| 2065 | -version = "0.5.12" | |
| 2139 | +name = "hmac" | |
| 2140 | +version = "0.13.0" | |
| 2066 | 2141 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2067 | -checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" | |
| 2142 | +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" | |
| 2068 | 2143 | dependencies = [ |
| 2069 | - "windows-sys 0.61.2", | |
| 2144 | + "digest 0.11.3", | |
| 2070 | 2145 | ] |
| 2071 | 2146 | |
| 2072 | 2147 | [[package]] |
@@ -2151,7 +2226,7 @@ dependencies = [
| 2151 | 2226 | "httpdate", |
| 2152 | 2227 | "reqwest 0.13.3", |
| 2153 | 2228 | "reqwest-middleware", |
| 2154 | - "sha2", | |
| 2229 | + "sha2 0.10.9", | |
| 2155 | 2230 | "tokio", |
| 2156 | 2231 | ] |
| 2157 | 2232 |
@@ -2168,6 +2243,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
| 2168 | 2243 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" |
| 2169 | 2244 | |
| 2170 | 2245 | [[package]] |
| 2246 | +name = "hybrid-array" | |
| 2247 | +version = "0.4.14" | |
| 2248 | +source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 2249 | +checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" | |
| 2250 | +dependencies = [ | |
| 2251 | + "typenum", | |
| 2252 | +] | |
| 2253 | + | |
| 2254 | +[[package]] | |
| 2171 | 2255 | name = "hyper" |
| 2172 | 2256 | version = "1.8.1" |
| 2173 | 2257 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -2458,17 +2542,6 @@ dependencies = [
| 2458 | 2542 | ] |
| 2459 | 2543 | |
| 2460 | 2544 | [[package]] |
| 2461 | -name = "inherent" | |
| 2462 | -version = "1.0.13" | |
| 2463 | -source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 2464 | -checksum = "c727f80bfa4a6c6e2508d2f05b6f4bfce242030bd88ed15ae5331c5b5d30fba7" | |
| 2465 | -dependencies = [ | |
| 2466 | - "proc-macro2", | |
| 2467 | - "quote", | |
| 2468 | - "syn 2.0.117", | |
| 2469 | -] | |
| 2470 | - | |
| 2471 | -[[package]] | |
| 2472 | 2545 | name = "inout" |
| 2473 | 2546 | version = "0.1.4" |
| 2474 | 2547 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -2542,7 +2615,7 @@ dependencies = [
| 2542 | 2615 | "base64 0.22.1", |
| 2543 | 2616 | "ed25519-dalek", |
| 2544 | 2617 | "getrandom 0.2.17", |
| 2545 | - "hmac", | |
| 2618 | + "hmac 0.12.1", | |
| 2546 | 2619 | "js-sys", |
| 2547 | 2620 | "p256", |
| 2548 | 2621 | "p384", |
@@ -2551,7 +2624,7 @@ dependencies = [
| 2551 | 2624 | "rsa", |
| 2552 | 2625 | "serde", |
| 2553 | 2626 | "serde_json", |
| 2554 | - "sha2", | |
| 2627 | + "sha2 0.10.9", | |
| 2555 | 2628 | "signature", |
| 2556 | 2629 | "simple_asn1", |
| 2557 | 2630 | ] |
@@ -2681,18 +2754,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
| 2681 | 2754 | checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" |
| 2682 | 2755 | |
| 2683 | 2756 | [[package]] |
| 2684 | -name = "libredox" | |
| 2685 | -version = "0.1.14" | |
| 2686 | -source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 2687 | -checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" | |
| 2688 | -dependencies = [ | |
| 2689 | - "bitflags 2.11.0", | |
| 2690 | - "libc", | |
| 2691 | - "plain", | |
| 2692 | - "redox_syscall 0.7.3", | |
| 2693 | -] | |
| 2694 | - | |
| 2695 | -[[package]] | |
| 2696 | 2757 | name = "libsqlite3-sys" |
| 2697 | 2758 | version = "0.30.1" |
| 2698 | 2759 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -2798,12 +2859,12 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
| 2798 | 2859 | |
| 2799 | 2860 | [[package]] |
| 2800 | 2861 | name = "md-5" |
| 2801 | -version = "0.10.6" | |
| 2862 | +version = "0.11.0" | |
| 2802 | 2863 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2803 | -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" | |
| 2864 | +checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98" | |
| 2804 | 2865 | dependencies = [ |
| 2805 | 2866 | "cfg-if", |
| 2806 | - "digest", | |
| 2867 | + "digest 0.11.3", | |
| 2807 | 2868 | ] |
| 2808 | 2869 | |
| 2809 | 2870 | [[package]] |
@@ -3075,7 +3136,7 @@ dependencies = [
| 3075 | 3136 | "serde", |
| 3076 | 3137 | "serde_json", |
| 3077 | 3138 | "serde_path_to_error", |
| 3078 | - "sha2", | |
| 3139 | + "sha2 0.10.9", | |
| 3079 | 3140 | "thiserror 1.0.69", |
| 3080 | 3141 | "url", |
| 3081 | 3142 | ] |
@@ -3108,7 +3169,7 @@ dependencies = [
| 3108 | 3169 | "chrono", |
| 3109 | 3170 | "dyn-clone", |
| 3110 | 3171 | "ed25519-dalek", |
| 3111 | - "hmac", | |
| 3172 | + "hmac 0.12.1", | |
| 3112 | 3173 | "http", |
| 3113 | 3174 | "itertools 0.10.5", |
| 3114 | 3175 | "log", |
@@ -3123,7 +3184,7 @@ dependencies = [
| 3123 | 3184 | "serde_path_to_error", |
| 3124 | 3185 | "serde_plain", |
| 3125 | 3186 | "serde_with", |
| 3126 | - "sha2", | |
| 3187 | + "sha2 0.10.9", | |
| 3127 | 3188 | "subtle", |
| 3128 | 3189 | "thiserror 1.0.69", |
| 3129 | 3190 | "url", |
@@ -3224,7 +3285,7 @@ dependencies = [
| 3224 | 3285 | "ecdsa", |
| 3225 | 3286 | "elliptic-curve", |
| 3226 | 3287 | "primeorder", |
| 3227 | - "sha2", | |
| 3288 | + "sha2 0.10.9", | |
| 3228 | 3289 | ] |
| 3229 | 3290 | |
| 3230 | 3291 | [[package]] |
@@ -3236,7 +3297,7 @@ dependencies = [
| 3236 | 3297 | "ecdsa", |
| 3237 | 3298 | "elliptic-curve", |
| 3238 | 3299 | "primeorder", |
| 3239 | - "sha2", | |
| 3300 | + "sha2 0.10.9", | |
| 3240 | 3301 | ] |
| 3241 | 3302 | |
| 3242 | 3303 | [[package]] |
@@ -3263,7 +3324,7 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
| 3263 | 3324 | dependencies = [ |
| 3264 | 3325 | "cfg-if", |
| 3265 | 3326 | "libc", |
| 3266 | - "redox_syscall 0.5.18", | |
| 3327 | + "redox_syscall", | |
| 3267 | 3328 | "smallvec", |
| 3268 | 3329 | "windows-link", |
| 3269 | 3330 | ] |
@@ -3394,12 +3455,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
| 3394 | 3455 | checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" |
| 3395 | 3456 | |
| 3396 | 3457 | [[package]] |
| 3397 | -name = "plain" | |
| 3398 | -version = "0.2.3" | |
| 3399 | -source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 3400 | -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" | |
| 3401 | - | |
| 3402 | -[[package]] | |
| 3403 | 3458 | name = "pluralizer" |
| 3404 | 3459 | version = "0.5.0" |
| 3405 | 3460 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -3429,7 +3484,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
| 3429 | 3484 | checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" |
| 3430 | 3485 | dependencies = [ |
| 3431 | 3486 | "cfg-if", |
| 3432 | - "cpufeatures", | |
| 3487 | + "cpufeatures 0.2.17", | |
| 3433 | 3488 | "opaque-debug", |
| 3434 | 3489 | "universal-hash", |
| 3435 | 3490 | ] |
@@ -3695,6 +3750,17 @@ dependencies = [
| 3695 | 3750 | ] |
| 3696 | 3751 | |
| 3697 | 3752 | [[package]] |
| 3753 | +name = "rand" | |
| 3754 | +version = "0.10.2" | |
| 3755 | +source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 3756 | +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" | |
| 3757 | +dependencies = [ | |
| 3758 | + "chacha20", | |
| 3759 | + "getrandom 0.4.2", | |
| 3760 | + "rand_core 0.10.1", | |
| 3761 | +] | |
| 3762 | + | |
| 3763 | +[[package]] | |
| 3698 | 3764 | name = "rand_chacha" |
| 3699 | 3765 | version = "0.3.1" |
| 3700 | 3766 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -3733,6 +3799,12 @@ dependencies = [
| 3733 | 3799 | ] |
| 3734 | 3800 | |
| 3735 | 3801 | [[package]] |
| 3802 | +name = "rand_core" | |
| 3803 | +version = "0.10.1" | |
| 3804 | +source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 3805 | +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" | |
| 3806 | + | |
| 3807 | +[[package]] | |
| 3736 | 3808 | name = "redis-protocol" |
| 3737 | 3809 | version = "5.0.1" |
| 3738 | 3810 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -3756,15 +3828,6 @@ dependencies = [
| 3756 | 3828 | ] |
| 3757 | 3829 | |
| 3758 | 3830 | [[package]] |
| 3759 | -name = "redox_syscall" | |
| 3760 | -version = "0.7.3" | |
| 3761 | -source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 3762 | -checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" | |
| 3763 | -dependencies = [ | |
| 3764 | - "bitflags 2.11.0", | |
| 3765 | -] | |
| 3766 | - | |
| 3767 | -[[package]] | |
| 3768 | 3831 | name = "ref-cast" |
| 3769 | 3832 | version = "1.0.25" |
| 3770 | 3833 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -3920,7 +3983,7 @@ version = "0.4.0"
| 3920 | 3983 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 3921 | 3984 | checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" |
| 3922 | 3985 | dependencies = [ |
| 3923 | - "hmac", | |
| 3986 | + "hmac 0.12.1", | |
| 3924 | 3987 | "subtle", |
| 3925 | 3988 | ] |
| 3926 | 3989 |
@@ -3993,7 +4056,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
| 3993 | 4056 | checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" |
| 3994 | 4057 | dependencies = [ |
| 3995 | 4058 | "const-oid", |
| 3996 | - "digest", | |
| 4059 | + "digest 0.10.7", | |
| 3997 | 4060 | "num-bigint-dig", |
| 3998 | 4061 | "num-integer", |
| 3999 | 4062 | "num-traits", |
@@ -4155,7 +4218,7 @@ dependencies = [
| 4155 | 4218 | "serde", |
| 4156 | 4219 | "serde_json", |
| 4157 | 4220 | "serial_test", |
| 4158 | - "sha2", | |
| 4221 | + "sha2 0.10.9", | |
| 4159 | 4222 | "subtle", |
| 4160 | 4223 | "thiserror 2.0.18", |
| 4161 | 4224 | "time", |
@@ -4197,7 +4260,7 @@ dependencies = [
| 4197 | 4260 | "serde", |
| 4198 | 4261 | "serde_json", |
| 4199 | 4262 | "serial_test", |
| 4200 | - "sha2", | |
| 4263 | + "sha2 0.10.9", | |
| 4201 | 4264 | "subtle", |
| 4202 | 4265 | "thiserror 2.0.18", |
| 4203 | 4266 | "tokio", |
@@ -4358,14 +4421,15 @@ dependencies = [
| 4358 | 4421 | |
| 4359 | 4422 | [[package]] |
| 4360 | 4423 | name = "sea-orm" |
| 4361 | -version = "2.0.0-rc.37" | |
| 4424 | +version = "2.0.0" | |
| 4362 | 4425 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 4363 | -checksum = "4b846dc1c7fefbea372c03765ff08307d68894bbad8c73b66176dcd53a3ee131" | |
| 4426 | +checksum = "549c6d29a2e7a84e35c5dfbc06370a62c4d35f2328c31005267bec586b34f682" | |
| 4364 | 4427 | dependencies = [ |
| 4365 | 4428 | "async-stream", |
| 4366 | 4429 | "async-trait", |
| 4367 | 4430 | "bigdecimal", |
| 4368 | 4431 | "chrono", |
| 4432 | + "derive-where", | |
| 4369 | 4433 | "derive_more", |
| 4370 | 4434 | "futures-util", |
| 4371 | 4435 | "itertools 0.14.0", |
@@ -4382,12 +4446,14 @@ dependencies = [
| 4382 | 4446 | "serde", |
| 4383 | 4447 | "serde_json", |
| 4384 | 4448 | "sqlx", |
| 4449 | + "sqlx-core", | |
| 4385 | 4450 | "strum", |
| 4386 | 4451 | "thiserror 2.0.18", |
| 4387 | 4452 | "time", |
| 4388 | 4453 | "tracing", |
| 4389 | 4454 | "url", |
| 4390 | 4455 | "uuid", |
| 4456 | + "web-time", | |
| 4391 | 4457 | ] |
| 4392 | 4458 | |
| 4393 | 4459 | [[package]] |
@@ -4403,9 +4469,9 @@ dependencies = [
| 4403 | 4469 | |
| 4404 | 4470 | [[package]] |
| 4405 | 4471 | name = "sea-orm-cli" |
| 4406 | -version = "2.0.0-rc.37" | |
| 4472 | +version = "2.0.0" | |
| 4407 | 4473 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 4408 | -checksum = "cd9b34d4c8e615079c04eb7863a429c2d2a8bf9c934eb9eeb580f51f36367124" | |
| 4474 | +checksum = "3ec4b7c39c90efa92b8bb0b91ac7159684b9fa0d6371ce39bfab0a9793ce7394" | |
| 4409 | 4475 | dependencies = [ |
| 4410 | 4476 | "chrono", |
| 4411 | 4477 | "clap", |
@@ -4423,9 +4489,9 @@ dependencies = [
| 4423 | 4489 | |
| 4424 | 4490 | [[package]] |
| 4425 | 4491 | name = "sea-orm-macros" |
| 4426 | -version = "2.0.0-rc.37" | |
| 4492 | +version = "2.0.0" | |
| 4427 | 4493 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 4428 | -checksum = "b449fe660e4d365f335222025df97ae01e670ef7ad788b3c67db9183b6cb0474" | |
| 4494 | +checksum = "b4cbb7ae053b9b37c919ea944a3bc52f7830a90c223f8a765c908293bca8f22d" | |
| 4429 | 4495 | dependencies = [ |
| 4430 | 4496 | "heck 0.5.0", |
| 4431 | 4497 | "itertools 0.14.0", |
@@ -4439,9 +4505,9 @@ dependencies = [
| 4439 | 4505 | |
| 4440 | 4506 | [[package]] |
| 4441 | 4507 | name = "sea-orm-migration" |
| 4442 | -version = "2.0.0-rc.37" | |
| 4508 | +version = "2.0.0" | |
| 4443 | 4509 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 4444 | -checksum = "b3ceb928aac8be83332d34d1fdbc827d43696135a800723ffeb2e0b33b7b495e" | |
| 4510 | +checksum = "ef3576c5301b67ea7d2ce4515858d700066e51911c7d228a439c00ff258695c8" | |
| 4445 | 4511 | dependencies = [ |
| 4446 | 4512 | "async-trait", |
| 4447 | 4513 | "clap", |
@@ -4455,12 +4521,11 @@ dependencies = [
| 4455 | 4521 | |
| 4456 | 4522 | [[package]] |
| 4457 | 4523 | name = "sea-query" |
| 4458 | -version = "1.0.0-rc.31" | |
| 4524 | +version = "1.0.1" | |
| 4459 | 4525 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 4460 | -checksum = "58decdaaaf2a698170af2fa1b2e8f7b43a970e7768bf18aebaab113bada46354" | |
| 4526 | +checksum = "8d190cfb3bcceb8a8d7d04dee5a0c77f60c7627979cdcb47fdcb8934f009badf" | |
| 4461 | 4527 | dependencies = [ |
| 4462 | 4528 | "chrono", |
| 4463 | - "inherent", | |
| 4464 | 4529 | "ordered-float 4.6.0", |
| 4465 | 4530 | "rust_decimal", |
| 4466 | 4531 | "sea-query-derive", |
@@ -4471,9 +4536,9 @@ dependencies = [
| 4471 | 4536 | |
| 4472 | 4537 | [[package]] |
| 4473 | 4538 | name = "sea-query-derive" |
| 4474 | -version = "1.0.0-rc.12" | |
| 4539 | +version = "1.0.0" | |
| 4475 | 4540 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 4476 | -checksum = "8d88ad44b6ad9788c8b9476b6b91f94c7461d1e19d39cd8ea37838b1e6ff5aa8" | |
| 4541 | +checksum = "a0b0f466921cdd3cf4b89d5c3ac2173dba89a873ab395b123a645de181ec7537" | |
| 4477 | 4542 | dependencies = [ |
| 4478 | 4543 | "darling 0.20.11", |
| 4479 | 4544 | "heck 0.4.1", |
@@ -4485,9 +4550,9 @@ dependencies = [
| 4485 | 4550 | |
| 4486 | 4551 | [[package]] |
| 4487 | 4552 | name = "sea-query-sqlx" |
| 4488 | -version = "0.8.0-rc.14" | |
| 4553 | +version = "0.9.1" | |
| 4489 | 4554 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 4490 | -checksum = "e4377164b09a11bb692dec6966eb0e6908d63d768defef0be689b39e02cf8544" | |
| 4555 | +checksum = "4eaa419cdb9157da1361186b1959983eb2ea0dcb9a3c69dc45c449ecb2af8fef" | |
| 4491 | 4556 | dependencies = [ |
| 4492 | 4557 | "sea-query", |
| 4493 | 4558 | "sqlx", |
@@ -4495,9 +4560,9 @@ dependencies = [
| 4495 | 4560 | |
| 4496 | 4561 | [[package]] |
| 4497 | 4562 | name = "sea-schema" |
| 4498 | -version = "0.17.0-rc.17" | |
| 4563 | +version = "0.18.1" | |
| 4499 | 4564 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 4500 | -checksum = "b363dd21c20fe4d1488819cb2bc7f8d4696c62dd9f39554f97639f54d57dd0ab" | |
| 4565 | +checksum = "3553c77dceed56e95bece9ea876c4dd67ca879ef51055a0b97a7bb89a8ae4fed" | |
| 4501 | 4566 | dependencies = [ |
| 4502 | 4567 | "async-trait", |
| 4503 | 4568 | "sea-query", |
@@ -4717,8 +4782,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
| 4717 | 4782 | checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" |
| 4718 | 4783 | dependencies = [ |
| 4719 | 4784 | "cfg-if", |
| 4720 | - "cpufeatures", | |
| 4721 | - "digest", | |
| 4785 | + "cpufeatures 0.2.17", | |
| 4786 | + "digest 0.10.7", | |
| 4787 | +] | |
| 4788 | + | |
| 4789 | +[[package]] | |
| 4790 | +name = "sha1" | |
| 4791 | +version = "0.11.0" | |
| 4792 | +source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 4793 | +checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" | |
| 4794 | +dependencies = [ | |
| 4795 | + "cfg-if", | |
| 4796 | + "cpufeatures 0.3.0", | |
| 4797 | + "digest 0.11.3", | |
| 4722 | 4798 | ] |
| 4723 | 4799 | |
| 4724 | 4800 | [[package]] |
@@ -4728,8 +4804,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
| 4728 | 4804 | checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" |
| 4729 | 4805 | dependencies = [ |
| 4730 | 4806 | "cfg-if", |
| 4731 | - "cpufeatures", | |
| 4732 | - "digest", | |
| 4807 | + "cpufeatures 0.2.17", | |
| 4808 | + "digest 0.10.7", | |
| 4809 | +] | |
| 4810 | + | |
| 4811 | +[[package]] | |
| 4812 | +name = "sha2" | |
| 4813 | +version = "0.11.0" | |
| 4814 | +source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 4815 | +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" | |
| 4816 | +dependencies = [ | |
| 4817 | + "cfg-if", | |
| 4818 | + "cpufeatures 0.3.0", | |
| 4819 | + "digest 0.11.3", | |
| 4733 | 4820 | ] |
| 4734 | 4821 | |
| 4735 | 4822 | [[package]] |
@@ -4769,7 +4856,7 @@ version = "2.2.0"
| 4769 | 4856 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 4770 | 4857 | checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" |
| 4771 | 4858 | dependencies = [ |
| 4772 | - "digest", | |
| 4859 | + "digest 0.10.7", | |
| 4773 | 4860 | "rand_core 0.6.4", |
| 4774 | 4861 | ] |
| 4775 | 4862 |
@@ -4859,9 +4946,9 @@ dependencies = [
| 4859 | 4946 | |
| 4860 | 4947 | [[package]] |
| 4861 | 4948 | name = "sqlx" |
| 4862 | -version = "0.8.6" | |
| 4949 | +version = "0.9.0" | |
| 4863 | 4950 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 4864 | -checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" | |
| 4951 | +checksum = "378620ccc25c62c89d8be1c819e76a88d59bdcc3304733330788948e619bfd71" | |
| 4865 | 4952 | dependencies = [ |
| 4866 | 4953 | "sqlx-core", |
| 4867 | 4954 | "sqlx-macros", |
@@ -4872,12 +4959,13 @@ dependencies = [
| 4872 | 4959 | |
| 4873 | 4960 | [[package]] |
| 4874 | 4961 | name = "sqlx-core" |
| 4875 | -version = "0.8.6" | |
| 4962 | +version = "0.9.0" | |
| 4876 | 4963 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 4877 | -checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" | |
| 4964 | +checksum = "05b44e85bf579a8eeb4ceaa77a3a523baf2bf0e9bac7e40f405d537b5d2d5ccb" | |
| 4878 | 4965 | dependencies = [ |
| 4879 | 4966 | "base64 0.22.1", |
| 4880 | 4967 | "bytes", |
| 4968 | + "cfg-if", | |
| 4881 | 4969 | "chrono", |
| 4882 | 4970 | "crc", |
| 4883 | 4971 | "crossbeam-queue", |
@@ -4887,18 +4975,17 @@ dependencies = [
| 4887 | 4975 | "futures-intrusive", |
| 4888 | 4976 | "futures-io", |
| 4889 | 4977 | "futures-util", |
| 4890 | - "hashbrown 0.15.5", | |
| 4891 | - "hashlink 0.10.0", | |
| 4978 | + "hashbrown 0.16.1", | |
| 4979 | + "hashlink", | |
| 4892 | 4980 | "indexmap 2.13.0", |
| 4893 | 4981 | "log", |
| 4894 | 4982 | "memchr", |
| 4895 | 4983 | "native-tls", |
| 4896 | - "once_cell", | |
| 4897 | 4984 | "percent-encoding", |
| 4898 | 4985 | "rust_decimal", |
| 4899 | 4986 | "serde", |
| 4900 | 4987 | "serde_json", |
| 4901 | - "sha2", | |
| 4988 | + "sha2 0.10.9", | |
| 4902 | 4989 | "smallvec", |
| 4903 | 4990 | "thiserror 2.0.18", |
| 4904 | 4991 | "time", |
@@ -4911,9 +4998,9 @@ dependencies = [
| 4911 | 4998 | |
| 4912 | 4999 | [[package]] |
| 4913 | 5000 | name = "sqlx-macros" |
| 4914 | -version = "0.8.6" | |
| 5001 | +version = "0.9.0" | |
| 4915 | 5002 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 4916 | -checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" | |
| 5003 | +checksum = "bd2b84f2bc39a5705ef27ec785a11c934a41bbd4a24941e257927cddc26b60bf" | |
| 4917 | 5004 | dependencies = [ |
| 4918 | 5005 | "proc-macro2", |
| 4919 | 5006 | "quote", |
@@ -4924,20 +5011,20 @@ dependencies = [
| 4924 | 5011 | |
| 4925 | 5012 | [[package]] |
| 4926 | 5013 | name = "sqlx-macros-core" |
| 4927 | -version = "0.8.6" | |
| 5014 | +version = "0.9.0" | |
| 4928 | 5015 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 4929 | -checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" | |
| 5016 | +checksum = "fb8d96de5fdc85a5c4ec813432b523ec637e80ba98f046555f75f7908ddac7c3" | |
| 4930 | 5017 | dependencies = [ |
| 5018 | + "cfg-if", | |
| 4931 | 5019 | "dotenvy", |
| 4932 | 5020 | "either", |
| 4933 | 5021 | "heck 0.5.0", |
| 4934 | 5022 | "hex", |
| 4935 | - "once_cell", | |
| 4936 | 5023 | "proc-macro2", |
| 4937 | 5024 | "quote", |
| 4938 | 5025 | "serde", |
| 4939 | 5026 | "serde_json", |
| 4940 | - "sha2", | |
| 5027 | + "sha2 0.10.9", | |
| 4941 | 5028 | "sqlx-core", |
| 4942 | 5029 | "sqlx-mysql", |
| 4943 | 5030 | "sqlx-postgres", |
@@ -4949,55 +5036,39 @@ dependencies = [
| 4949 | 5036 | |
| 4950 | 5037 | [[package]] |
| 4951 | 5038 | name = "sqlx-mysql" |
| 4952 | -version = "0.8.6" | |
| 5039 | +version = "0.9.0" | |
| 4953 | 5040 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 4954 | -checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" | |
| 5041 | +checksum = "90b8020fe17c5f2c245bfa2505d7ef59c5604839527c740266ad2214acebea27" | |
| 4955 | 5042 | dependencies = [ |
| 4956 | - "atoi", | |
| 4957 | - "base64 0.22.1", | |
| 4958 | 5043 | "bitflags 2.11.0", |
| 4959 | 5044 | "byteorder", |
| 4960 | 5045 | "bytes", |
| 4961 | 5046 | "chrono", |
| 4962 | 5047 | "crc", |
| 4963 | - "digest", | |
| 5048 | + "digest 0.11.3", | |
| 4964 | 5049 | "dotenvy", |
| 4965 | 5050 | "either", |
| 4966 | - "futures-channel", | |
| 4967 | 5051 | "futures-core", |
| 4968 | - "futures-io", | |
| 4969 | 5052 | "futures-util", |
| 4970 | 5053 | "generic-array", |
| 4971 | - "hex", | |
| 4972 | - "hkdf", | |
| 4973 | - "hmac", | |
| 4974 | - "itoa", | |
| 4975 | 5054 | "log", |
| 4976 | - "md-5", | |
| 4977 | - "memchr", | |
| 4978 | - "once_cell", | |
| 4979 | 5055 | "percent-encoding", |
| 4980 | - "rand 0.8.5", | |
| 4981 | - "rsa", | |
| 4982 | 5056 | "rust_decimal", |
| 4983 | 5057 | "serde", |
| 4984 | - "sha1", | |
| 4985 | - "sha2", | |
| 4986 | - "smallvec", | |
| 5058 | + "sha1 0.11.0", | |
| 5059 | + "sha2 0.11.0", | |
| 4987 | 5060 | "sqlx-core", |
| 4988 | - "stringprep", | |
| 4989 | 5061 | "thiserror 2.0.18", |
| 4990 | 5062 | "time", |
| 4991 | 5063 | "tracing", |
| 4992 | 5064 | "uuid", |
| 4993 | - "whoami", | |
| 4994 | 5065 | ] |
| 4995 | 5066 | |
| 4996 | 5067 | [[package]] |
| 4997 | 5068 | name = "sqlx-postgres" |
| 4998 | -version = "0.8.6" | |
| 5069 | +version = "0.9.0" | |
| 4999 | 5070 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 5000 | -checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" | |
| 5071 | +checksum = "87a2bdd6e83f6b3ea525ca9fee568030508b58355a43d0b2c1674d5f79dcd65e" | |
| 5001 | 5072 | dependencies = [ |
| 5002 | 5073 | "atoi", |
| 5003 | 5074 | "base64 0.22.1", |
@@ -5011,19 +5082,17 @@ dependencies = [
| 5011 | 5082 | "futures-core", |
| 5012 | 5083 | "futures-util", |
| 5013 | 5084 | "hex", |
| 5014 | - "hkdf", | |
| 5015 | - "hmac", | |
| 5016 | - "home", | |
| 5085 | + "hkdf 0.13.0", | |
| 5086 | + "hmac 0.13.0", | |
| 5017 | 5087 | "itoa", |
| 5018 | 5088 | "log", |
| 5019 | 5089 | "md-5", |
| 5020 | 5090 | "memchr", |
| 5021 | - "once_cell", | |
| 5022 | - "rand 0.8.5", | |
| 5091 | + "rand 0.10.2", | |
| 5023 | 5092 | "rust_decimal", |
| 5024 | 5093 | "serde", |
| 5025 | 5094 | "serde_json", |
| 5026 | - "sha2", | |
| 5095 | + "sha2 0.11.0", | |
| 5027 | 5096 | "smallvec", |
| 5028 | 5097 | "sqlx-core", |
| 5029 | 5098 | "stringprep", |
@@ -5036,13 +5105,14 @@ dependencies = [
| 5036 | 5105 | |
| 5037 | 5106 | [[package]] |
| 5038 | 5107 | name = "sqlx-sqlite" |
| 5039 | -version = "0.8.6" | |
| 5108 | +version = "0.9.0" | |
| 5040 | 5109 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 5041 | -checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" | |
| 5110 | +checksum = "488e99c397a62007e4229aec669a179816339afc6d2620ca6fa420dbee2e982c" | |
| 5042 | 5111 | dependencies = [ |
| 5043 | 5112 | "atoi", |
| 5044 | 5113 | "chrono", |
| 5045 | 5114 | "flume", |
| 5115 | + "form_urlencoded", | |
| 5046 | 5116 | "futures-channel", |
| 5047 | 5117 | "futures-core", |
| 5048 | 5118 | "futures-executor", |
@@ -5052,7 +5122,6 @@ dependencies = [
| 5052 | 5122 | "log", |
| 5053 | 5123 | "percent-encoding", |
| 5054 | 5124 | "serde", |
| 5055 | - "serde_urlencoded", | |
| 5056 | 5125 | "sqlx-core", |
| 5057 | 5126 | "thiserror 2.0.18", |
| 5058 | 5127 | "time", |
@@ -5117,9 +5186,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
| 5117 | 5186 | |
| 5118 | 5187 | [[package]] |
| 5119 | 5188 | name = "strum" |
| 5120 | -version = "0.27.2" | |
| 5189 | +version = "0.28.0" | |
| 5121 | 5190 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 5122 | -checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" | |
| 5191 | +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" | |
| 5123 | 5192 | |
| 5124 | 5193 | [[package]] |
| 5125 | 5194 | name = "subtle" |
@@ -5451,11 +5520,11 @@ checksum = "a2b36a9dd327e9f401320a2cb4572cc76ff43742bcfc3291f871691050f140ba"
| 5451 | 5520 | dependencies = [ |
| 5452 | 5521 | "base32", |
| 5453 | 5522 | "constant_time_eq", |
| 5454 | - "hmac", | |
| 5523 | + "hmac 0.12.1", | |
| 5455 | 5524 | "qrcodegen-image", |
| 5456 | 5525 | "rand 0.9.2", |
| 5457 | - "sha1", | |
| 5458 | - "sha2", | |
| 5526 | + "sha1 0.10.6", | |
| 5527 | + "sha2 0.10.9", | |
| 5459 | 5528 | "url", |
| 5460 | 5529 | "urlencoding", |
| 5461 | 5530 | ] |
@@ -5688,9 +5757,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
| 5688 | 5757 | |
| 5689 | 5758 | [[package]] |
| 5690 | 5759 | name = "typenum" |
| 5691 | -version = "1.19.0" | |
| 5760 | +version = "1.20.1" | |
| 5692 | 5761 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 5693 | -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" | |
| 5762 | +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" | |
| 5694 | 5763 | |
| 5695 | 5764 | [[package]] |
| 5696 | 5765 | name = "unicase" |
@@ -5743,7 +5812,7 @@ version = "0.5.1"
| 5743 | 5812 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 5744 | 5813 | checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" |
| 5745 | 5814 | dependencies = [ |
| 5746 | - "crypto-common", | |
| 5815 | + "crypto-common 0.1.7", | |
| 5747 | 5816 | "subtle", |
| 5748 | 5817 | ] |
| 5749 | 5818 |
@@ -5884,12 +5953,6 @@ dependencies = [
| 5884 | 5953 | ] |
| 5885 | 5954 | |
| 5886 | 5955 | [[package]] |
| 5887 | -name = "wasite" | |
| 5888 | -version = "0.1.0" | |
| 5889 | -source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 5890 | -checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" | |
| 5891 | - | |
| 5892 | -[[package]] | |
| 5893 | 5956 | name = "wasm-bindgen" |
| 5894 | 5957 | version = "0.2.114" |
| 5895 | 5958 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -6038,13 +6101,9 @@ dependencies = [
| 6038 | 6101 | |
| 6039 | 6102 | [[package]] |
| 6040 | 6103 | name = "whoami" |
| 6041 | -version = "1.6.1" | |
| 6104 | +version = "2.1.2" | |
| 6042 | 6105 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 6043 | -checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" | |
| 6044 | -dependencies = [ | |
| 6045 | - "libredox", | |
| 6046 | - "wasite", | |
| 6047 | -] | |
| 6106 | +checksum = "998767ef88740d1f5b0682a9c53c24431453923962269c2db68ee43788c5a40d" | |
| 6048 | 6107 | |
| 6049 | 6108 | [[package]] |
| 6050 | 6109 | name = "winapi" |
@@ -6140,20 +6199,11 @@ dependencies = [
| 6140 | 6199 | |
| 6141 | 6200 | [[package]] |
| 6142 | 6201 | name = "windows-sys" |
| 6143 | -version = "0.48.0" | |
| 6144 | -source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 6145 | -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" | |
| 6146 | -dependencies = [ | |
| 6147 | - "windows-targets 0.48.5", | |
| 6148 | -] | |
| 6149 | - | |
| 6150 | -[[package]] | |
| 6151 | -name = "windows-sys" | |
| 6152 | 6202 | version = "0.52.0" |
| 6153 | 6203 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 6154 | 6204 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" |
| 6155 | 6205 | dependencies = [ |
| 6156 | - "windows-targets 0.52.6", | |
| 6206 | + "windows-targets", | |
| 6157 | 6207 | ] |
| 6158 | 6208 | |
| 6159 | 6209 | [[package]] |
@@ -6162,7 +6212,7 @@ version = "0.59.0"
| 6162 | 6212 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 6163 | 6213 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" |
| 6164 | 6214 | dependencies = [ |
| 6165 | - "windows-targets 0.52.6", | |
| 6215 | + "windows-targets", | |
| 6166 | 6216 | ] |
| 6167 | 6217 | |
| 6168 | 6218 | [[package]] |
@@ -6176,67 +6226,34 @@ dependencies = [
| 6176 | 6226 | |
| 6177 | 6227 | [[package]] |
| 6178 | 6228 | name = "windows-targets" |
| 6179 | -version = "0.48.5" | |
| 6180 | -source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 6181 | -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" | |
| 6182 | -dependencies = [ | |
| 6183 | - "windows_aarch64_gnullvm 0.48.5", | |
| 6184 | - "windows_aarch64_msvc 0.48.5", | |
| 6185 | - "windows_i686_gnu 0.48.5", | |
| 6186 | - "windows_i686_msvc 0.48.5", | |
| 6187 | - "windows_x86_64_gnu 0.48.5", | |
| 6188 | - "windows_x86_64_gnullvm 0.48.5", | |
| 6189 | - "windows_x86_64_msvc 0.48.5", | |
| 6190 | -] | |
| 6191 | - | |
| 6192 | -[[package]] | |
| 6193 | -name = "windows-targets" | |
| 6194 | 6229 | version = "0.52.6" |
| 6195 | 6230 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 6196 | 6231 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" |
| 6197 | 6232 | dependencies = [ |
| 6198 | - "windows_aarch64_gnullvm 0.52.6", | |
| 6199 | - "windows_aarch64_msvc 0.52.6", | |
| 6200 | - "windows_i686_gnu 0.52.6", | |
| 6233 | + "windows_aarch64_gnullvm", | |
| 6234 | + "windows_aarch64_msvc", | |
| 6235 | + "windows_i686_gnu", | |
| 6201 | 6236 | "windows_i686_gnullvm", |
| 6202 | - "windows_i686_msvc 0.52.6", | |
| 6203 | - "windows_x86_64_gnu 0.52.6", | |
| 6204 | - "windows_x86_64_gnullvm 0.52.6", | |
| 6205 | - "windows_x86_64_msvc 0.52.6", | |
| 6237 | + "windows_i686_msvc", | |
| 6238 | + "windows_x86_64_gnu", | |
| 6239 | + "windows_x86_64_gnullvm", | |
| 6240 | + "windows_x86_64_msvc", | |
| 6206 | 6241 | ] |
| 6207 | 6242 | |
| 6208 | 6243 | [[package]] |
| 6209 | 6244 | name = "windows_aarch64_gnullvm" |
| 6210 | -version = "0.48.5" | |
| 6211 | -source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 6212 | -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" | |
| 6213 | - | |
| 6214 | -[[package]] | |
| 6215 | -name = "windows_aarch64_gnullvm" | |
| 6216 | 6245 | version = "0.52.6" |
| 6217 | 6246 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 6218 | 6247 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" |
| 6219 | 6248 | |
| 6220 | 6249 | [[package]] |
| 6221 | 6250 | name = "windows_aarch64_msvc" |
| 6222 | -version = "0.48.5" | |
| 6223 | -source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 6224 | -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" | |
| 6225 | - | |
| 6226 | -[[package]] | |
| 6227 | -name = "windows_aarch64_msvc" | |
| 6228 | 6251 | version = "0.52.6" |
| 6229 | 6252 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 6230 | 6253 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" |
| 6231 | 6254 | |
| 6232 | 6255 | [[package]] |
| 6233 | 6256 | name = "windows_i686_gnu" |
| 6234 | -version = "0.48.5" | |
| 6235 | -source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 6236 | -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" | |
| 6237 | - | |
| 6238 | -[[package]] | |
| 6239 | -name = "windows_i686_gnu" | |
| 6240 | 6257 | version = "0.52.6" |
| 6241 | 6258 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 6242 | 6259 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" |
@@ -6249,48 +6266,24 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
| 6249 | 6266 | |
| 6250 | 6267 | [[package]] |
| 6251 | 6268 | name = "windows_i686_msvc" |
| 6252 | -version = "0.48.5" | |
| 6253 | -source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 6254 | -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" | |
| 6255 | - | |
| 6256 | -[[package]] | |
| 6257 | -name = "windows_i686_msvc" | |
| 6258 | 6269 | version = "0.52.6" |
| 6259 | 6270 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 6260 | 6271 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" |
| 6261 | 6272 | |
| 6262 | 6273 | [[package]] |
| 6263 | 6274 | name = "windows_x86_64_gnu" |
| 6264 | -version = "0.48.5" | |
| 6265 | -source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 6266 | -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" | |
| 6267 | - | |
| 6268 | -[[package]] | |
| 6269 | -name = "windows_x86_64_gnu" | |
| 6270 | 6275 | version = "0.52.6" |
| 6271 | 6276 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 6272 | 6277 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" |
| 6273 | 6278 | |
| 6274 | 6279 | [[package]] |
| 6275 | 6280 | name = "windows_x86_64_gnullvm" |
| 6276 | -version = "0.48.5" | |
| 6277 | -source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 6278 | -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" | |
| 6279 | - | |
| 6280 | -[[package]] | |
| 6281 | -name = "windows_x86_64_gnullvm" | |
| 6282 | 6281 | version = "0.52.6" |
| 6283 | 6282 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 6284 | 6283 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" |
| 6285 | 6284 | |
| 6286 | 6285 | [[package]] |
| 6287 | 6286 | name = "windows_x86_64_msvc" |
| 6288 | -version = "0.48.5" | |
| 6289 | -source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 6290 | -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" | |
| 6291 | - | |
| 6292 | -[[package]] | |
| 6293 | -name = "windows_x86_64_msvc" | |
| 6294 | 6287 | version = "0.52.6" |
| 6295 | 6288 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 6296 | 6289 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" |
@@ -6438,7 +6431,7 @@ checksum = "631a50d867fafb7093e709d75aaee9e0e0d5deb934021fcea25ac2fe09edc51e"
| 6438 | 6431 | dependencies = [ |
| 6439 | 6432 | "arraydeque", |
| 6440 | 6433 | "encoding_rs", |
| 6441 | - "hashlink 0.11.0", | |
| 6434 | + "hashlink", | |
| 6442 | 6435 | ] |
| 6443 | 6436 | |
| 6444 | 6437 | [[package]] |
M
app/Cargo.toml
+1
-1
@@ -39,7 +39,7 @@ rustwarden-ui = { path = "../crates/rustwarden-ui" }
| 39 | 39 | rustwarden-fediverse = { path = "../crates/rustwarden-fediverse", optional = true } |
| 40 | 40 | rustwarden-fediverse-ui = { path = "../crates/rustwarden-fediverse-ui", optional = true } |
| 41 | 41 | rustwarden-fediverse-guard = { path = "../crates/rustwarden-fediverse-guard", optional = true } |
| 42 | -sea-orm = { version = "2.0.0-rc.20", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] } | |
| 42 | +sea-orm = { version = "2.0.0", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] } | |
| 43 | 43 | axum = { version = "0.8", features = ["macros"] } |
| 44 | 44 | tokio = { version = "1", features = ["full"] } |
| 45 | 45 | tower = { version = "0.5", features = ["limit", "util"] } |
M
crates/rustwarden-core/Cargo.toml
+3
-3
@@ -25,8 +25,8 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
| 25 | 25 | # Env |
| 26 | 26 | dotenvy = "0.15" |
| 27 | 27 | # Database ORM |
| 28 | -sea-orm = { version = "2.0.0-rc.20", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] } | |
| 29 | -sea-orm-migration = { version = "2.0.0-rc.20", features = ["sqlx-postgres", "runtime-tokio-native-tls"] } | |
| 28 | +sea-orm = { version = "2.0.0", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] } | |
| 29 | +sea-orm-migration = { version = "2.0.0", features = ["sqlx-postgres", "runtime-tokio-native-tls"] } | |
| 30 | 30 | # Password hashing |
| 31 | 31 | bcrypt = "0.19" |
| 32 | 32 | # Validation |
@@ -99,7 +99,7 @@ hyper = { version = "1", features = ["full"] }
| 99 | 99 | hyper-util = { version = "0.1", features = ["full"] } |
| 100 | 100 | tower = "0.5" |
| 101 | 101 | # Enable SeaORM mock backend for unit tests (RFC 0003+). |
| 102 | -sea-orm = { version = "2.0.0-rc.20", features = ["mock"] } | |
| 102 | +sea-orm = { version = "2.0.0", features = ["mock"] } | |
| 103 | 103 | # Fediverse interop tests (RFC 0020): fake-Mastodon HTTP server for |
| 104 | 104 | # round-trip verification of HTTP signatures and outbound delivery. |
| 105 | 105 | wiremock = "0.6" |
M
crates/rustwarden-core/src/services/oauth/providers/discord.rs
+115
-13
@@ -19,13 +19,54 @@ impl DiscordProvider {
| 19 | 19 | client_secret, |
| 20 | 20 | } |
| 21 | 21 | } |
| 22 | + | |
| 23 | + /// Build the form body for the token-exchange request. | |
| 24 | + /// | |
| 25 | + /// RFC 0035: the PKCE `code_verifier` is appended only when present, so a | |
| 26 | + /// non-PKCE flow (verifier `None`) behaves exactly as before. Discord applies | |
| 27 | + /// PKCE whenever a `code_challenge` is sent at the authorization step, so the | |
| 28 | + /// matching verifier must be replayed here. | |
| 29 | + fn token_form<'a>( | |
| 30 | + &'a self, | |
| 31 | + code: &'a str, | |
| 32 | + redirect_uri: &'a str, | |
| 33 | + pkce_verifier: Option<&'a str>, | |
| 34 | + ) -> Vec<(&'a str, &'a str)> { | |
| 35 | + let mut form = vec![ | |
| 36 | + ("client_id", self.client_id.as_str()), | |
| 37 | + ("client_secret", self.client_secret.as_str()), | |
| 38 | + ("grant_type", "authorization_code"), | |
| 39 | + ("code", code), | |
| 40 | + ("redirect_uri", redirect_uri), | |
| 41 | + ]; | |
| 42 | + if let Some(verifier) = pkce_verifier { | |
| 43 | + form.push(("code_verifier", verifier)); | |
| 44 | + } | |
| 45 | + form | |
| 46 | + } | |
| 22 | 47 | } |
| 23 | 48 | |
| 24 | -#[derive(Deserialize)] | |
| 49 | +#[derive(Deserialize, Debug)] | |
| 25 | 50 | struct DiscordTokenResponse { |
| 26 | 51 | access_token: String, |
| 27 | 52 | } |
| 28 | 53 | |
| 54 | +/// Parse the Discord token endpoint response. | |
| 55 | +/// | |
| 56 | +/// RFC 0035 §6: reading the body as text and parsing it here surfaces Discord's | |
| 57 | +/// structured OAuth error (e.g. `{"error":"invalid_grant",...}`) instead of an | |
| 58 | +/// opaque "error decoding response body". | |
| 59 | +fn parse_discord_token( | |
| 60 | + status: reqwest::StatusCode, | |
| 61 | + body: &str, | |
| 62 | +) -> Result<DiscordTokenResponse, AppError> { | |
| 63 | + serde_json::from_str::<DiscordTokenResponse>(body).map_err(|_| { | |
| 64 | + AppError::Internal(format!( | |
| 65 | + "Discord token exchange rejected (HTTP {status}): {body}" | |
| 66 | + )) | |
| 67 | + }) | |
| 68 | +} | |
| 69 | + | |
| 29 | 70 | #[derive(Deserialize)] |
| 30 | 71 | struct DiscordUser { |
| 31 | 72 | id: String, |
@@ -78,26 +119,24 @@ impl OAuthProvider for DiscordProvider {
| 78 | 119 | &self, |
| 79 | 120 | code: &str, |
| 80 | 121 | redirect_uri: &str, |
| 81 | - _pkce_verifier: Option<&str>, | |
| 122 | + pkce_verifier: Option<&str>, | |
| 82 | 123 | _nonce: Option<&str>, |
| 83 | 124 | ) -> Result<ProviderUserInfo, AppError> { |
| 84 | 125 | let http = reqwest::Client::new(); |
| 85 | 126 | |
| 86 | - let token_resp = http | |
| 127 | + let response = http | |
| 87 | 128 | .post("https://discord.com/api/oauth2/token") |
| 88 | - .form(&[ | |
| 89 | - ("client_id", self.client_id.as_str()), | |
| 90 | - ("client_secret", self.client_secret.as_str()), | |
| 91 | - ("grant_type", "authorization_code"), | |
| 92 | - ("code", code), | |
| 93 | - ("redirect_uri", redirect_uri), | |
| 94 | - ]) | |
| 129 | + .form(&self.token_form(code, redirect_uri, pkce_verifier)) | |
| 95 | 130 | .send() |
| 96 | 131 | .await |
| 97 | - .map_err(|e| AppError::Internal(format!("Discord token exchange failed: {}", e)))? | |
| 98 | - .json::<DiscordTokenResponse>() | |
| 132 | + .map_err(|e| AppError::Internal(format!("Discord token exchange failed: {}", e)))?; | |
| 133 | + | |
| 134 | + let status = response.status(); | |
| 135 | + let body = response | |
| 136 | + .text() | |
| 99 | 137 | .await |
| 100 | - .map_err(|e| AppError::Internal(format!("Discord token parse failed: {}", e)))?; | |
| 138 | + .map_err(|e| AppError::Internal(format!("Discord token read failed: {}", e)))?; | |
| 139 | + let token_resp = parse_discord_token(status, &body)?; | |
| 101 | 140 | |
| 102 | 141 | let user: DiscordUser = http |
| 103 | 142 | .get("https://discord.com/api/v10/users/@me") |
@@ -128,3 +167,66 @@ impl OAuthProvider for DiscordProvider {
| 128 | 167 | }) |
| 129 | 168 | } |
| 130 | 169 | } |
| 170 | + | |
| 171 | +#[cfg(test)] | |
| 172 | +mod tests { | |
| 173 | + use super::*; | |
| 174 | + | |
| 175 | + fn provider() -> DiscordProvider { | |
| 176 | + DiscordProvider::new("client-id".to_string(), "client-secret".to_string()) | |
| 177 | + } | |
| 178 | + | |
| 179 | + // RFC 0035 §7.1: the verifier must be present in the token form when supplied. | |
| 180 | + #[test] | |
| 181 | + fn token_form_includes_code_verifier_when_present() { | |
| 182 | + let p = provider(); | |
| 183 | + let form = p.token_form("the-code", "https://app.example/cb", Some("the-verifier")); | |
| 184 | + assert!( | |
| 185 | + form.contains(&("code_verifier", "the-verifier")), | |
| 186 | + "code_verifier must be sent to the token endpoint when PKCE is used" | |
| 187 | + ); | |
| 188 | + assert!(form.contains(&("grant_type", "authorization_code"))); | |
| 189 | + assert!(form.contains(&("redirect_uri", "https://app.example/cb"))); | |
| 190 | + } | |
| 191 | + | |
| 192 | + // RFC 0035 §7.1: a non-PKCE flow (verifier None) must not add the parameter. | |
| 193 | + #[test] | |
| 194 | + fn token_form_omits_code_verifier_when_absent() { | |
| 195 | + let p = provider(); | |
| 196 | + let form = p.token_form("the-code", "https://app.example/cb", None); | |
| 197 | + assert!(form.iter().all(|(k, _)| *k != "code_verifier")); | |
| 198 | + } | |
| 199 | + | |
| 200 | + // RFC 0035 §7.2: a code_challenge is emitted at authorization, so a matching | |
| 201 | + // verifier must be carried in the session for the exchange. | |
| 202 | + #[test] | |
| 203 | + fn authorization_url_emits_challenge_and_keeps_verifier() { | |
| 204 | + let auth = provider() | |
| 205 | + .authorization_url("https://app.example/callback") | |
| 206 | + .expect("authorization_url should succeed"); | |
| 207 | + assert!(auth.url.contains("code_challenge=")); | |
| 208 | + assert!(auth.url.contains("code_challenge_method=S256")); | |
| 209 | + assert!( | |
| 210 | + auth.pkce_verifier.is_some(), | |
| 211 | + "verifier must be retained whenever a challenge is sent" | |
| 212 | + ); | |
| 213 | + } | |
| 214 | + | |
| 215 | + // RFC 0035 §6: a structured OAuth error body must surface instead of an | |
| 216 | + // opaque deserialization failure. | |
| 217 | + #[test] | |
| 218 | + fn parse_discord_token_surfaces_error_body() { | |
| 219 | + let body = r#"{"error":"invalid_grant","error_description":"Invalid code_verifier"}"#; | |
| 220 | + let err = parse_discord_token(reqwest::StatusCode::BAD_REQUEST, body) | |
| 221 | + .expect_err("error body must not parse as success"); | |
| 222 | + assert!(err.to_string().contains("Invalid code_verifier")); | |
| 223 | + } | |
| 224 | + | |
| 225 | + #[test] | |
| 226 | + fn parse_discord_token_accepts_success_body() { | |
| 227 | + let body = r#"{"access_token":"discord_token","token_type":"Bearer"}"#; | |
| 228 | + let token = parse_discord_token(reqwest::StatusCode::OK, body) | |
| 229 | + .expect("valid token response should parse"); | |
| 230 | + assert_eq!(token.access_token, "discord_token"); | |
| 231 | + } | |
| 232 | +} |
M
crates/rustwarden-core/src/services/oauth/providers/github.rs
+112
-11
@@ -18,13 +18,51 @@ impl GitHubProvider {
| 18 | 18 | client_secret, |
| 19 | 19 | } |
| 20 | 20 | } |
| 21 | + | |
| 22 | + /// Build the form body for the token-exchange request. | |
| 23 | + /// | |
| 24 | + /// RFC 0035: the PKCE `code_verifier` is appended only when present, so a | |
| 25 | + /// non-PKCE flow (verifier `None`) behaves exactly as before. GitHub has | |
| 26 | + /// enforced PKCE since 2025-07-14, so a `code_challenge` emitted at the | |
| 27 | + /// authorization step must be matched by the verifier here. | |
| 28 | + fn token_form<'a>( | |
| 29 | + &'a self, | |
| 30 | + code: &'a str, | |
| 31 | + pkce_verifier: Option<&'a str>, | |
| 32 | + ) -> Vec<(&'a str, &'a str)> { | |
| 33 | + let mut form = vec![ | |
| 34 | + ("client_id", self.client_id.as_str()), | |
| 35 | + ("client_secret", self.client_secret.as_str()), | |
| 36 | + ("code", code), | |
| 37 | + ]; | |
| 38 | + if let Some(verifier) = pkce_verifier { | |
| 39 | + form.push(("code_verifier", verifier)); | |
| 40 | + } | |
| 41 | + form | |
| 42 | + } | |
| 21 | 43 | } |
| 22 | 44 | |
| 23 | -#[derive(Deserialize)] | |
| 45 | +#[derive(Deserialize, Debug)] | |
| 24 | 46 | struct GitHubTokenResponse { |
| 25 | 47 | access_token: String, |
| 26 | 48 | } |
| 27 | 49 | |
| 50 | +/// Parse the GitHub token endpoint response. | |
| 51 | +/// | |
| 52 | +/// RFC 0035 §6: on failure GitHub returns `{"error":...,"error_description":...}` | |
| 53 | +/// with an HTTP 200 status. Reading the body as text and parsing it here lets the | |
| 54 | +/// real provider error surface instead of an opaque "error decoding response body". | |
| 55 | +fn parse_github_token( | |
| 56 | + status: reqwest::StatusCode, | |
| 57 | + body: &str, | |
| 58 | +) -> Result<GitHubTokenResponse, AppError> { | |
| 59 | + serde_json::from_str::<GitHubTokenResponse>(body).map_err(|_| { | |
| 60 | + AppError::Internal(format!( | |
| 61 | + "GitHub token exchange rejected (HTTP {status}): {body}" | |
| 62 | + )) | |
| 63 | + }) | |
| 64 | +} | |
| 65 | + | |
| 28 | 66 | #[derive(Deserialize)] |
| 29 | 67 | struct GitHubUser { |
| 30 | 68 | id: i64, |
@@ -82,25 +120,25 @@ impl OAuthProvider for GitHubProvider {
| 82 | 120 | &self, |
| 83 | 121 | code: &str, |
| 84 | 122 | _redirect_uri: &str, |
| 85 | - _pkce_verifier: Option<&str>, | |
| 123 | + pkce_verifier: Option<&str>, | |
| 86 | 124 | _nonce: Option<&str>, |
| 87 | 125 | ) -> Result<ProviderUserInfo, AppError> { |
| 88 | 126 | let http = reqwest::Client::new(); |
| 89 | 127 | |
| 90 | - let token_resp = http | |
| 128 | + let response = http | |
| 91 | 129 | .post("https://github.com/login/oauth/access_token") |
| 92 | 130 | .header("Accept", "application/json") |
| 93 | - .form(&[ | |
| 94 | - ("client_id", self.client_id.as_str()), | |
| 95 | - ("client_secret", self.client_secret.as_str()), | |
| 96 | - ("code", code), | |
| 97 | - ]) | |
| 131 | + .form(&self.token_form(code, pkce_verifier)) | |
| 98 | 132 | .send() |
| 99 | 133 | .await |
| 100 | - .map_err(|e| AppError::Internal(format!("GitHub token exchange failed: {}", e)))? | |
| 101 | - .json::<GitHubTokenResponse>() | |
| 134 | + .map_err(|e| AppError::Internal(format!("GitHub token exchange failed: {}", e)))?; | |
| 135 | + | |
| 136 | + let status = response.status(); | |
| 137 | + let body = response | |
| 138 | + .text() | |
| 102 | 139 | .await |
| 103 | - .map_err(|e| AppError::Internal(format!("GitHub token parse failed: {}", e)))?; | |
| 140 | + .map_err(|e| AppError::Internal(format!("GitHub token read failed: {}", e)))?; | |
| 141 | + let token_resp = parse_github_token(status, &body)?; | |
| 104 | 142 | |
| 105 | 143 | let user: GitHubUser = http |
| 106 | 144 | .get("https://api.github.com/user") |
@@ -149,3 +187,66 @@ impl OAuthProvider for GitHubProvider {
| 149 | 187 | }) |
| 150 | 188 | } |
| 151 | 189 | } |
| 190 | + | |
| 191 | +#[cfg(test)] | |
| 192 | +mod tests { | |
| 193 | + use super::*; | |
| 194 | + | |
| 195 | + fn provider() -> GitHubProvider { | |
| 196 | + GitHubProvider::new("client-id".to_string(), "client-secret".to_string()) | |
| 197 | + } | |
| 198 | + | |
| 199 | + // RFC 0035 §7.1: the verifier must be present in the token form when supplied. | |
| 200 | + #[test] | |
| 201 | + fn token_form_includes_code_verifier_when_present() { | |
| 202 | + let p = provider(); | |
| 203 | + let form = p.token_form("the-code", Some("the-verifier")); | |
| 204 | + assert!( | |
| 205 | + form.contains(&("code_verifier", "the-verifier")), | |
| 206 | + "code_verifier must be sent to the token endpoint when PKCE is used" | |
| 207 | + ); | |
| 208 | + assert!(form.contains(&("code", "the-code"))); | |
| 209 | + } | |
| 210 | + | |
| 211 | + // RFC 0035 §7.1: a non-PKCE flow (verifier None) must not add the parameter. | |
| 212 | + #[test] | |
| 213 | + fn token_form_omits_code_verifier_when_absent() { | |
| 214 | + let p = provider(); | |
| 215 | + let form = p.token_form("the-code", None); | |
| 216 | + assert!(form.iter().all(|(k, _)| *k != "code_verifier")); | |
| 217 | + } | |
| 218 | + | |
| 219 | + // RFC 0035 §7.2: a code_challenge is emitted at authorization, so a matching | |
| 220 | + // verifier must be carried in the session for the exchange. | |
| 221 | + #[test] | |
| 222 | + fn authorization_url_emits_challenge_and_keeps_verifier() { | |
| 223 | + let auth = provider() | |
| 224 | + .authorization_url("https://app.example/callback") | |
| 225 | + .expect("authorization_url should succeed"); | |
| 226 | + assert!(auth.url.contains("code_challenge=")); | |
| 227 | + assert!(auth.url.contains("code_challenge_method=S256")); | |
| 228 | + assert!( | |
| 229 | + auth.pkce_verifier.is_some(), | |
| 230 | + "verifier must be retained whenever a challenge is sent" | |
| 231 | + ); | |
| 232 | + } | |
| 233 | + | |
| 234 | + // RFC 0035 §6: an error body returned with HTTP 200 must surface the raw | |
| 235 | + // provider message instead of an opaque deserialization error. | |
| 236 | + #[test] | |
| 237 | + fn parse_github_token_surfaces_error_body() { | |
| 238 | + let body = r#"{"error":"bad_verifier","error_description":"code_verifier mismatch"}"#; | |
| 239 | + let err = parse_github_token(reqwest::StatusCode::OK, body) | |
| 240 | + .expect_err("error body must not parse as success"); | |
| 241 | + let msg = err.to_string(); | |
| 242 | + assert!(msg.contains("code_verifier mismatch"), "got: {msg}"); | |
| 243 | + } | |
| 244 | + | |
| 245 | + #[test] | |
| 246 | + fn parse_github_token_accepts_success_body() { | |
| 247 | + let body = r#"{"access_token":"gho_token","token_type":"bearer"}"#; | |
| 248 | + let token = parse_github_token(reqwest::StatusCode::OK, body) | |
| 249 | + .expect("valid token response should parse"); | |
| 250 | + assert_eq!(token.access_token, "gho_token"); | |
| 251 | + } | |
| 252 | +} |
M
crates/rustwarden-core/src/services/oauth/providers/google.rs
+18
-0
@@ -142,3 +142,21 @@ impl OAuthProvider for GoogleProvider {
| 142 | 142 | }) |
| 143 | 143 | } |
| 144 | 144 | } |
| 145 | + | |
| 146 | +#[cfg(test)] | |
| 147 | +mod tests { | |
| 148 | + use super::*; | |
| 149 | + | |
| 150 | + // RFC 0035 §7.2: a code_challenge is emitted at authorization, so a matching | |
| 151 | + // verifier must be retained for the exchange (delegated to `openidconnect`). | |
| 152 | + #[test] | |
| 153 | + fn authorization_url_emits_challenge_and_keeps_verifier() { | |
| 154 | + let provider = GoogleProvider::new("client-id".to_string(), "client-secret".to_string()); | |
| 155 | + let auth = provider | |
| 156 | + .authorization_url("https://app.example/callback") | |
| 157 | + .expect("authorization_url should succeed"); | |
| 158 | + assert!(auth.url.contains("code_challenge=")); | |
| 159 | + assert!(auth.url.contains("code_challenge_method=S256")); | |
| 160 | + assert!(auth.pkce_verifier.is_some()); | |
| 161 | + } | |
| 162 | +} |
M
crates/rustwarden-core/src/services/oauth/providers/microsoft.rs
+19
-0
@@ -148,3 +148,22 @@ impl OAuthProvider for MicrosoftProvider {
| 148 | 148 | }) |
| 149 | 149 | } |
| 150 | 150 | } |
| 151 | + | |
| 152 | +#[cfg(test)] | |
| 153 | +mod tests { | |
| 154 | + use super::*; | |
| 155 | + | |
| 156 | + // RFC 0035 §7.2: a code_challenge is emitted at authorization, so a matching | |
| 157 | + // verifier must be retained for the exchange (delegated to `openidconnect`). | |
| 158 | + #[test] | |
| 159 | + fn authorization_url_emits_challenge_and_keeps_verifier() { | |
| 160 | + let provider = | |
| 161 | + MicrosoftProvider::new("client-id".to_string(), "client-secret".to_string(), None); | |
| 162 | + let auth = provider | |
| 163 | + .authorization_url("https://app.example/callback") | |
| 164 | + .expect("authorization_url should succeed"); | |
| 165 | + assert!(auth.url.contains("code_challenge=")); | |
| 166 | + assert!(auth.url.contains("code_challenge_method=S256")); | |
| 167 | + assert!(auth.pkce_verifier.is_some()); | |
| 168 | + } | |
| 169 | +} |
M
crates/rustwarden-core/src/services/resource_service.rs
+1
-1
@@ -471,7 +471,7 @@ impl ResourceService {
| 471 | 471 | .await?; |
| 472 | 472 | |
| 473 | 473 | let mut all = owned; |
| 474 | - for r in shared.into_iter().chain(public.into_iter()) { | |
| 474 | + for r in shared.into_iter().chain(public) { | |
| 475 | 475 | if !all.iter().any(|existing| existing.id == r.id) { |
| 476 | 476 | all.push(r); |
| 477 | 477 | } |
M
crates/rustwarden-fediverse-guard/Cargo.toml
+3
-3
@@ -24,8 +24,8 @@ rustwarden-fediverse = { path = "../rustwarden-fediverse" }
| 24 | 24 | tokio = { version = "1", features = ["sync", "time", "rt", "macros"] } |
| 25 | 25 | async-trait = "0.1" |
| 26 | 26 | # ORM + migrations |
| 27 | -sea-orm = { version = "2.0.0-rc.20", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] } | |
| 28 | -sea-orm-migration = { version = "2.0.0-rc.20", features = ["sqlx-postgres", "runtime-tokio-native-tls"] } | |
| 27 | +sea-orm = { version = "2.0.0", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] } | |
| 28 | +sea-orm-migration = { version = "2.0.0", features = ["sqlx-postgres", "runtime-tokio-native-tls"] } | |
| 29 | 29 | # Concurrent hot-path |
| 30 | 30 | dashmap = "6" |
| 31 | 31 | # Serialization |
@@ -47,7 +47,7 @@ tower-sessions = { version = "0.14", optional = true }
| 47 | 47 | workspace = true |
| 48 | 48 | |
| 49 | 49 | [dev-dependencies] |
| 50 | -sea-orm = { version = "2.0.0-rc.20", features = ["mock"] } | |
| 50 | +sea-orm = { version = "2.0.0", features = ["mock"] } | |
| 51 | 51 | tokio = { version = "1", features = ["full", "test-util"] } |
| 52 | 52 | |
| 53 | 53 | [[bin]] |
M
crates/rustwarden-fediverse-ui/Cargo.toml
+2
-2
@@ -17,7 +17,7 @@ serde = { version = "1.0", features = ["derive"] }
| 17 | 17 | serde_json = "1.0" |
| 18 | 18 | askama = "0.15" |
| 19 | 19 | tracing = "0.1" |
| 20 | -sea-orm = { version = "2.0.0-rc.20", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] } | |
| 20 | +sea-orm = { version = "2.0.0", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] } | |
| 21 | 21 | uuid = { version = "1.0", features = ["v4", "serde"] } |
| 22 | 22 | chrono = { version = "0.4", features = ["serde"] } |
| 23 | 23 | tower = { version = "0.5", features = ["limit"] } |
@@ -32,7 +32,7 @@ time = { version = "0.3", features = ["macros", "serde"] }
| 32 | 32 | # hit); `tower/util` provides `ServiceExt::oneshot`; `serial_test` serialises |
| 33 | 33 | # the process-global env mutations needed to load `FediverseConfig` / |
| 34 | 34 | # `AuthConfig`. |
| 35 | -sea-orm = { version = "2.0.0-rc.20", features = ["mock"] } | |
| 35 | +sea-orm = { version = "2.0.0", features = ["mock"] } | |
| 36 | 36 | tower = { version = "0.5", features = ["limit", "util"] } |
| 37 | 37 | serial_test = "3" |
| 38 | 38 |
M
crates/rustwarden-fediverse/Cargo.toml
+3
-3
@@ -21,8 +21,8 @@ serde_json = "1.0"
| 21 | 21 | # Tracing |
| 22 | 22 | tracing = "0.1" |
| 23 | 23 | # ORM |
| 24 | -sea-orm = { version = "2.0.0-rc.20", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] } | |
| 25 | -sea-orm-migration = { version = "2.0.0-rc.20", features = ["sqlx-postgres", "runtime-tokio-native-tls"] } | |
| 24 | +sea-orm = { version = "2.0.0", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] } | |
| 25 | +sea-orm-migration = { version = "2.0.0", features = ["sqlx-postgres", "runtime-tokio-native-tls"] } | |
| 26 | 26 | # Time & identifiers |
| 27 | 27 | chrono = { version = "0.4", features = ["serde"] } |
| 28 | 28 | uuid = { version = "1.0", features = ["v4", "serde"] } |
@@ -54,7 +54,7 @@ validator = { version = "0.20", features = ["derive"] }
| 54 | 54 | workspace = true |
| 55 | 55 | |
| 56 | 56 | [dev-dependencies] |
| 57 | -sea-orm = { version = "2.0.0-rc.20", features = ["mock"] } | |
| 57 | +sea-orm = { version = "2.0.0", features = ["mock"] } | |
| 58 | 58 | wiremock = "0.6" |
| 59 | 59 | # Serialise tests that mutate process-wide environment variables |
| 60 | 60 | # (ENCRYPTION_KEY, OAUTH_ENCRYPTION_KEY) so async tests on `MockDatabase` |
M
crates/rustwarden-ui/Cargo.toml
+1
-1
@@ -22,7 +22,7 @@ askama = "0.15"
| 22 | 22 | # Logging |
| 23 | 23 | tracing = "0.1" |
| 24 | 24 | # Database ORM |
| 25 | -sea-orm = { version = "2.0.0-rc.20", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] } | |
| 25 | +sea-orm = { version = "2.0.0", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] } | |
| 26 | 26 | # UUID & Datetime |
| 27 | 27 | uuid = { version = "1.0", features = ["v4", "serde"] } |
| 28 | 28 | chrono = { version = "0.4", features = ["serde"] } |
M
docs/SERVICES_REFERENCE.md
+21
-2
@@ -771,11 +771,30 @@ Interface que chaque provider implemente (Google, GitHub, Discord, Microsoft).
| 771 | 771 | |---------|-----------|-------------| |
| 772 | 772 | | `name` | `(&self) → &str` | Identifiant (`"google"`, `"github"`, `"discord"`, `"microsoft"`). | |
| 773 | 773 | | `display_name` | `(&self) → &str` | Nom affichable (`"Google"`, `"GitHub"`, etc.). | |
| 774 | -| `authorization_url` | `(&self, redirect_uri: &str) → Result<AuthorizationUrl>` | Genere l'URL d'autorisation avec state/nonce/PKCE. | | |
| 775 | -| `exchange_code` | `(&self, code, redirect_uri, pkce_verifier, nonce) → Result<ProviderUserInfo>` | Echange le code d'autorisation contre les infos utilisateur. | | |
| 774 | +| `authorization_url` | `(&self, redirect_uri: &str) → Result<AuthorizationUrl>` | Genere l'URL d'autorisation avec state CSRF, nonce (OIDC) et challenge PKCE `S256`. Le `pkce_verifier` correspondant est conserve en session. | | |
| 775 | +| `exchange_code` | `(&self, code, redirect_uri, pkce_verifier, nonce) → Result<ProviderUserInfo>` | Echange le code d'autorisation contre les infos utilisateur. Le `pkce_verifier` issu de la session est **transmis au endpoint token** (obligatoire depuis que GitHub impose PKCE, cf. RFC 0035). | | |
| 776 | 776 | |
| 777 | 777 | **Providers implementes** : Google (OIDC complet), GitHub (OAuth2 + REST API), Discord (OAuth2 + REST API), Microsoft (Azure AD avec support tenant). |
| 778 | 778 | |
| 779 | +#### PKCE (RFC 7636) — invariant sur les 4 providers | |
| 780 | + | |
| 781 | +Tous les providers emettent un `code_challenge=…&code_challenge_method=S256` a | |
| 782 | +l'autorisation et **rejouent le `code_verifier` a l'echange** : | |
| 783 | + | |
| 784 | +- **Google** et **Microsoft** (OIDC) delèguent au crate `openidconnect` via | |
| 785 | + `set_pkce_verifier(...)`. | |
| 786 | +- **GitHub** et **Discord** (OAuth2 + POST `reqwest` manuel) ajoutent le champ | |
| 787 | + `code_verifier` au formulaire d'echange, **uniquement s'il est present** | |
| 788 | + (rétro-compatible avec un flux sans PKCE). Cf. RFC 0035 : avant ce correctif | |
| 789 | + le verifier etait ignore, ce qui cassait la connexion GitHub depuis que GitHub | |
| 790 | + impose PKCE (14 juillet 2025). | |
| 791 | + | |
| 792 | +> **Diagnostic** : GitHub/Discord renvoient leurs erreurs sous forme de corps | |
| 793 | +> JSON (`{"error":…,"error_description":…}`, parfois en HTTP 200 pour GitHub). | |
| 794 | +> `exchange_code` lit le corps en texte avant de le parser et remonte le message | |
| 795 | +> brut du provider (`… token exchange rejected (HTTP …): …`) au lieu d'une erreur | |
| 796 | +> de desserialisation opaque. | |
| 797 | + | |
| 779 | 798 | --- |
| 780 | 799 | |
| 781 | 800 | ## 15. Rate limiting |
A
docs/rfcs/0035-oauth-pkce-code-verifier.md
+277
-0
@@ -0,0 +1,277 @@
| 1 | +# RFC — OAuth : `code_verifier` PKCE manquant à l'échange (providers GitHub & Discord) | |
| 2 | + | |
| 3 | +| | | | |
| 4 | +|---|---| | |
| 5 | +| **Statut** | Implémenté (2026-06-18) | | |
| 6 | +| **Date** | 2026-06-18 | | |
| 7 | +| **Composant** | `rustwarden-core` — `src/services/oauth/providers/` | | |
| 8 | +| **Auteur** | Intégrateur PasterMan (remonté depuis une instance en production) | | |
| 9 | +| **Destinataires** | Mainteneurs du framework Rustwarden | | |
| 10 | +| **Gravité** | Élevée — connexion OAuth GitHub **totalement cassée** en production | | |
| 11 | + | |
| 12 | +--- | |
| 13 | + | |
| 14 | +## 1. Résumé (TL;DR) | |
| 15 | + | |
| 16 | +Les providers OAuth **GitHub** et **Discord** envoient un `code_challenge` PKCE | |
| 17 | +(méthode `S256`) à l'étape d'autorisation, mais **n'envoient jamais le | |
| 18 | +`code_verifier` correspondant** à l'étape d'échange du code contre un token. Le | |
| 19 | +paramètre `pkce_verifier`, pourtant transmis par le handler de callback, est | |
| 20 | +ignoré (`_pkce_verifier`). | |
| 21 | + | |
| 22 | +Depuis que **GitHub impose PKCE (14 juillet 2025)**, un `code_challenge` envoyé | |
| 23 | +sans `code_verifier` est rejeté : le endpoint token renvoie un corps JSON | |
| 24 | +d'erreur (sans `access_token`). Résultat côté Rustwarden : | |
| 25 | + | |
| 26 | +``` | |
| 27 | +ERROR rustwarden_core::error: Internal error: GitHub token parse failed: error decoding response body | |
| 28 | +``` | |
| 29 | + | |
| 30 | +et l'utilisateur reçoit un `500 {"error":"Internal server error"}`. | |
| 31 | + | |
| 32 | +Les providers **Google** et **Microsoft** ne sont **pas** affectés : ils passent | |
| 33 | +par le crate `openidconnect` et appellent `set_pkce_verifier(...)` correctement. | |
| 34 | + | |
| 35 | +**Demande** : inclure `code_verifier` dans l'échange des providers GitHub et | |
| 36 | +Discord. Correctif minime, sans changement d'API publique. | |
| 37 | + | |
| 38 | +--- | |
| 39 | + | |
| 40 | +## 2. Symptôme observé en production | |
| 41 | + | |
| 42 | +- L'utilisateur clique « Se connecter avec GitHub ». | |
| 43 | +- Redirection vers `https://github.com/login/oauth/authorize?...&code_challenge=...&code_challenge_method=S256` — OK. | |
| 44 | +- Retour sur `https://<domaine>/api/v1/auth/oauth/github/callback?code=...&state=...`. | |
| 45 | +- Validation du `state` CSRF : **OK** (aucune erreur « state mismatch » dans les logs). | |
| 46 | +- Échange du `code` → **échec** : | |
| 47 | + | |
| 48 | +``` | |
| 49 | +DEBUG reqwest::connect: starting new connection: https://github.com/ | |
| 50 | +DEBUG hyper_util...: connected to 140.82.121.4:443 | |
| 51 | +ERROR rustwarden_core::error: Internal error: GitHub token parse failed: error decoding response body | |
| 52 | +``` | |
| 53 | + | |
| 54 | +Le message est trompeur : GitHub répond `200 OK` avec un corps du type | |
| 55 | +`{"error":"...","error_description":"..."}`. Comme le code désérialise | |
| 56 | +directement dans la struct de succès (`GitHubTokenResponse { access_token }`), | |
| 57 | +le champ manquant produit une erreur « error decoding response body » qui | |
| 58 | +**masque le vrai message d'erreur de GitHub** (voir §6). | |
| 59 | + | |
| 60 | +--- | |
| 61 | + | |
| 62 | +## 3. Cause racine | |
| 63 | + | |
| 64 | +### 3.1. Étape d'autorisation — un `code_challenge` est émis | |
| 65 | + | |
| 66 | +`src/services/oauth/providers/github.rs` (`authorization_url`) : | |
| 67 | + | |
| 68 | +```rust | |
| 69 | +// ~ligne 57 | |
| 70 | +let (pkce_challenge, pkce_verifier) = PkceCodeChallenge::new_random_sha256(); | |
| 71 | + | |
| 72 | +let url = format!( | |
| 73 | + "https://github.com/login/oauth/authorize?\ | |
| 74 | + client_id={}&redirect_uri={}&scope=user:email&state={}&\ | |
| 75 | + code_challenge={}&\ // ← challenge envoyé | |
| 76 | + code_challenge_method=S256", // ← méthode S256 | |
| 77 | + ... | |
| 78 | +); | |
| 79 | + | |
| 80 | +Ok(AuthorizationUrl { | |
| 81 | + url, | |
| 82 | + csrf_state: state.secret().to_string(), | |
| 83 | + nonce: None, | |
| 84 | + pkce_verifier: Some(pkce_verifier.secret().to_string()), // ← verifier conservé en session | |
| 85 | +}) | |
| 86 | +``` | |
| 87 | + | |
| 88 | +### 3.2. Le handler transmet bien le verifier | |
| 89 | + | |
| 90 | +`src/auth/oauth_handlers.rs` (`oauth_callback`) : | |
| 91 | + | |
| 92 | +```rust | |
| 93 | +// ~ligne 170 : récupéré depuis la session | |
| 94 | +let pkce_verifier: Option<String> = session.get(OAUTH_PKCE_KEY).await.unwrap_or(None); | |
| 95 | + | |
| 96 | +// ~ligne 186 : passé à l'échange | |
| 97 | +let user_info = provider | |
| 98 | + .exchange_code(code, &redirect_uri, pkce_verifier.as_deref(), nonce.as_deref()) | |
| 99 | + .await?; | |
| 100 | +``` | |
| 101 | + | |
| 102 | +### 3.3. L'échange ignore le verifier — le bug | |
| 103 | + | |
| 104 | +`src/services/oauth/providers/github.rs` (`exchange_code`) : | |
| 105 | + | |
| 106 | +```rust | |
| 107 | +async fn exchange_code( | |
| 108 | + &self, | |
| 109 | + code: &str, | |
| 110 | + _redirect_uri: &str, | |
| 111 | + _pkce_verifier: Option<&str>, // ← reçu mais IGNORÉ (préfixe _) | |
| 112 | + _nonce: Option<&str>, | |
| 113 | +) -> Result<ProviderUserInfo, AppError> { | |
| 114 | + let http = reqwest::Client::new(); | |
| 115 | + | |
| 116 | + let token_resp = http | |
| 117 | + .post("https://github.com/login/oauth/access_token") | |
| 118 | + .header("Accept", "application/json") | |
| 119 | + .form(&[ | |
| 120 | + ("client_id", self.client_id.as_str()), | |
| 121 | + ("client_secret", self.client_secret.as_str()), | |
| 122 | + ("code", code), | |
| 123 | + // ← MANQUE: ("code_verifier", verifier) | |
| 124 | + ]) | |
| 125 | + .send().await? | |
| 126 | + .json::<GitHubTokenResponse>().await?; // ← échoue ici quand GitHub renvoie une erreur | |
| 127 | + ... | |
| 128 | +} | |
| 129 | +``` | |
| 130 | + | |
| 131 | +### 3.4. Pourquoi maintenant | |
| 132 | + | |
| 133 | +GitHub a généralisé la prise en charge de PKCE le **14 juillet 2025** | |
| 134 | +(cf. §9). Auparavant, un `code_challenge` envoyé était ignoré, et l'échange | |
| 135 | +sans `code_verifier` réussissait. Désormais, le code d'autorisation est lié au | |
| 136 | +challenge et l'échange **exige** le verifier ; son absence provoque le rejet. | |
| 137 | +C'est une **régression côté serveur GitHub** qui révèle un défaut latent du | |
| 138 | +provider. | |
| 139 | + | |
| 140 | +--- | |
| 141 | + | |
| 142 | +## 4. Périmètre — providers concernés | |
| 143 | + | |
| 144 | +| Provider | Fichier | `code_challenge` à l'autorisation | `code_verifier` à l'échange | État | | |
| 145 | +|---|---|:--:|:--:|:--:| | |
| 146 | +| **GitHub** | `providers/github.rs` | oui (`~l.65`) | **non** (`_pkce_verifier`, `~l.85`) | ❌ | | |
| 147 | +| **Discord** | `providers/discord.rs` | oui (`~l.61`) | **non** (`_pkce_verifier`, `~l.81`) | ❌ | | |
| 148 | +| Google | `providers/google.rs` | oui (`~l.48`) | oui (`set_pkce_verifier`, `~l.100`) | ✅ | | |
| 149 | +| Microsoft | `providers/microsoft.rs` | oui (`~l.50`) | oui (`set_pkce_verifier`, `~l.106`) | ✅ | | |
| 150 | + | |
| 151 | +**Différence structurelle** : Google et Microsoft sont des providers OIDC qui | |
| 152 | +délèguent l'échange au crate `openidconnect` | |
| 153 | +(`token_request.set_pkce_verifier(PkceCodeVerifier::new(verifier))`). GitHub et | |
| 154 | +Discord construisent **manuellement** un POST `reqwest` et ont omis le paramètre. | |
| 155 | + | |
| 156 | +Discord applique également PKCE lorsqu'un challenge est fourni ; le provider | |
| 157 | +Discord est donc cassé de la même manière (ou le deviendra), même si ce RFC est | |
| 158 | +motivé par GitHub. | |
| 159 | + | |
| 160 | +--- | |
| 161 | + | |
| 162 | +## 5. Correctif proposé | |
| 163 | + | |
| 164 | +Ajouter `code_verifier` au formulaire d'échange, **uniquement s'il est présent** | |
| 165 | +(rétro-compatible avec un flux sans PKCE), pour `github.rs` et `discord.rs`. | |
| 166 | + | |
| 167 | +### 5.1. `providers/github.rs` | |
| 168 | + | |
| 169 | +```rust | |
| 170 | +async fn exchange_code( | |
| 171 | + &self, | |
| 172 | + code: &str, | |
| 173 | + _redirect_uri: &str, | |
| 174 | + pkce_verifier: Option<&str>, // était: _pkce_verifier | |
| 175 | + _nonce: Option<&str>, | |
| 176 | +) -> Result<ProviderUserInfo, AppError> { | |
| 177 | + let http = reqwest::Client::new(); | |
| 178 | + | |
| 179 | + let mut form = vec![ | |
| 180 | + ("client_id", self.client_id.as_str()), | |
| 181 | + ("client_secret", self.client_secret.as_str()), | |
| 182 | + ("code", code), | |
| 183 | + ]; | |
| 184 | + if let Some(verifier) = pkce_verifier { | |
| 185 | + form.push(("code_verifier", verifier)); // ← pièce manquante | |
| 186 | + } | |
| 187 | + | |
| 188 | + let token_resp = http | |
| 189 | + .post("https://github.com/login/oauth/access_token") | |
| 190 | + .header("Accept", "application/json") | |
| 191 | + .form(&form) | |
| 192 | + .send().await | |
| 193 | + .map_err(|e| AppError::Internal(format!("GitHub token exchange failed: {}", e)))? | |
| 194 | + .json::<GitHubTokenResponse>().await | |
| 195 | + .map_err(|e| AppError::Internal(format!("GitHub token parse failed: {}", e)))?; | |
| 196 | + // ... reste inchangé | |
| 197 | +} | |
| 198 | +``` | |
| 199 | + | |
| 200 | +### 5.2. `providers/discord.rs` | |
| 201 | + | |
| 202 | +Même correction : dé-préfixer `_pkce_verifier` → `pkce_verifier` et l'ajouter au | |
| 203 | +formulaire de la requête `POST https://discord.com/api/oauth2/token` sous la clé | |
| 204 | +`code_verifier` quand il est présent. | |
| 205 | + | |
| 206 | +--- | |
| 207 | + | |
| 208 | +## 6. Amélioration secondaire recommandée (qualité de diagnostic) | |
| 209 | + | |
| 210 | +Indépendamment du PKCE, l'échange désérialise **directement** la réponse dans la | |
| 211 | +struct de succès, ce qui **efface le message d'erreur du provider** et rend tout | |
| 212 | +incident illisible (« error decoding response body »). Recommandation : lire le | |
| 213 | +corps en texte d'abord, et remonter l'erreur OAuth structurée. | |
| 214 | + | |
| 215 | +```rust | |
| 216 | +let status = resp.status(); | |
| 217 | +let body = resp.text().await | |
| 218 | + .map_err(|e| AppError::Internal(format!("GitHub token read failed: {e}")))?; | |
| 219 | + | |
| 220 | +match serde_json::from_str::<GitHubTokenResponse>(&body) { | |
| 221 | + Ok(t) => t, | |
| 222 | + Err(_) => { | |
| 223 | + // GitHub renvoie {"error":"...","error_description":"..."} en HTTP 200 | |
| 224 | + return Err(AppError::Internal(format!( | |
| 225 | + "GitHub token exchange rejected (HTTP {status}): {body}" | |
| 226 | + ))); | |
| 227 | + } | |
| 228 | +} | |
| 229 | +``` | |
| 230 | + | |
| 231 | +Cela aurait fait apparaître directement dans les logs, par exemple, | |
| 232 | +`{"error":"...","error_description":"... code_verifier ..."}` au lieu d'un | |
| 233 | +message générique — divisant par dix le temps de diagnostic. | |
| 234 | + | |
| 235 | +--- | |
| 236 | + | |
| 237 | +## 7. Tests recommandés | |
| 238 | + | |
| 239 | +1. **Test unitaire d'échange** : vérifier que le formulaire POST contient | |
| 240 | + `code_verifier` lorsque `exchange_code` reçoit `Some(verifier)`, et qu'il ne | |
| 241 | + le contient pas pour `None` (mock du endpoint token via `wiremock`). | |
| 242 | +2. **Test de non-régression PKCE** : pour les 4 providers, garantir qu'un | |
| 243 | + `code_challenge` émis à l'autorisation est toujours accompagné d'un | |
| 244 | + `code_verifier` à l'échange (invariant testé directement). | |
| 245 | +3. **Test d'intégration GitHub** (manuel/CI gated) : flux complet sur une OAuth | |
| 246 | + App de test → obtention d'un `access_token`. | |
| 247 | + | |
| 248 | +--- | |
| 249 | + | |
| 250 | +## 8. Compatibilité et risques | |
| 251 | + | |
| 252 | +- **API publique** : inchangée. La signature du trait `OAuthProvider` n'est pas | |
| 253 | + modifiée ; seul le corps de `exchange_code` change (un `_pkce_verifier` | |
| 254 | + jusque-là ignoré devient utilisé). | |
| 255 | +- **Rétro-compatibilité** : l'ajout est conditionné par `if let Some(verifier)`, | |
| 256 | + donc un déploiement sans PKCE (verifier `None`) se comporte comme avant. | |
| 257 | +- **Sécurité** : envoyer le `code_verifier` est précisément le comportement PKCE | |
| 258 | + attendu (RFC 7636) ; cela **renforce** la sécurité du flux (protection contre | |
| 259 | + l'interception du code d'autorisation). | |
| 260 | +- **Risque de ne rien faire** : connexion GitHub définitivement cassée pour tous | |
| 261 | + les intégrateurs à jour des changements GitHub ; Discord cassé de même. | |
| 262 | + | |
| 263 | +--- | |
| 264 | + | |
| 265 | +## 9. Références | |
| 266 | + | |
| 267 | +- GitHub Changelog — *PKCE support for OAuth and GitHub App authentication* | |
| 268 | + (14 juillet 2025) : | |
| 269 | + https://github.blog/changelog/2025-07-14-pkce-support-for-oauth-and-github-app-authentication/ | |
| 270 | +- RFC 7636 — *Proof Key for Code Exchange by OAuth Public Clients* : | |
| 271 | + https://www.rfc-editor.org/rfc/rfc7636 | |
| 272 | +- Fichiers concernés (chemins relatifs au crate `rustwarden-core`) : | |
| 273 | + - `src/services/oauth/providers/github.rs` — `authorization_url`, `exchange_code` | |
| 274 | + - `src/services/oauth/providers/discord.rs` — `authorization_url`, `exchange_code` | |
| 275 | + - `src/services/oauth/providers/google.rs` — référence d'implémentation correcte | |
| 276 | + - `src/services/oauth/providers/microsoft.rs` — référence d'implémentation correcte | |
| 277 | + - `src/auth/oauth_handlers.rs` — `oauth_callback` (transmet `pkce_verifier`) |
M
template/Cargo.toml
+1
-1
@@ -13,7 +13,7 @@ rustwarden-core = { git = "https://github.com/OWNER/rustwarden.git", path = "cra
| 13 | 13 | rustwarden-ui = { git = "https://github.com/OWNER/rustwarden.git", path = "crates/rustwarden-ui" } |
| 14 | 14 | axum = { version = "0.8", features = ["macros"] } |
| 15 | 15 | tokio = { version = "1", features = ["full"] } |
| 16 | -sea-orm = { version = "2.0.0-rc.20", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] } | |
| 16 | +sea-orm = { version = "2.0.0", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] } | |
| 17 | 17 | tracing = "0.1" |
| 18 | 18 | anyhow = "1.0" |
| 19 | 19 | async-trait = "0.1" |
M
tools/rustwarden-cli/src/templates.rs
+2
-2
@@ -160,7 +160,7 @@ resolver = "2"
| 160 | 160 | |
| 161 | 161 | [workspace.package] |
| 162 | 162 | edition = "2024" |
| 163 | -rust-version = "1.85" | |
| 163 | +rust-version = "1.94" | |
| 164 | 164 | |
| 165 | 165 | [workspace.lints.clippy] |
| 166 | 166 | empty_line_after_doc_comments = "allow" |
@@ -182,7 +182,7 @@ path = "src/main.rs"
| 182 | 182 | rustwarden-core = {{ path = "crates/rustwarden-core" }}{ui_dep}{fediverse_dep}{fediverse_ui_dep} |
| 183 | 183 | axum = {{ version = "0.8", features = ["macros"] }} |
| 184 | 184 | tokio = {{ version = "1", features = ["full"] }} |
| 185 | -sea-orm = {{ version = "2.0.0-rc.20", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] }} | |
| 185 | +sea-orm = {{ version = "=2.0.0", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] }} | |
| 186 | 186 | tracing = "0.1" |
| 187 | 187 | anyhow = "1.0" |
| 188 | 188 | async-trait = "0.1" |
GitRust