Refactor qr module

This commit is contained in:
link2xt
2021-10-03 02:50:48 +00:00
parent a3562c5940
commit dbd8814d2c
10 changed files with 849 additions and 718 deletions

View File

@@ -2,7 +2,7 @@
use std::convert::{TryFrom, TryInto};
use anyhow::{bail, ensure, format_err, Context as _, Result};
use anyhow::{bail, ensure, Context as _, Result};
use async_std::path::PathBuf;
use deltachat_derive::{FromSql, ToSql};
use itertools::Itertools;
@@ -1339,12 +1339,11 @@ fn cat_fingerprint(
impl Context {
/// determine whether the specified addr maps to the/a self addr
pub async fn is_self_addr(&self, addr: &str) -> Result<bool> {
let self_addr = self
.get_config(Config::ConfiguredAddr)
.await?
.ok_or_else(|| format_err!("Not configured"))?;
Ok(addr_cmp(self_addr, addr))
if let Some(self_addr) = self.get_config(Config::ConfiguredAddr).await? {
Ok(addr_cmp(self_addr, addr))
} else {
Ok(false)
}
}
}
@@ -1491,7 +1490,7 @@ mod tests {
#[async_std::test]
async fn test_is_self_addr() -> Result<()> {
let t = TestContext::new().await;
assert!(t.is_self_addr("me@me.org").await.is_err());
assert_eq!(t.is_self_addr("me@me.org").await?, false);
let addr = t.configure_alice().await;
assert_eq!(t.is_self_addr("me@me.org").await?, false);

View File

@@ -68,7 +68,6 @@ pub mod key;
mod keyring;
pub mod location;
mod login_param;
pub mod lot;
pub mod message;
mod mimefactory;
pub mod mimeparser;

View File

@@ -1,181 +0,0 @@
//! # Legacy generic return values for C API.
use deltachat_derive::{FromSql, ToSql};
use crate::key::Fingerprint;
use crate::message::MessageState;
use crate::summary::{Summary, SummaryPrefix};
/// An object containing a set of values.
/// The meaning of the values is defined by the function returning the object.
/// Lot objects are created
/// eg. by chatlist.get_summary() or dc_msg_get_summary().
///
/// *Lot* is used in the meaning *heap* here.
#[derive(Default, Debug, Clone)]
pub struct Lot {
pub(crate) text1_meaning: Meaning,
pub(crate) text1: Option<String>,
pub(crate) text2: Option<String>,
pub(crate) timestamp: i64,
pub(crate) state: LotState,
pub(crate) id: u32,
pub(crate) fingerprint: Option<Fingerprint>,
pub(crate) invitenumber: Option<String>,
pub(crate) auth: Option<String>,
}
#[repr(u8)]
#[derive(
Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, ToSql, FromSql,
)]
pub enum Meaning {
None = 0,
Text1Draft = 1,
Text1Username = 2,
Text1Self = 3,
}
impl Default for Meaning {
fn default() -> Self {
Meaning::None
}
}
impl Lot {
pub fn new() -> Self {
Default::default()
}
pub fn get_text1(&self) -> Option<&str> {
self.text1.as_deref()
}
pub fn get_text2(&self) -> Option<&str> {
self.text2.as_deref()
}
pub fn get_text1_meaning(&self) -> Meaning {
self.text1_meaning
}
pub fn get_state(&self) -> LotState {
self.state
}
pub fn get_id(&self) -> u32 {
self.id
}
pub fn get_timestamp(&self) -> i64 {
self.timestamp
}
}
#[repr(u32)]
#[derive(
Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, ToSql, FromSql,
)]
pub enum LotState {
// Default
Undefined = 0,
// Qr States
/// id=contact
QrAskVerifyContact = 200,
/// text1=groupname
QrAskVerifyGroup = 202,
/// id=contact
QrFprOk = 210,
/// id=contact
QrFprMismatch = 220,
/// test1=formatted fingerprint
QrFprWithoutAddr = 230,
/// text1=domain
QrAccount = 250,
/// text1=domain, text2=instance pattern
QrWebrtcInstance = 260,
/// id=contact
QrAddr = 320,
/// text1=text
QrText = 330,
/// text1=URL
QrUrl = 332,
/// text1=error string
QrError = 400,
QrWithdrawVerifyContact = 500,
/// text1=groupname
QrWithdrawVerifyGroup = 502,
QrReviveVerifyContact = 510,
/// text1=groupname
QrReviveVerifyGroup = 512,
// Message States
MsgInFresh = 10,
MsgInNoticed = 13,
MsgInSeen = 16,
MsgOutPreparing = 18,
MsgOutDraft = 19,
MsgOutPending = 20,
MsgOutFailed = 24,
MsgOutDelivered = 26,
MsgOutMdnRcvd = 28,
}
impl Default for LotState {
fn default() -> Self {
LotState::Undefined
}
}
impl From<MessageState> for LotState {
fn from(s: MessageState) -> Self {
use MessageState::*;
match s {
Undefined => LotState::Undefined,
InFresh => LotState::MsgInFresh,
InNoticed => LotState::MsgInNoticed,
InSeen => LotState::MsgInSeen,
OutPreparing => LotState::MsgOutPreparing,
OutDraft => LotState::MsgOutDraft,
OutPending => LotState::MsgOutPending,
OutFailed => LotState::MsgOutFailed,
OutDelivered => LotState::MsgOutDelivered,
OutMdnRcvd => LotState::MsgOutMdnRcvd,
}
}
}
impl From<Summary> for Lot {
fn from(summary: Summary) -> Self {
let text2 = Some(summary.truncated_text(160).to_string());
let (text1, text1_meaning) = match summary.prefix {
None => (None, Meaning::None),
Some(SummaryPrefix::Draft(text)) => (Some(text), Meaning::Text1Draft),
Some(SummaryPrefix::Username(username)) => (Some(username), Meaning::Text1Username),
Some(SummaryPrefix::Me(text)) => (Some(text), Meaning::Text1Self),
};
Self {
text1_meaning,
text1,
text2,
timestamp: summary.timestamp,
state: summary.state.into(),
..Default::default()
}
}
}

