Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
568818d
fix test_profile_data_on_group_leave
link2xt May 6, 2025
036a693
[WIP] Migration for PGP-contacts
Hocuri Apr 24, 2025
2fcc2c1
Try to implement everything, but of course things still fail
Hocuri Apr 24, 2025
c420f86
Add a test and make it pass
Hocuri Apr 25, 2025
756c7fc
formatting
Hocuri Apr 25, 2025
32ccf85
Add another test & fix problems I found
Hocuri Apr 25, 2025
7b76c2c
Migrate verifications, migration should be completely implemented now
Hocuri Apr 25, 2025
368e286
Add two more tests, without finding any bugs
Hocuri Apr 25, 2025
5d6e451
Fix some things, now my personal database is correctly migrated now
Hocuri Apr 26, 2025
5c7eb54
fix: Don't create PGP chat if none of the members can encrypt
Hocuri Apr 26, 2025
66e52b8
feat: On error, report which SQL statement failed
Hocuri Apr 29, 2025
531ad82
feat: Allow to open context even though migrations failed
Hocuri Apr 29, 2025
3dc7e18
feat: Set migration error instead of re-using last_error
Hocuri Apr 29, 2025
7619420
Remove outdated TODOs
Hocuri Apr 29, 2025
db4fec7
fix test compilation
Hocuri Apr 29, 2025
85b99c0
Make debug=1 again for test builds
Hocuri Apr 29, 2025
0184aad
feat: If it's unclear who verified a contact, mark it as verified by …
Hocuri Apr 30, 2025
4a137f2
Resolve TODO
Hocuri May 1, 2025
c1138ce
Add one more info statement
Hocuri May 2, 2025
9dfa853
clippy, formatting
Hocuri May 5, 2025
17ca0b7
Small test improvements
Hocuri May 5, 2025
685688a
fix: Prefer peerstate with newer last_seen if multiple keys have the …
Hocuri May 5, 2025
11ff7ff
small style tweaks
Hocuri May 6, 2025
63fa13a
fix: Keep email email contact in 1:1 chat if PGP contact has a differ…
Hocuri May 6, 2025
a423c58
remove TODO
link2xt May 6, 2025
7a7ebab
unprotect 1:1 chats with email contacts
link2xt May 6, 2025
f61a3d0
deal with NULL verifier in acpeerstates
link2xt May 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions deltachat-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4362,6 +4362,7 @@ pub unsafe extern "C" fn dc_contact_get_verifier_id(contact: *mut dc_contact_t)
.context("failed to get verifier")
.log_err(ctx)
.unwrap_or_default()
.unwrap_or_default()
.unwrap_or_default();

verifier_contact_id.to_u32()
Expand Down
5 changes: 5 additions & 0 deletions deltachat-jsonrpc/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,11 @@ impl CommandApi {
Ok(ctx.get_blobdir().to_str().map(|s| s.to_owned()))
}

async fn get_migration_error(&self, account_id: u32) -> Result<Option<String>> {
let ctx = self.get_context(account_id).await?;
Ok(ctx.get_migration_error())
}

