[fractal] verification: Move in-room verification outside of Timeline
- From: Julian Sparber <jsparber src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal] verification: Move in-room verification outside of Timeline
- Date: Tue, 26 Apr 2022 09:25:26 +0000 (UTC)
commit 1614ce91797149421cc855698df67abf743676fa
Author: Kévin Commaille <zecakeh tedomum fr>
Date: Fri Apr 22 20:17:38 2022 +0200
verification: Move in-room verification outside of Timeline
data/resources/ui/content-room-history.ui | 6 +-
src/session/room/mod.rs | 33 ++++-
src/session/room/timeline/mod.rs | 151 +++--------------------
src/session/verification/verification_list.rs | 171 ++++++++++++++++++++++----
4 files changed, 194 insertions(+), 167 deletions(-)
---
diff --git a/data/resources/ui/content-room-history.ui b/data/resources/ui/content-room-history.ui
index 921f3d5dc..90cd23d48 100644
--- a/data/resources/ui/content-room-history.ui
+++ b/data/resources/ui/content-room-history.ui
@@ -113,10 +113,8 @@
<child>
<object class="ContentVerificationInfoBar" id="verification_info_bar">
<binding name="request">
- <lookup name="verification" type="Timeline">
- <lookup name="timeline" type="Room">
- <lookup name="room">ContentRoomHistory</lookup>
- </lookup>
+ <lookup name="verification">
+ <lookup name="room">ContentRoomHistory</lookup>
</lookup>
</binding>
</object>
diff --git a/src/session/room/mod.rs b/src/session/room/mod.rs
index 9688e5975..28e913daa 100644
--- a/src/session/room/mod.rs
+++ b/src/session/room/mod.rs
@@ -57,6 +57,7 @@ pub use self::{
TimelineSpinner, TimelineState,
},
};
+use super::verification::IdentityVerification;
use crate::{
components::{Pill, Toast},
gettext_f, ngettext_f,
@@ -104,6 +105,8 @@ mod imp {
pub highlight: Cell<HighlightFlags>,
pub predecessor: OnceCell<Box<RoomId>>,
pub successor: OnceCell<Box<RoomId>>,
+ /// The most recent verification request event.
+ pub verification: RefCell<Option<IdentityVerification>>,
}
#[glib::object_subclass]
@@ -228,6 +231,13 @@ mod imp {
None,
glib::ParamFlags::READABLE,
),
+ glib::ParamSpecObject::new(
+ "verification",
+ "Verification",
+ "The most recent active verification for a user in this room",
+ IdentityVerification::static_type(),
+ glib::ParamFlags::READWRITE,
+ ),
]
});
@@ -262,6 +272,7 @@ mod imp {
let topic = value.get().unwrap();
obj.store_topic(topic);
}
+ "verification" => obj.set_verification(value.get().unwrap()),
_ => unimplemented!(),
}
}
@@ -295,6 +306,7 @@ mod imp {
},
|id| id.as_ref().to_value(),
),
+ "verification" => obj.verification().to_value(),
_ => unimplemented!(),
}
}
@@ -1031,8 +1043,13 @@ impl Room {
// FIXME: notify only when the count has changed
self.notify_notification_count();
- for event in batch.iter().flat_map(|e| e.event.deserialize().ok()) {
- match &event {
+ let events: Vec<_> = batch
+ .iter()
+ .flat_map(|e| e.event.deserialize().ok())
+ .collect();
+
+ for event in events.iter() {
+ match event {
AnySyncRoomEvent::State(AnySyncStateEvent::RoomMember(event)) => {
self.members().update_member_for_member_event(event)
}
@@ -1055,6 +1072,9 @@ impl Room {
_ => {}
}
}
+ self.session()
+ .verification_list()
+ .handle_response_room(self, events.iter());
self.emit_by_name::<()>("order-changed", &[]);
}
@@ -1512,6 +1532,15 @@ impl Room {
error!("Can’t invite users, because this room isn’t a joined room");
}
}
+
+ pub fn set_verification(&self, verification: IdentityVerification) {
+ self.imp().verification.replace(Some(verification));
+ self.notify("verification");
+ }
+
+ pub fn verification(&self) -> Option<IdentityVerification> {
+ self.imp().verification.borrow().clone()
+ }
}
trait GlibDateTime {
diff --git a/src/session/room/timeline/mod.rs b/src/session/room/timeline/mod.rs
index ad14c91b1..aaa6de3bf 100644
--- a/src/session/room/timeline/mod.rs
+++ b/src/session/room/timeline/mod.rs
@@ -14,10 +14,7 @@ use gtk::{gio, glib, prelude::*, subclass::prelude::*};
use log::{error, warn};
use matrix_sdk::{
deserialized_responses::SyncRoomEvent,
- ruma::{
- events::{room::message::MessageType, AnySyncMessageLikeEvent, AnySyncRoomEvent},
- EventId, TransactionId,
- },
+ ruma::{EventId, TransactionId},
Error as MatrixError,
};
pub use timeline_day_divider::TimelineDayDivider;
@@ -27,11 +24,7 @@ pub use timeline_spinner::TimelineSpinner;
use tokio::task::JoinHandle;
use crate::{
- session::{
- room::{Event, Room},
- user::UserExt,
- verification::{IdentityVerification, VERIFICATION_CREATION_TIMEOUT},
- },
+ session::room::{Event, Room},
spawn_tokio,
};
@@ -79,8 +72,6 @@ mod imp {
/// A Hashset of `EventId`s that where just redacted.
pub redacted_events: RefCell<HashSet<Box<EventId>>>,
pub state: Cell<TimelineState>,
- /// The most recent verification request event
- pub verification: RefCell<Option<IdentityVerification>>,
pub backward_stream: Arc<Mutex<Option<BackwardStream>>>,
pub forward_handle: Arc<Mutex<Option<JoinHandle<()>>>>,
}
@@ -118,13 +109,6 @@ mod imp {
TimelineState::default() as i32,
glib::ParamFlags::READABLE,
),
- glib::ParamSpecObject::new(
- "verification",
- "Verification",
- "The most recent active verification for a user in this timeline",
- IdentityVerification::static_type(),
- glib::ParamFlags::READABLE,
- ),
]
});
@@ -152,7 +136,6 @@ mod imp {
"room" => obj.room().to_value(),
"empty" => obj.is_empty().to_value(),
"state" => obj.state().to_value(),
- "verification" => obj.verification().to_value(),
_ => unimplemented!(),
}
}
@@ -571,7 +554,7 @@ impl Timeline {
match handle.await.unwrap() {
Ok(Some(events)) => {
- let events: Vec<Event> = events
+ let events: Vec<_> = events
.into_iter()
.filter_map(|event| match event {
Ok(event) => Some(event),
@@ -580,7 +563,20 @@ impl Timeline {
None
}
})
- .map(|event| Event::new(event, &self.room()))
+ .collect();
+
+ let deser_events: Vec<_> = events
+ .iter()
+ .filter_map(|event| event.event.deserialize().ok())
+ .collect();
+ let room = self.room();
+ room.session()
+ .verification_list()
+ .handle_response_room(&room, deser_events.iter());
+
+ let events: Vec<Event> = events
+ .into_iter()
+ .map(|event| Event::new(event, &room))
.collect();
self.remove_loading_spinner();
@@ -670,8 +666,6 @@ impl Timeline {
for event in batch.into_iter() {
let event_id = event.matrix_event_id();
- self.handle_verification(&event);
-
if let Some(pending_id) = event
.matrix_transaction_id()
.and_then(|txn_id| pending_events.remove(&txn_id))
@@ -784,8 +778,6 @@ impl Timeline {
priv_.list.borrow_mut().reserve(added);
for event in batch {
- self.handle_verification(&event);
-
priv_
.event_map
.borrow_mut()
@@ -847,115 +839,6 @@ impl Timeline {
self.imp().list.borrow_mut().pop_front();
self.upcast_ref::<gio::ListModel>().items_changed(0, 1, 0);
}
-
- fn set_verification(&self, verification: IdentityVerification) {
- self.imp().verification.replace(Some(verification));
- self.notify("verification");
- }
-
- pub fn verification(&self) -> Option<IdentityVerification> {
- self.imp().verification.borrow().clone()
- }
-
- fn handle_verification(&self, event: &Event) {
- let message = if let Some(AnySyncRoomEvent::MessageLike(message)) = event.matrix_event() {
- message
- } else {
- return;
- };
-
- let session = self.room().session();
- let verification_list = session.verification_list();
-
- let request = match message {
- AnySyncMessageLikeEvent::RoomMessage(message) => {
- if let MessageType::VerificationRequest(request) = message.content.msgtype {
- // Ignore request that are too old
- if let Some(time) = message.origin_server_ts.to_system_time() {
- if let Ok(duration) = time.elapsed() {
- if duration > VERIFICATION_CREATION_TIMEOUT {
- return;
- }
- } else {
- warn!("Ignoring verification request because it was sent in the future. The
system time of the server or the local machine is probably wrong.");
- return;
- }
- } else {
- return;
- }
-
- let user = session.user().unwrap();
-
- let user_to_verify = if *request.to == *user.user_id() {
- // The request was sent by another user to verify us
- event.sender()
- } else if *message.sender == *user.user_id() {
- // The request was sent by us to verify another user
- self.room().members().member_by_id(request.to.into())
- } else {
- // Ignore the request when it doesn't verify us or wasn't set by us
- return;
- };
-
- // Ignore the request when we have a newer one
- let previous_verification = self.verification();
- if !(previous_verification.is_none()
- || &event.timestamp() > previous_verification.unwrap().start_time())
- {
- return;
- }
-
- let request = if let Some(request) = verification_list
- .get_by_id(&user_to_verify.user_id(), &event.matrix_event_id())
- {
- request
- } else {
- let request = IdentityVerification::for_flow_id(
- event.matrix_event_id().as_str(),
- &session,
- &user_to_verify.upcast(),
- &event.timestamp(),
- );
-
- verification_list.add(request.clone());
- request
- };
-
- self.set_verification(request);
- }
-
- return;
- }
- AnySyncMessageLikeEvent::KeyVerificationReady(e) => {
- verification_list.get_by_id(&e.sender, &e.content.relates_to.event_id)
- }
- AnySyncMessageLikeEvent::KeyVerificationStart(e) => {
- verification_list.get_by_id(&e.sender, &e.content.relates_to.event_id)
- }
- AnySyncMessageLikeEvent::KeyVerificationCancel(e) => {
- verification_list.get_by_id(&e.sender, &e.content.relates_to.event_id)
- }
- AnySyncMessageLikeEvent::KeyVerificationAccept(e) => {
- verification_list.get_by_id(&e.sender, &e.content.relates_to.event_id)
- }
- AnySyncMessageLikeEvent::KeyVerificationKey(e) => {
- verification_list.get_by_id(&e.sender, &e.content.relates_to.event_id)
- }
- AnySyncMessageLikeEvent::KeyVerificationMac(e) => {
- verification_list.get_by_id(&e.sender, &e.content.relates_to.event_id)
- }
- AnySyncMessageLikeEvent::KeyVerificationDone(e) => {
- verification_list.get_by_id(&e.sender, &e.content.relates_to.event_id)
- }
- _ => {
- return;
- }
- };
-
- if let Some(request) = request {
- request.notify_state();
- }
- }
}
async fn handle_forward_stream(
diff --git a/src/session/verification/verification_list.rs b/src/session/verification/verification_list.rs
index bbe3da93d..3f4e76489 100644
--- a/src/session/verification/verification_list.rs
+++ b/src/session/verification/verification_list.rs
@@ -3,13 +3,17 @@ use std::sync::Arc;
use gtk::{gio, glib, glib::clone, prelude::*, subclass::prelude::*};
use log::{debug, warn};
use matrix_sdk::ruma::{
- api::client::sync::sync_events::v3::ToDevice, events::AnyToDeviceEvent, UserId,
+ api::client::sync::sync_events::v3::ToDevice,
+ events::{
+ room::message::MessageType, AnySyncMessageLikeEvent, AnySyncRoomEvent, AnyToDeviceEvent,
+ },
+ MilliSecondsSinceUnixEpoch, UserId,
};
use crate::session::{
user::UserExt,
verification::{IdentityVerification, VERIFICATION_CREATION_TIMEOUT},
- Session,
+ Room, Session,
};
#[derive(Hash, PartialEq, Eq, Debug)]
@@ -135,7 +139,7 @@ impl VerificationList {
pub fn handle_response_to_device(&self, to_device: ToDevice) {
for event in to_device.events.iter().filter_map(|e| e.deserialize().ok()) {
- debug!("Received verification event: {:?}", event);
+ debug!("Received to-device verification event: {:?}", event);
let request = match event {
AnyToDeviceEvent::KeyVerificationRequest(e) => {
if let Some(request) = self.get_by_id(&e.sender, &e.content.transaction_id) {
@@ -149,32 +153,13 @@ impl VerificationList {
continue;
}
- // Ignore request that are too old
- let start_time = if let Some(time) = e.content.timestamp.to_system_time() {
- if let Ok(duration) = time.elapsed() {
- if duration > VERIFICATION_CREATION_TIMEOUT {
- debug!("Received verification event that already timedout");
- continue;
- }
-
- if let Ok(time) = glib::DateTime::from_unix_utc(
- e.content.timestamp.as_secs().into(),
- )
- .and_then(|t| t.to_local())
- {
- time
- } else {
- warn!("Ignore verification request because getting a correct timestamp
failed");
- continue;
- }
+ // Ignore requests that are too old
+ let start_time =
+ if let Some(time) = start_time_from_timestamp(&e.content.timestamp) {
+ time
} else {
- warn!("Ignore verification request because it was sent in the future. The
system time of the server or the local machine is probably wrong.");
continue;
- }
- } else {
- warn!("Ignore verification request because getting a correct timestamp failed");
- continue;
- };
+ };
let request = IdentityVerification::for_flow_id(
e.content.transaction_id.as_str(),
@@ -217,6 +202,113 @@ impl VerificationList {
}
}
+ pub fn handle_response_room<'a>(
+ &self,
+ room: &Room,
+ events: impl Iterator<Item = &'a AnySyncRoomEvent>,
+ ) {
+ for message_event in events.filter_map(|event| {
+ if let AnySyncRoomEvent::MessageLike(message_event) = event {
+ Some(message_event)
+ } else {
+ None
+ }
+ }) {
+ let request = match message_event {
+ AnySyncMessageLikeEvent::RoomMessage(message) => {
+ if let MessageType::VerificationRequest(request) = &message.content.msgtype {
+ debug!("Received in-room verification event: {:?}", message);
+ // Ignore request that are too old
+ let start_time = if let Some(time) =
+ start_time_from_timestamp(&message.origin_server_ts)
+ {
+ time
+ } else {
+ continue;
+ };
+
+ let session = self.session();
+ let user = session.user().unwrap();
+
+ let user_to_verify = if *request.to == *user.user_id() {
+ // The request was sent by another user to verify us
+ room.members().member_by_id(message.sender.clone().into())
+ } else if *message.sender == *user.user_id() {
+ // The request was sent by us to verify another user
+ room.members().member_by_id(request.to.clone().into())
+ } else {
+ // Ignore the request when it doesn't verify us or wasn't set by us
+ continue;
+ };
+
+ // Ignore the request when we have a newer one
+ let previous_verification = room.verification();
+ if !(previous_verification.is_none()
+ || &start_time > previous_verification.unwrap().start_time())
+ {
+ continue;
+ }
+
+ let request = if let Some(request) =
+ self.get_by_id(&user_to_verify.user_id(), &message.event_id)
+ {
+ request
+ } else {
+ let request = IdentityVerification::for_flow_id(
+ message.event_id.as_str(),
+ &session,
+ &user_to_verify.upcast(),
+ &start_time,
+ );
+
+ self.add(request.clone());
+ request
+ };
+
+ room.set_verification(request);
+ }
+
+ continue;
+ }
+ AnySyncMessageLikeEvent::KeyVerificationReady(e) => {
+ debug!("Received in-room verification event: {:?}", e);
+ self.get_by_id(&e.sender, &e.content.relates_to.event_id)
+ }
+ AnySyncMessageLikeEvent::KeyVerificationStart(e) => {
+ debug!("Received in-room verification event: {:?}", e);
+ self.get_by_id(&e.sender, &e.content.relates_to.event_id)
+ }
+ AnySyncMessageLikeEvent::KeyVerificationCancel(e) => {
+ debug!("Received in-room verification event: {:?}", e);
+ self.get_by_id(&e.sender, &e.content.relates_to.event_id)
+ }
+ AnySyncMessageLikeEvent::KeyVerificationAccept(e) => {
+ debug!("Received in-room verification event: {:?}", e);
+ self.get_by_id(&e.sender, &e.content.relates_to.event_id)
+ }
+ AnySyncMessageLikeEvent::KeyVerificationKey(e) => {
+ debug!("Received in-room verification event: {:?}", e);
+ self.get_by_id(&e.sender, &e.content.relates_to.event_id)
+ }
+ AnySyncMessageLikeEvent::KeyVerificationMac(e) => {
+ debug!("Received in-room verification event: {:?}", e);
+ self.get_by_id(&e.sender, &e.content.relates_to.event_id)
+ }
+ AnySyncMessageLikeEvent::KeyVerificationDone(e) => {
+ debug!("Received in-room verification event: {:?}", e);
+ self.get_by_id(&e.sender, &e.content.relates_to.event_id)
+ }
+ _ => {
+ continue;
+ }
+ };
+
+ if let Some(request) = request {
+ request.notify_state();
+ }
+ }
+ }
+
/// Add a new `IdentityVerification` request
pub fn add(&self, request: IdentityVerification) {
// Don't add requests that are already finished
@@ -287,3 +379,28 @@ impl VerificationList {
None
}
}
+
+fn start_time_from_timestamp(timestamp: &MilliSecondsSinceUnixEpoch) -> Option<glib::DateTime> {
+ if let Some(time) = timestamp.to_system_time() {
+ if let Ok(duration) = time.elapsed() {
+ if duration > VERIFICATION_CREATION_TIMEOUT {
+ debug!("Received verification event that already timedout");
+ return None;
+ }
+
+ if let Ok(time) =
+ glib::DateTime::from_unix_utc(timestamp.as_secs().into()).and_then(|t| t.to_local())
+ {
+ return Some(time);
+ } else {
+ warn!("Ignore verification request because getting a correct timestamp failed");
+ }
+ } else {
+ warn!("Ignore verification request because it was sent in the future. The system time of the
server or the local machine is probably wrong.");
+ }
+ } else {
+ warn!("Ignore verification request because getting a correct timestamp failed");
+ }
+
+ None
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]