Merge pull request 'Small fixes' (#98) from fix into master
This commit is contained in:
commit
c655870d23
10 changed files with 353 additions and 408 deletions
92
Cargo.lock
generated
92
Cargo.lock
generated
|
@ -26,13 +26,13 @@ checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
|
|||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.31"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26c4f3195085c36ea8d24d32b2f828d23296a9370a28aa39d111f6f16bef9f3b"
|
||||
checksum = "0eb7f9ad01405feb3c1dac82463038945cf88eea4569acaf3ad662233496dd96"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.29",
|
||||
"syn 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -98,9 +98,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.3.0"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5356f1d23ee24a1f785a56d1d1a5f0fd5b0f6a0c0fb2412ce11da71649ab78f6"
|
||||
checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
|
@ -277,9 +277,9 @@ version = "0.3.0"
|
|||
source = "git+https://github.com/SergioBenitez/Devise.git?rev=e58b3ac9a#e58b3ac9afc3b6ff10a8aaf02a3e768a8f530089"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"proc-macro2 1.0.17",
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.29",
|
||||
"syn 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -421,9 +421,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"proc-macro2 1.0.17",
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.29",
|
||||
"syn 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -621,9 +621,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.3.2"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292"
|
||||
checksum = "c398b2b113b55809ceb9ee3e753fcbac793f1956663f3c36549c1346015c2afe"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
@ -1002,16 +1002,16 @@ version = "0.4.17"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e58db2081ba5b4c93bd6be09c40fd36cb9193a8336c384f3b40012e531aa7e40"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.29",
|
||||
"syn 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.1.5"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7505eeebd78492e0f6108f7171c4948dbb120ee8119d9d77d0afa5469bef67f"
|
||||
checksum = "9df32da11d84f3a7d70205549562966279adb900e080fad3dccd8e64afccf0ad"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
|
@ -1027,9 +1027,9 @@ checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
|
|||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.16.3"
|
||||
version = "0.16.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c68a431ed29933a4eb5709aca9800989758c97759345860fa5db3cfced0b65d"
|
||||
checksum = "12faa637ed9ae3d3c881332e54b5ae2dba81cda9fc4bbce0faa1ba53abcead50"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crc32fast",
|
||||
|
@ -1066,9 +1066,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.17"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101"
|
||||
checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa"
|
||||
dependencies = [
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
@ -1088,7 +1088,7 @@ version = "1.0.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"proc-macro2 1.0.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1289,9 +1289,9 @@ version = "0.16.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52b82b4567b9af9b40a86f7778821c016ea961f55e4fee255f8f24bb28ee7452"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.29",
|
||||
"syn 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1343,9 +1343,9 @@ name = "ruma-events-macros"
|
|||
version = "0.21.3"
|
||||
source = "git+https://github.com/ruma/ruma-events.git?rev=4d09416cd1663d63c22153705c9e1fd77910797f#4d09416cd1663d63c22153705c9e1fd77910797f"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.29",
|
||||
"syn 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1365,9 +1365,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ruma-identifiers"
|
||||
version = "0.16.1"
|
||||
version = "0.16.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77c93b9d5f951a2fb57b19c048a05ac1dbdb280ff7617ec6b02f54bf14318ed8"
|
||||
checksum = "6316cb248e3e0323a5a269b8eaed571404fb4f65c81848549e9ba99fd9b8e9de"
|
||||
dependencies = [
|
||||
"rand",
|
||||
"serde",
|
||||
|
@ -1437,9 +1437,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.4"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1"
|
||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
|
@ -1505,9 +1505,9 @@ version = "1.0.111"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.29",
|
||||
"syn 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1611,9 +1611,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2 1.0.17",
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.29",
|
||||
"syn 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1629,11 +1629,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.29"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb37da98a55b1d08529362d9cbb863be17556873df2585904ab9d2bc951291d0"
|
||||
checksum = "93a56fabc59dce20fe48b6c832cc249c713e7ed88fa28b0ee0a3bfcaae5fe4e2"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.6",
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
@ -1667,9 +1667,9 @@ version = "1.0.19"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "893582086c2f98cde18f906265a65b5030a074b1046c674ae898be6519a7f479"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.29",
|
||||
"syn 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1711,9 +1711,9 @@ version = "0.2.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.29",
|
||||
"syn 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1837,9 +1837,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
|
||||
checksum = "55d1e41d56121e07f1e223db0a4def204e45c85425f6a16d462fd07c8d10d74c"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
|
@ -1890,9 +1890,9 @@ dependencies = [
|
|||
"bumpalo",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"proc-macro2 1.0.17",
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.29",
|
||||
"syn 1.0.30",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
@ -1924,9 +1924,9 @@ version = "0.2.63"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3156052d8ec77142051a533cdd686cba889537b213f948cd1d20869926e68e92"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.17",
|
||||
"proc-macro2 1.0.18",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.29",
|
||||
"syn 1.0.30",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
|
|
@ -15,7 +15,7 @@ edition = "2018"
|
|||
rocket = { git = "https://github.com/SergioBenitez/Rocket.git", branch = "async", features = ["tls"] }
|
||||
http = "0.2.1"
|
||||
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-events = { git = "https://github.com/ruma/ruma-events.git", rev = "4d09416cd1663d63c22153705c9e1fd77910797f" }
|
||||
ruma-signatures = { git = "https://github.com/ruma/ruma-signatures.git", rev = "1ca545cba8dfd43e0fc8e3c18e1311fb73390a97" }
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::{
|
|||
time::{Duration, SystemTime},
|
||||
};
|
||||
|
||||
use crate::{utils, Database, MatrixResult, Ruma};
|
||||
use log::{debug, warn};
|
||||
use rocket::{delete, get, options, post, put, State};
|
||||
use ruma_client_api::{
|
||||
|
@ -13,15 +14,13 @@ use ruma_client_api::{
|
|||
alias::{create_alias, delete_alias, get_alias},
|
||||
capabilities::get_capabilities,
|
||||
config::{get_global_account_data, set_global_account_data},
|
||||
device::{
|
||||
self, delete_device, delete_devices, get_device, get_devices, update_device,
|
||||
},
|
||||
device::{self, delete_device, delete_devices, get_device, get_devices, update_device},
|
||||
directory::{
|
||||
self, get_public_rooms, get_public_rooms_filtered, get_room_visibility,
|
||||
set_room_visibility,
|
||||
},
|
||||
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},
|
||||
membership::{
|
||||
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 serde_json::{json, value::RawValue};
|
||||
|
||||
use crate::{server_server, utils, Database, MatrixResult, Ruma};
|
||||
|
||||
const GUEST_NAME_LENGTH: usize = 10;
|
||||
const DEVICE_ID_LENGTH: usize = 10;
|
||||
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
|
||||
let device_id = body
|
||||
.device_id.clone()
|
||||
.device_id
|
||||
.clone()
|
||||
.unwrap_or_else(|| utils::random_string(DEVICE_ID_LENGTH));
|
||||
|
||||
// Generate new token for the device
|
||||
|
@ -184,7 +182,12 @@ pub fn register_route(
|
|||
|
||||
// Add device
|
||||
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();
|
||||
|
||||
// Initial data
|
||||
|
@ -311,7 +314,12 @@ pub fn login_route(
|
|||
|
||||
// Add device
|
||||
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();
|
||||
|
||||
MatrixResult(Ok(login::Response {
|
||||
|
@ -338,14 +346,23 @@ pub fn logout_route(
|
|||
|
||||
#[get("/_matrix/client/r0/capabilities")]
|
||||
pub fn get_capabilities_route() -> MatrixResult<get_capabilities::Response> {
|
||||
// TODO
|
||||
//let mut available = BTreeMap::new();
|
||||
//available.insert("5".to_owned(), get_capabilities::RoomVersionStability::Unstable);
|
||||
let mut available = BTreeMap::new();
|
||||
available.insert(
|
||||
"5".to_owned(),
|
||||
get_capabilities::RoomVersionStability::Stable,
|
||||
);
|
||||
available.insert(
|
||||
"6".to_owned(),
|
||||
get_capabilities::RoomVersionStability::Stable,
|
||||
);
|
||||
|
||||
MatrixResult(Ok(get_capabilities::Response {
|
||||
capabilities: get_capabilities::Capabilities {
|
||||
change_password: None,
|
||||
room_versions: None, //Some(get_capabilities::RoomVersionsCapability { default: "5".to_owned(), available }),
|
||||
change_password: None, // None means it is possible
|
||||
room_versions: Some(get_capabilities::RoomVersionsCapability {
|
||||
default: "6".to_owned(),
|
||||
available,
|
||||
}),
|
||||
custom_capabilities: BTreeMap::new(),
|
||||
},
|
||||
}))
|
||||
|
@ -749,11 +766,21 @@ pub fn get_keys_route(
|
|||
for (user_id, device_ids) in &body.device_keys {
|
||||
if device_ids.is_empty() {
|
||||
let mut container = BTreeMap::new();
|
||||
for (device_id, keys) in db
|
||||
for (device_id, mut keys) in db
|
||||
.users
|
||||
.all_device_keys(&user_id.clone())
|
||||
.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);
|
||||
}
|
||||
device_keys.insert(user_id.clone(), container);
|
||||
|
@ -761,7 +788,18 @@ pub fn get_keys_route(
|
|||
for device_id in device_ids {
|
||||
let mut container = BTreeMap::new();
|
||||
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);
|
||||
}
|
||||
|
@ -883,18 +921,12 @@ pub fn create_typing_event_route(
|
|||
_user_id: String,
|
||||
) -> MatrixResult<create_typing_event::Response> {
|
||||
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 {
|
||||
db.rooms
|
||||
.edus
|
||||
.roomactive_add(
|
||||
edu,
|
||||
&user_id,
|
||||
&body.room_id,
|
||||
body.timeout.map(|d| d.as_millis() as u64).unwrap_or(30000)
|
||||
+ utils::millis_since_unix_epoch().try_into().unwrap_or(0),
|
||||
|
@ -902,7 +934,10 @@ pub fn create_typing_event_route(
|
|||
)
|
||||
.unwrap();
|
||||
} 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))
|
||||
|
@ -954,7 +989,7 @@ pub fn create_room_route(
|
|||
.creation_content
|
||||
.as_ref()
|
||||
.and_then(|c| c.predecessor.clone()),
|
||||
room_version: RoomVersionId::version_5(),
|
||||
room_version: RoomVersionId::version_6(),
|
||||
})
|
||||
.unwrap(),
|
||||
None,
|
||||
|
@ -1279,11 +1314,11 @@ pub fn get_alias_route(
|
|||
}))
|
||||
} else {
|
||||
debug!("Room alias not found.");
|
||||
return MatrixResult(Err(Error {
|
||||
MatrixResult(Err(Error {
|
||||
kind: ErrorKind::NotFound,
|
||||
message: "Room with alias not found.".to_owned(),
|
||||
status_code: http::StatusCode::BAD_REQUEST,
|
||||
}));
|
||||
}))
|
||||
}
|
||||
} else {
|
||||
todo!("ask remote server");
|
||||
|
@ -1859,23 +1894,23 @@ pub fn get_state_events_route(
|
|||
) -> MatrixResult<get_state_events::Response> {
|
||||
let user_id = body.user_id.as_ref().expect("user is authenticated");
|
||||
|
||||
if db.rooms.is_joined(user_id, &body.room_id).unwrap() {
|
||||
MatrixResult(Ok(get_state_events::Response {
|
||||
room_state: db
|
||||
.rooms
|
||||
.room_state(&body.room_id)
|
||||
.unwrap()
|
||||
.values()
|
||||
.map(|pdu| pdu.to_state_event())
|
||||
.collect(),
|
||||
}))
|
||||
} else {
|
||||
MatrixResult(Err(Error {
|
||||
if !db.rooms.is_joined(user_id, &body.room_id).unwrap() {
|
||||
return MatrixResult(Err(Error {
|
||||
kind: ErrorKind::Forbidden,
|
||||
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(
|
||||
|
@ -1891,28 +1926,28 @@ pub fn get_state_events_for_key_route(
|
|||
) -> MatrixResult<get_state_events_for_key::Response> {
|
||||
let user_id = body.user_id.as_ref().expect("user is authenticated");
|
||||
|
||||
if db.rooms.is_joined(user_id, &body.room_id).unwrap() {
|
||||
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::BAD_REQUEST,
|
||||
}))
|
||||
}
|
||||
} else {
|
||||
MatrixResult(Err(Error {
|
||||
if !db.rooms.is_joined(user_id, &body.room_id).unwrap() {
|
||||
return MatrixResult(Err(Error {
|
||||
kind: ErrorKind::Forbidden,
|
||||
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> {
|
||||
let user_id = body.user_id.as_ref().expect("user is authenticated");
|
||||
|
||||
if db.rooms.is_joined(user_id, &body.room_id).unwrap() {
|
||||
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,
|
||||
}))
|
||||
}
|
||||
} else {
|
||||
MatrixResult(Err(Error {
|
||||
if !db.rooms.is_joined(user_id, &body.room_id).unwrap() {
|
||||
return MatrixResult(Err(Error {
|
||||
kind: ErrorKind::Forbidden,
|
||||
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,
|
||||
}))
|
||||
}
|
||||
|
@ -2011,7 +2046,12 @@ pub fn sync_route(
|
|||
(db.rooms
|
||||
.pdus_since(&room_id, last_read)
|
||||
.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)
|
||||
.into(),
|
||||
)
|
||||
|
@ -2040,30 +2080,23 @@ pub fn sync_route(
|
|||
let mut edus = db
|
||||
.rooms
|
||||
.edus
|
||||
.roomactives_all(&room_id)
|
||||
.roomlatests_since(&room_id, since)
|
||||
.unwrap()
|
||||
.map(|r| r.unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if edus.is_empty() {
|
||||
edus.push(
|
||||
EduEvent::Typing(ruma_events::typing::TypingEvent {
|
||||
content: ruma_events::typing::TypingEventContent {
|
||||
user_ids: Vec::new(),
|
||||
},
|
||||
room_id: None, // None because it can be inferred
|
||||
})
|
||||
.into(),
|
||||
);
|
||||
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());
|
||||
}
|
||||
|
||||
edus.extend(
|
||||
db.rooms
|
||||
.edus
|
||||
.roomlatests_since(&room_id, since)
|
||||
.unwrap()
|
||||
.map(|r| r.unwrap()),
|
||||
);
|
||||
|
||||
joined_rooms.insert(
|
||||
room_id.clone().try_into().unwrap(),
|
||||
sync_events::JoinedRoom {
|
||||
|
@ -2130,7 +2163,17 @@ pub fn sync_route(
|
|||
.map(|r| r.unwrap())
|
||||
.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(
|
||||
room_id.clone().try_into().unwrap(),
|
||||
|
@ -2218,7 +2261,7 @@ pub fn sync_route(
|
|||
} else {
|
||||
None // TODO: left
|
||||
},
|
||||
device_one_time_keys_count: Default::default(),
|
||||
device_one_time_keys_count: Default::default(), // TODO
|
||||
to_device: sync_events::ToDevice {
|
||||
events: db
|
||||
.users
|
||||
|
@ -2281,7 +2324,6 @@ pub fn get_message_events_route(
|
|||
|
||||
#[get("/_matrix/client/r0/voip/turnServer")]
|
||||
pub fn turn_server_route() -> MatrixResult<create_message_event::Response> {
|
||||
warn!("TODO: turn_server_route");
|
||||
MatrixResult(Err(Error {
|
||||
kind: ErrorKind::NotFound,
|
||||
message: "There is no turn server yet.".to_owned(),
|
||||
|
|
|
@ -70,7 +70,10 @@ impl Database {
|
|||
edus: rooms::RoomEdus {
|
||||
roomuserid_lastread: db.open_tree("roomuserid_lastread").unwrap(), // "Private" read receipt
|
||||
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(),
|
||||
eventid_pduid: db.open_tree("eventid_pduid").unwrap(),
|
||||
|
|
|
@ -52,31 +52,6 @@ impl Rooms {
|
|||
.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.
|
||||
pub fn room_state(&self, room_id: &RoomId) -> Result<HashMap<(EventType, String), PduEvent>> {
|
||||
let mut hashmap = HashMap::new();
|
||||
|
@ -329,15 +304,11 @@ impl Rooms {
|
|||
false
|
||||
} else if let member::MembershipState::Ban = current_membership {
|
||||
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 {
|
||||
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 {
|
||||
if let Some(third_party_invite_json) = content.get("third_party_invite")
|
||||
|
@ -351,46 +322,35 @@ impl Rooms {
|
|||
)?;
|
||||
todo!("handle third party invites");
|
||||
}
|
||||
} else if sender_membership != member::MembershipState::Join {
|
||||
false
|
||||
} else if current_membership == member::MembershipState::Join
|
||||
} else if sender_membership != member::MembershipState::Join
|
||||
|| current_membership == member::MembershipState::Join
|
||||
|| current_membership == member::MembershipState::Ban
|
||||
{
|
||||
false
|
||||
} else if sender_power
|
||||
.filter(|&p| p >= &power_levels.invite)
|
||||
.is_some()
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
sender_power
|
||||
.filter(|&p| p >= &power_levels.invite)
|
||||
.is_some()
|
||||
}
|
||||
} else if target_membership == member::MembershipState::Leave {
|
||||
if sender == target_user_id {
|
||||
current_membership == member::MembershipState::Join
|
||||
|| current_membership == member::MembershipState::Invite
|
||||
} else if sender_membership != member::MembershipState::Join {
|
||||
false
|
||||
} else if current_membership == member::MembershipState::Ban
|
||||
&& sender_power.filter(|&p| p < &power_levels.ban).is_some()
|
||||
} else if sender_membership != member::MembershipState::Join
|
||||
|| current_membership == member::MembershipState::Ban
|
||||
&& sender_power.filter(|&p| p < &power_levels.ban).is_some()
|
||||
{
|
||||
false
|
||||
} else if sender_power.filter(|&p| p >= &power_levels.kick).is_some()
|
||||
&& target_power < sender_power
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
sender_power.filter(|&p| p >= &power_levels.kick).is_some()
|
||||
&& target_power < sender_power
|
||||
}
|
||||
} else if target_membership == member::MembershipState::Ban {
|
||||
if sender_membership != member::MembershipState::Join {
|
||||
false
|
||||
} else if sender_power.filter(|&p| p >= &power_levels.ban).is_some()
|
||||
&& target_power < sender_power
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
sender_power.filter(|&p| p >= &power_levels.ban).is_some()
|
||||
&& target_power < sender_power
|
||||
}
|
||||
} else {
|
||||
false
|
||||
|
@ -668,16 +628,21 @@ impl Rooms {
|
|||
globals: &super::globals::Globals,
|
||||
) -> Result<()> {
|
||||
if let Some(room_id) = room_id {
|
||||
// New alias
|
||||
self.alias_roomid
|
||||
.insert(alias.alias(), &*room_id.to_string())?;
|
||||
let mut aliasid = room_id.to_string().as_bytes().to_vec();
|
||||
aliasid.extend_from_slice(&globals.next_count()?.to_be_bytes());
|
||||
self.aliasid_alias.insert(aliasid, &*alias.alias())?;
|
||||
} else {
|
||||
if let Some(room_id) = self.alias_roomid.remove(alias.alias())? {
|
||||
for key in self.aliasid_alias.scan_prefix(room_id).keys() {
|
||||
self.aliasid_alias.remove(key?)?;
|
||||
}
|
||||
// room_id=None means remove alias
|
||||
let room_id = self
|
||||
.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_identifiers::{RoomId, UserId};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
pub struct RoomEdus {
|
||||
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) 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 {
|
||||
|
@ -79,10 +81,11 @@ impl RoomEdus {
|
|||
.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(
|
||||
&self,
|
||||
event: EduEvent,
|
||||
user_id: &UserId,
|
||||
room_id: &RoomId,
|
||||
timeout: u64,
|
||||
globals: &super::super::globals::Globals,
|
||||
|
@ -90,9 +93,73 @@ impl RoomEdus {
|
|||
let mut prefix = room_id.to_string().as_bytes().to_vec();
|
||||
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
|
||||
.roomactiveid_roomactive
|
||||
.roomactiveid_userid
|
||||
.scan_prefix(&prefix)
|
||||
.filter_map(|r| r.ok())
|
||||
.filter(|(_, v)| v == user_id.as_bytes())
|
||||
{
|
||||
self.roomactiveid_userid.remove(outdated_edu.0)?;
|
||||
found_outdated = true;
|
||||
}
|
||||
|
||||
if found_outdated {
|
||||
self.roomid_lastroomactiveupdate.insert(
|
||||
&room_id.to_string().as_bytes(),
|
||||
&globals.next_count()?.to_be_bytes(),
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Makes sure that typing events with old timestamps get removed.
|
||||
fn roomactives_maintain(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
globals: &super::super::globals::Globals,
|
||||
) -> Result<()> {
|
||||
let mut prefix = room_id.to_string().as_bytes().to_vec();
|
||||
prefix.push(0xff);
|
||||
|
||||
let current_timestamp = utils::millis_since_unix_epoch();
|
||||
|
||||
let mut found_outdated = false;
|
||||
|
||||
// Find all outdated edus before inserting a new one
|
||||
for outdated_edu in self
|
||||
.roomactiveid_userid
|
||||
.scan_prefix(&prefix)
|
||||
.keys()
|
||||
.filter_map(|r| r.ok())
|
||||
|
@ -101,60 +168,59 @@ impl RoomEdus {
|
|||
k.split(|&c| c == 0xff)
|
||||
.nth(1)
|
||||
.expect("roomactive has valid timestamp and delimiters"),
|
||||
) < utils::millis_since_unix_epoch()
|
||||
) < current_timestamp
|
||||
})
|
||||
{
|
||||
// This is an outdated edu (time > timestamp)
|
||||
self.roomlatestid_roomlatest.remove(outdated_edu)?;
|
||||
found_outdated = true;
|
||||
}
|
||||
|
||||
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(&globals.next_count()?.to_be_bytes());
|
||||
|
||||
self.roomactiveid_roomactive
|
||||
.insert(room_active_id, &*serde_json::to_string(&event)?)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Removes an active event manually (before the timeout is reached).
|
||||
pub fn roomactive_remove(&self, event: EduEvent, room_id: &RoomId) -> Result<()> {
|
||||
let mut prefix = room_id.to_string().as_bytes().to_vec();
|
||||
prefix.push(0xff);
|
||||
|
||||
let json = serde_json::to_string(&event)?;
|
||||
|
||||
// Remove outdated entries
|
||||
for outdated_edu in self
|
||||
.roomactiveid_roomactive
|
||||
.scan_prefix(&prefix)
|
||||
.filter_map(|r| r.ok())
|
||||
.filter(|(_, v)| v == json.as_bytes())
|
||||
{
|
||||
self.roomactiveid_roomactive.remove(outdated_edu.0)?;
|
||||
if found_outdated {
|
||||
self.roomid_lastroomactiveupdate.insert(
|
||||
&room_id.to_string().as_bytes(),
|
||||
&globals.next_count()?.to_be_bytes(),
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns an iterator over all active events (e.g. typing notifications).
|
||||
pub fn roomactives_all(
|
||||
pub fn last_roomactive_update(
|
||||
&self,
|
||||
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();
|
||||
prefix.push(0xff);
|
||||
|
||||
let mut first_active_edu = prefix.clone();
|
||||
first_active_edu.extend_from_slice(&utils::millis_since_unix_epoch().to_be_bytes());
|
||||
let mut user_ids = Vec::new();
|
||||
|
||||
self.roomactiveid_roomactive
|
||||
.range(first_active_edu..)
|
||||
.filter_map(|r| r.ok())
|
||||
.take_while(move |(k, _)| k.starts_with(&prefix))
|
||||
.map(|(_, v)| Ok(serde_json::from_slice(&v)?))
|
||||
for user_id in self
|
||||
.roomactiveid_userid
|
||||
.scan_prefix(prefix)
|
||||
.values()
|
||||
.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`.
|
||||
|
|
|
@ -361,14 +361,12 @@ impl Users {
|
|||
|
||||
self.userdeviceid_devicekeys.scan_prefix(key).map(|r| {
|
||||
let (key, value) = r?;
|
||||
Ok((
|
||||
utils::string_from_bytes(
|
||||
key.rsplit(|&b| b == 0xff)
|
||||
.next()
|
||||
.ok_or(Error::BadDatabase("userdeviceid is invalid"))?,
|
||||
)?,
|
||||
serde_json::from_slice(&*value)?,
|
||||
))
|
||||
let userdeviceid = utils::string_from_bytes(
|
||||
key.rsplit(|&b| b == 0xff)
|
||||
.next()
|
||||
.ok_or(Error::BadDatabase("userdeviceid is invalid"))?,
|
||||
)?;
|
||||
Ok((userdeviceid, serde_json::from_slice(&*value)?))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
13
src/main.rs
13
src/main.rs
|
@ -6,12 +6,9 @@ mod database;
|
|||
mod error;
|
||||
mod pdu;
|
||||
mod ruma_wrapper;
|
||||
mod server_server;
|
||||
//mod server_server;
|
||||
mod utils;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
pub use database::Database;
|
||||
pub use error::{Error, Result};
|
||||
pub use pdu::PduEvent;
|
||||
|
@ -87,10 +84,10 @@ fn setup_rocket() -> rocket::Rocket {
|
|||
client_server::delete_device_route,
|
||||
client_server::delete_devices_route,
|
||||
client_server::options_route,
|
||||
server_server::well_known_server,
|
||||
server_server::get_server_version,
|
||||
server_server::get_server_keys,
|
||||
server_server::get_server_keys_deprecated,
|
||||
//server_server::well_known_server,
|
||||
//server_server::get_server_version,
|
||||
//server_server::get_server_keys,
|
||||
//server_server::get_server_keys_deprecated,
|
||||
],
|
||||
)
|
||||
.attach(AdHoc::on_attach("Config", |rocket| {
|
||||
|
|
124
src/test.rs
124
src/test.rs
|
@ -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 with invites
|
||||
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 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/leave can leave a room
|
||||
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 power_levels should not explode if the old power levels were empty
|
||||
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.member to myself
|
||||
Version responds 200 OK with valid structure
|
||||
|
@ -60,7 +47,6 @@ Can create filter
|
|||
Should reject keys claiming to belong to a different user
|
||||
Can add account data
|
||||
Checking local federation server
|
||||
Alternative server names do not cause a routing loop
|
||||
Can read configuration endpoint
|
||||
AS cannot create users outside its own namespace
|
||||
Changing the actions of an unknown default rule fails with 404
|
||||
|
@ -79,3 +65,15 @@ GET /events with non-numeric 'limit'
|
|||
GET /events with negative 'limit'
|
||||
GET /events with non-numeric 'timeout'
|
||||
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…
Reference in a new issue