diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 83b3cf4a9..48ad596aa 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -13,7 +13,8 @@ steps: - label: ":rust: Build and Test" command: | echo "--- :rust: Building + Testing" - make test-rust + make test-rust-lib + make test-rust-doc - label: ":rust: Lint" command: | echo "--- :rust: Running Clippy" diff --git a/.buildkite/setup-test-site.sh b/.buildkite/setup-test-site.sh index 28b54b0ae..d2cb32c68 100755 --- a/.buildkite/setup-test-site.sh +++ b/.buildkite/setup-test-site.sh @@ -34,7 +34,11 @@ wp import /tmp/testdata.xml --authors=create ## Then clean up the importer plugin wp plugin delete wordpress-importer -printf "http://localhost\ntest@example.com\n" >> /tmp/test_credentials - -## Create an Application password for the admin user, and store it where it can be used by the test suite -wp user application-password create test@example.com test --porcelain >> /tmp/test_credentials +{ + printf "http://localhost\ntest@example.com\n" + ## Create an Application password for the admin user, and store it where it can be used by the test suite + wp user application-password create test@example.com test --porcelain + printf "themedemos\n" + ## Create an Application password for a subscriber user, and store it where it can be used by the test suite + wp user application-password create themedemos test --porcelain +} >> /tmp/test_credentials diff --git a/Cargo.lock b/Cargo.lock index bf9367668..68ed72f15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,20 +17,54 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" dependencies = [ "anstyle", "anstyle-parse", @@ -42,9 +76,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anstyle-parse" @@ -57,9 +91,9 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3a318f1f38d2418400f8209655bfd825785afd25aa30bb7ba6cc792e4596748" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ "windows-sys 0.52.0", ] @@ -76,9 +110,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "askama" @@ -92,9 +126,9 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.12.2" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a0fc7dcf8bd4ead96b1d36b41df47c14beedf7b0301fc543d8f2384e66a2ec0" +checksum = "19fe8d6cb13c4714962c072ea496f3392015f0989b1a2847bb4b2d9effd71d83" dependencies = [ "askama_parser", "basic-toml", @@ -103,7 +137,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn", + "syn 2.0.60", ] [[package]] @@ -114,24 +148,33 @@ checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" [[package]] name = "askama_parser" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c268a96e01a4c47c8c5c2472aaa570707e006a875ea63e819f75474ceedaf7b4" +checksum = "acb1161c6b64d1c3d83108213c2a2533a342ac225aabd0bda218278c2ddb00c0" dependencies = [ "nom", ] +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -144,9 +187,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" @@ -154,11 +197,17 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "basic-toml" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2db21524cad41c5591204d22d75e1970a2d1f71060214ca931dc7d5afe2c14e5" +checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8" dependencies = [ "serde", ] @@ -180,21 +229,39 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +dependencies = [ + "serde", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] -name = "bytes" +name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "camino" @@ -207,9 +274,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34637b3140142bdf929fb439e8aa4ebad7651ebf7b1080b3930aa16ac1459ff" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" dependencies = [ "serde", ] @@ -230,12 +297,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" [[package]] name = "cfg-if" @@ -243,11 +307,25 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.5", +] + [[package]] name = "clap" -version = "4.4.10" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fffed7514f420abec6d183b1d3acfd9099c79c3a10a06ade4f8203f1411272" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", @@ -255,9 +333,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.9" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63361bae7eef3771745f02d8d892bec2fee5f6e34af316ba556e7f97a7069ff1" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstream", "anstyle", @@ -267,21 +345,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn", + "syn 2.0.60", ] [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "colorchoice" @@ -289,6 +367,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "core-foundation" version = "0.9.4" @@ -306,82 +390,103 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] -name = "darling" -version = "0.20.8" +name = "cpufeatures" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ - "darling_core", - "darling_macro", + "libc", ] [[package]] -name = "darling_core" -version = "0.20.8" +name = "crc" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn", + "crc-catalog", ] [[package]] -name = "darling_macro" -version = "0.20.8" +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crossbeam-queue" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "darling_core", - "quote", - "syn", + "crossbeam-utils", ] [[package]] -name = "derive_builder" -version = "0.20.0" +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "crypto-common" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "derive_builder_macro", + "generic-array", + "typenum", ] [[package]] -name = "derive_builder_core" -version = "0.20.0" +name = "der" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn", + "const-oid", + "pem-rfc7468", + "zeroize", ] [[package]] -name = "derive_builder_macro" -version = "0.20.0" +name = "digest" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "derive_builder_core", - "syn", + "block-buffer", + "const-oid", + "crypto-common", + "subtle", ] [[package]] name = "dissimilar" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86e3bdc80eee6e16b2b6b0f87fbc98c04bee3455e35174c0de1a125d0688c632" +checksum = "440d59c0c6d96354061909b4769b2ca03868dbaee203e7b779d9021ebbde3058" + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "either" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +dependencies = [ + "serde", +] [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -402,11 +507,45 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" + +[[package]] +name = "finl_unicode" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" + +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "spin 0.9.8", +] [[package]] name = "fnv" @@ -489,6 +628,17 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + [[package]] name = "futures-io" version = "0.3.30" @@ -503,7 +653,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.60", ] [[package]] @@ -542,6 +692,27 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gimli" version = "0.28.1" @@ -567,9 +738,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51ee2dd2e4f378392eeff5d51618cd9a63166a2513846bbc55f21cfacd9199d4" +checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" dependencies = [ "bytes", "fnv", @@ -589,24 +760,79 @@ name = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +dependencies = [ + "hashbrown", +] [[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -655,9 +881,9 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "hyper" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "futures-channel", @@ -710,10 +936,27 @@ dependencies = [ ] [[package]] -name = "ident_case" -version = "1.0.1" +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] [[package]] name = "idna" @@ -727,9 +970,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown", @@ -741,17 +984,26 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -761,30 +1013,70 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libsqlite3-sys" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "lock_api" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "md-5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "mime" @@ -810,18 +1102,18 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", @@ -856,6 +1148,53 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", + "libm", +] + [[package]] name = "num_cpus" version = "1.16.0" @@ -868,9 +1207,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -889,11 +1228,11 @@ checksum = "6c548d5c78976f6955d72d0ced18c48ca07030f7a1d4024529fedd7c1c01b29c" [[package]] name = "openssl" -version = "0.10.61" +version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b8419dc8cc6d866deb801274bba2e6f8f6108c1bb7fcc10ee5ab864931dbb45" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.5.0", "cfg-if", "foreign-types", "libc", @@ -910,7 +1249,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.60", ] [[package]] @@ -921,9 +1260,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.97" +version = "0.9.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3eaad34cdd97d81de97964fc7f29e2d104f483840d906ef56daa1912338460b" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", @@ -932,12 +1271,35 @@ dependencies = [ ] [[package]] -name = "parse_link_header" -version = "0.3.3" +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", +] + +[[package]] +name = "parse_link_header" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3687fe9debbbf2a019f381a8bc6b42049b22647449b39af54b3013985c0cf6de" dependencies = [ - "http 0.2.11", + "http 0.2.12", "lazy_static", "regex", ] @@ -948,6 +1310,15 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -971,14 +1342,14 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.60", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -986,11 +1357,32 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plain" @@ -998,24 +1390,60 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -1027,9 +1455,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.3" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", @@ -1039,9 +1467,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -1050,9 +1478,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "relative-path" @@ -1062,11 +1490,11 @@ checksum = "e898588f33fdd5b9420719948f9f2a32c922a246964576f71ba7f24f80610fbc" [[package]] name = "reqwest" -version = "0.12.2" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d66674f2b6fb864665eea7a3c1ac4e3dfacd2fda83cf6f935a612e01b0e3338" +checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ - "base64 0.21.5", + "base64 0.22.0", "bytes", "encoding_rs", "futures-channel", @@ -1103,6 +1531,26 @@ dependencies = [ "winreg", ] +[[package]] +name = "rsa" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "rstest" version = "0.19.0" @@ -1128,7 +1576,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn", + "syn 2.0.60", "unicode-ident", ] @@ -1149,11 +1597,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -1162,28 +1610,41 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.4" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64 0.21.5", + "base64 0.22.0", + "rustls-pki-types", ] +[[package]] +name = "rustls-pki-types" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "beb461507cee2c2ff151784c52762cf4d9ff6a61f3e80968600ed24fa837fa54" + [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "scroll" version = "0.12.0" @@ -1201,14 +1662,14 @@ checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.60", ] [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -1219,9 +1680,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", @@ -1229,38 +1690,38 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.60", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", @@ -1288,6 +1749,47 @@ dependencies = [ "serde", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + [[package]] name = "siphasher" version = "0.3.11" @@ -1317,12 +1819,247 @@ checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "sqlformat" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" +dependencies = [ + "itertools", + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9a2ccff1a000a5a59cd33da541d9f2fdcd9e6e8229cc200565942bff36d0aaa" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24ba59a9342a3d9bab6c56c118be528b27c9b60e490080e9711a04dccac83ef6" +dependencies = [ + "ahash", + "atoi", + "byteorder", + "bytes", + "chrono", + "crc", + "crossbeam-queue", + "either", + "event-listener", + "futures-channel", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashlink", + "hex", + "indexmap", + "log", + "memchr", + "native-tls", + "once_cell", + "paste", + "percent-encoding", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlformat", + "thiserror", + "tokio", + "tokio-stream", + "tracing", + "url", +] + +[[package]] +name = "sqlx-macros" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea40e2345eb2faa9e1e5e326db8c34711317d2b5e08d0d5741619048a803127" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 1.0.109", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8" +dependencies = [ + "dotenvy", + "either", + "heck 0.4.1", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", + "syn 1.0.109", + "tempfile", + "tokio", + "url", +] + +[[package]] +name = "sqlx-mysql" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" +dependencies = [ + "atoi", + "base64 0.21.7", + "bitflags 2.5.0", + "byteorder", + "bytes", + "chrono", + "crc", + "digest", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand", + "rsa", + "serde", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" +dependencies = [ + "atoi", + "base64 0.21.7", + "bitflags 2.5.0", + "byteorder", + "chrono", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "rand", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b244ef0a8414da0bed4bb1910426e890b19e5e9bccc27ada6b797d05c55ae0aa" +dependencies = [ + "atoi", + "chrono", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "sqlx-core", + "tracing", + "url", + "urlencoding", ] [[package]] @@ -1331,17 +2068,45 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "stringprep" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" +dependencies = [ + "finl_unicode", + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" -version = "2.0.52" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -1377,15 +2142,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.1" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1399,9 +2163,9 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" dependencies = [ "smawk", "unicode-linebreak", @@ -1410,22 +2174,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.60", ] [[package]] @@ -1445,20 +2209,34 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", "libc", "mio", "num_cpus", + "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2", + "tokio-macros", "windows-sys 0.48.0", ] +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "tokio-native-tls" version = "0.3.1" @@ -1469,6 +2247,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.10" @@ -1515,9 +2304,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.9" +version = "0.22.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" dependencies = [ "indexmap", "serde", @@ -1562,9 +2351,21 @@ checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "log", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "tracing-core" version = "0.1.32" @@ -1582,9 +2383,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "trybuild" -version = "1.0.90" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aa6f84ec205ebf87fb7a0abdbcd1467fa5af0e86878eb6d888b78ecbb10b6d5" +checksum = "8ad7eb6319ebadebca3dacf1f85a93bc54b73dd81b9036795f73de7ddfe27d5a" dependencies = [ "dissimilar", "glob", @@ -1596,6 +2397,12 @@ dependencies = [ "toml 0.8.12", ] +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "unicase" version = "2.7.0" @@ -1607,9 +2414,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -1625,24 +2432,36 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + [[package]] name = "unicode-width" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + [[package]] name = "uniffi" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37a4fc8954608e2d53e6ea0093ac16c3ce540f9a0cd27ab658caa0282537c54" +checksum = "a5566fae48a5cb017005bf9cd622af5236b2a203a13fb548afde3506d3c68277" dependencies = [ "anyhow", "camino", @@ -1655,9 +2474,9 @@ dependencies = [ [[package]] name = "uniffi_bindgen" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "868c9efaec99e71c60bb22cbd8c89a62e68506a828898c90a6106bde0f298964" +checksum = "4a77bb514bcd4bf27c9bd404d7c3f2a6a8131b957eba9c22cfeb7751c4278e09" dependencies = [ "anyhow", "askama", @@ -1667,7 +2486,7 @@ dependencies = [ "fs-err", "glob", "goblin", - "heck", + "heck 0.4.1", "once_cell", "paste", "serde", @@ -1680,9 +2499,9 @@ dependencies = [ [[package]] name = "uniffi_build" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bb32968ec02e5093df86e4fa8df7759a4cf64d2bde86238b0407c8ec97d80f" +checksum = "45cba427aeb7b3a8b54830c4c915079a7a3c62608dd03dddba1d867a8a023eb4" dependencies = [ "anyhow", "camino", @@ -1691,19 +2510,19 @@ dependencies = [ [[package]] name = "uniffi_checksum_derive" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7f91c2de378a5993a6d0367d9c6e178bbc98309919ee42fccc0142a5adbb25" +checksum = "ae7e5a6c33b1dec3f255f57ec0b6af0f0b2bb3021868be1d5eec7a38e2905ebc" dependencies = [ "quote", - "syn", + "syn 2.0.60", ] [[package]] name = "uniffi_core" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "574b9665ccbf2eaf7e58ca93587d3ba0ef7ead824c4d9b825b54170d1edcd9a2" +checksum = "0ea3eb5474d50fc149b7e4d86b9c5bd4a61dcc167f0683902bf18ae7bbb3deef" dependencies = [ "anyhow", "bytes", @@ -1717,9 +2536,9 @@ dependencies = [ [[package]] name = "uniffi_macros" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18c0cd00841fbcfaac392c1121fc59231c35a8257b68d67dba21322d10ef97d3" +checksum = "18331d35003f46f0d04047fbe4227291815b83a937a8c32bc057f990962182c4" dependencies = [ "bincode", "camino", @@ -1728,16 +2547,16 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn", + "syn 2.0.60", "toml 0.5.11", "uniffi_meta", ] [[package]] name = "uniffi_meta" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70be6fa1fd9b2d3a1138f068da3d1c40394c33c9c880f8b477bd3a2043283893" +checksum = "f7224422c4cfd181c7ca9fca2154abca4d21db962f926f270f996edd38b0c4b8" dependencies = [ "anyhow", "bytes", @@ -1747,9 +2566,9 @@ dependencies = [ [[package]] name = "uniffi_testing" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b28ac70a40b629dec58c8519771637abbe2a1bc09fb0a3019568632917ea9182" +checksum = "f8ce878d0bdfc288b58797044eaaedf748526c56eef3575380bb4d4b19d69eee" dependencies = [ "anyhow", "camino", @@ -1760,9 +2579,9 @@ dependencies = [ [[package]] name = "uniffi_udl" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4823fb2c22e735d437eb4e497f276ea415364da9a3823adcfb8366be7dbd714d" +checksum = "8c43c9ed40a8d20a5c3eae2d23031092db6b96dc8e571beb449ba9757484cea0" dependencies = [ "anyhow", "textwrap", @@ -1782,6 +2601,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf8parse" version = "0.2.1" @@ -1815,11 +2640,17 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1827,24 +2658,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn", + "syn 2.0.60", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -1854,9 +2685,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1864,28 +2695,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -1901,35 +2732,32 @@ dependencies = [ ] [[package]] -name = "winapi" -version = "0.3.9" +name = "whoami" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "redox_syscall", + "wasite", ] -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "134306a13c5647ad6453e8deaec55d3a44d6021970129e6188735e74bf546697" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] [[package]] name = "windows-sys" @@ -1946,7 +2774,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.5", ] [[package]] @@ -1966,17 +2794,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -1987,9 +2816,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -1999,9 +2828,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -2011,9 +2840,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -2023,9 +2858,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -2035,9 +2870,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -2047,9 +2882,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -2059,24 +2894,24 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" dependencies = [ "memchr", ] [[package]] name = "winreg" -version = "0.50.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" dependencies = [ "cfg-if", "windows-sys 0.48.0", @@ -2086,7 +2921,6 @@ dependencies = [ name = "wp_api" version = "0.1.0" dependencies = [ - "derive_builder", "http 1.1.0", "parse_link_header", "rstest", @@ -2098,15 +2932,6 @@ dependencies = [ "wp_derive", ] -[[package]] -name = "wp_cli" -version = "0.1.0" -dependencies = [ - "base64 0.22.0", - "wp_api", - "wp_networking", -] - [[package]] name = "wp_derive" version = "0.1.0" @@ -2114,7 +2939,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn", + "syn 2.0.60", "thiserror", "trybuild", "uniffi", @@ -2124,8 +2949,14 @@ dependencies = [ name = "wp_networking" version = "0.1.0" dependencies = [ + "base64 0.22.0", + "chrono", + "futures", "http 1.1.0", "reqwest", + "serde_json", + "sqlx", + "tokio", "wp_api", ] @@ -2135,3 +2966,29 @@ version = "0.1.0" dependencies = [ "uniffi", ] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/Cargo.toml b/Cargo.toml index 56e67a680..2db4fcc17 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,6 @@ [workspace] members = [ "wp_api", - "wp_cli", "wp_derive", "wp_networking", "wp_uniffi_bindgen", @@ -9,6 +8,9 @@ members = [ resolver = "2" [workspace.dependencies] +base64 = "0.22" http = "1.1" +serde = { version = "1.0", features = [ "derive" ] } +serde_json = "1.0" thiserror = "1.0" uniffi = "0.27.0" diff --git a/Makefile b/Makefile index beaf5ff07..826c5b2ce 100644 --- a/Makefile +++ b/Makefile @@ -20,8 +20,7 @@ swift_package_platform_watchos := $(call swift_package_platform_version,watchos) swift_package_platform_tvos := $(call swift_package_platform_version,tvos) # Required for supporting tvOS and watchOS. We can update the nightly toolchain version if needed. -# The project doesn't compile with the nightly toolchain built on 2024-03-28 and onward. -rust_nightly_toolchain := nightly-2024-03-27 +rust_nightly_toolchain := nightly-2024-04-30 uname := $(shell uname | tr A-Z a-z) ifeq ($(uname), linux) @@ -208,10 +207,13 @@ test-android: bindings _test-android publish-android-local: bindings _publish-android-local -test-rust: - $(rust_docker_run) cargo test +test-rust-lib: + $(rust_docker_run) cargo test --lib -test-server: +test-rust-doc: + $(rust_docker_run) cargo test --doc + +test-server: stop-server rm -rf test_credentials && touch test_credentials && chmod 777 test_credentials docker-compose up -d docker-compose run wpcli @@ -219,6 +221,12 @@ test-server: stop-server: docker-compose down +dump-mysql: + docker exec -it wordpress-rs-mysql-1 /bin/bash -c "mysqldump --defaults-extra-file=mysql_config/config.cnf --no-tablespaces wordpress > dump.sql" + +restore-mysql: + docker exec -it wordpress-rs-mysql-1 /bin/bash -c "mysql --defaults-extra-file=mysql_config/config.cnf --database wordpress < dump.sql" + lint: lint-rust lint-swift lint-rust: diff --git a/docker-compose.yml b/docker-compose.yml index 1cec8de04..e7496eae6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,6 +2,7 @@ version: '3' services: wordpress: image: 'public.ecr.aws/docker/library/wordpress:${WORDPRESS_VERSION:-latest}' + container_name: 'wordpress' ports: - '80:80' volumes: @@ -54,6 +55,8 @@ services: MYSQL_USER: 'wordpress' MYSQL_PASSWORD: 'wordpress' MYSQL_RANDOM_ROOT_PASSWORD: true + volumes: + - ./mysql_config:/mysql_config healthcheck: test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"] interval: 4s diff --git a/mysql_config/config.cnf b/mysql_config/config.cnf new file mode 100644 index 000000000..3b5e793c6 --- /dev/null +++ b/mysql_config/config.cnf @@ -0,0 +1,4 @@ +[client] +user = "wordpress" +password = "wordpress" +host = "localhost" diff --git a/wp_api/Cargo.toml b/wp_api/Cargo.toml index 07c0347bc..efbd2db17 100644 --- a/wp_api/Cargo.toml +++ b/wp_api/Cargo.toml @@ -8,12 +8,11 @@ crate-type = ["lib", "cdylib", "staticlib"] name = "wp_api" [dependencies] -derive_builder = "0.20" http = { workspace = true } url = "2.5" parse_link_header = "0.3" -serde = { version = "1.0", features = [ "derive" ] } -serde_json = "1.0" +serde = { workspace = true } +serde_json = { workspace = true } thiserror = { workspace = true } uniffi = { workspace = true } wp_derive = { path = "../wp_derive" } diff --git a/wp_api/src/api_error.rs b/wp_api/src/api_error.rs index b2eaa0ad6..155502995 100644 --- a/wp_api/src/api_error.rs +++ b/wp_api/src/api_error.rs @@ -1,50 +1,87 @@ -use http::StatusCode; +use serde::Deserialize; -#[derive(Debug, thiserror::Error, uniffi::Error)] +#[derive(Debug, PartialEq, Eq, thiserror::Error, uniffi::Error)] pub enum WPApiError { - #[error( - "Client error with type '{:?}' and status_code '{}'", - error_type, - status_code - )] - ClientError { - error_type: ClientErrorType, + #[error("Rest error '{:?}' with Status Code '{}'", rest_error, status_code)] + RestError { + rest_error: WPRestErrorWrapper, status_code: u16, + response: String, }, - #[error("Server error with status_code '{}'", status_code)] - ServerError { status_code: u16 }, #[error("Error while parsing. \nReason: {}\nResponse: {}", reason, response)] ParsingError { reason: String, response: String }, - #[error("Error that's not yet handled by the library")] - UnknownError, + #[error( + "Error that's not yet handled by the library:\nStatus Code: '{}'.\nResponse: '{}'", + status_code, + response + )] + UnknownError { status_code: u16, response: String }, } -#[derive(Debug, uniffi::Enum)] -pub enum ClientErrorType { - BadRequest, - Unauthorized, - TooManyRequests, - Other, +#[derive(serde::Deserialize, PartialEq, Eq, Debug, uniffi::Enum)] +#[serde(untagged)] +pub enum WPRestErrorWrapper { + Recognized(WPRestError), + Unrecognized(UnrecognizedWPRestError), } -impl ClientErrorType { - pub fn from_status_code(status_code: u16) -> Option { - if let Ok(status_code) = StatusCode::from_u16(status_code) { - if status_code.is_client_error() { - if status_code == StatusCode::BAD_REQUEST { - Some(Self::BadRequest) - } else if status_code == StatusCode::UNAUTHORIZED { - Some(Self::Unauthorized) - } else if status_code == StatusCode::TOO_MANY_REQUESTS { - Some(Self::TooManyRequests) - } else { - Some(Self::Other) - } - } else { - None - } - } else { - None - } - } +#[derive(Debug, Deserialize, PartialEq, Eq, uniffi::Record)] +pub struct WPRestError { + pub code: WPRestErrorCode, + pub message: String, +} + +#[derive(Debug, Deserialize, PartialEq, Eq, uniffi::Record)] +pub struct UnrecognizedWPRestError { + pub code: String, + pub message: String, +} + +#[derive(Debug, Deserialize, PartialEq, Eq, uniffi::Error)] +pub enum WPRestErrorCode { + #[serde(rename = "rest_cannot_create_user")] + CannotCreateUser, + #[serde(rename = "rest_cannot_edit")] + CannotEdit, + #[serde(rename = "rest_cannot_edit_roles")] + CannotEditRoles, + #[serde(rename = "rest_forbidden_context")] + ForbiddenContext, + #[serde(rename = "rest_forbidden_orderby")] + ForbiddenOrderBy, + #[serde(rename = "rest_forbidden_who")] + ForbiddenWho, + #[serde(rename = "rest_invalid_param")] + InvalidParam, + #[serde(rename = "rest_not_logged_in")] + Unauthorized, + #[serde(rename = "rest_user_cannot_delete")] + UserCannotDelete, + #[serde(rename = "rest_user_cannot_view")] + UserCannotView, + #[serde(rename = "rest_user_invalid_email")] + UserInvalidEmail, + #[serde(rename = "rest_user_invalid_id")] + UserInvalidId, + #[serde(rename = "rest_user_invalid_reassign")] + UserInvalidReassign, + #[serde(rename = "rest_user_invalid_role")] + UserInvalidRole, + #[serde(rename = "rest_user_invalid_slug")] + UserInvalidSlug, + // Tested, but we believe these errors are imppossible to get unless the requests are manually modified + #[serde(rename = "rest_user_exists")] + UserExists, + #[serde(rename = "rest_user_invalid_argument")] + UserInvalidArgument, + #[serde(rename = "rest_trash_not_supported")] + TrashNotSupported, + // Untested, because we believe these errors require multisite + #[serde(rename = "rest_user_create")] + UserCreate, + // Untested, because we believe these errors are impossible to get + #[serde(rename = "rest_user_invalid_username")] + UserInvalidUsername, + #[serde(rename = "rest_user_invalid_password")] + UserInvalidPassword, } diff --git a/wp_api/src/endpoint/users_endpoint.rs b/wp_api/src/endpoint/users_endpoint.rs index ca1d2ba31..6ac92c55c 100644 --- a/wp_api/src/endpoint/users_endpoint.rs +++ b/wp_api/src/endpoint/users_endpoint.rs @@ -116,11 +116,11 @@ mod tests { page: Some(2), per_page: Some(60), search: Some("foo".to_string()), - exclude: None, - include: None, + exclude: Vec::new(), + include: Vec::new(), offset: None, order: None, - order_by: None, + orderby: None, slug: vec!["bar".to_string(), "baz".to_string()], roles: Vec::new(), capabilities: Vec::new(), diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index c359a9406..addb65958 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -321,21 +321,24 @@ pub fn parse_api_details_response(response: WPNetworkResponse) -> Result Result<(), WPApiError> { + let response_str = String::from_utf8_lossy(&response.body).to_string(); // TODO: Further parse the response body to include error message // TODO: Lots of unwraps to get a basic setup working - if let Some(client_error_type) = ClientErrorType::from_status_code(response.status_code) { - return Err(WPApiError::ClientError { - error_type: client_error_type, - status_code: response.status_code, - }); - } let status = http::StatusCode::from_u16(response.status_code).unwrap(); - if status.is_server_error() { - return Err(WPApiError::ServerError { + if let Ok(rest_error) = serde_json::from_slice(&response.body) { + Err(WPApiError::RestError { + rest_error, + status_code: response.status_code, + response: response_str, + }) + } else if status.is_client_error() || status.is_server_error() { + Err(WPApiError::UnknownError { status_code: response.status_code, - }); + response: response_str, + }) + } else { + Ok(()) } - Ok(()) } // TODO: Figure out why we can't expose this method on `WPNetworkResponse` via UniFFI diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index 9c4fac6ef..d7b0c18e3 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -1,6 +1,5 @@ use std::collections::HashMap; -use derive_builder::Builder; use serde::{Deserialize, Serialize}; use wp_derive::WPContextual; @@ -91,6 +90,28 @@ impl WPApiParamUsersOrderBy { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Enum)] +pub enum WPApiParamUsersWho { + All, + Authors, +} + +impl WPApiParamUsersWho { + // The only valid value for this parameter is "authors" + fn as_str(&self) -> Option<&str> { + match self { + Self::All => None, + Self::Authors => Some("authors"), + } + } +} + +impl Default for WPApiParamUsersWho { + fn default() -> Self { + Self::All + } +} + #[derive(Default, uniffi::Record)] pub struct UserListParams { // TODO: Implement the `_filter` @@ -103,9 +124,9 @@ pub struct UserListParams { /// Limit results to those matching a string. pub search: Option, /// Ensure result set excludes specific IDs. - pub exclude: Option, + pub exclude: Vec, /// Limit result set to specific IDs. - pub include: Option, + pub include: Vec, /// Offset the result set by a specific number of items. pub offset: Option, /// Order sort attribute ascending or descending. @@ -115,7 +136,7 @@ pub struct UserListParams { /// Sort collection by user attribute. /// Default: `name` /// One of: `id`, `include`, `name`, `registered_date`, `slug`, `include_slugs`, `email`, `url` - pub order_by: Option, + pub orderby: Option, /// Limit result set to users with one or more specific slugs. pub slug: Vec, /// Limit result set to users matching at least one specific role provided. Accepts csv list or single role. @@ -124,7 +145,7 @@ pub struct UserListParams { pub capabilities: Vec, /// Limit result set to users who are considered authors. /// One of: `authors` - pub who: Option, + pub who: Option, /// Limit result set to users who have published posts. pub has_published_posts: Option, } @@ -135,11 +156,29 @@ impl UserListParams { ("page", self.page.map(|x| x.to_string())), ("per_page", self.per_page.map(|x| x.to_string())), ("search", self.search.clone()), - ("exclude", self.exclude.clone()), - ("include", self.include.clone()), + ( + "exclude", + (!self.exclude.is_empty()).then_some( + self.exclude + .iter() + .map(|x| x.to_string()) + .collect::>() + .join(","), + ), + ), + ( + "include", + (!self.include.is_empty()).then_some( + self.include + .iter() + .map(|x| x.to_string()) + .collect::>() + .join(","), + ), + ), ("offset", self.offset.map(|x| x.to_string())), ("order", self.order.map(|x| x.as_str().to_string())), - ("order_by", self.order_by.map(|x| x.as_str().to_string())), + ("orderby", self.orderby.map(|x| x.as_str().to_string())), ( "slug", (!self.slug.is_empty()).then_some(self.slug.join(",")), @@ -152,7 +191,10 @@ impl UserListParams { "capabilities", (!self.capabilities.is_empty()).then_some(self.capabilities.join(",")), ), - ("who", self.who.clone()), + ( + "who", + self.who.and_then(|x| x.as_str().map(|s| s.to_string())), + ), ( "has_published_post", self.has_published_posts.map(|x| x.to_string()), @@ -164,7 +206,7 @@ impl UserListParams { } } -#[derive(Builder, Serialize, uniffi::Record)] +#[derive(Serialize, uniffi::Record)] pub struct UserCreateParams { /// Login name for the user. pub username: String, @@ -174,105 +216,103 @@ pub struct UserCreateParams { pub password: String, /// Display name for the user. #[uniffi(default = None)] - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub name: Option, /// First name for the user. #[uniffi(default = None)] - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub first_name: Option, /// Last name for the user. #[uniffi(default = None)] - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub last_name: Option, /// URL of the user. #[uniffi(default = None)] - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub url: Option, /// Description of the user. #[uniffi(default = None)] - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub description: Option, /// Locale for the user. /// One of: , `en_US` #[uniffi(default = None)] - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub locale: Option, /// The nickname for the user. #[uniffi(default = None)] - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub nickname: Option, /// An alphanumeric identifier for the user. #[uniffi(default = None)] - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub slug: Option, /// Roles assigned to the user. - #[builder(default)] #[serde(skip_serializing_if = "Vec::is_empty")] pub roles: Vec, /// Meta fields. #[uniffi(default = None)] - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub meta: Option, } -#[derive(Builder, Serialize, uniffi::Record)] +impl UserCreateParams { + pub fn new(username: String, email: String, password: String) -> Self { + Self { + username, + email, + password, + name: None, + first_name: None, + last_name: None, + url: None, + description: None, + locale: None, + nickname: None, + slug: None, + roles: Vec::new(), + meta: None, + } + } +} + +#[derive(Default, Serialize, uniffi::Record)] pub struct UserUpdateParams { /// Display name for the user. - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub name: Option, /// First name for the user. - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub first_name: Option, /// Last name for the user. - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub last_name: Option, /// The email address for the user. - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub email: Option, /// URL of the user. - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub url: Option, /// Description of the user. - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub description: Option, /// Locale for the user. /// One of: , `en_US` - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub locale: Option, /// The nickname for the user. - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub nickname: Option, /// An alphanumeric identifier for the user. - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub slug: Option, /// Roles assigned to the user. - #[builder(default)] #[serde(skip_serializing_if = "Vec::is_empty")] pub roles: Vec, /// Password for the user (never included). - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub password: Option, /// Meta fields. - #[builder(default)] #[serde(skip_serializing_if = "Option::is_none")] pub meta: Option, } diff --git a/wp_cli/Cargo.toml b/wp_cli/Cargo.toml deleted file mode 100644 index b307c5e8c..000000000 --- a/wp_cli/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "wp_cli" -version = "0.1.0" -edition = "2021" -default-run = "wp_cli" - -[dependencies] -base64 = "0.22" -wp_api = { path = "../wp_api" } -wp_networking = { path = "../wp_networking" } diff --git a/wp_cli/src/main.rs b/wp_cli/src/main.rs deleted file mode 100644 index 5f5827701..000000000 --- a/wp_cli/src/main.rs +++ /dev/null @@ -1,137 +0,0 @@ -use std::fs::read_to_string; - -use base64::prelude::*; -use wp_api::{ - UserCreateParamsBuilder, UserDeleteParams, UserUpdateParamsBuilder, WPAuthentication, WPContext, -}; -use wp_networking::WPNetworking; - -fn main() { - // A very naive approach just to get things working for now - this whole code will be deleted - // soon - let file_contents = read_to_string("test_credentials").unwrap(); - let lines: Vec<&str> = file_contents.lines().collect(); - let site_url = lines[0]; - let auth_base64_token = BASE64_STANDARD.encode(format!("{}:{}", lines[1], lines[2])); - - let authentication = WPAuthentication::AuthorizationHeader { - token: auth_base64_token, - }; - - let wp_networking = WPNetworking::new(site_url.into(), authentication); - - let user_list_request = wp_networking - .api_helper - .list_users_request(WPContext::Edit, &None); - let user_list = wp_api::parse_list_users_response_with_edit_context( - &wp_networking.request(user_list_request).unwrap(), - ) - .unwrap(); - println!("User List: {:?}", user_list); - - let first_user = user_list.first().unwrap(); - let user_retrieve_request = wp_networking - .api_helper - .retrieve_user_request(first_user.id, WPContext::Embed); - println!( - "{:?}", - wp_api::parse_retrieve_user_response_with_embed_context( - &wp_networking.request(user_retrieve_request).unwrap() - ) - ); - - let user_create_params = UserCreateParamsBuilder::default() - .username("t_username".to_string()) - .email("t_email@foo.com".to_string()) - .password("t_password".to_string()) - .build() - .unwrap(); - - let user_create_request = wp_networking - .api_helper - .create_user_request(&user_create_params); - let user_create_response = wp_networking.request(user_create_request).unwrap(); - let created_user = - wp_api::parse_retrieve_user_response_with_edit_context(&user_create_response); - - println!( - "Create user response: {:?}", - String::from_utf8_lossy(&user_create_response.body) - ); - println!("Created User: {:?}", created_user); - - let created_user = created_user.unwrap(); - let user_update_params = UserUpdateParamsBuilder::default() - .email(Some("t_email_updated@foo.com".to_string())) - .build() - .unwrap(); - let user_update_request = wp_networking - .api_helper - .update_user_request(created_user.id, &user_update_params); - let user_update_response = wp_networking.request(user_update_request).unwrap(); - let updated_user = - wp_api::parse_retrieve_user_response_with_edit_context(&user_update_response); - - println!( - "Update user response: {:?}", - String::from_utf8_lossy(&user_update_response.body) - ); - println!("Updated User: {:?}", updated_user); - - let user_delete_params = UserDeleteParams { - reassign: first_user.id, - }; - let user_delete_request = wp_networking - .api_helper - .delete_user_request(created_user.id, &user_delete_params); - let user_delete_response = wp_networking.request(user_delete_request).unwrap(); - println!( - "Delete user response: {:?}", - String::from_utf8_lossy(&user_delete_response.body) - ); - println!( - "Retrieve current user: {:?}", - wp_api::parse_retrieve_user_response_with_edit_context( - &wp_networking - .request( - wp_networking - .api_helper - .retrieve_current_user_request(WPContext::Edit) - ) - .unwrap() - ) - ); - - let update_current_user_params = UserUpdateParamsBuilder::default() - .description(Some("updated_description".to_string())) - .build() - .unwrap(); - let update_current_user_request = wp_networking - .api_helper - .update_current_user_request(&update_current_user_params); - let update_current_user_response = wp_networking.request(update_current_user_request).unwrap(); - let updated_current_user = - wp_api::parse_retrieve_user_response_with_edit_context(&update_current_user_response); - println!( - "Update current user response: {:?}", - String::from_utf8_lossy(&update_current_user_response.body) - ); - println!("Updated Current User: {:?}", updated_current_user); - - // Remember to use a temporary user to test this - // println!( - // "Delete current user: {:?}", - // String::from_utf8_lossy( - // &wp_networking - // .request( - // wp_networking - // .api_helper - // .delete_current_user_request(&UserDeleteParams { - // reassign: first_user.id - // }) - // ) - // .unwrap() - // .body - // ) - // ); -} diff --git a/wp_derive/Cargo.toml b/wp_derive/Cargo.toml index 73c5d36d6..ba36af543 100644 --- a/wp_derive/Cargo.toml +++ b/wp_derive/Cargo.toml @@ -17,7 +17,7 @@ trybuild = { version = "1.0", features = ["diff"] } [dependencies] proc-macro2 = "1.0" quote = "1.0" -serde = { version = "1.0", features = [ "derive" ] } +serde = { workspace = true } syn = { version = "2.0", features = ["extra-traits"] } thiserror = { workspace = true } uniffi = { workspace = true } diff --git a/wp_networking/Cargo.toml b/wp_networking/Cargo.toml index b3a969c19..51428a5e4 100644 --- a/wp_networking/Cargo.toml +++ b/wp_networking/Cargo.toml @@ -4,6 +4,14 @@ version = "0.1.0" edition = "2021" [dependencies] +base64 = { workspace = true } http = { workspace = true } reqwest = { version = "0.12", features = ["blocking"] } wp_api = { path = "../wp_api" } + +[dev-dependencies] +chrono = { version = "0.4" } +futures = "0.3" +serde_json = { workspace = true } +sqlx = { version = "0.7", features = [ "chrono", "mysql", "runtime-tokio", "tls-native-tls" ]} +tokio = { version = "1.37", features = [ "full" ] } diff --git a/wp_networking/src/lib.rs b/wp_networking/src/lib.rs index 40ed0cd16..69f1407ae 100644 --- a/wp_networking/src/lib.rs +++ b/wp_networking/src/lib.rs @@ -1,23 +1,22 @@ #![allow(dead_code, unused_variables)] use http::HeaderMap; -use reqwest::blocking::Client; -use wp_api::{WPApiHelper, WPAuthentication, WPNetworkRequest, WPNetworkResponse}; +use wp_api::{WPNetworkRequest, WPNetworkResponse}; -pub struct WPNetworking { - client: Client, - pub api_helper: WPApiHelper, +pub struct AsyncWPNetworking { + client: reqwest::Client, } -impl WPNetworking { - pub fn new(site_url: String, authentication: WPAuthentication) -> Self { +impl Default for AsyncWPNetworking { + fn default() -> Self { Self { - client: reqwest::blocking::Client::new(), - api_helper: WPApiHelper::new(site_url, authentication), + client: reqwest::Client::new(), } } +} - pub fn request( +impl AsyncWPNetworking { + pub async fn async_request( &self, wp_request: WPNetworkRequest, ) -> Result { @@ -30,8 +29,13 @@ impl WPNetworking { if let Some(body) = wp_request.body { request = request.body(body); } - let response = request.send()?; - Ok(wp_network_response(response)) + let response = request.send().await?; + + Ok(WPNetworkResponse { + status_code: response.status().as_u16(), + body: response.bytes().await.unwrap().to_vec(), + header_map: None, // TODO: Properly read the headers + }) } } diff --git a/wp_networking/tests/test_helpers.rs b/wp_networking/tests/test_helpers.rs new file mode 100644 index 000000000..381c6194e --- /dev/null +++ b/wp_networking/tests/test_helpers.rs @@ -0,0 +1,156 @@ +use base64::prelude::*; +use std::fs::read_to_string; +use wp_api::{ + UserId, WPApiError, WPApiHelper, WPAuthentication, WPNetworkRequest, WPNetworkResponse, + WPRestError, WPRestErrorCode, WPRestErrorWrapper, +}; + +use wp_networking::AsyncWPNetworking; + +// The first user is also the current user +pub const FIRST_USER_ID: UserId = UserId(1); +pub const SECOND_USER_ID: UserId = UserId(2); +pub const SECOND_USER_EMAIL: &str = "themeshaperwp+demos@gmail.com"; +pub const SECOND_USER_SLUG: &str = "themedemos"; + +pub fn api() -> WPApiHelper { + let credentials = test_credentials(); + let auth_base64_token = BASE64_STANDARD.encode(format!( + "{}:{}", + credentials.admin_username, credentials.admin_password + )); + let authentication = WPAuthentication::AuthorizationHeader { + token: auth_base64_token, + }; + WPApiHelper::new(credentials.site_url, authentication) +} + +pub fn api_as_subscriber() -> WPApiHelper { + let credentials = test_credentials(); + let auth_base64_token = BASE64_STANDARD.encode(format!( + "{}:{}", + credentials.subscriber_username, credentials.subscriber_password + )); + let authentication = WPAuthentication::AuthorizationHeader { + token: auth_base64_token, + }; + WPApiHelper::new(credentials.site_url, authentication) +} + +pub trait WPNetworkRequestExecutor { + fn execute( + self, + ) -> impl std::future::Future> + Send; +} + +impl WPNetworkRequestExecutor for WPNetworkRequest { + async fn execute(self) -> Result { + AsyncWPNetworking::default().async_request(self).await + } +} + +pub trait WPNetworkResponseParser { + fn parse(&self, parser: F) -> Result + where + F: Fn(&WPNetworkResponse) -> Result; +} + +impl WPNetworkResponseParser for WPNetworkResponse { + fn parse(&self, parser: F) -> Result + where + F: Fn(&WPNetworkResponse) -> Result, + { + parser(self) + } +} + +pub trait AssertWpError { + fn assert_wp_error(self, expected_error_code: WPRestErrorCode); +} + +impl AssertWpError for Result { + fn assert_wp_error(self, expected_error_code: WPRestErrorCode) { + let expected_status_code = + expected_status_code_for_wp_rest_error_code(&expected_error_code); + let err = self.unwrap_err(); + if let WPApiError::RestError { + rest_error: + WPRestErrorWrapper::Recognized(WPRestError { + code: error_code, + message: _, + }), + status_code, + response, + } = err + { + assert_eq!( + expected_error_code, error_code, + "Incorrect error code. Expected '{:?}', found '{:?}'. Response was: '{:?}'", + expected_error_code, error_code, response + ); + assert_eq!( + expected_status_code, status_code, + "Incorrect status code. Expected '{:?}', found '{:?}'. Response was: '{:?}'", + expected_status_code, status_code, response + ); + } else if let WPApiError::RestError { + rest_error: WPRestErrorWrapper::Unrecognized(unrecognized_error), + status_code, + response, + } = err + { + panic!( + "Received unhandled WPRestError variant: '{:?}' with status_code: '{}'. Response was: '{:?}'", + unrecognized_error, status_code, response + ); + } else { + panic!("Unexpected wp_error '{:?}'", err); + } + } +} + +pub struct TestCredentials { + pub site_url: String, + pub admin_username: String, + pub admin_password: String, + pub subscriber_username: String, + pub subscriber_password: String, +} + +pub fn test_credentials() -> TestCredentials { + let file_contents = read_to_string("../test_credentials").unwrap(); + let lines: Vec<&str> = file_contents.lines().collect(); + TestCredentials { + site_url: lines[0].to_string(), + admin_username: lines[1].to_string(), + admin_password: lines[2].to_string(), + subscriber_username: lines[3].to_string(), + subscriber_password: lines[4].to_string(), + } +} + +fn expected_status_code_for_wp_rest_error_code(error_code: &WPRestErrorCode) -> u16 { + match error_code { + WPRestErrorCode::CannotCreateUser => 403, + WPRestErrorCode::CannotEdit => 403, + WPRestErrorCode::CannotEditRoles => 403, + WPRestErrorCode::ForbiddenContext => 403, + WPRestErrorCode::ForbiddenOrderBy => 403, + WPRestErrorCode::ForbiddenWho => 403, + WPRestErrorCode::InvalidParam => 400, + WPRestErrorCode::TrashNotSupported => 501, + WPRestErrorCode::Unauthorized => 401, + WPRestErrorCode::UserCannotDelete => 403, + WPRestErrorCode::UserCannotView => 403, + WPRestErrorCode::UserCreate => 500, + WPRestErrorCode::UserExists => 400, + WPRestErrorCode::UserInvalidArgument => 400, + WPRestErrorCode::UserInvalidEmail => 400, + WPRestErrorCode::UserInvalidId => 404, + WPRestErrorCode::UserInvalidPassword => 400, + WPRestErrorCode::UserInvalidReassign => 400, + WPRestErrorCode::UserInvalidRole => 400, + WPRestErrorCode::UserInvalidSlug => 400, + WPRestErrorCode::UserInvalidUsername => 400, + } +} diff --git a/wp_networking/tests/test_users_err.rs b/wp_networking/tests/test_users_err.rs new file mode 100644 index 000000000..5de16b18f --- /dev/null +++ b/wp_networking/tests/test_users_err.rs @@ -0,0 +1,327 @@ +use test_helpers::SECOND_USER_EMAIL; +use wp_api::{ + UserCreateParams, UserDeleteParams, UserId, UserListParams, UserUpdateParams, WPApiHelper, + WPApiParamUsersOrderBy, WPApiParamUsersWho, WPAuthentication, WPContext, WPRestErrorCode, +}; + +use crate::test_helpers::{ + api, api_as_subscriber, AssertWpError, WPNetworkRequestExecutor, WPNetworkResponseParser, + FIRST_USER_ID, SECOND_USER_ID, SECOND_USER_SLUG, +}; + +pub mod test_helpers; + +#[tokio::test] +async fn create_user_err_cannot_create_user() { + api_as_subscriber() + .create_user_request(&valid_user_create_params()) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::CannotCreateUser); +} + +#[tokio::test] +async fn delete_user_err_user_cannot_delete() { + api_as_subscriber() + .delete_user_request( + FIRST_USER_ID, + &UserDeleteParams { + reassign: SECOND_USER_ID, + }, + ) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::UserCannotDelete); +} + +#[tokio::test] +async fn delete_user_err_user_invalid_reassign() { + api() + .delete_user_request( + FIRST_USER_ID, + &UserDeleteParams { + reassign: UserId(987654321), + }, + ) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::UserInvalidReassign); +} + +#[tokio::test] +async fn delete_current_user_err_user_invalid_reassign() { + api() + .delete_current_user_request(&UserDeleteParams { + reassign: UserId(987654321), + }) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::UserInvalidReassign); +} + +#[tokio::test] +async fn list_users_err_forbidden_context() { + api_as_subscriber() + .list_users_request(WPContext::Edit, &None) + .execute() + .await + .unwrap() + .parse(wp_api::parse_list_users_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::ForbiddenContext); +} + +#[tokio::test] +async fn list_users_err_forbidden_orderby_email() { + let mut params = UserListParams::default(); + params.orderby = Some(WPApiParamUsersOrderBy::Email); + api_as_subscriber() + .list_users_request(WPContext::View, &Some(params)) + .execute() + .await + .unwrap() + .parse(wp_api::parse_list_users_response_with_view_context) + .assert_wp_error(WPRestErrorCode::ForbiddenOrderBy); +} + +#[tokio::test] +async fn list_users_err_forbidden_who() { + let mut params = UserListParams::default(); + params.who = Some(WPApiParamUsersWho::Authors); + api_as_subscriber() + .list_users_request(WPContext::View, &Some(params)) + .execute() + .await + .unwrap() + .parse(wp_api::parse_list_users_response_with_view_context) + .assert_wp_error(WPRestErrorCode::ForbiddenWho); +} + +#[tokio::test] +async fn list_users_with_capabilities_err_user_cannot_view() { + let mut params = UserListParams::default(); + params.capabilities = vec!["foo".to_string()]; + api_as_subscriber() + .list_users_request(WPContext::Edit, &Some(params)) + .execute() + .await + .unwrap() + .parse(wp_api::parse_list_users_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::UserCannotView); +} + +#[tokio::test] +async fn list_users_with_roles_err_user_cannot_view() { + let mut params = UserListParams::default(); + params.roles = vec!["foo".to_string()]; + api_as_subscriber() + .list_users_request(WPContext::Edit, &Some(params)) + .execute() + .await + .unwrap() + .parse(wp_api::parse_list_users_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::UserCannotView); +} + +#[tokio::test] +async fn list_users_orderby_registered_date_err_forbidden_orderby() { + let mut params = UserListParams::default(); + params.orderby = Some(WPApiParamUsersOrderBy::RegisteredDate); + api_as_subscriber() + .list_users_request(WPContext::View, &Some(params)) + .execute() + .await + .unwrap() + .parse(wp_api::parse_list_users_response_with_view_context) + .assert_wp_error(WPRestErrorCode::ForbiddenOrderBy); +} + +#[tokio::test] +async fn retrieve_user_err_user_invalid_id() { + api() + .retrieve_user_request(UserId(987654321), WPContext::Edit) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::UserInvalidId); +} + +#[tokio::test] +async fn retrieve_user_err_unauthorized() { + WPApiHelper::new( + test_helpers::test_credentials().site_url, + WPAuthentication::None, + ) + .retrieve_current_user_request(WPContext::Edit) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::Unauthorized); +} + +#[tokio::test] +async fn update_user_err_cannot_edit() { + let mut params = UserUpdateParams::default(); + params.slug = Some("new_slug".to_string()); + // Subscribers can't update someone else's slug + api_as_subscriber() + .update_user_request(FIRST_USER_ID, ¶ms) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::CannotEdit); +} + +#[tokio::test] +async fn update_user_err_user_invalid_argument() { + let mut request = api().update_user_request(FIRST_USER_ID, &UserUpdateParams::default()); + request.body = Some( + serde_json::json!({ + "username": "new_username", + }) + .to_string() + .into_bytes(), + ); + // Usernames are not editable + request + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::UserInvalidArgument); +} + +#[tokio::test] +async fn update_user_err_cannot_edit_roles() { + let mut params = UserUpdateParams::default(); + params.roles = vec!["new_role".to_string()]; + // Subscribers can't update their roles + api_as_subscriber() + .update_user_request(SECOND_USER_ID, ¶ms) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::CannotEditRoles); +} + +#[tokio::test] +async fn update_user_err_user_invalid_email() { + let mut params = UserUpdateParams::default(); + params.email = Some(SECOND_USER_EMAIL.to_string()); + // Can't update user's email to an email that's already in use + api() + .update_user_request(FIRST_USER_ID, ¶ms) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::UserInvalidEmail); +} + +#[tokio::test] +async fn update_user_email_err_invalid_param() { + let mut params = UserUpdateParams::default(); + params.email = Some("not_valid".to_string()); + api() + .update_user_request(FIRST_USER_ID, ¶ms) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::InvalidParam); +} + +#[tokio::test] +async fn update_user_password_err_invalid_param() { + let mut params = UserUpdateParams::default(); + params.password = Some("".to_string()); + api() + .update_user_request(FIRST_USER_ID, ¶ms) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::InvalidParam); +} + +#[tokio::test] +async fn update_user_err_user_invalid_role() { + let mut params = UserUpdateParams::default(); + params.roles = vec!["doesnt_exist".to_string()]; + // Can't update user's email to a role that doesn't exist + api() + .update_user_request(FIRST_USER_ID, ¶ms) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::UserInvalidRole); +} + +#[tokio::test] +async fn update_user_err_user_invalid_slug() { + let mut params = UserUpdateParams::default(); + params.slug = Some(SECOND_USER_SLUG.to_string()); + // Can't update user's slug to a slug that's already in use + api() + .update_user_request(FIRST_USER_ID, ¶ms) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::UserInvalidSlug); +} + +// In the following tests, we manually modify the request because the errors they test are not +// possible to get without it. We believe these tests are still useful as they act as a +// documentation for how these errors might be received. + +#[tokio::test] +async fn create_user_err_user_exists() { + let mut request = api().create_user_request(&valid_user_create_params()); + request.url.push_str("?id=1"); + request + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::UserExists); +} + +#[tokio::test] +async fn delete_user_err_trash_not_supported() { + let mut request = api().delete_user_request( + FIRST_USER_ID, + &UserDeleteParams { + reassign: SECOND_USER_ID, + }, + ); + request.url = request.url.replace("&force=true", ""); + request + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .assert_wp_error(WPRestErrorCode::TrashNotSupported); +} + +// Helpers + +fn valid_user_create_params() -> UserCreateParams { + UserCreateParams::new( + "t_username".to_string(), + "t_email@foo.com".to_string(), + "t_password".to_string(), + ) +} diff --git a/wp_networking/tests/test_users_immut.rs b/wp_networking/tests/test_users_immut.rs new file mode 100644 index 000000000..43e76b44f --- /dev/null +++ b/wp_networking/tests/test_users_immut.rs @@ -0,0 +1,276 @@ +use wp_api::{ + UserListParams, WPApiParamOrder, WPApiParamUsersOrderBy, WPApiParamUsersWho, WPContext, +}; + +use crate::test_helpers::{ + api, WPNetworkRequestExecutor, WPNetworkResponseParser, FIRST_USER_ID, SECOND_USER_ID, +}; + +pub mod test_helpers; + +#[tokio::test] +async fn list_users_with_edit_context() { + assert!(api() + .list_users_request(WPContext::Edit, &None) + .execute() + .await + .unwrap() + .parse(wp_api::parse_list_users_response_with_edit_context) + .is_ok()); +} + +#[tokio::test] +async fn list_users_with_embed_context() { + assert!(api() + .list_users_request(WPContext::Embed, &None) + .execute() + .await + .unwrap() + .parse(wp_api::parse_list_users_response_with_embed_context) + .is_ok()); +} + +#[tokio::test] +async fn list_users_with_view_context() { + assert!(api() + .list_users_request(WPContext::View, &None) + .execute() + .await + .unwrap() + .parse(wp_api::parse_list_users_response_with_view_context) + .is_ok()); +} + +#[tokio::test] +async fn list_users_param_page() { + let mut params = UserListParams::default(); + params.page = Some(2); + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_per_page() { + let mut params = UserListParams::default(); + params.per_page = Some(2); + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_search() { + let mut params = UserListParams::default(); + params.search = Some("foo".to_string()); + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_exclude() { + let mut params = UserListParams::default(); + params.exclude = vec![FIRST_USER_ID]; + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_include() { + let mut params = UserListParams::default(); + params.include = vec![SECOND_USER_ID]; + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_offset() { + let mut params = UserListParams::default(); + params.offset = Some(2); + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_order_asc() { + let mut params = UserListParams::default(); + params.order = Some(WPApiParamOrder::Asc); + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_order_desc() { + let mut params = UserListParams::default(); + params.order = Some(WPApiParamOrder::Desc); + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_orderby_id() { + let mut params = UserListParams::default(); + params.orderby = Some(WPApiParamUsersOrderBy::Id); + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_orderby_include() { + let mut params = UserListParams::default(); + params.orderby = Some(WPApiParamUsersOrderBy::Include); + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_orderby_name() { + let mut params = UserListParams::default(); + params.orderby = Some(WPApiParamUsersOrderBy::Name); + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_orderby_registered_date() { + let mut params = UserListParams::default(); + params.orderby = Some(WPApiParamUsersOrderBy::RegisteredDate); + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_orderby_slug() { + let mut params = UserListParams::default(); + params.orderby = Some(WPApiParamUsersOrderBy::Slug); + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_orderby_include_slugs() { + let mut params = UserListParams::default(); + params.orderby = Some(WPApiParamUsersOrderBy::IncludeSlugs); + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_orderby_email() { + let mut params = UserListParams::default(); + params.orderby = Some(WPApiParamUsersOrderBy::Email); + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_orderby_url() { + let mut params = UserListParams::default(); + params.orderby = Some(WPApiParamUsersOrderBy::Url); + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_slug() { + let mut params = UserListParams::default(); + params.slug = vec!["foo".to_string()]; + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_roles_edit_posts() { + let mut params = UserListParams::default(); + params.roles = vec!["edit_posts".to_string()]; + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_capabilities() { + let mut params = UserListParams::default(); + params.capabilities = vec!["foo".to_string()]; + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_who_all() { + let mut params = UserListParams::default(); + params.who = Some(WPApiParamUsersWho::All); + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_who_authors() { + let mut params = UserListParams::default(); + params.who = Some(WPApiParamUsersWho::Authors); + test_user_list_params(params).await; +} + +#[tokio::test] +async fn list_users_param_has_published_posts() { + let mut params = UserListParams::default(); + params.has_published_posts = Some(true); + test_user_list_params(params).await; +} + +#[tokio::test] +async fn retrieve_user_with_edit_context() { + assert!(api() + .retrieve_user_request(FIRST_USER_ID, WPContext::Edit) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .is_ok()); +} + +#[tokio::test] +async fn retrieve_user_with_embed_context() { + assert!(api() + .retrieve_user_request(FIRST_USER_ID, WPContext::Embed) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_embed_context) + .is_ok()); +} + +#[tokio::test] +async fn retrieve_user_with_view_context() { + assert!(api() + .retrieve_user_request(FIRST_USER_ID, WPContext::View) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_view_context) + .is_ok()); +} + +#[tokio::test] +async fn retrieve_current_user_with_edit_context() { + assert!(api() + .retrieve_current_user_request(WPContext::Edit) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .is_ok()); +} + +#[tokio::test] +async fn retrieve_current_user_with_embed_context() { + assert!(api() + .retrieve_current_user_request(WPContext::Embed) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_embed_context) + .is_ok()); +} + +#[tokio::test] +async fn retrieve_current_user_with_view_context() { + assert!(api() + .retrieve_current_user_request(WPContext::View) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_view_context) + .is_ok()); +} + +async fn test_user_list_params(params: UserListParams) { + let parsed_response = api() + .list_users_request(WPContext::Edit, &Some(params)) + .execute() + .await + .unwrap() + .parse(wp_api::parse_list_users_response_with_edit_context); + assert!( + parsed_response.is_ok(), + "Response was: '{:?}'", + parsed_response + ); +} diff --git a/wp_networking/tests/test_users_mut.rs b/wp_networking/tests/test_users_mut.rs new file mode 100644 index 000000000..f88e4bbaf --- /dev/null +++ b/wp_networking/tests/test_users_mut.rs @@ -0,0 +1,236 @@ +use wp_api::{UserCreateParams, UserDeleteParams, UserUpdateParams}; +use wp_db::{DbUser, DbUserMeta}; + +use crate::test_helpers::{ + api, WPNetworkRequestExecutor, WPNetworkResponseParser, FIRST_USER_ID, SECOND_USER_ID, +}; + +pub mod test_helpers; +pub mod wp_db; + +#[tokio::test] +async fn create_user() { + wp_db::run_and_restore(|mut db| async move { + let username = "t_username"; + let email = "t_email@foo.com"; + let password = "t_password"; + + // Create a user using the API + let params = UserCreateParams::new( + username.to_string(), + email.to_string(), + password.to_string(), + ); + let created_user = api() + .create_user_request(¶ms) + .execute() + .await + .unwrap() + .parse(wp_api::parse_retrieve_user_response_with_edit_context) + .unwrap(); + + // Assert that the user is in DB + let created_user_from_db = db.user(created_user.id.0 as u64).await.unwrap(); + assert_eq!(created_user_from_db.username, username); + assert_eq!(created_user_from_db.email, email); + }) + .await; +} + +#[tokio::test] +async fn delete_user() { + wp_db::run_and_restore(|mut db| async move { + // Delete the user using the API and ensure it's successful + let user_delete_params = UserDeleteParams { + reassign: FIRST_USER_ID, + }; + let user_delete_response = api() + .delete_user_request(SECOND_USER_ID, &user_delete_params) + .execute() + .await; + assert!(user_delete_response.is_ok()); + + // Assert that the DB doesn't have a record of the user anymore + assert!(matches!( + db.user(SECOND_USER_ID.0 as u64).await.unwrap_err(), + sqlx::Error::RowNotFound + )); + }) + .await; +} + +#[tokio::test] +async fn delete_current_user() { + wp_db::run_and_restore(|mut db| async move { + // Delete the user using the API and ensure it's successful + let user_delete_params = UserDeleteParams { + reassign: SECOND_USER_ID, + }; + let user_delete_response = api() + .delete_current_user_request(&user_delete_params) + .execute() + .await; + assert!(user_delete_response.is_ok()); + + // Assert that the DB doesn't have a record of the user anymore + assert!(matches!( + // The first user is also the current user + db.user(FIRST_USER_ID.0 as u64).await.unwrap_err(), + sqlx::Error::RowNotFound + )); + }) + .await; +} + +#[tokio::test] +async fn update_user_name() { + let new_name = "new_name"; + let mut params = UserUpdateParams::default(); + params.name = Some(new_name.to_string()); + test_update_user(params, |user, _| { + assert_eq!(user.name, new_name); + }) + .await; +} + +#[tokio::test] +async fn update_user_first_name() { + let new_first_name = "new_first_name"; + let mut params = UserUpdateParams::default(); + params.first_name = Some(new_first_name.to_string()); + test_update_user(params, |_, meta_list| { + assert_eq!(find_meta(&meta_list, "first_name"), new_first_name); + }) + .await; +} + +#[tokio::test] +async fn update_user_last_name() { + let new_last_name = "new_last_name"; + let mut params = UserUpdateParams::default(); + params.last_name = Some(new_last_name.to_string()); + test_update_user(params, |_, meta_list| { + assert_eq!(find_meta(&meta_list, "last_name"), new_last_name); + }) + .await; +} + +#[tokio::test] +async fn update_user_email() { + let new_email = "new_email@foo.com"; + let mut params = UserUpdateParams::default(); + params.email = Some(new_email.to_string()); + test_update_user(params, |user, _| { + assert_eq!(user.email, new_email); + }) + .await; +} + +#[tokio::test] +async fn update_user_url() { + let new_url = "https://new_url"; + let mut params = UserUpdateParams::default(); + params.url = Some(new_url.to_string()); + test_update_user(params, |user, _| { + assert_eq!(user.url, new_url); + }) + .await; +} + +#[tokio::test] +async fn update_user_description() { + let new_description = "new_description"; + let mut params = UserUpdateParams::default(); + params.description = Some(new_description.to_string()); + test_update_user(params, |_, meta_list| { + assert_eq!(find_meta(&meta_list, "description"), new_description); + }) + .await; +} + +#[tokio::test] +async fn update_user_nickname() { + let new_nickname = "new_nickname"; + let mut params = UserUpdateParams::default(); + params.nickname = Some(new_nickname.to_string()); + test_update_user(params, |_, meta_list| { + assert_eq!(find_meta(&meta_list, "nickname"), new_nickname); + }) + .await; +} + +#[tokio::test] +async fn update_user_slug() { + let new_slug = "new_slug"; + let mut params = UserUpdateParams::default(); + params.slug = Some(new_slug.to_string()); + test_update_user(params, |user, _| { + assert_eq!(user.slug, new_slug); + }) + .await; +} + +#[tokio::test] +async fn update_user_roles() { + wp_db::run_and_restore(|_| async move { + let new_role = "new_role"; + let mut params = UserUpdateParams::default(); + params.roles = vec![new_role.to_string()]; + let user_update_response = api() + .update_user_request(FIRST_USER_ID, ¶ms) + .execute() + .await; + // It's quite tricky to validate the roles from DB, so we just ensure the request was + // successful + assert!(user_update_response.is_ok()); + }) + .await; +} + +#[tokio::test] +async fn update_user_password() { + wp_db::run_and_restore(|_| async move { + let new_password = "new_password"; + let mut params = UserUpdateParams::default(); + params.password = Some(new_password.to_string()); + let user_update_response = api() + .update_user_request(FIRST_USER_ID, ¶ms) + .execute() + .await; + // It's quite tricky to validate the password from DB, so we just ensure the request was + // successful + assert!(user_update_response.is_ok()); + }) + .await; +} + +async fn test_update_user(params: UserUpdateParams, assert: F) +where + F: Fn(DbUser, Vec) -> (), +{ + wp_db::run_and_restore(|mut db| async move { + let user_update_response = api() + .update_user_request(FIRST_USER_ID, ¶ms) + .execute() + .await; + assert!(user_update_response.is_ok()); + + let db_user_after_update = db.user(FIRST_USER_ID.0 as u64).await.unwrap(); + let db_user_meta_after_update = db.user_meta(FIRST_USER_ID.0 as u64).await.unwrap(); + assert(db_user_after_update, db_user_meta_after_update); + }) + .await; +} + +fn find_meta(meta_list: &Vec, meta_key: &str) -> String { + meta_list + .iter() + .find_map(|m| { + if m.meta_key == meta_key { + Some(m.meta_value.clone()) + } else { + None + } + }) + .unwrap() +} diff --git a/wp_networking/tests/wp_db.rs b/wp_networking/tests/wp_db.rs new file mode 100644 index 000000000..d22104320 --- /dev/null +++ b/wp_networking/tests/wp_db.rs @@ -0,0 +1,81 @@ +use std::process::Command; + +use futures::Future; +use sqlx::{mysql::MySqlConnectOptions, ConnectOptions, MySqlConnection}; + +pub async fn run_and_restore(f: F) +where + F: FnOnce(WordPressDb) -> Fut, + Fut: Future, +{ + let options = MySqlConnectOptions::new() + .host("localhost") + .username("wordpress") + .password("wordpress") + .database("wordpress"); + let conn = MySqlConnectOptions::connect(&options).await.unwrap(); + f(WordPressDb { conn }).await +} + +pub struct WordPressDb { + conn: MySqlConnection, +} + +impl Drop for WordPressDb { + fn drop(&mut self) { + println!("Restoring WordPressDB.."); + Command::new("make") + .arg("-C") + .arg("../") + .arg("restore-mysql") + .status() + .expect("Failed to restore db"); + } +} + +impl WordPressDb { + pub async fn users(&mut self) -> Result, sqlx::Error> { + sqlx::query_as("SELECT * FROM wp_users") + .fetch_all(&mut self.conn) + .await + } + + pub async fn user(&mut self, user_id: u64) -> Result { + sqlx::query_as("SELECT * FROM wp_users WHERE ID = ?") + .bind(user_id) + .fetch_one(&mut self.conn) + .await + } + + pub async fn user_meta(&mut self, user_id: u64) -> Result, sqlx::Error> { + sqlx::query_as("SELECT * FROM wp_usermeta WHERE user_id = ?") + .bind(user_id) + .fetch_all(&mut self.conn) + .await + } +} + +#[derive(Debug, sqlx::FromRow)] +pub struct DbUser { + #[sqlx(rename = "ID")] + pub id: u64, + #[sqlx(rename = "user_login")] + pub username: String, + #[sqlx(rename = "user_nicename")] + pub slug: String, + #[sqlx(rename = "user_email")] + pub email: String, + #[sqlx(rename = "user_url")] + pub url: String, + #[sqlx(rename = "user_registered")] + pub registered_date: chrono::DateTime, + #[sqlx(rename = "display_name")] + pub name: String, +} + +#[derive(Debug, sqlx::FromRow)] +pub struct DbUserMeta { + pub user_id: u64, + pub meta_key: String, + pub meta_value: String, +}