Keep track of State at event for state resolution
feat: first steps towards joining rooms over federation Add state-res as a dependency of conduit Add reverse_topological_power_sort before append_pdu Implement statehashstatid_pduid tree for keeping track of state Clean up implementation of state_hash as key for tracking state
This commit is contained in:
		
							parent
							
								
									8e55623bde
								
							
						
					
					
						commit
						c4f5a0a631
					
				
					 24 changed files with 818 additions and 356 deletions
				
			
		
							
								
								
									
										206
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										206
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							|  | @ -75,6 +75,15 @@ dependencies = [ | |||
|  "opaque-debug 0.2.3", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "ansi_term" | ||||
| version = "0.12.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" | ||||
| dependencies = [ | ||||
|  "winapi 0.3.9", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "arc-swap" | ||||
| version = "0.4.7" | ||||
|  | @ -248,6 +257,17 @@ version = "0.1.10" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "chrono" | ||||
| version = "0.4.15" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "942f72db697d8767c22d46a598e01f2d3b475501ea43d0db4f16d90259182d0b" | ||||
| dependencies = [ | ||||
|  "num-integer", | ||||
|  "num-traits", | ||||
|  "time 0.1.43", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "cloudabi" | ||||
| version = "0.1.0" | ||||
|  | @ -281,6 +301,7 @@ dependencies = [ | |||
|  "serde", | ||||
|  "serde_json", | ||||
|  "sled", | ||||
|  "state-res", | ||||
|  "thiserror", | ||||
|  "tokio", | ||||
| ] | ||||
|  | @ -456,6 +477,12 @@ version = "0.4.6" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "either" | ||||
| version = "1.6.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "cd56b59865bce947ac5958779cfa508f6c3b9497cc762b7e24a12d11ccde2c4f" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "encoding_rs" | ||||
| version = "0.8.23" | ||||
|  | @ -872,6 +899,15 @@ version = "2.3.0" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "itertools" | ||||
| version = "0.9.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" | ||||
| dependencies = [ | ||||
|  "either", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "itoa" | ||||
| version = "0.4.6" | ||||
|  | @ -951,6 +987,21 @@ version = "0.10.0" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "maplit" | ||||
| version = "1.0.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "matchers" | ||||
| version = "0.0.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" | ||||
| dependencies = [ | ||||
|  "regex-automata", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "matches" | ||||
| version = "0.1.8" | ||||
|  | @ -1439,6 +1490,31 @@ dependencies = [ | |||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "regex" | ||||
| version = "1.3.9" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" | ||||
| dependencies = [ | ||||
|  "regex-syntax", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "regex-automata" | ||||
| version = "0.1.9" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" | ||||
| dependencies = [ | ||||
|  "byteorder", | ||||
|  "regex-syntax", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "regex-syntax" | ||||
| version = "0.6.18" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "remove_dir_all" | ||||
| version = "0.5.3" | ||||
|  | @ -1560,21 +1636,23 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma" | ||||
| version = "0.0.1" | ||||
| source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#c2adc9ecb85538505ff351dbd883c9106f651744" | ||||
| source = "git+https://github.com/ruma/ruma?rev=aff914050eb297bd82b8aafb12158c88a9e480e1#aff914050eb297bd82b8aafb12158c88a9e480e1" | ||||
| dependencies = [ | ||||
|  "ruma-api", | ||||
|  "ruma-appservice-api", | ||||
|  "ruma-client-api", | ||||
|  "ruma-common", | ||||
|  "ruma-events", | ||||
|  "ruma-federation-api", | ||||
|  "ruma-identifiers", | ||||
|  "ruma-serde", | ||||
|  "ruma-signatures", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "ruma-api" | ||||
| version = "0.17.0-alpha.1" | ||||
| source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#c2adc9ecb85538505ff351dbd883c9106f651744" | ||||
| source = "git+https://github.com/ruma/ruma?rev=aff914050eb297bd82b8aafb12158c88a9e480e1#aff914050eb297bd82b8aafb12158c88a9e480e1" | ||||
| dependencies = [ | ||||
|  "http", | ||||
|  "percent-encoding", | ||||
|  | @ -1589,7 +1667,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-api-macros" | ||||
| version = "0.17.0-alpha.1" | ||||
| source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#c2adc9ecb85538505ff351dbd883c9106f651744" | ||||
| source = "git+https://github.com/ruma/ruma?rev=aff914050eb297bd82b8aafb12158c88a9e480e1#aff914050eb297bd82b8aafb12158c88a9e480e1" | ||||
| dependencies = [ | ||||
|  "proc-macro-crate", | ||||
|  "proc-macro2", | ||||
|  | @ -1597,14 +1675,28 @@ dependencies = [ | |||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "ruma-appservice-api" | ||||
| version = "0.2.0-alpha.1" | ||||
| source = "git+https://github.com/ruma/ruma?rev=aff914050eb297bd82b8aafb12158c88a9e480e1#aff914050eb297bd82b8aafb12158c88a9e480e1" | ||||
| dependencies = [ | ||||
|  "ruma-api", | ||||
|  "ruma-common", | ||||
|  "ruma-events", | ||||
|  "ruma-identifiers", | ||||
|  "serde", | ||||
|  "serde_json", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "ruma-client-api" | ||||
| version = "0.10.0-alpha.1" | ||||
| source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#c2adc9ecb85538505ff351dbd883c9106f651744" | ||||
| source = "git+https://github.com/ruma/ruma?rev=aff914050eb297bd82b8aafb12158c88a9e480e1#aff914050eb297bd82b8aafb12158c88a9e480e1" | ||||
| dependencies = [ | ||||
|  "assign", | ||||
|  "http", | ||||
|  "js_int", | ||||
|  "percent-encoding", | ||||
|  "ruma-api", | ||||
|  "ruma-common", | ||||
|  "ruma-events", | ||||
|  | @ -1618,7 +1710,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-common" | ||||
| version = "0.2.0" | ||||
| source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#c2adc9ecb85538505ff351dbd883c9106f651744" | ||||
| source = "git+https://github.com/ruma/ruma?rev=aff914050eb297bd82b8aafb12158c88a9e480e1#aff914050eb297bd82b8aafb12158c88a9e480e1" | ||||
| dependencies = [ | ||||
|  "js_int", | ||||
|  "ruma-identifiers", | ||||
|  | @ -1631,7 +1723,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-events" | ||||
| version = "0.22.0-alpha.1" | ||||
| source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#c2adc9ecb85538505ff351dbd883c9106f651744" | ||||
| source = "git+https://github.com/ruma/ruma?rev=aff914050eb297bd82b8aafb12158c88a9e480e1#aff914050eb297bd82b8aafb12158c88a9e480e1" | ||||
| dependencies = [ | ||||
|  "js_int", | ||||
|  "ruma-common", | ||||
|  | @ -1646,7 +1738,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-events-macros" | ||||
| version = "0.22.0-alpha.1" | ||||
| source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#c2adc9ecb85538505ff351dbd883c9106f651744" | ||||
| source = "git+https://github.com/ruma/ruma?rev=aff914050eb297bd82b8aafb12158c88a9e480e1#aff914050eb297bd82b8aafb12158c88a9e480e1" | ||||
| dependencies = [ | ||||
|  "proc-macro-crate", | ||||
|  "proc-macro2", | ||||
|  | @ -1657,7 +1749,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-federation-api" | ||||
| version = "0.0.3" | ||||
| source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#c2adc9ecb85538505ff351dbd883c9106f651744" | ||||
| source = "git+https://github.com/ruma/ruma?rev=aff914050eb297bd82b8aafb12158c88a9e480e1#aff914050eb297bd82b8aafb12158c88a9e480e1" | ||||
| dependencies = [ | ||||
|  "js_int", | ||||
|  "ruma-api", | ||||
|  | @ -1672,7 +1764,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-identifiers" | ||||
| version = "0.17.4" | ||||
| source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#c2adc9ecb85538505ff351dbd883c9106f651744" | ||||
| source = "git+https://github.com/ruma/ruma?rev=aff914050eb297bd82b8aafb12158c88a9e480e1#aff914050eb297bd82b8aafb12158c88a9e480e1" | ||||
| dependencies = [ | ||||
|  "rand", | ||||
|  "ruma-identifiers-macros", | ||||
|  | @ -1684,7 +1776,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-identifiers-macros" | ||||
| version = "0.17.4" | ||||
| source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#c2adc9ecb85538505ff351dbd883c9106f651744" | ||||
| source = "git+https://github.com/ruma/ruma?rev=aff914050eb297bd82b8aafb12158c88a9e480e1#aff914050eb297bd82b8aafb12158c88a9e480e1" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  | @ -1695,7 +1787,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-identifiers-validation" | ||||
| version = "0.1.1" | ||||
| source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#c2adc9ecb85538505ff351dbd883c9106f651744" | ||||
| source = "git+https://github.com/ruma/ruma?rev=aff914050eb297bd82b8aafb12158c88a9e480e1#aff914050eb297bd82b8aafb12158c88a9e480e1" | ||||
| dependencies = [ | ||||
|  "ruma-serde", | ||||
|  "serde", | ||||
|  | @ -1706,7 +1798,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-serde" | ||||
| version = "0.2.3" | ||||
| source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#c2adc9ecb85538505ff351dbd883c9106f651744" | ||||
| source = "git+https://github.com/ruma/ruma?rev=aff914050eb297bd82b8aafb12158c88a9e480e1#aff914050eb297bd82b8aafb12158c88a9e480e1" | ||||
| dependencies = [ | ||||
|  "form_urlencoded", | ||||
|  "itoa", | ||||
|  | @ -1718,7 +1810,7 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "ruma-signatures" | ||||
| version = "0.6.0-dev.1" | ||||
| source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#c2adc9ecb85538505ff351dbd883c9106f651744" | ||||
| source = "git+https://github.com/ruma/ruma?rev=aff914050eb297bd82b8aafb12158c88a9e480e1#aff914050eb297bd82b8aafb12158c88a9e480e1" | ||||
| dependencies = [ | ||||
|  "base64 0.12.3", | ||||
|  "ring", | ||||
|  | @ -1910,6 +2002,15 @@ dependencies = [ | |||
|  "opaque-debug 0.3.0", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "sharded-slab" | ||||
| version = "0.0.9" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "06d5a3f5166fb5b42a5439f2eee8b9de149e235961e3eb21c5808fc3ea17ff3e" | ||||
| dependencies = [ | ||||
|  "lazy_static", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "signal-hook-registry" | ||||
| version = "1.2.1" | ||||
|  | @ -1983,6 +2084,22 @@ version = "0.4.1" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7345c971d1ef21ffdbd103a75990a15eb03604fc8b8852ca8cb418ee1a099028" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "state-res" | ||||
| version = "0.1.0" | ||||
| source = "git+https://github.com/ruma/state-res#789c8140890e076d38b23fa1147c4ff0500c0d38" | ||||
| dependencies = [ | ||||
|  "itertools", | ||||
|  "js_int", | ||||
|  "maplit", | ||||
|  "ruma", | ||||
|  "serde", | ||||
|  "serde_json", | ||||
|  "thiserror", | ||||
|  "tracing", | ||||
|  "tracing-subscriber", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "stdweb" | ||||
| version = "0.4.20" | ||||
|  | @ -2104,6 +2221,15 @@ dependencies = [ | |||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "thread_local" | ||||
| version = "1.0.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" | ||||
| dependencies = [ | ||||
|  "lazy_static", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "time" | ||||
| version = "0.1.43" | ||||
|  | @ -2251,9 +2377,21 @@ checksum = "6d79ca061b032d6ce30c660fded31189ca0b9922bf483cd70759f13a2d86786c" | |||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "log", | ||||
|  "tracing-attributes", | ||||
|  "tracing-core", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tracing-attributes" | ||||
| version = "0.1.10" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "1fe233f4227389ab7df5b32649239da7ebe0b281824b4e84b342d04d3fd8c25e" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tracing-core" | ||||
| version = "0.1.14" | ||||
|  | @ -2263,6 +2401,48 @@ dependencies = [ | |||
|  "lazy_static", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tracing-log" | ||||
| version = "0.1.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "5e0f8c7178e13481ff6765bd169b33e8d554c5d2bbede5e32c356194be02b9b9" | ||||
| dependencies = [ | ||||
|  "lazy_static", | ||||
|  "log", | ||||
|  "tracing-core", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tracing-serde" | ||||
| version = "0.1.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b6ccba2f8f16e0ed268fc765d9b7ff22e965e7185d32f8f1ec8294fe17d86e79" | ||||
| dependencies = [ | ||||
|  "serde", | ||||
|  "tracing-core", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tracing-subscriber" | ||||
| version = "0.2.11" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "abd165311cc4d7a555ad11cc77a37756df836182db0d81aac908c8184c584f40" | ||||
| dependencies = [ | ||||
|  "ansi_term", | ||||
|  "chrono", | ||||
|  "lazy_static", | ||||
|  "matchers", | ||||
|  "regex", | ||||
|  "serde", | ||||
|  "serde_json", | ||||
|  "sharded-slab", | ||||
|  "smallvec", | ||||
|  "thread_local", | ||||
|  "tracing-core", | ||||
|  "tracing-log", | ||||
|  "tracing-serde", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "try-lock" | ||||
| version = "0.2.3" | ||||
|  |  | |||
|  | @ -16,9 +16,7 @@ edition = "2018" | |||
| #rocket = { git = "https://github.com/SergioBenitez/Rocket.git", rev = "8d779caa22c63b15a6c3ceb75d8f6d4971b2eb67", features = ["tls"] } # Used to handle requests | ||||
| rocket = { git = "https://github.com/timokoesters/Rocket.git", branch = "empty_parameters", features = ["tls"] } | ||||
| 
 | ||||
| #ruma = { git = "https://github.com/ruma/ruma", features = ["rand", "client-api", "federation-api", "unstable-pre-spec", "unstable-synapse-quirks"], rev = "987d48666cf166cf12100b5dbc61b5e3385c4014" } # Used for matrix spec type definitions and helpers | ||||
| ruma = { git = "https://github.com/timokoesters/ruma", features = ["rand", "client-api", "federation-api", "unstable-pre-spec", "unstable-synapse-quirks"], branch = "timo-fixes" } # Used for matrix spec type definitions and helpers | ||||
| #ruma = { path = "../ruma/ruma", features = ["rand", "client-api", "federation-api", "unstable-pre-spec", "unstable-synapse-quirks"] } | ||||
| ruma = { git = "https://github.com/ruma/ruma", features = ["rand", "client-api", "federation-api", "unstable-pre-spec", "unstable-synapse-quirks"], rev = "aff914050eb297bd82b8aafb12158c88a9e480e1" } # Used for matrix spec type definitions and helpers | ||||
| tokio = "0.2.22" # Used for long polling | ||||
| sled = "0.32.0" # Used for storing data permanently | ||||
| log = "0.4.8" # Used for emitting log entries | ||||
|  | @ -33,6 +31,9 @@ reqwest = "0.10.6" # Used to send requests | |||
| thiserror = "1.0.19" # Used for conduit::Error type | ||||
| image = { version = "0.23.4", default-features = false, features = ["jpeg", "png", "gif"] } # Used to generate thumbnails for images | ||||
| base64 = "0.12.3" # Used to encode server public key | ||||
| # state-res = { path = "../../state-res" } | ||||
| state-res = { git = "https://github.com/ruma/state-res", version = "0.1.0" } | ||||
| 
 | ||||
| 
 | ||||
| [features] | ||||
| default = ["conduit_bin"] | ||||
|  |  | |||
|  | @ -75,7 +75,7 @@ pub fn get_register_available_route( | |||
| )] | ||||
| pub fn register_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<register::Request>, | ||||
|     body: Ruma<register::IncomingRequest>, | ||||
| ) -> ConduitResult<register::Response> { | ||||
|     if db.globals.registration_disabled() { | ||||
|         return Err(Error::BadRequest( | ||||
|  | @ -223,7 +223,7 @@ pub fn register_route( | |||
| )] | ||||
| pub fn change_password_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<change_password::Request>, | ||||
|     body: Ruma<change_password::IncomingRequest>, | ||||
| ) -> ConduitResult<change_password::Response> { | ||||
|     let sender_id = body.sender_id.as_ref().expect("user is authenticated"); | ||||
|     let device_id = body.device_id.as_ref().expect("user is authenticated"); | ||||
|  | @ -305,7 +305,7 @@ pub fn whoami_route(body: Ruma<whoami::Request>) -> ConduitResult<whoami::Respon | |||
| )] | ||||
| pub fn deactivate_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<deactivate::Request>, | ||||
|     body: Ruma<deactivate::IncomingRequest>, | ||||
| ) -> ConduitResult<deactivate::Response> { | ||||
|     let sender_id = body.sender_id.as_ref().expect("user is authenticated"); | ||||
|     let device_id = body.device_id.as_ref().expect("user is authenticated"); | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ pub fn create_alias_route( | |||
|     db.rooms | ||||
|         .set_alias(&body.room_alias, Some(&body.room_id), &db.globals)?; | ||||
| 
 | ||||
|     Ok(create_alias::Response.into()) | ||||
|     Ok(create_alias::Response::new().into()) | ||||
| } | ||||
| 
 | ||||
| #[cfg_attr(
 | ||||
|  | @ -39,7 +39,7 @@ pub fn delete_alias_route( | |||
| ) -> ConduitResult<delete_alias::Response> { | ||||
|     db.rooms.set_alias(&body.room_alias, None, &db.globals)?; | ||||
| 
 | ||||
|     Ok(delete_alias::Response.into()) | ||||
|     Ok(delete_alias::Response::new().into()) | ||||
| } | ||||
| 
 | ||||
| #[cfg_attr(
 | ||||
|  | @ -60,11 +60,7 @@ pub async fn get_alias_route( | |||
|         ) | ||||
|         .await?; | ||||
| 
 | ||||
|         return Ok(get_alias::Response { | ||||
|             room_id: response.room_id, | ||||
|             servers: response.servers, | ||||
|         } | ||||
|         .into()); | ||||
|         return Ok(get_alias::Response::new(response.room_id, response.servers).into()); | ||||
|     } | ||||
| 
 | ||||
|     let room_id = db | ||||
|  | @ -75,9 +71,5 @@ pub async fn get_alias_route( | |||
|             "Room with alias not found.", | ||||
|         ))?; | ||||
| 
 | ||||
|     Ok(get_alias::Response { | ||||
|         room_id, | ||||
|         servers: vec![db.globals.server_name().to_string()], | ||||
|     } | ||||
|     .into()) | ||||
|     Ok(get_alias::Response::new(room_id, vec![db.globals.server_name().to_string()]).into()) | ||||
| } | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ use rocket::get; | |||
| )] | ||||
| pub fn get_context_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<get_context::Request>, | ||||
|     body: Ruma<get_context::IncomingRequest>, | ||||
| ) -> ConduitResult<get_context::Response> { | ||||
|     let sender_id = body.sender_id.as_ref().expect("user is authenticated"); | ||||
| 
 | ||||
|  | @ -75,18 +75,18 @@ pub fn get_context_route( | |||
|         .map(|(_, pdu)| pdu.to_room_event()) | ||||
|         .collect::<Vec<_>>(); | ||||
| 
 | ||||
|     Ok(get_context::Response { | ||||
|         start: start_token, | ||||
|         end: end_token, | ||||
|         events_before, | ||||
|         event: Some(base_event), | ||||
|         events_after, | ||||
|         state: db // TODO: State at event
 | ||||
|             .rooms | ||||
|             .room_state_full(&body.room_id)? | ||||
|             .values() | ||||
|             .map(|pdu| pdu.to_state_event()) | ||||
|             .collect(), | ||||
|     } | ||||
|     .into()) | ||||
|     let mut resp = get_context::Response::new(); | ||||
|     resp.start = start_token; | ||||
|     resp.end = end_token; | ||||
|     resp.events_before = events_before; | ||||
|     resp.event = Some(base_event); | ||||
|     resp.events_after = events_after; | ||||
|     resp.state = db // TODO: State at event
 | ||||
|         .rooms | ||||
|         .room_state_full(&body.room_id)? | ||||
|         .values() | ||||
|         .map(|pdu| pdu.to_state_event()) | ||||
|         .collect(); | ||||
| 
 | ||||
|     Ok(resp.into()) | ||||
| } | ||||
|  |  | |||
|  | @ -37,7 +37,7 @@ pub fn get_devices_route( | |||
| )] | ||||
| pub fn get_device_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<get_device::Request>, | ||||
|     body: Ruma<get_device::IncomingRequest>, | ||||
|     _device_id: String, | ||||
| ) -> ConduitResult<get_device::Response> { | ||||
|     let sender_id = body.sender_id.as_ref().expect("user is authenticated"); | ||||
|  | @ -56,7 +56,7 @@ pub fn get_device_route( | |||
| )] | ||||
| pub fn update_device_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<update_device::Request>, | ||||
|     body: Ruma<update_device::IncomingRequest>, | ||||
|     _device_id: String, | ||||
| ) -> ConduitResult<update_device::Response> { | ||||
|     let sender_id = body.sender_id.as_ref().expect("user is authenticated"); | ||||
|  | @ -80,7 +80,7 @@ pub fn update_device_route( | |||
| )] | ||||
| pub fn delete_device_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<delete_device::Request>, | ||||
|     body: Ruma<delete_device::IncomingRequest>, | ||||
|     _device_id: String, | ||||
| ) -> ConduitResult<delete_device::Response> { | ||||
|     let sender_id = body.sender_id.as_ref().expect("user is authenticated"); | ||||
|  | @ -127,7 +127,7 @@ pub fn delete_device_route( | |||
| )] | ||||
| pub fn delete_devices_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<delete_devices::Request>, | ||||
|     body: Ruma<delete_devices::IncomingRequest>, | ||||
| ) -> ConduitResult<delete_devices::Response> { | ||||
|     let sender_id = body.sender_id.as_ref().expect("user is authenticated"); | ||||
|     let device_id = body.device_id.as_ref().expect("user is authenticated"); | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ use ruma::{ | |||
|             error::ErrorKind, | ||||
|             r0::{ | ||||
|                 directory::{ | ||||
|                     self, get_public_rooms, get_public_rooms_filtered, get_room_visibility, | ||||
|                     get_public_rooms, get_public_rooms_filtered, get_room_visibility, | ||||
|                     set_room_visibility, | ||||
|                 }, | ||||
|                 room, | ||||
|  | @ -14,6 +14,7 @@ use ruma::{ | |||
|         }, | ||||
|         federation, | ||||
|     }, | ||||
|     directory::PublicRoomsChunk, | ||||
|     events::{ | ||||
|         room::{avatar, canonical_alias, guest_access, history_visibility, name, topic}, | ||||
|         EventType, | ||||
|  | @ -35,15 +36,15 @@ pub async fn get_public_rooms_filtered_route( | |||
|     if let Some(other_server) = body | ||||
|         .server | ||||
|         .clone() | ||||
|         .filter(|server| server != &db.globals.server_name().as_str()) | ||||
|         .filter(|server| server != db.globals.server_name().as_str()) | ||||
|     { | ||||
|         let response = server_server::send_request( | ||||
|             &db, | ||||
|             other_server, | ||||
|             federation::directory::get_public_rooms::v1::Request { | ||||
|                 limit: body.limit, | ||||
|                 since: body.since.clone(), | ||||
|                 room_network: federation::directory::get_public_rooms::v1::RoomNetwork::Matrix, | ||||
|                 since: body.since.as_deref(), | ||||
|                 room_network: ruma::directory::RoomNetwork::Matrix, | ||||
|             }, | ||||
|         ) | ||||
|         .await?; | ||||
|  | @ -107,7 +108,7 @@ pub async fn get_public_rooms_filtered_route( | |||
|                 // TODO: Do not load full state?
 | ||||
|                 let state = db.rooms.room_state_full(&room_id)?; | ||||
| 
 | ||||
|                 let chunk = directory::PublicRoomsChunk { | ||||
|                 let chunk = PublicRoomsChunk { | ||||
|                     aliases: Vec::new(), | ||||
|                     canonical_alias: state | ||||
|                         .get(&(EventType::RoomCanonicalAlias, "".to_owned())) | ||||
|  | @ -272,7 +273,7 @@ pub async fn get_public_rooms_route( | |||
|             body: get_public_rooms_filtered::IncomingRequest { | ||||
|                 filter: None, | ||||
|                 limit, | ||||
|                 room_network: get_public_rooms_filtered::RoomNetwork::Matrix, | ||||
|                 room_network: ruma::directory::RoomNetwork::Matrix, | ||||
|                 server, | ||||
|                 since, | ||||
|             }, | ||||
|  |  | |||
|  | @ -7,23 +7,18 @@ use rocket::{get, post}; | |||
| #[cfg_attr(feature = "conduit_bin", get("/_matrix/client/r0/user/<_>/filter/<_>"))] | ||||
| pub fn get_filter_route() -> ConduitResult<get_filter::Response> { | ||||
|     // TODO
 | ||||
|     Ok(get_filter::Response { | ||||
|         filter: filter::FilterDefinition { | ||||
|             event_fields: None, | ||||
|             event_format: None, | ||||
|             account_data: None, | ||||
|             room: None, | ||||
|             presence: None, | ||||
|         }, | ||||
|     } | ||||
|     Ok(get_filter::Response::new(filter::FilterDefinition { | ||||
|         event_fields: None, | ||||
|         event_format: None, | ||||
|         account_data: None, | ||||
|         room: None, | ||||
|         presence: None, | ||||
|     }) | ||||
|     .into()) | ||||
| } | ||||
| 
 | ||||
| #[cfg_attr(feature = "conduit_bin", post("/_matrix/client/r0/user/<_>/filter"))] | ||||
| pub fn create_filter_route() -> ConduitResult<create_filter::Response> { | ||||
|     // TODO
 | ||||
|     Ok(create_filter::Response { | ||||
|         filter_id: utils::random_string(10), | ||||
|     } | ||||
|     .into()) | ||||
|     Ok(create_filter::Response::new(utils::random_string(10)).into()) | ||||
| } | ||||
|  |  | |||
|  | @ -167,7 +167,7 @@ pub fn claim_keys_route( | |||
| )] | ||||
| pub fn upload_signing_keys_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<upload_signing_keys::Request>, | ||||
|     body: Ruma<upload_signing_keys::IncomingRequest>, | ||||
| ) -> ConduitResult<upload_signing_keys::Response> { | ||||
|     let sender_id = body.sender_id.as_ref().expect("user is authenticated"); | ||||
|     let device_id = body.device_id.as_ref().expect("user is authenticated"); | ||||
|  |  | |||
|  | @ -53,7 +53,7 @@ pub fn create_content_route( | |||
| )] | ||||
| pub fn get_content_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<get_content::Request>, | ||||
|     body: Ruma<get_content::IncomingRequest>, | ||||
|     _server_name: String, | ||||
|     _media_id: String, | ||||
| ) -> ConduitResult<get_content::Response> { | ||||
|  | @ -85,7 +85,7 @@ pub fn get_content_route( | |||
| )] | ||||
| pub fn get_content_thumbnail_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<get_content_thumbnail::Request>, | ||||
|     body: Ruma<get_content_thumbnail::IncomingRequest>, | ||||
|     _server_name: String, | ||||
|     _media_id: String, | ||||
| ) -> ConduitResult<get_content_thumbnail::Response> { | ||||
|  |  | |||
|  | @ -20,6 +20,8 @@ use ruma::{ | |||
|     events::{room::member, EventType}, | ||||
|     EventId, Raw, RoomId, RoomVersionId, | ||||
| }; | ||||
| use state_res::StateEvent; | ||||
| 
 | ||||
| use std::{collections::BTreeMap, convert::TryFrom}; | ||||
| 
 | ||||
| #[cfg(feature = "conduit_bin")] | ||||
|  | @ -92,17 +94,73 @@ pub async fn join_room_by_id_route( | |||
|         let send_join_response = server_server::send_request( | ||||
|             &db, | ||||
|             body.room_id.server_name().to_string(), | ||||
|             federation::membership::create_join_event::v2::Request { | ||||
|             federation::membership::create_join_event::v1::Request { | ||||
|                 room_id: body.room_id.clone(), | ||||
|                 event_id, | ||||
|                 pdu_stub: serde_json::from_value::<Raw<_>>(join_event_stub_value) | ||||
|                 pdu_stub: serde_json::from_value(join_event_stub_value) | ||||
|                     .expect("Raw::from_value always works"), | ||||
|             }, | ||||
|         ) | ||||
|         .await?; | ||||
| 
 | ||||
|         dbg!(send_join_response); | ||||
|         todo!("Take send_join_response and 'create' the room using that data"); | ||||
|         dbg!(&send_join_response); | ||||
|         // todo!("Take send_join_response and 'create' the room using that data");
 | ||||
| 
 | ||||
|         let mut event_map = send_join_response | ||||
|             .room_state | ||||
|             .state | ||||
|             .iter() | ||||
|             .map(|pdu| pdu.deserialize().map(StateEvent::Full)) | ||||
|             .map(|ev| { | ||||
|                 let ev = ev?; | ||||
|                 Ok::<_, serde_json::Error>((ev.event_id(), ev)) | ||||
|             }) | ||||
|             .collect::<Result<BTreeMap<EventId, StateEvent>, _>>() | ||||
|             .map_err(|_| Error::bad_database("Invalid PDU found in db."))?; | ||||
| 
 | ||||
|         let _auth_chain = send_join_response | ||||
|             .room_state | ||||
|             .auth_chain | ||||
|             .iter() | ||||
|             .flat_map(|pdu| pdu.deserialize().ok()) | ||||
|             .map(StateEvent::Full) | ||||
|             .collect::<Vec<_>>(); | ||||
| 
 | ||||
|         // TODO make StateResolution's methods free functions ? or no self param ?
 | ||||
|         let sorted_events_ids = state_res::StateResolution::default() | ||||
|             .reverse_topological_power_sort( | ||||
|                 &body.room_id, | ||||
|                 &event_map.keys().cloned().collect::<Vec<_>>(), | ||||
|                 &mut event_map, | ||||
|                 &db.rooms, | ||||
|                 &[], // TODO auth_diff: is this none since we have a set of resolved events we only want to sort
 | ||||
|             ); | ||||
| 
 | ||||
|         for ev_id in &sorted_events_ids { | ||||
|             // this is a `state_res::StateEvent` that holds a `ruma::Pdu`
 | ||||
|             let pdu = event_map.get(ev_id).ok_or_else(|| { | ||||
|                 Error::Conflict("Found event_id in sorted events that is not in resolved state") | ||||
|             })?; | ||||
| 
 | ||||
|             db.rooms.append_pdu( | ||||
|                 PduBuilder { | ||||
|                     room_id: pdu.room_id().unwrap_or(&body.room_id).clone(), | ||||
|                     sender: pdu.sender().clone(), | ||||
|                     event_type: pdu.kind(), | ||||
|                     content: pdu.content().clone(), | ||||
|                     unsigned: Some( | ||||
|                         pdu.unsigned() | ||||
|                             .iter() | ||||
|                             .map(|(k, v)| (k.clone(), v.clone())) | ||||
|                             .collect(), | ||||
|                     ), | ||||
|                     state_key: pdu.state_key(), | ||||
|                     redacts: pdu.redacts().cloned(), | ||||
|                 }, | ||||
|                 &db.globals, | ||||
|                 &db.account_data, | ||||
|             )?; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     let event = member::MemberEventContent { | ||||
|  | @ -127,10 +185,7 @@ pub async fn join_room_by_id_route( | |||
|         &db.account_data, | ||||
|     )?; | ||||
| 
 | ||||
|     Ok(join_room_by_id::Response { | ||||
|         room_id: body.room_id.clone(), | ||||
|     } | ||||
|     .into()) | ||||
|     Ok(join_room_by_id::Response::new(body.room_id.clone()).into()) | ||||
| } | ||||
| 
 | ||||
| #[cfg_attr(
 | ||||
|  | @ -140,7 +195,7 @@ pub async fn join_room_by_id_route( | |||
| pub async fn join_room_by_id_or_alias_route( | ||||
|     db: State<'_, Database>, | ||||
|     db2: State<'_, Database>, | ||||
|     body: Ruma<join_room_by_id_or_alias::Request>, | ||||
|     body: Ruma<join_room_by_id_or_alias::IncomingRequest>, | ||||
| ) -> ConduitResult<join_room_by_id_or_alias::Response> { | ||||
|     let room_id = match RoomId::try_from(body.room_id_or_alias.clone()) { | ||||
|         Ok(room_id) => room_id, | ||||
|  | @ -148,7 +203,13 @@ pub async fn join_room_by_id_or_alias_route( | |||
|             client_server::get_alias_route( | ||||
|                 db, | ||||
|                 Ruma { | ||||
|                     body: alias::get_alias::IncomingRequest { room_alias }, | ||||
|                     body: alias::get_alias::IncomingRequest::try_from(http::Request::new( | ||||
|                         serde_json::json!({ "room_alias": room_alias }) | ||||
|                             .to_string() | ||||
|                             .as_bytes() | ||||
|                             .to_vec(), | ||||
|                     )) | ||||
|                     .unwrap(), | ||||
|                     sender_id: body.sender_id.clone(), | ||||
|                     device_id: body.device_id.clone(), | ||||
|                     json_body: None, | ||||
|  | @ -160,14 +221,32 @@ pub async fn join_room_by_id_or_alias_route( | |||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     // TODO ruma needs to implement the same constructors for the Incoming variants
 | ||||
|     let tps = if let Some(in_tps) = &body.third_party_signed { | ||||
|         Some(ruma::api::client::r0::membership::ThirdPartySigned { | ||||
|             token: &in_tps.token, | ||||
|             sender: &in_tps.sender, | ||||
|             signatures: in_tps.signatures.clone(), | ||||
|             mxid: &in_tps.mxid, | ||||
|         }) | ||||
|     } else { | ||||
|         None | ||||
|     }; | ||||
| 
 | ||||
|     let body = Ruma { | ||||
|         sender_id: body.sender_id.clone(), | ||||
|         device_id: body.device_id.clone(), | ||||
|         json_body: None, | ||||
|         body: join_room_by_id::IncomingRequest { | ||||
|             room_id, | ||||
|             third_party_signed: body.third_party_signed.clone(), | ||||
|         }, | ||||
|         body: join_room_by_id::IncomingRequest::try_from(http::Request::new( | ||||
|             serde_json::json!({ | ||||
|                 "room_id": room_id, | ||||
|                 "third_party_signed": tps, | ||||
|             }) | ||||
|             .to_string() | ||||
|             .as_bytes() | ||||
|             .to_vec(), | ||||
|         )) | ||||
|         .unwrap(), | ||||
|     }; | ||||
| 
 | ||||
|     Ok(join_room_by_id_or_alias::Response { | ||||
|  | @ -219,7 +298,7 @@ pub fn leave_room_route( | |||
|         &db.account_data, | ||||
|     )?; | ||||
| 
 | ||||
|     Ok(leave_room::Response.into()) | ||||
|     Ok(leave_room::Response::new().into()) | ||||
| } | ||||
| 
 | ||||
| #[cfg_attr(
 | ||||
|  | @ -266,7 +345,7 @@ pub fn invite_user_route( | |||
| )] | ||||
| pub fn kick_user_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<kick_user::Request>, | ||||
|     body: Ruma<kick_user::IncomingRequest>, | ||||
| ) -> ConduitResult<kick_user::Response> { | ||||
|     let sender_id = body.sender_id.as_ref().expect("user is authenticated"); | ||||
| 
 | ||||
|  | @ -304,7 +383,7 @@ pub fn kick_user_route( | |||
|         &db.account_data, | ||||
|     )?; | ||||
| 
 | ||||
|     Ok(kick_user::Response.into()) | ||||
|     Ok(kick_user::Response::new().into()) | ||||
| } | ||||
| 
 | ||||
| #[cfg_attr(
 | ||||
|  | @ -313,7 +392,7 @@ pub fn kick_user_route( | |||
| )] | ||||
| pub fn ban_user_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<ban_user::Request>, | ||||
|     body: Ruma<ban_user::IncomingRequest>, | ||||
| ) -> ConduitResult<ban_user::Response> { | ||||
|     let sender_id = body.sender_id.as_ref().expect("user is authenticated"); | ||||
| 
 | ||||
|  | @ -359,7 +438,7 @@ pub fn ban_user_route( | |||
|         &db.account_data, | ||||
|     )?; | ||||
| 
 | ||||
|     Ok(ban_user::Response.into()) | ||||
|     Ok(ban_user::Response::new().into()) | ||||
| } | ||||
| 
 | ||||
| #[cfg_attr(
 | ||||
|  | @ -368,7 +447,7 @@ pub fn ban_user_route( | |||
| )] | ||||
| pub fn unban_user_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<unban_user::Request>, | ||||
|     body: Ruma<unban_user::IncomingRequest>, | ||||
| ) -> ConduitResult<unban_user::Response> { | ||||
|     let sender_id = body.sender_id.as_ref().expect("user is authenticated"); | ||||
| 
 | ||||
|  | @ -405,7 +484,7 @@ pub fn unban_user_route( | |||
|         &db.account_data, | ||||
|     )?; | ||||
| 
 | ||||
|     Ok(unban_user::Response.into()) | ||||
|     Ok(unban_user::Response::new().into()) | ||||
| } | ||||
| 
 | ||||
| #[cfg_attr(
 | ||||
|  | @ -414,13 +493,13 @@ pub fn unban_user_route( | |||
| )] | ||||
| pub fn forget_room_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<forget_room::Request>, | ||||
|     body: Ruma<forget_room::IncomingRequest>, | ||||
| ) -> ConduitResult<forget_room::Response> { | ||||
|     let sender_id = body.sender_id.as_ref().expect("user is authenticated"); | ||||
| 
 | ||||
|     db.rooms.forget(&body.room_id, &sender_id)?; | ||||
| 
 | ||||
|     Ok(forget_room::Response.into()) | ||||
|     Ok(forget_room::Response::new().into()) | ||||
| } | ||||
| 
 | ||||
| #[cfg_attr(
 | ||||
|  |  | |||
|  | @ -1,8 +1,11 @@ | |||
| use super::State; | ||||
| use crate::{pdu::PduBuilder, ConduitResult, Database, Error, Ruma}; | ||||
| use ruma::api::client::{ | ||||
|     error::ErrorKind, | ||||
|     r0::message::{get_message_events, send_message_event}, | ||||
| use ruma::{ | ||||
|     api::client::{ | ||||
|         error::ErrorKind, | ||||
|         r0::message::{get_message_events, send_message_event}, | ||||
|     }, | ||||
|     events::EventContent, | ||||
| }; | ||||
| use std::convert::TryInto; | ||||
| 
 | ||||
|  | @ -26,7 +29,7 @@ pub fn send_message_event_route( | |||
|         PduBuilder { | ||||
|             room_id: body.room_id.clone(), | ||||
|             sender: sender_id.clone(), | ||||
|             event_type: body.event_type.clone(), | ||||
|             event_type: body.content.event_type().into(), | ||||
|             content: serde_json::from_str( | ||||
|                 body.json_body | ||||
|                     .ok_or(Error::BadRequest(ErrorKind::BadJson, "Invalid JSON body."))? | ||||
|  | @ -41,7 +44,7 @@ pub fn send_message_event_route( | |||
|         &db.account_data, | ||||
|     )?; | ||||
| 
 | ||||
|     Ok(send_message_event::Response { event_id }.into()) | ||||
|     Ok(send_message_event::Response::new(event_id).into()) | ||||
| } | ||||
| 
 | ||||
| #[cfg_attr(
 | ||||
|  | @ -50,7 +53,7 @@ pub fn send_message_event_route( | |||
| )] | ||||
| pub fn get_message_events_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<get_message_events::Request>, | ||||
|     body: Ruma<get_message_events::IncomingRequest>, | ||||
| ) -> ConduitResult<get_message_events::Response> { | ||||
|     let sender_id = body.sender_id.as_ref().expect("user is authenticated"); | ||||
| 
 | ||||
|  | @ -92,13 +95,13 @@ pub fn get_message_events_route( | |||
|                 .map(|(_, pdu)| pdu.to_room_event()) | ||||
|                 .collect::<Vec<_>>(); | ||||
| 
 | ||||
|             Ok(get_message_events::Response { | ||||
|                 start: Some(body.from.clone()), | ||||
|                 end: end_token, | ||||
|                 chunk: events_after, | ||||
|                 state: Vec::new(), | ||||
|             } | ||||
|             .into()) | ||||
|             let mut resp = get_message_events::Response::new(); | ||||
|             resp.start = Some(body.from.clone()); | ||||
|             resp.end = end_token; | ||||
|             resp.chunk = events_after; | ||||
|             resp.state = Vec::new(); | ||||
| 
 | ||||
|             Ok(resp.into()) | ||||
|         } | ||||
|         get_message_events::Direction::Backward => { | ||||
|             let events_before = db | ||||
|  | @ -116,13 +119,13 @@ pub fn get_message_events_route( | |||
|                 .map(|(_, pdu)| pdu.to_room_event()) | ||||
|                 .collect::<Vec<_>>(); | ||||
| 
 | ||||
|             Ok(get_message_events::Response { | ||||
|                 start: Some(body.from.clone()), | ||||
|                 end: start_token, | ||||
|                 chunk: events_before, | ||||
|                 state: Vec::new(), | ||||
|             } | ||||
|             .into()) | ||||
|             let mut resp = get_message_events::Response::new(); | ||||
|             resp.start = Some(body.from.clone()); | ||||
|             resp.end = start_token; | ||||
|             resp.chunk = events_before; | ||||
|             resp.state = Vec::new(); | ||||
| 
 | ||||
|             Ok(resp.into()) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -315,7 +315,7 @@ pub fn create_room_route( | |||
|         db.rooms.set_public(&room_id, true)?; | ||||
|     } | ||||
| 
 | ||||
|     Ok(create_room::Response { room_id }.into()) | ||||
|     Ok(create_room::Response::new(room_id).into()) | ||||
| } | ||||
| 
 | ||||
| #[cfg_attr(
 | ||||
|  |  | |||
|  | @ -1,5 +1,4 @@ | |||
| use super::State; | ||||
| use super::{DEVICE_ID_LENGTH, TOKEN_LENGTH}; | ||||
| use super::{State, DEVICE_ID_LENGTH, TOKEN_LENGTH}; | ||||
| use crate::{utils, ConduitResult, Database, Error, Ruma}; | ||||
| use ruma::{ | ||||
|     api::client::{ | ||||
|  | @ -18,10 +17,7 @@ use rocket::{get, post}; | |||
| /// when logging in.
 | ||||
| #[cfg_attr(feature = "conduit_bin", get("/_matrix/client/r0/login"))] | ||||
| pub fn get_login_types_route() -> ConduitResult<get_login_types::Response> { | ||||
|     Ok(get_login_types::Response { | ||||
|         flows: vec![get_login_types::LoginType::Password], | ||||
|     } | ||||
|     .into()) | ||||
|     Ok(get_login_types::Response::new(vec![get_login_types::LoginType::Password]).into()) | ||||
| } | ||||
| 
 | ||||
| /// # `POST /_matrix/client/r0/login`
 | ||||
|  | @ -40,15 +36,15 @@ pub fn get_login_types_route() -> ConduitResult<get_login_types::Response> { | |||
| )] | ||||
| pub fn login_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<login::Request>, | ||||
|     body: Ruma<login::IncomingRequest>, | ||||
| ) -> ConduitResult<login::Response> { | ||||
|     // Validate login method
 | ||||
|     let user_id = | ||||
|         // TODO: Other login methods
 | ||||
|         if let (login::UserInfo::MatrixId(username), login::LoginInfo::Password { password }) = | ||||
|             (body.user.clone(), body.login_info.clone()) | ||||
|         if let (login::IncomingUserInfo::MatrixId(username), login::IncomingLoginInfo::Password { password }) = | ||||
|             (&body.user, &body.login_info) | ||||
|         { | ||||
|             let user_id = UserId::parse_with_server_name(username, db.globals.server_name()) | ||||
|             let user_id = UserId::parse_with_server_name(username.to_string(), db.globals.server_name()) | ||||
|                 .map_err(|_| Error::BadRequest( | ||||
|                     ErrorKind::InvalidUsername, | ||||
|                     "Username is invalid." | ||||
|  | @ -126,7 +122,7 @@ pub fn logout_route( | |||
| 
 | ||||
|     db.users.remove_device(&sender_id, device_id)?; | ||||
| 
 | ||||
|     Ok(logout::Response.into()) | ||||
|     Ok(logout::Response::new().into()) | ||||
| } | ||||
| 
 | ||||
| /// # `POST /_matrix/client/r0/logout/all`
 | ||||
|  | @ -154,5 +150,5 @@ pub fn logout_all_route( | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     Ok(logout_all::Response.into()) | ||||
|     Ok(logout_all::Response::new().into()) | ||||
| } | ||||
|  |  | |||
|  | @ -8,9 +8,9 @@ use ruma::{ | |||
|             send_state_event_for_empty_key, send_state_event_for_key, | ||||
|         }, | ||||
|     }, | ||||
|     events::{room::canonical_alias, EventType}, | ||||
|     Raw, | ||||
|     events::{AnyStateEventContent, EventContent}, | ||||
| }; | ||||
| use std::convert::TryFrom; | ||||
| 
 | ||||
| #[cfg(feature = "conduit_bin")] | ||||
| use rocket::{get, put}; | ||||
|  | @ -33,17 +33,10 @@ pub fn send_state_event_for_key_route( | |||
|     ) | ||||
|     .map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Invalid JSON body."))?; | ||||
| 
 | ||||
|     if body.event_type == EventType::RoomCanonicalAlias { | ||||
|         let canonical_alias = serde_json::from_value::< | ||||
|             Raw<canonical_alias::CanonicalAliasEventContent>, | ||||
|         >(content.clone()) | ||||
|         .expect("from_value::<Raw<..>> can never fail") | ||||
|         .deserialize() | ||||
|         .map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid canonical alias."))?; | ||||
|     if let AnyStateEventContent::RoomCanonicalAlias(canonical_alias) = &body.content { | ||||
|         let mut aliases = canonical_alias.alt_aliases.clone(); | ||||
| 
 | ||||
|         let mut aliases = canonical_alias.alt_aliases; | ||||
| 
 | ||||
|         if let Some(alias) = canonical_alias.alias { | ||||
|         if let Some(alias) = canonical_alias.alias.clone() { | ||||
|             aliases.push(alias); | ||||
|         } | ||||
| 
 | ||||
|  | @ -68,7 +61,7 @@ pub fn send_state_event_for_key_route( | |||
|         PduBuilder { | ||||
|             room_id: body.room_id.clone(), | ||||
|             sender: sender_id.clone(), | ||||
|             event_type: body.event_type.clone(), | ||||
|             event_type: body.content.event_type().into(), | ||||
|             content, | ||||
|             unsigned: None, | ||||
|             state_key: Some(body.state_key.clone()), | ||||
|  | @ -78,7 +71,7 @@ pub fn send_state_event_for_key_route( | |||
|         &db.account_data, | ||||
|     )?; | ||||
| 
 | ||||
|     Ok(send_state_event_for_key::Response { event_id }.into()) | ||||
|     Ok(send_state_event_for_key::Response::new(event_id).into()) | ||||
| } | ||||
| 
 | ||||
| #[cfg_attr(
 | ||||
|  | @ -93,25 +86,28 @@ pub fn send_state_event_for_empty_key_route( | |||
|     let Ruma { | ||||
|         body: | ||||
|             send_state_event_for_empty_key::IncomingRequest { | ||||
|                 room_id, | ||||
|                 event_type, | ||||
|                 data, | ||||
|                 room_id, content, .. | ||||
|             }, | ||||
|         sender_id, | ||||
|         device_id, | ||||
|         json_body, | ||||
|     } = body; | ||||
| 
 | ||||
|     Ok(send_state_event_for_empty_key::Response { | ||||
|         event_id: send_state_event_for_key_route( | ||||
|     Ok(send_state_event_for_empty_key::Response::new( | ||||
|         send_state_event_for_key_route( | ||||
|             db, | ||||
|             Ruma { | ||||
|                 body: send_state_event_for_key::IncomingRequest { | ||||
|                     room_id, | ||||
|                     event_type, | ||||
|                     data, | ||||
|                     state_key: "".to_owned(), | ||||
|                 }, | ||||
|                 body: send_state_event_for_key::IncomingRequest::try_from(http::Request::new( | ||||
|                     serde_json::json!({ | ||||
|                         "room_id": room_id, | ||||
|                         "state_key": "", | ||||
|                         "content": content, | ||||
|                     }) | ||||
|                     .to_string() | ||||
|                     .as_bytes() | ||||
|                     .to_vec(), | ||||
|                 )) | ||||
|                 .unwrap(), | ||||
|                 sender_id, | ||||
|                 device_id, | ||||
|                 json_body, | ||||
|  | @ -119,7 +115,7 @@ pub fn send_state_event_for_empty_key_route( | |||
|         )? | ||||
|         .0 | ||||
|         .event_id, | ||||
|     } | ||||
|     ) | ||||
|     .into()) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -31,7 +31,7 @@ use std::{ | |||
| )] | ||||
| pub async fn sync_events_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<sync_events::Request>, | ||||
|     body: Ruma<sync_events::IncomingRequest>, | ||||
| ) -> ConduitResult<sync_events::Response> { | ||||
|     let sender_id = body.sender_id.as_ref().expect("user is authenticated"); | ||||
|     let device_id = body.device_id.as_ref().expect("user is authenticated"); | ||||
|  |  | |||
|  | @ -1,6 +1,5 @@ | |||
| use crate::ConduitResult; | ||||
| use ruma::api::client::unversioned::get_supported_versions; | ||||
| use std::collections::BTreeMap; | ||||
| 
 | ||||
| #[cfg(feature = "conduit_bin")] | ||||
| use rocket::get; | ||||
|  | @ -17,13 +16,11 @@ use rocket::get; | |||
| /// unstable features in their stable releases
 | ||||
| #[cfg_attr(feature = "conduit_bin", get("/_matrix/client/versions"))] | ||||
| pub fn get_supported_versions_route() -> ConduitResult<get_supported_versions::Response> { | ||||
|     let mut unstable_features = BTreeMap::new(); | ||||
|     let mut resp = | ||||
|         get_supported_versions::Response::new(vec!["r0.5.0".to_owned(), "r0.6.0".to_owned()]); | ||||
| 
 | ||||
|     unstable_features.insert("org.matrix.e2e_cross_signing".to_owned(), true); | ||||
|     resp.unstable_features | ||||
|         .insert("org.matrix.e2e_cross_signing".to_owned(), true); | ||||
| 
 | ||||
|     Ok(get_supported_versions::Response { | ||||
|         versions: vec!["r0.5.0".to_owned(), "r0.6.0".to_owned()], | ||||
|         unstable_features, | ||||
|     } | ||||
|     .into()) | ||||
|     Ok(resp.into()) | ||||
| } | ||||
|  |  | |||
|  | @ -97,8 +97,8 @@ impl Database { | |||
|                 }, | ||||
|                 pduid_pdu: db.open_tree("pduid_pdu")?, | ||||
|                 eventid_pduid: db.open_tree("eventid_pduid")?, | ||||
|                 roomstateid_pduid: db.open_tree("roomstateid_pduid")?, | ||||
|                 roomid_pduleaves: db.open_tree("roomid_pduleaves")?, | ||||
|                 roomstateid_pdu: db.open_tree("roomstateid_pdu")?, | ||||
| 
 | ||||
|                 alias_roomid: db.open_tree("alias_roomid")?, | ||||
|                 aliasid_alias: db.open_tree("alias_roomid")?, | ||||
|  | @ -111,6 +111,9 @@ impl Database { | |||
|                 userroomid_invited: db.open_tree("userroomid_invited")?, | ||||
|                 roomuserid_invited: db.open_tree("roomuserid_invited")?, | ||||
|                 userroomid_left: db.open_tree("userroomid_left")?, | ||||
| 
 | ||||
|                 stateid_pduid: db.open_tree("stateid_pduid")?, | ||||
|                 pduid_statehash: db.open_tree("pduid_statehash")?, | ||||
|             }, | ||||
|             account_data: account_data::AccountData { | ||||
|                 roomuserdataid_accountdata: db.open_tree("roomuserdataid_accountdata")?, | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ use ruma::{ | |||
|     events::{ | ||||
|         ignored_user_list, | ||||
|         room::{ | ||||
|             join_rules, member, | ||||
|             member, | ||||
|             power_levels::{self, PowerLevelsEventContent}, | ||||
|             redaction, | ||||
|         }, | ||||
|  | @ -18,19 +18,31 @@ use ruma::{ | |||
|     EventId, Raw, RoomAliasId, RoomId, UserId, | ||||
| }; | ||||
| use sled::IVec; | ||||
| use state_res::{event_auth, Requester, StateEvent, StateMap, StateStore}; | ||||
| 
 | ||||
| use std::{ | ||||
|     collections::{BTreeMap, HashMap}, | ||||
|     collections::{hash_map::DefaultHasher, BTreeMap, HashMap}, | ||||
|     convert::{TryFrom, TryInto}, | ||||
|     hash::{Hash, Hasher}, | ||||
|     mem, | ||||
|     result::Result as StdResult, | ||||
| }; | ||||
| 
 | ||||
| /// The unique identifier of each state group.
 | ||||
| ///
 | ||||
| /// This is created when a state group is added to the database by
 | ||||
| /// hashing the entire state.
 | ||||
| pub type StateHashId = String; | ||||
| 
 | ||||
| /// This identifier consists of roomId + count. It represents a
 | ||||
| /// unique event, it will never be overwritten or removed.
 | ||||
| pub type PduId = IVec; | ||||
| 
 | ||||
| pub struct Rooms { | ||||
|     pub edus: edus::RoomEdus, | ||||
|     pub(super) pduid_pdu: sled::Tree, // PduId = RoomId + Count
 | ||||
|     pub(super) eventid_pduid: sled::Tree, | ||||
|     pub(super) roomid_pduleaves: sled::Tree, | ||||
|     pub(super) roomstateid_pdu: sled::Tree, // RoomStateId = Room + StateType + StateKey
 | ||||
| 
 | ||||
|     pub(super) alias_roomid: sled::Tree, | ||||
|     pub(super) aliasid_alias: sled::Tree, // AliasId = RoomId + Count
 | ||||
|     pub(super) publicroomids: sled::Tree, | ||||
|  | @ -42,9 +54,263 @@ pub struct Rooms { | |||
|     pub(super) userroomid_invited: sled::Tree, | ||||
|     pub(super) roomuserid_invited: sled::Tree, | ||||
|     pub(super) userroomid_left: sled::Tree, | ||||
| 
 | ||||
|     // STATE TREES
 | ||||
|     /// This holds the full current state, including the latest event.
 | ||||
|     pub(super) roomstateid_pduid: sled::Tree, // RoomStateId = Room + StateType + StateKey
 | ||||
|     /// This holds the full room state minus the latest event.
 | ||||
|     pub(super) pduid_statehash: sled::Tree, // PDU id -> StateHash
 | ||||
|     /// Also holds the full room state minus the latest event.
 | ||||
|     pub(super) stateid_pduid: sled::Tree, // StateId = StateHash + (EventType, StateKey)
 | ||||
| } | ||||
| 
 | ||||
| impl StateStore for Rooms { | ||||
|     fn get_event(&self, room_id: &RoomId, event_id: &EventId) -> StdResult<StateEvent, String> { | ||||
|         let pid = self | ||||
|             .eventid_pduid | ||||
|             .get(event_id.as_bytes()) | ||||
|             .map_err(|e| e.to_string())? | ||||
|             .ok_or_else(|| "PDU via room_id and event_id not found in the db.".to_owned())?; | ||||
| 
 | ||||
|         utils::deserialize( | ||||
|             &self | ||||
|                 .pduid_pdu | ||||
|                 .get(pid) | ||||
|                 .map_err(|e| e.to_string())? | ||||
|                 .ok_or_else(|| "PDU via pduid not found in db.".to_owned())?, | ||||
|         ) | ||||
|         .and_then(|pdu: StateEvent| { | ||||
|             // conduit's PDU's always contain a room_id but some
 | ||||
|             // of ruma's do not so this must be an Option
 | ||||
|             if pdu.room_id() == Some(room_id) { | ||||
|                 Ok(pdu) | ||||
|             } else { | ||||
|                 Err(Error::bad_database("Found PDU for incorrect room in db.")) | ||||
|             } | ||||
|         }) | ||||
|         .map_err(|e| e.to_string()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // These are the methods related to STATE resolution.
 | ||||
| impl Rooms { | ||||
|     /// Generates a new StateHash and associates it with the incoming event.
 | ||||
|     ///
 | ||||
|     /// This adds all current state events (not including the incoming event)
 | ||||
|     /// to `stateid_pduid` and adds the incoming event to `pduid_statehash`.
 | ||||
|     /// The incoming event is the `pdu_id` passed to this method.
 | ||||
|     pub fn append_state_pdu(&self, room_id: &RoomId, pdu_id: &[u8]) -> Result<StateHashId> { | ||||
|         let state_hash = self.new_state_hash_id(room_id)?; | ||||
|         let state = self.current_state_pduids(room_id)?; | ||||
| 
 | ||||
|         let mut key = state_hash.as_bytes().to_vec(); | ||||
|         key.push(0xff); | ||||
| 
 | ||||
|         // TODO eventually we could avoid writing to the DB so much on every event
 | ||||
|         // by keeping track of the delta and write that every so often
 | ||||
|         for ((ev_ty, state_key), pid) in state { | ||||
|             let mut state_id = key.to_vec(); | ||||
|             state_id.extend_from_slice(ev_ty.to_string().as_bytes()); | ||||
|             key.push(0xff); | ||||
|             state_id.extend_from_slice(state_key.expect("state event").as_bytes()); | ||||
|             key.push(0xff); | ||||
| 
 | ||||
|             self.stateid_pduid.insert(&state_id, &pid)?; | ||||
|         } | ||||
| 
 | ||||
|         // This event's state does not include the event itself. `current_state_pduids`
 | ||||
|         // uses `roomstateid_pduid` before the current event is inserted to the tree so the state
 | ||||
|         // will be everything up to but not including the incoming event.
 | ||||
|         self.pduid_statehash.insert(pdu_id, state_hash.as_bytes())?; | ||||
| 
 | ||||
|         Ok(state_hash) | ||||
|     } | ||||
| 
 | ||||
|     /// Builds a `StateMap` by iterating over all keys that start
 | ||||
|     /// with `state_hash`, this gives the full state at event "x".
 | ||||
|     pub fn get_statemap_by_hash(&self, state_hash: StateHashId) -> Result<StateMap<EventId>> { | ||||
|         self.stateid_pduid | ||||
|             .scan_prefix(state_hash.as_bytes()) | ||||
|             .values() | ||||
|             .map(|pduid| { | ||||
|                 self.pduid_pdu.get(&pduid?)?.map_or_else( | ||||
|                     || Err(Error::bad_database("Failed to find StateMap.")), | ||||
|                     |b| { | ||||
|                         serde_json::from_slice::<PduEvent>(&b) | ||||
|                             .map_err(|_| Error::bad_database("Invalid PDU in db.")) | ||||
|                     }, | ||||
|                 ) | ||||
|             }) | ||||
|             .map(|pdu| { | ||||
|                 let pdu = pdu?; | ||||
|                 Ok(((pdu.kind, pdu.state_key), pdu.event_id)) | ||||
|             }) | ||||
|             .collect::<Result<StateMap<_>>>() | ||||
|     } | ||||
| 
 | ||||
|     // TODO make this return Result
 | ||||
|     /// Fetches the previous StateHash ID to `current`.
 | ||||
|     pub fn prev_state_hash(&self, current: StateHashId) -> Option<StateHashId> { | ||||
|         let mut found = false; | ||||
|         for pair in self.pduid_statehash.iter().rev() { | ||||
|             let prev = utils::string_from_bytes(&pair.ok()?.1).ok()?; | ||||
|             if current == prev { | ||||
|                 found = true; | ||||
|             } | ||||
|             if current != prev && found { | ||||
|                 return Some(prev); | ||||
|             } | ||||
|         } | ||||
|         None | ||||
|     } | ||||
| 
 | ||||
|     /// Fetch the current State using the `roomstateid_pduid` tree.
 | ||||
|     pub fn current_state_pduids(&self, room_id: &RoomId) -> Result<StateMap<PduId>> { | ||||
|         // TODO this could also scan roomstateid_pduid if we passed in room_id ?
 | ||||
|         self.roomstateid_pduid | ||||
|             .scan_prefix(room_id.as_bytes()) | ||||
|             .values() | ||||
|             .map(|pduid| { | ||||
|                 let pduid = &pduid?; | ||||
|                 self.pduid_pdu.get(pduid)?.map_or_else( | ||||
|                     || { | ||||
|                         Err(Error::bad_database( | ||||
|                             "Failed to find current state of pduid's.", | ||||
|                         )) | ||||
|                     }, | ||||
|                     |b| { | ||||
|                         Ok(( | ||||
|                             serde_json::from_slice::<PduEvent>(&b) | ||||
|                                 .map_err(|_| Error::bad_database("Invalid PDU in db."))?, | ||||
|                             pduid.clone(), | ||||
|                         )) | ||||
|                     }, | ||||
|                 ) | ||||
|             }) | ||||
|             .map(|pair| { | ||||
|                 let (pdu, id) = pair?; | ||||
|                 Ok(((pdu.kind, pdu.state_key), id)) | ||||
|             }) | ||||
|             .collect::<Result<StateMap<_>>>() | ||||
|     } | ||||
| 
 | ||||
|     /// Returns the last state hash key added to the db.
 | ||||
|     pub fn current_state_hash(&self, room_id: &RoomId) -> Result<StateHashId> { | ||||
|         let mut prefix = room_id.as_bytes().to_vec(); | ||||
|         prefix.push(0xff); | ||||
| 
 | ||||
|         // We must check here because this method is called outside and before
 | ||||
|         // `append_state_pdu` so the DB can be empty
 | ||||
|         if self.pduid_statehash.scan_prefix(prefix).next().is_none() { | ||||
|             // TODO use ring crate to hash
 | ||||
|             return Ok(room_id.as_str().to_owned()); | ||||
|         } | ||||
| 
 | ||||
|         self.pduid_statehash | ||||
|             .iter() | ||||
|             .next_back() | ||||
|             .map(|pair| { | ||||
|                 utils::string_from_bytes(&pair?.1) | ||||
|                     .map_err(|_| Error::bad_database("Invalid state hash string in db.")) | ||||
|             }) | ||||
|             .ok_or_else(|| Error::bad_database("No PDU's found for this room."))? | ||||
|     } | ||||
| 
 | ||||
|     /// This fetches auth event_ids from the current state using the
 | ||||
|     /// full `roomstateid_pdu` tree.
 | ||||
|     pub fn get_auth_event_ids( | ||||
|         &self, | ||||
|         room_id: &RoomId, | ||||
|         kind: &EventType, | ||||
|         sender: &UserId, | ||||
|         state_key: Option<&str>, | ||||
|         content: serde_json::Value, | ||||
|     ) -> Result<Vec<EventId>> { | ||||
|         let auth_events = state_res::auth_types_for_event( | ||||
|             kind.clone(), | ||||
|             sender, | ||||
|             state_key.map(|s| s.to_string()), | ||||
|             content, | ||||
|         ); | ||||
| 
 | ||||
|         let mut events = vec![]; | ||||
|         for (event_type, state_key) in auth_events { | ||||
|             if let Some(state_key) = state_key.as_ref() { | ||||
|                 if let Some(id) = self.room_state_get(room_id, &event_type, state_key)? { | ||||
|                     events.push(id.event_id); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         Ok(events) | ||||
|     } | ||||
| 
 | ||||
|     // This fetches auth events from the current state using the
 | ||||
|     /// full `roomstateid_pdu` tree.
 | ||||
|     pub fn get_auth_events( | ||||
|         &self, | ||||
|         room_id: &RoomId, | ||||
|         kind: &EventType, | ||||
|         sender: &UserId, | ||||
|         state_key: Option<&str>, | ||||
|         content: serde_json::Value, | ||||
|     ) -> Result<StateMap<PduEvent>> { | ||||
|         let auth_events = state_res::auth_types_for_event( | ||||
|             kind.clone(), | ||||
|             sender, | ||||
|             state_key.map(|s| s.to_string()), | ||||
|             content, | ||||
|         ); | ||||
| 
 | ||||
|         let mut events = StateMap::new(); | ||||
|         for (event_type, state_key) in auth_events { | ||||
|             if let Some(s_key) = state_key.as_ref() { | ||||
|                 if let Some(pdu) = self.room_state_get(room_id, &event_type, s_key)? { | ||||
|                     events.insert((event_type, state_key), pdu); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         Ok(events) | ||||
|     } | ||||
| 
 | ||||
|     /// Generate a new StateHash.
 | ||||
|     ///
 | ||||
|     /// A unique hash made from hashing the current states pduid's.
 | ||||
|     /// Because `append_state_pdu` handles the empty state db case it does not
 | ||||
|     /// have to be here.
 | ||||
|     fn new_state_hash_id(&self, room_id: &RoomId) -> Result<StateHashId> { | ||||
|         // Use hashed roomId as the first StateHash key for first state event in room
 | ||||
|         if self | ||||
|             .pduid_statehash | ||||
|             .scan_prefix(room_id.as_bytes()) | ||||
|             .next() | ||||
|             .is_none() | ||||
|         { | ||||
|             // TODO use ring crate to hash
 | ||||
|             return Ok(room_id.as_str().to_owned()); | ||||
|         } | ||||
| 
 | ||||
|         let pdu_ids_to_hash = self | ||||
|             .pduid_statehash | ||||
|             .scan_prefix(room_id.as_bytes()) | ||||
|             .values() | ||||
|             .next_back() | ||||
|             .unwrap() // We just checked if the tree was empty
 | ||||
|             .map(|hash| { | ||||
|                 self.stateid_pduid | ||||
|                     .scan_prefix(hash) | ||||
|                     .values() | ||||
|                     // pduid is roomId + count so just hash the whole thing
 | ||||
|                     .map(|pid| Ok(pid?.to_vec())) | ||||
|                     .collect::<Result<Vec<Vec<u8>>>>() | ||||
|             })??; | ||||
| 
 | ||||
|         let mut hasher = DefaultHasher::new(); | ||||
|         pdu_ids_to_hash.hash(&mut hasher); | ||||
|         let hash = hasher.finish().to_string(); | ||||
|         // TODO not sure how you want to hash this
 | ||||
|         Ok(hash) | ||||
|     } | ||||
| 
 | ||||
|     /// Checks if a room exists.
 | ||||
|     pub fn exists(&self, room_id: &RoomId) -> Result<bool> { | ||||
|         let mut prefix = room_id.to_string().as_bytes().to_vec(); | ||||
|  | @ -64,16 +330,20 @@ impl Rooms { | |||
|         room_id: &RoomId, | ||||
|     ) -> Result<HashMap<(EventType, String), PduEvent>> { | ||||
|         let mut hashmap = HashMap::new(); | ||||
|         for pdu in self | ||||
|             .roomstateid_pdu | ||||
|             .scan_prefix(&room_id.to_string().as_bytes()) | ||||
|             .values() | ||||
|             .map(|value| { | ||||
|                 Ok::<_, Error>( | ||||
|                     serde_json::from_slice::<PduEvent>(&value?) | ||||
|         for pdu in | ||||
|             self.roomstateid_pduid | ||||
|                 .scan_prefix(&room_id.to_string().as_bytes()) | ||||
|                 .values() | ||||
|                 .map(|value| { | ||||
|                     Ok::<_, Error>( | ||||
|                         serde_json::from_slice::<PduEvent>( | ||||
|                             &self.pduid_pdu.get(value?)?.ok_or_else(|| { | ||||
|                                 Error::bad_database("PDU not found for ID in db.") | ||||
|                             })?, | ||||
|                         ) | ||||
|                         .map_err(|_| Error::bad_database("Invalid PDU in db."))?, | ||||
|                 ) | ||||
|             }) | ||||
|                     ) | ||||
|                 }) | ||||
|         { | ||||
|             let pdu = pdu?; | ||||
|             let state_key = pdu.state_key.clone().ok_or_else(|| { | ||||
|  | @ -95,16 +365,20 @@ impl Rooms { | |||
|         prefix.extend_from_slice(&event_type.to_string().as_bytes()); | ||||
| 
 | ||||
|         let mut hashmap = HashMap::new(); | ||||
|         for pdu in self | ||||
|             .roomstateid_pdu | ||||
|             .scan_prefix(&prefix) | ||||
|             .values() | ||||
|             .map(|value| { | ||||
|                 Ok::<_, Error>( | ||||
|                     serde_json::from_slice::<PduEvent>(&value?) | ||||
|         for pdu in | ||||
|             self.roomstateid_pduid | ||||
|                 .scan_prefix(&prefix) | ||||
|                 .values() | ||||
|                 .map(|value| { | ||||
|                     Ok::<_, Error>( | ||||
|                         serde_json::from_slice::<PduEvent>( | ||||
|                             &self.pduid_pdu.get(value?)?.ok_or_else(|| { | ||||
|                                 Error::bad_database("PDU not found for ID in db.") | ||||
|                             })?, | ||||
|                         ) | ||||
|                         .map_err(|_| Error::bad_database("Invalid PDU in db."))?, | ||||
|                 ) | ||||
|             }) | ||||
|                     ) | ||||
|                 }) | ||||
|         { | ||||
|             let pdu = pdu?; | ||||
|             let state_key = pdu.state_key.clone().ok_or_else(|| { | ||||
|  | @ -115,23 +389,28 @@ impl Rooms { | |||
|         Ok(hashmap) | ||||
|     } | ||||
| 
 | ||||
|     /// Returns the full room state.
 | ||||
|     /// Returns a single PDU in `room_id` with key (`event_type`, `state_key`).
 | ||||
|     pub fn room_state_get( | ||||
|         &self, | ||||
|         room_id: &RoomId, | ||||
|         event_type: &EventType, | ||||
|         state_key: &str, | ||||
|     ) -> Result<Option<PduEvent>> { | ||||
|         let mut key = room_id.to_string().as_bytes().to_vec(); | ||||
|         let mut key = room_id.as_bytes().to_vec(); | ||||
|         key.push(0xff); | ||||
|         key.extend_from_slice(&event_type.to_string().as_bytes()); | ||||
|         key.push(0xff); | ||||
|         key.extend_from_slice(&state_key.as_bytes()); | ||||
| 
 | ||||
|         self.roomstateid_pdu.get(&key)?.map_or(Ok(None), |value| { | ||||
|         self.roomstateid_pduid.get(&key)?.map_or(Ok(None), |value| { | ||||
|             Ok::<_, Error>(Some( | ||||
|                 serde_json::from_slice::<PduEvent>(&value) | ||||
|                     .map_err(|_| Error::bad_database("Invalid PDU in db."))?, | ||||
|                 serde_json::from_slice::<PduEvent>( | ||||
|                     &self | ||||
|                         .pduid_pdu | ||||
|                         .get(value)? | ||||
|                         .ok_or_else(|| Error::bad_database("PDU not found for ID in db."))?, | ||||
|                 ) | ||||
|                 .map_err(|_| Error::bad_database("Invalid PDU in db."))?, | ||||
|             )) | ||||
|         }) | ||||
|     } | ||||
|  | @ -139,7 +418,7 @@ impl Rooms { | |||
|     /// Returns the `count` of this pdu's id.
 | ||||
|     pub fn get_pdu_count(&self, event_id: &EventId) -> Result<Option<u64>> { | ||||
|         self.eventid_pduid | ||||
|             .get(event_id.to_string().as_bytes())? | ||||
|             .get(event_id.as_bytes())? | ||||
|             .map_or(Ok(None), |pdu_id| { | ||||
|                 Ok(Some( | ||||
|                     utils::u64_from_bytes( | ||||
|  | @ -153,7 +432,7 @@ impl Rooms { | |||
|     /// Returns the json of a pdu.
 | ||||
|     pub fn get_pdu_json(&self, event_id: &EventId) -> Result<Option<serde_json::Value>> { | ||||
|         self.eventid_pduid | ||||
|             .get(event_id.to_string().as_bytes())? | ||||
|             .get(event_id.as_bytes())? | ||||
|             .map_or(Ok(None), |pdu_id| { | ||||
|                 Ok(Some( | ||||
|                     serde_json::from_slice(&self.pduid_pdu.get(pdu_id)?.ok_or_else(|| { | ||||
|  | @ -174,7 +453,7 @@ impl Rooms { | |||
|     /// Returns the pdu.
 | ||||
|     pub fn get_pdu(&self, event_id: &EventId) -> Result<Option<PduEvent>> { | ||||
|         self.eventid_pduid | ||||
|             .get(event_id.to_string().as_bytes())? | ||||
|             .get(event_id.as_bytes())? | ||||
|             .map_or(Ok(None), |pdu_id| { | ||||
|                 Ok(Some( | ||||
|                     serde_json::from_slice(&self.pduid_pdu.get(pdu_id)?.ok_or_else(|| { | ||||
|  | @ -238,16 +517,15 @@ impl Rooms { | |||
| 
 | ||||
|     /// Replace the leaves of a room with a new event.
 | ||||
|     pub fn replace_pdu_leaves(&self, room_id: &RoomId, event_id: &EventId) -> Result<()> { | ||||
|         let mut prefix = room_id.to_string().as_bytes().to_vec(); | ||||
|         let mut prefix = room_id.as_bytes().to_vec(); | ||||
|         prefix.push(0xff); | ||||
| 
 | ||||
|         for key in self.roomid_pduleaves.scan_prefix(&prefix).keys() { | ||||
|             self.roomid_pduleaves.remove(key?)?; | ||||
|         } | ||||
| 
 | ||||
|         prefix.extend_from_slice(event_id.to_string().as_bytes()); | ||||
|         self.roomid_pduleaves | ||||
|             .insert(&prefix, &*event_id.to_string())?; | ||||
|         prefix.extend_from_slice(event_id.as_bytes()); | ||||
|         self.roomid_pduleaves.insert(&prefix, event_id.as_bytes())?; | ||||
| 
 | ||||
|         Ok(()) | ||||
|     } | ||||
|  | @ -272,6 +550,14 @@ impl Rooms { | |||
|         // TODO: Make sure this isn't called twice in parallel
 | ||||
|         let prev_events = self.get_pdu_leaves(&room_id)?; | ||||
| 
 | ||||
|         let auth_events = self.get_auth_events( | ||||
|             &room_id, | ||||
|             &event_type, | ||||
|             &sender, | ||||
|             state_key.as_deref(), | ||||
|             content.clone(), | ||||
|         )?; | ||||
| 
 | ||||
|         // Is the event authorized?
 | ||||
|         if let Some(state_key) = &state_key { | ||||
|             let power_levels = self | ||||
|  | @ -333,138 +619,24 @@ impl Rooms { | |||
|                     // Don't allow encryption events when it's disabled
 | ||||
|                     !globals.encryption_disabled() | ||||
|                 } | ||||
|                 EventType::RoomMember => { | ||||
|                     let target_user_id = UserId::try_from(&**state_key).map_err(|_| { | ||||
|                         Error::BadRequest( | ||||
|                             ErrorKind::InvalidParam, | ||||
|                             "State key of member event does not contain user id.", | ||||
|                         ) | ||||
|                     })?; | ||||
| 
 | ||||
|                     let current_membership = self | ||||
|                         .room_state_get( | ||||
|                             &room_id, | ||||
|                             &EventType::RoomMember, | ||||
|                             &target_user_id.to_string(), | ||||
|                         )? | ||||
|                         .map_or(Ok::<_, Error>(member::MembershipState::Leave), |pdu| { | ||||
|                             Ok(serde_json::from_value::<Raw<member::MemberEventContent>>( | ||||
|                                 pdu.content, | ||||
|                             ) | ||||
|                             .expect("Raw::from_value always works.") | ||||
|                             .deserialize() | ||||
|                             .map_err(|_| Error::bad_database("Invalid Member event in db."))? | ||||
|                             .membership) | ||||
|                         })?; | ||||
| 
 | ||||
|                     let target_membership = | ||||
|                         serde_json::from_value::<Raw<member::MemberEventContent>>(content.clone()) | ||||
|                             .expect("Raw::from_value always works.") | ||||
|                             .deserialize() | ||||
|                             .map_err(|_| Error::bad_database("Invalid Member event in db."))? | ||||
|                             .membership; | ||||
| 
 | ||||
|                     let target_power = power_levels.users.get(&target_user_id).map_or_else( | ||||
|                         || { | ||||
|                             if target_membership != member::MembershipState::Join { | ||||
|                                 None | ||||
|                             } else { | ||||
|                                 Some(&power_levels.users_default) | ||||
|                             } | ||||
|                         }, | ||||
|                         // If it's okay, wrap with Some(_)
 | ||||
|                         Some, | ||||
|                     ); | ||||
| 
 | ||||
|                     let join_rules = | ||||
|                         self.room_state_get(&room_id, &EventType::RoomJoinRules, "")? | ||||
|                             .map_or(Ok::<_, Error>(join_rules::JoinRule::Public), |pdu| { | ||||
|                                 Ok(serde_json::from_value::< | ||||
|                                     Raw<join_rules::JoinRulesEventContent>, | ||||
|                                 >(pdu.content) | ||||
|                                 .expect("Raw::from_value always works.") | ||||
|                                 .deserialize() | ||||
|                                 .map_err(|_| { | ||||
|                                     Error::bad_database("Database contains invalid JoinRules event") | ||||
|                                 })? | ||||
|                                 .join_rule) | ||||
|                             })?; | ||||
| 
 | ||||
|                     if target_membership == member::MembershipState::Join { | ||||
|                         let mut prev_events = prev_events.iter(); | ||||
|                         let prev_event = self | ||||
|                             .get_pdu(prev_events.next().ok_or(Error::BadRequest( | ||||
|                                 ErrorKind::Unknown, | ||||
|                                 "Membership can't be the first event", | ||||
|                             ))?)? | ||||
|                             .ok_or_else(|| { | ||||
|                                 Error::bad_database("PDU leaf points to invalid event!") | ||||
|                             })?; | ||||
|                         if prev_event.kind == EventType::RoomCreate | ||||
|                             && prev_event.prev_events.is_empty() | ||||
|                         { | ||||
|                             true | ||||
|                         } else if sender != target_user_id { | ||||
|                             false | ||||
|                         } else if let member::MembershipState::Ban = current_membership { | ||||
|                             false | ||||
|                         } else { | ||||
|                             join_rules == join_rules::JoinRule::Invite | ||||
|                                 && (current_membership == member::MembershipState::Join | ||||
|                                     || current_membership == member::MembershipState::Invite) | ||||
|                                 || join_rules == join_rules::JoinRule::Public | ||||
|                         } | ||||
|                     } else if target_membership == member::MembershipState::Invite { | ||||
|                         if let Some(third_party_invite_json) = content.get("third_party_invite") { | ||||
|                             if current_membership == member::MembershipState::Ban { | ||||
|                                 false | ||||
|                             } else { | ||||
|                                 let _third_party_invite = | ||||
|                                     serde_json::from_value::<member::ThirdPartyInvite>( | ||||
|                                         third_party_invite_json.clone(), | ||||
|                                     ) | ||||
|                                     .map_err(|_| { | ||||
|                                         Error::BadRequest( | ||||
|                                             ErrorKind::InvalidParam, | ||||
|                                             "ThirdPartyInvite is invalid", | ||||
|                                         ) | ||||
|                                     })?; | ||||
|                                 todo!("handle third party invites"); | ||||
|                             } | ||||
|                         } else if sender_membership != member::MembershipState::Join | ||||
|                             || current_membership == member::MembershipState::Join | ||||
|                             || current_membership == member::MembershipState::Ban | ||||
|                         { | ||||
|                             false | ||||
|                         } else { | ||||
|                             sender_power | ||||
|                                 .filter(|&p| p >= &power_levels.invite) | ||||
|                                 .is_some() | ||||
|                         } | ||||
|                     } else if target_membership == member::MembershipState::Leave { | ||||
|                         if sender == target_user_id { | ||||
|                             current_membership == member::MembershipState::Join | ||||
|                                 || current_membership == member::MembershipState::Invite | ||||
|                         } else if sender_membership != member::MembershipState::Join | ||||
|                             || current_membership == member::MembershipState::Ban | ||||
|                                 && sender_power.filter(|&p| p < &power_levels.ban).is_some() | ||||
|                         { | ||||
|                             false | ||||
|                         } else { | ||||
|                             sender_power.filter(|&p| p >= &power_levels.kick).is_some() | ||||
|                                 && target_power < sender_power | ||||
|                         } | ||||
|                     } else if target_membership == member::MembershipState::Ban { | ||||
|                         if sender_membership != member::MembershipState::Join { | ||||
|                             false | ||||
|                         } else { | ||||
|                             sender_power.filter(|&p| p >= &power_levels.ban).is_some() | ||||
|                                 && target_power < sender_power | ||||
|                         } | ||||
|                     } else { | ||||
|                         false | ||||
|                     } | ||||
|                 } | ||||
|                 EventType::RoomMember => event_auth::is_membership_change_allowed( | ||||
|                     // TODO this is a bit of a hack but not sure how to have a type
 | ||||
|                     // declared in `state_res` crate be
 | ||||
|                     Requester { | ||||
|                         prev_event_ids: prev_events.to_owned(), | ||||
|                         room_id: &room_id, | ||||
|                         content: &content, | ||||
|                         state_key: Some(state_key.to_owned()), | ||||
|                         sender: &sender, | ||||
|                     }, | ||||
|                     &auth_events | ||||
|                         .iter() | ||||
|                         .map(|((ty, key), pdu)| { | ||||
|                             Ok(((ty.clone(), key.clone()), pdu.convert_for_state_res()?)) | ||||
|                         }) | ||||
|                         .collect::<Result<StateMap<_>>>()?, | ||||
|                 ) | ||||
|                 .ok_or(Error::Conflict("Found incoming PDU with invalid data."))?, | ||||
|                 EventType::RoomCreate => prev_events.is_empty(), | ||||
|                 // Not allow any of the following events if the sender is not joined.
 | ||||
|                 _ if sender_membership != member::MembershipState::Join => false, | ||||
|  | @ -474,7 +646,7 @@ impl Rooms { | |||
|                         >= &power_levels.state_default | ||||
|                 } | ||||
|             } { | ||||
|                 error!("Unauthorized"); | ||||
|                 error!("Unauthorized {}", event_type); | ||||
|                 // Not authorized
 | ||||
|                 return Err(Error::BadRequest( | ||||
|                     ErrorKind::Forbidden, | ||||
|  | @ -483,7 +655,7 @@ impl Rooms { | |||
|             } | ||||
|         } else if !self.is_joined(&sender, &room_id)? { | ||||
|             // TODO: auth rules apply to all events, not only those with a state key
 | ||||
|             error!("Unauthorized"); | ||||
|             error!("Unauthorized {}", event_type); | ||||
|             return Err(Error::BadRequest( | ||||
|                 ErrorKind::Forbidden, | ||||
|                 "Event is not authorized", | ||||
|  | @ -524,7 +696,10 @@ impl Rooms { | |||
|             depth: depth | ||||
|                 .try_into() | ||||
|                 .map_err(|_| Error::bad_database("Depth is invalid"))?, | ||||
|             auth_events: Vec::new(), | ||||
|             auth_events: auth_events | ||||
|                 .into_iter() | ||||
|                 .map(|(_, pdu)| pdu.event_id) | ||||
|                 .collect(), | ||||
|             redacts: redacts.clone(), | ||||
|             unsigned, | ||||
|             hashes: ruma::events::pdu::EventHash { | ||||
|  | @ -564,15 +739,19 @@ impl Rooms { | |||
|         self.pduid_pdu.insert(&pdu_id, &*pdu_json.to_string())?; | ||||
| 
 | ||||
|         self.eventid_pduid | ||||
|             .insert(pdu.event_id.to_string(), pdu_id.clone())?; | ||||
|             .insert(pdu.event_id.to_string(), &*pdu_id)?; | ||||
| 
 | ||||
|         if let Some(state_key) = pdu.state_key { | ||||
|             let mut key = room_id.to_string().as_bytes().to_vec(); | ||||
|         if let Some(state_key) = &pdu.state_key { | ||||
|             // We call this first because our StateHash relies on the
 | ||||
|             // state before the new event
 | ||||
|             self.append_state_pdu(&room_id, &pdu_id)?; | ||||
| 
 | ||||
|             let mut key = room_id.as_bytes().to_vec(); | ||||
|             key.push(0xff); | ||||
|             key.extend_from_slice(pdu.kind.to_string().as_bytes()); | ||||
|             key.push(0xff); | ||||
|             key.extend_from_slice(state_key.as_bytes()); | ||||
|             self.roomstateid_pdu.insert(key, &*pdu_json.to_string())?; | ||||
|             self.roomstateid_pduid.insert(key, pdu_id.as_slice())?; | ||||
|         } | ||||
| 
 | ||||
|         match event_type { | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ use crate::{Error, Result}; | |||
| use ruma::{ | ||||
|     api::client::{ | ||||
|         error::ErrorKind, | ||||
|         r0::uiaa::{AuthData, UiaaInfo}, | ||||
|         r0::uiaa::{IncomingAuthData, UiaaInfo}, | ||||
|     }, | ||||
|     DeviceId, UserId, | ||||
| }; | ||||
|  | @ -26,12 +26,12 @@ impl Uiaa { | |||
|         &self, | ||||
|         user_id: &UserId, | ||||
|         device_id: &DeviceId, | ||||
|         auth: &AuthData, | ||||
|         auth: &IncomingAuthData, | ||||
|         uiaainfo: &UiaaInfo, | ||||
|         users: &super::users::Users, | ||||
|         globals: &super::globals::Globals, | ||||
|     ) -> Result<(bool, UiaaInfo)> { | ||||
|         if let AuthData::DirectRequest { | ||||
|         if let IncomingAuthData::DirectRequest { | ||||
|             kind, | ||||
|             session, | ||||
|             auth_parameters, | ||||
|  |  | |||
							
								
								
									
										29
									
								
								src/pdu.rs
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								src/pdu.rs
									
									
									
									
									
								
							|  | @ -177,6 +177,35 @@ impl PduEvent { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| impl PduEvent { | ||||
|     pub fn convert_for_state_res(&self) -> Result<state_res::StateEvent> { | ||||
|         serde_json::from_value(json!({ | ||||
|             "event_id": self.event_id, | ||||
|             "room_id": self.room_id, | ||||
|             "sender": self.sender, | ||||
|             "origin": self.origin, | ||||
|             "origin_server_ts": self.origin_server_ts, | ||||
|             "type": self.kind, | ||||
|             "content": self.content, | ||||
|             "state_key": self.state_key, | ||||
|             "prev_events": self.prev_events | ||||
|                 .iter() | ||||
|                 .map(|id| (id, EventHash { sha256: "hello".into() })) | ||||
|                 .collect::<Vec<_>>(), | ||||
|             "depth": self.depth, | ||||
|             "auth_events": self.auth_events | ||||
|                 .iter() | ||||
|                 .map(|id| (id, EventHash { sha256: "hello".into() })) | ||||
|                 .collect::<Vec<_>>(), | ||||
|             "redacts": self.redacts, | ||||
|             "unsigned": self.unsigned, | ||||
|             "hashes": self.hashes, | ||||
|             "signatures": self.signatures, | ||||
|         })) | ||||
|         .map_err(|_| Error::bad_database("Failed to convert PDU to ruma::Pdu type.")) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Build the start of a PDU in order to add it to the `Database`.
 | ||||
| #[derive(Debug)] | ||||
| pub struct PduBuilder { | ||||
|  |  | |||
|  | @ -1,5 +1,8 @@ | |||
| use crate::Error; | ||||
| use ruma::identifiers::{DeviceId, UserId}; | ||||
| use ruma::{ | ||||
|     api::IncomingRequest, | ||||
|     identifiers::{DeviceId, UserId}, | ||||
| }; | ||||
| use std::{convert::TryInto, ops::Deref}; | ||||
| 
 | ||||
| #[cfg(feature = "conduit_bin")] | ||||
|  | @ -16,13 +19,12 @@ use { | |||
|         tokio::io::AsyncReadExt, | ||||
|         Request, State, | ||||
|     }, | ||||
|     ruma::api::IncomingRequest, | ||||
|     std::io::Cursor, | ||||
| }; | ||||
| 
 | ||||
| /// This struct converts rocket requests into ruma structs by converting them into http requests
 | ||||
| /// first.
 | ||||
| pub struct Ruma<T> { | ||||
| pub struct Ruma<T: IncomingRequest> { | ||||
|     pub body: T, | ||||
|     pub sender_id: Option<UserId>, | ||||
|     pub device_id: Option<Box<DeviceId>>, | ||||
|  | @ -110,7 +112,7 @@ impl<'a, T: IncomingRequest> FromTransformedData<'a> for Ruma<T> { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<T> Deref for Ruma<T> { | ||||
| impl<T: IncomingRequest> Deref for Ruma<T> { | ||||
|     type Target = T; | ||||
| 
 | ||||
|     fn deref(&self) -> &Self::Target { | ||||
|  |  | |||
|  | @ -1,14 +1,17 @@ | |||
| use crate::{client_server, ConduitResult, Database, Error, Result, Ruma}; | ||||
| use http::header::{HeaderValue, AUTHORIZATION}; | ||||
| use rocket::{get, post, put, response::content::Json, State}; | ||||
| use ruma::api::federation::{ | ||||
|     directory::get_public_rooms, | ||||
|     discovery::{ | ||||
|         get_server_keys, get_server_version::v1 as get_server_version, ServerKey, VerifyKey, | ||||
| use ruma::api::{ | ||||
|     client, | ||||
|     federation::{ | ||||
|         directory::get_public_rooms, | ||||
|         discovery::{ | ||||
|             get_server_keys, get_server_version::v1 as get_server_version, ServerKey, VerifyKey, | ||||
|         }, | ||||
|         transactions::send_transaction_message, | ||||
|     }, | ||||
|     transactions::send_transaction_message, | ||||
|     OutgoingRequest, | ||||
| }; | ||||
| use ruma::api::{client, OutgoingRequest}; | ||||
| use serde_json::json; | ||||
| use std::{ | ||||
|     collections::BTreeMap, | ||||
|  | @ -204,11 +207,11 @@ pub fn get_server_keys_deprecated(db: State<'_, Database>) -> Json<String> { | |||
| )] | ||||
| pub async fn get_public_rooms_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<get_public_rooms::v1::Request>, | ||||
|     body: Ruma<get_public_rooms::v1::IncomingRequest>, | ||||
| ) -> ConduitResult<get_public_rooms::v1::Response> { | ||||
|     let Ruma { | ||||
|         body: | ||||
|             get_public_rooms::v1::Request { | ||||
|             get_public_rooms::v1::IncomingRequest { | ||||
|                 room_network: _room_network, // TODO
 | ||||
|                 limit, | ||||
|                 since, | ||||
|  | @ -229,7 +232,7 @@ pub async fn get_public_rooms_route( | |||
|             body: client::r0::directory::get_public_rooms_filtered::IncomingRequest { | ||||
|                 filter: None, | ||||
|                 limit, | ||||
|                 room_network: client::r0::directory::get_public_rooms_filtered::RoomNetwork::Matrix, | ||||
|                 room_network: ruma::directory::RoomNetwork::Matrix, | ||||
|                 server: None, | ||||
|                 since, | ||||
|             }, | ||||
|  | @ -268,9 +271,9 @@ pub async fn get_public_rooms_route( | |||
|     feature = "conduit_bin", | ||||
|     put("/_matrix/federation/v1/send/<_>", data = "<body>") | ||||
| )] | ||||
| pub fn send_transaction_message_route( | ||||
|     db: State<'_, Database>, | ||||
|     body: Ruma<send_transaction_message::v1::Request>, | ||||
| pub fn send_transaction_message_route<'a>( | ||||
|     _db: State<'a, Database>, | ||||
|     body: Ruma<send_transaction_message::v1::IncomingRequest>, | ||||
| ) -> ConduitResult<send_transaction_message::v1::Response> { | ||||
|     dbg!(&*body); | ||||
|     Ok(send_transaction_message::v1::Response { | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| use crate::Error; | ||||
| use argon2::{Config, Variant}; | ||||
| use cmp::Ordering; | ||||
| use rand::prelude::*; | ||||
|  | @ -90,3 +91,8 @@ pub fn common_elements( | |||
|             .all(|b| b) | ||||
|     })) | ||||
| } | ||||
| 
 | ||||
| pub fn deserialize<'de, T: serde::Deserialize<'de>>(val: &'de sled::IVec) -> Result<T, Error> { | ||||
|     serde_json::from_slice::<T>(val.as_ref()) | ||||
|         .map_err(|_| Error::bad_database("PDU in db is invalid.")) | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue