Browse Source

verification: Refactor and clean up

af/unable-to-decryt-styling
Kévin Commaille 11 months ago
parent
commit
a2cc7999c3
No known key found for this signature in database
GPG Key ID: C971D9DBC9D678D
  1. 793
      src/session/model/verification/identity_verification.rs
  2. 262
      src/session/model/verification/verification_list.rs

793
src/session/model/verification/identity_verification.rs

File diff suppressed because it is too large Load Diff

262
src/session/model/verification/verification_list.rs

@ -32,7 +32,7 @@ mod imp {
pub(super) list: RefCell<IndexMap<VerificationKey, IdentityVerification>>,
/// The current session.
#[property(get, construct_only)]
pub session: glib::WeakRef<Session>,
session: glib::WeakRef<Session>,
}
#[glib::object_subclass]
@ -67,6 +67,129 @@ mod imp {
.map(|(_, item)| item.clone().upcast())
}
}
impl VerificationList {
/// Add a verification received via a to-device event.
pub(super) async fn add_to_device_request(&self, request: VerificationRequest) {
if request.is_done() || request.is_cancelled() || request.is_passive() {
// Ignore requests that are already finished.
return;
}
let Some(session) = self.session.upgrade() else {
return;
};
let verification = IdentityVerification::new(request, &session.user(), None).await;
self.add(verification.clone());
if verification.state() == VerificationState::Requested {
session
.notifications()
.show_to_device_identity_verification(&verification)
.await;
}
}
/// Add a verification received via an in-room event.
pub(super) async fn add_in_room_request(
&self,
request: VerificationRequest,
room_id: &RoomId,
) {
if request.is_done() || request.is_cancelled() || request.is_passive() {
// Ignore requests that are already finished.
return;
}
let Some(session) = self.session.upgrade() else {
return;
};
let Some(room) = session.room_list().get(room_id) else {
error!(
"Room for verification request `({}, {})` not found",
request.other_user_id(),
request.flow_id()
);
return;
};
if matches!(
room.own_member().membership(),
Membership::Leave | Membership::Ban
) {
// Ignore requests where the user is not in the room anymore.
return;
}
let other_user_id = request.other_user_id().to_owned();
let member = room.members().map_or_else(
|| Member::new(&room, other_user_id.clone()),
|l| l.get_or_create(other_user_id.clone()),
);
// Ensure the member is up-to-date.
let matrix_room = room.matrix_room().clone();
let handle =
spawn_tokio!(async move { matrix_room.get_member_no_sync(&other_user_id).await });
match handle.await.expect("task was not aborted") {
Ok(Some(matrix_member)) => member.update_from_room_member(&matrix_member),
Ok(None) => {
error!(
"Room member for verification request `({}, {})` not found",
request.other_user_id(),
request.flow_id()
);
return;
}
Err(error) => {
error!(
"Could not get room member for verification request `({}, {})`: {error}",
request.other_user_id(),
request.flow_id()
);
return;
}
}
let verification =
IdentityVerification::new(request, member.upcast_ref(), Some(&room)).await;
room.set_verification(Some(&verification));
self.add(verification.clone());
if verification.state() == VerificationState::Requested {
session
.notifications()
.show_in_room_identity_verification(&verification)
.await;
}
}
/// Add the given verification to the list.
pub(super) fn add(&self, verification: IdentityVerification) {
let key = verification.key();
// Don't add request that already exists.
if self.list.borrow().contains_key(&key) {
return;
}
let obj = self.obj();
verification.connect_remove_from_list(clone!(
#[weak]
obj,
move |verification| {
obj.remove(&verification.key());
}
));
let (pos, _) = self.list.borrow_mut().insert_full(key, verification);
obj.items_changed(pos as u32, 0, 1);
}
}
}
glib::wrapper! {
@ -82,7 +205,7 @@ impl VerificationList {
}
/// Initialize this list to listen to new verification requests.
pub fn init(&self) {
pub(crate) fn init(&self) {
let Some(session) = self.session() else {
return;
};
@ -121,7 +244,7 @@ impl VerificationList {
ctx.spawn(async move {
spawn!(async move {
if let Some(obj) = obj_weak.upgrade() {
obj.add_to_device_request(request).await;
obj.imp().add_to_device_request(request).await;
}
});
});
@ -154,7 +277,7 @@ impl VerificationList {
ctx.spawn(async move {
spawn!(async move {
if let Some(obj) = obj_weak.upgrade() {
obj.add_in_room_request(request, &room_id).await;
obj.imp().add_in_room_request(request, &room_id).await;
}
});
});
@ -163,124 +286,6 @@ impl VerificationList {
);
}
/// Add a verification received via a to-device event.
async fn add_to_device_request(&self, request: VerificationRequest) {
if request.is_done() || request.is_cancelled() || request.is_passive() {
// Ignore requests that are already finished.
return;
}
let Some(session) = self.session() else {
return;
};
let verification = IdentityVerification::new(request, &session.user(), None).await;
self.add(verification.clone());
if verification.state() == VerificationState::Requested {
session
.notifications()
.show_to_device_identity_verification(&verification)
.await;
}
}
/// Add a verification received via an in-room event.
async fn add_in_room_request(&self, request: VerificationRequest, room_id: &RoomId) {
if request.is_done() || request.is_cancelled() || request.is_passive() {
// Ignore requests that are already finished.
return;
}
let Some(session) = self.session() else {
return;
};
let Some(room) = session.room_list().get(room_id) else {
error!(
"Room for verification request `({}, {})` not found",
request.other_user_id(),
request.flow_id()
);
return;
};
if matches!(
room.own_member().membership(),
Membership::Leave | Membership::Ban
) {
// Ignore requests where the user is not in the room anymore.
return;
}
let other_user_id = request.other_user_id().to_owned();
let member = room.members().map_or_else(
|| Member::new(&room, other_user_id.clone()),
|l| l.get_or_create(other_user_id.clone()),
);
// Ensure the member is up-to-date.
let matrix_room = room.matrix_room().clone();
let handle =
spawn_tokio!(async move { matrix_room.get_member_no_sync(&other_user_id).await });
match handle.await.unwrap() {
Ok(Some(matrix_member)) => member.update_from_room_member(&matrix_member),
Ok(None) => {
error!(
"Room member for verification request `({}, {})` not found",
request.other_user_id(),
request.flow_id()
);
return;
}
Err(error) => {
error!(
"Could not get room member for verification request `({}, {})`: {error}",
request.other_user_id(),
request.flow_id()
);
return;
}
}
let verification =
IdentityVerification::new(request, member.upcast_ref(), Some(&room)).await;
room.set_verification(Some(&verification));
self.add(verification.clone());
if verification.state() == VerificationState::Requested {
session
.notifications()
.show_in_room_identity_verification(&verification)
.await;
}
}
/// Add the given verification to the list.
fn add(&self, verification: IdentityVerification) {
let imp = self.imp();
let key = verification.key();
// Don't add request that already exists.
if imp.list.borrow().contains_key(&key) {
return;
}
verification.connect_remove_from_list(clone!(
#[weak(rename_to = obj)]
self,
move |verification| {
obj.remove(&verification.key());
}
));
let (pos, _) = imp.list.borrow_mut().insert_full(key, verification);
self.items_changed(pos as u32, 0, 1);
}
/// Remove the verification with the given key.
pub(crate) fn remove(&self, key: &VerificationKey) {
let Some((pos, ..)) = self.imp().list.borrow_mut().shift_remove_full(key) else {
@ -300,7 +305,7 @@ impl VerificationList {
}
// Returns the ongoing session verification, if any.
pub fn ongoing_session_verification(&self) -> Option<IdentityVerification> {
pub(crate) fn ongoing_session_verification(&self) -> Option<IdentityVerification> {
let list = self.imp().list.borrow();
list.values()
.find(|v| v.is_self_verification() && !v.is_finished())
@ -308,7 +313,10 @@ impl VerificationList {
}
// Returns the ongoing verification in the given room, if any.
pub fn ongoing_room_verification(&self, room_id: &RoomId) -> Option<IdentityVerification> {
pub(crate) fn ongoing_room_verification(
&self,
room_id: &RoomId,
) -> Option<IdentityVerification> {
let list = self.imp().list.borrow();
list.values()
.find(|v| v.room().is_some_and(|room| room.room_id() == room_id) && !v.is_finished())
@ -319,7 +327,7 @@ impl VerificationList {
///
/// If `user` is `None`, a new session verification is started for our own
/// user and sent to other devices.
pub async fn create(&self, user: Option<User>) -> Result<IdentityVerification, ()> {
pub(crate) async fn create(&self, user: Option<User>) -> Result<IdentityVerification, ()> {
let Some(session) = self.session() else {
error!("Could not create identity verification: failed to upgrade session");
return Err(());
@ -340,7 +348,7 @@ impl VerificationList {
.await
});
match handle.await.unwrap() {
match handle.await.expect("task was not aborted") {
Ok(request) => {
let room = if let Some(room_id) = request.room_id() {
let Some(room) = session.room_list().get(room_id) else {
@ -357,7 +365,7 @@ impl VerificationList {
};
let verification = IdentityVerification::new(request, &user, room.as_ref()).await;
self.add(verification.clone());
self.imp().add(verification.clone());
Ok(verification)
}

Loading…
Cancel
Save