diff --git a/src/chat.rs b/src/chat.rs index 6827d8613..02f4d44ae 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -2808,10 +2808,10 @@ pub(crate) async fn get_chat_cnt(context: &Context) -> Result { pub(crate) async fn get_chat_id_by_grpid( context: &Context, grpid: impl AsRef, -) -> Result<(ChatId, bool, Blocked)> { +) -> Result> { context .sql - .query_row( + .query_row_optional( "SELECT id, blocked, protected FROM chats WHERE grpid=?;", paramsv![grpid.as_ref()], |row| { diff --git a/src/contact.rs b/src/contact.rs index 9539d7232..c919cee59 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -1202,7 +1202,8 @@ WHERE type=? AND id IN ( // also unblock mailinglist // if the contact is a mailinglist address explicitly created to allow unblocking if !new_blocking && contact.origin == Origin::MailinglistAddress { - if let Ok((chat_id, _, _)) = chat::get_chat_id_by_grpid(context, contact.addr).await { + if let Some((chat_id, _, _)) = chat::get_chat_id_by_grpid(context, contact.addr).await? + { chat_id.unblock(context).await?; } } diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index fb6ccb2e7..e35703645 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -532,7 +532,7 @@ async fn add_parts( list_id, mime_parser, ) - .await + .await? { chat_id = Some(new_chat_id); chat_id_blocked = new_chat_id_blocked; @@ -548,7 +548,7 @@ async fn add_parts( sender, mime_parser, ) - .await + .await? { chat_id = Some(new_chat_id); chat_id_blocked = new_chat_id_blocked; @@ -1347,13 +1347,9 @@ async fn create_or_lookup_group( }; // check, if we have a chat with this group ID - let mut chat_id = if let Ok((chat_id, _protected, _blocked)) = - chat::get_chat_id_by_grpid(context, &grpid).await - { - Some(chat_id) - } else { - None - }; + let mut chat_id = chat::get_chat_id_by_grpid(context, &grpid) + .await? + .map(|(chat_id, _protected, _blocked)| chat_id); // For chat messages, we don't have to guess (is_*probably*_private_reply()) but we know for sure that // they belong to the group because of the Chat-Group-Id or Message-Id header @@ -1616,7 +1612,7 @@ async fn create_or_lookup_mailinglist( allow_creation: bool, list_id_header: &str, mime_parser: &MimeMessage, -) -> Option<(ChatId, Blocked)> { +) -> Result> { static LIST_ID: Lazy = Lazy::new(|| Regex::new(r"^(.+)<(.+)>$").unwrap()); let (mut name, listid) = match LIST_ID.captures(list_id_header) { Some(cap) => (cap[1].trim().to_string(), cap[2].trim().to_string()), @@ -1630,8 +1626,8 @@ async fn create_or_lookup_mailinglist( ), }; - if let Ok((chat_id, _, blocked)) = chat::get_chat_id_by_grpid(context, &listid).await { - return Some((chat_id, blocked)); + if let Some((chat_id, _, blocked)) = chat::get_chat_id_by_grpid(context, &listid).await? { + return Ok(Some((chat_id, blocked))); } // for mailchimp lists, the name in `ListId` is just a long number. @@ -1678,7 +1674,7 @@ async fn create_or_lookup_mailinglist( if allow_creation { // list does not exist but should be created - match create_multiuser_record( + let chat_id = create_multiuser_record( context, Chattype::Mailinglist, &listid, @@ -1687,25 +1683,18 @@ async fn create_or_lookup_mailinglist( ProtectionStatus::Unprotected, ) .await - { - Ok(chat_id) => { - chat::add_to_chat_contacts_table(context, chat_id, DC_CONTACT_ID_SELF).await; - Some((chat_id, Blocked::Request)) - } - Err(e) => { - warn!( - context, - "Failed to create mailinglist '{}' for grpid={}: {}", - &name, - &listid, - e.to_string() - ); - None - } - } + .map_err(|err| { + err.context(format!( + "Failed to create mailinglist '{}' for grpid={}", + &name, &listid + )) + })?; + + chat::add_to_chat_contacts_table(context, chat_id, DC_CONTACT_ID_SELF).await; + Ok(Some((chat_id, Blocked::Request))) } else { info!(context, "creating list forbidden by caller"); - None + Ok(None) } } diff --git a/src/imap.rs b/src/imap.rs index 4806ee52b..3670a11b6 100644 --- a/src/imap.rs +++ b/src/imap.rs @@ -1636,7 +1636,7 @@ pub(crate) async fn prefetch_should_download( // deleted from the database or has not arrived yet. if let Some(rfc724_mid) = headers.get_header_value(HeaderDef::MessageId) { if let Some(group_id) = dc_extract_grpid_from_rfc724_mid(&rfc724_mid) { - if let Ok((_chat_id, _, _)) = get_chat_id_by_grpid(context, group_id).await { + if get_chat_id_by_grpid(context, group_id).await?.is_some() { return Ok(true); } } diff --git a/src/qr.rs b/src/qr.rs index 66ac98570..3170e20d0 100644 --- a/src/qr.rs +++ b/src/qr.rs @@ -324,11 +324,9 @@ pub async fn set_config_from_qr(context: &Context, qr: &str) -> Result<(), Error let chat_id = if lot.state == LotState::QrReviveVerifyContact { None } else { - Some( - get_chat_id_by_grpid(context, &lot.text2.unwrap_or_default()) - .await? - .0, - ) + get_chat_id_by_grpid(context, &lot.text2.unwrap_or_default()) + .await? + .map(|(chat_id, _protected, _blocked)| chat_id) }; token::save( context, diff --git a/src/securejoin.rs b/src/securejoin.rs index 20e344a72..e6f254403 100644 --- a/src/securejoin.rs +++ b/src/securejoin.rs @@ -3,7 +3,7 @@ use std::convert::TryFrom; use std::time::{Duration, Instant}; -use anyhow::{bail, Context as _, Error, Result}; +use anyhow::{anyhow, bail, Context as _, Error, Result}; use async_std::channel::Receiver; use async_std::sync::Mutex; use percent_encoding::{utf8_percent_encode, AsciiSet, NON_ALPHANUMERIC}; @@ -327,14 +327,14 @@ async fn securejoin(context: &Context, qr: &str) -> Result { let start = Instant::now(); let chatid = loop { { - match chat::get_chat_id_by_grpid(context, &group_id).await { - Ok((chatid, _is_protected, _blocked)) => break chatid, - Err(err) => { + match chat::get_chat_id_by_grpid(context, &group_id).await? { + Some((chatid, _is_protected, _blocked)) => break chatid, + None => { if start.elapsed() > Duration::from_secs(7) { context.free_ongoing().await; - return Err(err - .context("Ongoing sender dropped (this is a bug)") - .into()); + return Err(JoinError::Other(anyhow!( + "Ongoing sender dropped (this is a bug)" + ))); } } } @@ -650,8 +650,8 @@ pub(crate) async fn handle_securejoin_handshake( return Ok(HandshakeMessage::Ignore); } }; - match chat::get_chat_id_by_grpid(context, field_grpid).await { - Ok((group_chat_id, _, _)) => { + match chat::get_chat_id_by_grpid(context, field_grpid).await? { + Some((group_chat_id, _, _)) => { if let Err(err) = chat::add_contact_to_chat_ex(context, group_chat_id, contact_id, true) .await @@ -659,12 +659,7 @@ pub(crate) async fn handle_securejoin_handshake( error!(context, "failed to add contact: {}", err); } } - Err(err) => { - error!(context, "Chat {} not found: {}", &field_grpid, err); - return Err( - err.context(format!("Chat for group {} not found", &field_grpid)) - ); - } + None => bail!("Chat {} not found", &field_grpid), } } else { // Alice -> Bob diff --git a/src/securejoin/bobstate.rs b/src/securejoin/bobstate.rs index e36159c0c..df374dd97 100644 --- a/src/securejoin/bobstate.rs +++ b/src/securejoin/bobstate.rs @@ -12,7 +12,7 @@ use anyhow::{Error, Result}; use async_std::sync::MutexGuard; use crate::chat::{self, ChatId}; -use crate::constants::{Blocked, Viewtype}; +use crate::constants::Viewtype; use crate::contact::{Contact, Origin}; use crate::context::Context; use crate::events::EventType; @@ -336,9 +336,10 @@ impl BobState { // the very handshake message we're handling now. But // only after we have returned. It does not impact // the security invariants of secure-join however. - let (_, is_verified_group, _) = chat::get_chat_id_by_grpid(context, grpid) - .await - .unwrap_or((ChatId::new(0), false, Blocked::Not)); + + let is_verified_group = chat::get_chat_id_by_grpid(context, grpid) + .await? + .map_or(false, |(_chat_id, is_protected, _blocked)| is_protected); // when joining a non-verified group // the vg-member-added message may be unencrypted // when not all group members have keys or prefer encryption.