Direct message rooms should be encrypted from creation (#29)

This commit is contained in:
Ulyssa 2023-03-03 16:37:11 -08:00
parent 0ed1d53946
commit 11625262f1
No known key found for this signature in database
GPG key ID: 1B3965A3D18B9B64
3 changed files with 110 additions and 9 deletions

View file

@ -131,6 +131,24 @@ pub enum MessageAction {
Unreact(Option<String>), Unreact(Option<String>),
} }
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum CreateRoomType {
/// A direct message room.
Direct(OwnedUserId),
}
bitflags::bitflags! {
pub struct CreateRoomFlags: u32 {
const NONE = 0b00000000;
/// Make the room public.
const PUBLIC = 0b00000001;
/// Encrypt this room.
const ENCRYPTED = 0b00000010;
}
}
bitflags::bitflags! { bitflags::bitflags! {
pub struct DownloadFlags: u32 { pub struct DownloadFlags: u32 {
const NONE = 0b00000000; const NONE = 0b00000000;

View file

@ -185,8 +185,16 @@ impl RoomState {
match act { match act {
RoomAction::InviteAccept => { RoomAction::InviteAccept => {
if let Some(room) = store.application.worker.client.get_invited_room(self.id()) { if let Some(room) = store.application.worker.client.get_invited_room(self.id()) {
let details = room.invite_details().await.map_err(IambError::from)?;
let details = details.invitee.event().original_content();
let is_direct = details.and_then(|ev| ev.is_direct).unwrap_or_default();
room.accept_invitation().await.map_err(IambError::from)?; room.accept_invitation().await.map_err(IambError::from)?;
if is_direct {
room.set_is_direct(true).await.map_err(IambError::from)?;
}
Ok(vec![]) Ok(vec![])
} else { } else {
Err(IambError::NotInvited.into()) Err(IambError::NotInvited.into())

View file

@ -24,6 +24,7 @@ use matrix_sdk::{
room::Visibility, room::Visibility,
space::get_hierarchy::v1::Request as SpaceHierarchyRequest, space::get_hierarchy::v1::Request as SpaceHierarchyRequest,
}, },
assign,
events::{ events::{
key::verification::{ key::verification::{
done::{OriginalSyncKeyVerificationDoneEvent, ToDeviceKeyVerificationDoneEvent}, done::{OriginalSyncKeyVerificationDoneEvent, ToDeviceKeyVerificationDoneEvent},
@ -35,16 +36,22 @@ use matrix_sdk::{
presence::PresenceEvent, presence::PresenceEvent,
reaction::ReactionEventContent, reaction::ReactionEventContent,
room::{ room::{
encryption::RoomEncryptionEventContent,
message::{MessageType, RoomMessageEventContent}, message::{MessageType, RoomMessageEventContent},
name::RoomNameEventContent, name::RoomNameEventContent,
redaction::{OriginalSyncRoomRedactionEvent, SyncRoomRedactionEvent}, redaction::{OriginalSyncRoomRedactionEvent, SyncRoomRedactionEvent},
}, },
tag::Tags, tag::Tags,
typing::SyncTypingEvent, typing::SyncTypingEvent,
AnyInitialStateEvent,
AnyTimelineEvent, AnyTimelineEvent,
EmptyStateKey,
InitialStateEvent,
SyncMessageLikeEvent, SyncMessageLikeEvent,
SyncStateEvent, SyncStateEvent,
}, },
serde::Raw,
EventEncryptionAlgorithm,
OwnedRoomId, OwnedRoomId,
OwnedRoomOrAliasId, OwnedRoomOrAliasId,
OwnedUserId, OwnedUserId,
@ -58,7 +65,16 @@ use matrix_sdk::{
use modalkit::editing::action::{EditInfo, InfoMessage, UIError}; use modalkit::editing::action::{EditInfo, InfoMessage, UIError};
use crate::{ use crate::{
base::{AsyncProgramStore, EventLocation, IambError, IambResult, Receipts, VerifyAction}, base::{
AsyncProgramStore,
CreateRoomFlags,
CreateRoomType,
EventLocation,
IambError,
IambResult,
Receipts,
VerifyAction,
},
message::MessageFetchResult, message::MessageFetchResult,
ApplicationSettings, ApplicationSettings,
}; };
@ -71,6 +87,69 @@ fn initial_devname() -> String {
format!("{} on {}", IAMB_DEVICE_NAME, gethostname().to_string_lossy()) format!("{} on {}", IAMB_DEVICE_NAME, gethostname().to_string_lossy())
} }
pub async fn create_room(
client: &Client,
room_alias_name: Option<&str>,
rt: CreateRoomType,
flags: CreateRoomFlags,
) -> IambResult<OwnedRoomId> {
let creation_content = None;
let mut initial_state = vec![];
let is_direct;
let preset;
let mut invite = vec![];
let visibility = if flags.contains(CreateRoomFlags::PUBLIC) {
Visibility::Public
} else {
Visibility::Private
};
match rt {
CreateRoomType::Direct(user) => {
invite.push(user);
is_direct = true;
preset = Some(RoomPreset::TrustedPrivateChat);
},
}
// Set up encryption.
if flags.contains(CreateRoomFlags::ENCRYPTED) {
// XXX: Once matrix-sdk uses ruma 0.8, then this can skip the cast.
let algo = EventEncryptionAlgorithm::MegolmV1AesSha2;
let content = RoomEncryptionEventContent::new(algo);
let encr = InitialStateEvent { content, state_key: EmptyStateKey };
let encr_raw = Raw::new(&encr).map_err(IambError::from)?;
let encr_raw = encr_raw.cast::<AnyInitialStateEvent>();
initial_state.push(encr_raw);
}
let request = assign!(CreateRoomRequest::new(), {
room_alias_name,
creation_content,
initial_state: initial_state.as_slice(),
invite: invite.as_slice(),
is_direct,
visibility,
preset,
});
let resp = client.create_room(request).await.map_err(IambError::from)?;
if is_direct {
if let Some(room) = client.get_room(&resp.room_id) {
room.set_is_direct(true).await.map_err(IambError::from)?;
} else {
error!(
room_id = resp.room_id.as_str(),
"Couldn't set is_direct for new direct message room"
);
}
}
return Ok(resp.room_id);
}
#[derive(Debug)] #[derive(Debug)]
pub enum LoginStyle { pub enum LoginStyle {
SessionRestore(Session), SessionRestore(Session),
@ -788,15 +867,11 @@ impl ClientWorker {
} }
} }
let mut request = CreateRoomRequest::new(); let rt = CreateRoomType::Direct(user.clone());
let invite = [user.clone()]; let flags = CreateRoomFlags::ENCRYPTED;
request.is_direct = true;
request.invite = &invite;
request.visibility = Visibility::Private;
request.preset = Some(RoomPreset::PrivateChat);
match self.client.create_room(request).await { match create_room(&self.client, None, rt, flags).await {
Ok(resp) => self.get_room(resp.room_id).await, Ok(room_id) => self.get_room(room_id).await,
Err(e) => { Err(e) => {
error!( error!(
user_id = user.as_str(), user_id = user.as_str(),