feat: notifications, simple permission systems
This commit is contained in:
		
							parent
							
								
									169dbe6c37
								
							
						
					
					
						commit
						b02c568941
					
				
					 6 changed files with 506 additions and 126 deletions
				
			
		
							
								
								
									
										93
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										93
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							|  | @ -34,7 +34,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "da71fef07bc806586090247e971229289f64c210a278ee5ae419314eb386b31d" | ||||
| dependencies = [ | ||||
|  "proc-macro2 1.0.10", | ||||
|  "quote 1.0.3", | ||||
|  "quote 1.0.4", | ||||
|  "syn 1.0.18", | ||||
| ] | ||||
| 
 | ||||
|  | @ -247,7 +247,7 @@ version = "0.3.0" | |||
| source = "git+https://github.com/SergioBenitez/Devise.git?rev=e58b3ac9a#e58b3ac9afc3b6ff10a8aaf02a3e768a8f530089" | ||||
| dependencies = [ | ||||
|  "devise_core", | ||||
|  "quote 1.0.3", | ||||
|  "quote 1.0.4", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -257,7 +257,7 @@ source = "git+https://github.com/SergioBenitez/Devise.git?rev=e58b3ac9a#e58b3ac9 | |||
| dependencies = [ | ||||
|  "bitflags", | ||||
|  "proc-macro2 1.0.10", | ||||
|  "quote 1.0.3", | ||||
|  "quote 1.0.4", | ||||
|  "syn 1.0.18", | ||||
| ] | ||||
| 
 | ||||
|  | @ -414,7 +414,7 @@ checksum = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7" | |||
| dependencies = [ | ||||
|  "proc-macro-hack", | ||||
|  "proc-macro2 1.0.10", | ||||
|  "quote 1.0.3", | ||||
|  "quote 1.0.4", | ||||
|  "syn 1.0.18", | ||||
| ] | ||||
| 
 | ||||
|  | @ -616,9 +616,9 @@ checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" | |||
| 
 | ||||
| [[package]] | ||||
| name = "js-sys" | ||||
| version = "0.3.37" | ||||
| version = "0.3.38" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055" | ||||
| checksum = "0b823ebafcee1632403f2782d28728aab353f7881547a700043ef455c078326f" | ||||
| dependencies = [ | ||||
|  "wasm-bindgen", | ||||
| ] | ||||
|  | @ -796,6 +796,12 @@ dependencies = [ | |||
|  "libc", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "once_cell" | ||||
| version = "1.3.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "openssl" | ||||
| version = "0.10.29" | ||||
|  | @ -903,7 +909,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "8988430ce790d8682672117bc06dda364c0be32d3abd738234f19f3240bad99a" | ||||
| dependencies = [ | ||||
|  "proc-macro2 1.0.10", | ||||
|  "quote 1.0.3", | ||||
|  "quote 1.0.4", | ||||
|  "syn 1.0.18", | ||||
| ] | ||||
| 
 | ||||
|  | @ -988,9 +994,9 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "quote" | ||||
| version = "1.0.3" | ||||
| version = "1.0.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" | ||||
| checksum = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7" | ||||
| dependencies = [ | ||||
|  "proc-macro2 1.0.10", | ||||
| ] | ||||
|  | @ -1117,13 +1123,13 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "ring" | ||||
| version = "0.16.12" | ||||
| version = "0.16.13" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "1ba5a8ec64ee89a76c98c549af81ff14813df09c3e6dc4766c3856da48597a0c" | ||||
| checksum = "703516ae74571f24b465b4a1431e81e2ad51336cb0ded733a55a1aa3eccac196" | ||||
| dependencies = [ | ||||
|  "cc", | ||||
|  "lazy_static", | ||||
|  "libc", | ||||
|  "once_cell", | ||||
|  "spin", | ||||
|  "untrusted", | ||||
|  "web-sys", | ||||
|  | @ -1162,7 +1168,7 @@ source = "git+https://github.com/SergioBenitez/Rocket.git?branch=async#78c8ac8cc | |||
| dependencies = [ | ||||
|  "devise", | ||||
|  "indexmap", | ||||
|  "quote 1.0.3", | ||||
|  "quote 1.0.4", | ||||
|  "rocket_http", | ||||
|  "version_check 0.9.1", | ||||
|  "yansi 0.5.0", | ||||
|  | @ -1212,14 +1218,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "0f6b02a6a860a96e3c2081c8aea88b37b2918b53e539856b73aadde1908b65ad" | ||||
| dependencies = [ | ||||
|  "proc-macro2 1.0.10", | ||||
|  "quote 1.0.3", | ||||
|  "quote 1.0.4", | ||||
|  "syn 1.0.18", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "ruma-client-api" | ||||
| version = "0.8.0-rc.5" | ||||
| source = "git+https://github.com/ruma/ruma-client-api.git#5a26c387646e17ba076e478d1e7b896b7e47137d" | ||||
| source = "git+https://github.com/ruma/ruma-client-api.git#dbb60142cf336784d809c6c4d79bd8de4c67fb5f" | ||||
| dependencies = [ | ||||
|  "http", | ||||
|  "js_int", | ||||
|  | @ -1254,14 +1260,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "abd3cfe96c9887fe2eebfa2e5e7d3a4afff02c374874d4e718f46dab5fd3320d" | ||||
| dependencies = [ | ||||
|  "proc-macro2 1.0.10", | ||||
|  "quote 1.0.3", | ||||
|  "quote 1.0.4", | ||||
|  "syn 1.0.18", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "ruma-federation-api" | ||||
| version = "0.0.1" | ||||
| source = "git+https://github.com/ruma/ruma-federation-api.git#263f2ffc75be6542bd68161e446adf588505fb56" | ||||
| source = "git+https://github.com/ruma/ruma-federation-api.git#ccbf216f39bbbaa59131cc200eae5bd18aa1947c" | ||||
| dependencies = [ | ||||
|  "js_int", | ||||
|  "ruma-api", | ||||
|  | @ -1284,13 +1290,16 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "ruma-serde" | ||||
| version = "0.1.0" | ||||
| version = "0.1.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "09901d608958f63618546957134dd4242d2ca07a885a28f794ad4574a937c22c" | ||||
| checksum = "6ce9a52acce7ed3809e1b47d9cc67ee93972a2b0fedaaa76d6e794456a79858b" | ||||
| dependencies = [ | ||||
|  "dtoa", | ||||
|  "itoa", | ||||
|  "js_int", | ||||
|  "serde", | ||||
|  "serde_json", | ||||
|  "url", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -1412,7 +1421,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c" | ||||
| dependencies = [ | ||||
|  "proc-macro2 1.0.10", | ||||
|  "quote 1.0.3", | ||||
|  "quote 1.0.4", | ||||
|  "syn 1.0.18", | ||||
| ] | ||||
| 
 | ||||
|  | @ -1506,7 +1515,7 @@ checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" | |||
| dependencies = [ | ||||
|  "heck", | ||||
|  "proc-macro2 1.0.10", | ||||
|  "quote 1.0.3", | ||||
|  "quote 1.0.4", | ||||
|  "syn 1.0.18", | ||||
| ] | ||||
| 
 | ||||
|  | @ -1528,7 +1537,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213" | ||||
| dependencies = [ | ||||
|  "proc-macro2 1.0.10", | ||||
|  "quote 1.0.3", | ||||
|  "quote 1.0.4", | ||||
|  "unicode-xid 0.2.0", | ||||
| ] | ||||
| 
 | ||||
|  | @ -1576,9 +1585,9 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "tokio" | ||||
| version = "0.2.19" | ||||
| version = "0.2.20" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7d9c43f1bb96970e153bcbae39a65e249ccb942bd9d36dbdf086024920417c9c" | ||||
| checksum = "05c1d570eb1a36f0345a5ce9c6c6e665b70b73d11236912c0b477616aeec47b1" | ||||
| dependencies = [ | ||||
|  "bytes", | ||||
|  "fnv", | ||||
|  | @ -1604,7 +1613,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389" | ||||
| dependencies = [ | ||||
|  "proc-macro2 1.0.10", | ||||
|  "quote 1.0.3", | ||||
|  "quote 1.0.4", | ||||
|  "syn 1.0.18", | ||||
| ] | ||||
| 
 | ||||
|  | @ -1764,9 +1773,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" | |||
| 
 | ||||
| [[package]] | ||||
| name = "wasm-bindgen" | ||||
| version = "0.2.60" | ||||
| version = "0.2.61" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f" | ||||
| checksum = "f56e97dbea16d5f56549d6c8ea7f36efb6be98507308650c1a5970574b3941b9" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "serde", | ||||
|  | @ -1776,24 +1785,24 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "wasm-bindgen-backend" | ||||
| version = "0.2.60" | ||||
| version = "0.2.61" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd" | ||||
| checksum = "7b75d4f3f9b81dfc7d66b955876b325b20e8affd4ce8d93e51162626fc5faadb" | ||||
| dependencies = [ | ||||
|  "bumpalo", | ||||
|  "lazy_static", | ||||
|  "log", | ||||
|  "proc-macro2 1.0.10", | ||||
|  "quote 1.0.3", | ||||
|  "quote 1.0.4", | ||||
|  "syn 1.0.18", | ||||
|  "wasm-bindgen-shared", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "wasm-bindgen-futures" | ||||
| version = "0.4.10" | ||||
| version = "0.4.11" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7add542ea1ac7fdaa9dc25e031a6af33b7d63376292bd24140c637d00d1c312a" | ||||
| checksum = "736dcd8f8455458c82614f12116aabd0209d440c1a28d8824bcaed755ac3e058" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "js-sys", | ||||
|  | @ -1803,22 +1812,22 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "wasm-bindgen-macro" | ||||
| version = "0.2.60" | ||||
| version = "0.2.61" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4" | ||||
| checksum = "9dcde4b19e863521c1e78ecf100935132396291b09ae0ae2e155ff84ccbe9736" | ||||
| dependencies = [ | ||||
|  "quote 1.0.3", | ||||
|  "quote 1.0.4", | ||||
|  "wasm-bindgen-macro-support", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "wasm-bindgen-macro-support" | ||||
| version = "0.2.60" | ||||
| version = "0.2.61" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931" | ||||
| checksum = "13d87d2b117af2b86472402d70f7eb173bbe166beb5e727f3c0bebecdf356504" | ||||
| dependencies = [ | ||||
|  "proc-macro2 1.0.10", | ||||
|  "quote 1.0.3", | ||||
|  "quote 1.0.4", | ||||
|  "syn 1.0.18", | ||||
|  "wasm-bindgen-backend", | ||||
|  "wasm-bindgen-shared", | ||||
|  | @ -1826,15 +1835,15 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "wasm-bindgen-shared" | ||||
| version = "0.2.60" | ||||
| version = "0.2.61" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639" | ||||
| checksum = "71f77b681efd0bca6f8ea356cdc2e497538b41d3e2a02afed18ce8f022231d29" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "web-sys" | ||||
| version = "0.3.37" | ||||
| version = "0.3.38" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb" | ||||
| checksum = "07c5819dc39222a788ca169a81aef7d02739019256300534f493b5747d5469c2" | ||||
| dependencies = [ | ||||
|  "js-sys", | ||||
|  "wasm-bindgen", | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ directories = "2.0.2" | |||
| js_int = "0.1.5" | ||||
| serde_json = "1.0.52" | ||||
| serde = "1.0.106" | ||||
| tokio = { version = "0.2.19", features = ["macros"] } | ||||
| tokio = { version = "0.2.20", features = ["macros"] } | ||||
| rand = "0.7.3" | ||||
| rust-argon2 = "0.8.2" | ||||
| reqwest = "0.10.4" | ||||
|  |  | |||
|  | @ -8,10 +8,12 @@ use ruma_client_api::{ | |||
|         account::register, | ||||
|         alias::get_alias, | ||||
|         capabilities::get_capabilities, | ||||
|         client_exchange::send_event_to_device, | ||||
|         config::{get_global_account_data, set_global_account_data}, | ||||
|         directory::{self, get_public_rooms_filtered}, | ||||
|         filter::{self, create_filter, get_filter}, | ||||
|         keys::{get_keys, upload_keys}, | ||||
|         media::get_media_config, | ||||
|         membership::{ | ||||
|             forget_room, get_member_events, invite_user, join_room_by_id, join_room_by_id_or_alias, | ||||
|             leave_room, | ||||
|  | @ -21,7 +23,7 @@ use ruma_client_api::{ | |||
|         profile::{ | ||||
|             get_avatar_url, get_display_name, get_profile, set_avatar_url, set_display_name, | ||||
|         }, | ||||
|         push::get_pushrules_all, | ||||
|         push::{self, get_pushrules_all, set_pushrule, set_pushrule_enabled}, | ||||
|         read_marker::set_read_marker, | ||||
|         room::create_room, | ||||
|         session::{get_login_types, login}, | ||||
|  | @ -40,7 +42,6 @@ use serde_json::json; | |||
| use std::{ | ||||
|     collections::BTreeMap, | ||||
|     convert::{TryFrom, TryInto}, | ||||
|     path::PathBuf, | ||||
|     time::{Duration, SystemTime}, | ||||
| }; | ||||
| 
 | ||||
|  | @ -238,9 +239,86 @@ pub fn get_capabilities_route( | |||
| #[get("/_matrix/client/r0/pushrules")] | ||||
| pub fn get_pushrules_all_route() -> MatrixResult<get_pushrules_all::Response> { | ||||
|     // TODO
 | ||||
|     MatrixResult(Ok(get_pushrules_all::Response { | ||||
|         global: BTreeMap::new(), | ||||
|     })) | ||||
|     let mut global = BTreeMap::new(); | ||||
|     global.insert( | ||||
|         push::RuleKind::Underride, | ||||
|         vec![push::PushRule { | ||||
|             actions: vec![ | ||||
|                 push::Action::Notify, | ||||
|                 push::Action::SetTweak { | ||||
|                     kind: push::TweakKind::Highlight, | ||||
|                     value: Some(false.into()), | ||||
|                 }, | ||||
|             ], | ||||
|             default: true, | ||||
|             enabled: true, | ||||
|             rule_id: ".m.rule.message".to_owned(), | ||||
|             conditions: Some(vec![push::PushCondition::EventMatch { | ||||
|                 key: "type".to_owned(), | ||||
|                 pattern: "m.room.message".to_owned(), | ||||
|             }]), | ||||
|             pattern: None, | ||||
|         }], | ||||
|     ); | ||||
|     MatrixResult(Ok(get_pushrules_all::Response { global })) | ||||
| } | ||||
| 
 | ||||
| #[put(
 | ||||
|     "/_matrix/client/r0/pushrules/<_scope>/<_kind>/<_rule_id>", | ||||
|     data = "<body>" | ||||
| )] | ||||
| pub fn set_pushrule_route( | ||||
|     data: State<Data>, | ||||
|     body: Ruma<set_pushrule::Request>, | ||||
|     _scope: String, | ||||
|     _kind: String, | ||||
|     _rule_id: String, | ||||
| ) -> MatrixResult<set_pushrule::Response> { | ||||
|     // TODO
 | ||||
|     let user_id = body.user_id.clone().expect("user is authenticated"); | ||||
|     data.room_userdata_update( | ||||
|         None, | ||||
|         &user_id, | ||||
|         EduEvent::PushRules(ruma_events::push_rules::PushRulesEvent { | ||||
|             content: ruma_events::push_rules::PushRulesEventContent { | ||||
|                 global: ruma_events::push_rules::Ruleset { | ||||
|                     content: vec![], | ||||
|                     override_rules: vec![], | ||||
|                     room: vec![], | ||||
|                     sender: vec![], | ||||
|                     underride: vec![ruma_events::push_rules::ConditionalPushRule { | ||||
|                         actions: vec![ | ||||
|                             ruma_events::push_rules::Action::Notify, | ||||
|                             ruma_events::push_rules::Action::SetTweak( | ||||
|                                 ruma_events::push_rules::Tweak::Highlight { value: false }, | ||||
|                             ), | ||||
|                         ], | ||||
|                         default: true, | ||||
|                         enabled: true, | ||||
|                         rule_id: ".m.rule.message".to_owned(), | ||||
|                         conditions: vec![ruma_events::push_rules::PushCondition::EventMatch( | ||||
|                             ruma_events::push_rules::EventMatchCondition { | ||||
|                                 key: "type".to_owned(), | ||||
|                                 pattern: "m.room.message".to_owned(), | ||||
|                             }, | ||||
|                         )], | ||||
|                     }], | ||||
|                 }, | ||||
|             }, | ||||
|         }), | ||||
|     ); | ||||
| 
 | ||||
|     MatrixResult(Ok(set_pushrule::Response)) | ||||
| } | ||||
| 
 | ||||
| #[put("/_matrix/client/r0/pushrules/<_scope>/<_kind>/<_rule_id>/enabled")] | ||||
| pub fn set_pushrule_enabled_route( | ||||
|     _scope: String, | ||||
|     _kind: String, | ||||
|     _rule_id: String, | ||||
| ) -> MatrixResult<set_pushrule_enabled::Response> { | ||||
|     // TODO
 | ||||
|     MatrixResult(Ok(set_pushrule_enabled::Response)) | ||||
| } | ||||
| 
 | ||||
| #[get(
 | ||||
|  | @ -284,7 +362,6 @@ pub fn set_global_account_data_route( | |||
|     _user_id: String, | ||||
|     _type: String, | ||||
| ) -> MatrixResult<set_global_account_data::Response> { | ||||
|     // TODO
 | ||||
|     MatrixResult(Ok(set_global_account_data::Response)) | ||||
| } | ||||
| 
 | ||||
|  | @ -485,8 +562,20 @@ pub fn set_read_marker_route( | |||
|     _room_id: String, | ||||
| ) -> MatrixResult<set_read_marker::Response> { | ||||
|     let user_id = body.user_id.clone().expect("user is authenticated"); | ||||
|     // TODO: Fully read
 | ||||
|     data.room_userdata_update( | ||||
|         Some(&body.room_id), | ||||
|         &user_id, | ||||
|         EduEvent::FullyRead(ruma_events::fully_read::FullyReadEvent { | ||||
|             content: ruma_events::fully_read::FullyReadEventContent { | ||||
|                 event_id: body.fully_read.clone(), | ||||
|             }, | ||||
|             room_id: Some(body.room_id.clone()), | ||||
|         }), | ||||
|     ); | ||||
| 
 | ||||
|     if let Some(event) = &body.read_receipt { | ||||
|         data.room_read_set(&body.room_id, &user_id, event); | ||||
| 
 | ||||
|         let mut user_receipts = BTreeMap::new(); | ||||
|         user_receipts.insert( | ||||
|             user_id.clone(), | ||||
|  | @ -564,6 +653,8 @@ pub fn create_room_route( | |||
|         Some("".to_owned()), | ||||
|     ); | ||||
| 
 | ||||
|     data.room_join(&room_id, &user_id); | ||||
| 
 | ||||
|     data.pdu_append( | ||||
|         room_id.clone(), | ||||
|         user_id.clone(), | ||||
|  | @ -604,8 +695,6 @@ pub fn create_room_route( | |||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     data.room_join(&room_id, &user_id); | ||||
| 
 | ||||
|     for user in &body.invite { | ||||
|         data.room_invite(&user_id, &room_id, user); | ||||
|     } | ||||
|  | @ -855,17 +944,22 @@ pub fn create_message_event_route( | |||
|     _txn_id: String, | ||||
|     body: Ruma<create_message_event::Request>, | ||||
| ) -> MatrixResult<create_message_event::Response> { | ||||
|     let user_id = body.user_id.clone().expect("user is authenticated"); | ||||
| 
 | ||||
|     let mut unsigned = serde_json::Map::new(); | ||||
|     unsigned.insert("transaction_id".to_owned(), body.txn_id.clone().into()); | ||||
| 
 | ||||
|     let event_id = data.pdu_append( | ||||
|     let event_id = data | ||||
|         .pdu_append( | ||||
|             body.room_id.clone(), | ||||
|         body.user_id.clone().expect("user is authenticated"), | ||||
|             user_id.clone(), | ||||
|             body.event_type.clone(), | ||||
|             body.json_body.clone(), | ||||
|             Some(unsigned), | ||||
|             None, | ||||
|     ); | ||||
|         ) | ||||
|         .expect("message events are always okay"); | ||||
| 
 | ||||
|     MatrixResult(Ok(create_message_event::Response { event_id })) | ||||
| } | ||||
| 
 | ||||
|  | @ -880,16 +974,21 @@ pub fn create_state_event_for_key_route( | |||
|     _state_key: String, | ||||
|     body: Ruma<create_state_event_for_key::Request>, | ||||
| ) -> MatrixResult<create_state_event_for_key::Response> { | ||||
|     let user_id = body.user_id.clone().expect("user is authenticated"); | ||||
| 
 | ||||
|     // Reponse of with/without key is the same
 | ||||
|     let event_id = data.pdu_append( | ||||
|     if let Some(event_id) = data.pdu_append( | ||||
|         body.room_id.clone(), | ||||
|         body.user_id.clone().expect("user is authenticated"), | ||||
|         body.event_type.clone(), | ||||
|         body.json_body.clone(), | ||||
|         None, | ||||
|         Some(body.state_key.clone()), | ||||
|     ); | ||||
|     ) { | ||||
|         MatrixResult(Ok(create_state_event_for_key::Response { event_id })) | ||||
|     } else { | ||||
|         panic!("TODO: error missing permissions"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[put(
 | ||||
|  | @ -902,16 +1001,21 @@ pub fn create_state_event_for_empty_key_route( | |||
|     _event_type: String, | ||||
|     body: Ruma<create_state_event_for_empty_key::Request>, | ||||
| ) -> MatrixResult<create_state_event_for_empty_key::Response> { | ||||
|     let user_id = body.user_id.clone().expect("user is authenticated"); | ||||
| 
 | ||||
|     // Reponse of with/without key is the same
 | ||||
|     let event_id = data.pdu_append( | ||||
|     if let Some(event_id) = data.pdu_append( | ||||
|         body.room_id.clone(), | ||||
|         body.user_id.clone().expect("user is authenticated"), | ||||
|         body.event_type.clone(), | ||||
|         body.json_body, | ||||
|         body.json_body.clone(), | ||||
|         None, | ||||
|         Some("".to_owned()), | ||||
|     ); | ||||
|     ) { | ||||
|         MatrixResult(Ok(create_state_event_for_empty_key::Response { event_id })) | ||||
|     } else { | ||||
|         panic!("TODO: error missing permissions"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[get("/_matrix/client/r0/sync", data = "<body>")] | ||||
|  | @ -919,7 +1023,7 @@ pub fn sync_route( | |||
|     data: State<Data>, | ||||
|     body: Ruma<sync_events::Request>, | ||||
| ) -> MatrixResult<sync_events::Response> { | ||||
|     std::thread::sleep(Duration::from_millis(300)); | ||||
|     std::thread::sleep(Duration::from_millis(1500)); | ||||
|     let user_id = body.user_id.clone().expect("user is authenticated"); | ||||
|     let next_batch = data.last_pdu_index().to_string(); | ||||
| 
 | ||||
|  | @ -932,7 +1036,7 @@ pub fn sync_route( | |||
|         .unwrap_or(0); | ||||
| 
 | ||||
|     for room_id in joined_roomids { | ||||
|         let pdus = data.pdus_since(&room_id, since); | ||||
|         let mut pdus = data.pdus_since(&room_id, since); | ||||
| 
 | ||||
|         let mut send_member_count = false; | ||||
|         let mut send_full_state = false; | ||||
|  | @ -946,6 +1050,25 @@ pub fn sync_route( | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         let notification_count = if let Some(last_read) = data.room_read_get(&room_id, &user_id) { | ||||
|             Some((data.pdus_since(&room_id, last_read).len() as u32).into()) | ||||
|         } else { | ||||
|             None | ||||
|         }; | ||||
| 
 | ||||
|         // They /sync response doesn't always return all messages, so we say the output is
 | ||||
|         // limited unless there are enough events
 | ||||
|         let mut limited = true; | ||||
|         pdus = pdus.split_off(pdus.len().checked_sub(10).unwrap_or_else(|| { | ||||
|             limited = false; | ||||
|             0 | ||||
|         })); | ||||
| 
 | ||||
|         let prev_batch = pdus | ||||
|             .first() | ||||
|             .and_then(|e| data.pdu_get_count(&e.event_id)) | ||||
|             .map(|c| c.to_string()); | ||||
| 
 | ||||
|         let room_events = pdus | ||||
|             .into_iter() | ||||
|             .map(|pdu| pdu.to_room_event()) | ||||
|  | @ -957,7 +1080,13 @@ pub fn sync_route( | |||
|         joined_rooms.insert( | ||||
|             room_id.clone().try_into().unwrap(), | ||||
|             sync_events::JoinedRoom { | ||||
|                 account_data: sync_events::AccountData { events: Vec::new() }, | ||||
|                 account_data: sync_events::AccountData { | ||||
|                     events: data | ||||
|                         .room_userdata_since(Some(&room_id), &user_id, since) | ||||
|                         .into_iter() | ||||
|                         .map(|(_, v)| v) | ||||
|                         .collect(), | ||||
|                 }, | ||||
|                 summary: sync_events::RoomSummary { | ||||
|                     heroes: Vec::new(), | ||||
|                     joined_member_count: if send_member_count { | ||||
|  | @ -973,11 +1102,11 @@ pub fn sync_route( | |||
|                 }, | ||||
|                 unread_notifications: sync_events::UnreadNotificationsCount { | ||||
|                     highlight_count: None, | ||||
|                     notification_count: None, | ||||
|                     notification_count, | ||||
|                 }, | ||||
|                 timeline: sync_events::Timeline { | ||||
|                     limited: None, | ||||
|                     prev_batch: Some(since.to_string()), | ||||
|                     limited: if limited { Some(limited) } else { None }, | ||||
|                     prev_batch, | ||||
|                     events: room_events, | ||||
|                 }, | ||||
|                 // TODO: state before timeline
 | ||||
|  | @ -1042,6 +1171,13 @@ pub fn sync_route( | |||
|             invite: invited_rooms, | ||||
|         }, | ||||
|         presence: sync_events::Presence { events: Vec::new() }, | ||||
|         account_data: sync_events::AccountData { | ||||
|             events: data | ||||
|                 .room_userdata_since(None, &user_id, since) | ||||
|                 .into_iter() | ||||
|                 .map(|(_, v)| v) | ||||
|                 .collect(), | ||||
|         }, | ||||
|         device_lists: Default::default(), | ||||
|         device_one_time_keys_count: Default::default(), | ||||
|         to_device: sync_events::ToDevice { events: Vec::new() }, | ||||
|  | @ -1059,14 +1195,23 @@ pub fn get_message_events_route( | |||
|     } | ||||
| 
 | ||||
|     if let Ok(from) = body.from.clone().parse() { | ||||
|         let pdus = data.pdus_until(&body.room_id, from); | ||||
|         let pdus = data.pdus_until( | ||||
|             &body.room_id, | ||||
|             from, | ||||
|             body.limit.map(|l| l.try_into().unwrap()).unwrap_or(10), | ||||
|         ); | ||||
|         let prev_batch = pdus | ||||
|             .last() | ||||
|             .and_then(|e| data.pdu_get_count(&e.event_id)) | ||||
|             .map(|c| c.to_string()); | ||||
|         let room_events = pdus | ||||
|             .into_iter() | ||||
|             .map(|pdu| pdu.to_room_event()) | ||||
|             .collect::<Vec<_>>(); | ||||
| 
 | ||||
|         MatrixResult(Ok(get_message_events::Response { | ||||
|             start: Some(body.from.clone()), | ||||
|             end: None, | ||||
|             end: prev_batch, | ||||
|             chunk: room_events, | ||||
|             state: Vec::new(), | ||||
|         })) | ||||
|  | @ -1099,6 +1244,23 @@ pub fn publicised_groups_route() -> MatrixResult<create_message_event::Response> | |||
|     })) | ||||
| } | ||||
| 
 | ||||
| #[put("/_matrix/client/r0/sendToDevice/<_event_type>/<_txn_id>")] | ||||
| pub fn send_event_to_device_route( | ||||
|     _event_type: String, | ||||
|     _txn_id: String, | ||||
| ) -> MatrixResult<send_event_to_device::Response> { | ||||
|     // TODO
 | ||||
|     MatrixResult(Ok(send_event_to_device::Response)) | ||||
| } | ||||
| 
 | ||||
| #[get("/_matrix/media/r0/config")] | ||||
| pub fn get_media_config_route() -> MatrixResult<get_media_config::Response> { | ||||
|     // TODO
 | ||||
|     MatrixResult(Ok(get_media_config::Response { | ||||
|         upload_size: 0_u32.into(), | ||||
|     })) | ||||
| } | ||||
| 
 | ||||
| #[options("/<_segments..>")] | ||||
| pub fn options_route( | ||||
|     _segments: rocket::http::uri::Segments, | ||||
|  |  | |||
							
								
								
									
										287
									
								
								src/data.rs
									
									
									
									
									
								
							
							
						
						
									
										287
									
								
								src/data.rs
									
									
									
									
									
								
							|  | @ -1,11 +1,15 @@ | |||
| use crate::{utils, Database, PduEvent}; | ||||
| use ruma_events::{collections::only::Event as EduEvent, EventJson, EventType}; | ||||
| use crate::{database::COUNTER, utils, Database, PduEvent}; | ||||
| use ruma_events::{ | ||||
|     collections::only::Event as EduEvent, room::power_levels::PowerLevelsEventContent, EventJson, | ||||
|     EventType, | ||||
| }; | ||||
| use ruma_federation_api::RoomV3Pdu; | ||||
| use ruma_identifiers::{EventId, RoomId, UserId}; | ||||
| use serde_json::json; | ||||
| use std::{ | ||||
|     collections::HashMap, | ||||
|     convert::{TryFrom, TryInto}, | ||||
|     mem, | ||||
| }; | ||||
| 
 | ||||
| pub struct Data { | ||||
|  | @ -189,7 +193,14 @@ impl Data { | |||
|     } | ||||
| 
 | ||||
|     pub fn room_join(&self, room_id: &RoomId, user_id: &UserId) -> bool { | ||||
|         if !self.room_exists(room_id) { | ||||
|         if !self.room_exists(room_id) | ||||
|             && !self | ||||
|                 .db | ||||
|                 .userid_joinroomids | ||||
|                 .get_iter(user_id.to_string().as_bytes()) | ||||
|                 .values() | ||||
|                 .any(|r| r.unwrap() == room_id.to_string().as_bytes()) | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|  | @ -249,8 +260,7 @@ impl Data { | |||
|     /// Check if a room exists by looking for PDUs in that room.
 | ||||
|     pub fn room_exists(&self, room_id: &RoomId) -> bool { | ||||
|         // Create the first part of the full pdu id
 | ||||
|         let mut prefix = vec![b'd']; | ||||
|         prefix.extend_from_slice(room_id.to_string().as_bytes()); | ||||
|         let mut prefix = room_id.to_string().as_bytes().to_vec(); | ||||
|         prefix.push(0xff); // Add delimiter so we don't find rooms starting with the same id
 | ||||
| 
 | ||||
|         if let Some((key, _)) = self.db.pduid_pdu.get_gt(&prefix).unwrap() { | ||||
|  | @ -397,13 +407,14 @@ impl Data { | |||
|             .collect() | ||||
|     } | ||||
| 
 | ||||
|     pub fn room_pdu_first(&self, room_id: &RoomId, pdu_index: u64) -> bool { | ||||
|         let mut pdu_id = vec![b'd']; | ||||
|         pdu_id.extend_from_slice(room_id.to_string().as_bytes()); | ||||
|         pdu_id.push(0xff); | ||||
|         pdu_id.extend_from_slice(&pdu_index.to_be_bytes()); | ||||
| 
 | ||||
|         self.db.pduid_pdu.get_lt(&pdu_id).unwrap().is_none() | ||||
|     pub fn pdu_get_count(&self, event_id: &EventId) -> Option<u64> { | ||||
|         self.db | ||||
|             .eventid_pduid | ||||
|             .get(event_id.to_string().as_bytes()) | ||||
|             .unwrap() | ||||
|             .map(|pdu_id| { | ||||
|                 utils::u64_from_bytes(&pdu_id[pdu_id.len() - mem::size_of::<u64>()..pdu_id.len()]) | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|     pub fn pdu_get(&self, event_id: &EventId) -> Option<RoomV3Pdu> { | ||||
|  | @ -459,7 +470,39 @@ impl Data { | |||
|         content: serde_json::Value, | ||||
|         unsigned: Option<serde_json::Map<String, serde_json::Value>>, | ||||
|         state_key: Option<String>, | ||||
|     ) -> EventId { | ||||
|     ) -> Option<EventId> { | ||||
|         // Is the event authorized?
 | ||||
|         if state_key.is_some() { | ||||
|             if let Some(pdu) = self | ||||
|                 .room_state(&room_id) | ||||
|                 .get(&(EventType::RoomPowerLevels, "".to_owned())) | ||||
|             { | ||||
|                 let power_levels = serde_json::from_value::<EventJson<PowerLevelsEventContent>>( | ||||
|                     pdu.content.clone(), | ||||
|                 ) | ||||
|                 .unwrap() | ||||
|                 .deserialize() | ||||
|                 .unwrap(); | ||||
| 
 | ||||
|                 match event_type { | ||||
|                     EventType::RoomMember => { | ||||
|                         // Member events are okay for now (TODO)
 | ||||
|                     } | ||||
|                     _ if power_levels | ||||
|                         .users | ||||
|                         .get(&sender) | ||||
|                         .unwrap_or(&power_levels.users_default) | ||||
|                         <= &0.into() => | ||||
|                     { | ||||
|                         // Not authorized
 | ||||
|                         return None; | ||||
|                     } | ||||
|                     // User has sufficient power
 | ||||
|                     _ => {} | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // prev_events are the leaves of the current graph. This method removes all leaves from the
 | ||||
|         // room and replaces them with our event
 | ||||
|         // TODO: Make sure this isn't called twice in parallel
 | ||||
|  | @ -523,22 +566,19 @@ impl Data { | |||
| 
 | ||||
|         self.pdu_leaves_replace(&room_id, &pdu.event_id); | ||||
| 
 | ||||
|         // The new value will need a new index. We store the last used index in 'n'
 | ||||
|         // The count will go up regardless of the room_id
 | ||||
|         // This is also the next_batch/since value
 | ||||
|         // Increment the last index and use that
 | ||||
|         let index = utils::u64_from_bytes( | ||||
|             &self | ||||
|                 .db | ||||
|                 .pduid_pdu | ||||
|                 .update_and_fetch(b"n", utils::increment) | ||||
|                 .global | ||||
|                 .update_and_fetch(COUNTER, utils::increment) | ||||
|                 .unwrap() | ||||
|                 .unwrap(), | ||||
|         ); | ||||
| 
 | ||||
|         let mut pdu_id = vec![b'd']; | ||||
|         pdu_id.extend_from_slice(room_id.to_string().as_bytes()); | ||||
| 
 | ||||
|         let mut pdu_id = room_id.to_string().as_bytes().to_vec(); | ||||
|         pdu_id.push(0xff); // Add delimiter so we don't find rooms starting with the same id
 | ||||
|         pdu_id.extend_from_slice(&index.to_be_bytes()); | ||||
| 
 | ||||
|  | @ -564,7 +604,9 @@ impl Data { | |||
|                 .unwrap(); | ||||
|         } | ||||
| 
 | ||||
|         pdu.event_id | ||||
|         self.room_read_set(&room_id, &sender, &pdu.event_id); | ||||
| 
 | ||||
|         Some(pdu.event_id) | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a vector of all PDUs in a room.
 | ||||
|  | @ -573,12 +615,11 @@ impl Data { | |||
|     } | ||||
| 
 | ||||
|     pub fn last_pdu_index(&self) -> u64 { | ||||
|         let count_key: Vec<u8> = vec![b'n']; | ||||
|         utils::u64_from_bytes( | ||||
|             &self | ||||
|                 .db | ||||
|                 .pduid_pdu | ||||
|                 .get(&count_key) | ||||
|                 .global | ||||
|                 .get(&COUNTER) | ||||
|                 .unwrap() | ||||
|                 .unwrap_or_else(|| (&0_u64.to_be_bytes()).into()), | ||||
|         ) | ||||
|  | @ -586,15 +627,23 @@ impl Data { | |||
| 
 | ||||
|     /// Returns a vector of all events in a room that happened after the event with id `since`.
 | ||||
|     pub fn pdus_since(&self, room_id: &RoomId, since: u64) -> Vec<PduEvent> { | ||||
|         // Create the first part of the full pdu id
 | ||||
|         let mut pdu_id = room_id.to_string().as_bytes().to_vec(); | ||||
|         pdu_id.push(0xff); // Add delimiter so we don't find rooms starting with the same id
 | ||||
|         pdu_id.extend_from_slice(&(since).to_be_bytes()); | ||||
| 
 | ||||
|         self.pdus_since_pduid(room_id, pdu_id) | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a vector of all events in a room that happened after the event with id `since`.
 | ||||
|     pub fn pdus_since_pduid(&self, room_id: &RoomId, pdu_id: Vec<u8>) -> Vec<PduEvent> { | ||||
|         let mut pdus = Vec::new(); | ||||
| 
 | ||||
|         // Create the first part of the full pdu id
 | ||||
|         let mut prefix = vec![b'd']; | ||||
|         prefix.extend_from_slice(room_id.to_string().as_bytes()); | ||||
|         let mut prefix = room_id.to_string().as_bytes().to_vec(); | ||||
|         prefix.push(0xff); // Add delimiter so we don't find rooms starting with the same id
 | ||||
| 
 | ||||
|         let mut current = prefix.clone(); | ||||
|         current.extend_from_slice(&since.to_be_bytes()); | ||||
|         let mut current = pdu_id; | ||||
| 
 | ||||
|         while let Some((key, value)) = self.db.pduid_pdu.get_gt(¤t).unwrap() { | ||||
|             if key.starts_with(&prefix) { | ||||
|  | @ -608,19 +657,18 @@ impl Data { | |||
|         pdus | ||||
|     } | ||||
| 
 | ||||
|     pub fn pdus_until(&self, room_id: &RoomId, until: u64) -> Vec<PduEvent> { | ||||
|     pub fn pdus_until(&self, room_id: &RoomId, until: u64, max: u32) -> Vec<PduEvent> { | ||||
|         let mut pdus = Vec::new(); | ||||
| 
 | ||||
|         // Create the first part of the full pdu id
 | ||||
|         let mut prefix = vec![b'd']; | ||||
|         prefix.extend_from_slice(room_id.to_string().as_bytes()); | ||||
|         let mut prefix = room_id.to_string().as_bytes().to_vec(); | ||||
|         prefix.push(0xff); // Add delimiter so we don't find rooms starting with the same id
 | ||||
| 
 | ||||
|         let mut current = prefix.clone(); | ||||
|         current.extend_from_slice(&until.to_be_bytes()); | ||||
| 
 | ||||
|         while let Some((key, value)) = self.db.pduid_pdu.get_lt(¤t).unwrap() { | ||||
|             if key.starts_with(&prefix) { | ||||
|             if pdus.len() < max as usize && key.starts_with(&prefix) { | ||||
|                 current = key.to_vec(); | ||||
|                 pdus.push(serde_json::from_slice(&value).expect("pdu in db is valid")); | ||||
|             } else { | ||||
|  | @ -670,8 +718,8 @@ impl Data { | |||
|         let index = utils::u64_from_bytes( | ||||
|             &self | ||||
|                 .db | ||||
|                 .pduid_pdu | ||||
|                 .update_and_fetch(b"n", utils::increment) | ||||
|                 .global | ||||
|                 .update_and_fetch(COUNTER, utils::increment) | ||||
|                 .unwrap() | ||||
|                 .unwrap(), | ||||
|         ); | ||||
|  | @ -695,17 +743,14 @@ impl Data { | |||
|         prefix.push(0xff); | ||||
| 
 | ||||
|         let mut current = prefix.clone(); | ||||
|         current.extend_from_slice(&since.to_be_bytes()); | ||||
|         current.extend_from_slice(&(since + 1).to_be_bytes()); | ||||
| 
 | ||||
|         while let Some((key, value)) = self.db.roomlatestid_roomlatest.get_gt(¤t).unwrap() { | ||||
|             if key.starts_with(&prefix) { | ||||
|                 current = key.to_vec(); | ||||
|                 room_latests.push( | ||||
|                     serde_json::from_slice::<EventJson<EduEvent>>(&value) | ||||
|                         .expect("room_latest in db is valid") | ||||
|                         .deserialize() | ||||
|                         .expect("room_latest in db is valid") | ||||
|                         .into(), | ||||
|                         .expect("room_latest in db is valid"), | ||||
|                 ); | ||||
|             } else { | ||||
|                 break; | ||||
|  | @ -715,6 +760,11 @@ impl Data { | |||
|         room_latests | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a vector of the most recent read_receipts in a room that happened after the event with id `since`.
 | ||||
|     pub fn roomlatests_all(&self, room_id: &RoomId) -> Vec<EventJson<EduEvent>> { | ||||
|         self.roomlatests_since(room_id, 0) | ||||
|     } | ||||
| 
 | ||||
|     pub fn roomactive_add(&self, event: EduEvent, room_id: &RoomId, timeout: u64) { | ||||
|         let mut prefix = room_id.to_string().as_bytes().to_vec(); | ||||
|         prefix.push(0xff); | ||||
|  | @ -737,8 +787,8 @@ impl Data { | |||
|         let index = utils::u64_from_bytes( | ||||
|             &self | ||||
|                 .db | ||||
|                 .pduid_pdu | ||||
|                 .update_and_fetch(b"n", utils::increment) | ||||
|                 .global | ||||
|                 .update_and_fetch(COUNTER, utils::increment) | ||||
|                 .unwrap() | ||||
|                 .unwrap(), | ||||
|         ); | ||||
|  | @ -790,10 +840,7 @@ impl Data { | |||
|                 current = key.to_vec(); | ||||
|                 room_actives.push( | ||||
|                     serde_json::from_slice::<EventJson<EduEvent>>(&value) | ||||
|                         .expect("room_active in db is valid") | ||||
|                         .deserialize() | ||||
|                         .expect("room_active in db is valid") | ||||
|                         .into(), | ||||
|                         .expect("room_active in db is valid"), | ||||
|                 ); | ||||
|             } else { | ||||
|                 break; | ||||
|  | @ -813,6 +860,158 @@ impl Data { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn room_userdata_update( | ||||
|         &self, | ||||
|         room_id: Option<&RoomId>, | ||||
|         user_id: &UserId, | ||||
|         event: EduEvent, | ||||
|     ) { | ||||
|         let mut prefix = room_id | ||||
|             .map(|r| r.to_string()) | ||||
|             .unwrap_or_default() | ||||
|             .as_bytes() | ||||
|             .to_vec(); | ||||
|         prefix.push(0xff); | ||||
|         prefix.extend_from_slice(&user_id.to_string().as_bytes()); | ||||
|         prefix.push(0xff); | ||||
| 
 | ||||
|         // Start with last
 | ||||
|         if let Some(mut current) = self | ||||
|             .db | ||||
|             .roomuserdataid_accountdata | ||||
|             .scan_prefix(&prefix) | ||||
|             .keys() | ||||
|             .next_back() | ||||
|             .map(|c| c.unwrap()) | ||||
|         { | ||||
|             // Remove old entry (there should be at most one)
 | ||||
|             loop { | ||||
|                 if !current.starts_with(&prefix) { | ||||
|                     // We're in another room or user
 | ||||
|                     break; | ||||
|                 } | ||||
|                 if current.rsplit(|&b| b == 0xff).nth(2).unwrap() == user_id.to_string().as_bytes() | ||||
|                 { | ||||
|                     // This is the old room_latest
 | ||||
|                     self.db.roomuserdataid_accountdata.remove(current).unwrap(); | ||||
|                     break; | ||||
|                 } | ||||
|                 // Else, try the event before that
 | ||||
|                 if let Some((k, _)) = self.db.roomuserdataid_accountdata.get_lt(current).unwrap() { | ||||
|                     current = k; | ||||
|                 } else { | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Increment the last index and use that
 | ||||
|         let index = utils::u64_from_bytes( | ||||
|             &self | ||||
|                 .db | ||||
|                 .global | ||||
|                 .update_and_fetch(COUNTER, utils::increment) | ||||
|                 .unwrap() | ||||
|                 .unwrap(), | ||||
|         ); | ||||
| 
 | ||||
|         let mut key = prefix; | ||||
|         key.extend_from_slice(&index.to_be_bytes()); | ||||
| 
 | ||||
|         let json = serde_json::to_value(&event).unwrap(); | ||||
|         key.extend_from_slice(json["type"].as_str().unwrap().as_bytes()); | ||||
| 
 | ||||
|         self.db | ||||
|             .roomuserdataid_accountdata | ||||
|             .insert(key, &*json.to_string()) | ||||
|             .unwrap(); | ||||
|     } | ||||
| 
 | ||||
|     pub fn room_userdata_get( | ||||
|         &self, | ||||
|         room_id: Option<&RoomId>, | ||||
|         user_id: &UserId, | ||||
|         kind: &str, | ||||
|     ) -> Option<EventJson<EduEvent>> { | ||||
|         self.room_userdata_all(room_id, user_id).remove(kind) | ||||
|     } | ||||
| 
 | ||||
|     pub fn room_userdata_since( | ||||
|         &self, | ||||
|         room_id: Option<&RoomId>, | ||||
|         user_id: &UserId, | ||||
|         since: u64, | ||||
|     ) -> HashMap<String, EventJson<EduEvent>> { | ||||
|         let mut userdata = HashMap::new(); | ||||
| 
 | ||||
|         let mut prefix = room_id | ||||
|             .map(|r| r.to_string()) | ||||
|             .unwrap_or_default() | ||||
|             .as_bytes() | ||||
|             .to_vec(); | ||||
|         prefix.push(0xff); | ||||
|         prefix.extend_from_slice(&user_id.to_string().as_bytes()); | ||||
|         prefix.push(0xff); | ||||
| 
 | ||||
|         let mut current = prefix.clone(); | ||||
|         current.extend_from_slice(&(since + 1).to_be_bytes()); | ||||
| 
 | ||||
|         while let Some((key, value)) = self.db.roomuserdataid_accountdata.get_gt(¤t).unwrap() | ||||
|         { | ||||
|             if key.starts_with(&prefix) { | ||||
|                 current = key.to_vec(); | ||||
|                 let json = serde_json::from_slice::<serde_json::Value>(&value).unwrap(); | ||||
|                 userdata.insert( | ||||
|                     json["type"].as_str().unwrap().to_owned(), | ||||
|                     serde_json::from_value::<EventJson<EduEvent>>(json) | ||||
|                         .expect("userdata in db is valid"), | ||||
|                 ); | ||||
|             } else { | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         userdata | ||||
|     } | ||||
| 
 | ||||
|     pub fn room_userdata_all( | ||||
|         &self, | ||||
|         room_id: Option<&RoomId>, | ||||
|         user_id: &UserId, | ||||
|     ) -> HashMap<String, EventJson<EduEvent>> { | ||||
|         self.room_userdata_since(room_id, user_id, 0) | ||||
|     } | ||||
| 
 | ||||
|     pub fn room_read_set( | ||||
|         &self, | ||||
|         room_id: &RoomId, | ||||
|         user_id: &UserId, | ||||
|         event_id: &EventId, | ||||
|     ) -> Option<()> { | ||||
|         let mut key = room_id.to_string().as_bytes().to_vec(); | ||||
|         key.push(0xff); | ||||
|         key.extend_from_slice(&user_id.to_string().as_bytes()); | ||||
| 
 | ||||
|         self.db | ||||
|             .roomuserid_lastread | ||||
|             .insert(key, &self.pdu_get_count(event_id)?.to_be_bytes()) | ||||
|             .unwrap(); | ||||
| 
 | ||||
|         Some(()) | ||||
|     } | ||||
| 
 | ||||
|     pub fn room_read_get(&self, room_id: &RoomId, user_id: &UserId) -> Option<u64> { | ||||
|         let mut key = room_id.to_string().as_bytes().to_vec(); | ||||
|         key.push(0xff); | ||||
|         key.extend_from_slice(&user_id.to_string().as_bytes()); | ||||
| 
 | ||||
|         self.db | ||||
|             .roomuserid_lastread | ||||
|             .get(key) | ||||
|             .unwrap() | ||||
|             .map(|v| utils::u64_from_bytes(&v)) | ||||
|     } | ||||
| 
 | ||||
|     pub fn debug(&self) { | ||||
|         self.db.debug(); | ||||
|     } | ||||
|  |  | |||
|  | @ -5,6 +5,8 @@ use std::fs::remove_dir_all; | |||
| 
 | ||||
| pub struct MultiValue(sled::Tree); | ||||
| 
 | ||||
| pub const COUNTER: &str = "c"; | ||||
| 
 | ||||
| impl MultiValue { | ||||
|     /// Get an iterator over all values.
 | ||||
|     pub fn iter_all(&self) -> sled::Iter { | ||||
|  | @ -67,22 +69,24 @@ pub struct Database { | |||
|     pub userid_deviceids: MultiValue, | ||||
|     pub userdeviceid_token: sled::Tree, | ||||
|     pub token_userid: sled::Tree, | ||||
|     pub pduid_pdu: sled::Tree, // PduId = 'd' + RoomId + Since (global since counter is at 'n')
 | ||||
|     pub pduid_pdu: sled::Tree, // PduId = RoomId + Count
 | ||||
|     pub eventid_pduid: sled::Tree, | ||||
|     pub roomid_pduleaves: MultiValue, | ||||
|     pub roomstateid_pdu: sled::Tree, // Room + StateType + StateKey
 | ||||
|     pub roomuserdataid_accountdata: sled::Tree, // RoomUserDataId = Room + User + Count + Type
 | ||||
|     pub roomuserid_lastread: sled::Tree, // RoomUserId = Room + User
 | ||||
|     pub roomid_joinuserids: MultiValue, | ||||
|     pub roomid_inviteuserids: MultiValue, | ||||
|     pub userid_joinroomids: MultiValue, | ||||
|     pub userid_inviteroomids: MultiValue, | ||||
|     pub userid_leftroomids: MultiValue, | ||||
|     // EDUs:
 | ||||
|     pub roomlatestid_roomlatest: sled::Tree, // Read Receipts, RoomLatestId = RoomId + Since + UserId TODO: Types
 | ||||
|     pub roomactiveid_roomactive: sled::Tree, // Typing, RoomActiveId = TimeoutTime + Since
 | ||||
|     pub globalallid_globalall: sled::Tree,   // ToDevice, GlobalAllId = UserId + Since
 | ||||
|     pub globallatestid_globallatest: sled::Tree, // Presence, GlobalLatestId = Since + Type + UserId
 | ||||
|     pub roomlatestid_roomlatest: sled::Tree, // Read Receipts, RoomLatestId = RoomId + Count + UserId TODO: Types
 | ||||
|     pub roomactiveid_roomactive: sled::Tree, // Typing, RoomActiveId = TimeoutTime + Count
 | ||||
|     pub globalallid_globalall: sled::Tree,   // ToDevice, GlobalAllId = UserId + Count
 | ||||
|     pub globallatestid_globallatest: sled::Tree, // Presence, GlobalLatestId = Count + Type + UserId
 | ||||
|     pub keypair: ruma_signatures::Ed25519KeyPair, | ||||
|     _db: sled::Db, | ||||
|     pub global: sled::Db, | ||||
| } | ||||
| 
 | ||||
| impl Database { | ||||
|  | @ -116,6 +120,8 @@ impl Database { | |||
|             eventid_pduid: db.open_tree("eventid_pduid").unwrap(), | ||||
|             roomid_pduleaves: MultiValue(db.open_tree("roomid_pduleaves").unwrap()), | ||||
|             roomstateid_pdu: db.open_tree("roomstateid_pdu").unwrap(), | ||||
|             roomuserdataid_accountdata: db.open_tree("roomuserdataid_accountdata").unwrap(), | ||||
|             roomuserid_lastread: db.open_tree("roomuserid_lastread").unwrap(), | ||||
|             roomid_joinuserids: MultiValue(db.open_tree("roomid_joinuserids").unwrap()), | ||||
|             roomid_inviteuserids: MultiValue(db.open_tree("roomid_inviteuserids").unwrap()), | ||||
|             userid_joinroomids: MultiValue(db.open_tree("userid_joinroomids").unwrap()), | ||||
|  | @ -132,7 +138,7 @@ impl Database { | |||
|                 "key1".to_owned(), | ||||
|             ) | ||||
|             .unwrap(), | ||||
|             _db: db, | ||||
|             global: db, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -29,6 +29,8 @@ fn setup_rocket() -> rocket::Rocket { | |||
|                 client_server::login_route, | ||||
|                 client_server::get_capabilities_route, | ||||
|                 client_server::get_pushrules_all_route, | ||||
|                 client_server::set_pushrule_route, | ||||
|                 client_server::set_pushrule_enabled_route, | ||||
|                 client_server::get_filter_route, | ||||
|                 client_server::create_filter_route, | ||||
|                 client_server::set_global_account_data_route, | ||||
|  | @ -61,6 +63,8 @@ fn setup_rocket() -> rocket::Rocket { | |||
|                 client_server::get_message_events_route, | ||||
|                 client_server::turn_server_route, | ||||
|                 client_server::publicised_groups_route, | ||||
|                 client_server::send_event_to_device_route, | ||||
|                 client_server::get_media_config_route, | ||||
|                 client_server::options_route, | ||||
|                 server_server::well_known_server, | ||||
|                 server_server::get_server_version, | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue