Merge branch 'improvements' into 'master'

Implement /devices

Closes #62

See merge request famedly/conduit!64
next
Timo Kösters 2021-04-21 09:03:18 +00:00
commit 14c7ecf722
5 changed files with 76 additions and 5 deletions

View File

@ -152,6 +152,13 @@ pub async fn invite_user_route(
let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let sender_user = body.sender_user.as_ref().expect("user is authenticated");
if let invite_user::IncomingInvitationRecipient::UserId { user_id } = &body.recipient { if let invite_user::IncomingInvitationRecipient::UserId { user_id } = &body.recipient {
if body.room_id.server_name() != db.globals.server_name() {
return Err(Error::BadRequest(
ErrorKind::Forbidden,
"Inviting users from other homeservers is not implemented yet.",
));
}
db.rooms.build_and_append_pdu( db.rooms.build_and_append_pdu(
PduBuilder { PduBuilder {
event_type: EventType::RoomMember, event_type: EventType::RoomMember,

View File

@ -123,6 +123,7 @@ impl Database {
userid_avatarurl: db.open_tree("userid_avatarurl")?, userid_avatarurl: db.open_tree("userid_avatarurl")?,
userdeviceid_token: db.open_tree("userdeviceid_token")?, userdeviceid_token: db.open_tree("userdeviceid_token")?,
userdeviceid_metadata: db.open_tree("userdeviceid_metadata")?, userdeviceid_metadata: db.open_tree("userdeviceid_metadata")?,
userid_devicelistversion: db.open_tree("userid_devicelistversion")?,
token_userdeviceid: db.open_tree("token_userdeviceid")?, token_userdeviceid: db.open_tree("token_userdeviceid")?,
onetimekeyid_onetimekeys: db.open_tree("onetimekeyid_onetimekeys")?, onetimekeyid_onetimekeys: db.open_tree("onetimekeyid_onetimekeys")?,
userid_lastonetimekeyupdate: db.open_tree("userid_lastonetimekeyupdate")?, userid_lastonetimekeyupdate: db.open_tree("userid_lastonetimekeyupdate")?,

View File

@ -22,6 +22,7 @@ pub struct Users {
pub(super) userid_avatarurl: sled::Tree, pub(super) userid_avatarurl: sled::Tree,
pub(super) userdeviceid_token: sled::Tree, pub(super) userdeviceid_token: sled::Tree,
pub(super) userdeviceid_metadata: sled::Tree, // This is also used to check if a device exists pub(super) userdeviceid_metadata: sled::Tree, // This is also used to check if a device exists
pub(super) userid_devicelistversion: sled::Tree, // DevicelistVersion = u64
pub(super) token_userdeviceid: sled::Tree, pub(super) token_userdeviceid: sled::Tree,
pub(super) onetimekeyid_onetimekeys: sled::Tree, // OneTimeKeyId = UserId + DeviceKeyId pub(super) onetimekeyid_onetimekeys: sled::Tree, // OneTimeKeyId = UserId + DeviceKeyId
@ -189,6 +190,10 @@ impl Users {
userdeviceid.push(0xff); userdeviceid.push(0xff);
userdeviceid.extend_from_slice(device_id.as_bytes()); userdeviceid.extend_from_slice(device_id.as_bytes());
self.userid_devicelistversion
.update_and_fetch(&user_id.as_bytes(), utils::increment)?
.expect("utils::increment will always put in a value");
self.userdeviceid_metadata.insert( self.userdeviceid_metadata.insert(
userdeviceid, userdeviceid,
serde_json::to_string(&Device { serde_json::to_string(&Device {
@ -227,6 +232,10 @@ impl Users {
// TODO: Remove onetimekeys // TODO: Remove onetimekeys
self.userid_devicelistversion
.update_and_fetch(&user_id.as_bytes(), utils::increment)?
.expect("utils::increment will always put in a value");
self.userdeviceid_metadata.remove(&userdeviceid)?; self.userdeviceid_metadata.remove(&userdeviceid)?;
Ok(()) Ok(())
@ -811,6 +820,10 @@ impl Users {
// Only existing devices should be able to call this. // Only existing devices should be able to call this.
assert!(self.userdeviceid_metadata.get(&userdeviceid)?.is_some()); assert!(self.userdeviceid_metadata.get(&userdeviceid)?.is_some());
self.userid_devicelistversion
.update_and_fetch(&user_id.as_bytes(), utils::increment)?
.expect("utils::increment will always put in a value");
self.userdeviceid_metadata.insert( self.userdeviceid_metadata.insert(
userdeviceid, userdeviceid,
serde_json::to_string(device) serde_json::to_string(device)
@ -840,6 +853,16 @@ impl Users {
}) })
} }
pub fn get_devicelist_version(&self, user_id: &UserId) -> Result<Option<u64>> {
self.userid_devicelistversion
.get(user_id.as_bytes())?
.map_or(Ok(None), |bytes| {
utils::u64_from_bytes(&bytes)
.map_err(|_| Error::bad_database("Invalid devicelistversion in db."))
.map(Some)
})
}
pub fn all_devices_metadata(&self, user_id: &UserId) -> impl Iterator<Item = Result<Device>> { pub fn all_devices_metadata(&self, user_id: &UserId) -> impl Iterator<Item = Result<Device>> {
let mut key = user_id.as_bytes().to_vec(); let mut key = user_id.as_bytes().to_vec();
key.push(0xff); key.push(0xff);

View File

@ -171,6 +171,7 @@ fn setup_rocket() -> (rocket::Rocket, Config) {
server_server::create_join_event_template_route, server_server::create_join_event_template_route,
server_server::create_join_event_route, server_server::create_join_event_route,
server_server::create_invite_route, server_server::create_invite_route,
server_server::get_devices_route,
server_server::get_room_information_route, server_server::get_room_information_route,
server_server::get_profile_information_route, server_server::get_profile_information_route,
], ],

View File

@ -8,6 +8,7 @@ use ruma::{
api::{ api::{
client::error::ErrorKind, client::error::ErrorKind,
federation::{ federation::{
device::get_devices::{self, v1::UserDevice},
directory::{get_public_rooms, get_public_rooms_filtered}, directory::{get_public_rooms, get_public_rooms_filtered},
discovery::{ discovery::{
get_remote_server_keys, get_server_keys, get_server_version, ServerSigningKeys, get_remote_server_keys, get_server_keys, get_server_version, ServerSigningKeys,
@ -861,8 +862,6 @@ fn handle_incoming_pdu<'a>(
.collect(), .collect(),
); );
} }
&state_at_incoming_event;
// TODO: set incoming_auth_events? // TODO: set incoming_auth_events?
} }
@ -1859,12 +1858,12 @@ pub async fn create_join_event_route<'a>(
auth_chain: auth_chain_ids auth_chain: auth_chain_ids
.iter() .iter()
.filter_map(|id| db.rooms.get_pdu_json(&id).ok().flatten()) .filter_map(|id| db.rooms.get_pdu_json(&id).ok().flatten())
.map(|json| PduEvent::convert_to_outgoing_federation_event(json)) .map(PduEvent::convert_to_outgoing_federation_event)
.collect(), .collect(),
state: state_ids state: state_ids
.iter() .iter()
.filter_map(|id| db.rooms.get_pdu_json(&id).ok().flatten()) .filter_map(|id| db.rooms.get_pdu_json(&id).ok().flatten())
.map(|json| PduEvent::convert_to_outgoing_federation_event(json)) .map(PduEvent::convert_to_outgoing_federation_event)
.collect(), .collect(),
}, },
} }
@ -1979,6 +1978,46 @@ pub async fn create_invite_route<'a>(
.into()) .into())
} }
#[cfg_attr(
feature = "conduit_bin",
get("/_matrix/federation/v1/user/devices/<_>", data = "<body>")
)]
#[tracing::instrument(skip(db, body))]
pub fn get_devices_route<'a>(
db: State<'a, Database>,
body: Ruma<get_devices::v1::Request<'_>>,
) -> ConduitResult<get_devices::v1::Response> {
if !db.globals.allow_federation() {
return Err(Error::bad_config("Federation is disabled."));
}
Ok(get_devices::v1::Response {
user_id: body.user_id.clone(),
stream_id: db
.users
.get_devicelist_version(&body.user_id)?
.unwrap_or(0)
.try_into()
.expect("version will not grow that large"),
devices: db
.users
.all_devices_metadata(&body.user_id)
.filter_map(|r| r.ok())
.filter_map(|metadata| {
Some(UserDevice {
keys: db
.users
.get_device_keys(&body.user_id, &metadata.device_id)
.ok()??,
device_id: metadata.device_id,
device_display_name: metadata.display_name,
})
})
.collect(),
}
.into())
}
#[cfg_attr( #[cfg_attr(
feature = "conduit_bin", feature = "conduit_bin",
get("/_matrix/federation/v1/query/directory", data = "<body>") get("/_matrix/federation/v1/query/directory", data = "<body>")
@ -1995,7 +2034,7 @@ pub fn get_room_information_route<'a>(
let room_id = db let room_id = db
.rooms .rooms
.id_from_alias(&body.room_alias)? .id_from_alias(&body.room_alias)?
.ok_or_else(|| Error::BadRequest(ErrorKind::NotFound, "Room alias not found."))?; .ok_or(Error::BadRequest(ErrorKind::NotFound, "Room alias not found."))?;
Ok(get_room_information::v1::Response { Ok(get_room_information::v1::Response {
room_id, room_id,