first commit

This commit is contained in:
2026-04-04 01:33:50 +03:00
commit 05e2355615
33 changed files with 12383 additions and 0 deletions

226
src/room/verification.rs Normal file
View File

@@ -0,0 +1,226 @@
use std::{cell::RefCell, rc::Rc};
use matrix_sdk::{
encryption::verification::{SasVerification, VerificationRequest},
ruma::{
events::{
key::verification::VerificationMethod, room::message::MessageType,
AnySyncMessageLikeEvent,
},
UserId,
},
};
use crate::{
connection::Connection,
render::{Render, StartVerificationContext, VerificationContext},
};
use super::{buffer::RoomBuffer, members::Members};
#[derive(Clone)]
pub struct Verification {
own_user_id: Rc<UserId>,
connection: Rc<RefCell<Option<Connection>>>,
members: Members,
buffer: RoomBuffer,
inner: Rc<RefCell<Option<ActiveVerification>>>,
}
#[derive(Clone, Debug)]
enum ActiveVerification {
Request(VerificationRequest),
Sas(SasVerification),
}
impl From<VerificationRequest> for ActiveVerification {
fn from(v: VerificationRequest) -> Self {
Self::Request(v)
}
}
impl From<SasVerification> for ActiveVerification {
fn from(v: SasVerification) -> Self {
Self::Sas(v)
}
}
impl Verification {
pub fn new(
own_user_id: Rc<UserId>,
connection: Rc<RefCell<Option<Connection>>>,
members: Members,
buffer: RoomBuffer,
) -> Self {
Self {
own_user_id,
connection,
members,
buffer,
inner: Rc::new(RefCell::new(None)),
}
}
pub async fn confirm(&self) {
let connection = self.connection.borrow().clone();
if let Some(c) = connection {
if let Some(ActiveVerification::Sas(verification)) =
self.inner.borrow().clone()
{
let ret =
c.spawn(async move { verification.confirm().await }).await;
}
}
}
pub async fn accept(&self) {
let connection = self.connection.borrow().clone();
let verification = self.inner.borrow().clone();
if let Some(c) = connection {
if let Some(ActiveVerification::Request(verification)) =
verification
{
let verification_clone = verification.clone();
let ret = c
.spawn(async move {
verification
.accept_with_methods(vec![
VerificationMethod::SasV1,
])
.await
})
.await;
// We automatically start SAS verification here since it's the
// only method we support.
if let Some(sas) = c
.spawn(async move { verification_clone.start_sas().await })
.await
.unwrap()
{
*self.inner.borrow_mut() = Some(sas.into());
}
}
}
}
pub async fn handle_room_verification(
&self,
event: &AnySyncMessageLikeEvent,
) {
// TODO remove this expect.
let sender =
self.members.get(event.sender()).await.expect(
"Rendering a message but the sender isn't in the nicklist",
);
let own_member = self
.members
.get(&self.own_user_id)
.await
.expect("Own member missing from the store");
let send_time = event.origin_server_ts();
let connection = self.connection.borrow().clone();
match event {
AnySyncMessageLikeEvent::KeyVerificationReady(_) => {}
AnySyncMessageLikeEvent::KeyVerificationStart(e) => {
if let Some(connection) = connection {
let Some(e) = e.as_original() else {
// Unhandled redacted event
return;
};
let flow_id = &e.content.relates_to.event_id;
if let Some(sas) = connection
.client()
.encryption()
.get_verification(&e.sender, flow_id.as_str())
.await
.map(|s| s.sas())
.flatten()
{
let context = StartVerificationContext::Room(
e.sender.to_owned(),
sas.clone().into(),
);
let rendered = e.content.render_with_prefix(
send_time,
event.event_id(),
&sender,
&context,
);
self.buffer
.replace_verification_event(flow_id, rendered);
*self.inner.borrow_mut() = Some(sas.clone().into());
// We accept here automatically since the only method
// we're supporting is SAS verification
let ret = connection
.spawn(async move { sas.accept().await })
.await;
}
}
}
AnySyncMessageLikeEvent::KeyVerificationCancel(_) => {
self.inner.borrow_mut().take();
}
AnySyncMessageLikeEvent::KeyVerificationAccept(_) => {}
AnySyncMessageLikeEvent::KeyVerificationKey(e) => {
let Some(e) = e.as_original() else {
// Unhandled redacted event
return;
};
let flow_id = &e.content.relates_to.event_id;
if let Some(ActiveVerification::Sas(sas)) =
self.inner.borrow().clone()
{
if sas.can_be_presented() {
let rendered = e.content.render_with_prefix(
send_time,
event.event_id(),
&sender,
&sas,
);
self.buffer
.replace_verification_event(flow_id, rendered);
}
}
}
AnySyncMessageLikeEvent::KeyVerificationMac(_) => {}
AnySyncMessageLikeEvent::KeyVerificationDone(_) => {}
AnySyncMessageLikeEvent::RoomMessage(e) => {
let Some(e) = e.as_original() else {
// Unhandled redacted event
return;
};
if let MessageType::VerificationRequest(content) =
&e.content.msgtype
{
let rendered = content.render_with_prefix(
send_time,
&e.event_id,
&sender.clone(),
&VerificationContext::Room(sender, own_member),
);
self.buffer.print_rendered_event(rendered);
if let Some(connection) = connection {
if let Some(verification) = connection
.client()
.encryption()
.get_verification_request(&e.sender, &e.event_id)
.await
{
*self.inner.borrow_mut() =
Some(verification.into());
}
}
}
}
_ => {}
}
}
}