|
|
|
|
@ -4,6 +4,7 @@ use std::{
@@ -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::{
@@ -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::{
@@ -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(
@@ -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(
@@ -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(
@@ -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(
@@ -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(
@@ -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(
@@ -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(
@@ -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(
@@ -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(
@@ -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(
@@ -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(
@@ -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(
@@ -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(
@@ -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(
@@ -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(
@@ -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(
@@ -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(
@@ -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(
@@ -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(), |
|
|
|
|
|