From e0203dbc6a3190f949612c412726f43a968f3aa0 Mon Sep 17 00:00:00 2001 From: BlackDex Date: Thu, 30 Mar 2023 17:18:59 +0200 Subject: [PATCH] WIP: WebSockets via Rocket --- Cargo.lock | 265 +++++++++++++++------------------- Cargo.toml | 16 +- src/api/notifications.rs | 230 ++++++++++++++++++++++++----- src/db/models/organization.rs | 1 + 4 files changed, 323 insertions(+), 189 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6c893cad2c6..a2bf5939c7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,7 +120,7 @@ dependencies = [ "log", "parking", "polling", - "rustix 0.37.3", + "rustix", "slab", "socket2", "waker-fn", @@ -216,7 +216,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.10", + "syn 2.0.12", ] [[package]] @@ -587,9 +587,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c00419335c41018365ddf7e4d5f1c12ee3659ddcf3e01974650ba1de73d038" +checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" dependencies = [ "cc", "cxxbridge-flags", @@ -599,9 +599,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb8307ad413a98fff033c8545ecf133e3257747b3bae935e7602aab8aa92d4ca" +checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" dependencies = [ "cc", "codespan-reporting", @@ -609,24 +609,24 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.10", + "syn 2.0.12", ] [[package]] name = "cxxbridge-flags" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc52e2eb08915cb12596d29d55f0b5384f00d697a646dbd269b6ecb0fbd9d31" +checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" [[package]] name = "cxxbridge-macro" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "631569015d0d8d54e6c241733f944042623ab6df7bc3be7466874b05fcdb1c5f" +checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.10", + "syn 2.0.12", ] [[package]] @@ -719,7 +719,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.10", + "syn 2.0.12", ] [[package]] @@ -837,17 +837,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "errno" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" -dependencies = [ - "errno-dragonfly", - "libc", - "winapi", -] - [[package]] name = "errno" version = "0.3.0" @@ -959,9 +948,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", @@ -974,9 +963,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", "futures-sink", @@ -984,15 +973,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-executor" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1997dd9df74cdac935c76252744c1ed5794fac083242ea4fe77ef3ed60ba0f83" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" dependencies = [ "futures-core", "futures-task", @@ -1001,9 +990,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[package]] name = "futures-lite" @@ -1022,26 +1011,26 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.12", ] [[package]] name = "futures-sink" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "futures-task" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" [[package]] name = "futures-timer" @@ -1051,9 +1040,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures-channel", "futures-core", @@ -1082,9 +1071,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -1412,19 +1401,19 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" +checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" [[package]] name = "is-terminal" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8687c819457e979cc940d09cb16e42a1bf70aa6b60a549de6d3a62a0ee90c69e" +checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", - "rustix 0.36.11", + "rustix", "windows-sys 0.45.0", ] @@ -1526,9 +1515,9 @@ checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" [[package]] name = "libmimalloc-sys" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8c7cbf8b89019683667e347572e6d55a7df7ea36b0c4ce69961b0cde67b174" +checksum = "ef2c45001fb108f37d41bed8efd715769acb14674c1ce3e266ef0e317ef5f877" dependencies = [ "cc", "libc", @@ -1562,15 +1551,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" - -[[package]] -name = "linux-raw-sys" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd550e73688e6d578f0ac2119e32b797a327631a42f9433e59d02e139c8df60d" +checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" [[package]] name = "lock_api" @@ -1675,9 +1658,9 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.34" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcb174b18635f7561a0c6c9fc2ce57218ac7523cf72c50af80e2d79ab8f3ba1" +checksum = "92666043c712f7f5c756d07443469ddcda6dd971cc15258bb7f3c3216fd1b7aa" dependencies = [ "libmimalloc-sys", ] @@ -1717,9 +1700,9 @@ dependencies = [ [[package]] name = "multer" -version = "2.0.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed4198ce7a4cbd2a57af78d28c6fbb57d81ac5f1d6ad79ac6c5587419cbdf22" +checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2" dependencies = [ "bytes", "encoding_rs", @@ -1729,7 +1712,7 @@ dependencies = [ "log", "memchr", "mime", - "spin 0.9.6", + "spin 0.9.7", "tokio", "tokio-util", "version_check", @@ -1946,7 +1929,7 @@ checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.2.16", "smallvec", "windows-sys 0.45.0", ] @@ -1997,7 +1980,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.10", + "syn 2.0.12", ] [[package]] @@ -2017,9 +2000,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.5.6" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cbd939b234e95d72bc393d51788aec68aeeb5d51e748ca08ff3aad58cb722f7" +checksum = "7b1403e8401ad5dedea73c626b99758535b342502f8d1e361f4a2dd952749122" dependencies = [ "thiserror", "ucd-trie", @@ -2027,9 +2010,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.5.6" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a81186863f3d0a27340815be8f2078dd8050b14cd71913db9fbda795e5f707d7" +checksum = "be99c4c1d2fc2769b1d00239431d711d08f6efedcecb8b6e30707160aee99c15" dependencies = [ "pest", "pest_generator", @@ -2037,22 +2020,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.5.6" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75a1ef20bf3193c15ac345acb32e26b3dc3223aff4d77ae4fc5359567683796b" +checksum = "e56094789873daa36164de2e822b3888c6ae4b4f9da555a1103587658c805b1e" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.12", ] [[package]] name = "pest_meta" -version = "2.5.6" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e3b284b1f13a20dc5ebc90aff59a51b8d7137c221131b52a7260c08cbc1cc80" +checksum = "6733073c7cff3d8459fda0e42f13a047870242aed8b509fe98000928975f359e" dependencies = [ "once_cell", "pest", @@ -2178,9 +2161,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.53" +version = "1.0.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73" +checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534" dependencies = [ "unicode-ident", ] @@ -2193,7 +2176,7 @@ checksum = "606c4ba35817e2922a308af55ad51bab3645b59eae5c570d4a6cf07e36bd493b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.10", + "syn 2.0.12", "version_check", "yansi", ] @@ -2310,6 +2293,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "ref-cast" version = "1.0.16" @@ -2327,7 +2319,7 @@ checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.10", + "syn 2.0.12", ] [[package]] @@ -2358,9 +2350,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "reqwest" -version = "0.11.15" +version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ba30cc2c0cd02af1222ed216ba659cdb2f879dfe3181852fe7c50b1d0005949" +checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" dependencies = [ "async-compression", "base64 0.21.0", @@ -2449,8 +2441,7 @@ dependencies = [ [[package]] name = "rocket" version = "0.5.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58734f7401ae5cfd129685b48f61182331745b357b96f2367f01aebaf1cc9cc9" +source = "git+https://github.com/SergioBenitez/Rocket?rev=fbb0ace52981fde8825cad08ec42710c4e61c216#fbb0ace52981fde8825cad08ec42710c4e61c216" dependencies = [ "async-stream", "async-trait", @@ -2488,8 +2479,7 @@ dependencies = [ [[package]] name = "rocket_codegen" version = "0.5.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7093353f14228c744982e409259fb54878ba9563d08214f2d880d59ff2fc508b" +source = "git+https://github.com/SergioBenitez/Rocket?rev=fbb0ace52981fde8825cad08ec42710c4e61c216#fbb0ace52981fde8825cad08ec42710c4e61c216" dependencies = [ "devise", "glob", @@ -2497,15 +2487,14 @@ dependencies = [ "proc-macro2", "quote", "rocket_http", - "syn 2.0.10", + "syn 2.0.12", "unicode-xid", ] [[package]] name = "rocket_http" version = "0.5.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936012c99162a03a67f37f9836d5f938f662e26f2717809761a9ac46432090f4" +source = "git+https://github.com/SergioBenitez/Rocket?rev=fbb0ace52981fde8825cad08ec42710c4e61c216#fbb0ace52981fde8825cad08ec42710c4e61c216" dependencies = [ "cookie 0.17.0", "either", @@ -2554,42 +2543,28 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4165c9963ab29e422d6c26fbc1d37f15bace6b2810221f9d925023480fcf0e" -dependencies = [ - "bitflags 1.3.2", - "errno 0.2.8", - "io-lifetimes", - "libc", - "linux-raw-sys 0.1.4", - "windows-sys 0.45.0", -] - -[[package]] -name = "rustix" -version = "0.37.3" +version = "0.37.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b24138615de35e32031d041a09032ef3487a616d901ca4db224e7d557efae2" +checksum = "d097081ed288dfe45699b72f5b5d648e5f15d64d900c7080273baa20c16a6849" dependencies = [ "bitflags 1.3.2", - "errno 0.3.0", + "errno", "io-lifetimes", "libc", - "linux-raw-sys 0.3.0", + "linux-raw-sys", "windows-sys 0.45.0", ] [[package]] name = "rustls" -version = "0.20.8" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +checksum = "07180898a28ed6a7f7ba2311594308f595e3dd2e3c3812fa0a80a47b45f17e5d" dependencies = [ "log", "ring", + "rustls-webpki", "sct", - "webpki", ] [[package]] @@ -2601,6 +2576,16 @@ dependencies = [ "base64 0.21.0", ] +[[package]] +name = "rustls-webpki" +version = "0.100.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.12" @@ -2699,9 +2684,9 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" [[package]] name = "serde" -version = "1.0.158" +version = "1.0.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9" +checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" dependencies = [ "serde_derive", ] @@ -2718,20 +2703,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.158" +version = "1.0.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad" +checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" dependencies = [ "proc-macro2", "quote", - "syn 2.0.10", + "syn 2.0.12", ] [[package]] name = "serde_json" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" +checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" dependencies = [ "itoa", "ryu", @@ -2862,9 +2847,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.9.6" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5d6e0250b93c8427a177b849d144a96d5acc57006149479403d7861ab721e34" +checksum = "c0959fd6f767df20b231736396e4f602171e00d95205676286e79d4a4eb67bef" [[package]] name = "stable-pattern" @@ -2909,9 +2894,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.10" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aad1363ed6d37b84299588d62d3a7d95b5a5c2d9aad5c85609fda12afaa1f40" +checksum = "79d9531f94112cfc3e4c8f5f02cb2b58f72c97b7efd85f70203cc6d8efda5927" dependencies = [ "proc-macro2", "quote", @@ -2933,15 +2918,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" +checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", - "rustix 0.36.11", - "windows-sys 0.42.0", + "redox_syscall 0.3.5", + "rustix", + "windows-sys 0.45.0", ] [[package]] @@ -2970,7 +2955,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.10", + "syn 2.0.12", ] [[package]] @@ -3038,14 +3023,13 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.26.0" +version = "1.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" +checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001" dependencies = [ "autocfg", "bytes", "libc", - "memchr", "mio", "num_cpus", "parking_lot", @@ -3058,13 +3042,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.8.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.12", ] [[package]] @@ -3079,13 +3063,12 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.23.4" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +checksum = "e0d409377ff5b1e3ca6437aa86c1eb7d40c134bfec254e44c830defa92669db5" dependencies = [ "rustls", "tokio", - "webpki", ] [[package]] @@ -3628,16 +3611,6 @@ dependencies = [ "url", ] -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "which" version = "4.4.0" diff --git a/Cargo.toml b/Cargo.toml index 446b8795748..0ce9a05154b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,12 +65,12 @@ rmpv = "1.0.0" # MessagePack library dashmap = "5.4.0" # Async futures -futures = "0.3.27" -tokio = { version = "1.26.0", features = ["rt-multi-thread", "fs", "io-util", "parking_lot", "time", "signal"] } +futures = "0.3.28" +tokio = { version = "1.27.0", features = ["rt-multi-thread", "fs", "io-util", "parking_lot", "time", "signal"] } # A generic serialization/deserialization framework -serde = { version = "1.0.158", features = ["derive"] } -serde_json = "1.0.94" +serde = { version = "1.0.159", features = ["derive"] } +serde_json = "1.0.95" # A safe, extensible ORM and Query builder diesel = { version = "2.0.3", features = ["chrono", "r2d2"] } @@ -122,7 +122,7 @@ email_address = "0.2.4" handlebars = { version = "4.3.6", features = ["dir_source"] } # HTTP client (Used for favicons, version check, DUO and HIBP API) -reqwest = { version = "0.11.15", features = ["stream", "json", "gzip", "brotli", "socks", "cookies", "trust-dns"] } +reqwest = { version = "0.11.16", features = ["stream", "json", "gzip", "brotli", "socks", "cookies", "trust-dns"] } # Favicon extraction libraries html5gum = "0.5.2" @@ -152,7 +152,7 @@ semver = "1.0.17" # Allow overriding the default memory allocator # Mainly used for the musl builds, since the default musl malloc is very slow -mimalloc = { version = "0.1.34", features = ["secure"], default-features = false, optional = true } +mimalloc = { version = "0.1.35", features = ["secure"], default-features = false, optional = true } which = "4.4.0" # Argon2 library with support for the PHC format @@ -161,6 +161,10 @@ argon2 = "0.5.0" # Reading a password from the cli for generating the Argon2id ADMIN_TOKEN rpassword = "7.2.0" +[patch.crates-io] +# Use newest ring +rocket = { git = 'https://github.com/SergioBenitez/Rocket', rev = 'fbb0ace52981fde8825cad08ec42710c4e61c216' } + # Strip debuginfo from the release builds # Also enable thin LTO for some optimizations [profile.release] diff --git a/src/api/notifications.rs b/src/api/notifications.rs index 2c96f0e4f29..c62879bd703 100644 --- a/src/api/notifications.rs +++ b/src/api/notifications.rs @@ -1,52 +1,211 @@ -use std::{ - net::SocketAddr, - sync::{ - atomic::{AtomicBool, Ordering}, - Arc, - }, - time::Duration, -}; +use std::{net::SocketAddr, sync::Arc, time::Duration}; use chrono::NaiveDateTime; -use futures::{SinkExt, StreamExt}; use rmpv::Value; -use rocket::Route; +use rocket::{ + data::{IoHandler, IoStream}, + futures::{future::BoxFuture, SinkExt, StreamExt}, + request::{FromRequest, Outcome}, + response::{self, Responder, Response}, + Request, Route, +}; use tokio::{ net::{TcpListener, TcpStream}, sync::mpsc::Sender, }; use tokio_tungstenite::{ accept_hdr_async, - tungstenite::{handshake, Message}, + tungstenite::{ + error::{Error as TtError, Result as TtResult}, + handshake::{self, derive_accept_key}, + protocol::Role, + Message, + }, + WebSocketStream, }; use crate::{ - api::EmptyResult, - db::models::{Cipher, Folder, Send, User}, + auth::ClientIp, + db::models::{Cipher, Folder, Send as DbSend, User}, Error, CONFIG, }; +use once_cell::sync::Lazy; + +static WS_USERS: Lazy> = Lazy::new(|| { + Arc::new(WebSocketUsers { + map: Arc::new(dashmap::DashMap::new()), + }) +}); + pub fn routes() -> Vec { - routes![websockets_err] + routes![websockets_hub] +} + +#[derive(Debug)] +pub struct WebSocket(String); + +#[derive(FromForm, Debug)] +pub struct WsAccessToken { + access_token: Option, } -#[get("/hub")] -fn websockets_err() -> EmptyResult { - static SHOW_WEBSOCKETS_MSG: AtomicBool = AtomicBool::new(true); +#[rocket::async_trait] +impl<'r> FromRequest<'r> for WebSocket { + type Error = std::convert::Infallible; + + async fn from_request(req: &'r Request<'_>) -> Outcome { + use rocket::http::uncased::eq; + + let headers = req.headers(); + let is_upgrade = headers.get("Connection").any(|h| h.split(',').any(|v| eq(v.trim(), "upgrade"))); + let is_ws = headers.get("Upgrade").any(|h| h.split(',').any(|v| eq(v.trim(), "websocket"))); + let is_ws_13 = headers.get_one("Sec-WebSocket-Version").map_or(false, |v| v == "13"); + let key = headers.get_one("Sec-WebSocket-Key").map(|k| derive_accept_key(k.as_bytes())); + match key { + Some(key) if is_upgrade && is_ws && is_ws_13 => Outcome::Success(WebSocket(key)), + Some(_) | None => Outcome::Forward(()), + } + } +} - if CONFIG.websocket_enabled() - && SHOW_WEBSOCKETS_MSG.compare_exchange(true, false, Ordering::Relaxed, Ordering::Relaxed).is_ok() +type ChannelHandler<'r> = + Box) -> BoxFuture<'static, TtResult<(), TtError>> + Send + 'r>; + +pub struct Channel<'r> { + ws: WebSocket, + handler: ChannelHandler<'r>, +} + +impl WebSocket { + pub fn channel<'r, F: Send + 'r>(self, handler: F) -> Channel<'r> + where + F: FnMut(WebSocketStream) -> BoxFuture<'static, TtResult<(), TtError>> + 'r, { - err!( - " - ########################################################### - '/notifications/hub' should be proxied to the websocket server or notifications won't work. - Go to the Wiki for more info, or disable WebSockets setting WEBSOCKET_ENABLED=false. - ###########################################################################################\n" - ) + Channel { + ws: self, + handler: Box::new(handler), + } + } +} + +impl<'r, 'o: 'r> Responder<'r, 'o> for Channel<'o> { + fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> { + Response::build() + .raw_header("Sec-Websocket-Version", "13") + .raw_header("Sec-WebSocket-Accept", self.ws.0.clone()) + .upgrade("websocket", self) + .ok() + } +} + +/// Returns `Ok(true)` if processing should continue, `Ok(false)` if processing +/// has terminated without error, and `Err(e)` if an error has occurred. +fn handle_result(result: TtResult<()>) -> std::io::Result { + match result { + Ok(_) => Ok(true), + Err(TtError::ConnectionClosed) => Ok(false), + Err(TtError::Io(e)) => Err(e), + Err(e) => Err(std::io::Error::new(std::io::ErrorKind::Other, e)), + } +} + +#[rocket::async_trait] +impl IoHandler for Channel<'_> { + async fn io(&mut self, io: IoStream) -> std::io::Result<()> { + let stream = WebSocketStream::from_raw_socket(io, Role::Server, None).await; + let result = (self.handler)(stream).await; + handle_result(result).map(|_| ()) + } +} + +#[get("/hub?")] +async fn websockets_hub<'r>(ws: WebSocket, data: WsAccessToken, ip: ClientIp) -> Result, Error> { + let addr = ip.ip; + info!("Accepting Rocket WS connection from {addr}"); + + let mut user_uuid: Option = None; + if let Some(token) = data.access_token { + if let Ok(claims) = crate::auth::decode_login(&token) { + user_uuid = Some(claims.sub); + } } else { - Err(Error::empty()) + err_code!("Invalid claim", 401) } + let user_uuid = user_uuid.expect("User UUID should be set after the handshake"); + + let res = ws.channel(move |mut stream| { + let user_uuid = user_uuid.clone(); + Box::pin(async move { + let users = Arc::clone(&WS_USERS); + // Add a channel to send messages to this client to the map + let entry_uuid = uuid::Uuid::new_v4(); + let (tx, mut rx) = tokio::sync::mpsc::channel::(100); + users.map.entry(user_uuid.clone()).or_default().push((entry_uuid, tx)); + + let mut interval = tokio::time::interval(Duration::from_secs(15)); + loop { + tokio::select! { + res = stream.next() => { + match res { + Some(Ok(message)) => { + // Respond to any pings + if let Message::Ping(ping) = message { + if stream.send(Message::Pong(ping)).await.is_err() { + break; + } + continue; + } else if let Message::Pong(_) = message { + /* Ignored */ + continue; + } + + // We should receive an initial message with the protocol and version, and we will reply to it + if let Message::Text(ref message) = message { + let msg = message.strip_suffix(RECORD_SEPARATOR as char).unwrap_or(message); + + if serde_json::from_str(msg).ok() == Some(INITIAL_MESSAGE) { + stream.send(Message::binary(INITIAL_RESPONSE)).await?; + continue; + } + } + + // Just echo anything else the client sends + if stream.send(message).await.is_err() { + break; + } + } + _ => break, + } + } + + res = rx.recv() => { + match res { + Some(res) => { + if stream.send(res).await.is_err() { + break; + } + }, + None => break, + } + } + + _ = interval.tick() => { + if stream.send(Message::Ping(create_ping())).await.is_err() { + break; + } + } + } + } + + info!("Closing Rocket WS connection from {addr}"); + // Delete from map + users.map.entry(user_uuid).or_default().retain(|(uuid, _)| uuid != &entry_uuid); + Ok(()) + }) + }); + + Ok(res) } // @@ -196,7 +355,7 @@ impl WebSocketUsers { } } - pub async fn send_send_update(&self, ut: UpdateType, send: &Send, user_uuids: &[String]) { + pub async fn send_send_update(&self, ut: UpdateType, send: &DbSend, user_uuids: &[String]) { let user_uuid = convert_option(send.user_uuid.clone()); let data = create_update( @@ -280,15 +439,12 @@ pub enum UpdateType { None = 100, } -pub type Notify<'a> = &'a rocket::State; - -pub fn start_notification_server() -> WebSocketUsers { - let users = WebSocketUsers { - map: Arc::new(dashmap::DashMap::new()), - }; +pub type Notify<'a> = &'a rocket::State>; +pub fn start_notification_server() -> Arc { + let users = Arc::clone(&WS_USERS); if CONFIG.websocket_enabled() { - let users2 = users.clone(); + let users2 = Arc::::clone(&users); tokio::spawn(async move { let addr = (CONFIG.websocket_address(), CONFIG.websocket_port()); info!("Starting WebSockets server on {}:{}", addr.0, addr.1); @@ -300,7 +456,7 @@ pub fn start_notification_server() -> WebSocketUsers { loop { tokio::select! { Ok((stream, addr)) = listener.accept() => { - tokio::spawn(handle_connection(stream, users2.clone(), addr)); + tokio::spawn(handle_connection(stream, Arc::::clone(&users2), addr)); } _ = &mut shutdown_rx => { @@ -316,7 +472,7 @@ pub fn start_notification_server() -> WebSocketUsers { users } -async fn handle_connection(stream: TcpStream, users: WebSocketUsers, addr: SocketAddr) -> Result<(), Error> { +async fn handle_connection(stream: TcpStream, users: Arc, addr: SocketAddr) -> Result<(), Error> { let mut user_uuid: Option = None; info!("Accepting WS connection from {addr}"); diff --git a/src/db/models/organization.rs b/src/db/models/organization.rs index 6010c20725a..e0b92239b92 100644 --- a/src/db/models/organization.rs +++ b/src/db/models/organization.rs @@ -715,6 +715,7 @@ impl UserOrganization { ) ) .select(users_organizations::all_columns) + .distinct() .load::(conn).expect("Error loading user organizations").from_db() }} }