Skip to content

Commit 67051f4

Browse files
committed
Add SecurejoinSourceStats, not tested yet
1 parent 03eff8f commit 67051f4

File tree

4 files changed

+107
-3
lines changed

4 files changed

+107
-3
lines changed

deltachat-jsonrpc/src/api.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -867,9 +867,9 @@ impl CommandApi {
867867
/// **returns**: The chat ID of the joined chat, the UI may redirect to the this chat.
868868
/// A returned chat ID does not guarantee that the chat is protected or the belonging contact is verified.
869869
///
870-
async fn secure_join(&self, account_id: u32, qr: String) -> Result<u32> {
870+
async fn secure_join(&self, account_id: u32, qr: String, source: Option<u32>) -> Result<u32> {
871871
let ctx = self.get_context(account_id).await?;
872-
let chat_id = securejoin::join_securejoin(&ctx, &qr).await?;
872+
let chat_id = securejoin::join_securejoin_with_source(&ctx, &qr, source).await?;
873873
Ok(chat_id.to_u32())
874874
}
875875

src/securejoin.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use deltachat_contact_tools::ContactAddress;
55
use percent_encoding::{NON_ALPHANUMERIC, utf8_percent_encode};
66

77
use crate::chat::{self, Chat, ChatId, ChatIdBlocked, ProtectionStatus, get_chat_id_by_grpid};
8-
use crate::chatlist_events;
98
use crate::config::Config;
109
use crate::constants::{Blocked, Chattype, NON_ALPHANUMERIC_WITHOUT_DOT};
1110
use crate::contact::mark_contact_id_as_verified;
@@ -15,6 +14,7 @@ use crate::e2ee::ensure_secret_key_exists;
1514
use crate::events::EventType;
1615
use crate::headerdef::HeaderDef;
1716
use crate::key::{DcKey, Fingerprint, load_self_public_key};
17+
use crate::log::LogExt as _;
1818
use crate::log::{error, info, warn};
1919
use crate::message::{Message, Viewtype};
2020
use crate::mimeparser::{MimeMessage, SystemMessage};
@@ -23,6 +23,7 @@ use crate::qr::check_qr;
2323
use crate::securejoin::bob::JoinerProgress;
2424
use crate::sync::Sync::*;
2525
use crate::token;
26+
use crate::{chatlist_events, self_reporting};
2627

2728
mod bob;
2829
mod qrinvite;
@@ -151,6 +152,27 @@ pub async fn join_securejoin(context: &Context, qr: &str) -> Result<ChatId> {
151152
})
152153
}
153154

