fix: If importing a backup fails, delete the partially-imported profile (#7885)

fix https://github.com/chatmail/core/issues/7863

`test_import_encrypted_bak_into_encrypted_acct` CFFI test fails because
it tests that trying to import an encrypted account with a wrong
passphrase into an already-encrypted database will fail, but leave the
already-encrypted database (esp, leave it with the same password).

But in order to reset the database after a failed login attempt, I'm
using this code:

```rust
        context.sql.close().await;
        fs::remove_file(context.sql.dbfile.as_path())
            .await
            .log_err(context)
            .ok();
        context
            .sql
            .open(context, "".to_string()) // <-- NOTE THIS LINE
            .await
            .log_err(context)
            .ok();
```

We're not remembering the password, so, we can't just pass the correct
password there.

Since password-protected databases are not really supported anyways, we
decided to just skip the test.

I also tried two tricks for deleting everything [found on
Stackoverflow](https://stackoverflow.com/questions/525512/drop-all-tables-command),
but neither of them managed to actually reset the database (i.e. they
led to a failed Rust test, because asserting
`!context2.is_configured().await?` failed):

```rust
        context
            .sql
            .call_write(|conn| {
                let mut stmt = conn.prepare(
                    "select 'drop table ' || name || ';' from sqlite_master where type = 'table';",
                )?;
                let mut iter = stmt.query(())?;
                while iter.next()?.is_some() {}
                Ok(())
            })
            .await
            .log_err(context)
            .ok();
        context
            .sql
            .run_migrations(context)
            .await
            .log_err(context)
            .ok();
```

```rust
        context
            .sql
            .transaction(|t| {
                t.execute_batch(
                    "
PRAGMA writable_schema = 1;
delete from sqlite_master where type in ('table', 'index', 'trigger');
PRAGMA writable_schema = 0",
                )?;
                Ok(())
            })
            .await
            .log_err(context)
            .ok();
        context
            .sql
            .run_migrations(context)
            .await
            .log_err(context)
            .ok();
```

---------

Co-authored-by: l <link2xt@testrun.org>
This commit is contained in:
Hocuri
2026-02-25 16:25:33 +01:00
committed by GitHub
parent d7bf10d7a4
commit 7d8989a068
3 changed files with 138 additions and 16 deletions

View File

@@ -467,6 +467,32 @@ mod tests {
}
}
/// Tests that trying to accidentally overwrite a profile
/// that is in use will fail.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_cant_overwrite_profile_in_use() -> Result<()> {
let mut tcm = TestContextManager::new();
let ctx0 = &tcm.alice().await;
let ctx1 = &tcm.bob().await;
// Prepare to transfer backup.
let provider = BackupProvider::prepare(ctx0).await?;
// Try to overwrite an existing profile.
let err = get_backup(ctx1, provider.qr()).await.unwrap_err();
assert!(format!("{err:#}").contains("Cannot import backups to accounts in use"));
// ctx0 is supposed to also finish, and emit an error:
provider.await.unwrap();
ctx0.evtracker
.get_matching(|e| matches!(e, EventType::Error(_)))
.await;
assert_eq!(ctx1.get_primary_self_addr().await?, "bob@example.net");
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_drop_provider() {
let mut tcm = TestContextManager::new();