diff --git a/Cargo.lock b/Cargo.lock index 84001dc..e50907d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,9 +44,9 @@ checksum = "5f093eed78becd229346bf859eec0aa4dd7ddde0757287b2b4107a1f09c80002" [[package]] name = "async-trait" -version = "0.1.48" +version = "0.1.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36ea56748e10732c49404c153638a15ec3d6211ec5ff35d9bb20e13b93576adf" +checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722" dependencies = [ "proc-macro2", "quote", @@ -153,6 +153,12 @@ dependencies = [ "jobserver", ] +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -183,6 +189,7 @@ name = "conduit" version = "0.1.0" dependencies = [ "base64 0.13.0", + "bytes", "directories", "http", "image", @@ -216,9 +223,9 @@ dependencies = [ [[package]] name = "const_fn" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076a6803b0dacd6a88cfe64deba628b01533ff5ef265687e6938280c1afd0a28" +checksum = "402da840495de3f976eaefc3485b7f5eb5b0bf9761f9a47be27fe975b3b8c2ec" [[package]] name = "constant_time_eq" @@ -226,10 +233,17 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "cookie" -version = "0.15.0-dev" -source = "git+https://github.com/SergioBenitez/cookie-rs.git?rev=1c3ca83#1c3ca838543b60a4448d279dc4b903cc7a2bc22a" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf8865bac3d9a3bde5bde9088ca431b11f5d37c7a578b8086af77248b76627" dependencies = [ "percent-encoding", "time 0.2.26", @@ -258,7 +272,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -267,7 +281,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crossbeam-utils", "lazy_static", "memoffset", @@ -281,7 +295,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" dependencies = [ "autocfg", - "cfg-if", + "cfg-if 1.0.0", "lazy_static", ] @@ -301,10 +315,22 @@ dependencies = [ "byteorder", ] +[[package]] +name = "derive_more" +version = "0.99.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f82b1b72f1263f214c0f823371768776c4f5841b942c9883aa8e5ec584fd0ba6" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "devise" version = "0.3.0" -source = "git+https://github.com/SergioBenitez/Devise.git?rev=3648468#3648468a9ede9ca896cd35bc1eb818c7a9fb3047" +source = "git+https://github.com/SergioBenitez/Devise.git?rev=df00b5#df00b5162edd53e8d496e7935774e69b5f7f6bdf" dependencies = [ "devise_codegen", "devise_core", @@ -313,7 +339,7 @@ dependencies = [ [[package]] name = "devise_codegen" version = "0.3.0" -source = "git+https://github.com/SergioBenitez/Devise.git?rev=3648468#3648468a9ede9ca896cd35bc1eb818c7a9fb3047" +source = "git+https://github.com/SergioBenitez/Devise.git?rev=df00b5#df00b5162edd53e8d496e7935774e69b5f7f6bdf" dependencies = [ "devise_core", "quote", @@ -322,7 +348,7 @@ dependencies = [ [[package]] name = "devise_core" version = "0.3.0" -source = "git+https://github.com/SergioBenitez/Devise.git?rev=3648468#3648468a9ede9ca896cd35bc1eb818c7a9fb3047" +source = "git+https://github.com/SergioBenitez/Devise.git?rev=df00b5#df00b5162edd53e8d496e7935774e69b5f7f6bdf" dependencies = [ "bitflags", "proc-macro2", @@ -375,7 +401,7 @@ version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -544,13 +570,26 @@ dependencies = [ "byteorder", ] +[[package]] +name = "generator" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061d3be1afec479d56fa3bd182bf966c7999ec175fcfdb87ac14d417241366c6" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "winapi", +] + [[package]] name = "getrandom" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] @@ -561,7 +600,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi 0.10.2+wasi-snapshot-preview1", ] @@ -660,15 +699,15 @@ dependencies = [ [[package]] name = "httparse" -version = "1.3.6" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc35c995b9d93ec174cf9a27d425c7892722101e14993cd227fdb51d70cf9589" +checksum = "4a1ce40d6fc9764887c2fdc7305c3dcc429ba11ff981c1509416afd5697e4437" [[package]] name = "httpdate" -version = "0.3.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" +checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9" [[package]] name = "humantime" @@ -681,9 +720,9 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.5" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf09f61b52cfcf4c00de50df88ae423d6c02354e385a86341133b5338630ad1" +checksum = "1e5f105c494081baa3bf9e200b279e27ec1623895cd504c7dbef8d0b080fcf54" dependencies = [ "bytes", "futures-channel", @@ -720,9 +759,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" dependencies = [ "matches", "unicode-bidi", @@ -769,7 +808,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -822,9 +861,9 @@ checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" [[package]] name = "jobserver" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" +checksum = "972f5ae5d1cb9c6ae417789196c803205313edde988685da5e3aae0827b9e7fd" dependencies = [ "libc", ] @@ -900,7 +939,20 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", +] + +[[package]] +name = "loom" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0e8460f2f2121162705187214720353c517b97bdfb3494c0b1e33d83ebe4bed" +dependencies = [ + "cfg-if 0.1.10", + "generator", + "scoped-tls", + "serde", + "serde_json", ] [[package]] @@ -991,6 +1043,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "multer" +version = "1.2.2" +source = "git+https://github.com/rousan/multer-rs.git?rev=7e4f0c5f#7e4f0c5fe14e4c531f503922bfe04f68b32ddf17" +dependencies = [ + "bytes", + "derive_more", + "encoding_rs", + "futures-util", + "http", + "httparse", + "log", + "mime", + "tokio", + "tokio-util", + "twoway", + "version_check", +] + [[package]] name = "ntapi" version = "0.3.6" @@ -1129,10 +1200,10 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "instant", "libc", - "redox_syscall 0.2.5", + "redox_syscall 0.2.6", "smallvec", "winapi", ] @@ -1185,18 +1256,18 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pin-project" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc174859768806e91ae575187ada95c91a29e96a98dc5d2cd9a1fed039501ba6" +checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a490329918e856ed1b083f244e3bfe2d8c4f336407e4ea9e1a9f479ff09049e5" +checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f" dependencies = [ "proc-macro2", "quote", @@ -1350,9 +1421,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" +checksum = "8270314b5ccceb518e7e578952f0b72b88222d02e8f77f5ecf7abbb673539041" dependencies = [ "bitflags", ] @@ -1390,9 +1461,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.4.5" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19" +checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759" dependencies = [ "aho-corasick", "memchr", @@ -1415,6 +1486,15 @@ version = "0.6.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548" +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + [[package]] name = "reqwest" version = "0.11.3" @@ -1478,27 +1558,33 @@ dependencies = [ [[package]] name = "rocket" version = "0.5.0-dev" -source = "git+https://github.com/SergioBenitez/Rocket.git?rev=93e62c86eddf7cc9a7fc40b044182f83f0d7d92a#93e62c86eddf7cc9a7fc40b044182f83f0d7d92a" +source = "git+https://github.com/SergioBenitez/Rocket.git?rev=801e04bd5369eb39e126c75f6d11e1e9597304d8#801e04bd5369eb39e126c75f6d11e1e9597304d8" dependencies = [ "async-trait", "atomic", "atty", "binascii", + "bytes", "either", "figment", "futures", + "indexmap", "log", "memchr", + "multer", "num_cpus", "parking_lot", + "pin-project-lite", "rand", "ref-cast", "rocket_codegen", "rocket_http", "serde", "state", + "tempfile", "time 0.2.26", "tokio", + "tokio-util", "ubyte", "version_check", "yansi", @@ -1507,19 +1593,20 @@ dependencies = [ [[package]] name = "rocket_codegen" version = "0.5.0-dev" -source = "git+https://github.com/SergioBenitez/Rocket.git?rev=93e62c86eddf7cc9a7fc40b044182f83f0d7d92a#93e62c86eddf7cc9a7fc40b044182f83f0d7d92a" +source = "git+https://github.com/SergioBenitez/Rocket.git?rev=801e04bd5369eb39e126c75f6d11e1e9597304d8#801e04bd5369eb39e126c75f6d11e1e9597304d8" dependencies = [ "devise", "glob", "indexmap", "quote", "rocket_http", + "unicode-xid", ] [[package]] name = "rocket_http" version = "0.5.0-dev" -source = "git+https://github.com/SergioBenitez/Rocket.git?rev=93e62c86eddf7cc9a7fc40b044182f83f0d7d92a#93e62c86eddf7cc9a7fc40b044182f83f0d7d92a" +source = "git+https://github.com/SergioBenitez/Rocket.git?rev=801e04bd5369eb39e126c75f6d11e1e9597304d8#801e04bd5369eb39e126c75f6d11e1e9597304d8" dependencies = [ "cookie", "either", @@ -1527,26 +1614,27 @@ dependencies = [ "hyper", "indexmap", "log", + "memchr", "mime", "parking_lot", "pear", "percent-encoding", "pin-project-lite", "ref-cast", + "serde", "smallvec", + "stable-pattern", "state", "time 0.2.26", "tokio", "tokio-rustls", "uncased", - "unicode-xid", - "version_check", ] [[package]] name = "ruma" -version = "0.0.2" -source = "git+https://github.com/ruma/ruma?rev=c1693569f15920e408aa6a26b7f3cc7fc6693a63#c1693569f15920e408aa6a26b7f3cc7fc6693a63" +version = "0.0.3" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "assign", "js_int", @@ -1565,9 +1653,10 @@ dependencies = [ [[package]] name = "ruma-api" -version = "0.17.0-alpha.2" -source = "git+https://github.com/ruma/ruma?rev=c1693569f15920e408aa6a26b7f3cc7fc6693a63#c1693569f15920e408aa6a26b7f3cc7fc6693a63" +version = "0.17.0-alpha.4" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ + "bytes", "http", "percent-encoding", "ruma-api-macros", @@ -1580,8 +1669,8 @@ dependencies = [ [[package]] name = "ruma-api-macros" -version = "0.17.0-alpha.2" -source = "git+https://github.com/ruma/ruma?rev=c1693569f15920e408aa6a26b7f3cc7fc6693a63#c1693569f15920e408aa6a26b7f3cc7fc6693a63" +version = "0.17.0-alpha.4" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1591,8 +1680,8 @@ dependencies = [ [[package]] name = "ruma-appservice-api" -version = "0.2.0-alpha.2" -source = "git+https://github.com/ruma/ruma?rev=c1693569f15920e408aa6a26b7f3cc7fc6693a63#c1693569f15920e408aa6a26b7f3cc7fc6693a63" +version = "0.2.0-alpha.3" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "ruma-api", "ruma-common", @@ -1605,10 +1694,11 @@ dependencies = [ [[package]] name = "ruma-client-api" -version = "0.10.0-alpha.2" -source = "git+https://github.com/ruma/ruma?rev=c1693569f15920e408aa6a26b7f3cc7fc6693a63#c1693569f15920e408aa6a26b7f3cc7fc6693a63" +version = "0.10.0-alpha.3" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "assign", + "bytes", "http", "js_int", "maplit", @@ -1624,8 +1714,8 @@ dependencies = [ [[package]] name = "ruma-common" -version = "0.4.0" -source = "git+https://github.com/ruma/ruma?rev=c1693569f15920e408aa6a26b7f3cc7fc6693a63#c1693569f15920e408aa6a26b7f3cc7fc6693a63" +version = "0.5.0" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "indexmap", "js_int", @@ -1640,8 +1730,8 @@ dependencies = [ [[package]] name = "ruma-events" -version = "0.22.0-alpha.2" -source = "git+https://github.com/ruma/ruma?rev=c1693569f15920e408aa6a26b7f3cc7fc6693a63#c1693569f15920e408aa6a26b7f3cc7fc6693a63" +version = "0.22.0-alpha.3" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "js_int", "ruma-common", @@ -1654,8 +1744,8 @@ dependencies = [ [[package]] name = "ruma-events-macros" -version = "0.22.0-alpha.2" -source = "git+https://github.com/ruma/ruma?rev=c1693569f15920e408aa6a26b7f3cc7fc6693a63#c1693569f15920e408aa6a26b7f3cc7fc6693a63" +version = "0.22.0-alpha.3" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1665,8 +1755,8 @@ dependencies = [ [[package]] name = "ruma-federation-api" -version = "0.1.0-alpha.1" -source = "git+https://github.com/ruma/ruma?rev=c1693569f15920e408aa6a26b7f3cc7fc6693a63#c1693569f15920e408aa6a26b7f3cc7fc6693a63" +version = "0.1.0-alpha.2" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "js_int", "ruma-api", @@ -1681,7 +1771,7 @@ dependencies = [ [[package]] name = "ruma-identifiers" version = "0.19.0" -source = "git+https://github.com/ruma/ruma?rev=c1693569f15920e408aa6a26b7f3cc7fc6693a63#c1693569f15920e408aa6a26b7f3cc7fc6693a63" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "paste", "rand", @@ -1695,7 +1785,7 @@ dependencies = [ [[package]] name = "ruma-identifiers-macros" version = "0.19.0" -source = "git+https://github.com/ruma/ruma?rev=c1693569f15920e408aa6a26b7f3cc7fc6693a63#c1693569f15920e408aa6a26b7f3cc7fc6693a63" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "proc-macro2", "quote", @@ -1705,13 +1795,13 @@ dependencies = [ [[package]] name = "ruma-identifiers-validation" -version = "0.2.3" -source = "git+https://github.com/ruma/ruma?rev=c1693569f15920e408aa6a26b7f3cc7fc6693a63#c1693569f15920e408aa6a26b7f3cc7fc6693a63" +version = "0.3.0" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" [[package]] name = "ruma-identity-service-api" -version = "0.0.1" -source = "git+https://github.com/ruma/ruma?rev=c1693569f15920e408aa6a26b7f3cc7fc6693a63#c1693569f15920e408aa6a26b7f3cc7fc6693a63" +version = "0.1.0-alpha.1" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "ruma-api", "ruma-common", @@ -1723,8 +1813,8 @@ dependencies = [ [[package]] name = "ruma-push-gateway-api" -version = "0.0.1" -source = "git+https://github.com/ruma/ruma?rev=c1693569f15920e408aa6a26b7f3cc7fc6693a63#c1693569f15920e408aa6a26b7f3cc7fc6693a63" +version = "0.1.0-alpha.1" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "js_int", "ruma-api", @@ -1739,8 +1829,9 @@ dependencies = [ [[package]] name = "ruma-serde" version = "0.3.1" -source = "git+https://github.com/ruma/ruma?rev=c1693569f15920e408aa6a26b7f3cc7fc6693a63#c1693569f15920e408aa6a26b7f3cc7fc6693a63" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ + "bytes", "form_urlencoded", "itoa", "js_int", @@ -1752,7 +1843,7 @@ dependencies = [ [[package]] name = "ruma-serde-macros" version = "0.3.1" -source = "git+https://github.com/ruma/ruma?rev=c1693569f15920e408aa6a26b7f3cc7fc6693a63#c1693569f15920e408aa6a26b7f3cc7fc6693a63" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1763,7 +1854,7 @@ dependencies = [ [[package]] name = "ruma-signatures" version = "0.7.0" -source = "git+https://github.com/ruma/ruma?rev=c1693569f15920e408aa6a26b7f3cc7fc6693a63#c1693569f15920e408aa6a26b7f3cc7fc6693a63" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "base64 0.13.0", "ring", @@ -1796,9 +1887,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.19.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "064fd21ff87c6e87ed4506e68beb42459caa4a0e2eb144932e6776768556980b" +checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" dependencies = [ "base64 0.13.0", "log", @@ -1819,6 +1910,12 @@ dependencies = [ "security-framework", ] +[[package]] +name = "rustversion" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd" + [[package]] name = "ryu" version = "1.0.5" @@ -1835,6 +1932,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + [[package]] name = "scopeguard" version = "1.1.0" @@ -1981,9 +2084,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" [[package]] name = "sled" @@ -2014,7 +2117,7 @@ version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "winapi", ] @@ -2035,6 +2138,15 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "stable-pattern" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4564168c00635f88eaed410d5efa8131afa8d8699a612c80c455a0ba05c21045" +dependencies = [ + "memchr", +] + [[package]] name = "standback" version = "0.2.17" @@ -2047,13 +2159,15 @@ dependencies = [ [[package]] name = "state" version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3015a7d0a5fd5105c91c3710d42f9ccf0abfb287d62206484dcc67f9569a6483" +source = "git+https://github.com/SergioBenitez/state.git?rev=8f94dc#8f94dce673b7d4b0e7b96c808a84f5e2a4be4a60" +dependencies = [ + "loom", +] [[package]] name = "state-res" version = "0.1.0" -source = "git+https://github.com/ruma/state-res?rev=4516d73e8c7495330619bfb5b42c3bbf704293d8#4516d73e8c7495330619bfb5b42c3bbf704293d8" +source = "git+https://github.com/ruma/state-res?rev=1dd252d1c97a38def74bc097c197a33179ed8fbb#1dd252d1c97a38def74bc097c197a33179ed8fbb" dependencies = [ "itertools 0.10.0", "log", @@ -2115,15 +2229,29 @@ checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" [[package]] name = "syn" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb" +checksum = "b9505f307c872bab8eb46f77ae357c8eba1fdacead58ee5a850116b1d7f82883" dependencies = [ "proc-macro2", "quote", "unicode-xid", ] +[[package]] +name = "tempfile" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "rand", + "redox_syscall 0.2.6", + "remove_dir_all", + "winapi", +] + [[package]] name = "termcolor" version = "1.1.2" @@ -2323,7 +2451,7 @@ version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2407,12 +2535,12 @@ dependencies = [ [[package]] name = "trust-dns-proto" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d57e219ba600dd96c2f6d82eb79645068e14edbc5c7e27514af40436b88150c" +checksum = "952a078337565ba39007de99b151770f41039253a31846f0a3d5cd5a4ac8eedf" dependencies = [ "async-trait", - "cfg-if", + "cfg-if 1.0.0", "data-encoding", "enum-as-inner", "futures-channel", @@ -2432,11 +2560,11 @@ dependencies = [ [[package]] name = "trust-dns-resolver" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0437eea3a6da51acc1e946545ff53d5b8fb2611ff1c3bed58522dde100536ae" +checksum = "da9c97f7d103e0f94dbe384a57908833505ae5870126492f166821b7cf685589" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "futures-util", "ipconfig", "lazy_static", @@ -2456,6 +2584,16 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +[[package]] +name = "twoway" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b40075910de3a912adbd80b5d8bad6ad10a23eeb1f5bf9d4006839e899ba5bc" +dependencies = [ + "memchr", + "unchecked-index", +] + [[package]] name = "ubyte" version = "0.10.1" @@ -2471,9 +2609,16 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baeed7327e25054889b9bd4f975f32e5f4c5d434042d59ab6cd4142c0a76ed0" dependencies = [ + "serde", "version_check", ] +[[package]] +name = "unchecked-index" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c" + [[package]] name = "unicode-bidi" version = "0.3.5" @@ -2556,7 +2701,7 @@ version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "serde", "serde_json", "wasm-bindgen-macro", @@ -2583,7 +2728,7 @@ version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81b8b767af23de6ac18bf2168b690bed2902743ddf0fb39252e36f9e2bfc63ea" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -2640,9 +2785,9 @@ dependencies = [ [[package]] name = "weezl" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a32b378380f4e9869b22f0b5177c68a5519f03b3454fde0b291455ddbae266c" +checksum = "d8b77fdfd5a253be4ab714e4ffa3c49caf146b4de743e97510c0656cf90f1e8e" [[package]] name = "widestring" diff --git a/Cargo.toml b/Cargo.toml index fa495df..a800350 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,16 +14,16 @@ edition = "2018" [dependencies] # Used to handle requests # TODO: This can become optional as soon as proper configs are supported -rocket = { git = "https://github.com/SergioBenitez/Rocket.git", rev = "93e62c86eddf7cc9a7fc40b044182f83f0d7d92a", features = ["tls"] } # Used to handle requests +rocket = { git = "https://github.com/SergioBenitez/Rocket.git", rev = "801e04bd5369eb39e126c75f6d11e1e9597304d8", features = ["tls"] } # Used to handle requests #rocket = { git = "https://github.com/timokoesters/Rocket.git", branch = "empty_parameters", default-features = false, features = ["tls"] } # Used for matrix spec type definitions and helpers -ruma = { git = "https://github.com/ruma/ruma", rev = "c1693569f15920e408aa6a26b7f3cc7fc6693a63", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "unstable-pre-spec", "unstable-exhaustive-types"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "unstable-pre-spec", "unstable-exhaustive-types"] } #ruma = { git = "https://github.com/timokoesters/ruma", rev = "220d5b4a76b3b781f7f8297fbe6b14473b04214b", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "unstable-pre-spec", "unstable-exhaustive-types"] } #ruma = { path = "../ruma/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "unstable-pre-spec", "unstable-exhaustive-types"] } # Used when doing state resolution -state-res = { git = "https://github.com/ruma/state-res", rev = "4516d73e8c7495330619bfb5b42c3bbf704293d8", features = ["unstable-pre-spec"] } +state-res = { git = "https://github.com/ruma/state-res", rev = "1dd252d1c97a38def74bc097c197a33179ed8fbb", features = ["unstable-pre-spec"] } #state-res = { path = "../state-res", features = ["unstable-pre-spec"] } # Used for long polling and federation sender, should be the same as rocket::tokio @@ -32,6 +32,8 @@ tokio = "1.2.0" sled = { version = "0.34.6", features = ["compression", "no_metrics"] } #sled = { git = "https://github.com/spacejam/sled.git", rev = "e4640e0773595229f398438886f19bca6f7326a2", features = ["compression"] } +# Used for the http request / response body type for Ruma endpoints used with reqwest +bytes = "1.0.1" # Used for emitting log entries log = "0.4.14" # Used for rocket<->ruma conversions diff --git a/src/appservice_server.rs b/src/appservice_server.rs index 1b72c76..8f64edf 100644 --- a/src/appservice_server.rs +++ b/src/appservice_server.rs @@ -1,7 +1,8 @@ use crate::{utils, Error, Result}; +use bytes::BytesMut; use http::header::{HeaderValue, CONTENT_TYPE}; use log::warn; -use ruma::api::{IncomingResponse, OutgoingRequest}; +use ruma::api::{IncomingResponse, OutgoingRequest, SendAccessToken}; use std::{ convert::{TryFrom, TryInto}, fmt::Debug, @@ -20,8 +21,9 @@ where let hs_token = registration.get("hs_token").unwrap().as_str().unwrap(); let mut http_request = request - .try_into_http_request(&destination, Some("")) - .unwrap(); + .try_into_http_request::(&destination, SendAccessToken::IfRequired("")) + .unwrap() + .map(|body| body.freeze()); let mut parts = http_request.uri().clone().into_parts(); let old_path_and_query = parts.path_and_query.unwrap().as_str().to_owned(); @@ -49,51 +51,46 @@ where *reqwest_request.timeout_mut() = Some(Duration::from_secs(30)); let url = reqwest_request.url().clone(); - let reqwest_response = globals.reqwest_client().execute(reqwest_request).await; + let mut reqwest_response = globals.reqwest_client().execute(reqwest_request).await?; // Because reqwest::Response -> http::Response is complicated: - match reqwest_response { - Ok(mut reqwest_response) => { - let status = reqwest_response.status(); - let mut http_response = http::Response::builder().status(status); - let headers = http_response.headers_mut().unwrap(); + let status = reqwest_response.status(); + let mut http_response = http::Response::builder().status(status); + let headers = http_response.headers_mut().unwrap(); - for (k, v) in reqwest_response.headers_mut().drain() { - if let Some(key) = k { - headers.insert(key, v); - } - } - - let status = reqwest_response.status(); - - let body = reqwest_response.bytes().await.unwrap_or_else(|e| { - warn!("server error: {}", e); - Vec::new().into() - }); // TODO: handle timeout - - if status != 200 { - warn!( - "Appservice returned bad response {} {}\n{}\n{:?}", - destination, - status, - url, - utils::string_from_bytes(&body) - ); - } - - let response = T::IncomingResponse::try_from_http_response( - http_response - .body(body) - .expect("reqwest body is valid http body"), - ); - response.map_err(|_| { - warn!( - "Appservice returned invalid response bytes {}\n{}", - destination, url - ); - Error::BadServerResponse("Server returned bad response.") - }) + for (k, v) in reqwest_response.headers_mut().drain() { + if let Some(key) = k { + headers.insert(key, v); } - Err(e) => Err(e.into()), } + + let status = reqwest_response.status(); + + let body = reqwest_response.bytes().await.unwrap_or_else(|e| { + warn!("server error: {}", e); + Vec::new().into() + }); // TODO: handle timeout + + if status != 200 { + warn!( + "Appservice returned bad response {} {}\n{}\n{:?}", + destination, + status, + url, + utils::string_from_bytes(&body) + ); + } + + let response = T::IncomingResponse::try_from_http_response( + http_response + .body(body) + .expect("reqwest body is valid http body"), + ); + response.map_err(|_| { + warn!( + "Appservice returned invalid response bytes {}\n{}", + destination, url + ); + Error::BadServerResponse("Server returned bad response.") + }) } diff --git a/src/client_server/message.rs b/src/client_server/message.rs index 04f27de..ecd2665 100644 --- a/src/client_server/message.rs +++ b/src/client_server/message.rs @@ -5,7 +5,7 @@ use ruma::{ error::ErrorKind, r0::message::{get_message_events, send_message_event}, }, - events::EventContent, + events::EventType, EventId, }; use std::{ @@ -55,7 +55,7 @@ pub async fn send_message_event_route( let event_id = db.rooms.build_and_append_pdu( PduBuilder { - event_type: body.content.event_type().into(), + event_type: EventType::from(&body.event_type), content: serde_json::from_str( body.json_body .as_ref() diff --git a/src/client_server/session.rs b/src/client_server/session.rs index cb6442d..3718003 100644 --- a/src/client_server/session.rs +++ b/src/client_server/session.rs @@ -26,7 +26,12 @@ use rocket::{get, post}; #[cfg_attr(feature = "conduit_bin", get("/_matrix/client/r0/login"))] #[tracing::instrument] pub async fn get_login_types_route() -> ConduitResult { - Ok(get_login_types::Response::new(vec![get_login_types::LoginType::Password]).into()) + Ok( + get_login_types::Response::new(vec![get_login_types::LoginType::Password( + Default::default(), + )]) + .into(), + ) } /// # `POST /_matrix/client/r0/login` diff --git a/src/client_server/state.rs b/src/client_server/state.rs index 88cce03..68e0c7f 100644 --- a/src/client_server/state.rs +++ b/src/client_server/state.rs @@ -6,9 +6,13 @@ use ruma::{ r0::state::{get_state_events, get_state_events_for_key, send_state_event}, }, events::{ - room::history_visibility::{HistoryVisibility, HistoryVisibilityEventContent}, - AnyStateEventContent, EventContent, EventType, + room::{ + canonical_alias::CanonicalAliasEventContent, + history_visibility::{HistoryVisibility, HistoryVisibilityEventContent}, + }, + AnyStateEventContent, EventType, }, + serde::Raw, EventId, RoomId, UserId, }; @@ -26,21 +30,13 @@ pub async fn send_state_event_for_key_route( ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); - let content = serde_json::from_str::( - body.json_body - .as_ref() - .ok_or(Error::BadRequest(ErrorKind::BadJson, "Invalid JSON body."))? - .get(), - ) - .map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Invalid JSON body."))?; - let event_id = send_state_event_for_key_helper( &db, sender_user, - &body.content, - content, &body.room_id, - Some(body.state_key.to_owned()), + EventType::from(&body.event_type), + &body.body.body, // Yes, I hate it too + body.state_key.to_owned(), ) .await?; @@ -58,31 +54,15 @@ pub async fn send_state_event_for_empty_key_route( db: State<'_, Database>, body: Ruma>, ) -> ConduitResult { - // This just calls send_state_event_for_key_route - let Ruma { - body, - sender_user, - json_body, - .. - } = body; - - let json = serde_json::from_str::( - json_body - .as_ref() - .ok_or(Error::BadRequest(ErrorKind::BadJson, "Invalid JSON body."))? - .get(), - ) - .map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Invalid JSON body."))?; + let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let event_id = send_state_event_for_key_helper( &db, - sender_user - .as_ref() - .expect("no user for send state empty key route"), - &body.content, - json, + sender_user, &body.room_id, - Some("".into()), + EventType::from(&body.event_type), + &body.body.body, + body.state_key.to_owned(), ) .await?; @@ -183,7 +163,7 @@ pub async fn get_state_events_for_key_route( ))?; Ok(get_state_events_for_key::Response { - content: serde_json::value::to_raw_value(&event.content) + content: serde_json::from_value(event.content) .map_err(|_| Error::bad_database("Invalid event content in database"))?, } .into()) @@ -234,7 +214,7 @@ pub async fn get_state_events_for_empty_key_route( ))?; Ok(get_state_events_for_key::Response { - content: serde_json::value::to_raw_value(&event.content) + content: serde_json::from_value(event.content) .map_err(|_| Error::bad_database("Invalid event content in database"))?, } .into()) @@ -243,17 +223,19 @@ pub async fn get_state_events_for_empty_key_route( pub async fn send_state_event_for_key_helper( db: &Database, sender: &UserId, - content: &AnyStateEventContent, - json: serde_json::Value, room_id: &RoomId, - state_key: Option, + event_type: EventType, + json: &Raw, + state_key: String, ) -> Result { let sender_user = sender; - if let AnyStateEventContent::RoomCanonicalAlias(canonical_alias) = content { + if let Ok(canonical_alias) = + serde_json::from_str::(json.json().get()) + { let mut aliases = canonical_alias.alt_aliases.clone(); - if let Some(alias) = canonical_alias.alias.clone() { + if let Some(alias) = canonical_alias.alias { aliases.push(alias); } @@ -276,10 +258,10 @@ pub async fn send_state_event_for_key_helper( let event_id = db.rooms.build_and_append_pdu( PduBuilder { - event_type: content.event_type().into(), - content: json, + event_type, + content: serde_json::from_str(json.json().get()).expect("content is valid json"), unsigned: None, - state_key, + state_key: Some(state_key), redacts: None, }, &sender_user, diff --git a/src/database/globals.rs b/src/database/globals.rs index acecf02..04f8d29 100644 --- a/src/database/globals.rs +++ b/src/database/globals.rs @@ -52,7 +52,10 @@ impl ServerCertVerifier for MatrixServerVerifier { if result.is_ok() { return result; } - info!("Server {:?} is non-compliant, retrying TLS verification with original name", dns_name); + info!( + "Server {:?} is non-compliant, retrying TLS verification with original name", + dns_name + ); } self.inner .verify_server_cert(roots, presented_certs, dns_name, ocsp_response) diff --git a/src/database/pusher.rs b/src/database/pusher.rs index 40b829f..7c7abb3 100644 --- a/src/database/pusher.rs +++ b/src/database/pusher.rs @@ -1,13 +1,14 @@ use crate::{Database, Error, PduEvent, Result}; +use bytes::BytesMut; use log::{error, info, warn}; use ruma::{ api::{ - client::r0::push::{Pusher, PusherKind}, + client::r0::push::{get_pushers, set_pusher, PusherKind}, push_gateway::send_event_notification::{ self, v1::{Device, Notification, NotificationCounts, NotificationPriority}, }, - IncomingResponse, OutgoingRequest, + IncomingResponse, OutgoingRequest, SendAccessToken, }, events::{room::power_levels::PowerLevelsEventContent, EventType}, push::{Action, PushConditionRoomCtx, PushFormat, Ruleset, Tweak}, @@ -30,7 +31,7 @@ impl PushData { }) } - pub fn set_pusher(&self, sender: &UserId, pusher: Pusher) -> Result<()> { + pub fn set_pusher(&self, sender: &UserId, pusher: set_pusher::Pusher) -> Result<()> { let mut key = sender.as_bytes().to_vec(); key.push(0xff); key.extend_from_slice(pusher.pushkey.as_bytes()); @@ -52,7 +53,7 @@ impl PushData { Ok(()) } - pub fn get_pusher(&self, senderkey: &[u8]) -> Result> { + pub fn get_pusher(&self, senderkey: &[u8]) -> Result> { self.senderkey_pusher .get(senderkey)? .map(|push| { @@ -62,7 +63,7 @@ impl PushData { .transpose() } - pub fn get_pushers(&self, sender: &UserId) -> Result> { + pub fn get_pushers(&self, sender: &UserId) -> Result> { let mut prefix = sender.as_bytes().to_vec(); prefix.push(0xff); @@ -99,11 +100,12 @@ where let destination = destination.replace("/_matrix/push/v1/notify", ""); let http_request = request - .try_into_http_request(&destination, Some("")) + .try_into_http_request::(&destination, SendAccessToken::IfRequired("")) .map_err(|e| { warn!("Failed to find destination {}: {}", destination, e); Error::BadServerResponse("Invalid destination") - })?; + })? + .map(|body| body.freeze()); let reqwest_request = reqwest::Request::try_from(http_request) .expect("all http requests are valid reqwest requests"); @@ -164,7 +166,7 @@ where pub async fn send_push_notice( user: &UserId, unread: UInt, - pusher: &Pusher, + pusher: &get_pushers::Pusher, ruleset: Ruleset, pdu: &PduEvent, db: &Database, @@ -205,7 +207,7 @@ pub fn get_actions<'a>( ruleset: &'a Ruleset, pdu: &PduEvent, db: &Database, -) -> Result> { +) -> Result<&'a [Action]> { let power_levels: PowerLevelsEventContent = db .rooms .room_state_get(&pdu.room_id, &EventType::RoomPowerLevels, "")? @@ -228,20 +230,18 @@ pub fn get_actions<'a>( notification_power_levels: power_levels.notifications, }; - Ok(ruleset - .get_actions(&pdu.to_sync_room_event(), &ctx) - .map(Clone::clone)) + Ok(ruleset.get_actions(&pdu.to_sync_room_event(), &ctx)) } async fn send_notice( unread: UInt, - pusher: &Pusher, + pusher: &get_pushers::Pusher, tweaks: Vec, event: &PduEvent, db: &Database, ) -> Result<()> { // TODO: email - if pusher.kind == Some(PusherKind::Email) { + if pusher.kind == PusherKind::Email { return Ok(()); } @@ -250,7 +250,7 @@ async fn send_notice( // 1. if "event_id_only" is the only format kind it seems we should never add more info // 2. can pusher/devices have conflicting formats let event_id_only = pusher.data.format == Some(PushFormat::EventIdOnly); - let url = if let Some(url) = pusher.data.url.as_ref() { + let url = if let Some(url) = &pusher.data.url { url } else { error!("Http Pusher must have URL specified."); diff --git a/src/database/rooms/edus.rs b/src/database/rooms/edus.rs index c48f4c2..f69e897 100644 --- a/src/database/rooms/edus.rs +++ b/src/database/rooms/edus.rs @@ -9,7 +9,7 @@ use ruma::{ RoomId, UInt, UserId, }; use std::{ - collections::HashMap, + collections::{HashMap, HashSet}, convert::{TryFrom, TryInto}, mem, }; @@ -280,7 +280,7 @@ impl RoomEdus { let mut prefix = room_id.as_bytes().to_vec(); prefix.push(0xff); - let mut user_ids = Vec::new(); + let mut user_ids = HashSet::new(); for user_id in self .typingid_userid @@ -295,11 +295,13 @@ impl RoomEdus { ) }) { - user_ids.push(user_id?); + user_ids.insert(user_id?); } Ok(SyncEphemeralRoomEvent { - content: ruma::events::typing::TypingEventContent { user_ids }, + content: ruma::events::typing::TypingEventContent { + user_ids: user_ids.into_iter().collect(), + }, }) } diff --git a/src/main.rs b/src/main.rs index ba8448d..af1ddac 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,7 +21,6 @@ pub use ruma_wrapper::{ConduitResult, Ruma, RumaResponse}; use rocket::{ catch, catchers, - fairing::AdHoc, figment::{ providers::{Env, Format, Toml}, Figment, @@ -31,26 +30,9 @@ use rocket::{ use tracing::span; use tracing_subscriber::{prelude::*, Registry}; -fn setup_rocket() -> (rocket::Rocket, Config) { - // Force log level off, so we can use our own logger - std::env::set_var("CONDUIT_LOG_LEVEL", "off"); - - let config = - Figment::from(rocket::Config::release_default()) - .merge( - Toml::file(Env::var("CONDUIT_CONFIG").expect( - "The CONDUIT_CONFIG env var needs to be set. Example: /etc/conduit.toml", - )) - .nested(), - ) - .merge(Env::prefixed("CONDUIT_").global()); - - let parsed_config = config - .extract::() - .expect("It looks like your config is invalid. Please take a look at the error"); - let parsed_config2 = parsed_config.clone(); - +fn setup_rocket(config: Figment, data: Database) -> rocket::Rocket { let rocket = rocket::custom(config) + .manage(data) .mount( "/", routes![ @@ -176,29 +158,44 @@ fn setup_rocket() -> (rocket::Rocket, Config) { server_server::get_profile_information_route, ], ) - .register(catchers![ - not_found_catcher, - forbidden_catcher, - unknown_token_catcher, - missing_token_catcher, - bad_json_catcher - ]) - .attach(AdHoc::on_attach("Config", |rocket| async { - let data = Database::load_or_create(parsed_config2) - .await - .expect("config is valid"); + .register( + "/", + catchers![ + not_found_catcher, + forbidden_catcher, + unknown_token_catcher, + missing_token_catcher, + bad_json_catcher + ], + ); - data.sending.start_handler(&data); - - Ok(rocket.manage(data)) - })); - - (rocket, parsed_config) + rocket } #[rocket::main] async fn main() { - let (rocket, config) = setup_rocket(); + // Force log level off, so we can use our own logger + std::env::set_var("CONDUIT_LOG_LEVEL", "off"); + + let raw_config = + Figment::from(rocket::Config::release_default()) + .merge( + Toml::file(Env::var("CONDUIT_CONFIG").expect( + "The CONDUIT_CONFIG env var needs to be set. Example: /etc/conduit.toml", + )) + .nested(), + ) + .merge(Env::prefixed("CONDUIT_").global()); + + let config = raw_config + .extract::() + .expect("It looks like your config is invalid. Please take a look at the error"); + + let db = Database::load_or_create(config.clone()) + .await + .expect("config is valid"); + + db.sending.start_handler(&db); if config.allow_jaeger { let (tracer, _uninstall) = opentelemetry_jaeger::new_pipeline() @@ -210,17 +207,13 @@ async fn main() { let root = span!(tracing::Level::INFO, "app_start", work_units = 2); let _enter = root.enter(); - - rocket.launch().await.unwrap(); } else { std::env::set_var("CONDUIT_LOG", config.log); pretty_env_logger::init_custom_env("CONDUIT_LOG"); - - let root = span!(tracing::Level::INFO, "app_start", work_units = 2); - let _enter = root.enter(); - - rocket.launch().await.unwrap(); } + + let rocket = setup_rocket(raw_config, db); + rocket.launch().await.unwrap(); } #[catch(404)] diff --git a/src/ruma_wrapper.rs b/src/ruma_wrapper.rs index c60c04e..49a9fb0 100644 --- a/src/ruma_wrapper.rs +++ b/src/ruma_wrapper.rs @@ -8,20 +8,22 @@ use std::ops::Deref; #[cfg(feature = "conduit_bin")] use { - crate::utils, + crate::{server_server, utils}, log::{debug, warn}, rocket::{ - data::{ - ByteUnit, Data, FromDataFuture, FromTransformedData, Transform, TransformFuture, - Transformed, - }, + data::{self, ByteUnit, Data, FromData}, http::Status, outcome::Outcome::*, response::{self, Responder}, tokio::io::AsyncReadExt, Request, State, }, - ruma::api::{AuthScheme, IncomingRequest}, + ruma::{ + api::{AuthScheme, IncomingRequest}, + signatures::CanonicalJsonValue, + ServerName, + }, + std::collections::BTreeMap, std::convert::TryFrom, std::io::Cursor, }; @@ -32,139 +34,261 @@ pub struct Ruma { pub body: T::Incoming, pub sender_user: Option, pub sender_device: Option>, - pub json_body: Option>, // This is None when body is not a valid string + // This is None when body is not a valid string + pub json_body: Option>, pub from_appservice: bool, } #[cfg(feature = "conduit_bin")] -impl<'a, T: Outgoing> FromTransformedData<'a> for Ruma +#[rocket::async_trait] +impl<'a, T: Outgoing> FromData<'a> for Ruma where T::Incoming: IncomingRequest, { type Error = (); - type Owned = Data; - type Borrowed = Self::Owned; - fn transform<'r>( - _req: &'r Request<'_>, - data: Data, - ) -> TransformFuture<'r, Self::Owned, Self::Error> { - Box::pin(async move { Transform::Owned(Success(data)) }) - } - - fn from_data( - request: &'a Request<'_>, - outcome: Transformed<'a, Self>, - ) -> FromDataFuture<'a, Self, Self::Error> { + async fn from_data(request: &'a Request<'_>, data: Data) -> data::Outcome { let metadata = T::Incoming::METADATA; + let db = request + .guard::>() + .await + .expect("database was loaded"); - Box::pin(async move { - let data = rocket::try_outcome!(outcome.owned()); - let db = request - .guard::>() - .await - .expect("database was loaded"); + // Get token from header or query value + let token = request + .headers() + .get_one("Authorization") + .map(|s| s[7..].to_owned()) // Split off "Bearer " + .or_else(|| request.query_value("access_token").and_then(|r| r.ok())); - // Get token from header or query value - let token = request - .headers() - .get_one("Authorization") - .map(|s| s[7..].to_owned()) // Split off "Bearer " - .or_else(|| request.get_query_value("access_token").and_then(|r| r.ok())); + let limit = db.globals.max_request_size(); + let mut handle = data.open(ByteUnit::Byte(limit.into())); + let mut body = Vec::new(); + handle.read_to_end(&mut body).await.unwrap(); - let (sender_user, sender_device, from_appservice) = if let Some((_id, registration)) = - db.appservice - .iter_all() - .filter_map(|r| r.ok()) - .find(|(_id, registration)| { - registration - .get("as_token") - .and_then(|as_token| as_token.as_str()) - .map_or(false, |as_token| token.as_deref() == Some(as_token)) - }) { - match metadata.authentication { - AuthScheme::AccessToken | AuthScheme::QueryOnlyAccessToken => { - let user_id = request.get_query_value::("user_id").map_or_else( - || { - UserId::parse_with_server_name( - registration - .get("sender_localpart") - .unwrap() - .as_str() - .unwrap(), - db.globals.server_name(), - ) - .unwrap() - }, - |string| { - UserId::try_from(string.expect("parsing to string always works")) + let (sender_user, sender_device, from_appservice) = if let Some((_id, registration)) = db + .appservice + .iter_all() + .filter_map(|r| r.ok()) + .find(|(_id, registration)| { + registration + .get("as_token") + .and_then(|as_token| as_token.as_str()) + .map_or(false, |as_token| token.as_deref() == Some(as_token)) + }) { + match metadata.authentication { + AuthScheme::AccessToken | AuthScheme::QueryOnlyAccessToken => { + let user_id = request.query_value::("user_id").map_or_else( + || { + UserId::parse_with_server_name( + registration + .get("sender_localpart") .unwrap() - }, - ); + .as_str() + .unwrap(), + db.globals.server_name(), + ) + .unwrap() + }, + |string| { + UserId::try_from(string.expect("parsing to string always works")) + .unwrap() + }, + ); + + if !db.users.exists(&user_id).unwrap() { + // Forbidden + return Failure((Status::raw(580), ())); + } + + // TODO: Check if appservice is allowed to be that user + (Some(user_id), None, true) + } + AuthScheme::ServerSignatures => (None, None, true), + AuthScheme::None => (None, None, true), + } + } else { + match metadata.authentication { + AuthScheme::AccessToken | AuthScheme::QueryOnlyAccessToken => { + if let Some(token) = token { + match db.users.find_from_token(&token).unwrap() { + // Unknown Token + None => return Failure((Status::raw(581), ())), + Some((user_id, device_id)) => { + (Some(user_id), Some(device_id.into()), false) + } + } + } else { + // Missing Token + return Failure((Status::raw(582), ())); + } + } + AuthScheme::ServerSignatures => { + // Get origin from header + let x_matrix = match request.headers().get_one("Authorization").map(|s| { + // Split off "X-Matrix " and parse the rest + s[9..] + .split_terminator(',') + .map(|field| { + let mut splits = field.splitn(2, '='); + (splits.next(), splits.next().map(|s| s.trim_matches('"'))) + }) + .collect::>() + }) { + Some(t) => t, + None => { + warn!("No Authorization header"); - if !db.users.exists(&user_id).unwrap() { // Forbidden return Failure((Status::raw(580), ())); } + }; - // TODO: Check if appservice is allowed to be that user - (Some(user_id), None, true) - } - AuthScheme::ServerSignatures => (None, None, true), - AuthScheme::None => (None, None, true), - } - } else { - match metadata.authentication { - AuthScheme::AccessToken | AuthScheme::QueryOnlyAccessToken => { - if let Some(token) = token { - match db.users.find_from_token(&token).unwrap() { - // Unknown Token - None => return Failure((Status::raw(581), ())), - Some((user_id, device_id)) => { - (Some(user_id), Some(device_id.into()), false) - } + let origin_str = match x_matrix.get(&Some("origin")) { + Some(Some(o)) => *o, + _ => { + warn!("Invalid X-Matrix header origin field: {:?}", x_matrix); + + // Forbidden + return Failure((Status::raw(580), ())); + } + }; + + let origin = match Box::::try_from(origin_str) { + Ok(s) => s, + _ => { + warn!( + "Invalid server name in X-Matrix header origin field: {:?}", + x_matrix + ); + + // Forbidden + return Failure((Status::raw(580), ())); + } + }; + + let key = match x_matrix.get(&Some("key")) { + Some(Some(k)) => *k, + _ => { + warn!("Invalid X-Matrix header key field: {:?}", x_matrix); + + // Forbidden + return Failure((Status::raw(580), ())); + } + }; + + let sig = match x_matrix.get(&Some("sig")) { + Some(Some(s)) => *s, + _ => { + warn!("Invalid X-Matrix header sig field: {:?}", x_matrix); + + // Forbidden + return Failure((Status::raw(580), ())); + } + }; + + let json_body = serde_json::from_slice::(&body); + + let mut request_map = BTreeMap::::new(); + + if let Ok(json_body) = json_body { + request_map.insert("content".to_owned(), json_body); + }; + + request_map.insert( + "method".to_owned(), + CanonicalJsonValue::String(request.method().to_string()), + ); + request_map.insert( + "uri".to_owned(), + CanonicalJsonValue::String(request.uri().to_string()), + ); + request_map.insert( + "origin".to_owned(), + CanonicalJsonValue::String(origin.as_str().to_owned()), + ); + request_map.insert( + "destination".to_owned(), + CanonicalJsonValue::String(db.globals.server_name().as_str().to_owned()), + ); + + let mut origin_signatures = BTreeMap::new(); + origin_signatures + .insert(key.to_owned(), CanonicalJsonValue::String(sig.to_owned())); + + let mut signatures = BTreeMap::new(); + signatures.insert( + origin.as_str().to_owned(), + CanonicalJsonValue::Object(origin_signatures), + ); + + request_map.insert( + "signatures".to_owned(), + CanonicalJsonValue::Object(signatures), + ); + + let keys = match server_server::fetch_signing_keys( + &db, + &origin, + vec![&key.to_owned()], + ) + .await + { + Ok(b) => b, + Err(e) => { + warn!("Failed to fetch signing keys: {}", e); + + // Forbidden + return Failure((Status::raw(580), ())); + } + }; + + let mut pub_key_map = BTreeMap::new(); + pub_key_map.insert(origin.as_str().to_owned(), keys); + + match ruma::signatures::verify_json(&pub_key_map, &request_map) { + Ok(()) => (None, None, false), + Err(e) => { + warn!("Failed to verify json request from {}: {}", origin, e); + + if request.uri().to_string().contains('@') { + warn!("Request uri contained '@' character. Make sure your reverse proxy gives Conduit the raw uri (apache: use nocanon)"); } - } else { - // Missing Token - return Failure((Status::raw(582), ())); + + // Forbidden + return Failure((Status::raw(580), ())); } } - AuthScheme::ServerSignatures => (None, None, false), - AuthScheme::None => (None, None, false), } - }; - - let mut http_request = http::Request::builder() - .uri(request.uri().to_string()) - .method(&*request.method().to_string()); - for header in request.headers().iter() { - http_request = http_request.header(header.name.as_str(), &*header.value); + AuthScheme::None => (None, None, false), } + }; - let limit = db.globals.max_request_size(); - let mut handle = data.open(ByteUnit::Byte(limit.into())); - let mut body = Vec::new(); - handle.read_to_end(&mut body).await.unwrap(); + let mut http_request = http::Request::builder() + .uri(request.uri().to_string()) + .method(&*request.method().to_string()); + for header in request.headers().iter() { + http_request = http_request.header(header.name.as_str(), &*header.value); + } - let http_request = http_request.body(&*body).unwrap(); - debug!("{:?}", http_request); - match ::try_from_http_request(http_request) { - Ok(t) => Success(Ruma { - body: t, - sender_user, - sender_device, - // TODO: Can we avoid parsing it again? (We only need this for append_pdu) - json_body: utils::string_from_bytes(&body) - .ok() - .and_then(|s| serde_json::value::RawValue::from_string(s).ok()), - from_appservice, - }), - Err(e) => { - warn!("{:?}", e); - Failure((Status::raw(583), ())) - } + let http_request = http_request.body(&*body).unwrap(); + debug!("{:?}", http_request); + match ::try_from_http_request(http_request) { + Ok(t) => Success(Ruma { + body: t, + sender_user, + sender_device, + // TODO: Can we avoid parsing it again? (We only need this for append_pdu) + json_body: utils::string_from_bytes(&body) + .ok() + .and_then(|s| serde_json::value::RawValue::from_string(s).ok()), + from_appservice, + }), + Err(e) => { + warn!("{:?}", e); + Failure((Status::raw(583), ())) } - }) + } } } @@ -194,36 +318,34 @@ where 'o: 'r, { fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> { - let http_response: Result, _> = self.0.try_into_http_response(); - match http_response { - Ok(http_response) => { - let mut response = rocket::response::Response::build(); + let http_response = self + .0 + .try_into_http_response::>() + .map_err(|_| Status::InternalServerError)?; - let status = http_response.status(); - response.raw_status(status.into(), ""); + let mut response = rocket::response::Response::build(); - for header in http_response.headers() { - response - .raw_header(header.0.to_string(), header.1.to_str().unwrap().to_owned()); - } + let status = http_response.status(); + response.raw_status(status.into(), ""); - let http_body = http_response.into_body(); - - response.sized_body(http_body.len(), Cursor::new(http_body)); - - response.raw_header("Access-Control-Allow-Origin", "*"); - response.raw_header( - "Access-Control-Allow-Methods", - "GET, POST, PUT, DELETE, OPTIONS", - ); - response.raw_header( - "Access-Control-Allow-Headers", - "Origin, X-Requested-With, Content-Type, Accept, Authorization", - ); - response.raw_header("Access-Control-Max-Age", "86400"); - response.ok() - } - Err(_) => Err(Status::InternalServerError), + for header in http_response.headers() { + response.raw_header(header.0.to_string(), header.1.to_str().unwrap().to_owned()); } + + let http_body = http_response.into_body(); + + response.sized_body(http_body.len(), Cursor::new(http_body)); + + response.raw_header("Access-Control-Allow-Origin", "*"); + response.raw_header( + "Access-Control-Allow-Methods", + "GET, POST, PUT, DELETE, OPTIONS", + ); + response.raw_header( + "Access-Control-Allow-Headers", + "Origin, X-Requested-With, Content-Type, Accept, Authorization", + ); + response.raw_header("Access-Control-Max-Age", "86400"); + response.ok() } } diff --git a/src/server_server.rs b/src/server_server.rs index ad198fc..187ec4f 100644 --- a/src/server_server.rs +++ b/src/server_server.rs @@ -21,9 +21,9 @@ use ruma::{ create_join_event_template, }, query::{get_profile_information, get_room_information}, - transactions::send_transaction_message, + transactions::{edu::Edu, send_transaction_message}, }, - IncomingResponse, OutgoingRequest, OutgoingResponse, + IncomingResponse, OutgoingRequest, OutgoingResponse, SendAccessToken, }, directory::{IncomingFilter, IncomingRoomNetwork}, events::{ @@ -141,7 +141,7 @@ where }; let mut http_request = request - .try_into_http_request(&actual_destination, Some("")) + .try_into_http_request::>(&actual_destination, SendAccessToken::IfRequired("")) .map_err(|e| { warn!("Failed to find destination {}: {}", actual_destination, e); Error::BadServerResponse("Invalid destination") @@ -454,7 +454,7 @@ pub fn get_server_keys_route(db: State<'_, Database>) -> Json { valid_until_ts: SystemTime::now() + Duration::from_secs(60 * 2), }, } - .try_into_http_response() + .try_into_http_response::>() .unwrap() .body(), ) @@ -585,39 +585,32 @@ pub async fn send_transaction_message_route<'a>( return Err(Error::bad_config("Federation is disabled.")); } - for edu in &body.edus { - match serde_json::from_str::(edu.json().get()) { - Ok(edu) => match edu.edu_type.as_str() { - "m.typing" => { - if let Some(typing) = edu.content.get("typing") { - if typing.as_bool().unwrap_or_default() { - db.rooms.edus.typing_add( - &UserId::try_from(edu.content["user_id"].as_str().unwrap()) - .unwrap(), - &RoomId::try_from(edu.content["room_id"].as_str().unwrap()) - .unwrap(), - 3000 + utils::millis_since_unix_epoch(), - &db.globals, - )?; - } else { - db.rooms.edus.typing_remove( - &UserId::try_from(edu.content["user_id"].as_str().unwrap()) - .unwrap(), - &RoomId::try_from(edu.content["room_id"].as_str().unwrap()) - .unwrap(), - &db.globals, - )?; - } - } + for edu in body + .edus + .iter() + .map(|edu| serde_json::from_str::(edu.json().get())) + .filter_map(|r| r.ok()) + { + match edu { + Edu::Presence(_) => {} + Edu::Receipt(_) => {} + Edu::Typing(typing) => { + if typing.typing { + db.rooms.edus.typing_add( + &typing.user_id, + &typing.room_id, + 3000 + utils::millis_since_unix_epoch(), + &db.globals, + )?; + } else { + db.rooms + .edus + .typing_remove(&typing.user_id, &typing.room_id, &db.globals)?; } - "m.presence" => {} - "m.receipt" => {} - "m.device_list_update" => {} - _ => {} - }, - Err(_err) => { - continue; } + Edu::DeviceListUpdate(_) => {} + Edu::DirectToDevice(_) => {} + Edu::_Custom(_) => {} } } @@ -2106,7 +2099,10 @@ pub fn get_room_information_route<'a>( let room_id = db .rooms .id_from_alias(&body.room_alias)? - .ok_or(Error::BadRequest(ErrorKind::NotFound, "Room alias not found."))?; + .ok_or(Error::BadRequest( + ErrorKind::NotFound, + "Room alias not found.", + ))?; Ok(get_room_information::v1::Response { room_id, @@ -2205,7 +2201,7 @@ pub async fn fetch_required_signing_keys( #[cfg(test)] mod tests { - use super::{FedDest, add_port_to_hostname, get_ip_with_port}; + use super::{add_port_to_hostname, get_ip_with_port, FedDest}; #[test] fn ips_get_default_ports() {