1020
src/qr.rs

File diff suppressed because it is too large Load Diff

View File

@@ -31,7 +31,7 @@ mod bobstate;
mod qrinvite;
use bobstate::{BobHandshakeStage, BobState, BobStateHandle};
use qrinvite::{QrError, QrInvite};
use qrinvite::QrInvite;
pub const NON_ALPHANUMERIC_WITHOUT_DOT: &AsciiSet = &NON_ALPHANUMERIC.remove(b'.');
@@ -247,9 +247,6 @@ async fn get_self_fingerprint(context: &Context) -> Option<Fingerprint> {
#[derive(Debug, thiserror::Error)]
pub enum JoinError {
#[error("Unknown QR-code: {0}")]
QrCode(#[from] QrError),
#[error("An \"ongoing\" process is already running")]
OngoingRunning,
@@ -293,7 +290,7 @@ async fn securejoin(context: &Context, qr: &str) -> Result<ChatId, JoinError> {
========================================================*/
info!(context, "Requesting secure-join ...",);
let qr_scan = check_qr(context, qr).await;
let qr_scan = check_qr(context, qr).await?;
let invite = QrInvite::try_from(qr_scan)?;
@@ -1146,7 +1143,7 @@ mod tests {
async fn test_setup_contact_bad_qr() {
let bob = TestContext::new_bob().await;
let ret = dc_join_securejoin(&bob.ctx, "not a qr code").await;
assert!(matches!(ret, Err(JoinError::QrCode(_))));
assert!(ret.is_err());
}
#[async_std::test]

View File

@@ -1,16 +1,15 @@
//! Supporting code for the QR-code invite.
//!
//! QR-codes are decoded into a more general-purpose [`Lot`] struct normally, this struct is
//! so general it is not even specific to QR-codes. This makes working with it rather hard,
//! so here we have a wrapper type that specifically deals with Secure-Join QR-codes so
//! that the Secure-Join code can have many more guarantees when dealing with this.
//! QR-codes are decoded into a more general-purpose [`Qr`] struct normally. This makes working
//! with it rather hard, so here we have a wrapper type that specifically deals with Secure-Join
//! QR-codes so that the Secure-Join code can have more guarantees when dealing with this.
use std::convert::TryFrom;
use anyhow::Result;
use anyhow::{bail, Error, Result};
use crate::key::Fingerprint;
use crate::lot::{Lot, LotState};
use crate::qr::Qr;
/// Represents the data from a QR-code scan.
///
@@ -66,53 +65,38 @@ impl QrInvite {
}
}
impl TryFrom<Lot> for QrInvite {
type Error = QrError;
impl TryFrom<Qr> for QrInvite {
type Error = Error;
fn try_from(lot: Lot) -> Result<Self, Self::Error> {
if lot.state != LotState::QrAskVerifyContact && lot.state != LotState::QrAskVerifyGroup {
return Err(QrError::UnsupportedProtocol);
}
if lot.id == 0 {
return Err(QrError::MissingContactId);
}
let fingerprint = lot.fingerprint.ok_or(QrError::MissingFingerprint)?;
let invitenumber = lot.invitenumber.ok_or(QrError::MissingInviteNumber)?;
let authcode = lot.auth.ok_or(QrError::MissingAuthCode)?;
match lot.state {
LotState::QrAskVerifyContact => Ok(QrInvite::Contact {
contact_id: lot.id,
fn try_from(qr: Qr) -> Result<Self> {
match qr {
Qr::AskVerifyContact {
contact_id,
fingerprint,
invitenumber,
authcode,
} => Ok(QrInvite::Contact {
contact_id,
fingerprint,
invitenumber,
authcode,
}),
LotState::QrAskVerifyGroup => Ok(QrInvite::Group {
contact_id: lot.id,
Qr::AskVerifyGroup {
grpname,
grpid,
contact_id,
fingerprint,
name: lot.text1.ok_or(QrError::MissingGroupName)?,
grpid: lot.text2.ok_or(QrError::MissingGroupId)?,
invitenumber,
authcode,
} => Ok(QrInvite::Group {
contact_id,
fingerprint,
name: grpname,
grpid,
invitenumber,
authcode,
}),
_ => Err(QrError::UnsupportedProtocol),
_ => bail!("Unsupported QR type {:?}", qr),
}
}
}
#[derive(Debug, thiserror::Error)]
pub enum QrError {
#[error("Unsupported protocol in QR-code")]
UnsupportedProtocol,
#[error("Missing fingerprint")]
MissingFingerprint,
#[error("Missing invitenumber")]
MissingInviteNumber,
#[error("Missing auth code")]
MissingAuthCode,
#[error("Missing group name")]
MissingGroupName,
#[error("Missing group id")]
MissingGroupId,
#[error("Missing contact id")]
MissingContactId,
}