Merge pull request 'Small fixes' (#98) from fix into master

merge-requests/22/head
Timo Kösters 4 years ago
commit c655870d23

92
Cargo.lock generated

@ -26,13 +26,13 @@ checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.31" version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26c4f3195085c36ea8d24d32b2f828d23296a9370a28aa39d111f6f16bef9f3b" checksum = "0eb7f9ad01405feb3c1dac82463038945cf88eea4569acaf3ad662233496dd96"
dependencies = [ dependencies = [
"proc-macro2 1.0.17", "proc-macro2 1.0.18",
"quote 1.0.6", "quote 1.0.6",
"syn 1.0.29", "syn 1.0.30",
] ]
[[package]] [[package]]
@ -98,9 +98,9 @@ dependencies = [
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.3.0" version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5356f1d23ee24a1f785a56d1d1a5f0fd5b0f6a0c0fb2412ce11da71649ab78f6" checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
@ -277,9 +277,9 @@ version = "0.3.0"
source = "git+https://github.com/SergioBenitez/Devise.git?rev=e58b3ac9a#e58b3ac9afc3b6ff10a8aaf02a3e768a8f530089" source = "git+https://github.com/SergioBenitez/Devise.git?rev=e58b3ac9a#e58b3ac9afc3b6ff10a8aaf02a3e768a8f530089"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"proc-macro2 1.0.17", "proc-macro2 1.0.18",
"quote 1.0.6", "quote 1.0.6",
"syn 1.0.29", "syn 1.0.30",
] ]
[[package]] [[package]]
@ -421,9 +421,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39" checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39"
dependencies = [ dependencies = [
"proc-macro-hack", "proc-macro-hack",
"proc-macro2 1.0.17", "proc-macro2 1.0.18",
"quote 1.0.6", "quote 1.0.6",
"syn 1.0.29", "syn 1.0.30",
] ]
[[package]] [[package]]
@ -621,9 +621,9 @@ dependencies = [
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.3.2" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" checksum = "c398b2b113b55809ceb9ee3e753fcbac793f1956663f3c36549c1346015c2afe"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
@ -1002,16 +1002,16 @@ version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e58db2081ba5b4c93bd6be09c40fd36cb9193a8336c384f3b40012e531aa7e40" checksum = "e58db2081ba5b4c93bd6be09c40fd36cb9193a8336c384f3b40012e531aa7e40"
dependencies = [ dependencies = [
"proc-macro2 1.0.17", "proc-macro2 1.0.18",
"quote 1.0.6", "quote 1.0.6",
"syn 1.0.29", "syn 1.0.30",
] ]
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.1.5" version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7505eeebd78492e0f6108f7171c4948dbb120ee8119d9d77d0afa5469bef67f" checksum = "9df32da11d84f3a7d70205549562966279adb900e080fad3dccd8e64afccf0ad"
[[package]] [[package]]
name = "pin-utils" name = "pin-utils"
@ -1027,9 +1027,9 @@ checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
[[package]] [[package]]
name = "png" name = "png"
version = "0.16.3" version = "0.16.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c68a431ed29933a4eb5709aca9800989758c97759345860fa5db3cfced0b65d" checksum = "12faa637ed9ae3d3c881332e54b5ae2dba81cda9fc4bbce0faa1ba53abcead50"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"crc32fast", "crc32fast",
@ -1066,9 +1066,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.17" version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101" checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa"
dependencies = [ dependencies = [
"unicode-xid 0.2.0", "unicode-xid 0.2.0",
] ]
@ -1088,7 +1088,7 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea" checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
dependencies = [ dependencies = [
"proc-macro2 1.0.17", "proc-macro2 1.0.18",
] ]
[[package]] [[package]]
@ -1289,9 +1289,9 @@ version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52b82b4567b9af9b40a86f7778821c016ea961f55e4fee255f8f24bb28ee7452" checksum = "52b82b4567b9af9b40a86f7778821c016ea961f55e4fee255f8f24bb28ee7452"
dependencies = [ dependencies = [
"proc-macro2 1.0.17", "proc-macro2 1.0.18",
"quote 1.0.6", "quote 1.0.6",
"syn 1.0.29", "syn 1.0.30",
] ]
[[package]] [[package]]
@ -1343,9 +1343,9 @@ name = "ruma-events-macros"
version = "0.21.3" version = "0.21.3"
source = "git+https://github.com/ruma/ruma-events.git?rev=4d09416cd1663d63c22153705c9e1fd77910797f#4d09416cd1663d63c22153705c9e1fd77910797f" source = "git+https://github.com/ruma/ruma-events.git?rev=4d09416cd1663d63c22153705c9e1fd77910797f#4d09416cd1663d63c22153705c9e1fd77910797f"
dependencies = [ dependencies = [
"proc-macro2 1.0.17", "proc-macro2 1.0.18",
"quote 1.0.6", "quote 1.0.6",
"syn 1.0.29", "syn 1.0.30",
] ]
[[package]] [[package]]
@ -1365,9 +1365,9 @@ dependencies = [
[[package]] [[package]]
name = "ruma-identifiers" name = "ruma-identifiers"
version = "0.16.1" version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77c93b9d5f951a2fb57b19c048a05ac1dbdb280ff7617ec6b02f54bf14318ed8" checksum = "6316cb248e3e0323a5a269b8eaed571404fb4f65c81848549e9ba99fd9b8e9de"
dependencies = [ dependencies = [
"rand", "rand",
"serde", "serde",
@ -1437,9 +1437,9 @@ dependencies = [
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.4" version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]] [[package]]
name = "schannel" name = "schannel"
@ -1505,9 +1505,9 @@ version = "1.0.111"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250" checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250"
dependencies = [ dependencies = [
"proc-macro2 1.0.17", "proc-macro2 1.0.18",
"quote 1.0.6", "quote 1.0.6",
"syn 1.0.29", "syn 1.0.30",
] ]
[[package]] [[package]]
@ -1611,9 +1611,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2 1.0.17", "proc-macro2 1.0.18",
"quote 1.0.6", "quote 1.0.6",
"syn 1.0.29", "syn 1.0.30",
] ]
[[package]] [[package]]
@ -1629,11 +1629,11 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.29" version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb37da98a55b1d08529362d9cbb863be17556873df2585904ab9d2bc951291d0" checksum = "93a56fabc59dce20fe48b6c832cc249c713e7ed88fa28b0ee0a3bfcaae5fe4e2"
dependencies = [ dependencies = [
"proc-macro2 1.0.17", "proc-macro2 1.0.18",
"quote 1.0.6", "quote 1.0.6",
"unicode-xid 0.2.0", "unicode-xid 0.2.0",
] ]
@ -1667,9 +1667,9 @@ version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "893582086c2f98cde18f906265a65b5030a074b1046c674ae898be6519a7f479" checksum = "893582086c2f98cde18f906265a65b5030a074b1046c674ae898be6519a7f479"
dependencies = [ dependencies = [
"proc-macro2 1.0.17", "proc-macro2 1.0.18",
"quote 1.0.6", "quote 1.0.6",
"syn 1.0.29", "syn 1.0.30",
] ]
[[package]] [[package]]
@ -1711,9 +1711,9 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389" checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389"
dependencies = [ dependencies = [
"proc-macro2 1.0.17", "proc-macro2 1.0.18",
"quote 1.0.6", "quote 1.0.6",
"syn 1.0.29", "syn 1.0.30",
] ]
[[package]] [[package]]
@ -1837,9 +1837,9 @@ dependencies = [
[[package]] [[package]]
name = "vcpkg" name = "vcpkg"
version = "0.2.8" version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" checksum = "55d1e41d56121e07f1e223db0a4def204e45c85425f6a16d462fd07c8d10d74c"
[[package]] [[package]]
name = "version_check" name = "version_check"
@ -1890,9 +1890,9 @@ dependencies = [
"bumpalo", "bumpalo",
"lazy_static", "lazy_static",
"log", "log",
"proc-macro2 1.0.17", "proc-macro2 1.0.18",
"quote 1.0.6", "quote 1.0.6",
"syn 1.0.29", "syn 1.0.30",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -1924,9 +1924,9 @@ version = "0.2.63"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3156052d8ec77142051a533cdd686cba889537b213f948cd1d20869926e68e92" checksum = "3156052d8ec77142051a533cdd686cba889537b213f948cd1d20869926e68e92"
dependencies = [ dependencies = [
"proc-macro2 1.0.17", "proc-macro2 1.0.18",
"quote 1.0.6", "quote 1.0.6",
"syn 1.0.29", "syn 1.0.30",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]

@ -15,7 +15,7 @@ edition = "2018"
rocket = { git = "https://github.com/SergioBenitez/Rocket.git", branch = "async", features = ["tls"] } rocket = { git = "https://github.com/SergioBenitez/Rocket.git", branch = "async", features = ["tls"] }
http = "0.2.1" http = "0.2.1"
ruma-client-api = { git = "https://github.com/ruma/ruma-client-api.git", rev = "c725288cd099690c1d13f1a9b9e57228bc860a62" } ruma-client-api = { git = "https://github.com/ruma/ruma-client-api.git", rev = "c725288cd099690c1d13f1a9b9e57228bc860a62" }
ruma-identifiers = { version = "0.16.1", features = ["rand"] } ruma-identifiers = { version = "0.16.2", features = ["rand"] }
ruma-api = "0.16.1" ruma-api = "0.16.1"
ruma-events = { git = "https://github.com/ruma/ruma-events.git", rev = "4d09416cd1663d63c22153705c9e1fd77910797f" } ruma-events = { git = "https://github.com/ruma/ruma-events.git", rev = "4d09416cd1663d63c22153705c9e1fd77910797f" }
ruma-signatures = { git = "https://github.com/ruma/ruma-signatures.git", rev = "1ca545cba8dfd43e0fc8e3c18e1311fb73390a97" } ruma-signatures = { git = "https://github.com/ruma/ruma-signatures.git", rev = "1ca545cba8dfd43e0fc8e3c18e1311fb73390a97" }

@ -4,6 +4,7 @@ use std::{
time::{Duration, SystemTime}, time::{Duration, SystemTime},
}; };
use crate::{utils, Database, MatrixResult, Ruma};
use log::{debug, warn}; use log::{debug, warn};
use rocket::{delete, get, options, post, put, State}; use rocket::{delete, get, options, post, put, State};
use ruma_client_api::{ use ruma_client_api::{
@ -13,15 +14,13 @@ use ruma_client_api::{
alias::{create_alias, delete_alias, get_alias}, alias::{create_alias, delete_alias, get_alias},
capabilities::get_capabilities, capabilities::get_capabilities,
config::{get_global_account_data, set_global_account_data}, config::{get_global_account_data, set_global_account_data},
device::{ device::{self, delete_device, delete_devices, get_device, get_devices, update_device},
self, delete_device, delete_devices, get_device, get_devices, update_device,
},
directory::{ directory::{
self, get_public_rooms, get_public_rooms_filtered, get_room_visibility, self, get_public_rooms, get_public_rooms_filtered, get_room_visibility,
set_room_visibility, set_room_visibility,
}, },
filter::{self, create_filter, get_filter}, filter::{self, create_filter, get_filter},
keys::{claim_keys, get_keys, upload_keys}, keys::{self, claim_keys, get_keys, upload_keys},
media::{create_content, get_content, get_content_thumbnail, get_media_config}, media::{create_content, get_content, get_content_thumbnail, get_media_config},
membership::{ membership::{
forget_room, get_member_events, invite_user, join_room_by_id, join_room_by_id_or_alias, forget_room, get_member_events, invite_user, join_room_by_id, join_room_by_id_or_alias,
@ -58,8 +57,6 @@ use ruma_events::{
use ruma_identifiers::{DeviceId, RoomAliasId, RoomId, RoomVersionId, UserId}; use ruma_identifiers::{DeviceId, RoomAliasId, RoomId, RoomVersionId, UserId};
use serde_json::{json, value::RawValue}; use serde_json::{json, value::RawValue};
use crate::{server_server, utils, Database, MatrixResult, Ruma};
const GUEST_NAME_LENGTH: usize = 10; const GUEST_NAME_LENGTH: usize = 10;
const DEVICE_ID_LENGTH: usize = 10; const DEVICE_ID_LENGTH: usize = 10;
const SESSION_ID_LENGTH: usize = 256; const SESSION_ID_LENGTH: usize = 256;
@ -176,7 +173,8 @@ pub fn register_route(
// Generate new device id if the user didn't specify one // Generate new device id if the user didn't specify one
let device_id = body let device_id = body
.device_id.clone() .device_id
.clone()
.unwrap_or_else(|| utils::random_string(DEVICE_ID_LENGTH)); .unwrap_or_else(|| utils::random_string(DEVICE_ID_LENGTH));
// Generate new token for the device // Generate new token for the device
@ -184,7 +182,12 @@ pub fn register_route(
// Add device // Add device
db.users db.users
.create_device(&user_id, &device_id, &token, body.initial_device_display_name.clone()) .create_device(
&user_id,
&device_id,
&token,
body.initial_device_display_name.clone(),
)
.unwrap(); .unwrap();
// Initial data // Initial data
@ -311,7 +314,12 @@ pub fn login_route(
// Add device // Add device
db.users db.users
.create_device(&user_id, &device_id, &token, body.initial_device_display_name.clone()) .create_device(
&user_id,
&device_id,
&token,
body.initial_device_display_name.clone(),
)
.unwrap(); .unwrap();
MatrixResult(Ok(login::Response { MatrixResult(Ok(login::Response {
@ -338,14 +346,23 @@ pub fn logout_route(
#[get("/_matrix/client/r0/capabilities")] #[get("/_matrix/client/r0/capabilities")]
pub fn get_capabilities_route() -> MatrixResult<get_capabilities::Response> { pub fn get_capabilities_route() -> MatrixResult<get_capabilities::Response> {
// TODO let mut available = BTreeMap::new();
//let mut available = BTreeMap::new(); available.insert(
//available.insert("5".to_owned(), get_capabilities::RoomVersionStability::Unstable); "5".to_owned(),
get_capabilities::RoomVersionStability::Stable,
);
available.insert(
"6".to_owned(),
get_capabilities::RoomVersionStability::Stable,
);
MatrixResult(Ok(get_capabilities::Response { MatrixResult(Ok(get_capabilities::Response {
capabilities: get_capabilities::Capabilities { capabilities: get_capabilities::Capabilities {
change_password: None, change_password: None, // None means it is possible
room_versions: None, //Some(get_capabilities::RoomVersionsCapability { default: "5".to_owned(), available }), room_versions: Some(get_capabilities::RoomVersionsCapability {
default: "6".to_owned(),
available,
}),
custom_capabilities: BTreeMap::new(), custom_capabilities: BTreeMap::new(),
}, },
})) }))
@ -749,11 +766,21 @@ pub fn get_keys_route(
for (user_id, device_ids) in &body.device_keys { for (user_id, device_ids) in &body.device_keys {
if device_ids.is_empty() { if device_ids.is_empty() {
let mut container = BTreeMap::new(); let mut container = BTreeMap::new();
for (device_id, keys) in db for (device_id, mut keys) in db
.users .users
.all_device_keys(&user_id.clone()) .all_device_keys(&user_id.clone())
.map(|r| r.unwrap()) .map(|r| r.unwrap())
{ {
let metadata = db
.users
.get_device_metadata(user_id, &device_id)
.unwrap()
.expect("this device should exist");
keys.unsigned = Some(keys::UnsignedDeviceInfo {
device_display_name: metadata.display_name,
});
container.insert(device_id, keys); container.insert(device_id, keys);
} }
device_keys.insert(user_id.clone(), container); device_keys.insert(user_id.clone(), container);
@ -761,7 +788,18 @@ pub fn get_keys_route(
for device_id in device_ids { for device_id in device_ids {
let mut container = BTreeMap::new(); let mut container = BTreeMap::new();
for keys in db.users.get_device_keys(&user_id.clone(), &device_id) { for keys in db.users.get_device_keys(&user_id.clone(), &device_id) {
container.insert(device_id.clone(), keys.unwrap()); let mut keys = keys.unwrap();
let metadata = db
.users
.get_device_metadata(user_id, &device_id)
.unwrap()
.expect("this device should exist");
keys.unsigned = Some(keys::UnsignedDeviceInfo {
device_display_name: metadata.display_name,
});
container.insert(device_id.clone(), keys);
} }
device_keys.insert(user_id.clone(), container); device_keys.insert(user_id.clone(), container);
} }
@ -883,18 +921,12 @@ pub fn create_typing_event_route(
_user_id: String, _user_id: String,
) -> MatrixResult<create_typing_event::Response> { ) -> MatrixResult<create_typing_event::Response> {
let user_id = body.user_id.as_ref().expect("user is authenticated"); let user_id = body.user_id.as_ref().expect("user is authenticated");
let edu = EduEvent::Typing(ruma_events::typing::TypingEvent {
content: ruma_events::typing::TypingEventContent {
user_ids: vec![user_id.clone()],
},
room_id: None, // None because it can be inferred
});
if body.typing { if body.typing {
db.rooms db.rooms
.edus .edus
.roomactive_add( .roomactive_add(
edu, &user_id,
&body.room_id, &body.room_id,
body.timeout.map(|d| d.as_millis() as u64).unwrap_or(30000) body.timeout.map(|d| d.as_millis() as u64).unwrap_or(30000)
+ utils::millis_since_unix_epoch().try_into().unwrap_or(0), + utils::millis_since_unix_epoch().try_into().unwrap_or(0),
@ -902,7 +934,10 @@ pub fn create_typing_event_route(
) )
.unwrap(); .unwrap();
} else { } else {
db.rooms.edus.roomactive_remove(edu, &body.room_id).unwrap(); db.rooms
.edus
.roomactive_remove(&user_id, &body.room_id, &db.globals)
.unwrap();
} }
MatrixResult(Ok(create_typing_event::Response)) MatrixResult(Ok(create_typing_event::Response))
@ -954,7 +989,7 @@ pub fn create_room_route(
.creation_content .creation_content
.as_ref() .as_ref()
.and_then(|c| c.predecessor.clone()), .and_then(|c| c.predecessor.clone()),
room_version: RoomVersionId::version_5(), room_version: RoomVersionId::version_6(),
}) })
.unwrap(), .unwrap(),
None, None,
@ -1279,11 +1314,11 @@ pub fn get_alias_route(
})) }))
} else { } else {
debug!("Room alias not found."); debug!("Room alias not found.");
return MatrixResult(Err(Error { MatrixResult(Err(Error {
kind: ErrorKind::NotFound, kind: ErrorKind::NotFound,
message: "Room with alias not found.".to_owned(), message: "Room with alias not found.".to_owned(),
status_code: http::StatusCode::BAD_REQUEST, status_code: http::StatusCode::BAD_REQUEST,
})); }))
} }
} else { } else {
todo!("ask remote server"); todo!("ask remote server");
@ -1859,23 +1894,23 @@ pub fn get_state_events_route(
) -> MatrixResult<get_state_events::Response> { ) -> MatrixResult<get_state_events::Response> {
let user_id = body.user_id.as_ref().expect("user is authenticated"); let user_id = body.user_id.as_ref().expect("user is authenticated");
if db.rooms.is_joined(user_id, &body.room_id).unwrap() { if !db.rooms.is_joined(user_id, &body.room_id).unwrap() {
MatrixResult(Ok(get_state_events::Response { return MatrixResult(Err(Error {
room_state: db
.rooms
.room_state(&body.room_id)
.unwrap()
.values()
.map(|pdu| pdu.to_state_event())
.collect(),
}))
} else {
MatrixResult(Err(Error {
kind: ErrorKind::Forbidden, kind: ErrorKind::Forbidden,
message: "You don't have permission to view the room state.".to_owned(), message: "You don't have permission to view the room state.".to_owned(),
status_code: http::StatusCode::BAD_REQUEST, status_code: http::StatusCode::FORBIDDEN,
})) }));
} }
MatrixResult(Ok(get_state_events::Response {
room_state: db
.rooms
.room_state(&body.room_id)
.unwrap()
.values()
.map(|pdu| pdu.to_state_event())
.collect(),
}))
} }
#[get( #[get(
@ -1891,28 +1926,28 @@ pub fn get_state_events_for_key_route(
) -> MatrixResult<get_state_events_for_key::Response> { ) -> MatrixResult<get_state_events_for_key::Response> {
let user_id = body.user_id.as_ref().expect("user is authenticated"); let user_id = body.user_id.as_ref().expect("user is authenticated");
if db.rooms.is_joined(user_id, &body.room_id).unwrap() { if !db.rooms.is_joined(user_id, &body.room_id).unwrap() {
if let Some(event) = db return MatrixResult(Err(Error {
.rooms
.room_state(&body.room_id)
.unwrap()
.get(&(body.event_type.clone(), body.state_key.clone()))
{
MatrixResult(Ok(get_state_events_for_key::Response {
content: serde_json::value::to_raw_value(&event.content).unwrap(),
}))
} else {
MatrixResult(Err(Error {
kind: ErrorKind::NotFound,
message: "State event not found.".to_owned(),
status_code: http::StatusCode::BAD_REQUEST,
}))
}
} else {
MatrixResult(Err(Error {
kind: ErrorKind::Forbidden, kind: ErrorKind::Forbidden,
message: "You don't have permission to view the room state.".to_owned(), message: "You don't have permission to view the room state.".to_owned(),
status_code: http::StatusCode::BAD_REQUEST, status_code: http::StatusCode::FORBIDDEN,
}));
}
if let Some(event) = db
.rooms
.room_state(&body.room_id)
.unwrap()
.get(&(body.event_type.clone(), body.state_key.clone()))
{
MatrixResult(Ok(get_state_events_for_key::Response {
content: serde_json::value::to_raw_value(&event.content).unwrap(),
}))
} else {
MatrixResult(Err(Error {
kind: ErrorKind::NotFound,
message: "State event not found.".to_owned(),
status_code: http::StatusCode::NOT_FOUND,
})) }))
} }
} }
@ -1929,27 +1964,27 @@ pub fn get_state_events_for_empty_key_route(
) -> MatrixResult<get_state_events_for_key::Response> { ) -> MatrixResult<get_state_events_for_key::Response> {
let user_id = body.user_id.as_ref().expect("user is authenticated"); let user_id = body.user_id.as_ref().expect("user is authenticated");
if db.rooms.is_joined(user_id, &body.room_id).unwrap() { if !db.rooms.is_joined(user_id, &body.room_id).unwrap() {
if let Some(event) = db return MatrixResult(Err(Error {
.rooms
.room_state(&body.room_id)
.unwrap()
.get(&(body.event_type.clone(), "".to_owned()))
{
MatrixResult(Ok(get_state_events_for_key::Response {
content: serde_json::value::to_raw_value(event).unwrap(),
}))
} else {
MatrixResult(Err(Error {
kind: ErrorKind::NotFound,
message: "State event not found.".to_owned(),
status_code: http::StatusCode::BAD_REQUEST,
}))
}
} else {
MatrixResult(Err(Error {
kind: ErrorKind::Forbidden, kind: ErrorKind::Forbidden,
message: "You don't have permission to view the room state.".to_owned(), message: "You don't have permission to view the room state.".to_owned(),
status_code: http::StatusCode::FORBIDDEN,
}));
}
if let Some(event) = db
.rooms
.room_state(&body.room_id)
.unwrap()
.get(&(body.event_type.clone(), "".to_owned()))
{
MatrixResult(Ok(get_state_events_for_key::Response {
content: serde_json::value::to_raw_value(event).unwrap(),
}))
} else {
MatrixResult(Err(Error {
kind: ErrorKind::NotFound,
message: "State event not found.".to_owned(),
status_code: http::StatusCode::BAD_REQUEST, status_code: http::StatusCode::BAD_REQUEST,
})) }))
} }
@ -2011,7 +2046,12 @@ pub fn sync_route(
(db.rooms (db.rooms
.pdus_since(&room_id, last_read) .pdus_since(&room_id, last_read)
.unwrap() .unwrap()
.filter(|pdu| matches!(pdu.as_ref().unwrap().kind.clone(), EventType::RoomMessage | EventType::RoomEncrypted)) .filter(|pdu| {
matches!(
pdu.as_ref().unwrap().kind.clone(),
EventType::RoomMessage | EventType::RoomEncrypted
)
})
.count() as u32) .count() as u32)
.into(), .into(),
) )
@ -2040,30 +2080,23 @@ pub fn sync_route(
let mut edus = db let mut edus = db
.rooms .rooms
.edus .edus
.roomactives_all(&room_id) .roomlatests_since(&room_id, since)
.unwrap()
.map(|r| r.unwrap()) .map(|r| r.unwrap())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if edus.is_empty() { if db
edus.push( .rooms
EduEvent::Typing(ruma_events::typing::TypingEvent { .edus
content: ruma_events::typing::TypingEventContent { .last_roomactive_update(&room_id, &db.globals)
user_ids: Vec::new(), .unwrap()
}, > since
room_id: None, // None because it can be inferred {
}) edus.push(serde_json::from_str(&serde_json::to_string(
.into(), &EduEvent::Typing(db.rooms.edus.roomactives_all(&room_id).unwrap()),
); ).unwrap()).unwrap());
} }
edus.extend(
db.rooms
.edus
.roomlatests_since(&room_id, since)
.unwrap()
.map(|r| r.unwrap()),
);
joined_rooms.insert( joined_rooms.insert(
room_id.clone().try_into().unwrap(), room_id.clone().try_into().unwrap(),
sync_events::JoinedRoom { sync_events::JoinedRoom {
@ -2130,7 +2163,17 @@ pub fn sync_route(
.map(|r| r.unwrap()) .map(|r| r.unwrap())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
edus.extend(db.rooms.edus.roomactives_all(&room_id).map(|r| r.unwrap())); if db
.rooms
.edus
.last_roomactive_update(&room_id, &db.globals)
.unwrap()
> since
{
edus.push(serde_json::from_str(&serde_json::to_string(
&EduEvent::Typing(db.rooms.edus.roomactives_all(&room_id).unwrap()),
).unwrap()).unwrap());
}
left_rooms.insert( left_rooms.insert(
room_id.clone().try_into().unwrap(), room_id.clone().try_into().unwrap(),
@ -2218,7 +2261,7 @@ pub fn sync_route(
} else { } else {
None // TODO: left None // TODO: left
}, },
device_one_time_keys_count: Default::default(), device_one_time_keys_count: Default::default(), // TODO
to_device: sync_events::ToDevice { to_device: sync_events::ToDevice {
events: db events: db
.users .users
@ -2281,7 +2324,6 @@ pub fn get_message_events_route(
#[get("/_matrix/client/r0/voip/turnServer")] #[get("/_matrix/client/r0/voip/turnServer")]
pub fn turn_server_route() -> MatrixResult<create_message_event::Response> { pub fn turn_server_route() -> MatrixResult<create_message_event::Response> {
warn!("TODO: turn_server_route");
MatrixResult(Err(Error { MatrixResult(Err(Error {
kind: ErrorKind::NotFound, kind: ErrorKind::NotFound,
message: "There is no turn server yet.".to_owned(), message: "There is no turn server yet.".to_owned(),

@ -70,7 +70,10 @@ impl Database {
edus: rooms::RoomEdus { edus: rooms::RoomEdus {
roomuserid_lastread: db.open_tree("roomuserid_lastread").unwrap(), // "Private" read receipt roomuserid_lastread: db.open_tree("roomuserid_lastread").unwrap(), // "Private" read receipt
roomlatestid_roomlatest: db.open_tree("roomlatestid_roomlatest").unwrap(), // Read receipts roomlatestid_roomlatest: db.open_tree("roomlatestid_roomlatest").unwrap(), // Read receipts
roomactiveid_roomactive: db.open_tree("roomactiveid_roomactive").unwrap(), // Typing notifs roomactiveid_userid: db.open_tree("roomactiveid_userid").unwrap(), // Typing notifs
roomid_lastroomactiveupdate: db
.open_tree("roomid_lastroomactiveupdate")
.unwrap(),
}, },
pduid_pdu: db.open_tree("pduid_pdu").unwrap(), pduid_pdu: db.open_tree("pduid_pdu").unwrap(),
eventid_pduid: db.open_tree("eventid_pduid").unwrap(), eventid_pduid: db.open_tree("eventid_pduid").unwrap(),

@ -52,31 +52,6 @@ impl Rooms {
.is_some()) .is_some())
} }
// TODO: Remove and replace with public room dir
/// Returns a vector over all rooms.
pub fn all_rooms(&self) -> Vec<RoomId> {
let mut room_ids = self
.roomid_pduleaves
.iter()
.keys()
.map(|key| {
RoomId::try_from(
&*utils::string_from_bytes(
&key.unwrap()
.iter()
.copied()
.take_while(|&x| x != 0xff) // until delimiter
.collect::<Vec<_>>(),
)
.unwrap(),
)
.unwrap()
})
.collect::<Vec<_>>();
room_ids.dedup();
room_ids
}
/// Returns the full room state. /// Returns the full room state.
pub fn room_state(&self, room_id: &RoomId) -> Result<HashMap<(EventType, String), PduEvent>> { pub fn room_state(&self, room_id: &RoomId) -> Result<HashMap<(EventType, String), PduEvent>> {
let mut hashmap = HashMap::new(); let mut hashmap = HashMap::new();
@ -329,15 +304,11 @@ impl Rooms {
false false
} else if let member::MembershipState::Ban = current_membership { } else if let member::MembershipState::Ban = current_membership {
false false
} else if join_rules == join_rules::JoinRule::Invite
&& (current_membership == member::MembershipState::Join
|| current_membership == member::MembershipState::Invite)
{
true
} else if join_rules == join_rules::JoinRule::Public {
true
} else { } else {
false 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 { } else if target_membership == member::MembershipState::Invite {
if let Some(third_party_invite_json) = content.get("third_party_invite") if let Some(third_party_invite_json) = content.get("third_party_invite")
@ -351,46 +322,35 @@ impl Rooms {
)?; )?;
todo!("handle third party invites"); todo!("handle third party invites");
} }
} else if sender_membership != member::MembershipState::Join { } else if sender_membership != member::MembershipState::Join
false || current_membership == member::MembershipState::Join
} else if current_membership == member::MembershipState::Join
|| current_membership == member::MembershipState::Ban || current_membership == member::MembershipState::Ban
{ {
false false
} else if sender_power
.filter(|&p| p >= &power_levels.invite)
.is_some()
{
true
} else { } else {
false sender_power
.filter(|&p| p >= &power_levels.invite)
.is_some()
} }
} else if target_membership == member::MembershipState::Leave { } else if target_membership == member::MembershipState::Leave {
if sender == target_user_id { if sender == target_user_id {
current_membership == member::MembershipState::Join current_membership == member::MembershipState::Join
|| current_membership == member::MembershipState::Invite || current_membership == member::MembershipState::Invite
} else if sender_membership != member::MembershipState::Join { } else if sender_membership != member::MembershipState::Join
false || current_membership == member::MembershipState::Ban
} else if current_membership == member::MembershipState::Ban && sender_power.filter(|&p| p < &power_levels.ban).is_some()
&& sender_power.filter(|&p| p < &power_levels.ban).is_some()
{ {
false false
} else if sender_power.filter(|&p| p >= &power_levels.kick).is_some()
&& target_power < sender_power
{
true
} else { } else {
false sender_power.filter(|&p| p >= &power_levels.kick).is_some()
&& target_power < sender_power
} }
} else if target_membership == member::MembershipState::Ban { } else if target_membership == member::MembershipState::Ban {
if sender_membership != member::MembershipState::Join { if sender_membership != member::MembershipState::Join {
false false
} else if sender_power.filter(|&p| p >= &power_levels.ban).is_some()
&& target_power < sender_power
{
true
} else { } else {
false sender_power.filter(|&p| p >= &power_levels.ban).is_some()
&& target_power < sender_power
} }
} else { } else {
false false
@ -668,16 +628,21 @@ impl Rooms {
globals: &super::globals::Globals, globals: &super::globals::Globals,
) -> Result<()> { ) -> Result<()> {
if let Some(room_id) = room_id { if let Some(room_id) = room_id {
// New alias
self.alias_roomid self.alias_roomid
.insert(alias.alias(), &*room_id.to_string())?; .insert(alias.alias(), &*room_id.to_string())?;
let mut aliasid = room_id.to_string().as_bytes().to_vec(); let mut aliasid = room_id.to_string().as_bytes().to_vec();
aliasid.extend_from_slice(&globals.next_count()?.to_be_bytes()); aliasid.extend_from_slice(&globals.next_count()?.to_be_bytes());
self.aliasid_alias.insert(aliasid, &*alias.alias())?; self.aliasid_alias.insert(aliasid, &*alias.alias())?;
} else { } else {
if let Some(room_id) = self.alias_roomid.remove(alias.alias())? { // room_id=None means remove alias
for key in self.aliasid_alias.scan_prefix(room_id).keys() { let room_id = self
self.aliasid_alias.remove(key?)?; .alias_roomid
} .remove(alias.alias())?
.ok_or(Error::BadRequest("Alias does not exist"))?;
for key in self.aliasid_alias.scan_prefix(room_id).keys() {
self.aliasid_alias.remove(key?)?;
} }
} }

@ -1,11 +1,13 @@
use crate::{utils, Result}; use crate::{utils, Error, Result};
use ruma_events::{collections::only::Event as EduEvent, EventJson}; use ruma_events::{collections::only::Event as EduEvent, EventJson};
use ruma_identifiers::{RoomId, UserId}; use ruma_identifiers::{RoomId, UserId};
use std::convert::TryFrom;
pub struct RoomEdus { pub struct RoomEdus {
pub(in super::super) roomuserid_lastread: sled::Tree, // RoomUserId = Room + User pub(in super::super) roomuserid_lastread: sled::Tree, // RoomUserId = Room + User
pub(in super::super) roomlatestid_roomlatest: sled::Tree, // Read Receipts, RoomLatestId = RoomId + Count + UserId pub(in super::super) roomlatestid_roomlatest: sled::Tree, // Read Receipts, RoomLatestId = RoomId + Count + UserId
pub(in super::super) roomactiveid_roomactive: sled::Tree, // Typing, RoomActiveId = RoomId + TimeoutTime + Count pub(in super::super) roomactiveid_userid: sled::Tree, // Typing, RoomActiveId = RoomId + TimeoutTime + Count
pub(in super::super) roomid_lastroomactiveupdate: sled::Tree, // LastRoomActiveUpdate = Count
} }
impl RoomEdus { impl RoomEdus {
@ -79,10 +81,11 @@ impl RoomEdus {
.map(|(_, v)| Ok(serde_json::from_slice(&v)?))) .map(|(_, v)| Ok(serde_json::from_slice(&v)?)))
} }
/// Adds an event that will be saved until the `timeout` timestamp (e.g. typing notifications). /// Sets a user as typing until the timeout timestamp is reached or roomactive_remove is
/// called.
pub fn roomactive_add( pub fn roomactive_add(
&self, &self,
event: EduEvent, user_id: &UserId,
room_id: &RoomId, room_id: &RoomId,
timeout: u64, timeout: u64,
globals: &super::super::globals::Globals, globals: &super::super::globals::Globals,
@ -90,71 +93,134 @@ impl RoomEdus {
let mut prefix = room_id.to_string().as_bytes().to_vec(); let mut prefix = room_id.to_string().as_bytes().to_vec();
prefix.push(0xff); prefix.push(0xff);
// Cleanup all outdated edus before inserting a new one let count = globals.next_count()?.to_be_bytes();
let mut room_active_id = prefix;
room_active_id.extend_from_slice(&timeout.to_be_bytes());
room_active_id.push(0xff);
room_active_id.extend_from_slice(&count);
self.roomactiveid_userid
.insert(&room_active_id, &*user_id.to_string().as_bytes())?;
self.roomid_lastroomactiveupdate
.insert(&room_id.to_string().as_bytes(), &count)?;
Ok(())
}
/// Removes a user from typing before the timeout is reached.
pub fn roomactive_remove(
&self,
user_id: &UserId,
room_id: &RoomId,
globals: &super::super::globals::Globals,
) -> Result<()> {
let mut prefix = room_id.to_string().as_bytes().to_vec();
prefix.push(0xff);
let user_id = user_id.to_string();
let mut found_outdated = false;
// Maybe there are multiple ones from calling roomactive_add multiple times
for outdated_edu in self for outdated_edu in self
.roomactiveid_roomactive .roomactiveid_userid
.scan_prefix(&prefix) .scan_prefix(&prefix)
.keys()
.filter_map(|r| r.ok()) .filter_map(|r| r.ok())
.take_while(|k| { .filter(|(_, v)| v == user_id.as_bytes())
utils::u64_from_bytes(
k.split(|&c| c == 0xff)
.nth(1)
.expect("roomactive has valid timestamp and delimiters"),
) < utils::millis_since_unix_epoch()
})
{ {
// This is an outdated edu (time > timestamp) self.roomactiveid_userid.remove(outdated_edu.0)?;
self.roomlatestid_roomlatest.remove(outdated_edu)?; found_outdated = true;
} }
let mut room_active_id = prefix; if found_outdated {
room_active_id.extend_from_slice(&timeout.to_be_bytes()); self.roomid_lastroomactiveupdate.insert(
room_active_id.push(0xff); &room_id.to_string().as_bytes(),
room_active_id.extend_from_slice(&globals.next_count()?.to_be_bytes()); &globals.next_count()?.to_be_bytes(),
)?;
self.roomactiveid_roomactive }
.insert(room_active_id, &*serde_json::to_string(&event)?)?;
Ok(()) Ok(())
} }
/// Removes an active event manually (before the timeout is reached). /// Makes sure that typing events with old timestamps get removed.
pub fn roomactive_remove(&self, event: EduEvent, room_id: &RoomId) -> Result<()> { fn roomactives_maintain(
&self,
room_id: &RoomId,
globals: &super::super::globals::Globals,
) -> Result<()> {
let mut prefix = room_id.to_string().as_bytes().to_vec(); let mut prefix = room_id.to_string().as_bytes().to_vec();
prefix.push(0xff); prefix.push(0xff);
let json = serde_json::to_string(&event)?; let current_timestamp = utils::millis_since_unix_epoch();
// Remove outdated entries let mut found_outdated = false;
// Find all outdated edus before inserting a new one
for outdated_edu in self for outdated_edu in self
.roomactiveid_roomactive .roomactiveid_userid
.scan_prefix(&prefix) .scan_prefix(&prefix)
.keys()
.filter_map(|r| r.ok()) .filter_map(|r| r.ok())
.filter(|(_, v)| v == json.as_bytes()) .take_while(|k| {
utils::u64_from_bytes(
k.split(|&c| c == 0xff)
.nth(1)
.expect("roomactive has valid timestamp and delimiters"),
) < current_timestamp
})
{ {
self.roomactiveid_roomactive.remove(outdated_edu.0)?; // This is an outdated edu (time > timestamp)
self.roomlatestid_roomlatest.remove(outdated_edu)?;
found_outdated = true;
}
if found_outdated {
self.roomid_lastroomactiveupdate.insert(
&room_id.to_string().as_bytes(),
&globals.next_count()?.to_be_bytes(),
)?;
} }
Ok(()) Ok(())
} }
/// Returns an iterator over all active events (e.g. typing notifications). /// Returns an iterator over all active events (e.g. typing notifications).
pub fn roomactives_all( pub fn last_roomactive_update(
&self, &self,
room_id: &RoomId, room_id: &RoomId,
) -> impl Iterator<Item = Result<EventJson<EduEvent>>> { globals: &super::super::globals::Globals,
) -> Result<u64> {
self.roomactives_maintain(room_id, globals)?;
Ok(self
.roomid_lastroomactiveupdate
.get(&room_id.to_string().as_bytes())?
.map(|bytes| utils::u64_from_bytes(&bytes))
.unwrap_or(0))
}
/// Returns an iterator over all active events (e.g. typing notifications).
pub fn roomactives_all(&self, room_id: &RoomId) -> Result<ruma_events::typing::TypingEvent> {
let mut prefix = room_id.to_string().as_bytes().to_vec(); let mut prefix = room_id.to_string().as_bytes().to_vec();
prefix.push(0xff); prefix.push(0xff);
let mut first_active_edu = prefix.clone(); let mut user_ids = Vec::new();
first_active_edu.extend_from_slice(&utils::millis_since_unix_epoch().to_be_bytes());
self.roomactiveid_roomactive for user_id in self
.range(first_active_edu..) .roomactiveid_userid
.filter_map(|r| r.ok()) .scan_prefix(prefix)
.take_while(move |(k, _)| k.starts_with(&prefix)) .values()
.map(|(_, v)| Ok(serde_json::from_slice(&v)?)) .map(|user_id| Ok::<_, Error>(UserId::try_from(utils::string_from_bytes(&user_id?)?)?))
{
user_ids.push(user_id?);
}
Ok(ruma_events::typing::TypingEvent {
content: ruma_events::typing::TypingEventContent { user_ids },
room_id: None, // Can be inferred
})
} }
/// Sets a private read marker at `count`. /// Sets a private read marker at `count`.

@ -361,14 +361,12 @@ impl Users {
self.userdeviceid_devicekeys.scan_prefix(key).map(|r| { self.userdeviceid_devicekeys.scan_prefix(key).map(|r| {
let (key, value) = r?; let (key, value) = r?;
Ok(( let userdeviceid = utils::string_from_bytes(
utils::string_from_bytes( key.rsplit(|&b| b == 0xff)
key.rsplit(|&b| b == 0xff) .next()
.next() .ok_or(Error::BadDatabase("userdeviceid is invalid"))?,
.ok_or(Error::BadDatabase("userdeviceid is invalid"))?, )?;
)?, Ok((userdeviceid, serde_json::from_slice(&*value)?))
serde_json::from_slice(&*value)?,
))
}) })
} }

@ -6,12 +6,9 @@ mod database;
mod error; mod error;
mod pdu; mod pdu;
mod ruma_wrapper; mod ruma_wrapper;
mod server_server; //mod server_server;
mod utils; mod utils;
#[cfg(test)]
mod test;
pub use database::Database; pub use database::Database;
pub use error::{Error, Result}; pub use error::{Error, Result};
pub use pdu::PduEvent; pub use pdu::PduEvent;
@ -87,10 +84,10 @@ fn setup_rocket() -> rocket::Rocket {
client_server::delete_device_route, client_server::delete_device_route,
client_server::delete_devices_route, client_server::delete_devices_route,
client_server::options_route, client_server::options_route,
server_server::well_known_server, //server_server::well_known_server,
server_server::get_server_version, //server_server::get_server_version,
server_server::get_server_keys, //server_server::get_server_keys,
server_server::get_server_keys_deprecated, //server_server::get_server_keys_deprecated,
], ],
) )
.attach(AdHoc::on_attach("Config", |rocket| { .attach(AdHoc::on_attach("Config", |rocket| {

@ -1,124 +0,0 @@
use super::*;
use rocket::local::Client;
use serde_json::{json, Value};
fn setup_client() -> Client {
Database::try_remove("localhost");
let rocket = setup_rocket();
Client::new(rocket).expect("valid rocket instance")
}
#[tokio::test]
async fn register_login() {
let client = setup_client();
let mut response = client
.post("/_matrix/client/r0/register?kind=user")
.body(registration_init())
.dispatch()
.await;
let body = serde_json::from_str::<Value>(&response.body_string().await.unwrap()).unwrap();
assert_eq!(response.status().code, 401);
assert!(dbg!(&body["flows"]).as_array().unwrap().len() > 0);
assert!(body["session"].as_str().unwrap().len() > 0);
}
#[tokio::test]
async fn login_after_register_correct_password() {
let client = setup_client();
let mut response = client
.post("/_matrix/client/r0/register?kind=user")
.body(registration_init())
.dispatch()
.await;
let body = serde_json::from_str::<Value>(&response.body_string().await.unwrap()).unwrap();
let session = body["session"].clone();
let response = client
.post("/_matrix/client/r0/register?kind=user")
.body(registration(session.as_str().unwrap()))
.dispatch()
.await;
assert_eq!(response.status().code, 200);
let login_response = client
.post("/_matrix/client/r0/login")
.body(login_with_password("ilovebananas"))
.dispatch()
.await;
assert_eq!(login_response.status().code, 200);
}
#[tokio::test]
async fn login_after_register_incorrect_password() {
let client = setup_client();
let mut response = client
.post("/_matrix/client/r0/register?kind=user")
.body(registration_init())
.dispatch()
.await;
let body = serde_json::from_str::<Value>(&response.body_string().await.unwrap()).unwrap();
let session = body["session"].clone();
let response = client
.post("/_matrix/client/r0/register?kind=user")
.body(registration(session.as_str().unwrap()))
.dispatch()
.await;
assert_eq!(response.status().code, 200);
let mut login_response = client
.post("/_matrix/client/r0/login")
.body(login_with_password("idontlovebananas"))
.dispatch()
.await;
let body = serde_json::from_str::<Value>(&login_response.body_string().await.unwrap()).unwrap();
assert_eq!(
body.as_object()
.unwrap()
.get("errcode")
.unwrap()
.as_str()
.unwrap(),
"M_FORBIDDEN"
);
assert_eq!(login_response.status().code, 403);
}
fn registration_init() -> &'static str {
r#"{
"username": "cheeky_monkey",
"password": "ilovebananas",
"device_id": "GHTYAJCE",
"initial_device_display_name": "Jungle Phone",
"inhibit_login": false
}"#
}
fn registration(session: &str) -> String {
json!({
"auth": {
"session": session,
"type": "m.login.dummy"
},
"username": "cheeky_monkey",
"password": "ilovebananas",
"device_id": "GHTYAJCE",
"initial_device_display_name": "Jungle Phone",
"inhibit_login": false
})
.to_string()
}
fn login_with_password(password: &str) -> String {
json!({
"type": "m.login.password",
"identifier": {
"type": "m.id.user",
"user": "cheeky_monkey"
},
"password": password,
"initial_device_display_name": "Jungle Phone"
})
.to_string()
}

@ -28,26 +28,13 @@ POST /login wrong password is rejected
POST /createRoom makes a private room POST /createRoom makes a private room
POST /createRoom makes a private room with invites POST /createRoom makes a private room with invites
GET /rooms/:room_id/state/m.room.member/:user_id fetches my membership GET /rooms/:room_id/state/m.room.member/:user_id fetches my membership
GET /rooms/:room_id/state/m.room.power_levels fetches powerlevels
POST /join/:room_alias can join a room
POST /join/:room_id can join a room POST /join/:room_id can join a room
POST /join/:room_id can join a room with custom content
POST /join/:room_alias can join a room with custom content
POST /rooms/:room_id/join can join a room POST /rooms/:room_id/join can join a room
POST /rooms/:room_id/leave can leave a room POST /rooms/:room_id/leave can leave a room
POST /rooms/:room_id/invite can send an invite POST /rooms/:room_id/invite can send an invite
POST /rooms/:room_id/ban can ban a user
POST /rooms/:room_id/send/:event_type sends a message
PUT /rooms/:room_id/send/:event_type/:txn_id sends a message
PUT /rooms/:room_id/send/:event_type/:txn_id deduplicates the same txn id
GET /rooms/:room_id/state/m.room.power_levels can fetch levels
PUT /rooms/:room_id/state/m.room.power_levels can set levels PUT /rooms/:room_id/state/m.room.power_levels can set levels
PUT power_levels should not explode if the old power levels were empty PUT power_levels should not explode if the old power levels were empty
Both GET and PUT work Both GET and PUT work
POST /rooms/:room_id/read_markers can create read marker
User signups are forbidden from starting with '_'
Request to logout with invalid an access token is rejected
Request to logout without an access token is rejected
Room creation reports m.room.create to myself Room creation reports m.room.create to myself
Room creation reports m.room.member to myself Room creation reports m.room.member to myself
Version responds 200 OK with valid structure Version responds 200 OK with valid structure
@ -60,7 +47,6 @@ Can create filter
Should reject keys claiming to belong to a different user Should reject keys claiming to belong to a different user
Can add account data Can add account data
Checking local federation server Checking local federation server
Alternative server names do not cause a routing loop
Can read configuration endpoint Can read configuration endpoint
AS cannot create users outside its own namespace AS cannot create users outside its own namespace
Changing the actions of an unknown default rule fails with 404 Changing the actions of an unknown default rule fails with 404
@ -78,4 +64,16 @@ Trying to get push rules with unknown rule_id fails with 404
GET /events with non-numeric 'limit' GET /events with non-numeric 'limit'
GET /events with negative 'limit' GET /events with negative 'limit'
GET /events with non-numeric 'timeout' GET /events with non-numeric 'timeout'
Getting push rules doesn't corrupt the cache SYN-390 Getting push rules doesn't corrupt the cache SYN-390
GET /publicRooms lists newly-created room
PUT /directory/room/:room_alias creates alias
3pid invite join with wrong but valid signature are rejected
3pid invite join valid signature but revoked keys are rejected
3pid invite join valid signature but unreachable ID server are rejected
query for user with no keys returns empty key dict
Can upload without a file name
Can upload with ASCII file name
User appears in user directory
User directory correctly update on display name change
User in shared private room does appear in user directory
User in dir while user still shares private rooms

Loading…
Cancel
Save