diff --git a/Cargo.lock b/Cargo.lock index 52ea2675..a4a9773e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,9 +120,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" [[package]] name = "arbitrary" @@ -135,9 +135,9 @@ dependencies = [ [[package]] name = "arc-swap" -version = "1.8.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d03449bb8ca2cc2ef70869af31463d1ae5ccc8fa3e334b307203fbf815207e" +checksum = "f9f3647c145568cec02c42054e07bdf9a5a698e15b466fb2341bfc393cd24aa5" dependencies = [ "rustversion", ] @@ -180,9 +180,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "ascii-canvas" -version = "3.0.0" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +checksum = "ef1e3e699d84ab1b0911a1010c5c106aa34ae89aeac103be5ce0c3859db1e891" dependencies = [ "term", ] @@ -211,7 +211,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", "synstructure", ] @@ -223,7 +223,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -293,7 +293,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -315,7 +315,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -326,7 +326,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -565,7 +565,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -583,7 +583,7 @@ dependencies = [ "regex", "rustc-hash 2.1.1", "shlex", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -602,30 +602,15 @@ dependencies = [ "serde_json", ] -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec 0.6.3", -] - [[package]] name = "bit-set" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ - "bit-vec 0.8.0", + "bit-vec", ] -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - [[package]] name = "bit-vec" version = "0.8.0" @@ -634,9 +619,9 @@ checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" dependencies = [ "serde_core", ] @@ -787,14 +772,14 @@ checksum = "89385e82b5d1821d2219e0b095efa2cc1f246cbf99080f3be46a1a85c0d392d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] name = "bytemuck" -version = "1.24.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" [[package]] name = "byteorder" @@ -804,9 +789,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" dependencies = [ "serde", ] @@ -903,9 +888,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.54" +version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6354c81bbfd62d9cfa9cb3c773c2b7b2a3a482d569de977fd0e961f6e7c00583" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", "jobserver", @@ -1479,7 +1464,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -1513,7 +1498,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -1527,7 +1512,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -1538,7 +1523,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -1549,7 +1534,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -1704,9 +1689,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "cc3dc5ad92c2e2d1c193bbbbdf2ea477cb81331de4f3103f267ca18368b988c4" dependencies = [ "powerfmt", "serde_core", @@ -1720,7 +1705,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -1803,16 +1788,6 @@ dependencies = [ "dirs-sys", ] -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - [[package]] name = "dirs-sys" version = "0.5.0" @@ -1821,21 +1796,10 @@ checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", - "redox_users 0.5.2", + "redox_users", "windows-sys 0.61.2", ] -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users 0.4.6", - "winapi", -] - [[package]] name = "displaydoc" version = "0.2.5" @@ -1844,7 +1808,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -2044,9 +2008,9 @@ dependencies = [ [[package]] name = "ena" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" +checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1" dependencies = [ "log", ] @@ -2075,7 +2039,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -2127,7 +2091,7 @@ version = "0.15.4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -2154,7 +2118,7 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72cf461f865c862bb7dc573f643dd6a2b6842f7c30b07882b56bd148cc2761b8" dependencies = [ - "bit-set 0.8.0", + "bit-set", "regex-automata", "regex-syntax", ] @@ -2216,15 +2180,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "find-msvc-tools" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db" - -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "fixedbitset" @@ -2234,9 +2192,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "libz-sys", @@ -2353,7 +2311,7 @@ checksum = "c4ca5370149145ec3741cd7e82832f17f893b9421ee4e484d9511c6702bd9911" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", "try_map", ] @@ -2385,9 +2343,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -2400,9 +2358,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -2410,15 +2368,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -2427,9 +2385,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-lite" @@ -2448,32 +2406,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -2483,7 +2441,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -2556,6 +2513,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", + "wasip3", +] + [[package]] name = "ghash" version = "0.5.1" @@ -2589,7 +2559,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -2714,7 +2684,7 @@ checksum = "149e3ea90eb5a26ad354cfe3cb7f7401b9329032d0235f2687d03a35f30e5d4c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -3135,7 +3105,7 @@ dependencies = [ "tokio", "tokio-rustls 0.26.4", "tower-service", - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", ] [[package]] @@ -3153,14 +3123,13 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64 0.22.1", "bytes", "futures-channel", - "futures-core", "futures-util", "http 1.4.0", "http-body 1.0.1", @@ -3280,6 +3249,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "idea" version = "0.5.1" @@ -3388,7 +3363,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", "zstd", ] @@ -3505,15 +3480,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -3660,9 +3626,9 @@ dependencies = [ [[package]] name = "jmap-tools" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6ea6b2f1d3b2c7c53dfa4fc7bf2bc2a419fb30920849a01300dabeac9493013" +checksum = "1913b7861fd4a4c4dc25a617f06c4952525f9ed8bb880a3dba672953188f2eed" dependencies = [ "hashify", "rkyv", @@ -3680,6 +3646,7 @@ dependencies = [ "hashify", "jmap-tools", "mail-parser", + "registry", "rkyv", "serde", "serde_json", @@ -3744,9 +3711,9 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" dependencies = [ "cpufeatures", ] @@ -3791,32 +3758,33 @@ dependencies = [ [[package]] name = "lalrpop" -version = "0.20.2" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" +checksum = "ba4ebbd48ce411c1d10fb35185f5a51a7bfa3d8b24b4e330d30c9e3a34129501" dependencies = [ "ascii-canvas", - "bit-set 0.5.3", + "bit-set", "ena", - "itertools 0.11.0", + "itertools 0.14.0", "lalrpop-util", - "petgraph 0.6.5", + "petgraph 0.7.1", "regex", "regex-syntax", + "sha3", "string_cache", "term", - "tiny-keccak", "unicode-xid", "walkdir", ] [[package]] name = "lalrpop-util" -version = "0.20.2" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" +checksum = "b5baa5e9ff84f1aefd264e6869907646538a52147a755d494517a8007fb48733" dependencies = [ "regex-automata", + "rustversion", ] [[package]] @@ -3863,6 +3831,12 @@ dependencies = [ "x509-parser", ] +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libbz2-rs-sys" version = "0.2.2" @@ -3871,9 +3845,9 @@ checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7" [[package]] name = "libc" -version = "0.2.180" +version = "0.2.182" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" [[package]] name = "libflate" @@ -4112,9 +4086,9 @@ dependencies = [ [[package]] name = "mail-parser" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf4390741c4e6fa330bdeccdfb580815dbb462952de91838b723357985119a3" +checksum = "f82a3d6522697593ba4c683e0a6ee5a40fee93bc1a525e3cc6eeb3da11fd8897" dependencies = [ "encoding_rs", "hashify", @@ -4136,7 +4110,7 @@ dependencies = [ "smtp-proto", "tokio", "tokio-rustls 0.26.4", - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", ] [[package]] @@ -4191,7 +4165,7 @@ checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -4229,9 +4203,9 @@ checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0" [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memory-stats" @@ -4360,7 +4334,7 @@ checksum = "4568f25ccbd45ab5d5603dc34318c1ec56b117531781260002151b8530a9f931" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -4376,7 +4350,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", "termcolor", "thiserror 2.0.18", ] @@ -4597,9 +4571,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" [[package]] name = "num-integer" @@ -4660,7 +4634,25 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags", +] + +[[package]] +name = "objc2-system-configuration" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7216bd11cbda54ccabcab84d523dc93b858ec75ecfb3a7d89513fa22464da396" +dependencies = [ + "objc2-core-foundation", ] [[package]] @@ -4732,7 +4724,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -4982,9 +4974,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.5" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9eb05c21a464ea704b53158d358a31e6425db2f63a1a7312268b05fe2b75f7" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" dependencies = [ "memchr", "ucd-trie", @@ -4992,9 +4984,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.8.5" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f9dbced329c441fa79d80472764b1a2c7e57123553b8519b36663a2fb234ed" +checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77" dependencies = [ "pest", "pest_generator", @@ -5002,22 +4994,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.5" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bb96d5051a78f44f43c8f712d8e810adb0ebf923fc9ed2655a7f66f63ba8ee5" +checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] name = "pest_meta" -version = "2.8.5" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "602113b5b5e8621770cfd490cfd90b9f84ab29bd2b0e49ad83eb6d186cef2365" +checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" dependencies = [ "pest", "sha2 0.10.9", @@ -5025,11 +5017,11 @@ dependencies = [ [[package]] name = "petgraph" -version = "0.6.5" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" dependencies = [ - "fixedbitset 0.4.2", + "fixedbitset", "indexmap 2.13.0", ] @@ -5039,7 +5031,7 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ - "fixedbitset 0.5.7", + "fixedbitset", "hashbrown 0.15.5", "indexmap 2.13.0", "serde", @@ -5095,7 +5087,7 @@ dependencies = [ "phf_shared 0.13.1", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -5142,7 +5134,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -5250,9 +5242,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "postgres-protocol" @@ -5328,7 +5320,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -5402,7 +5394,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -5420,7 +5412,7 @@ version = "0.15.4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -5457,7 +5449,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -5472,9 +5464,9 @@ dependencies = [ [[package]] name = "psl" -version = "2.1.183" +version = "2.1.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4171658a0c9db483caa2dbd02dd4ade6574a23d7e3ff3483646f9b5e9dbd5b0" +checksum = "66fed3dc7578357ff12137c75eac73413b6aba9a7204916c19f2a0e9e1e920e0" dependencies = [ "psl-types", ] @@ -5502,7 +5494,7 @@ checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -5944,7 +5936,7 @@ dependencies = [ "tokio-rustls 0.26.4", "tokio-util", "url", - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", ] [[package]] @@ -5956,17 +5948,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "redox_users" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" -dependencies = [ - "getrandom 0.2.17", - "libredox", - "thiserror 1.0.69", -] - [[package]] name = "redox_users" version = "0.5.2" @@ -5995,14 +5976,14 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] name = "regex" -version = "1.12.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -6012,9 +5993,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -6023,9 +6004,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" [[package]] name = "registry" @@ -6033,6 +6014,7 @@ version = "0.15.4" dependencies = [ "ahash", "hashify", + "jmap-tools", "serde", "serde_json", "trc", @@ -6090,7 +6072,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", ] [[package]] @@ -6153,9 +6135,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360b333c61ae24e5af3ae7c8660bd6b21ccd8200dbbc5d33c2454421e85b9c69" +checksum = "1a30e631b7f4a03dee9056b8ef6982e8ba371dd5bedb74d3ec86df4499132c70" dependencies = [ "bytecheck", "bytes", @@ -6172,13 +6154,13 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02f8cdd12b307ab69fe0acf4cd2249c7460eb89dce64a0febadf934ebb6a9e" +checksum = "8100bb34c0a1d0f907143db3149e6b4eea3c33b9ee8b189720168e818303986f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -6428,7 +6410,7 @@ dependencies = [ "openssl-probe 0.2.1", "rustls-pki-types", "schannel", - "security-framework 3.5.1", + "security-framework 3.6.0", ] [[package]] @@ -6474,7 +6456,7 @@ dependencies = [ "rustls-native-certs 0.8.3", "rustls-platform-verifier-android", "rustls-webpki 0.103.9", - "security-framework 3.5.1", + "security-framework 3.6.0", "security-framework-sys", "webpki-root-certs", "windows-sys 0.61.2", @@ -6525,9 +6507,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "salsa20" @@ -6594,9 +6576,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e910108742c57a770f492731f99be216a52fadd361b06c8fb59d74ccc267d2" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" dependencies = [ "dyn-clone", "either", @@ -6608,14 +6590,14 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4908ad288c5035a8eb12cfdf0d49270def0a268ee162b75eeee0f85d155a7c45" +checksum = "7d115b50f4aaeea07e79c1912f645c7513d81715d0420f8bc77a18c6260b307f" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -6691,9 +6673,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.5.1" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +checksum = "d17b898a6d6948c3a8ee4372c17cb384f90d2e6e912ef00895b14fd7ab54ec38" dependencies = [ "bitflags", "core-foundation 0.10.1", @@ -6704,9 +6686,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.15.0" +version = "2.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +checksum = "321c8673b092a9a42605034a9879d73cb79101ed5fd117bc9a597b89b4e9e61a" dependencies = [ "core-foundation-sys", "libc", @@ -6720,9 +6702,9 @@ checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "sequoia-openpgp" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0e334ce3ec5b9b47d86a80563b3ecec435f59acf37e86058b3b686a42c5a2ba" +checksum = "0620e44a7d514adf7df87b44db235f13b81fed7ddc265adb26f014d42626ac47" dependencies = [ "aes", "aes-gcm", @@ -6761,7 +6743,7 @@ dependencies = [ "p256", "p384", "p521", - "rand 0.8.5", + "rand 0.9.2", "rand_core 0.6.4", "regex", "regex-syntax", @@ -6814,7 +6796,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -6825,7 +6807,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -6870,7 +6852,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -6897,7 +6879,7 @@ dependencies = [ "indexmap 1.9.3", "indexmap 2.13.0", "schemars 0.9.0", - "schemars 1.2.0", + "schemars 1.2.1", "serde_core", "serde_json", "serde_with_macros", @@ -6913,7 +6895,7 @@ dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -6952,7 +6934,7 @@ checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -7164,9 +7146,9 @@ checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" @@ -7221,7 +7203,7 @@ dependencies = [ "trc", "types", "utils", - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", "x509-parser", ] @@ -7511,9 +7493,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.114" +version = "2.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +checksum = "6e614ed320ac28113fa64972c4262d5dbc89deacdfd00c34a3e4cea073243c12" dependencies = [ "proc-macro2", "quote", @@ -7537,7 +7519,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -7554,13 +7536,11 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "term" -version = "0.7.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +checksum = "d8c27177b12a6399ffc08b98f76f7c9a1f4fe9fc967c784c5a071fa8d93cf7e1" dependencies = [ - "dirs-next", - "rustversion", - "winapi", + "windows-sys 0.61.2", ] [[package]] @@ -7666,7 +7646,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -7677,7 +7657,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -7691,9 +7671,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.45" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", @@ -7707,15 +7687,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.25" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -7804,7 +7784,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -7938,9 +7918,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.6+spec-1.1.0" +version = "1.0.8+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +checksum = "0742ff5ff03ea7e67c8ae6c93cac239e0d9784833362da3f9a9c1da8dfefcbdc" dependencies = [ "winnow", ] @@ -8074,7 +8054,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -8286,9 +8266,9 @@ checksum = "0b993bddc193ae5bd0d623b49ec06ac3e9312875fdae725a975c51db1cc1677f" [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" [[package]] name = "unicode-normalization" @@ -8363,7 +8343,7 @@ checksum = "3b5bb2756c16fb66f80cfbf5fb0e0c09a7001e739f453c9ec241b9c8b1556fda" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -8435,18 +8415,18 @@ dependencies = [ "tokio", "tokio-rustls 0.26.4", "trc", - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", "x509-parser", "xxhash-rust", ] [[package]] name = "uuid" -version = "1.20.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" +checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.1", "js-sys", "serde_core", "sha1_smol", @@ -8473,7 +8453,7 @@ checksum = "8c44ce98e7227a04eeb4cf9c784109a5c9710e54849ceb4f09f8597247897f1e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", "unzip-n", ] @@ -8562,6 +8542,15 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "wasite" version = "1.0.2" @@ -8617,7 +8606,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", "wasm-bindgen-shared", ] @@ -8630,6 +8619,28 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.13.0", + "wasm-encoder", + "wasmparser", +] + [[package]] name = "wasm-streams" version = "0.4.2" @@ -8643,6 +8654,18 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "semver", +] + [[package]] name = "web-sys" version = "0.3.85" @@ -8665,9 +8688,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36a29fc0408b113f68cf32637857ab740edfafdf460c326cd2afaa2d84cc05dc" +checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" dependencies = [ "rustls-pki-types", ] @@ -8678,14 +8701,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", ] [[package]] name = "webpki-roots" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" dependencies = [ "rustls-pki-types", ] @@ -8701,11 +8724,13 @@ dependencies = [ [[package]] name = "whoami" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fae98cf96deed1b7572272dfc777713c249ae40aa1cf8862e091e8b745f5361" +checksum = "d6a5b12f9df4f978d2cfdb1bd3bac52433f44393342d7ee9c25f5a1c14c0f45d" dependencies = [ + "libc", "libredox", + "objc2-system-configuration", "wasite", "web-sys", ] @@ -8768,7 +8793,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -8779,7 +8804,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -9118,6 +9143,88 @@ name = "wit-bindgen" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.13.0", + "prettyplease", + "syn 2.0.115", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.115", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap 2.13.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.13.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "writeable" @@ -9147,9 +9254,9 @@ dependencies = [ [[package]] name = "x509-parser" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3e137310115a65136898d2079f003ce33331a6c4b0d51f1531d1be082b6425" +checksum = "d43b0f71ce057da06bc0851b23ee24f3f86190b07203dd8f567d0b706a185202" dependencies = [ "asn1-rs", "data-encoding", @@ -9203,7 +9310,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", "synstructure", ] @@ -9350,7 +9457,7 @@ dependencies = [ "hashbrown 0.16.1", "keyed-set", "rand 0.8.5", - "schemars 1.2.0", + "schemars 1.2.1", "serde", "token-cell", "zenoh-result", @@ -9394,7 +9501,7 @@ dependencies = [ "tokio", "tokio-util", "tracing", - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", "x509-parser", "zenoh-buffers", "zenoh-codec", @@ -9423,7 +9530,7 @@ dependencies = [ "tokio", "tokio-util", "tracing", - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", "zenoh-config", "zenoh-core", "zenoh-link-commons", @@ -9470,7 +9577,7 @@ dependencies = [ "tokio-rustls 0.26.4", "tokio-util", "tracing", - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", "x509-parser", "zenoh-config", "zenoh-core", @@ -9510,7 +9617,7 @@ checksum = "b760a458cd906ac888b37fd1abdb21a0f58ecc64cc3882f83a976cb5ca8e0632" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", "zenoh-keyexpr", ] @@ -9649,7 +9756,7 @@ dependencies = [ "libc", "libloading", "pnet_datalink", - "schemars 1.2.0", + "schemars 1.2.1", "serde", "serde_json", "shellexpand", @@ -9663,22 +9770,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.35" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdea86ddd5568519879b8187e1cf04e24fce28f7fe046ceecbce472ff19a2572" +checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.35" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c15e1b46eff7c6c91195752e0eeed8ef040e391cdece7c25376957d5f15df22" +checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -9698,7 +9805,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", "synstructure", ] @@ -9719,7 +9826,7 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -9752,7 +9859,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -9784,15 +9891,15 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.5.5" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" +checksum = "a7948af682ccbc3342b6e9420e8c51c1fe5d7bf7756002b4a3c6cabfe96a7e3c" [[package]] name = "zmij" -version = "1.0.17" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02aae0f83f69aafc94776e879363e9771d7ecbffe2c7fbb6c14c5e00dfe88439" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" [[package]] name = "zopfli" diff --git a/crates/common/src/config/server/mod.rs b/crates/common/src/config/server/mod.rs index ee6ef496..5b2afcc5 100644 --- a/crates/common/src/config/server/mod.rs +++ b/crates/common/src/config/server/mod.rs @@ -8,7 +8,7 @@ use crate::network::TcpAcceptor; use ahash::AHashMap; use registry::{ schema::structs::NetworkListener, - types::{id::Id, ipmask::IpAddrOrMask}, + types::{id::ObjectId, ipmask::IpAddrOrMask}, }; use serde::{Deserialize, Serialize}; use std::{fmt::Display, net::SocketAddr, sync::Arc}; @@ -29,7 +29,7 @@ pub struct Listeners { #[derive(Debug, Default)] pub struct Listener { - pub registry_id: Id, + pub registry_id: ObjectId, pub id: String, pub protocol: ServerProtocol, pub listeners: Vec, diff --git a/crates/common/src/config/smtp/mod.rs b/crates/common/src/config/smtp/mod.rs index 6d1fd512..7d98b069 100644 --- a/crates/common/src/config/smtp/mod.rs +++ b/crates/common/src/config/smtp/mod.rs @@ -15,7 +15,7 @@ use self::{ session::SessionConfig, }; use crate::expr::Expression; -use registry::{schema::structs::Rate, types::id::Id}; +use registry::{schema::structs::Rate, types::id::ObjectId}; use store::registry::bootstrap::Bootstrap; #[derive(Clone)] @@ -30,7 +30,7 @@ pub struct SmtpConfig { #[derive(Debug, Default, Clone)] //#[cfg_attr(feature = "test_mode", derive(PartialEq, Eq))] pub struct QueueRateLimiter { - pub id: Id, + pub id: ObjectId, pub expr: Expression, pub keys: u16, pub rate: Rate, diff --git a/crates/common/src/config/smtp/queue.rs b/crates/common/src/config/smtp/queue.rs index 0d448ee0..978b798b 100644 --- a/crates/common/src/config/smtp/queue.rs +++ b/crates/common/src/config/smtp/queue.rs @@ -170,7 +170,7 @@ pub struct QueueQuotas { #[derive(Clone)] pub struct QueueQuota { - pub id: Id, + pub id: ObjectId, pub expr: Expression, pub keys: u16, pub size: Option, @@ -233,7 +233,7 @@ impl QueueConfig { let mut queue_id_to_name = AHashMap::new(); for obj in bp.list_infallible::().await { if let Some(queue_name) = QueueName::new(&obj.object.name) { - queue_id_to_name.insert(obj.id, queue_name); + queue_id_to_name.insert(obj.id.id(), queue_name); queue.virtual_queues.insert( queue_name, VirtualQueue { @@ -245,7 +245,8 @@ impl QueueConfig { // Parse queue strategies for obj in bp.list_infallible::().await { - let virtual_queue = if let Some(name) = queue_id_to_name.get(&obj.object.queue_id) { + let virtual_queue = if let Some(name) = queue_id_to_name.get(&obj.object.queue_id.id()) + { *name } else { bp.build_error( diff --git a/crates/common/src/config/smtp/session.rs b/crates/common/src/config/smtp/session.rs index 301dee18..c0806269 100644 --- a/crates/common/src/config/smtp/session.rs +++ b/crates/common/src/config/smtp/session.rs @@ -127,7 +127,7 @@ pub struct Data { #[derive(Clone)] pub struct Milter { pub enable: IfBlock, - pub id: Id, + pub id: ObjectId, pub addrs: Vec, pub hostname: String, pub port: u16, @@ -153,7 +153,7 @@ pub enum MilterVersion { #[derive(Clone)] pub struct MTAHook { pub enable: IfBlock, - pub id: Id, + pub id: ObjectId, pub url: String, pub timeout: Duration, pub headers: HeaderMap, diff --git a/crates/common/src/config/telemetry.rs b/crates/common/src/config/telemetry.rs index 872fd18b..47e00399 100644 --- a/crates/common/src/config/telemetry.rs +++ b/crates/common/src/config/telemetry.rs @@ -372,7 +372,7 @@ impl Tracers { // Create tracer let mut tracer = TelemetrySubscriber { - id: format!("t_{id}"), + id: format!("t_{}", id.id()), interests: Default::default(), lossy, typ, @@ -470,7 +470,7 @@ impl Tracers { // Build tracer let mut tracer = TelemetrySubscriber { - id: format!("w_{id}"), + id: format!("w_{}", id.id()), interests: Default::default(), lossy: hook.lossy, typ: TelemetrySubscriberType::Webhook(WebhookTracer { diff --git a/crates/common/src/enterprise/alerts.rs b/crates/common/src/enterprise/alerts.rs index de3d86fd..c6974950 100644 --- a/crates/common/src/enterprise/alerts.rs +++ b/crates/common/src/enterprise/alerts.rs @@ -91,7 +91,7 @@ impl Server { AlertMethod::Event { message } => { trc::event!( Telemetry(TelemetryEvent::Alert), - Id = alert.id.to_string(), + Id = alert.id.id(), Details = message.as_ref().map(|m| m.build()) ); diff --git a/crates/common/src/enterprise/config.rs b/crates/common/src/enterprise/config.rs index b0218684..8cacd9e2 100644 --- a/crates/common/src/enterprise/config.rs +++ b/crates/common/src/enterprise/config.rs @@ -14,19 +14,15 @@ use super::{ }; use crate::{enterprise::llm::ApiType, expr::if_block::BootstrapExprExt}; use ahash::AHashMap; -use registry::{ - schema::{ - enums::AiModelType, - prelude::{Object, Property}, - structs::{ - self, AiModel, Alert, CalendarAlarm, CalendarScheduling, DataRetention, SpamLlm, - }, - }, - types::id::Id, +use registry::schema::{ + enums::AiModelType, + prelude::{Object, Property}, + structs::{self, AiModel, Alert, CalendarAlarm, CalendarScheduling, DataRetention, SpamLlm}, }; use std::sync::Arc; use store::registry::bootstrap::Bootstrap; use trc::MetricType; +use types::id::Id; use utils::template::Template; impl Enterprise { @@ -84,11 +80,7 @@ impl Enterprise { // Update the license if a new one was obtained if let Some(license) = update_license { enterprise.license_key = Some(license); - if let Err(err) = bp - .registry - .update(Object::Enterprise.singleton(), &enterprise) - .await - { + if let Err(err) = bp.registry.update(Id::singleton(), &enterprise).await { trc::error!( err.caused_by(trc::location!()) .details("Failed to update license key") @@ -145,7 +137,7 @@ impl Enterprise { default_temperature: api.temperature, }); ai_apis.insert(api.id.clone(), api.clone()); - ai_apis_ids.insert(id, api); + ai_apis_ids.insert(id.id(), api); } // Build the enterprise configuration @@ -237,14 +229,14 @@ impl Enterprise { impl SpamFilterLlmConfig { pub async fn parse( bp: &mut Bootstrap, - models: &AHashMap>, + models: &AHashMap>, ) -> Option { match bp.setting_infallible::().await { SpamLlm::Enable(llm) => { - let Some(model) = models.get(&llm.model).cloned() else { + let Some(model) = models.get(&llm.model_id.id()).cloned() else { bp.build_error( Object::SpamLlm.singleton(), - format!("Model {:?} not found in AI API configuration", llm.model), + format!("Model {:?} not found in AI API configuration", llm.model_id), ); return None; }; diff --git a/crates/common/src/enterprise/mod.rs b/crates/common/src/enterprise/mod.rs index 6bcc1399..c7953050 100644 --- a/crates/common/src/enterprise/mod.rs +++ b/crates/common/src/enterprise/mod.rs @@ -24,7 +24,7 @@ use llm::AiApiConfig; use mail_parser::DateTime; use registry::{ schema::structs::{Domain, Tenant}, - types::id::Id, + types::id::ObjectId, }; use std::{sync::Arc, time::Duration}; use trc::{AddContext, MetricType}; @@ -61,7 +61,7 @@ pub struct SpamFilterLlmConfig { #[derive(Clone, Debug)] pub struct MetricAlert { - pub id: Id, + pub id: ObjectId, pub condition: Expression, pub method: Vec, } diff --git a/crates/common/src/expr/eval.rs b/crates/common/src/expr/eval.rs index f5f5969c..dab093e3 100644 --- a/crates/common/src/expr/eval.rs +++ b/crates/common/src/expr/eval.rs @@ -15,7 +15,7 @@ use compact_str::{CompactString, ToCompactString, format_compact}; use hyper::StatusCode; use registry::{ schema::prelude::Property, - types::{EnumType, id::Id}, + types::{EnumType, id::ObjectId}, }; use std::{cmp::Ordering, fmt::Display}; use trc::{Collector, EvalEvent}; @@ -91,7 +91,7 @@ impl Server { &'x self, expr: &'x Expression, resolver: &'x V, - obj_id: Id, + obj_id: ObjectId, property: Property, session_id: u64, ) -> Option { diff --git a/crates/common/src/expr/if_block.rs b/crates/common/src/expr/if_block.rs index a88c7dd3..eb75bd9b 100644 --- a/crates/common/src/expr/if_block.rs +++ b/crates/common/src/expr/if_block.rs @@ -16,7 +16,7 @@ use registry::{ prelude::{ExpressionContext, Property}, structs, }, - types::id::Id, + types::id::ObjectId, }; use store::registry::bootstrap::Bootstrap; @@ -28,14 +28,14 @@ pub struct IfThen { #[derive(Debug, Clone, PartialEq, Eq)] pub struct IfBlock { - pub id: Id, + pub id: ObjectId, pub property: Property, pub if_then: Box<[IfThen]>, pub default: Expression, } impl IfBlock { - pub fn new_default(id: Id, expr_ctx: ExpressionContext<'_>) -> Self { + pub fn new_default(id: ObjectId, expr_ctx: ExpressionContext<'_>) -> Self { let token_map = TokenMap::default(); if let Some(default) = &expr_ctx.default { @@ -57,7 +57,7 @@ impl IfBlock { } } - pub fn empty(id: Id, property: Property) -> Self { + pub fn empty(id: ObjectId, property: Property) -> Self { Self { id, property, @@ -82,18 +82,18 @@ impl Expression { } pub(crate) trait BootstrapExprExt { - fn compile_expr(&mut self, id: Id, expr_ctx: &ExpressionContext<'_>) -> IfBlock; - fn compile_default_expr(&mut self, id: Id, expr_ctx: &ExpressionContext<'_>) -> IfBlock; + fn compile_expr(&mut self, id: ObjectId, expr_ctx: &ExpressionContext<'_>) -> IfBlock; + fn compile_default_expr(&mut self, id: ObjectId, expr_ctx: &ExpressionContext<'_>) -> IfBlock; fn try_compile_expr( &mut self, - id: Id, + id: ObjectId, expr_ctx: &ExpressionContext<'_>, expr: &structs::Expression, ) -> Option; } impl BootstrapExprExt for Bootstrap { - fn compile_expr(&mut self, id: Id, expr_ctx: &ExpressionContext<'_>) -> IfBlock { + fn compile_expr(&mut self, id: ObjectId, expr_ctx: &ExpressionContext<'_>) -> IfBlock { if expr_ctx.expr.else_.is_empty() && expr_ctx.expr.match_.is_empty() { return IfBlock::empty(id, expr_ctx.property); } @@ -105,7 +105,7 @@ impl BootstrapExprExt for Bootstrap { } } - fn compile_default_expr(&mut self, id: Id, expr_ctx: &ExpressionContext<'_>) -> IfBlock { + fn compile_default_expr(&mut self, id: ObjectId, expr_ctx: &ExpressionContext<'_>) -> IfBlock { if let Some(default) = &expr_ctx.default { self.try_compile_expr(id, expr_ctx, default) .expect("Valid default expression") @@ -116,7 +116,7 @@ impl BootstrapExprExt for Bootstrap { fn try_compile_expr( &mut self, - id: Id, + id: ObjectId, expr_ctx: &ExpressionContext<'_>, expr: &structs::Expression, ) -> Option { @@ -212,7 +212,7 @@ impl BootstrapExprExt for Bootstrap { } impl IfBlock { - pub fn into_default(self, id: Id, property: Property) -> IfBlock { + pub fn into_default(self, id: ObjectId, property: Property) -> IfBlock { IfBlock { id, property, diff --git a/crates/common/src/ipc.rs b/crates/common/src/ipc.rs index 6c6d2129..5d6ba4fe 100644 --- a/crates/common/src/ipc.rs +++ b/crates/common/src/ipc.rs @@ -15,7 +15,7 @@ use mail_auth::{ mta_sts::TlsRpt, report::{Record, tlsrpt::FailureDetails}, }; -use registry::{schema::prelude::Object, types::id::Id}; +use registry::{schema::prelude::Object, types::id::ObjectId}; use std::{ sync::{ Arc, @@ -104,8 +104,8 @@ pub enum BroadcastEvent { #[derive(Debug)] pub enum RegistryChange { - Insert(Id), - Delete(Id), + Insert(ObjectId), + Delete(ObjectId), Reload(Object), } diff --git a/crates/common/src/network/security.rs b/crates/common/src/network/security.rs index 42261aea..4e6334e7 100644 --- a/crates/common/src/network/security.rs +++ b/crates/common/src/network/security.rs @@ -13,9 +13,10 @@ use ahash::AHashSet; use registry::{ schema::{ enums::BlockReason, + prelude::Object, structs::{self, AllowedIp, BlockedIp, Rate}, }, - types::{datetime::UTCDateTime, ipmask::IpAddrOrMask}, + types::{datetime::UTCDateTime, id::ObjectId, ipmask::IpAddrOrMask}, }; use std::{fmt::Debug, net::IpAddr}; use store::{registry::bootstrap::Bootstrap, write::now}; @@ -251,8 +252,10 @@ impl Server { .caused_by(trc::location!())?; // Increment version - self.cluster_broadcast(BroadcastEvent::RegistryChange(RegistryChange::Insert(id))) - .await; + self.cluster_broadcast(BroadcastEvent::RegistryChange(RegistryChange::Insert( + Object::BlockedIp.id(id.id()), + ))) + .await; Ok(()) } diff --git a/crates/http/src/auth/oauth/registration.rs b/crates/http/src/auth/oauth/registration.rs index 250f73f9..97508760 100644 --- a/crates/http/src/auth/oauth/registration.rs +++ b/crates/http/src/auth/oauth/registration.rs @@ -29,6 +29,7 @@ use store::{ registry::RegistryQuery, }; use trc::{AddContext, AuthEvent}; +use types::id::Id; pub trait ClientRegistrationHandler: Sync + Send { fn handle_oauth_registration_request( @@ -85,7 +86,7 @@ impl ClientRegistrationHandler for Server { created_at: UTCDateTime::now(), description: request.client_name.clone(), contacts: request.contacts.clone(), - member_tenant_id: tenant_id.map(|id| Object::Tenant.id(id as u64)), + member_tenant_id: tenant_id.map(|id| Id::new(id as u64)), redirect_uris: request.redirect_uris.clone(), logo: request.logo_uri.clone(), ..Default::default() diff --git a/crates/jmap-proto/Cargo.toml b/crates/jmap-proto/Cargo.toml index 2b475452..70e44aca 100644 --- a/crates/jmap-proto/Cargo.toml +++ b/crates/jmap-proto/Cargo.toml @@ -7,6 +7,7 @@ edition = "2024" utils = { path = "../utils" } types = { path = "../types" } trc = { path = "../trc" } +registry = { path = "../registry" } jmap-tools = { version = "0.1" } calcard = { version = "0.3" } mail-parser = { version = "0.11", features = ["full_encoding", "rkyv"] } diff --git a/crates/jmap-proto/src/object/mod.rs b/crates/jmap-proto/src/object/mod.rs index ba3ab3d2..938fe1d2 100644 --- a/crates/jmap-proto/src/object/mod.rs +++ b/crates/jmap-proto/src/object/mod.rs @@ -25,6 +25,7 @@ pub mod participant_identity; pub mod principal; pub mod push_subscription; pub mod quota; +pub mod registry; pub mod search_snippet; pub mod share_notification; pub mod sieve; diff --git a/crates/jmap-proto/src/object/registry.rs b/crates/jmap-proto/src/object/registry.rs new file mode 100644 index 00000000..e7643238 --- /dev/null +++ b/crates/jmap-proto/src/object/registry.rs @@ -0,0 +1,173 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +use crate::{ + object::{AnyId, JmapObject, JmapObjectId, MaybeReference, parse_ref}, + request::deserialize::DeserializeArguments, +}; +use jmap_tools::{Element, Key}; +use registry::{ + jmap::RegistryValue, + schema::prelude::{Object, Property}, +}; +use std::borrow::Cow; +use types::{blob::BlobId, id::Id}; + +#[derive(Debug)] +pub struct Registry; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum RegistryFilter { + Type(Object), + Text(String), + Id(Vec), + Property(Property), + _T(String), +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum RegistryComparator { + Id, + Property(Property), + _T(String), +} + +impl JmapObject for Registry { + type Property = Property; + + type Element = RegistryValue; + + type Id = Id; + + type Filter = RegistryFilter; + + type Comparator = RegistryComparator; + + type GetArguments = (); + + type SetArguments<'de> = (); + + type QueryArguments = (); + + type CopyArguments = (); + + type ParseArguments = (); + + const ID_PROPERTY: Self::Property = Property::Id; +} + +impl JmapObjectId for Property { + fn as_id(&self) -> Option { + None + } + + fn as_any_id(&self) -> Option { + None + } + + fn as_id_ref(&self) -> Option<&str> { + None + } + + fn try_set_id(&mut self, _: super::AnyId) -> bool { + false + } +} + +impl JmapObjectId for RegistryValue { + fn as_id(&self) -> Option { + if let RegistryValue::Id(id) = self { + Some(*id) + } else { + None + } + } + + fn as_any_id(&self) -> Option { + match self { + RegistryValue::Id(id) => Some(AnyId::Id(*id)), + RegistryValue::BlobId(id) => Some(AnyId::BlobId(id.clone())), + _ => None, + } + } + + fn as_id_ref(&self) -> Option<&str> { + if let RegistryValue::IdReference(r) = self { + Some(r) + } else { + None + } + } + + fn try_set_id(&mut self, new_id: AnyId) -> bool { + match new_id { + AnyId::Id(id) => { + *self = RegistryValue::Id(id); + } + AnyId::BlobId(id) => { + *self = RegistryValue::BlobId(id); + } + } + true + } +} + +impl<'de> DeserializeArguments<'de> for RegistryFilter { + fn deserialize_argument(&mut self, key: &str, map: &mut A) -> Result<(), A::Error> + where + A: serde::de::MapAccess<'de>, + { + hashify::fnc_map!(key.as_bytes(), + b"text" => { + *self = RegistryFilter::Text(map.next_value()?); + }, + b"id" => { + *self = RegistryFilter::Id(map.next_value()?); + }, + _ => { + *self = RegistryFilter::_T(key.to_string()); + let _ = map.next_value::()?; + } + ); + + Ok(()) + } +} + +impl<'de> DeserializeArguments<'de> for RegistryComparator { + fn deserialize_argument(&mut self, key: &str, map: &mut A) -> Result<(), A::Error> + where + A: serde::de::MapAccess<'de>, + { + if key == "property" { + let value = map.next_value::>()?; + hashify::fnc_map!(value.as_bytes(), + b"id" => { + *self = RegistryComparator::Id; + }, + _ => { + *self = RegistryComparator::_T(key.to_string()); + } + ); + } else { + let _ = map.next_value::()?; + } + + Ok(()) + } +} + +impl Default for RegistryFilter { + fn default() -> Self { + RegistryFilter::_T("".to_string()) + } +} + +impl Default for RegistryComparator { + fn default() -> Self { + RegistryComparator::_T("".to_string()) + } +} diff --git a/crates/jmap-proto/src/references/eval.rs b/crates/jmap-proto/src/references/eval.rs index bbc0cb1f..2b486f6e 100644 --- a/crates/jmap-proto/src/references/eval.rs +++ b/crates/jmap-proto/src/references/eval.rs @@ -84,6 +84,9 @@ impl Response<'_> { GetResponseMethod::PrincipalAvailability(response) => { response.eval_jptr(path, &mut results) } + GetResponseMethod::Registry(response) => { + response.eval_jptr(path, &mut results) + } }, ResponseMethod::Changes(response) => match response { ChangesResponseMethod::Email(response) => { diff --git a/crates/jmap-proto/src/references/resolve.rs b/crates/jmap-proto/src/references/resolve.rs index 130afb58..0743163d 100644 --- a/crates/jmap-proto/src/references/resolve.rs +++ b/crates/jmap-proto/src/references/resolve.rs @@ -57,6 +57,7 @@ impl Response<'_> { request.resolve_references(self)? } GetRequestMethod::PrincipalAvailability(_) => (), + GetRequestMethod::Registry(request) => request.resolve_references(self)?, }, RequestMethod::Set(request) => match request { SetRequestMethod::Email(request) => request.resolve_references(self)?, @@ -78,6 +79,7 @@ impl Response<'_> { SetRequestMethod::ParticipantIdentity(request) => { request.resolve_references(self)? } + SetRequestMethod::Registry(request) => request.resolve_references(self)?, }, RequestMethod::Copy(request) => match request { CopyRequestMethod::Email(request) => request.resolve_references(self)?, diff --git a/crates/jmap-proto/src/request/deserialize.rs b/crates/jmap-proto/src/request/deserialize.rs index f4407bee..337786aa 100644 --- a/crates/jmap-proto/src/request/deserialize.rs +++ b/crates/jmap-proto/src/request/deserialize.rs @@ -4,12 +4,11 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use std::{fmt, marker::PhantomData}; - use serde::{ Deserializer, de::{self, MapAccess, Visitor}, }; +use std::{fmt, marker::PhantomData}; pub trait DeserializeArguments<'de> { fn deserialize_argument(&mut self, key: &str, map: &mut A) -> Result<(), A::Error> diff --git a/crates/jmap-proto/src/request/method.rs b/crates/jmap-proto/src/request/method.rs index cf23b24d..fafe1f3a 100644 --- a/crates/jmap-proto/src/request/method.rs +++ b/crates/jmap-proto/src/request/method.rs @@ -4,7 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use std::fmt::Display; +use std::{borrow::Cow, fmt::Display}; +use registry::{schema::prelude::Object, types::EnumType}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct MethodName { @@ -35,6 +36,7 @@ pub enum MethodObject { FileNode, ParticipantIdentity, ShareNotification, + Registry(Object), } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -56,7 +58,7 @@ pub enum MethodFunction { impl Display for MethodName { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(self.as_str()) + f.write_str(self.as_str().as_ref()) } } @@ -72,7 +74,7 @@ impl MethodName { } } - pub fn as_str(&self) -> &'static str { + pub fn as_str(&self) -> Cow<'static, str> { match (self.fnc, self.obj) { (MethodFunction::Get, MethodObject::PushSubscription) => "PushSubscription/get", (MethodFunction::Set, MethodObject::PushSubscription) => "PushSubscription/set", @@ -181,8 +183,11 @@ impl MethodName { (MethodFunction::Set, MethodObject::ParticipantIdentity) => "ParticipantIdentity/set", (MethodFunction::Echo, MethodObject::Core) => "Core/echo", + (method, MethodObject::Registry(obj)) => { + return Cow::Owned(format!("x:{}/{}", obj.as_str(), method.as_str())); + } _ => "error", - } + }.into() } pub fn parse(s: &str) -> Option { @@ -293,7 +298,16 @@ impl MethodName { "Core/echo" => (MethodObject::Core, MethodFunction::Echo), - ).map(|(obj, fnc)| MethodName { obj, fnc }) + ).or_else(|| { + let (obj, fnc) = s.strip_prefix("x:")?.split_once('/')?; + let obj = Object::parse(obj)?; + let fnc = hashify::tiny_map!(fnc.as_bytes(), + "get" => MethodFunction::Get, + "set" => MethodFunction::Set, + "query" => MethodFunction::Query, + )?; + (MethodObject::Registry(obj), fnc).into() + }).map(|(obj, fnc)| MethodName { obj, fnc }) } } @@ -322,10 +336,33 @@ impl Display for MethodObject { MethodObject::CalendarEvent => "CalendarEvent", MethodObject::CalendarEventNotification => "CalendarEventNotification", MethodObject::ShareNotification => "ShareNotification", + MethodObject::Registry(obj) => { + f.write_str("x:")?; + return f.write_str(obj.as_str()); + }, }) } } +impl MethodFunction { + pub fn as_str(&self) -> &'static str { + match self { + MethodFunction::Get => "get", + MethodFunction::Set => "set", + MethodFunction::Changes => "changes", + MethodFunction::Query => "query", + MethodFunction::QueryChanges => "queryChanges", + MethodFunction::Copy => "copy", + MethodFunction::Import => "import", + MethodFunction::Parse => "parse", + MethodFunction::Validate => "validate", + MethodFunction::Lookup => "lookup", + MethodFunction::Upload => "upload", + MethodFunction::Echo => "echo", + MethodFunction::GetAvailability => "getAvailability", + } + } +} impl<'de> serde::Deserialize<'de> for MethodName { fn deserialize(deserializer: D) -> Result @@ -345,6 +382,6 @@ impl serde::Serialize for MethodName { where S: serde::Serializer, { - serializer.serialize_str(self.as_str()) + serializer.serialize_str(self.as_str().as_ref()) } } diff --git a/crates/jmap-proto/src/request/mod.rs b/crates/jmap-proto/src/request/mod.rs index 6193912e..4625784c 100644 --- a/crates/jmap-proto/src/request/mod.rs +++ b/crates/jmap-proto/src/request/mod.rs @@ -34,7 +34,7 @@ use crate::{ contact::ContactCard, email::Email, email_submission::EmailSubmission, file_node::FileNode, identity::Identity, mailbox::Mailbox, participant_identity::ParticipantIdentity, principal::Principal, push_subscription::PushSubscription, quota::Quota, - share_notification::ShareNotification, sieve::Sieve, thread::Thread, + registry::Registry, share_notification::ShareNotification, sieve::Sieve, thread::Thread, vacation_response::VacationResponse, }, request::{capability::CapabilityIds, reference::MaybeIdReference}, @@ -97,6 +97,7 @@ pub enum GetRequestMethod { CalendarEventNotification(GetRequest), ParticipantIdentity(GetRequest), ShareNotification(GetRequest), + Registry(GetRequest), } #[derive(Debug)] @@ -116,6 +117,7 @@ pub enum SetRequestMethod<'x> { CalendarEvent(SetRequest<'x, CalendarEvent>), CalendarEventNotification(SetRequest<'x, CalendarEventNotification>), ParticipantIdentity(SetRequest<'x, ParticipantIdentity>), + Registry(SetRequest<'x, Registry>), } #[derive(Debug)] @@ -139,6 +141,7 @@ pub enum QueryRequestMethod { CalendarEvent(QueryRequest), CalendarEventNotification(QueryRequest), ShareNotification(QueryRequest), + Registry(QueryRequest), } #[derive(Debug)] diff --git a/crates/jmap-proto/src/request/parser.rs b/crates/jmap-proto/src/request/parser.rs index 5ab4d5da..59a508a9 100644 --- a/crates/jmap-proto/src/request/parser.rs +++ b/crates/jmap-proto/src/request/parser.rs @@ -248,6 +248,13 @@ impl<'de> Visitor<'de> for CallVisitor { return Err(de::Error::invalid_length(1, &self)); } }, + (MethodFunction::Get, MethodObject::Registry(_)) => match seq.next_element() { + Ok(Some(value)) => RequestMethod::Get(GetRequestMethod::Registry(value)), + Err(err) => RequestMethod::invalid(err), + Ok(None) => { + return Err(de::Error::invalid_length(1, &self)); + } + }, (MethodFunction::Set, MethodObject::Email) => match seq.next_element() { Ok(Some(value)) => RequestMethod::Set(SetRequestMethod::Email(value)), Err(err) => RequestMethod::invalid(err), @@ -357,6 +364,13 @@ impl<'de> Visitor<'de> for CallVisitor { return Err(de::Error::invalid_length(1, &self)); } }, + (MethodFunction::Set, MethodObject::Registry(_)) => match seq.next_element() { + Ok(Some(value)) => RequestMethod::Set(SetRequestMethod::Registry(value)), + Err(err) => RequestMethod::invalid(err), + Ok(None) => { + return Err(de::Error::invalid_length(1, &self)); + } + }, (MethodFunction::Query, MethodObject::Email) => match seq.next_element() { Ok(Some(value)) => RequestMethod::Query(QueryRequestMethod::Email(value)), Err(err) => RequestMethod::invalid(err), @@ -440,6 +454,13 @@ impl<'de> Visitor<'de> for CallVisitor { return Err(de::Error::invalid_length(1, &self)); } }, + (MethodFunction::Query, MethodObject::Registry(_)) => match seq.next_element() { + Ok(Some(value)) => RequestMethod::Query(QueryRequestMethod::Registry(value)), + Err(err) => RequestMethod::invalid(err), + Ok(None) => { + return Err(de::Error::invalid_length(1, &self)); + } + }, (MethodFunction::QueryChanges, MethodObject::Email) => match seq.next_element() { Ok(Some(value)) => { RequestMethod::QueryChanges(QueryChangesRequestMethod::Email(value)) diff --git a/crates/jmap-proto/src/response/mod.rs b/crates/jmap-proto/src/response/mod.rs index 06b14ea1..c0c85ce2 100644 --- a/crates/jmap-proto/src/response/mod.rs +++ b/crates/jmap-proto/src/response/mod.rs @@ -44,6 +44,7 @@ use crate::{ principal::Principal, push_subscription::PushSubscription, quota::Quota, + registry::Registry, share_notification::ShareNotification, sieve::Sieve, thread::Thread, @@ -96,6 +97,7 @@ pub enum GetResponseMethod { CalendarEventNotification(CalendarEventNotificationGetResponse), ParticipantIdentity(GetResponse), ShareNotification(GetResponse), + Registry(GetResponse), } #[derive(Debug, serde::Serialize)] @@ -116,6 +118,7 @@ pub enum SetResponseMethod { CalendarEvent(SetResponse), CalendarEventNotification(SetResponse), ParticipantIdentity(SetResponse), + Registry(SetResponse), } #[derive(Debug, serde::Serialize)] @@ -295,6 +298,12 @@ impl<'x> From> for ResponseMethod<'x> { } } +impl<'x> From> for ResponseMethod<'x> { + fn from(value: GetResponse) -> Self { + ResponseMethod::Get(GetResponseMethod::Registry(value)) + } +} + impl<'x> From> for ResponseMethod<'x> { fn from(value: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::Email(value)) @@ -349,6 +358,12 @@ impl<'x> From> for ResponseMethod<'x> { } } +impl<'x> From> for ResponseMethod<'x> { + fn from(value: SetResponse) -> Self { + ResponseMethod::Set(SetResponseMethod::Registry(value)) + } +} + impl<'x> From> for ResponseMethod<'x> { fn from(value: ChangesResponse) -> Self { ResponseMethod::Changes(ChangesResponseMethod::Email(value)) diff --git a/crates/jmap/src/api/auth.rs b/crates/jmap/src/api/auth.rs index 5f587165..8c750320 100644 --- a/crates/jmap/src/api/auth.rs +++ b/crates/jmap/src/api/auth.rs @@ -5,11 +5,11 @@ */ use common::auth::AccessToken; -use registry::schema::enums::Permission; use jmap_proto::request::{ CopyRequestMethod, GetRequestMethod, ParseRequestMethod, QueryChangesRequestMethod, QueryRequestMethod, RequestMethod, SetRequestMethod, method::MethodObject, }; +use registry::schema::enums::Permission; use types::{collection::Collection, id::Id}; pub trait JmapAuthorization { @@ -80,6 +80,10 @@ impl JmapAuthorization for AccessToken { } GetRequestMethod::ParticipantIdentity(_) => Permission::JmapParticipantIdentityGet, GetRequestMethod::ShareNotification(_) => Permission::JmapShareNotificationGet, + GetRequestMethod::Registry(request) => { + let todo = "map registry objects to permissions"; + Permission::JmapEmailGet + } }, RequestMethod::Set(m) => match &m { SetRequestMethod::Email(_) => Permission::JmapEmailSet, @@ -99,6 +103,10 @@ impl JmapAuthorization for AccessToken { Permission::JmapCalendarEventNotificationSet } SetRequestMethod::ParticipantIdentity(_) => Permission::JmapParticipantIdentitySet, + SetRequestMethod::Registry(other) => { + let todo = "map registry objects to permissions"; + Permission::JmapEmailSet + } }, RequestMethod::Changes(_) => match object { MethodObject::Email => Permission::JmapEmailChanges, @@ -123,7 +131,8 @@ impl JmapAuthorization for AccessToken { | MethodObject::SearchSnippet | MethodObject::VacationResponse | MethodObject::SieveScript - | MethodObject::AddressBook => Permission::JmapEmailChanges, + | MethodObject::AddressBook + | MethodObject::Registry(_) => Permission::JmapEmailChanges, }, RequestMethod::Copy(m) => match &m { CopyRequestMethod::Email(_) => Permission::JmapEmailCopy, @@ -174,6 +183,10 @@ impl JmapAuthorization for AccessToken { Permission::JmapCalendarEventNotificationQuery } QueryRequestMethod::ShareNotification(_) => Permission::JmapShareNotificationQuery, + QueryRequestMethod::Registry(other) => { + let todo = "map registry objects to permissions"; + Permission::JmapShareNotificationQuery + } }, RequestMethod::SearchSnippet(_) => Permission::JmapSearchSnippet, RequestMethod::ValidateScript(_) => Permission::JmapSieveScriptValidate, diff --git a/crates/jmap/src/api/request.rs b/crates/jmap/src/api/request.rs index 8b5f93ea..a6894e09 100644 --- a/crates/jmap/src/api/request.rs +++ b/crates/jmap/src/api/request.rs @@ -33,6 +33,7 @@ use crate::{ principal::{availability::PrincipalGetAvailability, get::PrincipalGet, query::PrincipalQuery}, push::{get::PushSubscriptionFetch, set::PushSubscriptionSet}, quota::{get::QuotaGet, query::QuotaQuery}, + registry::{get::RegistryGet, query::RegistryQuery, set::RegistrySet}, share_notification::{ get::ShareNotificationGet, query::ShareNotificationQuery, set::ShareNotificationSet, }, @@ -165,6 +166,9 @@ impl RequestHandler for Server { set_response.update_created_ids(&mut response); } SetResponseMethod::CalendarEventNotification(_) => {} + SetResponseMethod::Registry(set_response) => { + set_response.update_created_ids(&mut response); + } } } ResponseMethod::ImportEmail(import_response) => { @@ -343,6 +347,12 @@ impl RequestHandler for Server { self.share_notification_get(req).await?.into() } + GetRequestMethod::Registry(mut req) => { + set_account_id_if_missing(&mut req.account_id, access_token); + access_token.assert_is_member(req.account_id)?; + + self.registry_get(req, access_token).await?.into() + } }, RequestMethod::Query(req) => match req { QueryRequestMethod::Email(mut req) => { @@ -410,6 +420,12 @@ impl RequestHandler for Server { self.share_notification_query(req).await?.into() } + QueryRequestMethod::Registry(mut req) => { + set_account_id_if_missing(&mut req.account_id, access_token); + access_token.assert_is_member(req.account_id)?; + + self.registry_query(req, access_token).await?.into() + } }, RequestMethod::Set(req) => match req { SetRequestMethod::Email(mut req) => { @@ -512,6 +528,12 @@ impl RequestHandler for Server { self.participant_identity_set(req).await?.into() } + SetRequestMethod::Registry(mut req) => { + set_account_id_if_missing(&mut req.account_id, access_token); + access_token.assert_is_member(req.account_id)?; + + self.registry_set(req, access_token).await?.into() + } }, RequestMethod::Changes(mut req) => { set_account_id_if_missing(&mut req.account_id, access_token); diff --git a/crates/jmap/src/changes/get.rs b/crates/jmap/src/changes/get.rs index 3cdf9617..6ad4808c 100644 --- a/crates/jmap/src/changes/get.rs +++ b/crates/jmap/src/changes/get.rs @@ -329,7 +329,8 @@ impl IntermediateChangesResponse { | MethodObject::VacationResponse | MethodObject::SieveScript | MethodObject::Principal - | MethodObject::Quota => unreachable!(), + | MethodObject::Quota + | MethodObject::Registry(_) => unreachable!(), }) } } diff --git a/crates/jmap/src/lib.rs b/crates/jmap/src/lib.rs index 441a1381..62fde961 100644 --- a/crates/jmap/src/lib.rs +++ b/crates/jmap/src/lib.rs @@ -22,6 +22,7 @@ pub mod participant_identity; pub mod principal; pub mod push; pub mod quota; +pub mod registry; pub mod share_notification; pub mod sieve; pub mod submission; diff --git a/crates/jmap/src/registry/get.rs b/crates/jmap/src/registry/get.rs new file mode 100644 index 00000000..18f3207f --- /dev/null +++ b/crates/jmap/src/registry/get.rs @@ -0,0 +1,29 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +use common::{Server, auth::AccessToken}; +use jmap_proto::{ + method::get::{GetRequest, GetResponse}, + object::registry::Registry, +}; + +pub trait RegistryGet: Sync + Send { + fn registry_get( + &self, + request: GetRequest, + access_token: &AccessToken, + ) -> impl Future>> + Send; +} + +impl RegistryGet for Server { + async fn registry_get( + &self, + mut request: GetRequest, + access_token: &AccessToken, + ) -> trc::Result> { + todo!() + } +} diff --git a/crates/jmap/src/registry/mod.rs b/crates/jmap/src/registry/mod.rs new file mode 100644 index 00000000..c036acc9 --- /dev/null +++ b/crates/jmap/src/registry/mod.rs @@ -0,0 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +pub mod get; +pub mod query; +pub mod set; diff --git a/crates/jmap/src/registry/query.rs b/crates/jmap/src/registry/query.rs new file mode 100644 index 00000000..b7582a45 --- /dev/null +++ b/crates/jmap/src/registry/query.rs @@ -0,0 +1,29 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +use common::{Server, auth::AccessToken}; +use jmap_proto::{ + method::query::{QueryRequest, QueryResponse}, + object::registry::Registry, +}; + +pub trait RegistryQuery: Sync + Send { + fn registry_query( + &self, + request: QueryRequest, + access_token: &AccessToken, + ) -> impl Future> + Send; +} + +impl RegistryQuery for Server { + async fn registry_query( + &self, + mut request: QueryRequest, + access_token: &AccessToken, + ) -> trc::Result { + todo!() + } +} diff --git a/crates/jmap/src/registry/set.rs b/crates/jmap/src/registry/set.rs new file mode 100644 index 00000000..a8f0fa3b --- /dev/null +++ b/crates/jmap/src/registry/set.rs @@ -0,0 +1,29 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +use common::{Server, auth::AccessToken}; +use jmap_proto::{ + method::set::{SetRequest, SetResponse}, + object::registry::Registry, +}; + +pub trait RegistrySet: Sync + Send { + fn registry_set( + &self, + request: SetRequest<'_, Registry>, + access_token: &AccessToken, + ) -> impl Future>> + Send; +} + +impl RegistrySet for Server { + async fn registry_set( + &self, + mut request: SetRequest<'_, Registry>, + access_token: &AccessToken, + ) -> trc::Result> { + todo!() + } +} diff --git a/crates/registry/Cargo.toml b/crates/registry/Cargo.toml index 4ab41838..379e4ef4 100644 --- a/crates/registry/Cargo.toml +++ b/crates/registry/Cargo.toml @@ -11,6 +11,7 @@ serde = { version = "1.0", features = ["derive"]} serde_json = "1.0" hashify = "0.2.7" ahash = { version = "0.8" } +jmap-tools = { version = "0.1" } [features] test_mode = [] diff --git a/crates/registry/src/jmap.rs b/crates/registry/src/jmap.rs new file mode 100644 index 00000000..0c58a3a7 --- /dev/null +++ b/crates/registry/src/jmap.rs @@ -0,0 +1,538 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +use crate::{ + schema::prelude::Property, + types::{EnumType, error::PatchError}, +}; +use jmap_tools::{JsonPointer, JsonPointerItem, Key, Value}; +use std::{borrow::Cow, fmt::Debug, str::FromStr}; +use types::{blob::BlobId, id::Id}; +use utils::map::vec_map::VecMap; + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum RegistryValue { + Id(Id), + BlobId(BlobId), + IdReference(String), +} + +#[derive(Debug, Clone)] +pub struct JsonPointerPatch<'x> { + ptr: &'x JsonPointer, + pos: usize, +} + +pub trait RegistryJsonPatch: Debug + Default { + fn patch( + &mut self, + pointer: JsonPointerPatch<'_>, + value: Value<'_, Property, RegistryValue>, + ) -> Result<(), PatchError>; +} +pub trait RegistryJsonPropertyPatch: Debug + Default { + fn patch_property( + &mut self, + pointer: JsonPointerPatch<'_>, + value: Value<'_, Property, RegistryValue>, + ) -> Result<(), PatchError>; +} + +pub trait RegistryJsonEnumPatch: Debug { + fn patch( + &mut self, + pointer: JsonPointerPatch<'_>, + value: Value<'_, Property, RegistryValue>, + ) -> Result<(), PatchError>; +} + +impl<'x> JsonPointerPatch<'x> { + pub fn new(ptr: &'x JsonPointer) -> Self { + Self { ptr, pos: 0 } + } + + #[allow(clippy::should_implement_trait)] + pub fn next(&mut self) -> Option<&JsonPointerItem> { + self.ptr.as_slice().get(self.pos).inspect(|_| self.pos += 1) + } + + pub fn next_property(&mut self) -> Option { + self.next().and_then(|item| { + if let JsonPointerItem::Key(Key::Property(prop)) = item { + Some(*prop) + } else { + None + } + }) + } + + pub fn peek(&self) -> Option<&JsonPointerItem> { + self.ptr.as_slice().get(self.pos) + } + + pub fn path(&self) -> String { + self.ptr.to_string() + } + + pub fn has_next(&self) -> bool { + self.ptr.as_slice().len() > self.pos + } + + pub fn assert_eof(&self) -> Result<(), PatchError> { + if self.has_next() { + Err(PatchError::new( + JsonPointerPatch::new(self.ptr), + "Invalid JSON Pointer path", + )) + } else { + Ok(()) + } + } +} + +impl jmap_tools::Property for Property { + fn try_parse(_: Option<&Key<'_, Self>>, value: &str) -> Option { + Property::parse(value) + } + + fn to_cow(&self) -> Cow<'static, str> { + self.as_str().into() + } +} + +impl FromStr for Property { + type Err = (); + + fn from_str(s: &str) -> Result { + Property::parse(s).ok_or(()) + } +} + +impl jmap_tools::Element for RegistryValue { + type Property = Property; + + fn try_parse

(key: &Key<'_, Self::Property>, value: &str) -> Option { + if let Key::Property(prop) = key { + match prop { + Property::Id + | Property::MemberGroupIds + | Property::MemberTenantId + | Property::RoleIds + | Property::DnsServerId + | Property::DirectoryId + | Property::DomainId + | Property::AccountId + | Property::DefaultDomainId + | Property::DefaultUserRoleId + | Property::DefaultTenantRoleId + | Property::QueueId + | Property::ModelId + | Property::AcmeProviderId => { + if let Some(reference) = value.strip_prefix('#') { + Some(RegistryValue::IdReference(reference.to_string())) + } else { + Id::from_str(value).map(RegistryValue::Id).ok() + } + } + Property::BlobId => { + if let Some(reference) = value.strip_prefix('#') { + Some(RegistryValue::IdReference(reference.to_string())) + } else { + BlobId::from_str(value).map(RegistryValue::BlobId).ok() + } + } + _ => None, + } + } else { + None + } + } + + fn to_cow(&self) -> Cow<'static, str> { + match self { + RegistryValue::Id(id) => id.to_string().into(), + RegistryValue::BlobId(blob_id) => blob_id.to_string().into(), + RegistryValue::IdReference(r) => format!("#{r}").into(), + } + } +} + +impl From for RegistryValue { + fn from(id: Id) -> Self { + RegistryValue::Id(id) + } +} + +impl From for RegistryValue { + fn from(id: BlobId) -> Self { + RegistryValue::BlobId(id) + } +} + +impl RegistryJsonPatch for Option { + fn patch( + &mut self, + pointer: JsonPointerPatch<'_>, + value: Value<'_, Property, RegistryValue>, + ) -> Result<(), PatchError> { + if let Value::Null = value { + *self = None; + pointer.assert_eof() + } else if let Some(inner) = self { + inner.patch(pointer, value) + } else { + let mut inner = T::default(); + inner.patch(pointer, value).inspect(|_| *self = Some(inner)) + } + } +} + +impl RegistryJsonEnumPatch for Option { + fn patch( + &mut self, + pointer: JsonPointerPatch<'_>, + value: Value<'_, Property, RegistryValue>, + ) -> Result<(), PatchError> { + if let Value::Null = value { + *self = None; + pointer.assert_eof() + } else if let Some(inner) = self { + inner.patch(pointer, value) + } else { + let mut inner = T::default(); + inner.patch(pointer, value).inspect(|_| *self = Some(inner)) + } + } +} + +impl RegistryJsonPatch for String { + fn patch( + &mut self, + pointer: JsonPointerPatch<'_>, + value: Value<'_, Property, RegistryValue>, + ) -> Result<(), PatchError> { + if let Some(value) = value.into_string().filter(|v| !v.is_empty()) { + *self = value.into(); + pointer.assert_eof() + } else { + Err(PatchError::new( + pointer, + "Invalid value for string property (expected non-empty string)", + )) + } + } +} + +impl RegistryJsonPatch for bool { + fn patch( + &mut self, + pointer: JsonPointerPatch<'_>, + value: Value<'_, Property, RegistryValue>, + ) -> Result<(), PatchError> { + if let Some(new_value) = value.as_bool() { + *self = new_value; + pointer.assert_eof() + } else { + Err(PatchError::new( + pointer, + "Invalid value for boolean property (expected true or false)", + )) + } + } +} + +impl RegistryJsonPatch for u64 { + fn patch( + &mut self, + pointer: JsonPointerPatch<'_>, + value: Value<'_, Property, RegistryValue>, + ) -> Result<(), PatchError> { + if let Some(new_value) = value.as_u64() { + *self = new_value; + pointer.assert_eof() + } else { + Err(PatchError::new( + pointer, + "Invalid value for unsigned integer property (expected non-negative integer)", + )) + } + } +} + +impl RegistryJsonPatch for i64 { + fn patch( + &mut self, + pointer: JsonPointerPatch<'_>, + value: Value<'_, Property, RegistryValue>, + ) -> Result<(), PatchError> { + if let Some(new_value) = value.as_i64() { + *self = new_value; + pointer.assert_eof() + } else { + Err(PatchError::new( + pointer, + "Invalid value for signed integer property (expected integer)", + )) + } + } +} + +impl RegistryJsonPatch for f64 { + fn patch( + &mut self, + pointer: JsonPointerPatch<'_>, + value: Value<'_, Property, RegistryValue>, + ) -> Result<(), PatchError> { + if let Some(new_value) = value.as_f64().filter(|v| v.is_finite()) { + *self = new_value; + pointer.assert_eof() + } else { + Err(PatchError::new( + pointer, + "Invalid value for float property (expected finite number)", + )) + } + } +} + +impl RegistryJsonEnumPatch for T { + fn patch( + &mut self, + pointer: JsonPointerPatch<'_>, + value: Value<'_, Property, RegistryValue>, + ) -> Result<(), PatchError> { + if let Some(new_value) = value.as_str().and_then(|v| T::parse(v.as_ref())) { + *self = new_value; + pointer.assert_eof() + } else { + Err(PatchError::new( + pointer, + format!("Invalid value {:?} for enum type {:?}.", value, self), + )) + } + } +} + +impl RegistryJsonPatch for Vec { + fn patch( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: Value<'_, Property, RegistryValue>, + ) -> Result<(), PatchError> { + match (pointer.next(), value) { + (Some(JsonPointerItem::Number(idx)), Value::Null) => { + if *idx < self.len() as u64 { + self.remove(*idx as usize); + return Ok(()); + } + } + (Some(JsonPointerItem::Number(idx)), value) => { + if let Some(inner) = self.get_mut(*idx as usize) { + return inner.patch(pointer, value); + } else if *idx == self.len() as u64 { + let mut inner = T::default(); + return inner.patch(pointer, value).inspect(|_| self.push(inner)); + } + } + (None, Value::Array(items)) => { + self.clear(); + for item in items { + let mut inner = T::default(); + inner.patch(pointer.clone(), item)?; + self.push(inner); + } + return Ok(()); + } + _ => {} + } + + Err(PatchError::new(pointer, "Invalid value for array property")) + } +} + +impl RegistryJsonEnumPatch for Vec { + fn patch( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: Value<'_, Property, RegistryValue>, + ) -> Result<(), PatchError> { + match (pointer.next(), value) { + (Some(JsonPointerItem::Number(idx)), Value::Null) => { + if *idx < self.len() as u64 { + self.remove(*idx as usize); + return Ok(()); + } + } + (Some(JsonPointerItem::Number(idx)), value) => { + if let Some(inner) = self.get_mut(*idx as usize) { + return inner.patch(pointer, value); + } else if *idx == self.len() as u64 { + let mut inner = T::default(); + return inner.patch(pointer, value).inspect(|_| self.push(inner)); + } + } + (None, Value::Array(items)) => { + self.clear(); + for item in items { + let mut inner = T::default(); + inner.patch(pointer.clone(), item)?; + self.push(inner); + } + return Ok(()); + } + _ => {} + } + + Err(PatchError::new(pointer, "Invalid value for array property")) + } +} + +impl RegistryJsonPatch for VecMap { + fn patch( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: Value<'_, Property, RegistryValue>, + ) -> Result<(), PatchError> { + match (pointer.next(), value) { + (Some(JsonPointerItem::Number(idx)), Value::Null) => { + if let Some(key) = K::try_from_integer(*idx) { + self.remove(&key); + return Ok(()); + } + } + (Some(JsonPointerItem::Key(key)), Value::Null) => { + if let Some(key) = K::try_from_string(key.to_string().as_ref()) { + self.remove(&key); + return Ok(()); + } + } + (Some(JsonPointerItem::Key(key)), value) => { + if let Some(key) = K::try_from_string(key.to_string().as_ref()) { + return self.get_mut_or_insert(key).patch(pointer, value); + } + } + (Some(JsonPointerItem::Number(idx)), value) => { + if let Some(key) = K::try_from_integer(*idx) { + return self.get_mut_or_insert(key).patch(pointer, value); + } + } + (None, Value::Object(items)) => { + self.clear(); + for (key, value) in items.into_vec() { + if let Some(key) = K::try_from_string(key.to_string().as_ref()) { + let mut inner = V::default(); + inner.patch(pointer.clone(), value)?; + self.set(key, inner); + } else { + return Err(PatchError::new( + pointer.clone(), + "Invalid key for object property", + )); + } + } + return Ok(()); + } + _ => {} + } + + Err(PatchError::new( + pointer, + "Invalid value for object property", + )) + } +} + +impl RegistryJsonPatch for T { + fn patch( + &mut self, + pointer: JsonPointerPatch<'_>, + value: jmap_tools::Value<'_, Property, crate::jmap::RegistryValue>, + ) -> Result<(), PatchError> { + if pointer.has_next() { + self.patch_property(pointer, value) + } else if let Some(object) = value.into_object() { + let mut ptr = JsonPointer::new(vec![JsonPointerItem::Root]); + for (key, value) in object.into_vec() { + if let Some(property) = key.as_property() { + ptr.as_mut_slice()[0] = JsonPointerItem::Key(Key::Property(*property)); + match self.patch_property(JsonPointerPatch::new(&ptr), value) { + Ok(()) => {} + Err(mut e) => { + if !e.path.is_empty() { + e.path = format!("{}/{}", e.path, property.as_str()); + } else { + e.path = property.as_str().to_string(); + } + return Err(e); + } + } + } else { + return Err(PatchError::new(pointer.clone(), "Invalid key for object")); + } + } + Ok(()) + } else { + Err(PatchError::new(pointer, "Invalid value type for object")) + } + } +} + +trait MapItem: Sized + PartialEq + Eq + Debug { + fn try_from_string(value: &str) -> Option; + fn try_from_integer(value: u64) -> Option; +} + +impl MapItem for String { + fn try_from_string(value: &str) -> Option { + let value = value.trim(); + if !value.is_empty() { + Some(value.to_string()) + } else { + None + } + } + + fn try_from_integer(value: u64) -> Option { + Some(value.to_string()) + } +} + +impl MapItem for u32 { + fn try_from_string(value: &str) -> Option { + value.parse().ok() + } + + fn try_from_integer(value: u64) -> Option { + value.try_into().ok() + } +} + +impl MapItem for T { + fn try_from_string(value: &str) -> Option { + Self::parse(value) + } + + fn try_from_integer(_: u64) -> Option { + None + } +} + +pub fn object_type( + pointer: &JsonPointerPatch<'_>, + value: &Value<'_, Property, RegistryValue>, +) -> Result { + value + .as_object() + .and_then(|obj| obj.get(&jmap_tools::Key::Property(Property::Type))) + .and_then(|v| v.as_str()) + .and_then(|v| T::parse(v.as_ref())) + .ok_or_else(|| { + PatchError::new( + pointer.clone(), + "Missing or invalid '@type' property in object", + ) + }) +} diff --git a/crates/registry/src/lib.rs b/crates/registry/src/lib.rs index 2156a015..75dc5957 100644 --- a/crates/registry/src/lib.rs +++ b/crates/registry/src/lib.rs @@ -4,6 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ +pub mod jmap; pub mod pickle; pub mod schema; pub mod types; diff --git a/crates/registry/src/pickle.rs b/crates/registry/src/pickle.rs index 7b0993f6..461dd9ab 100644 --- a/crates/registry/src/pickle.rs +++ b/crates/registry/src/pickle.rs @@ -122,8 +122,8 @@ impl Pickle for String { } fn unpickle(stream: &mut PickledStream<'_>) -> Option { - let mut len_arr = [0u8; 4]; - len_arr.copy_from_slice(stream.read_bytes(4)?); + let mut len_arr = [0u8; std::mem::size_of::()]; + len_arr.copy_from_slice(stream.read_bytes(std::mem::size_of::())?); let bytes = stream.read_bytes(u32::from_le_bytes(len_arr) as usize)?; String::from_utf8(bytes.to_vec()).ok() } @@ -135,8 +135,8 @@ impl Pickle for T { } fn unpickle(stream: &mut PickledStream<'_>) -> Option { - let mut id_arr = [0u8; 2]; - id_arr.copy_from_slice(stream.read_bytes(2)?); + let mut id_arr = [0u8; std::mem::size_of::()]; + id_arr.copy_from_slice(stream.read_bytes(std::mem::size_of::())?); Self::from_id(u16::from_le_bytes(id_arr)) } } @@ -243,27 +243,3 @@ where Some(map) } } - -impl Pickle for trc::EventType { - fn pickle(&self, out: &mut Vec) { - out.extend_from_slice(&self.to_id().to_le_bytes()); - } - - fn unpickle(stream: &mut PickledStream<'_>) -> Option { - let mut id_arr = [0u8; 2]; - id_arr.copy_from_slice(stream.read_bytes(2)?); - Self::from_id(u16::from_le_bytes(id_arr)) - } -} - -impl Pickle for trc::MetricType { - fn pickle(&self, out: &mut Vec) { - out.extend_from_slice(&self.to_id().to_le_bytes()); - } - - fn unpickle(stream: &mut PickledStream<'_>) -> Option { - let mut id_arr = [0u8; 2]; - id_arr.copy_from_slice(stream.read_bytes(2)?); - Self::from_id(u16::from_le_bytes(id_arr)) - } -} diff --git a/crates/registry/src/schema/mod.rs b/crates/registry/src/schema/mod.rs index faa8256a..9227b023 100644 --- a/crates/registry/src/schema/mod.rs +++ b/crates/registry/src/schema/mod.rs @@ -11,7 +11,8 @@ use crate::{ }, types::EnumType, }; -use std::fmt::Display; +use std::{cmp::Ordering, fmt::Display}; +use trc::TOTAL_EVENT_COUNT; use utils::{ Client, HeaderMap, cron::SimpleCron, @@ -27,6 +28,9 @@ pub mod properties; pub mod properties_impl; #[allow(clippy::large_enum_variant)] pub mod structs; +#[allow(clippy::needless_borrows_for_generic_args)] +#[allow(clippy::len_zero)] +#[allow(clippy::collapsible_if)] #[allow(clippy::derivable_impls)] pub mod structs_impl; @@ -161,3 +165,55 @@ impl From for trc::Level { } } } + +impl EnumType for trc::EventType { + const COUNT: usize = TOTAL_EVENT_COUNT; + + fn parse(s: &str) -> Option { + trc::EventType::parse(s) + } + + fn as_str(&self) -> &'static str { + trc::EventType::as_str(self) + } + + fn from_id(id: u16) -> Option { + trc::EventType::from_id(id) + } + + fn to_id(&self) -> u16 { + trc::EventType::to_id(self) + } +} + +impl EnumType for trc::MetricType { + const COUNT: usize = TOTAL_EVENT_COUNT; + + fn parse(s: &str) -> Option { + trc::MetricType::parse(s) + } + + fn as_str(&self) -> &'static str { + trc::MetricType::as_str(self) + } + + fn from_id(id: u16) -> Option { + trc::MetricType::from_id(id) + } + + fn to_id(&self) -> u16 { + trc::MetricType::to_id(self) + } +} + +impl PartialOrd for Property { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Property { + fn cmp(&self, other: &Self) -> Ordering { + self.to_id().cmp(&other.to_id()) + } +} diff --git a/crates/registry/src/schema/prelude.rs b/crates/registry/src/schema/prelude.rs index 8a5ad16a..6ac05ea2 100644 --- a/crates/registry/src/schema/prelude.rs +++ b/crates/registry/src/schema/prelude.rs @@ -3,7 +3,10 @@ * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ - +pub use crate::jmap::{ + JsonPointerPatch, RegistryJsonEnumPatch, RegistryJsonPatch, RegistryJsonPropertyPatch, + object_type, +}; pub use crate::pickle::Pickle; pub use crate::schema::enums::*; pub use crate::schema::properties::*; @@ -14,13 +17,13 @@ pub use crate::types::ObjectType; pub use crate::types::datetime::UTCDateTime; pub use crate::types::duration::Duration; pub use crate::types::error::*; -pub use crate::types::id::Id; pub use crate::types::index::IndexBuilder; pub use crate::types::ipaddr::IpAddr; pub use crate::types::ipmask::IpAddrOrMask; pub use crate::types::socketaddr::SocketAddr; pub use serde::{Deserialize, Serialize}; pub use std::str::FromStr; +pub use types::id::Id; pub use utils::map::vec_map::VecMap; #[derive(Debug)] diff --git a/crates/registry/src/types/datetime.rs b/crates/registry/src/types/datetime.rs index 9b7131ea..a5a114b0 100644 --- a/crates/registry/src/types/datetime.rs +++ b/crates/registry/src/types/datetime.rs @@ -4,7 +4,11 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use crate::pickle::{Pickle, PickledStream}; +use crate::{ + jmap::{JsonPointerPatch, RegistryJsonPatch}, + pickle::{Pickle, PickledStream}, + types::error::PatchError, +}; use std::{fmt::Display, str::FromStr, time::SystemTime}; #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] @@ -262,6 +266,32 @@ impl From for UTCDateTime { } } +impl RegistryJsonPatch for UTCDateTime { + fn patch( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: jmap_tools::Value<'_, crate::schema::prelude::Property, crate::jmap::RegistryValue>, + ) -> Result<(), PatchError> { + match (value, pointer.next()) { + (jmap_tools::Value::Str(value), None) => { + if let Ok(new_value) = UTCDateTime::from_str(value.as_ref()) { + *self = new_value; + Ok(()) + } else { + Err(PatchError::new( + pointer, + "Failed to parse UTCDateTime from string", + )) + } + } + _ => Err(PatchError::new( + pointer, + "Invalid path for UTCDateTime, expected a string value", + )), + } + } +} + #[cfg(test)] mod tests { use std::str::FromStr; diff --git a/crates/registry/src/types/duration.rs b/crates/registry/src/types/duration.rs index 569be6be..1a9b9baa 100644 --- a/crates/registry/src/types/duration.rs +++ b/crates/registry/src/types/duration.rs @@ -4,7 +4,11 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use crate::pickle::{Pickle, PickledStream}; +use crate::{ + jmap::{JsonPointerPatch, RegistryJsonPatch}, + pickle::{Pickle, PickledStream}, + types::error::PatchError, +}; use std::{fmt::Display, str::FromStr}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -52,7 +56,7 @@ impl serde::Serialize for Duration { where S: serde::Serializer, { - serializer.serialize_str(self.to_string().as_str()) + serializer.serialize_u64(self.0.as_millis() as u64) } } @@ -132,3 +136,23 @@ impl Pickle for Duration { ))) } } + +impl RegistryJsonPatch for Duration { + fn patch( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: jmap_tools::Value<'_, crate::schema::prelude::Property, crate::jmap::RegistryValue>, + ) -> Result<(), PatchError> { + match (value, pointer.next()) { + (jmap_tools::Value::Number(value), None) => { + if let Some(new_value) = value.as_u64().filter(|v| *v > 0) { + *self = Duration::from_millis(new_value); + Ok(()) + } else { + Err(PatchError::new(pointer, "Invalid duration value")) + } + } + _ => Err(PatchError::new(pointer, "Invalid path for Duration")), + } + } +} diff --git a/crates/registry/src/types/error.rs b/crates/registry/src/types/error.rs index 5f3786db..4fce25de 100644 --- a/crates/registry/src/types/error.rs +++ b/crates/registry/src/types/error.rs @@ -5,10 +5,11 @@ */ use crate::{ + jmap::JsonPointerPatch, schema::prelude::{Object, Property}, - types::id::Id, + types::id::ObjectId, }; -use std::fmt::Display; +use std::{borrow::Cow, fmt::Display}; #[derive(Debug, Clone, PartialEq, Eq)] pub enum ValidationError { @@ -23,30 +24,36 @@ pub enum ValidationError { #[derive(Debug, Clone, PartialEq, Eq)] pub enum Error { Validation { - object_id: Id, + object_id: ObjectId, errors: Vec, }, Build { - object_id: Id, + object_id: ObjectId, message: String, }, Internal { - object_id: Option, + object_id: Option, error: trc::Error, }, TypeMismatch { - object_id: Id, + object_id: ObjectId, object_type: Object, expected_type: Object, }, NotFound { - object_id: Id, + object_id: ObjectId, }, } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct PatchError { + pub path: String, + pub message: Cow<'static, str>, +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct Warning { - pub object_id: Id, + pub object_id: ObjectId, pub property: Option, pub message: String, } @@ -89,7 +96,7 @@ impl ValidationError { } impl Warning { - pub fn new(object_id: Id, message: impl Display) -> Self { + pub fn new(object_id: ObjectId, message: impl Display) -> Self { Self { object_id, property: None, @@ -97,7 +104,7 @@ impl Warning { } } - pub fn for_property(object_id: Id, property: Property, message: impl Display) -> Self { + pub fn for_property(object_id: ObjectId, property: Property, message: impl Display) -> Self { Self { object_id, property: Some(property), @@ -146,3 +153,12 @@ impl Display for ValidationError { } } } + +impl PatchError { + pub fn new(path: JsonPointerPatch<'_>, message: impl Into>) -> Self { + Self { + path: path.path(), + message: message.into(), + } + } +} diff --git a/crates/registry/src/types/id.rs b/crates/registry/src/types/id.rs index aab6abe2..6a2afad1 100644 --- a/crates/registry/src/types/id.rs +++ b/crates/registry/src/types/id.rs @@ -5,20 +5,21 @@ */ use crate::{ + jmap::{JsonPointerPatch, RegistryJsonPatch, RegistryValue}, pickle::{Pickle, PickledStream}, schema::prelude::Object, - types::EnumType, + types::{EnumType, error::PatchError}, }; -use std::str::FromStr; -use utils::codec::base32_custom::{BASE32_ALPHABET, BASE32_INVERSE}; +use std::{fmt::Display, str::FromStr}; +use types::{blob::BlobId, id::Id}; #[derive(Debug, PartialEq, Clone, Copy, Eq, Hash)] -pub struct Id { +pub struct ObjectId { object: Object, id: u64, } -impl Id { +impl ObjectId { pub fn new(object: Object, id: impl Into) -> Self { Self { object, @@ -37,151 +38,97 @@ impl Id { pub fn is_valid(&self) -> bool { self.id != u64::MAX } +} - pub fn as_string(&self) -> String { - let mut out = String::with_capacity(14); - encode(self.object.to_id() as u64, &mut out); - out.push(':'); - encode(self.id, &mut out); - out +impl Display for ObjectId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}:{}", self.object.as_str(), Id::new(self.id)) } } impl Object { - pub fn id(&self, id: u64) -> Id { - Id::new(*self, id) + pub fn id(&self, id: u64) -> ObjectId { + ObjectId::new(*self, id) } - pub fn singleton(&self) -> Id { - Id::new(*self, 20080258862541u64) + pub fn singleton(&self) -> ObjectId { + ObjectId::new(*self, 20080258862541u64) } } -impl FromStr for Id { - type Err = (); - - fn from_str(s: &str) -> Result { - match s.split_once(':') { - Some((obj_str, id_str)) => { - let object_id = decode(obj_str).ok_or(())?; - let object = Object::from_id(object_id as u16).ok_or(())?; - let id = decode(id_str).ok_or(())?; - Ok(Id::new(object, id)) - } - None => Err(()), - } - } -} - -fn decode(s: &str) -> Option { - let mut n = 0u64; - - for &ch in s.as_bytes() { - let i = BASE32_INVERSE[ch as usize]; - if i != u8::MAX { - n = (n << 5) | i as u64; - } else { - return None; - } - } - - Some(n) -} - -// From https://github.com/archer884/crockford by J/A -// License: MIT/Apache 2.0 -fn encode(n: u64, out: &mut String) { - match n { - 0 => out.push('a'), - mut n => { - // Used for the initial shift. - const QUAD_SHIFT: usize = 60; - const QUAD_RESET: usize = 4; - - // Used for all subsequent shifts. - const FIVE_SHIFT: usize = 59; - const FIVE_RESET: usize = 5; - - // After we clear the four most significant bits, the four least significant bits will be - // replaced with 0001. We can then know to stop once the four most significant bits are, - // likewise, 0001. - const STOP_BIT: u64 = 1 << QUAD_SHIFT; - - // Start by getting the most significant four bits. We get four here because these would be - // leftovers when starting from the least significant bits. In either case, tag the four least - // significant bits with our stop bit. - match (n >> QUAD_SHIFT) as usize { - // Eat leading zero-bits. This should not be done if the first four bits were non-zero. - // Additionally, we *must* do this in increments of five bits. - 0 => { - n <<= QUAD_RESET; - n |= 1; - n <<= n.leading_zeros() / 5 * 5; - } - - // Write value of first four bytes. - i => { - n <<= QUAD_RESET; - n |= 1; - out.push(char::from(BASE32_ALPHABET[i])); - } - } - - // From now until we reach the stop bit, take the five most significant bits and then shift - // left by five bits. - while n != STOP_BIT { - out.push(char::from(BASE32_ALPHABET[(n >> FIVE_SHIFT) as usize])); - n <<= FIVE_RESET; - } - } - } -} - -impl Default for Id { +impl Default for ObjectId { fn default() -> Self { - Id::new(Object::Account, u64::MAX) - } -} - -impl serde::Serialize for Id { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_str(self.as_string().as_str()) - } -} - -impl<'de> serde::Deserialize<'de> for Id { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - Id::from_str(<&str>::deserialize(deserializer)?) - .map_err(|_| serde::de::Error::custom("invalid Registry ID")) - } -} - -impl std::fmt::Display for Id { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(&self.as_string()) + ObjectId::new(Object::Account, u64::MAX) } } impl Pickle for Id { fn pickle(&self, out: &mut Vec) { - out.extend_from_slice(&self.object.to_id().to_le_bytes()); - out.extend_from_slice(&self.id.to_le_bytes()); + out.extend_from_slice(&self.id().to_le_bytes()); } fn unpickle(data: &mut PickledStream<'_>) -> Option { - let mut arr = [0u8; 2]; - arr.copy_from_slice(data.read_bytes(2)?); - let object = Object::from_id(u16::from_le_bytes(arr))?; - let mut arr = [0u8; 8]; + let mut arr = [0u8; std::mem::size_of::()]; arr.copy_from_slice(data.read_bytes(8)?); let id = u64::from_le_bytes(arr); - Some(Id { object, id }) + Some(Id::new(id)) + } +} + +impl RegistryJsonPatch for Id { + fn patch( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: jmap_tools::Value<'_, crate::schema::prelude::Property, crate::jmap::RegistryValue>, + ) -> Result<(), PatchError> { + match (value, pointer.next()) { + (jmap_tools::Value::Element(RegistryValue::Id(value)), None) => { + *self = value; + Ok(()) + } + (jmap_tools::Value::Str(value), None) => { + if let Ok(new_value) = Id::from_str(value.as_ref()) { + *self = new_value; + Ok(()) + } else { + Err(PatchError::new(pointer, "Failed to parse Id from string")) + } + } + _ => Err(PatchError::new( + pointer, + "Invalid path for Id, expected a string value", + )), + } + } +} + +impl RegistryJsonPatch for BlobId { + fn patch( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: jmap_tools::Value<'_, crate::schema::prelude::Property, crate::jmap::RegistryValue>, + ) -> Result<(), PatchError> { + match (value, pointer.next()) { + (jmap_tools::Value::Element(RegistryValue::BlobId(value)), None) => { + *self = value; + Ok(()) + } + (jmap_tools::Value::Str(value), None) => { + if let Ok(new_value) = BlobId::from_str(value.as_ref()) { + *self = new_value; + Ok(()) + } else { + Err(PatchError::new( + pointer, + "Failed to parse BlobId from string", + )) + } + } + _ => Err(PatchError::new( + pointer, + "Invalid path for BlobId, expected a string value", + )), + } } } diff --git a/crates/registry/src/types/index.rs b/crates/registry/src/types/index.rs index add1c5ac..6246b4aa 100644 --- a/crates/registry/src/types/index.rs +++ b/crates/registry/src/types/index.rs @@ -6,17 +6,44 @@ use crate::{ schema::prelude::{Object, Property}, - types::{id::Id, ipmask::IpAddrOrMask}, + types::ipmask::IpAddrOrMask, }; use ahash::AHashSet; use std::borrow::Cow; +use types::id::Id; -#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)] -pub enum IndexType { - Unique, - Search, - TextSearch, - Global, +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum IndexKey<'x> { + Unique { + property: Property, + value: IndexValue<'x>, + }, + Search { + property: Property, + value: IndexValue<'x>, + }, + TextSearch { + property: Property, + value: IndexValue<'x>, + }, + Global { + property: Property, + value_1: IndexValue<'x>, + value_2: IndexValue<'x>, + }, + ForeignKey { + property: Property, + object: Object, + id: u64, + type_filter: IndexValue<'x>, + tenant_filter: bool, + }, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ObjectFilter<'x> { + pub property: Property, + pub value: IndexValue<'x>, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -25,22 +52,16 @@ pub enum IndexValue<'x> { Bytes(Vec), U64(u64), I64(i64), + U32(u32), U16(u16), None, } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct IndexKey<'x> { - pub property: Property, - pub typ: IndexType, - pub value: IndexValue<'x>, - pub value_composite: IndexValue<'x>, -} - #[derive(Debug, Default)] pub struct IndexBuilder<'x> { pub object: Option, + pub tenant_id: Option, pub keys: AHashSet>, } @@ -52,29 +73,23 @@ impl<'x> IndexBuilder<'x> { } pub fn typ(&mut self, typ: u16) { - self.keys.insert(IndexKey { + self.keys.insert(IndexKey::Search { property: Property::Type, - typ: IndexType::Search, value: IndexValue::U16(typ), - value_composite: IndexValue::None, }); } pub fn unique(&mut self, property: Property, value: impl Into>) { - self.keys.insert(IndexKey { + self.keys.insert(IndexKey::Unique { property, - typ: IndexType::Unique, value: value.into(), - value_composite: IndexValue::None, }); } pub fn search(&mut self, property: Property, value: impl Into>) { - self.keys.insert(IndexKey { + self.keys.insert(IndexKey::Search { property, - typ: IndexType::Search, value: value.into(), - value_composite: IndexValue::None, }); } @@ -87,29 +102,24 @@ impl<'x> IndexBuilder<'x> { .chars() .all(|ch| ch.is_lowercase() || !ch.is_alphabetic()) { - self.keys.insert(IndexKey { + self.keys.insert(IndexKey::TextSearch { property, - typ: IndexType::TextSearch, value: IndexValue::Text(Cow::Borrowed(word)), - value_composite: IndexValue::None, }); } else { - self.keys.insert(IndexKey { + self.keys.insert(IndexKey::TextSearch { property, - typ: IndexType::TextSearch, value: IndexValue::Text(Cow::Owned(word.to_lowercase())), - value_composite: IndexValue::Text(Cow::Borrowed(word)), }); } } } pub fn global(&mut self, property: Property, value: impl Into>) { - self.keys.insert(IndexKey { + self.keys.insert(IndexKey::Global { property, - typ: IndexType::Global, - value: value.into(), - value_composite: IndexValue::None, + value_1: value.into(), + value_2: IndexValue::None, }); } @@ -119,13 +129,31 @@ impl<'x> IndexBuilder<'x> { value: impl Into>, composite: impl Into>, ) { - self.keys.insert(IndexKey { + self.keys.insert(IndexKey::Global { property, - typ: IndexType::Global, - value: value.into(), - value_composite: composite.into(), + value_1: value.into(), + value_2: composite.into(), }); } + + pub fn foreign_key( + &mut self, + property: Property, + object: Object, + id: Option, + type_filter: Option, + tenant_filter: bool, + ) { + if let Some(id) = id { + self.keys.insert(IndexKey::ForeignKey { + property, + object, + id: id.id(), + type_filter: type_filter.map(IndexValue::U16).unwrap_or(IndexValue::None), + tenant_filter, + }); + } + } } impl From for IndexValue<'_> { diff --git a/crates/registry/src/types/ipaddr.rs b/crates/registry/src/types/ipaddr.rs index dba6dd8e..a9161037 100644 --- a/crates/registry/src/types/ipaddr.rs +++ b/crates/registry/src/types/ipaddr.rs @@ -6,7 +6,11 @@ use std::{fmt::Display, net::Ipv4Addr, str::FromStr}; -use crate::pickle::{Pickle, PickledStream}; +use crate::{ + jmap::{JsonPointerPatch, RegistryJsonPatch}, + pickle::{Pickle, PickledStream}, + types::error::PatchError, +}; #[derive(Debug, Clone, Copy, PartialEq)] #[repr(transparent)] @@ -113,3 +117,29 @@ impl Pickle for IpAddr { std::net::IpAddr::unpickle(data).map(IpAddr) } } + +impl RegistryJsonPatch for IpAddr { + fn patch( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: jmap_tools::Value<'_, crate::schema::prelude::Property, crate::jmap::RegistryValue>, + ) -> Result<(), PatchError> { + match (value, pointer.next()) { + (jmap_tools::Value::Str(value), None) => { + if let Ok(new_value) = IpAddr::from_str(value.as_ref()) { + *self = new_value; + Ok(()) + } else { + Err(PatchError::new( + pointer, + "Failed to parse IpAddr from string", + )) + } + } + _ => Err(PatchError::new( + pointer, + "Invalid path for IpAddr, expected a string value", + )), + } + } +} diff --git a/crates/registry/src/types/ipmask.rs b/crates/registry/src/types/ipmask.rs index 19d0b03c..4d6b355e 100644 --- a/crates/registry/src/types/ipmask.rs +++ b/crates/registry/src/types/ipmask.rs @@ -4,7 +4,11 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use crate::pickle::{Pickle, PickledStream}; +use crate::{ + jmap::{JsonPointerPatch, RegistryJsonPatch}, + pickle::{Pickle, PickledStream}, + types::error::PatchError, +}; use std::{ fmt::{Display, Formatter}, net::{IpAddr, Ipv4Addr, Ipv6Addr}, @@ -243,6 +247,32 @@ impl Pickle for IpAddrOrMask { } } +impl RegistryJsonPatch for IpAddrOrMask { + fn patch( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: jmap_tools::Value<'_, crate::schema::prelude::Property, crate::jmap::RegistryValue>, + ) -> Result<(), PatchError> { + match (value, pointer.next()) { + (jmap_tools::Value::Str(value), None) => { + if let Ok(new_value) = IpAddrOrMask::from_str(value.as_ref()) { + *self = new_value; + Ok(()) + } else { + Err(PatchError::new( + pointer, + "Failed to parse IpAddrOrMask from string", + )) + } + } + _ => Err(PatchError::new( + pointer, + "Invalid path for IpAddrOrMask, expected a string value", + )), + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/registry/src/types/mod.rs b/crates/registry/src/types/mod.rs index 7cc9f5af..274fc696 100644 --- a/crates/registry/src/types/mod.rs +++ b/crates/registry/src/types/mod.rs @@ -9,6 +9,7 @@ use crate::{ schema::prelude::Object, types::{error::ValidationError, index::IndexBuilder}, }; +use std::fmt::Debug; pub mod datetime; pub mod duration; @@ -19,7 +20,7 @@ pub mod ipaddr; pub mod ipmask; pub mod socketaddr; -pub trait EnumType: Sized { +pub trait EnumType: Sized + Debug + PartialEq + Eq { const COUNT: usize; fn parse(s: &str) -> Option; diff --git a/crates/registry/src/types/socketaddr.rs b/crates/registry/src/types/socketaddr.rs index c4dab835..87598881 100644 --- a/crates/registry/src/types/socketaddr.rs +++ b/crates/registry/src/types/socketaddr.rs @@ -6,7 +6,11 @@ use std::{fmt::Display, str::FromStr}; -use crate::pickle::{Pickle, PickledStream}; +use crate::{ + jmap::{JsonPointerPatch, RegistryJsonPatch}, + pickle::{Pickle, PickledStream}, + types::error::PatchError, +}; #[derive(Debug, Clone, PartialEq)] pub struct SocketAddr(pub std::net::SocketAddr); @@ -82,3 +86,29 @@ impl Pickle for SocketAddr { Some(SocketAddr(std::net::SocketAddr::new(ip, port))) } } + +impl RegistryJsonPatch for SocketAddr { + fn patch( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: jmap_tools::Value<'_, crate::schema::prelude::Property, crate::jmap::RegistryValue>, + ) -> Result<(), PatchError> { + match (value, pointer.next()) { + (jmap_tools::Value::Str(value), None) => { + if let Ok(new_value) = SocketAddr::from_str(value.as_ref()) { + *self = new_value; + Ok(()) + } else { + Err(PatchError::new( + pointer, + "Failed to parse SocketAddr from string", + )) + } + } + _ => Err(PatchError::new( + pointer, + "Invalid path for SocketAddr, expected a string value", + )), + } + } +} diff --git a/crates/services/src/broadcast/mod.rs b/crates/services/src/broadcast/mod.rs index 5aceac0a..bbe0811f 100644 --- a/crates/services/src/broadcast/mod.rs +++ b/crates/services/src/broadcast/mod.rs @@ -9,7 +9,7 @@ use common::ipc::{ }; use registry::{ schema::prelude::Object, - types::{EnumType, id::Id}, + types::{EnumType, id::ObjectId}, }; use std::{borrow::Borrow, io::Write}; use types::type_state::StateChange; @@ -179,14 +179,20 @@ where let object_id = self.messages.next_leb128().ok_or(())?; let id = self.messages.next_leb128::().ok_or(())?; Ok(Some(BroadcastEvent::RegistryChange( - RegistryChange::Insert(Id::new(Object::from_id(object_id).ok_or(())?, id)), + RegistryChange::Insert(ObjectId::new( + Object::from_id(object_id).ok_or(())?, + id, + )), ))) } 5 => { let object_id = self.messages.next_leb128().ok_or(())?; let id = self.messages.next_leb128::().ok_or(())?; Ok(Some(BroadcastEvent::RegistryChange( - RegistryChange::Delete(Id::new(Object::from_id(object_id).ok_or(())?, id)), + RegistryChange::Delete(ObjectId::new( + Object::from_id(object_id).ok_or(())?, + id, + )), ))) } 6 => { diff --git a/crates/smtp/src/inbound/milter/mod.rs b/crates/smtp/src/inbound/milter/mod.rs index 7bfe9eae..342fb811 100644 --- a/crates/smtp/src/inbound/milter/mod.rs +++ b/crates/smtp/src/inbound/milter/mod.rs @@ -6,7 +6,7 @@ use self::receiver::Receiver; use common::config::smtp::session::MilterVersion; -use registry::types::id::Id; +use registry::types::id::ObjectId; use serde::{Deserialize, Serialize}; use std::{borrow::Cow, fmt::Display, net::IpAddr, time::Duration}; use tokio::io::{AsyncRead, AsyncWrite}; @@ -28,7 +28,7 @@ pub struct MilterClient { options: u32, flags_actions: u32, flags_protocol: u32, - id: Id, + id: ObjectId, session_id: u64, } diff --git a/crates/store/src/dispatch/registry.rs b/crates/store/src/dispatch/registry.rs index 882e085b..8be62a65 100644 --- a/crates/store/src/dispatch/registry.rs +++ b/crates/store/src/dispatch/registry.rs @@ -7,8 +7,9 @@ use crate::{RegistryStore, registry::RegistryObject}; use registry::{ schema::prelude::Object, - types::{ObjectType, id::Id}, + types::{ObjectType, id::ObjectId}, }; +use types::id::Id; impl RegistryStore { pub async fn object(&self, id: impl Into) -> trc::Result> { @@ -31,7 +32,7 @@ impl RegistryStore { todo!() } - pub async fn delete(&self, id: Id) -> trc::Result<()> { + pub async fn delete(&self, id: ObjectId) -> trc::Result<()> { todo!() } diff --git a/crates/store/src/registry/bootstrap.rs b/crates/store/src/registry/bootstrap.rs index 10111a7b..3ad03014 100644 --- a/crates/store/src/registry/bootstrap.rs +++ b/crates/store/src/registry/bootstrap.rs @@ -13,7 +13,7 @@ use registry::{ types::{ ObjectType, error::{Error, ValidationError, Warning}, - id::Id, + id::ObjectId, }, }; @@ -79,7 +79,7 @@ impl Bootstrap { Some(setting) } else { self.errors.push(Error::Validation { - object_id: Id::new(T::object(), id), + object_id: ObjectId::new(T::object(), id), errors, }); None @@ -87,14 +87,14 @@ impl Bootstrap { } Ok(None) => { self.errors.push(Error::NotFound { - object_id: Id::new(T::object(), id), + object_id: ObjectId::new(T::object(), id), }); None } Err(err) => { if !self.has_fatal_errors { self.errors.push(Error::Internal { - object_id: Some(Id::new(T::object(), id)), + object_id: Some(ObjectId::new(T::object(), id)), error: err, }); self.has_fatal_errors = true; @@ -123,14 +123,14 @@ impl Bootstrap { } } - pub fn build_error(&mut self, id: Id, message: impl Into) { + pub fn build_error(&mut self, id: ObjectId, message: impl Into) { self.errors.push(Error::Build { object_id: id, message: message.into(), }); } - pub fn build_warning(&mut self, id: Id, message: impl Into) { + pub fn build_warning(&mut self, id: ObjectId, message: impl Into) { self.warnings.push(Warning { object_id: id, property: None, @@ -138,7 +138,7 @@ impl Bootstrap { }); } - pub fn invalid_property(&mut self, id: Id, property: Property, value: impl Into) { + pub fn invalid_property(&mut self, id: ObjectId, property: Property, value: impl Into) { self.errors.push(Error::Validation { object_id: id, errors: vec![ValidationError::Invalid { @@ -148,7 +148,7 @@ impl Bootstrap { }); } - pub fn validate(&mut self, id: Id, object: &impl ObjectType) -> bool { + pub fn validate(&mut self, id: ObjectId, object: &impl ObjectType) -> bool { let mut errors = Vec::new(); if object.validate(&mut errors) { true diff --git a/crates/store/src/registry/mod.rs b/crates/store/src/registry/mod.rs index 75a83e4c..c533ee3a 100644 --- a/crates/store/src/registry/mod.rs +++ b/crates/store/src/registry/mod.rs @@ -9,11 +9,11 @@ pub mod query; use registry::{ schema::prelude::{Object, Property}, - types::{ObjectType, id::Id}, + types::{ObjectType, id::ObjectId}, }; pub struct RegistryObject { - pub id: Id, + pub id: ObjectId, pub object: T, }