diff --git a/.circleci/config.yml b/.circleci/config.yml index cd7f2d06..b0f7e651 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -63,7 +63,7 @@ commands: type: boolean default: false steps: - - run: cargo clippy <<^parameters.no_feature>>--no-default-features --features="${FEATURES}"<> --release -p <> -- -D warnings + - run: cargo clippy <<^parameters.no_feature>>--no-default-features --features="${FEATURES}"<> --release -p <> -- -D warnings -A clippy::needless_borrow run_with_coverage: description: run command with environment for coverage diff --git a/.circleci/images/plume-buildenv/Dockerfile b/.circleci/images/plume-buildenv/Dockerfile index 5187add0..41ec8072 100644 --- a/.circleci/images/plume-buildenv/Dockerfile +++ b/.circleci/images/plume-buildenv/Dockerfile @@ -11,7 +11,7 @@ RUN apt update &&\ rm -rf /var/lib/apt/lists/* #install and configure rust -RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain nightly-2021-01-15 -y &&\ +RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain nightly-2021-11-27 -y &&\ rustup component add rustfmt clippy &&\ rustup component add rust-std --target wasm32-unknown-unknown diff --git a/CHANGELOG.md b/CHANGELOG.md index b29f9ebc..f6a8bfcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,10 +16,11 @@ - Upgrade some dependent crates (#858) - Use tracing crate (#868) -- Update Rust version to nightly-2021-01-15 (#878) +- Update Rust version to nightly-2021-11-27 (#961) - Upgrade Tantivy to 0.13.3 and lindera-tantivy to 0.7.1 (#878) - Run searcher on actor system (#870) - Use article title as its slug instead of capitalizing and inserting hyphens (#920) +- Sign GET requests to other instances (#957) ### Fixed diff --git a/Cargo.lock b/Cargo.lock index 2030031e..0bd41319 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -133,9 +133,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ "getrandom 0.2.3", "once_cell", @@ -185,9 +185,9 @@ dependencies = [ [[package]] name = "arc-swap" -version = "1.3.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5ab7d9e73059c86c36473f459b52adbd99c3554a4fec492caef460806006f00" +checksum = "c5d78ce20460b82d3fa150275ed9d55e21064fc7951177baacf86a145c4a4b1f" [[package]] name = "array_tool" @@ -219,9 +219,9 @@ version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e" dependencies = [ - "proc-macro2 1.0.29", - "quote 1.0.9", - "syn 1.0.76", + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn 1.0.82", ] [[package]] @@ -383,9 +383,9 @@ dependencies = [ [[package]] name = "bitvec" -version = "0.19.5" +version = "0.19.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321" +checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33" dependencies = [ "funty", "radium", @@ -431,9 +431,9 @@ checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" [[package]] name = "bumpalo" -version = "3.7.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" +checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" [[package]] name = "bytecount" @@ -478,9 +478,9 @@ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" [[package]] name = "cc" -version = "1.0.70" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" [[package]] name = "census" @@ -522,7 +522,7 @@ dependencies = [ "num-integer", "num-traits 0.2.14", "serde 1.0.130", - "time", + "time 0.1.43", "winapi 0.3.9", ] @@ -570,9 +570,9 @@ dependencies = [ [[package]] name = "combine" -version = "4.6.1" +version = "4.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a909e4d93292cd8e9c42e189f61681eff9d67b6541f96b8a1a737f23737bd001" +checksum = "b2b2f5d0ee456f3928812dfc8c6d9a1d592b98678f6d56db9b0cd2b7bc6c8db5" dependencies = [ "memchr", ] @@ -595,11 +595,11 @@ dependencies = [ [[package]] name = "console_error_panic_hook" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "wasm-bindgen", ] @@ -647,7 +647,7 @@ dependencies = [ "percent-encoding 2.1.0", "rand 0.8.4", "sha2", - "time", + "time 0.1.43", ] [[package]] @@ -656,7 +656,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" dependencies = [ - "time", + "time 0.1.43", "url 1.7.2", ] @@ -673,16 +673,16 @@ dependencies = [ "publicsuffix", "serde 1.0.130", "serde_json", - "time", + "time 0.1.43", "try_from", "url 1.7.2", ] [[package]] name = "core-foundation" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" +checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" dependencies = [ "core-foundation-sys", "libc", @@ -690,9 +690,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "cpufeatures" @@ -711,9 +711,9 @@ checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" [[package]] name = "crc32fast" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +checksum = "3825b1e8580894917dc4468cb634a1b4e9745fddc854edad72d9c04644c0319f" dependencies = [ "cfg-if 1.0.0", ] @@ -885,11 +885,11 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "377c9b002a72a0b2c1a18c62e2f3864bdfea4a015e3683a96e24aa45dd6c02d1" +checksum = "a19c6cedffdc8c03a3346d723eb20bd85a13362bb96dc2ac000842c6381ec7bf" dependencies = [ - "nix 0.22.0", + "nix 0.23.0", "winapi 0.3.9", ] @@ -996,9 +996,9 @@ dependencies = [ [[package]] name = "diesel" -version = "1.4.7" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bba51ca66f57261fd17cadf8b73e4775cc307d0521d855de3f5de91a8f074e0e" +checksum = "b28135ecf6b7d446b43e27e225622a038cc4e2930a1022f51cdb97ada19b8e4d" dependencies = [ "bitflags 1.3.2", "byteorder 1.4.3", @@ -1027,9 +1027,9 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" dependencies = [ - "proc-macro2 1.0.29", - "quote 1.0.9", - "syn 1.0.76", + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn 1.0.82", ] [[package]] @@ -1103,7 +1103,7 @@ dependencies = [ "encoding", "lazy_static", "rand 0.4.6", - "time", + "time 0.1.43", "version_check 0.1.5", ] @@ -1173,9 +1173,9 @@ checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" [[package]] name = "encoding_rs" -version = "0.8.28" +version = "0.8.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" +checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746" dependencies = [ "cfg-if 1.0.0", ] @@ -1207,9 +1207,9 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.29", - "quote 1.0.9", - "syn 1.0.76", + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn 1.0.82", "synstructure", ] @@ -1236,9 +1236,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80edafed416a46fb378521624fab1cfa2eb514784fd8921adbe8a8d8321da811" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" dependencies = [ "cfg-if 1.0.0", "crc32fast", @@ -1352,9 +1352,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca" +checksum = "8cd0210d8c325c245ff06fd95a3b13689a1a276ac8cfa8e8720cb840bfb84b9e" dependencies = [ "futures-channel", "futures-core", @@ -1367,9 +1367,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" +checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27" dependencies = [ "futures-core", "futures-sink", @@ -1377,9 +1377,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" +checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445" [[package]] name = "futures-cpupool" @@ -1393,9 +1393,9 @@ dependencies = [ [[package]] name = "futures-executor" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c" +checksum = "7b808bf53348a36cab739d7e04755909b9fcaaa69b7d7e588b37b6ec62704c97" dependencies = [ "futures-core", "futures-task", @@ -1405,42 +1405,39 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" +checksum = "e481354db6b5c353246ccf6a728b0c5511d752c08da7260546fc0933869daa11" [[package]] name = "futures-macro" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" +checksum = "a89f17b21645bc4ed773c69af9c9a0effd4a3f1a3876eadd453469f8854e7fdd" dependencies = [ - "autocfg 1.0.1", - "proc-macro-hack 0.5.19", - "proc-macro2 1.0.29", - "quote 1.0.9", - "syn 1.0.76", + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn 1.0.82", ] [[package]] name = "futures-sink" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11" +checksum = "996c6442437b62d21a32cd9906f9c41e7dc1e19a9579843fad948696769305af" [[package]] name = "futures-task" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99" +checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12" [[package]] name = "futures-util" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481" +checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e" dependencies = [ - "autocfg 1.0.1", "futures-channel", "futures-core", "futures-io", @@ -1450,8 +1447,6 @@ dependencies = [ "memchr", "pin-project-lite 0.2.7", "pin-utils", - "proc-macro-hack 0.5.19", - "proc-macro-nested", "slab", ] @@ -1613,7 +1608,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http 0.2.4", + "http 0.2.5", "indexmap", "slab", "tokio 0.2.25", @@ -1638,7 +1633,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ - "ahash 0.7.4", + "ahash 0.7.6", ] [[package]] @@ -1728,9 +1723,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" +checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" dependencies = [ "bytes 1.1.0", "fnv", @@ -1756,7 +1751,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" dependencies = [ "bytes 0.5.6", - "http 0.2.4", + "http 0.2.5", ] [[package]] @@ -1783,7 +1778,7 @@ dependencies = [ "log 0.3.9", "mime 0.2.6", "num_cpus", - "time", + "time 0.1.43", "traitobject", "typeable", "unicase 1.4.2", @@ -1808,7 +1803,7 @@ dependencies = [ "log 0.4.14", "net2", "rustc_version", - "time", + "time 0.1.43", "tokio 0.1.22", "tokio-buf", "tokio-executor", @@ -1831,7 +1826,7 @@ dependencies = [ "futures-core", "futures-util", "h2 0.2.7", - "http 0.2.4", + "http 0.2.5", "http-body 0.3.1", "httparse", "httpdate", @@ -1930,9 +1925,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if 1.0.0", ] @@ -1978,9 +1973,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "js-sys" -version = "0.3.53" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4bf49d50e2961077d9c99f4b7997d770a1114f087c3c2e0069b36c13fc2979d" +checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" dependencies = [ "wasm-bindgen", ] @@ -2032,7 +2027,7 @@ checksum = "915f14e5fbd72f2f0816dcdbb98b56e7fe6d04dae6ed2c0395133b627aafda9e" dependencies = [ "async-trait", "bytes 0.5.6", - "futures 0.3.17", + "futures 0.3.18", "futures-util", "lazy_static", "lber", @@ -2076,7 +2071,7 @@ dependencies = [ "email", "lettre", "mime 0.3.16", - "time", + "time 0.1.43", "uuid 0.7.4", ] @@ -2101,9 +2096,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.101" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" +checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119" [[package]] name = "libsqlite3-sys" @@ -2374,9 +2369,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c" dependencies = [ "migrations_internals", - "proc-macro2 1.0.29", - "quote 1.0.9", - "syn 1.0.76", + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn 1.0.82", ] [[package]] @@ -2578,9 +2573,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1e25ee6b412c2a1e3fcb6a4499a5c1bfe7f43e014bdce9a6b6666e5aa2d187" +checksum = "f305c2c2e4c39a82f7bf0bf65fb557f9070ce06781d4f2454295cc34b1c43188" dependencies = [ "bitflags 1.3.2", "cc", @@ -2710,9 +2705,9 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "onig" -version = "6.2.0" +version = "6.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16fd3c0e73b516af509c13c4ba76ec0c987ce20d78b38cff356b8d01fc6a6c0" +checksum = "67ddfe2c93bb389eea6e6d713306880c7f6dcc99a75b659ce145d962c861b225" dependencies = [ "bitflags 1.3.2", "lazy_static", @@ -2722,9 +2717,9 @@ dependencies = [ [[package]] name = "onig_sys" -version = "69.7.0" +version = "69.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fd9442a09e4fbd08d196ddf419b2c79a43c3a46c800320cc841d45c2449a240" +checksum = "5dd3eee045c84695b53b20255bb7317063df090b68e18bfac0abb6c39cf7f33e" dependencies = [ "cc", "pkg-config", @@ -2738,9 +2733,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.36" +version = "0.10.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9facdb76fec0b73c406f125d44d86fdad818d66fef0531eec9233ca425ff4a" +checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" dependencies = [ "bitflags 1.3.2", "cfg-if 1.0.0", @@ -2758,9 +2753,9 @@ checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" [[package]] name = "openssl-sys" -version = "0.9.66" +version = "0.9.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1996d2d305e561b70d1ee0c53f1542833f4e1ac6ce9a6708b6ff2738ca67dc82" +checksum = "7df13d165e607909b363a4757a6f133f8a818a74e9d3a98d09c6128e15fa4c73" dependencies = [ "autocfg 1.0.1", "cc", @@ -2834,7 +2829,7 @@ dependencies = [ "instant", "libc", "redox_syscall 0.2.10", - "smallvec 1.6.1", + "smallvec 1.7.0", "winapi 0.3.9", ] @@ -2926,9 +2921,9 @@ version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" dependencies = [ - "proc-macro2 1.0.29", - "quote 1.0.9", - "syn 1.0.76", + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn 1.0.82", ] [[package]] @@ -2951,21 +2946,21 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.19" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" +checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f" [[package]] name = "plist" -version = "1.2.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38d026d73eeaf2ade76309d0c65db5a35ecf649e3cec428db316243ea9d6711" +checksum = "bd39bc6cdc9355ad1dc5eeedefee696bb35c34caf21768741e81826c0bbd7225" dependencies = [ "base64 0.13.0", - "chrono", "indexmap", "line-wrap", "serde 1.0.130", + "time 0.3.5", "xml-rs", ] @@ -3043,6 +3038,7 @@ dependencies = [ "heck", "hex", "hyper 0.12.36", + "once_cell", "openssl", "pulldown-cmark", "regex-syntax 0.6.25", @@ -3137,9 +3133,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" [[package]] name = "pq-sys" @@ -3177,12 +3173,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7be55bf0ae1635f4d7c7ddd6efc05c631e98a82104a73d35550bbc52db960027" -[[package]] -name = "proc-macro-nested" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" - [[package]] name = "proc-macro2" version = "0.2.3" @@ -3212,9 +3202,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.29" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" +checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" dependencies = [ "unicode-xid 0.2.2", ] @@ -3292,11 +3282,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" dependencies = [ - "proc-macro2 1.0.29", + "proc-macro2 1.0.32", ] [[package]] @@ -3643,7 +3633,7 @@ dependencies = [ "serde_json", "serde_urlencoded 0.5.5", "socks", - "time", + "time 0.1.43", "tokio 0.1.22", "tokio-executor", "tokio-io", @@ -3665,7 +3655,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "http 0.2.4", + "http 0.2.5", "http-body 0.3.1", "hyper 0.13.10", "hyper-tls 0.4.3", @@ -3698,7 +3688,7 @@ dependencies = [ "chrono", "config", "dashmap", - "futures 0.3.17", + "futures 0.3.18", "num_cpus", "pin-utils", "rand 0.7.3", @@ -3735,12 +3725,12 @@ dependencies = [ [[package]] name = "rocket" -version = "0.4.6" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fc7e5d6aaa32ace6893ae8a1875688ca7b07d6c2428ae88e704c3623c8866e9" +checksum = "4a7ab1dfdc75bb8bd2be381f37796b1b300c45a3c9145b34d86715e8dd90bf28" dependencies = [ "atty", - "base64 0.12.3", + "base64 0.13.0", "log 0.4.14", "memchr", "num_cpus", @@ -3748,7 +3738,7 @@ dependencies = [ "rocket_codegen", "rocket_http", "state", - "time", + "time 0.1.43", "toml 0.4.10", "version_check 0.9.3", "yansi", @@ -3771,9 +3761,9 @@ dependencies = [ [[package]] name = "rocket_contrib" -version = "0.4.5" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3946ca815127041d8f64455561031d058c22ae1b135251502c5ea523cf9e14b" +checksum = "6b6303dccab46dce6c7ac26c9b9d8d8cde1b19614b027c3f913be6611bff6d9b" dependencies = [ "log 0.4.14", "notify", @@ -3791,7 +3781,7 @@ dependencies = [ "ring", "rocket", "serde 1.0.130", - "time", + "time 0.1.43", ] [[package]] @@ -3805,9 +3795,9 @@ dependencies = [ "indexmap", "pear", "percent-encoding 1.0.1", - "smallvec 1.6.1", + "smallvec 1.7.0", "state", - "time", + "time 0.1.43", "unicode-xid 0.1.0", ] @@ -4015,16 +4005,16 @@ version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" dependencies = [ - "proc-macro2 1.0.29", - "quote 1.0.9", - "syn 1.0.76", + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn 1.0.82", ] [[package]] name = "serde_json" -version = "1.0.67" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f9e390c27c3c0ce8bc5d725f6e4d30a29d26659494aa4b17535f7522c5c950" +checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527" dependencies = [ "itoa", "ryu", @@ -4066,9 +4056,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.6" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9204c41a1597a8c5af23c82d1c921cb01ec0a4c59e07a9c7306062829a3903f3" +checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" dependencies = [ "block-buffer", "cfg-if 1.0.0", @@ -4079,9 +4069,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740223c51853f3145fe7c90360d2d4232f2b62e3449489c207eccde818979982" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" dependencies = [ "lazy_static", ] @@ -4094,9 +4084,9 @@ checksum = "83695fde96cbe9e08f0e4eb96b1b56fdbd44f2098ee27462dda964c7745fddc7" dependencies = [ "bitflags 1.3.2", "itertools 0.8.2", - "proc-macro2 1.0.29", - "quote 1.0.9", - "syn 1.0.76", + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn 1.0.82", ] [[package]] @@ -4107,9 +4097,9 @@ checksum = "e63e6744142336dfb606fe2b068afa2e1cca1ee6a5d8377277a92945d81fa331" dependencies = [ "bitflags 1.3.2", "itertools 0.8.2", - "proc-macro2 1.0.29", - "quote 1.0.9", - "syn 1.0.76", + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn 1.0.82", ] [[package]] @@ -4129,9 +4119,9 @@ checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" [[package]] name = "slab" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" [[package]] name = "slog" @@ -4172,9 +4162,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" [[package]] name = "snap" @@ -4255,8 +4245,8 @@ checksum = "f0f45ed1b65bf9a4bf2f7b7dc59212d1926e9eaf00fa998988e420fd124467c6" dependencies = [ "phf_generator", "phf_shared", - "proc-macro2 1.0.29", - "quote 1.0.9", + "proc-macro2 1.0.32", + "quote 1.0.10", "string_cache_shared", ] @@ -4335,12 +4325,12 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.76" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6f107db402c2c2055242dbf4d2af0e69197202e9faacbef9571bbe47f5a1b84" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" dependencies = [ - "proc-macro2 1.0.29", - "quote 1.0.9", + "proc-macro2 1.0.32", + "quote 1.0.10", "unicode-xid 0.2.2", ] @@ -4355,13 +4345,13 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.12.5" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "474aaa926faa1603c40b7885a9eaea29b444d1cb2850cb7c0e37bb1a4182f4fa" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.29", - "quote 1.0.9", - "syn 1.0.76", + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn 1.0.82", "unicode-xid 0.2.2", ] @@ -4406,7 +4396,7 @@ dependencies = [ "failure", "fnv", "fs2", - "futures 0.3.17", + "futures 0.3.18", "htmlescape", "levenshtein_automata", "log 0.4.14", @@ -4422,7 +4412,7 @@ dependencies = [ "rust-stemmers", "serde 1.0.130", "serde_json", - "smallvec 1.6.1", + "smallvec 1.7.0", "snap", "stable_deref_trait", "tantivy-fst", @@ -4449,7 +4439,7 @@ dependencies = [ "fail", "fnv", "fs2", - "futures 0.3.17", + "futures 0.3.18", "htmlescape", "levenshtein_automata", "log 0.4.14", @@ -4463,7 +4453,7 @@ dependencies = [ "rust-stemmers", "serde 1.0.130", "serde_json", - "smallvec 1.6.1", + "smallvec 1.7.0", "snap", "stable_deref_trait", "tantivy-fst", @@ -4566,22 +4556,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.29" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.29" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ - "proc-macro2 1.0.29", - "quote 1.0.9", - "syn 1.0.76", + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn 1.0.82", ] [[package]] @@ -4603,6 +4593,16 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "time" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41effe7cfa8af36f439fac33861b66b049edc6f9a32331e2312660529c1c24ad" +dependencies = [ + "itoa", + "libc", +] + [[package]] name = "tiny-keccak" version = "2.0.2" @@ -4614,9 +4614,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.3.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "848a1e1181b9f6753b5e96a092749e29b11d19ede67dfbbd6c7dc7e0f49b5338" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" dependencies = [ "tinyvec_macros", ] @@ -4745,9 +4745,9 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a" dependencies = [ - "proc-macro2 1.0.29", - "quote 1.0.9", - "syn 1.0.76", + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn 1.0.82", ] [[package]] @@ -4915,9 +4915,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.26" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d" +checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ "cfg-if 1.0.0", "log 0.4.14", @@ -4928,20 +4928,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.15" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2" +checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" dependencies = [ - "proc-macro2 1.0.29", - "quote 1.0.9", - "syn 1.0.76", + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn 1.0.82", ] [[package]] name = "tracing-core" -version = "0.1.19" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ca517f43f0fb96e0c3072ed5c275fe5eece87e8cb52f4a77b69226d3b1c9df8" +checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" dependencies = [ "lazy_static", ] @@ -4979,9 +4979,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.2.20" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9cbe87a2fa7e35900ce5de20220a582a9483a7063811defce79d7cbd59d4cfe" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" dependencies = [ "ansi_term 0.12.1", "chrono", @@ -4991,7 +4991,7 @@ dependencies = [ "serde 1.0.130", "serde_json", "sharded-slab", - "smallvec 1.6.1", + "smallvec 1.7.0", "thread_local", "tracing", "tracing-core", @@ -5061,9 +5061,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246f4c42e67e7a4e3c6106ff716a5d067d4132a642840b242e357e468a2a0085" +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" [[package]] name = "unicode-normalization" @@ -5082,9 +5082,9 @@ checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" [[package]] name = "unicode-width" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "unicode-xid" @@ -5280,9 +5280,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.76" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce9b1b516211d33767048e5d47fa2a381ed8b76fc48d2ce4aa39877f9f183e0" +checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" dependencies = [ "cfg-if 1.0.0", "serde 1.0.130", @@ -5292,24 +5292,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.76" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe8dc78e2326ba5f845f4b5bf548401604fa20b1dd1d365fb73b6c1d6364041" +checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" dependencies = [ "bumpalo", "lazy_static", "log 0.4.14", - "proc-macro2 1.0.29", - "quote 1.0.9", - "syn 1.0.76", + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn 1.0.82", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.26" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fded345a6559c2cfee778d562300c581f7d4ff3edb9b0d230d69800d213972" +checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -5319,38 +5319,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.76" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44468aa53335841d9d6b6c023eaab07c0cd4bddbcfdee3e2bb1e8d2cb8069fef" +checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" dependencies = [ - "quote 1.0.9", + "quote 1.0.10", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.76" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0195807922713af1e67dc66132c7328206ed9766af3858164fb583eedc25fbad" +checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" dependencies = [ - "proc-macro2 1.0.29", - "quote 1.0.9", - "syn 1.0.76", + "proc-macro2 1.0.32", + "quote 1.0.10", + "syn 1.0.82", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.76" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdb075a845574a1fa5f09fd77e43f7747599301ea3417a9fbffdeedfc1f4a29" +checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" [[package]] name = "web-sys" -version = "0.3.53" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224b2f6b67919060055ef1a67807367c2066ed520c3862cc013d26cf893a783c" +checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" dependencies = [ "js-sys", "wasm-bindgen", @@ -5479,9 +5479,9 @@ checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" [[package]] name = "yada" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd411f1634003c5ec3ebd98534a3c8b98b1dc8939cdeb63208ba338f20f2cfb" +checksum = "c87bb6793d892781be4f1f8d420d6a75bc2e80b3cb365dfa7efad337f50871a5" [[package]] name = "yaml-rust" diff --git a/Cargo.toml b/Cargo.toml index 4a31f7a0..41d6d163 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,13 +18,13 @@ guid-create = "0.1" lettre = "0.9.2" lettre_email = "0.9.2" num_cpus = "1.10" -rocket = "=0.4.6" -rocket_contrib = { version = "=0.4.5", features = ["json"] } +rocket = "0.4.6" +rocket_contrib = { version = "0.4.5", features = ["json"] } rocket_i18n = { git = "https://github.com/Plume-org/rocket_i18n", rev = "e922afa7c366038b3433278c03b1456b346074f2" } rpassword = "4.0" scheduled-thread-pool = "0.2.2" serde = "1.0" -serde_json = "< 1.0.70" +serde_json = "1.0.70" shrinkwraprs = "0.2.1" validator = "0.8" validator_derive = "0.8" diff --git a/assets/themes/default/_global.scss b/assets/themes/default/_global.scss index 35380919..867dffe7 100644 --- a/assets/themes/default/_global.scss +++ b/assets/themes/default/_global.scss @@ -229,6 +229,10 @@ p.error { opacity: 0.9; } } + + header { + display: flex; + } h3 { flex-grow: 1; @@ -236,9 +240,9 @@ p.error { font-family: $playfair; font-size: 1.75em; font-weight: normal; - line-height: 1.75; + line-height: 1.10; display: inline-block; - position: absolute; + position: relative; a { display: block; transition: color 0.1s ease-in; @@ -249,6 +253,7 @@ p.error { } .controls { + flex-shrink: 0; text-align: end; .button { diff --git a/build.rs b/build.rs index d9ba2568..98ca35de 100644 --- a/build.rs +++ b/build.rs @@ -41,9 +41,9 @@ fn main() { .expect("compile templates"); compile_themes().expect("Theme compilation error"); - recursive_copy(&Path::new("assets").join("icons"), &Path::new("static")) + recursive_copy(&Path::new("assets").join("icons"), Path::new("static")) .expect("Couldn't copy icons"); - recursive_copy(&Path::new("assets").join("images"), &Path::new("static")) + recursive_copy(&Path::new("assets").join("images"), Path::new("static")) .expect("Couldn't copy images"); create_dir_all(&Path::new("static").join("media")).expect("Couldn't init media directory"); @@ -97,12 +97,12 @@ fn compile_theme(path: &Path, out_dir: &Path) -> std::io::Result<()> { .components() .skip_while(|c| *c != Component::Normal(OsStr::new("themes"))) .skip(1) - .filter_map(|c| { + .map(|c| { c.as_os_str() .to_str() .unwrap_or_default() - .splitn(2, '.') - .next() + .split_once('.') + .map_or(c.as_os_str().to_str().unwrap_or_default(), |x| x.0) }) .collect::>() .join("-"); diff --git a/plume-cli/src/instance.rs b/plume-cli/src/instance.rs index 8fa48060..35793639 100644 --- a/plume-cli/src/instance.rs +++ b/plume-cli/src/instance.rs @@ -68,4 +68,6 @@ fn new<'a>(args: &ArgMatches<'a>, conn: &Connection) { }, ) .expect("Couldn't save instance"); + Instance::cache_local(conn); + Instance::create_local_instance_user(conn).expect("Couldn't save local instance user"); } diff --git a/plume-cli/src/main.rs b/plume-cli/src/main.rs index 35248a32..3615c10d 100644 --- a/plume-cli/src/main.rs +++ b/plume-cli/src/main.rs @@ -25,7 +25,7 @@ fn main() { e => e.map(|_| ()).unwrap(), } let conn = Conn::establish(CONFIG.database_url.as_str()); - let _ = conn.as_ref().map(|conn| Instance::cache_local(conn)); + let _ = conn.as_ref().map(Instance::cache_local); match matches.subcommand() { ("instance", Some(args)) => { diff --git a/plume-common/Cargo.toml b/plume-common/Cargo.toml index c9eca0c9..a67f748e 100644 --- a/plume-common/Cargo.toml +++ b/plume-common/Cargo.toml @@ -14,11 +14,11 @@ heck = "0.3.0" hex = "0.3" hyper = "0.12.33" openssl = "0.10.22" -rocket = "=0.4.6" +rocket = "0.4.6" reqwest = { version = "0.9", features = ["socks"] } serde = "1.0" serde_derive = "1.0" -serde_json = "< 1.0.70" +serde_json = "1.0.70" shrinkwraprs = "0.3.0" syntect = "4.5.0" tokio = "0.1.22" @@ -33,3 +33,6 @@ version = "0.4" default-features = false git = "https://git.joinplu.me/Plume/pulldown-cmark" branch = "bidi-plume" + +[dev-dependencies] +once_cell = "1.5.2" diff --git a/plume-common/src/activity_pub/inbox.rs b/plume-common/src/activity_pub/inbox.rs index 5215c520..48ba6c5f 100644 --- a/plume-common/src/activity_pub/inbox.rs +++ b/plume-common/src/activity_pub/inbox.rs @@ -1,6 +1,8 @@ -use reqwest::header::{HeaderValue, ACCEPT}; +use reqwest; use std::fmt::Debug; +use super::{request, sign::Signer}; + /// Represents an ActivityPub inbox. /// /// It routes an incoming Activity through the registered handlers. @@ -10,7 +12,50 @@ use std::fmt::Debug; /// ```rust /// # extern crate activitypub; /// # use activitypub::{actor::Person, activity::{Announce, Create}, object::Note}; +/// # use openssl::{hash::MessageDigest, pkey::PKey, rsa::Rsa}; +/// # use once_cell::sync::Lazy; /// # use plume_common::activity_pub::inbox::*; +/// # use plume_common::activity_pub::sign::{gen_keypair, Error as SignError, Result as SignResult, Signer}; +/// # +/// # static MY_SIGNER: Lazy = Lazy::new(|| MySigner::new()); +/// # +/// # struct MySigner { +/// # public_key: String, +/// # private_key: String, +/// # } +/// # +/// # impl MySigner { +/// # fn new() -> Self { +/// # let (pub_key, priv_key) = gen_keypair(); +/// # Self { +/// # public_key: String::from_utf8(pub_key).unwrap(), +/// # private_key: String::from_utf8(priv_key).unwrap(), +/// # } +/// # } +/// # } +/// # +/// # impl Signer for MySigner { +/// # fn get_key_id(&self) -> String { +/// # "mysigner".into() +/// # } +/// # +/// # fn sign(&self, to_sign: &str) -> SignResult> { +/// # let key = PKey::from_rsa(Rsa::private_key_from_pem(self.private_key.as_ref()).unwrap()) +/// # .unwrap(); +/// # let mut signer = openssl::sign::Signer::new(MessageDigest::sha256(), &key).unwrap(); +/// # signer.update(to_sign.as_bytes()).unwrap(); +/// # signer.sign_to_vec().map_err(|_| SignError()) +/// # } +/// # +/// # fn verify(&self, data: &str, signature: &[u8]) -> SignResult { +/// # let key = PKey::from_rsa(Rsa::public_key_from_pem(self.public_key.as_ref()).unwrap()) +/// # .unwrap(); +/// # let mut verifier = openssl::sign::Verifier::new(MessageDigest::sha256(), &key).unwrap(); +/// # verifier.update(data.as_bytes()).unwrap(); +/// # verifier.verify(&signature).map_err(|_| SignError()) +/// # } +/// # } +/// # /// # struct User; /// # impl FromId<()> for User { /// # type Error = (); @@ -23,6 +68,10 @@ use std::fmt::Debug; /// # fn from_activity(_: &(), obj: Person) -> Result { /// # Ok(User) /// # } +/// # +/// # fn get_sender() -> &'static dyn Signer { +/// # &*MY_SIGNER +/// # } /// # } /// # impl AsActor<&()> for User { /// # fn get_inbox_url(&self) -> String { @@ -42,6 +91,10 @@ use std::fmt::Debug; /// # fn from_activity(_: &(), obj: Note) -> Result { /// # Ok(Message) /// # } +/// # +/// # fn get_sender() -> &'static dyn Signer { +/// # &*MY_SIGNER +/// # } /// # } /// # impl AsObject for Message { /// # type Error = (); @@ -207,7 +260,7 @@ where }; // Handle the activity - match obj.activity(ctx, actor, &act_id) { + match obj.activity(ctx, actor, act_id) { Ok(res) => Inbox::Handled(res.into()), Err(e) => Inbox::Failed(e), } @@ -311,35 +364,16 @@ pub trait FromId: Sized { id: &str, proxy: Option, ) -> Result, Self::Error)> { - if let Some(proxy) = proxy { - reqwest::ClientBuilder::new().proxy(proxy) - } else { - reqwest::ClientBuilder::new() - } - .connect_timeout(Some(std::time::Duration::from_secs(5))) - .build() - .map_err(|_| (None, InboxError::DerefError.into()))? - .get(id) - .header( - ACCEPT, - HeaderValue::from_str( - &super::ap_accept_header() - .into_iter() - .collect::>() - .join(", "), - ) - .map_err(|_| (None, InboxError::DerefError.into()))?, - ) - .send() - .map_err(|_| (None, InboxError::DerefError)) - .and_then(|mut r| { - let json: serde_json::Value = r - .json() - .map_err(|_| (None, InboxError::InvalidObject(None)))?; - serde_json::from_value(json.clone()) - .map_err(|_| (Some(json), InboxError::InvalidObject(None))) - }) - .map_err(|(json, e)| (json, e.into())) + request::get(id, Self::get_sender(), proxy) + .map_err(|_| (None, InboxError::DerefError)) + .and_then(|mut r| { + let json: serde_json::Value = r + .json() + .map_err(|_| (None, InboxError::InvalidObject(None)))?; + serde_json::from_value(json.clone()) + .map_err(|_| (Some(json), InboxError::InvalidObject(None))) + }) + .map_err(|(json, e)| (json, e.into())) } /// Builds a `Self` from its ActivityPub representation @@ -347,6 +381,8 @@ pub trait FromId: Sized { /// Tries to find a `Self` with a given ID (`id`), using `ctx` (a database) fn from_db(ctx: &C, id: &str) -> Result; + + fn get_sender() -> &'static dyn Signer; } /// Should be implemented by anything representing an ActivityPub actor. @@ -385,6 +421,49 @@ pub trait AsActor { /// # extern crate activitypub; /// # use activitypub::{activity::Create, actor::Person, object::Note}; /// # use plume_common::activity_pub::inbox::{AsActor, AsObject, FromId}; +/// # use plume_common::activity_pub::sign::{gen_keypair, Error as SignError, Result as SignResult, Signer}; +/// # use openssl::{hash::MessageDigest, pkey::PKey, rsa::Rsa}; +/// # use once_cell::sync::Lazy; +/// # +/// # static MY_SIGNER: Lazy = Lazy::new(|| MySigner::new()); +/// # +/// # struct MySigner { +/// # public_key: String, +/// # private_key: String, +/// # } +/// # +/// # impl MySigner { +/// # fn new() -> Self { +/// # let (pub_key, priv_key) = gen_keypair(); +/// # Self { +/// # public_key: String::from_utf8(pub_key).unwrap(), +/// # private_key: String::from_utf8(priv_key).unwrap(), +/// # } +/// # } +/// # } +/// # +/// # impl Signer for MySigner { +/// # fn get_key_id(&self) -> String { +/// # "mysigner".into() +/// # } +/// # +/// # fn sign(&self, to_sign: &str) -> SignResult> { +/// # let key = PKey::from_rsa(Rsa::private_key_from_pem(self.private_key.as_ref()).unwrap()) +/// # .unwrap(); +/// # let mut signer = openssl::sign::Signer::new(MessageDigest::sha256(), &key).unwrap(); +/// # signer.update(to_sign.as_bytes()).unwrap(); +/// # signer.sign_to_vec().map_err(|_| SignError()) +/// # } +/// # +/// # fn verify(&self, data: &str, signature: &[u8]) -> SignResult { +/// # let key = PKey::from_rsa(Rsa::public_key_from_pem(self.public_key.as_ref()).unwrap()) +/// # .unwrap(); +/// # let mut verifier = openssl::sign::Verifier::new(MessageDigest::sha256(), &key).unwrap(); +/// # verifier.update(data.as_bytes()).unwrap(); +/// # verifier.verify(&signature).map_err(|_| SignError()) +/// # } +/// # } +/// # /// # struct Account; /// # impl FromId<()> for Account { /// # type Error = (); @@ -397,6 +476,10 @@ pub trait AsActor { /// # fn from_activity(_: &(), obj: Person) -> Result { /// # Ok(Account) /// # } +/// # +/// # fn get_sender() -> &'static dyn Signer { +/// # &*MY_SIGNER +/// # } /// # } /// # impl AsActor<()> for Account { /// # fn get_inbox_url(&self) -> String { @@ -420,6 +503,10 @@ pub trait AsActor { /// fn from_activity(_: &(), obj: Note) -> Result { /// Ok(Message { text: obj.object_props.content_string().map_err(|_| ())? }) /// } +/// +/// fn get_sender() -> &'static dyn Signer { +/// &*MY_SIGNER +/// } /// } /// /// impl AsObject for Message { @@ -459,7 +546,51 @@ where #[cfg(test)] mod tests { use super::*; + use crate::activity_pub::sign::{ + gen_keypair, Error as SignError, Result as SignResult, Signer, + }; use activitypub::{activity::*, actor::Person, object::Note}; + use once_cell::sync::Lazy; + use openssl::{hash::MessageDigest, pkey::PKey, rsa::Rsa}; + + static MY_SIGNER: Lazy = Lazy::new(|| MySigner::new()); + + struct MySigner { + public_key: String, + private_key: String, + } + + impl MySigner { + fn new() -> Self { + let (pub_key, priv_key) = gen_keypair(); + Self { + public_key: String::from_utf8(pub_key).unwrap(), + private_key: String::from_utf8(priv_key).unwrap(), + } + } + } + + impl Signer for MySigner { + fn get_key_id(&self) -> String { + "mysigner".into() + } + + fn sign(&self, to_sign: &str) -> SignResult> { + let key = PKey::from_rsa(Rsa::private_key_from_pem(self.private_key.as_ref()).unwrap()) + .unwrap(); + let mut signer = openssl::sign::Signer::new(MessageDigest::sha256(), &key).unwrap(); + signer.update(to_sign.as_bytes()).unwrap(); + signer.sign_to_vec().map_err(|_| SignError()) + } + + fn verify(&self, data: &str, signature: &[u8]) -> SignResult { + let key = PKey::from_rsa(Rsa::public_key_from_pem(self.public_key.as_ref()).unwrap()) + .unwrap(); + let mut verifier = openssl::sign::Verifier::new(MessageDigest::sha256(), &key).unwrap(); + verifier.update(data.as_bytes()).unwrap(); + verifier.verify(&signature).map_err(|_| SignError()) + } + } struct MyActor; impl FromId<()> for MyActor { @@ -473,6 +604,10 @@ mod tests { fn from_activity(_: &(), _obj: Person) -> Result { Ok(MyActor) } + + fn get_sender() -> &'static dyn Signer { + &*MY_SIGNER + } } impl AsActor<&()> for MyActor { @@ -497,6 +632,10 @@ mod tests { fn from_activity(_: &(), _obj: Note) -> Result { Ok(MyObject) } + + fn get_sender() -> &'static dyn Signer { + &*MY_SIGNER + } } impl AsObject for MyObject { type Error = (); @@ -601,6 +740,10 @@ mod tests { fn from_activity(_: &(), _obj: Person) -> Result { Err(()) } + + fn get_sender() -> &'static dyn Signer { + &*MY_SIGNER + } } impl AsActor<&()> for FailingActor { fn get_inbox_url(&self) -> String { diff --git a/plume-common/src/activity_pub/mod.rs b/plume-common/src/activity_pub/mod.rs index 3e94207e..23b2b5f4 100644 --- a/plume-common/src/activity_pub/mod.rs +++ b/plume-common/src/activity_pub/mod.rs @@ -145,7 +145,7 @@ where warn!("Inbox doesn't have host: {:?}", &inbox); continue; }; - let host_header_value = HeaderValue::from_str(&url.host_str().expect("Unreachable")); + let host_header_value = HeaderValue::from_str(url.host_str().expect("Unreachable")); if host_header_value.is_err() { warn!("Header value is invalid: {:?}", url.host_str()); continue; diff --git a/plume-common/src/activity_pub/request.rs b/plume-common/src/activity_pub/request.rs index 73e6d6ee..4258bd7b 100644 --- a/plume-common/src/activity_pub/request.rs +++ b/plume-common/src/activity_pub/request.rs @@ -1,6 +1,11 @@ use chrono::{offset::Utc, DateTime}; use openssl::hash::{Hasher, MessageDigest}; -use reqwest::header::{HeaderMap, HeaderValue, ACCEPT, CONTENT_TYPE, DATE, USER_AGENT}; +use reqwest::{ + header::{ + HeaderMap, HeaderValue, InvalidHeaderValue, ACCEPT, CONTENT_TYPE, DATE, HOST, USER_AGENT, + }, + ClientBuilder, Proxy, Response, Url, UrlError, +}; use std::ops::Deref; use std::time::SystemTime; use tracing::warn; @@ -13,6 +18,24 @@ const PLUME_USER_AGENT: &str = concat!("Plume/", env!("CARGO_PKG_VERSION")); #[derive(Debug)] pub struct Error(); +impl From for Error { + fn from(_err: UrlError) -> Self { + Error() + } +} + +impl From for Error { + fn from(_err: InvalidHeaderValue) -> Self { + Error() + } +} + +impl From for Error { + fn from(_err: reqwest::Error) -> Self { + Error() + } +} + pub struct Digest(String); impl Digest { @@ -118,8 +141,8 @@ type Path<'a> = &'a str; type Query<'a> = &'a str; type RequestTarget<'a> = (Method<'a>, Path<'a>, Option>); -pub fn signature( - signer: &S, +pub fn signature( + signer: &dyn Signer, headers: &HeaderMap, request_target: RequestTarget, ) -> Result { @@ -164,10 +187,35 @@ pub fn signature( )).map_err(|_| Error()) } +pub fn get(url_str: &str, sender: &dyn Signer, proxy: Option) -> Result { + let mut headers = headers(); + let url = Url::parse(url_str)?; + if !url.has_host() { + return Err(Error()); + } + let host_header_value = HeaderValue::from_str(url.host_str().expect("Unreachable"))?; + headers.insert(HOST, host_header_value); + if let Some(proxy) = proxy { + ClientBuilder::new().proxy(proxy) + } else { + ClientBuilder::new() + } + .connect_timeout(Some(std::time::Duration::from_secs(5))) + .build()? + .get(url_str) + .headers(headers.clone()) + .header( + "Signature", + signature(sender, &headers, ("get", url.path(), url.query()))?, + ) + .send() + .map_err(|_| Error()) +} + #[cfg(test)] mod tests { - use super::{signature, Error}; - use crate::activity_pub::sign::{gen_keypair, Signer}; + use super::signature; + use crate::activity_pub::sign::{gen_keypair, Error, Result, Signer}; use openssl::{hash::MessageDigest, pkey::PKey, rsa::Rsa}; use reqwest::header::HeaderMap; @@ -187,13 +235,11 @@ mod tests { } impl Signer for MySigner { - type Error = Error; - fn get_key_id(&self) -> String { "mysigner".into() } - fn sign(&self, to_sign: &str) -> Result, Self::Error> { + fn sign(&self, to_sign: &str) -> Result> { let key = PKey::from_rsa(Rsa::private_key_from_pem(self.private_key.as_ref()).unwrap()) .unwrap(); let mut signer = openssl::sign::Signer::new(MessageDigest::sha256(), &key).unwrap(); @@ -201,7 +247,7 @@ mod tests { signer.sign_to_vec().map_err(|_| Error()) } - fn verify(&self, data: &str, signature: &[u8]) -> Result { + fn verify(&self, data: &str, signature: &[u8]) -> Result { let key = PKey::from_rsa(Rsa::public_key_from_pem(self.public_key.as_ref()).unwrap()) .unwrap(); let mut verifier = openssl::sign::Verifier::new(MessageDigest::sha256(), &key).unwrap(); diff --git a/plume-common/src/activity_pub/sign.rs b/plume-common/src/activity_pub/sign.rs index a6bb5899..22aaf9d6 100644 --- a/plume-common/src/activity_pub/sign.rs +++ b/plume-common/src/activity_pub/sign.rs @@ -19,20 +19,25 @@ pub fn gen_keypair() -> (Vec, Vec) { #[derive(Debug)] pub struct Error(); +pub type Result = std::result::Result; + +impl From for Error { + fn from(_: openssl::error::ErrorStack) -> Self { + Self() + } +} pub trait Signer { - type Error; - fn get_key_id(&self) -> String; /// Sign some data with the signer keypair - fn sign(&self, to_sign: &str) -> Result, Self::Error>; + fn sign(&self, to_sign: &str) -> Result>; /// Verify if the signature is valid - fn verify(&self, data: &str, signature: &[u8]) -> Result; + fn verify(&self, data: &str, signature: &[u8]) -> Result; } pub trait Signable { - fn sign(&mut self, creator: &T) -> Result<&mut Self, Error> + fn sign(&mut self, creator: &T) -> Result<&mut Self> where T: Signer; fn verify(self, creator: &T) -> bool @@ -46,7 +51,7 @@ pub trait Signable { } impl Signable for serde_json::Value { - fn sign(&mut self, creator: &T) -> Result<&mut serde_json::Value, Error> { + fn sign(&mut self, creator: &T) -> Result<&mut serde_json::Value> { let creation_date = Utc::now().to_rfc3339(); let mut options = json!({ "type": "RsaSignature2017", @@ -182,7 +187,7 @@ pub fn verify_http_headers( } let digest = all_headers.get_one("digest").unwrap_or(""); let digest = request::Digest::from_header(digest); - if !digest.map(|d| d.verify_header(&data)).unwrap_or(false) { + if !digest.map(|d| d.verify_header(data)).unwrap_or(false) { // signature was valid, but body content does not match its digest return SignatureValidity::Invalid; } diff --git a/plume-common/src/utils.rs b/plume-common/src/utils.rs index 896b1386..4bb23c85 100644 --- a/plume-common/src/utils.rs +++ b/plume-common/src/utils.rs @@ -141,13 +141,13 @@ fn highlight_code<'a>( unreachable!(); }; let syntax_set = SyntaxSet::load_defaults_newlines(); - let syntax = syntax_set.find_syntax_by_token(&lang).unwrap_or_else(|| { + let syntax = syntax_set.find_syntax_by_token(lang).unwrap_or_else(|| { syntax_set - .find_syntax_by_name(&lang) + .find_syntax_by_name(lang) .unwrap_or_else(|| syntax_set.find_syntax_plain_text()) }); let mut html = ClassedHTMLGenerator::new_with_class_style( - &syntax, + syntax, &syntax_set, ClassStyle::Spaced, ); @@ -334,16 +334,15 @@ pub fn md_to_html<'a>( text_acc.push(c) } let mention = text_acc; - let short_mention = mention.splitn(1, '@').next().unwrap_or(""); let link = Tag::Link( LinkType::Inline, format!("{}@/{}/", base_url, &mention).into(), - short_mention.to_owned().into(), + mention.clone().into(), ); mentions.push(mention.clone()); events.push(Event::Start(link.clone())); - events.push(Event::Text(format!("@{}", &short_mention).into())); + events.push(Event::Text(format!("@{}", &mention).into())); events.push(Event::End(link)); ( diff --git a/plume-front/src/editor.rs b/plume-front/src/editor.rs index 8d0f2a81..1bb2e934 100644 --- a/plume-front/src/editor.rs +++ b/plume-front/src/editor.rs @@ -54,11 +54,6 @@ pub enum EditorError { DOMError, } -impl From for EditorError { - fn from(_: std::option::NoneError) -> Self { - EditorError::NoneError - } -} const AUTOSAVE_DEBOUNCE_TIME: i32 = 5000; #[derive(Serialize, Deserialize)] struct AutosaveInformation { @@ -198,7 +193,7 @@ fn clear_autosave() { .unwrap() .remove_item(&get_autosave_id()) .unwrap(); - console::log_1(&&format!("Saved to {}", &get_autosave_id()).into()); + console::log_1(&format!("Saved to {}", &get_autosave_id()).into()); } type TimeoutHandle = i32; lazy_static! { @@ -366,7 +361,9 @@ fn init_editor() -> Result<(), EditorError> { return Ok(()); } let old_ed = old_ed.unwrap(); - let old_title = document().get_element_by_id("plume-editor-title")?; + let old_title = document() + .get_element_by_id("plume-editor-title") + .ok_or(EditorError::NoneError)?; old_ed .dyn_ref::() .unwrap() @@ -434,7 +431,8 @@ fn init_editor() -> Result<(), EditorError> { bg.class_list().add_1("show").unwrap(); })) as Box); document() - .get_element_by_id("publish")? + .get_element_by_id("publish") + .ok_or(EditorError::NoneError)? .add_event_listener_with_callback("click", show_popup.as_ref().unchecked_ref()) .map_err(|_| EditorError::DOMError)?; show_popup.forget(); @@ -528,8 +526,14 @@ fn init_popup( cover_label .set_attribute("for", "cover") .map_err(|_| EditorError::DOMError)?; - let cover = document.get_element_by_id("cover")?; - cover.parent_element()?.remove_child(&cover).ok(); + let cover = document + .get_element_by_id("cover") + .ok_or(EditorError::NoneError)?; + cover + .parent_element() + .ok_or(EditorError::NoneError)? + .remove_child(&cover) + .ok(); popup .append_child(&cover_label) .map_err(|_| EditorError::DOMError)?; @@ -554,7 +558,7 @@ fn init_popup( draft.set_checked(draft_checkbox.checked()); draft_label - .append_child(&draft) + .append_child(draft) .map_err(|_| EditorError::DOMError)?; draft_label .append_child(&document.create_text_node(&i18n!(CATALOG, "This is a draft"))) @@ -620,11 +624,12 @@ fn init_popup( .map_err(|_| EditorError::DOMError)?; callback.forget(); popup - .append_child(&button) + .append_child(button) .map_err(|_| EditorError::DOMError)?; document - .body()? + .body() + .ok_or(EditorError::NoneError)? .append_child(&popup) .map_err(|_| EditorError::DOMError)?; Ok(popup) @@ -641,7 +646,8 @@ fn init_popup_bg() -> Result { .map_err(|_| EditorError::DOMError)?; document() - .body()? + .body() + .ok_or(EditorError::NoneError)? .append_child(&bg) .map_err(|_| EditorError::DOMError)?; let callback = Closure::wrap(Box::new(|_| close_popup()) as Box); diff --git a/plume-front/src/lib.rs b/plume-front/src/lib.rs index ecaf1d2c..ce81d2fb 100755 --- a/plume-front/src/lib.rs +++ b/plume-front/src/lib.rs @@ -1,5 +1,5 @@ #![recursion_limit = "128"] -#![feature(decl_macro, proc_macro_hygiene, try_trait)] +#![feature(decl_macro, proc_macro_hygiene)] #[macro_use] extern crate gettext_macros; @@ -61,7 +61,7 @@ lazy_static! { static ref CATALOG: gettext::Catalog = { let catalogs = include_i18n!(); let lang = window().unwrap().navigator().language().unwrap(); - let lang = lang.splitn(2, '-').next().unwrap_or("en"); + let lang = lang.split_once('-').map_or("en", |x| x.0); let english_position = catalogs .iter() @@ -85,7 +85,7 @@ pub fn main() -> Result<(), JsValue> { menu(); search(); editor::init() - .map_err(|e| console::error_1(&&format!("Editor error: {:?}", e).into())) + .map_err(|e| console::error_1(&format!("Editor error: {:?}", e).into())) .ok(); Ok(()) } diff --git a/plume-macro/src/lib.rs b/plume-macro/src/lib.rs index deea688b..b4d20cdd 100755 --- a/plume-macro/src/lib.rs +++ b/plume-macro/src/lib.rs @@ -58,7 +58,7 @@ pub fn import_migrations(input: TokenStream) -> TokenStream { (name, up_sql, down_sql) }) .collect::>(); - let migrations_name = migrations.iter().map(|m| &m.0).collect::>(); + let migrations_name = migrations.iter().map(|m| &m.0); let migrations_up = migrations .iter() .map(|m| m.1.as_str()) @@ -103,7 +103,7 @@ fn file_to_migration(file: &str) -> TokenStream2 { acc.push('\n'); } } else if let Some(acc_str) = line.strip_prefix("--#!") { - acc.push_str(&acc_str); + acc.push_str(acc_str); acc.push('\n'); } else if line.starts_with("--") { continue; diff --git a/plume-models/Cargo.toml b/plume-models/Cargo.toml index 883c6b6a..9afdcf8a 100644 --- a/plume-models/Cargo.toml +++ b/plume-models/Cargo.toml @@ -15,13 +15,13 @@ lazy_static = "1.0" ldap3 = "0.7.1" migrations_internals= "1.4.0" openssl = "0.10.22" -rocket = "=0.4.6" +rocket = "0.4.6" rocket_i18n = { git = "https://github.com/Plume-org/rocket_i18n", rev = "e922afa7c366038b3433278c03b1456b346074f2" } reqwest = "0.9" scheduled-thread-pool = "0.2.2" serde = "1.0" serde_derive = "1.0" -serde_json = "< 1.0.70" +serde_json = "1.0.70" tantivy = "0.13.3" url = "2.1" walkdir = "2.2" diff --git a/plume-models/src/api_tokens.rs b/plume-models/src/api_tokens.rs index 5e2eca07..dfff4135 100644 --- a/plume-models/src/api_tokens.rs +++ b/plume-models/src/api_tokens.rs @@ -86,14 +86,18 @@ impl<'a, 'r> FromRequest<'a, 'r> for ApiToken { } let mut parsed_header = headers[0].split(' '); - let auth_type = parsed_header.next().map_or_else( - || Outcome::Failure((Status::BadRequest, TokenError::NoType)), - Outcome::Success, - )?; - let val = parsed_header.next().map_or_else( - || Outcome::Failure((Status::BadRequest, TokenError::NoValue)), - Outcome::Success, - )?; + let auth_type = parsed_header + .next() + .map_or_else::, _, _>( + || Outcome::Failure((Status::BadRequest, TokenError::NoType)), + Outcome::Success, + )?; + let val = parsed_header + .next() + .map_or_else::, _, _>( + || Outcome::Failure((Status::BadRequest, TokenError::NoValue)), + Outcome::Success, + )?; if auth_type == "Bearer" { let conn = request diff --git a/plume-models/src/blocklisted_emails.rs b/plume-models/src/blocklisted_emails.rs index 4f396b1a..3d9928b3 100644 --- a/plume-models/src/blocklisted_emails.rs +++ b/plume-models/src/blocklisted_emails.rs @@ -28,7 +28,7 @@ impl BlocklistedEmail { pub fn delete_entries(conn: &Connection, ids: Vec) -> Result { use diesel::delete; for i in ids { - let be: BlocklistedEmail = BlocklistedEmail::find_by_id(&conn, i)?; + let be: BlocklistedEmail = BlocklistedEmail::find_by_id(conn, i)?; delete(&be).execute(conn)?; } Ok(true) diff --git a/plume-models/src/blogs.rs b/plume-models/src/blogs.rs index bf2a8ad5..9d0839ae 100644 --- a/plume-models/src/blogs.rs +++ b/plume-models/src/blogs.rs @@ -149,7 +149,15 @@ impl Blog { .into_iter() .find(|l| l.mime_type == Some(String::from("application/activity+json"))) .ok_or(Error::Webfinger) - .and_then(|l| Blog::from_id(conn, &l.href?, None, CONFIG.proxy()).map_err(|(_, e)| e)) + .and_then(|l| { + Blog::from_id( + conn, + &l.href.ok_or(Error::MissingApProperty)?, + None, + CONFIG.proxy(), + ) + .map_err(|(_, e)| e) + }) } pub fn to_activity(&self, conn: &Connection) -> Result { @@ -236,7 +244,7 @@ impl Blog { (min, max): (i32, i32), ) -> Result> { let mut coll = OrderedCollectionPage::default(); - let acts = self.get_activity_page(&conn, (min, max)); + let acts = self.get_activity_page(conn, (min, max)); //This still doesn't do anything because the outbox //doesn't do anything yet coll.collection_page_props.set_next_link(Id::new(&format!( @@ -265,7 +273,10 @@ impl Blog { pub fn get_keypair(&self) -> Result> { PKey::from_rsa(Rsa::private_key_from_pem( - self.private_key.clone()?.as_ref(), + self.private_key + .clone() + .ok_or(Error::MissingApProperty)? + .as_ref(), )?) .map_err(Error::from) } @@ -318,7 +329,7 @@ impl Blog { } pub fn delete(&self, conn: &Connection) -> Result<()> { - for post in Post::get_for_blog(conn, &self)? { + for post in Post::get_for_blog(conn, self)? { post.delete(conn)?; } diesel::delete(self) @@ -339,12 +350,12 @@ impl FromId for Blog { type Object = CustomGroup; fn from_db(conn: &DbConn, id: &str) -> Result { - Self::find_by_ap_url(&conn, id) + Self::find_by_ap_url(conn, id) } fn from_activity(conn: &DbConn, acct: CustomGroup) -> Result { let url = Url::parse(&acct.object.object_props.id_string()?)?; - let inst = url.host_str()?; + let inst = url.host_str().ok_or(Error::Url)?; let instance = Instance::find_by_domain(conn, inst).or_else(|_| { Instance::insert( conn, @@ -432,6 +443,10 @@ impl FromId for Blog { }, ) } + + fn get_sender() -> &'static dyn sign::Signer { + Instance::get_local_instance_user().expect("Failed to local instance user") + } } impl AsActor<&PlumeRocket> for Blog { @@ -451,24 +466,22 @@ impl AsActor<&PlumeRocket> for Blog { } impl sign::Signer for Blog { - type Error = Error; - fn get_key_id(&self) -> String { format!("{}#main-key", self.ap_url) } - fn sign(&self, to_sign: &str) -> Result> { - let key = self.get_keypair()?; + fn sign(&self, to_sign: &str) -> sign::Result> { + let key = self.get_keypair().map_err(|_| sign::Error())?; let mut signer = Signer::new(MessageDigest::sha256(), &key)?; signer.update(to_sign.as_bytes())?; - signer.sign_to_vec().map_err(Error::from) + signer.sign_to_vec().map_err(sign::Error::from) } - fn verify(&self, data: &str, signature: &[u8]) -> Result { + fn verify(&self, data: &str, signature: &[u8]) -> sign::Result { let key = PKey::from_rsa(Rsa::public_key_from_pem(self.public_key.as_ref())?)?; let mut verifier = Verifier::new(MessageDigest::sha256(), &key)?; verifier.update(data.as_bytes())?; - verifier.verify(&signature).map_err(Error::from) + verifier.verify(signature).map_err(sign::Error::from) } } diff --git a/plume-models/src/comments.rs b/plume-models/src/comments.rs index 2a9cac2f..0809aab5 100644 --- a/plume-models/src/comments.rs +++ b/plume-models/src/comments.rs @@ -21,6 +21,7 @@ use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl, SaveChangesDsl}; use plume_common::{ activity_pub::{ inbox::{AsActor, AsObject, FromId}, + sign::Signer, Id, IntoId, PUBLIC_VISIBILITY, }, utils, @@ -141,18 +142,20 @@ impl Comment { } pub fn create_activity(&self, conn: &DbConn) -> Result { - let author = User::get(&conn, self.author_id)?; + let author = User::get(conn, self.author_id)?; let note = self.to_activity(conn)?; let mut act = Create::default(); act.create_props.set_actor_link(author.into_id())?; act.create_props.set_object_object(note.clone())?; - act.object_props - .set_id_string(format!("{}/activity", self.ap_url.clone()?,))?; + act.object_props.set_id_string(format!( + "{}/activity", + self.ap_url.clone().ok_or(Error::MissingApProperty)?, + ))?; act.object_props .set_to_link_vec(note.object_props.to_link_vec::()?)?; act.object_props - .set_cc_link_vec(vec![Id::new(self.get_author(&conn)?.followers_endpoint)])?; + .set_cc_link_vec(vec![Id::new(self.get_author(conn)?.followers_endpoint)])?; Ok(act) } @@ -182,7 +185,9 @@ impl Comment { .set_actor_link(self.get_author(conn)?.into_id())?; let mut tombstone = Tombstone::default(); - tombstone.object_props.set_id_string(self.ap_url.clone()?)?; + tombstone + .object_props + .set_id_string(self.ap_url.clone().ok_or(Error::MissingApProperty)?)?; act.delete_props.set_object_object(tombstone)?; act.object_props @@ -204,7 +209,13 @@ impl FromId for Comment { fn from_activity(conn: &DbConn, note: Note) -> Result { let comm = { - let previous_url = note.object_props.in_reply_to.as_ref()?.as_str()?; + let previous_url = note + .object_props + .in_reply_to + .as_ref() + .ok_or(Error::MissingApProperty)? + .as_str() + .ok_or(Error::MissingApProperty)?; let previous_comment = Comment::find_by_ap_url(conn, previous_url); let is_public = |v: &Option| match v @@ -318,6 +329,10 @@ impl FromId for Comment { comm.notify(conn)?; Ok(comm) } + + fn get_sender() -> &'static dyn Signer { + Instance::get_local_instance_user().expect("Failed to local instance user") + } } impl AsObject for Comment { @@ -346,7 +361,7 @@ impl AsObject for Comment { m.delete(conn)?; } - for n in Notification::find_for_comment(&conn, &self)? { + for n in Notification::find_for_comment(conn, &self)? { n.delete(&**conn)?; } diff --git a/plume-models/src/config.rs b/plume-models/src/config.rs index f69597f8..fe5282a0 100644 --- a/plume-models/src/config.rs +++ b/plume-models/src/config.rs @@ -17,7 +17,7 @@ pub struct Config { pub db_min_idle: Option, pub search_index: String, pub search_tokenizers: SearchTokenizerConfig, - pub rocket: Result, + pub rocket: Result, pub logo: LogoConfig, pub default_theme: String, pub media_directory: String, @@ -31,21 +31,21 @@ impl Config { } #[derive(Debug, Clone)] -pub enum RocketError { - InvalidEnv, - InvalidAddress, - InvalidSecretKey, +pub enum InvalidRocketConfig { + Env, + Address, + SecretKey, } -fn get_rocket_config() -> Result { - let mut c = RocketConfig::active().map_err(|_| RocketError::InvalidEnv)?; +fn get_rocket_config() -> Result { + let mut c = RocketConfig::active().map_err(|_| InvalidRocketConfig::Env)?; let address = var("ROCKET_ADDRESS").unwrap_or_else(|_| "localhost".to_owned()); let port = var("ROCKET_PORT") .ok() .map(|s| s.parse::().unwrap()) .unwrap_or(7878); - let secret_key = var("ROCKET_SECRET_KEY").map_err(|_| RocketError::InvalidSecretKey)?; + let secret_key = var("ROCKET_SECRET_KEY").map_err(|_| InvalidRocketConfig::SecretKey)?; let form_size = var("FORM_SIZE") .unwrap_or_else(|_| "128".to_owned()) .parse::() @@ -56,10 +56,10 @@ fn get_rocket_config() -> Result { .unwrap(); c.set_address(address) - .map_err(|_| RocketError::InvalidAddress)?; + .map_err(|_| InvalidRocketConfig::Address)?; c.set_port(port); c.set_secret_key(secret_key) - .map_err(|_| RocketError::InvalidSecretKey)?; + .map_err(|_| InvalidRocketConfig::SecretKey)?; c.set_limits( Limits::new() @@ -155,7 +155,7 @@ impl Default for LogoConfig { .ok() .or_else(|| custom_main.clone()); let other = if let Some(main) = custom_main.clone() { - let ext = |path: &str| match path.rsplitn(2, '.').next() { + let ext = |path: &str| match path.rsplit_once('.').map(|x| x.1) { Some("png") => Some("image/png".to_owned()), Some("jpg") | Some("jpeg") => Some("image/jpeg".to_owned()), Some("svg") => Some("image/svg+xml".to_owned()), diff --git a/plume-models/src/follows.rs b/plume-models/src/follows.rs index da465d44..9450b59b 100644 --- a/plume-models/src/follows.rs +++ b/plume-models/src/follows.rs @@ -1,6 +1,6 @@ use crate::{ - ap_url, db_conn::DbConn, notifications::*, schema::follows, users::User, Connection, Error, - Result, CONFIG, + ap_url, db_conn::DbConn, instance::Instance, notifications::*, schema::follows, users::User, + Connection, Error, Result, CONFIG, }; use activitypub::activity::{Accept, Follow as FollowAct, Undo}; use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl, SaveChangesDsl}; @@ -183,6 +183,10 @@ impl FromId for Follow { .map_err(|(_, e)| e)?; Follow::accept_follow(conn, &actor, &target, follow, actor.id, target.id) } + + fn get_sender() -> &'static dyn Signer { + Instance::get_local_instance_user().expect("Failed to local instance user") + } } impl AsObject for Follow { @@ -195,7 +199,7 @@ impl AsObject for Follow { diesel::delete(&self).execute(&**conn)?; // delete associated notification if any - if let Ok(notif) = Notification::find(&conn, notification_kind::FOLLOW, self.id) { + if let Ok(notif) = Notification::find(conn, notification_kind::FOLLOW, self.id) { diesel::delete(¬if).execute(&**conn)?; } diff --git a/plume-models/src/instance.rs b/plume-models/src/instance.rs index 80babed5..86cb3d46 100644 --- a/plume-models/src/instance.rs +++ b/plume-models/src/instance.rs @@ -3,11 +3,12 @@ use crate::{ medias::Media, safe_string::SafeString, schema::{instances, users}, - users::{Role, User}, + users::{NewUser, Role, User}, Connection, Error, Result, }; use chrono::NaiveDateTime; -use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl}; +use diesel::{self, result::Error::NotFound, ExpressionMethods, QueryDsl, RunQueryDsl}; +use once_cell::sync::OnceCell; use plume_common::utils::md_to_html; use std::sync::RwLock; @@ -45,6 +46,9 @@ lazy_static! { static ref LOCAL_INSTANCE: RwLock> = RwLock::new(None); } +const LOCAL_INSTANCE_USERNAME: &str = "__instance__"; +static LOCAL_INSTANCE_USER: OnceCell = OnceCell::new(); + impl Instance { pub fn set_local(self) { LOCAL_INSTANCE.write().unwrap().replace(self); @@ -76,6 +80,42 @@ impl Instance { .map_err(Error::from) } + pub fn create_local_instance_user(conn: &Connection) -> Result { + let instance = Instance::get_local()?; + let email = format!("{}@{}", LOCAL_INSTANCE_USERNAME, &instance.public_domain); + NewUser::new_local( + conn, + LOCAL_INSTANCE_USERNAME.into(), + instance.public_domain, + Role::Instance, + "Local instance", + email, + None, + ) + } + + pub fn get_local_instance_user() -> Option<&'static User> { + LOCAL_INSTANCE_USER.get() + } + + pub fn get_local_instance_user_uncached(conn: &Connection) -> Result { + users::table + .filter(users::role.eq(3)) + .first(conn) + .or_else(|err| match err { + NotFound => Self::create_local_instance_user(conn), + _ => Err(Error::Db(err)), + }) + } + + pub fn cache_local_instance_user(conn: &Connection) { + let _ = LOCAL_INSTANCE_USER.get_or_init(|| { + Self::get_local_instance_user_uncached(conn) + .or_else(|_| Self::create_local_instance_user(conn)) + .expect("Failed to cache local instance user") + }); + } + pub fn page(conn: &Connection, (min, max): (i32, i32)) -> Result> { instances::table .order(instances::public_domain.asc()) @@ -304,6 +344,7 @@ pub(crate) mod tests { }) .collect(); Instance::cache_local(conn); + Instance::cache_local_instance_user(conn); res } diff --git a/plume-models/src/lib.rs b/plume-models/src/lib.rs index a3d10755..16d3a159 100755 --- a/plume-models/src/lib.rs +++ b/plume-models/src/lib.rs @@ -1,4 +1,3 @@ -#![feature(try_trait)] #![feature(never_type)] #![feature(proc_macro_hygiene)] #![feature(box_patterns)] @@ -18,7 +17,7 @@ extern crate serde_json; extern crate tantivy; use once_cell::sync::Lazy; -use plume_common::activity_pub::inbox::InboxError; +use plume_common::activity_pub::{inbox::InboxError, request, sign}; use posts::PostEvent; use riker::actors::{channel, ActorSystem, ChannelRef, SystemBuilder}; use users::UserEvent; @@ -80,15 +79,15 @@ impl From for Error { } } -impl From for Error { - fn from(err: diesel::result::Error) -> Self { - Error::Db(err) +impl From for Error { + fn from(_: sign::Error) -> Self { + Error::Signature } } -impl From for Error { - fn from(_: std::option::NoneError) -> Self { - Error::NotFound +impl From for Error { + fn from(err: diesel::result::Error) -> Self { + Error::Db(err) } } @@ -158,6 +157,12 @@ impl From> for Error { } } +impl From for Error { + fn from(_err: request::Error) -> Error { + Error::Request + } +} + pub type Result = std::result::Result; /// Adds a function to a model, that returns the first diff --git a/plume-models/src/likes.rs b/plume-models/src/likes.rs index 78d81b54..fa092af0 100644 --- a/plume-models/src/likes.rs +++ b/plume-models/src/likes.rs @@ -1,12 +1,13 @@ use crate::{ - db_conn::DbConn, notifications::*, posts::Post, schema::likes, timeline::*, users::User, - Connection, Error, Result, CONFIG, + db_conn::DbConn, instance::Instance, notifications::*, posts::Post, schema::likes, timeline::*, + users::User, Connection, Error, Result, CONFIG, }; use activitypub::activity; use chrono::NaiveDateTime; use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl}; use plume_common::activity_pub::{ inbox::{AsActor, AsObject, FromId}, + sign::Signer, Id, IntoId, PUBLIC_VISIBILITY, }; @@ -137,6 +138,10 @@ impl FromId for Like { res.notify(conn)?; Ok(res) } + + fn get_sender() -> &'static dyn Signer { + Instance::get_local_instance_user().expect("Failed to local instance user") + } } impl AsObject for Like { @@ -148,7 +153,7 @@ impl AsObject for Like { diesel::delete(&self).execute(&**conn)?; // delete associated notification if any - if let Ok(notif) = Notification::find(&conn, notification_kind::LIKE, self.id) { + if let Ok(notif) = Notification::find(conn, notification_kind::LIKE, self.id) { diesel::delete(¬if).execute(&**conn)?; } Ok(()) diff --git a/plume-models/src/lists.rs b/plume-models/src/lists.rs index 19d270b2..5b393f64 100644 --- a/plume-models/src/lists.rs +++ b/plume-models/src/lists.rs @@ -143,6 +143,7 @@ macro_rules! func { } } +#[allow(dead_code)] #[derive(Clone, Queryable, Identifiable)] struct ListElem { pub id: i32, diff --git a/plume-models/src/medias.rs b/plume-models/src/medias.rs index 13a212b6..68cb52c4 100644 --- a/plume-models/src/medias.rs +++ b/plume-models/src/medias.rs @@ -7,7 +7,7 @@ use askama_escape::escape; use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl}; use guid_create::GUID; use plume_common::{ - activity_pub::{inbox::FromId, Id}, + activity_pub::{inbox::FromId, request, Id}, utils::MediaProcessor, }; use std::{ @@ -104,8 +104,8 @@ impl Media { pub fn category(&self) -> MediaCategory { match &*self .file_path - .rsplitn(2, '.') - .next() + .rsplit_once('.') + .map(|x| x.1) .expect("Media::category: extension error") .to_lowercase() { @@ -208,31 +208,33 @@ impl Media { // TODO: merge with save_remote? pub fn from_activity(conn: &DbConn, image: &Image) -> Result { - let remote_url = image.object_props.url_string().ok()?; + let remote_url = image + .object_props + .url_string() + .or(Err(Error::MissingApProperty))?; let path = determine_mirror_file_path(&remote_url); - let parent = path.parent()?; + let parent = path.parent().ok_or(Error::InvalidValue)?; if !parent.is_dir() { DirBuilder::new().recursive(true).create(parent)?; } - let mut dest = fs::File::create(path.clone()).ok()?; + let mut dest = fs::File::create(path.clone())?; // TODO: conditional GET - if let Some(proxy) = CONFIG.proxy() { - reqwest::ClientBuilder::new().proxy(proxy.clone()).build()? - } else { - reqwest::Client::new() - } - .get(remote_url.as_str()) - .send() - .ok()? - .copy_to(&mut dest) - .ok()?; + request::get( + remote_url.as_str(), + User::get_sender(), + CONFIG.proxy().cloned(), + )? + .copy_to(&mut dest)?; - Media::find_by_file_path(conn, &path.to_str()?) + Media::find_by_file_path(conn, path.to_str().ok_or(Error::InvalidValue)?) .and_then(|mut media| { let mut updated = false; - let alt_text = image.object_props.content_string().ok()?; + let alt_text = image + .object_props + .content_string() + .or(Err(Error::NotFound))?; let sensitive = image.object_props.summary_string().is_ok(); let content_warning = image.object_props.summary_string().ok(); if media.alt_text != alt_text { @@ -264,8 +266,11 @@ impl Media { Media::insert( conn, NewMedia { - file_path: path.to_str()?.to_string(), - alt_text: image.object_props.content_string().ok()?, + file_path: path.to_str().ok_or(Error::InvalidValue)?.to_string(), + alt_text: image + .object_props + .content_string() + .or(Err(Error::NotFound))?, is_remote: false, remote_url: None, sensitive: image.object_props.summary_string().is_ok(), @@ -275,9 +280,10 @@ impl Media { image .object_props .attributed_to_link_vec::() - .ok()? + .or(Err(Error::NotFound))? .into_iter() - .next()? + .next() + .ok_or(Error::NotFound)? .as_ref(), None, CONFIG.proxy(), @@ -325,7 +331,7 @@ fn determine_mirror_file_path(url: &str) -> PathBuf { .next() .map(ToOwned::to_owned) .unwrap_or_else(|| String::from("png")); - file_path.push(format!("{}.{}", GUID::rand().to_string(), ext)); + file_path.push(format!("{}.{}", GUID::rand(), ext)); }); file_path } diff --git a/plume-models/src/mentions.rs b/plume-models/src/mentions.rs index 28e8e5c9..d83d48d8 100644 --- a/plume-models/src/mentions.rs +++ b/plume-models/src/mentions.rs @@ -47,7 +47,11 @@ impl Mention { pub fn get_user(&self, conn: &Connection) -> Result { match self.get_post(conn) { - Ok(p) => Ok(p.get_authors(conn)?.into_iter().next()?), + Ok(p) => Ok(p + .get_authors(conn)? + .into_iter() + .next() + .ok_or(Error::NotFound)?), Err(_) => self.get_comment(conn).and_then(|c| c.get_author(conn)), } } @@ -77,7 +81,7 @@ impl Mention { in_post: bool, notify: bool, ) -> Result { - let ap_url = ment.link_props.href_string().ok()?; + let ap_url = ment.link_props.href_string().or(Err(Error::NotFound))?; let mentioned = User::find_by_ap_url(conn, &ap_url)?; if in_post { diff --git a/plume-models/src/migrations.rs b/plume-models/src/migrations.rs index 301ddbfe..6a7c756c 100644 --- a/plume-models/src/migrations.rs +++ b/plume-models/src/migrations.rs @@ -105,7 +105,8 @@ impl ImportedMigrations { pub fn rerun_last_migration(&self, conn: &Connection, path: &Path) -> Result<()> { let latest_migration = conn.latest_run_migration_version()?; let id = latest_migration - .and_then(|m| self.0.binary_search_by_key(&m.as_str(), |m| m.name).ok())?; + .and_then(|m| self.0.binary_search_by_key(&m.as_str(), |m| m.name).ok()) + .ok_or(Error::NotFound)?; let migration = &self.0[id]; conn.transaction(|| { migration.revert(conn, path)?; diff --git a/plume-models/src/password_reset_requests.rs b/plume-models/src/password_reset_requests.rs index b86381b3..cfd93529 100644 --- a/plume-models/src/password_reset_requests.rs +++ b/plume-models/src/password_reset_requests.rs @@ -61,7 +61,7 @@ impl PasswordResetRequest { } pub fn find_and_delete_by_token(conn: &Connection, token: &str) -> Result { - let request = Self::find_by_token(&conn, &token)?; + let request = Self::find_by_token(conn, token)?; let filter = password_reset_requests::table.filter(password_reset_requests::id.eq(request.id)); diff --git a/plume-models/src/posts.rs b/plume-models/src/posts.rs index afd251f8..9a385db9 100644 --- a/plume-models/src/posts.rs +++ b/plume-models/src/posts.rs @@ -15,6 +15,7 @@ use once_cell::sync::Lazy; use plume_common::{ activity_pub::{ inbox::{AsActor, AsObject, FromId}, + sign::Signer, Hashtag, Id, IntoId, Licensed, Source, PUBLIC_VISIBILITY, }, utils::{iri_percent_encode_seg, md_to_html}, @@ -97,7 +98,7 @@ impl Post { } pub fn delete(&self, conn: &Connection) -> Result<()> { - for m in Mention::list_for_post(&conn, self.id)? { + for m in Mention::list_for_post(conn, self.id)? { m.delete(conn)?; } diesel::delete(self).execute(conn)?; @@ -457,14 +458,14 @@ impl Post { .filter_map(|(id, m)| id.map(|id| (m, id))) .collect::>(); - let old_mentions = Mention::list_for_post(&conn, self.id)?; + let old_mentions = Mention::list_for_post(conn, self.id)?; let old_user_mentioned = old_mentions .iter() .map(|m| m.mentioned_id) .collect::>(); for (m, id) in &mentions { - if !old_user_mentioned.contains(&id) { - Mention::from_activity(&*conn, &m, self.id, true, true)?; + if !old_user_mentioned.contains(id) { + Mention::from_activity(&*conn, m, self.id, true, true)?; } } @@ -476,7 +477,7 @@ impl Post { .iter() .filter(|m| !new_mentions.contains(&m.mentioned_id)) { - m.delete(&conn)?; + m.delete(conn)?; } Ok(()) } @@ -700,7 +701,7 @@ impl FromId for Post { Post::insert( conn, NewPost { - blog_id: blog?.id, + blog_id: blog.ok_or(Error::NotFound)?.id, slug: Self::slug(&title).to_string(), title, content: SafeString::new(&article.object_props.content_string()?), @@ -759,6 +760,10 @@ impl FromId for Post { Ok(post) } + + fn get_sender() -> &'static dyn Signer { + Instance::get_local_instance_user().expect("Failed to local instance user") + } } impl AsObject for Post { @@ -830,6 +835,10 @@ impl FromId for PostUpdate { tags: updated.object.object_props.tag, }) } + + fn get_sender() -> &'static dyn Signer { + Instance::get_local_instance_user().expect("Failed to local instance user") + } } impl AsObject for PostUpdate { diff --git a/plume-models/src/reshares.rs b/plume-models/src/reshares.rs index 19bceddf..58400196 100644 --- a/plume-models/src/reshares.rs +++ b/plume-models/src/reshares.rs @@ -1,12 +1,13 @@ use crate::{ - db_conn::DbConn, notifications::*, posts::Post, schema::reshares, timeline::*, users::User, - Connection, Error, Result, CONFIG, + db_conn::DbConn, instance::Instance, notifications::*, posts::Post, schema::reshares, + timeline::*, users::User, Connection, Error, Result, CONFIG, }; use activitypub::activity::{Announce, Undo}; use chrono::NaiveDateTime; use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl}; use plume_common::activity_pub::{ inbox::{AsActor, AsObject, FromId}, + sign::Signer, Id, IntoId, PUBLIC_VISIBILITY, }; @@ -162,6 +163,10 @@ impl FromId for Reshare { res.notify(conn)?; Ok(res) } + + fn get_sender() -> &'static dyn Signer { + Instance::get_local_instance_user().expect("Failed to local instance user") + } } impl AsObject for Reshare { @@ -173,7 +178,7 @@ impl AsObject for Reshare { diesel::delete(&self).execute(&**conn)?; // delete associated notification if any - if let Ok(notif) = Notification::find(&conn, notification_kind::RESHARE, self.id) { + if let Ok(notif) = Notification::find(conn, notification_kind::RESHARE, self.id) { diesel::delete(¬if).execute(&**conn)?; } diff --git a/plume-models/src/safe_string.rs b/plume-models/src/safe_string.rs index aafd02ae..fedcdd70 100644 --- a/plume-models/src/safe_string.rs +++ b/plume-models/src/safe_string.rs @@ -102,7 +102,7 @@ pub struct SafeString { impl SafeString { pub fn new(value: &str) -> Self { SafeString { - value: CLEAN.clean(&value).to_string(), + value: CLEAN.clean(value).to_string(), } } diff --git a/plume-models/src/search/query.rs b/plume-models/src/search/query.rs index 1e053d4a..a2c4f252 100644 --- a/plume-models/src/search/query.rs +++ b/plume-models/src/search/query.rs @@ -148,7 +148,7 @@ impl PlumeQuery { /// Parse a query string into this Query pub fn parse_query(&mut self, query: &str) -> &mut Self { - self.from_str_req(&query.trim()) + self.from_str_req(query.trim()) } /// Convert this Query to a Tantivy Query @@ -360,7 +360,7 @@ impl std::str::FromStr for PlumeQuery { fn from_str(query: &str) -> Result { let mut res: PlumeQuery = Default::default(); - res.from_str_req(&query.trim()); + res.from_str_req(query.trim()); Ok(res) } } diff --git a/plume-models/src/timeline/query.rs b/plume-models/src/timeline/query.rs index eef5255b..00509440 100644 --- a/plume-models/src/timeline/query.rs +++ b/plume-models/src/timeline/query.rs @@ -18,12 +18,6 @@ pub enum QueryError { RuntimeError(String), } -impl From for QueryError { - fn from(_: std::option::NoneError) -> Self { - QueryError::UnexpectedEndOfQuery - } -} - pub type QueryResult = std::result::Result; #[derive(Debug, Clone, Copy, PartialEq)] @@ -239,7 +233,7 @@ impl WithList { ) -> Result { match list { List::List(name) => { - let list = lists::List::find_for_user_by_name(conn, timeline.user_id, &name)?; + let list = lists::List::find_for_user_by_name(conn, timeline.user_id, name)?; match (self, list.kind()) { (WithList::Blog, ListType::Blog) => list.contains_blog(conn, post.blog_id), (WithList::Author { boosts, likes }, ListType::User) => match kind { @@ -414,7 +408,7 @@ enum List<'a> { fn parse_s<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], TQ<'a>)> { let mut res = Vec::new(); - let (left, token) = parse_a(&stream)?; + let (left, token) = parse_a(stream)?; res.push(token); stream = left; while !stream.is_empty() { @@ -436,7 +430,7 @@ fn parse_s<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], fn parse_a<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], TQ<'a>)> { let mut res = Vec::new(); - let (left, token) = parse_b(&stream)?; + let (left, token) = parse_b(stream)?; res.push(token); stream = left; while !stream.is_empty() { @@ -463,7 +457,7 @@ fn parse_b<'a, 'b>(stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], TQ< match left.get(0) { Some(Token::RParent(_)) => Ok((&left[1..], token)), Some(t) => t.get_error(Token::RParent(0)), - None => None?, + None => Err(QueryError::UnexpectedEndOfQuery), } } _ => parse_c(stream), @@ -484,9 +478,13 @@ fn parse_c<'a, 'b>(stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], TQ< } fn parse_d<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], Arg<'a>)> { - match stream.get(0).map(Token::get_text)? { + match stream + .get(0) + .map(Token::get_text) + .ok_or(QueryError::UnexpectedEndOfQuery)? + { s @ "blog" | s @ "author" | s @ "license" | s @ "tags" | s @ "lang" => { - match stream.get(1)? { + match stream.get(1).ok_or(QueryError::UnexpectedEndOfQuery)? { Token::Word(_, _, r#in) if r#in == &"in" => { let (mut left, list) = parse_l(&stream[2..])?; let kind = match s { @@ -498,7 +496,12 @@ fn parse_d<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], if *clude != "include" && *clude != "exclude" { break; } - match (*clude, left.get(1).map(Token::get_text)?) { + match ( + *clude, + left.get(1) + .map(Token::get_text) + .ok_or(QueryError::UnexpectedEndOfQuery)?, + ) { ("include", "reshares") | ("include", "reshare") => { boosts = true } @@ -529,7 +532,10 @@ fn parse_d<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], t => t.get_error(Token::Word(0, 0, "'in'")), } } - s @ "title" | s @ "subtitle" | s @ "content" => match (stream.get(1)?, stream.get(2)?) { + s @ "title" | s @ "subtitle" | s @ "content" => match ( + stream.get(1).ok_or(QueryError::UnexpectedEndOfQuery)?, + stream.get(2).ok_or(QueryError::UnexpectedEndOfQuery)?, + ) { (Token::Word(_, _, contains), Token::Word(_, _, w)) if contains == &"contains" => Ok(( &stream[3..], Arg::Contains( @@ -555,7 +561,13 @@ fn parse_d<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], if *clude != "include" && *clude != "exclude" { break; } - match (*clude, stream.get(2).map(Token::get_text)?) { + match ( + *clude, + stream + .get(2) + .map(Token::get_text) + .ok_or(QueryError::UnexpectedEndOfQuery)?, + ) { ("include", "reshares") | ("include", "reshare") => boosts = true, ("exclude", "reshares") | ("exclude", "reshare") => boosts = false, ("include", "likes") | ("include", "like") => likes = true, @@ -577,20 +589,23 @@ fn parse_d<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], "all" => Ok((&stream[1..], Arg::Boolean(Bool::All))), _ => unreachable!(), }, - _ => stream.get(0)?.get_error(Token::Word( - 0, - 0, - "one of 'blog', 'author', 'license', 'tags', 'lang', \ + _ => stream + .get(0) + .ok_or(QueryError::UnexpectedEndOfQuery)? + .get_error(Token::Word( + 0, + 0, + "one of 'blog', 'author', 'license', 'tags', 'lang', \ 'title', 'subtitle', 'content', 'followed', 'has_cover', 'local' or 'all'", - )), + )), } } fn parse_l<'a, 'b>(stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], List<'a>)> { - match stream.get(0)? { + match stream.get(0).ok_or(QueryError::UnexpectedEndOfQuery)? { Token::LBracket(_) => { let (left, list) = parse_m(&stream[1..])?; - match left.get(0)? { + match left.get(0).ok_or(QueryError::UnexpectedEndOfQuery)? { Token::RBracket(_) => Ok((&left[1..], List::Array(list))), t => t.get_error(Token::Word(0, 0, "one of ']' or ','")), } @@ -601,16 +616,20 @@ fn parse_l<'a, 'b>(stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], Lis } fn parse_m<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], Vec<&'a str>)> { - let mut res: Vec<&str> = vec![match stream.get(0)? { - Token::Word(_, _, w) => w, - t => return t.get_error(Token::Word(0, 0, "any word")), - }]; - stream = &stream[1..]; - while let Token::Comma(_) = stream[0] { - res.push(match stream.get(1)? { + let mut res: Vec<&str> = vec![ + match stream.get(0).ok_or(QueryError::UnexpectedEndOfQuery)? { Token::Word(_, _, w) => w, t => return t.get_error(Token::Word(0, 0, "any word")), - }); + }, + ]; + stream = &stream[1..]; + while let Token::Comma(_) = stream[0] { + res.push( + match stream.get(1).ok_or(QueryError::UnexpectedEndOfQuery)? { + Token::Word(_, _, w) => w, + t => return t.get_error(Token::Word(0, 0, "any word")), + }, + ); stream = &stream[2..]; } diff --git a/plume-models/src/users.rs b/plume-models/src/users.rs index 7924cfd4..8c42701b 100644 --- a/plume-models/src/users.rs +++ b/plume-models/src/users.rs @@ -22,17 +22,13 @@ use openssl::{ }; use plume_common::{ activity_pub::{ - ap_accept_header, inbox::{AsActor, AsObject, FromId}, - sign::{gen_keypair, Signer}, + request::get, + sign::{gen_keypair, Error as SignError, Result as SignResult, Signer}, ActivityStream, ApSignature, Id, IntoId, PublicKey, PUBLIC_VISIBILITY, }, utils, }; -use reqwest::{ - header::{HeaderValue, ACCEPT}, - ClientBuilder, -}; use riker::actors::{Publish, Tell}; use rocket::{ outcome::IntoOutcome, @@ -52,6 +48,7 @@ pub enum Role { Admin = 0, Moderator = 1, Normal = 2, + Instance = 3, } #[derive(Queryable, Identifiable, Clone, Debug, AsChangeset)] @@ -78,6 +75,7 @@ pub struct User { pub summary_html: SafeString, /// 0 = admin /// 1 = moderator + /// 3 = local instance /// anything else = normal user pub role: i32, pub preferred_theme: Option, @@ -210,7 +208,13 @@ impl User { .into_iter() .find(|l| l.mime_type == Some(String::from("application/activity+json"))) .ok_or(Error::Webfinger)?; - User::from_id(conn, link.href.as_ref()?, None, CONFIG.proxy()).map_err(|(_, e)| e) + User::from_id( + conn, + link.href.as_ref().ok_or(Error::Webfinger)?, + None, + CONFIG.proxy(), + ) + .map_err(|(_, e)| e) } pub fn fetch_remote_interact_uri(acct: &str) -> Result { @@ -223,20 +227,7 @@ impl User { } fn fetch(url: &str) -> Result { - let mut res = ClientBuilder::new() - .connect_timeout(Some(std::time::Duration::from_secs(5))) - .build()? - .get(url) - .header( - ACCEPT, - HeaderValue::from_str( - &ap_accept_header() - .into_iter() - .collect::>() - .join(", "), - )?, - ) - .send()?; + let mut res = get(url, Self::get_sender(), CONFIG.proxy().cloned())?; let text = &res.text()?; // without this workaround, publicKey is not correctly deserialized let ap_sign = serde_json::from_str::(text)?; @@ -255,10 +246,10 @@ impl User { conn, json.object .object_props - .icon_image()? + .icon_image()? // FIXME: Fails when icon is not set .object_props .url_string()?, - &self, + self, ) .ok(); @@ -427,12 +418,12 @@ impl User { let last = &format!( "{}?page={}", &self.outbox_url, - self.get_activities_count(&conn) / i64::from(ITEMS_PER_PAGE) + 1 + self.get_activities_count(conn) / i64::from(ITEMS_PER_PAGE) + 1 ); coll.collection_props.set_first_link(Id::new(first))?; coll.collection_props.set_last_link(Id::new(last))?; coll.collection_props - .set_total_items_u64(self.get_activities_count(&conn) as u64)?; + .set_total_items_u64(self.get_activities_count(conn) as u64)?; Ok(ActivityStream::new(coll)) } pub fn outbox_page( @@ -441,7 +432,7 @@ impl User { (min, max): (i32, i32), ) -> Result> { let acts = self.get_activities_page(conn, (min, max))?; - let n_acts = self.get_activities_count(&conn); + let n_acts = self.get_activities_count(conn); let mut coll = OrderedCollectionPage::default(); if n_acts - i64::from(min) >= i64::from(ITEMS_PER_PAGE) { coll.collection_page_props.set_next_link(Id::new(&format!( @@ -463,20 +454,7 @@ impl User { Ok(ActivityStream::new(coll)) } fn fetch_outbox_page(&self, url: &str) -> Result<(Vec, Option)> { - let mut res = ClientBuilder::new() - .connect_timeout(Some(std::time::Duration::from_secs(5))) - .build()? - .get(url) - .header( - ACCEPT, - HeaderValue::from_str( - &ap_accept_header() - .into_iter() - .collect::>() - .join(", "), - )?, - ) - .send()?; + let mut res = get(url, Self::get_sender(), CONFIG.proxy().cloned())?; let text = &res.text()?; let json: serde_json::Value = serde_json::from_str(text)?; let items = json["items"] @@ -490,20 +468,11 @@ impl User { Ok((items, next)) } pub fn fetch_outbox(&self) -> Result> { - let mut res = ClientBuilder::new() - .connect_timeout(Some(std::time::Duration::from_secs(5))) - .build()? - .get(&self.outbox_url[..]) - .header( - ACCEPT, - HeaderValue::from_str( - &ap_accept_header() - .into_iter() - .collect::>() - .join(", "), - )?, - ) - .send()?; + let mut res = get( + &self.outbox_url[..], + Self::get_sender(), + CONFIG.proxy().cloned(), + )?; let text = &res.text()?; let json: serde_json::Value = serde_json::from_str(text)?; if let Some(first) = json.get("first") { @@ -513,7 +482,7 @@ impl User { if page.is_empty() { break; } - items.extend(page.drain(..)); + items.append(&mut page); if let Some(n) = nxt { if n == next { break; @@ -535,20 +504,11 @@ impl User { } pub fn fetch_followers_ids(&self) -> Result> { - let mut res = ClientBuilder::new() - .connect_timeout(Some(std::time::Duration::from_secs(5))) - .build()? - .get(&self.followers_endpoint[..]) - .header( - ACCEPT, - HeaderValue::from_str( - &ap_accept_header() - .into_iter() - .collect::>() - .join(", "), - )?, - ) - .send()?; + let mut res = get( + &self.followers_endpoint[..], + Self::get_sender(), + CONFIG.proxy().cloned(), + )?; let text = &res.text()?; let json: serde_json::Value = serde_json::from_str(text)?; Ok(json["items"] @@ -720,7 +680,7 @@ impl User { pub fn get_keypair(&self) -> Result> { PKey::from_rsa(Rsa::private_key_from_pem( - self.private_key.clone()?.as_ref(), + self.private_key.clone().ok_or(Error::Signature)?.as_ref(), )?) .map_err(Error::from) } @@ -943,7 +903,7 @@ impl FromId for User { fn from_activity(conn: &DbConn, acct: CustomPerson) -> Result { let url = Url::parse(&acct.object.object_props.id_string()?)?; - let inst = url.host_str()?; + let inst = url.host_str().ok_or(Error::Url)?; let instance = Instance::find_by_domain(conn, inst).or_else(|_| { Instance::insert( conn, @@ -1031,6 +991,10 @@ impl FromId for User { Ok(user) } + + fn get_sender() -> &'static dyn Signer { + Instance::get_local_instance_user().expect("Failed to local instance user") + } } impl AsActor<&DbConn> for User { @@ -1063,24 +1027,22 @@ impl AsObject for User { } impl Signer for User { - type Error = Error; - fn get_key_id(&self) -> String { format!("{}#main-key", self.ap_url) } - fn sign(&self, to_sign: &str) -> Result> { - let key = self.get_keypair()?; + fn sign(&self, to_sign: &str) -> SignResult> { + let key = self.get_keypair().map_err(|_| SignError())?; let mut signer = sign::Signer::new(MessageDigest::sha256(), &key)?; signer.update(to_sign.as_bytes())?; - signer.sign_to_vec().map_err(Error::from) + signer.sign_to_vec().map_err(SignError::from) } - fn verify(&self, data: &str, signature: &[u8]) -> Result { + fn verify(&self, data: &str, signature: &[u8]) -> SignResult { let key = PKey::from_rsa(Rsa::public_key_from_pem(self.public_key.as_ref())?)?; let mut verifier = sign::Verifier::new(MessageDigest::sha256(), &key)?; verifier.update(data.as_bytes())?; - verifier.verify(&signature).map_err(Error::from) + verifier.verify(signature).map_err(SignError::from) } } @@ -1121,7 +1083,7 @@ impl NewUser { display_name, role: role as i32, summary: summary.to_owned(), - summary_html: SafeString::new(&utils::md_to_html(&summary, None, false, None).0), + summary_html: SafeString::new(&utils::md_to_html(summary, None, false, None).0), email: Some(email), hashed_password: password, instance_id: instance.id, diff --git a/rust-toolchain b/rust-toolchain index 1aad10c1..a1da0415 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2021-03-25 +nightly-2021-11-27 diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 11bebfe0..e61eb2ab 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -25,7 +25,7 @@ parts: plume: plugin: rust source: . - rust-revision: nightly-2021-03-25 + rust-revision: nightly-2021-11-27 build-packages: - libssl-dev - pkg-config diff --git a/src/api/mod.rs b/src/api/mod.rs index 5bc3bbc7..cd575c35 100755 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -19,12 +19,6 @@ impl From for ApiError { } } -impl From for ApiError { - fn from(err: std::option::NoneError) -> ApiError { - ApiError(err.into()) - } -} - impl<'r> Responder<'r> for ApiError { fn respond_to(self, req: &Request<'_>) -> response::Result<'r> { match self.0 { diff --git a/src/api/posts.rs b/src/api/posts.rs index 63490f84..56c80da9 100644 --- a/src/api/posts.rs +++ b/src/api/posts.rs @@ -1,7 +1,7 @@ use chrono::NaiveDateTime; use rocket_contrib::json::Json; -use crate::api::{authorization::*, Api}; +use crate::api::{authorization::*, Api, ApiError}; use plume_api::posts::*; use plume_common::{activity_pub::broadcast, utils::md_to_html}; use plume_models::{ @@ -121,14 +121,17 @@ pub fn create( Some(Media::get_media_processor(&conn, vec![&author])), ); - let blog = payload.blog_id.or_else(|| { - let blogs = Blog::find_for_author(&conn, &author).ok()?; - if blogs.len() == 1 { - Some(blogs[0].id) - } else { - None - } - })?; + let blog = payload + .blog_id + .or_else(|| { + let blogs = Blog::find_for_author(&conn, &author).ok()?; + if blogs.len() == 1 { + Some(blogs[0].id) + } else { + None + } + }) + .ok_or(ApiError(Error::NotFound))?; if Post::find_by_slug(&conn, slug, blog).is_ok() { return Err(Error::InvalidValue.into()); diff --git a/src/inbox.rs b/src/inbox.rs index a7a67276..78069b69 100644 --- a/src/inbox.rs +++ b/src/inbox.rs @@ -90,8 +90,8 @@ impl<'a, T: Deserialize<'a>> FromData<'a> for SignedJson { o: Transformed<'a, Self>, ) -> rocket::data::Outcome { let string = o.borrowed()?; - match serde_json::from_str(&string) { - Ok(v) => Success(SignedJson(Digest::from_body(&string), Json(v))), + match serde_json::from_str(string) { + Ok(v) => Success(SignedJson(Digest::from_body(string), Json(v))), Err(e) => { if e.is_data() { Failure((Status::UnprocessableEntity, JsonError::Parse(string, e))) diff --git a/src/main.rs b/src/main.rs index 8ca1aa4b..58cb3abe 100755 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ #![allow(clippy::too_many_arguments)] -#![feature(decl_macro, proc_macro_hygiene, try_trait)] +#![feature(decl_macro, proc_macro_hygiene)] #[macro_use] extern crate gettext_macros; @@ -57,7 +57,10 @@ fn init_pool() -> Option { builder = builder.max_size(max_size); }; let pool = builder.build(manager).ok()?; - Instance::cache_local(&pool.get().unwrap()); + let conn = pool.get().unwrap(); + Instance::cache_local(&conn); + let _ = Instance::create_local_instance_user(&conn); + Instance::cache_local_instance_user(&conn); Some(pool) } diff --git a/src/routes/blogs.rs b/src/routes/blogs.rs index df4da910..07a8e8f1 100644 --- a/src/routes/blogs.rs +++ b/src/routes/blogs.rs @@ -390,6 +390,7 @@ mod tests { posts::{NewPost, Post}, safe_string::SafeString, users::{NewUser, User, AUTH_COOKIE}, + Connection as Conn, CONFIG, }; use rocket::{ http::{Cookie, Cookies, SameSite}, @@ -398,6 +399,22 @@ mod tests { #[test] fn edit_link_within_post_card() { + let conn = Conn::establish(CONFIG.database_url.as_str()).unwrap(); + Instance::insert( + &conn, + NewInstance { + public_domain: "example.org".to_string(), + name: "Plume".to_string(), + local: true, + long_description: SafeString::new(""), + short_description: SafeString::new(""), + default_license: "CC-BY-SA".to_string(), + open_registrations: true, + short_description_html: String::new(), + long_description_html: String::new(), + }, + ) + .unwrap(); let rocket = init_rocket(); let client = Client::new(rocket).expect("valid rocket instance"); let dbpool = client.rocket().state::().unwrap(); diff --git a/src/routes/instance.rs b/src/routes/instance.rs index 648c2960..ae7acd5c 100644 --- a/src/routes/instance.rs +++ b/src/routes/instance.rs @@ -372,7 +372,7 @@ fn ban(id: i32, conn: &Connection, worker: &ScheduledThreadPool) -> Result<(), E .unwrap_or(false) { BlocklistedEmail::insert( - &conn, + conn, NewBlocklistedEmail { email_address: u.email.clone().unwrap(), note: "Banned".to_string(), diff --git a/src/routes/medias.rs b/src/routes/medias.rs index 10b25e28..8f920036 100644 --- a/src/routes/medias.rs +++ b/src/routes/medias.rs @@ -77,12 +77,7 @@ pub fn upload( .map(|ext| format!(".{}", ext)) }) .unwrap_or_default(); - let dest = format!( - "{}/{}{}", - CONFIG.media_directory, - GUID::rand().to_string(), - ext - ); + let dest = format!("{}/{}{}", CONFIG.media_directory, GUID::rand(), ext); match fields["file"][0].data { SavedData::Bytes(ref bytes) => fs::write(&dest, bytes) diff --git a/src/routes/posts.rs b/src/routes/posts.rs index df570a1d..de0f4541 100644 --- a/src/routes/posts.rs +++ b/src/routes/posts.rs @@ -425,7 +425,7 @@ pub fn create( Ok(_) => ValidationErrors::new(), Err(e) => e, }; - if Post::find_by_slug(&conn, &slug, blog.id).is_ok() { + if Post::find_by_slug(&conn, slug, blog.id).is_ok() { errors.add( "title", ValidationError { diff --git a/src/routes/search.rs b/src/routes/search.rs index 3d6fa8fc..33d8443f 100644 --- a/src/routes/search.rs +++ b/src/routes/search.rs @@ -54,7 +54,7 @@ pub fn search(query: Option>, conn: DbConn, rockets: PlumeRock let query = query.map(Form::into_inner).unwrap_or_default(); let page = query.page.unwrap_or_default(); let mut parsed_query = - Query::from_str(&query.q.as_deref().unwrap_or_default()).unwrap_or_default(); + Query::from_str(query.q.as_deref().unwrap_or_default()).unwrap_or_default(); param_to_query!(query, parsed_query; normal: title, subtitle, content, tag, instance, author, blog, lang, license; diff --git a/src/routes/user.rs b/src/routes/user.rs index 867c6a96..30b7ecb7 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -553,14 +553,14 @@ pub fn ap_followers( #[get("/@//atom.xml")] pub fn atom_feed(name: String, conn: DbConn) -> Option> { let conn = &conn; - let author = User::find_by_fqn(&conn, &name).ok()?; - let entries = Post::get_recents_for_author(&conn, &author, 15).ok()?; + let author = User::find_by_fqn(conn, &name).ok()?; + let entries = Post::get_recents_for_author(conn, &author, 15).ok()?; let uri = Instance::get_local() .ok()? .compute_box("@", &name, "atom.xml"); let title = &author.display_name; let default_updated = &author.creation_date; - let feed = super::build_atom_feed(entries, &uri, title, default_updated, &conn); + let feed = super::build_atom_feed(entries, &uri, title, default_updated, conn); Some(Content( ContentType::new("application", "atom+xml"), feed.to_string(), diff --git a/src/template_utils.rs b/src/template_utils.rs index 2e21c8fd..9266aa52 100644 --- a/src/template_utils.rs +++ b/src/template_utils.rs @@ -41,7 +41,7 @@ impl IntoContext for (&DbConn, &PlumeRocket) { Option<(String, String)>, ) { ( - &self.0, + self.0, &self.1.intl.catalog, self.1.user.clone(), self.1.flash_msg.clone(), diff --git a/templates/partials/comment.rs.html b/templates/partials/comment.rs.html index a1bafec3..499f9bbb 100644 --- a/templates/partials/comment.rs.html +++ b/templates/partials/comment.rs.html @@ -4,7 +4,7 @@ @(ctx: BaseContext, comment_tree: &CommentTree, in_reply_to: Option<&str>, blog: &str, slug: &str) -@if let Some(ref comm) = Some(&comment_tree.comment) { +@if let Some(comm) = Some(&comment_tree.comment) { @if let Ok(author) = comm.get_author(ctx.0) {