/// Copy file to blob dir.
async fn copy_to_blob_dir(&self, account_id: u32, path: String) -> Result<PathBuf> {
let ctx = self.get_context(account_id).await?;
Expand Down
1 change: 1 addition & 0 deletions deltachat-jsonrpc/src/api/types/contact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ impl ContactObject {
let verifier_id = contact
.get_verifier_id(context)
.await?
.flatten()
.map(|contact_id| contact_id.to_u32());

Ok(ContactObject {
Expand Down
12 changes: 4 additions & 8 deletions src/chat/chat_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1516,15 +1516,10 @@ async fn test_shall_attach_selfavatar() -> Result<()> {
async fn test_profile_data_on_group_leave() -> Result<()> {
let mut tcm = TestContextManager::new();
let t = &tcm.alice().await;
let bob = &tcm.bob().await;
let chat_id = create_group_chat(t, ProtectionStatus::Unprotected, "foo").await?;

let (contact_id, _) = Contact::add_or_lookup(
t,
"",
&ContactAddress::new("[email protected]")?,
Origin::IncomingUnknownTo,
)
.await?;
let contact_id = t.add_or_lookup_contact_id(bob).await;
add_contact_to_chat(t, chat_id, contact_id).await?;

send_text_msg(t, chat_id, "populate".to_string()).await?;
Expand All @@ -1539,7 +1534,8 @@ async fn test_profile_data_on_group_leave() -> Result<()> {

remove_contact_from_chat(t, chat_id, ContactId::SELF).await?;
let sent_msg = t.pop_sent_msg().await;
assert!(sent_msg.payload().contains("Chat-User-Avatar"));
let msg = bob.parse_msg(&sent_msg).await;
assert!(msg.header_exists(HeaderDef::ChatUserAvatar));
Ok(())
}

Expand Down
11 changes: 8 additions & 3 deletions src/contact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1547,11 +1547,14 @@ impl Contact {

/// Returns the `ContactId` that verified the contact.
///
/// If the function returns non-zero result,
/// If this returns Some(_),
/// display green checkmark in the profile and "Introduced by ..." line
/// with the name and address of the contact
/// formatted by [Self::get_name_n_addr].
pub async fn get_verifier_id(&self, context: &Context) -> Result<Option<ContactId>> {
///
/// If this returns `Some(None)`, then the contact is verified,
/// but it's unclear by whom.
pub async fn get_verifier_id(&self, context: &Context) -> Result<Option<Option<ContactId>>> {
let verifier_id: u32 = context
.sql
.query_get_value("SELECT verifier FROM contacts WHERE id=?", (self.id,))
Expand All @@ -1560,8 +1563,10 @@ impl Contact {

if verifier_id == 0 {
Ok(None)
} else if verifier_id == self.id.to_u32() {
Ok(Some(None))
} else {
Ok(Some(ContactId::new(verifier_id)))
Ok(Some(Some(ContactId::new(verifier_id))))
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,13 @@ pub struct InnerContext {
/// `last_error` should be used to avoid races with the event thread.
pub(crate) last_error: parking_lot::RwLock<String>,

/// It's not possible to emit migration errors as an event,
/// because at the time of the migration, there is no event emitter yet.
/// So, this holds the error that happened during migration, if any.
/// This is necessary for the possibly-failible PGP migration,
/// which happened 2025-05, and can be removed a few releases later.
pub(crate) migration_error: parking_lot::RwLock<Option<String>>,

/// If debug logging is enabled, this contains all necessary information
///
/// Standard RwLock instead of [`tokio::sync::RwLock`] is used
Expand Down Expand Up @@ -444,6 +451,7 @@ impl Context {
creation_time: tools::Time::now(),
last_full_folder_scan: Mutex::new(None),
last_error: parking_lot::RwLock::new("".to_string()),
migration_error: parking_lot::RwLock::new(None),
debug_logging: std::sync::RwLock::new(None),
push_subscriber,
push_subscribed: AtomicBool::new(false),
Expand Down
10 changes: 10 additions & 0 deletions src/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ impl Context {
let last_error = &*self.last_error.read();
last_error.clone()
}

pub fn set_migration_error(&self, error: &str) {
let mut migration_error = self.migration_error.write();
*migration_error = Some(error.to_string());
}

pub fn get_migration_error(&self) -> Option<String> {
let migration_error = &*self.migration_error.read();
migration_error.clone()
}
}

pub trait LogExt<T, E>
Expand Down
19 changes: 14 additions & 5 deletions src/sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,19 @@ impl Sql {
async fn try_open(&self, context: &Context, dbfile: &Path, passphrase: String) -> Result<()> {
*self.pool.write().await = Some(Self::new_pool(dbfile, passphrase.to_string())?);

self.run_migrations(context).await?;
if let Err(e) = self.run_migrations(context).await {
error!(context, "Running migrations failed: {e:#}");
// Emiting an error event probably doesn't work
// because we are in the process of opening the context,
// so there is no event emitter yet.
// So, try to report the error in other ways:
eprintln!("Running migrations failed: {e:#}");
context.set_migration_error(&format!("Updating Delta Chat failed. Please send this message to the Delta Chat developers, either at [email protected] or at https://support.delta.chat.\n\n{e:#}"));
// We can't simply close the db for two reasons:
// a. backup export would fail
// b. The UI would think that the account is unconfigured (because `is_configured()` fails)
// and remove the account when the user presses "Back"
}

Ok(())
}
Expand Down Expand Up @@ -263,10 +275,7 @@ impl Sql {
}

let passphrase_nonempty = !passphrase.is_empty();
if let Err(err) = self.try_open(context, &self.dbfile, passphrase).await {
self.close().await;
return Err(err);
}
self.try_open(context, &self.dbfile, passphrase).await?;
info!(context, "Opened database {:?}.", self.dbfile);
*self.is_encrypted.write().await = Some(passphrase_nonempty);

Expand Down
Loading
Loading