155+
/// Take a scanned QR-code and do the setup-contact/join-group/invite handshake.
156+
///
157+
/// This is the start of the process for the joiner. See the module and ffi documentation
158+
/// for more details.
159+
///
160+
/// The function returns immediately and the handshake will run in background.
161+
pub async fn join_securejoin_with_source(
162+
context: &Context,
163+
qr: &str,
164+
source: Option<u32>,
165+
) -> Result<ChatId> {
166+
let res = join_securejoin(context, qr).await?;
167+
168+
self_reporting::count_securejoin_source(context, source)
169+
.await
170+
.log_err(context)
171+
.ok();
172+
173+
Ok(res)
174+
}
175+
154176
async fn securejoin(context: &Context, qr: &str) -> Result<ChatId> {
155177
/*========================================================
156178
==== Bob - the joiner's side =====

src/self_reporting.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use std::collections::{BTreeMap, BTreeSet};
44

55
use anyhow::{ensure, Context as _, Result};
6+
use deltachat_derive::FromSql;
67
use pgp::types::PublicKeyTrait;
78
use serde::Serialize;
89

@@ -32,6 +33,7 @@ struct Statistics {
3233
self_reporting_id: String,
3334
contact_stats: Vec<ContactStat>,
3435
message_stats: MessageStats,
36+
securejoin_source_stats: SecurejoinSourceStats,
3537
}
3638
#[derive(Default, Serialize)]
3739
struct ChatNumbers {
@@ -430,10 +432,78 @@ async fn get_self_report(context: &Context) -> Result<String> {
430432
self_reporting_id,
431433
contact_stats: get_contact_stats(context).await?,
432434
message_stats: get_message_stats(context).await?,
435+
securejoin_source_stats: get_securejoin_source_stats(context).await?,
433436
};
434437

435438
Ok(serde_json::to_string_pretty(&statistics)?)
436439
}
437440

441+
#[repr(u32)]
442+
#[derive(Debug, Clone, Copy, FromPrimitive, FromSql, PartialEq, Eq, PartialOrd, Ord)]
443+
enum SecurejoinSource {
444+
Unknown = 0,
445+
ExternalLink = 1,
446+
InternalLink = 2,
447+
Clipboard = 3,
448+
ImageLoaded = 4,
449+
Scan = 5,
450+
}
451+
452+
#[derive(Serialize)]
453+
struct SecurejoinSourceStats {
454+
unknown: u32,
455+
external_link: u32,
456+
internal_link: u32,
457+
clipboard: u32,
458+
image_loaded: u32,
459+
scan: u32,
460+
}
461+
462+
pub(crate) async fn count_securejoin_source(context: &Context, source: Option<u32>) -> Result<()> {
463+
if context.get_config_bool(Config::SelfReporting).await? {
464+
let source = source
465+
.context("Missing securejoin source")
466+
.log_err(context)
467+
.unwrap_or(0);
468+
469+
context
470+
.sql
471+
.execute(
472+
"INSERT INTO stats_securejoin_sources VALUES (?, 1)
473+
ON CONFLICT (source) DO UPDATE SET count=count+1;",
474+
(source,),
475+
)
476+
.await?;
477+
}
478+
Ok(())
479+
}
480+
481+
async fn get_securejoin_source_stats(context: &Context) -> Result<SecurejoinSourceStats> {
482+
let map = context
483+
.sql
484+
.query_map(
485+
"SELECT source, count FROM stats_securejoin_sources",
486+
(),
487+
|row| {
488+
let source: SecurejoinSource = row.get(0)?;
489+
let count: u32 = row.get(1)?;
490+
Ok((source, count))
491+
},
492+
|rows| Ok(rows.collect::<rusqlite::Result<BTreeMap<_, _>>>()?),
493+
)
494+
.await?;
495+
496+
let stats = SecurejoinSourceStats {
497+
unknown: *map.get(&SecurejoinSource::Unknown).unwrap_or(&0),
498+
external_link: *map.get(&SecurejoinSource::ExternalLink).unwrap_or(&0),
499+
internal_link: *map.get(&SecurejoinSource::InternalLink).unwrap_or(&0),
500+
clipboard: *map.get(&SecurejoinSource::Clipboard).unwrap_or(&0),
501+
image_loaded: *map.get(&SecurejoinSource::ImageLoaded).unwrap_or(&0),
502+
scan: *map.get(&SecurejoinSource::Scan).unwrap_or(&0),
503+
};
504+
505+
Ok(stats)
506+
}
507+
438508
#[cfg(test)]
439509
mod self_reporting_tests;

src/sql/migrations.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,18 @@ CREATE INDEX gossip_timestamp_index ON gossip_timestamp (chat_id, fingerprint);
12471247
);
12481248
}
12491249

1250+
inc_and_check(&mut migration_version, 133)?;
1251+
if dbversion < migration_version {
1252+
sql.execute_migration(
1253+
"CREATE TABLE stats_securejoin_sources(
1254+
source INTEGER PRIMARY KEY,
1255+
count INTEGER NOT NULL DEFAULT 0
1256+
) STRICT",
1257+
133,
1258+
)
1259+
.await?;
1260+
}
1261+
12501262
let new_version = sql
12511263
.get_raw_config_int(VERSION_CFG)
12521264
.await?

0 commit comments

Comments
 (0)