[fractal/fractal-next] verification: Add support for user verification
- From: Julian Sparber <jsparber src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal/fractal-next] verification: Add support for user verification
- Date: Thu, 13 Jan 2022 14:34:40 +0000 (UTC)
commit 7104a1c45389b8d6131e5b3efb20315fcadab136
Author: Julian Sparber <julian sparber net>
Date: Fri Dec 17 16:08:29 2021 +0100
verification: Add support for user verification
src/session/room/timeline.rs | 128 ++++++++++++++++++++++++++++++++++-
src/session/sidebar/category_type.rs | 2 +-
src/session/verification/mod.rs | 2 +-
3 files changed, 127 insertions(+), 5 deletions(-)
---
diff --git a/src/session/room/timeline.rs b/src/session/room/timeline.rs
index 1d96a15d..7da6b202 100644
--- a/src/session/room/timeline.rs
+++ b/src/session/room/timeline.rs
@@ -1,17 +1,23 @@
use std::collections::HashMap;
use gtk::{gio, glib, glib::clone, prelude::*, subclass::prelude::*};
-use log::error;
+use log::{error, warn};
use matrix_sdk::{
ruma::{
api::client::r0::message::get_message_events::Direction,
- events::{AnySyncRoomEvent, AnySyncStateEvent},
+ events::{
+ room::message::MessageType, AnySyncMessageEvent, AnySyncRoomEvent, AnySyncStateEvent,
+ },
identifiers::EventId,
},
uuid::Uuid,
};
-use crate::session::room::{Event, Item, ItemType, Room};
+use crate::session::{
+ room::{Event, Item, ItemType, Room},
+ user::UserExt,
+ verification::{FlowId, IdentityVerification, VERIFICATION_CREATION_TIMEOUT},
+};
use crate::{spawn, spawn_tokio};
mod imp {
@@ -35,6 +41,8 @@ mod imp {
pub loading: Cell<bool>,
pub complete: Cell<bool>,
pub oldest_event: RefCell<Option<EventId>>,
+ /// The most recent verification reuqest event
+ pub verification: RefCell<Option<IdentityVerification>>,
}
#[glib::object_subclass]
@@ -77,6 +85,13 @@ mod imp {
false,
glib::ParamFlags::READABLE,
),
+ glib::ParamSpec::new_object(
+ "verification",
+ "Verification",
+ "The most recent active verification for a user in this timeline",
+ IdentityVerification::static_type(),
+ glib::ParamFlags::READABLE,
+ ),
]
});
@@ -105,6 +120,7 @@ mod imp {
"loading" => obj.loading().to_value(),
"empty" => obj.is_empty().to_value(),
"complete" => obj.is_complete().to_value(),
+ "verification" => obj.verification().to_value(),
_ => unimplemented!(),
}
}
@@ -399,6 +415,8 @@ 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))
@@ -488,6 +506,8 @@ impl Timeline {
priv_.list.borrow_mut().reserve(added);
for event in batch {
+ self.handle_verification(&event);
+
priv_
.event_map
.borrow_mut()
@@ -623,4 +643,106 @@ impl Timeline {
})
);
}
+
+ fn set_verification(&self, verification: IdentityVerification) {
+ let priv_ = imp::Timeline::from_instance(self);
+
+ priv_.verification.replace(Some(verification));
+ self.notify("verification");
+ }
+
+ pub fn verification(&self) -> Option<IdentityVerification> {
+ let priv_ = imp::Timeline::from_instance(self);
+
+ priv_.verification.borrow().clone()
+ }
+
+ fn handle_verification(&self, event: &Event) {
+ let message = if let Some(AnySyncRoomEvent::Message(message)) = event.matrix_event() {
+ message
+ } else {
+ return;
+ };
+
+ let session = self.room().session();
+
+ let flow_id = match message {
+ AnySyncMessageEvent::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)
+ } else {
+ // Ignore the request when it doesn't verify us or wasn't set by us
+ return;
+ };
+
+ let request = IdentityVerification::for_flow_id(
+ event.matrix_event_id().as_str(),
+ &session,
+ &user_to_verify.upcast(),
+ &event.timestamp(),
+ );
+
+ // Ignore the request when we have a newer one
+ let previous_verification = self.verification();
+ if previous_verification.is_none()
+ || request.start_time() > previous_verification.unwrap().start_time()
+ {
+ session.verification_list().add(request.clone());
+ self.set_verification(request);
+ }
+ }
+
+ return;
+ }
+ AnySyncMessageEvent::KeyVerificationReady(e) => {
+ FlowId::new(e.sender, e.content.relates_to.event_id.to_string())
+ }
+ AnySyncMessageEvent::KeyVerificationStart(e) => {
+ FlowId::new(e.sender, e.content.relates_to.event_id.to_string())
+ }
+ AnySyncMessageEvent::KeyVerificationCancel(e) => {
+ FlowId::new(e.sender, e.content.relates_to.event_id.to_string())
+ }
+ AnySyncMessageEvent::KeyVerificationAccept(e) => {
+ FlowId::new(e.sender, e.content.relates_to.event_id.to_string())
+ }
+ AnySyncMessageEvent::KeyVerificationKey(e) => {
+ FlowId::new(e.sender, e.content.relates_to.event_id.to_string())
+ }
+ AnySyncMessageEvent::KeyVerificationMac(e) => {
+ FlowId::new(e.sender, e.content.relates_to.event_id.to_string())
+ }
+ AnySyncMessageEvent::KeyVerificationDone(e) => {
+ FlowId::new(e.sender, e.content.relates_to.event_id.to_string())
+ }
+ _ => {
+ return;
+ }
+ };
+
+ if let Some(request) = session.verification_list().get_by_id(&flow_id) {
+ request.notify_state();
+ }
+ }
}
diff --git a/src/session/sidebar/category_type.rs b/src/session/sidebar/category_type.rs
index b5a23d08..f64edc20 100644
--- a/src/session/sidebar/category_type.rs
+++ b/src/session/sidebar/category_type.rs
@@ -24,7 +24,7 @@ impl Default for CategoryType {
impl ToString for CategoryType {
fn to_string(&self) -> String {
match self {
- CategoryType::VerificationRequest => gettext("Login Requests"),
+ CategoryType::VerificationRequest => gettext("Verifications"),
CategoryType::Invited => gettext("Invited"),
CategoryType::Favorite => gettext("Favorite"),
CategoryType::Normal => gettext("Rooms"),
diff --git a/src/session/verification/mod.rs b/src/session/verification/mod.rs
index a25fd89f..aa355ff5 100644
--- a/src/session/verification/mod.rs
+++ b/src/session/verification/mod.rs
@@ -2,7 +2,7 @@ mod identity_verification;
mod verification_list;
pub use self::identity_verification::{IdentityVerification, Mode as VerificationMode, SasData};
-pub use self::verification_list::VerificationList;
+pub use self::verification_list::{FlowId, VerificationList};
use std::time::Duration;
/// The time a verification is valid after it's creation.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]