Skip to content

Commit 6cd5fda

Browse files
committed
refactor(sql): recreate keypairs table
Removed unused `addr` and `created` field. `is_default` boolean flag is moved into `config` row pointing to the current default key.
1 parent 0c8cbf0 commit 6cd5fda

File tree

5 files changed

+62
-53
lines changed

5 files changed

+62
-53
lines changed

src/config.rs

+4-14
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::context::Context;
1515
use crate::events::EventType;
1616
use crate::mimefactory::RECOMMENDED_FILE_SIZE;
1717
use crate::provider::{get_provider_by_id, Provider};
18-
use crate::tools::{get_abs_path, improve_single_line_input, EmailAddress};
18+
use crate::tools::{get_abs_path, improve_single_line_input};
1919

2020
/// The available configuration keys.
2121
#[derive(
@@ -338,6 +338,9 @@ pub enum Config {
338338
/// until `chat_id.accept()` is called.
339339
#[strum(props(default = "0"))]
340340
VerifiedOneOnOneChats,
341+
342+
/// ID of the key in the `keypairs` table used for signatures.
343+
KeyId,
341344
}
342345

343346
impl Context {
@@ -576,8 +579,6 @@ impl Context {
576579
///
577580
/// This should only be used by test code and during configure.
578581
pub(crate) async fn set_primary_self_addr(&self, primary_new: &str) -> Result<()> {
579-
let old_addr = self.get_config(Config::ConfiguredAddr).await?;
580-
581582
// add old primary address (if exists) to secondary addresses
582583
let mut secondary_addrs = self.get_all_self_addrs().await?;
583584
// never store a primary address also as a secondary
@@ -591,17 +592,6 @@ impl Context {
591592
self.set_config(Config::ConfiguredAddr, Some(primary_new))
592593
.await?;
593594

594-
if let Some(old_addr) = old_addr {
595-
let old_addr = EmailAddress::new(&old_addr)?;
596-
let old_keypair = crate::key::load_keypair(self, &old_addr).await?;
597-
598-
if let Some(mut old_keypair) = old_keypair {
599-
old_keypair.addr = EmailAddress::new(primary_new)?;
600-
crate::key::store_self_keypair(self, &old_keypair, crate::key::KeyPairUse::Default)
601-
.await?;
602-
}
603-
}
604-
605595
Ok(())
606596
}
607597

src/context.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1318,6 +1318,7 @@ mod tests {
13181318
"socks5_port",
13191319
"socks5_user",
13201320
"socks5_password",
1321+
"key_id",
13211322
];
13221323
let t = TestContext::new().await;
13231324
let info = t.get_info().await.unwrap();

src/imex.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ async fn export_self_keys(context: &Context, dir: &Path) -> Result<()> {
670670
let keys = context
671671
.sql
672672
.query_map(
673-
"SELECT id, public_key, private_key, is_default FROM keypairs;",
673+
"SELECT id, public_key, private_key, id=(SELECT value FROM config WHERE keyname='key_id') FROM keypairs;",
674674
(),
675675
|row| {
676676
let id = row.get(0)?;

src/key.rs

+26-38
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::constants::KeyGenType;
1818
use crate::context::Context;
1919
use crate::log::LogExt;
2020
use crate::pgp::KeyPair;
21-
use crate::tools::{time, EmailAddress};
21+
use crate::tools::EmailAddress;
2222

2323
/// Convenience trait for working with keys.
2424
///
@@ -82,10 +82,9 @@ pub(crate) async fn load_self_public_key(context: &Context) -> Result<SignedPubl
8282
match context
8383
.sql
8484
.query_row_optional(
85-
r#"SELECT public_key
86-
FROM keypairs
87-
WHERE addr=(SELECT value FROM config WHERE keyname="configured_addr")
88-
AND is_default=1"#,
85+
"SELECT public_key
86+
FROM keypairs
87+
WHERE id=(SELECT value FROM config WHERE keyname='key_id')",
8988
(),
9089
|row| {
9190
let bytes: Vec<u8> = row.get(0)?;
@@ -106,10 +105,9 @@ pub(crate) async fn load_self_secret_key(context: &Context) -> Result<SignedSecr
106105
match context
107106
.sql
108107
.query_row_optional(
109-
r#"SELECT private_key
110-
FROM keypairs
111-
WHERE addr=(SELECT value FROM config WHERE keyname="configured_addr")
112-
AND is_default=1"#,
108+
"SELECT private_key
109+
FROM keypairs
110+
WHERE id=(SELECT value FROM config WHERE keyname='key_id')",
113111
(),
114112
|row| {
115113
let bytes: Vec<u8> = row.get(0)?;
@@ -132,8 +130,7 @@ pub(crate) async fn load_self_secret_keyring(context: &Context) -> Result<Vec<Si
132130
.query_map(
133131
r#"SELECT private_key
134132
FROM keypairs
135-
WHERE addr=(SELECT value FROM config WHERE keyname="configured_addr")
136-
ORDER BY is_default DESC"#,
133+
ORDER BY id=(SELECT value FROM config WHERE keyname='key_id') DESC"#,
137134
(),
138135
|row| row.get::<_, Vec<u8>>(0),
139136
|keys| keys.collect::<Result<Vec<_>, _>>().map_err(Into::into),
@@ -233,13 +230,10 @@ pub(crate) async fn load_keypair(
233230
let res = context
234231
.sql
235232
.query_row_optional(
236-
r#"
237-
SELECT public_key, private_key
238-
FROM keypairs
239-
WHERE addr=?1
240-
AND is_default=1;
241-
"#,
242-
(addr,),
233+
"SELECT public_key, private_key
234+
FROM keypairs
235+
WHERE id=(SELECT value FROM config WHERE keyname='key_id')",
236+
(),
243237
|row| {
244238
let pub_bytes: Vec<u8> = row.get(0)?;
245239
let sec_bytes: Vec<u8> = row.get(1)?;
@@ -293,32 +287,26 @@ pub async fn store_self_keypair(
293287
.transaction(|transaction| {
294288
let public_key = DcKey::to_bytes(&keypair.public);
295289
let secret_key = DcKey::to_bytes(&keypair.secret);
296-
transaction
297-
.execute(
298-
"DELETE FROM keypairs WHERE public_key=? OR private_key=?;",
299-
(&public_key, &secret_key),
300-
)
301-
.context("failed to remove old use of key")?;
302-
if default == KeyPairUse::Default {
303-
transaction
304-
.execute("UPDATE keypairs SET is_default=0;", ())
305-
.context("failed to clear default")?;
306-
}
290+
307291
let is_default = match default {
308-
KeyPairUse::Default => i32::from(true),
309-
KeyPairUse::ReadOnly => i32::from(false),
292+
KeyPairUse::Default => true,
293+
KeyPairUse::ReadOnly => false,
310294
};
311295

312-
let addr = keypair.addr.to_string();
313-
let t = time();
314-
315296
transaction
316297
.execute(
317-
"INSERT INTO keypairs (addr, is_default, public_key, private_key, created)
318-
VALUES (?,?,?,?,?);",
319-
(addr, is_default, &public_key, &secret_key, t),
298+
"INSERT OR REPLACE INTO keypairs (public_key, private_key)
299+
VALUES (?,?)",
300+
(&public_key, &secret_key),
320301
)
321-
.context("failed to insert keypair")?;
302+
.context("Failed to insert keypair")?;
303+
304+
if is_default {
305+
transaction.execute(
306+
"INSERT OR REPLACE INTO config (keyname, value) VALUES ('key_id', ?)",
307+
(transaction.last_insert_rowid(),),
308+
)?;
309+
}
322310

323311
Ok(())
324312
})

src/sql/migrations.rs

+30
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,36 @@ CREATE INDEX config_index1 ON config (keyname);
806806
.await?;
807807
}
808808

809+
if dbversion < 107 {
810+
sql.execute_migration(
811+
"CREATE TABLE new_keypairs (
812+
id INTEGER PRIMARY KEY AUTOINCREMENT,
813+
private_key UNIQUE NOT NULL,
814+
public_key UNIQUE NOT NULL
815+
);
816+
INSERT OR IGNORE INTO new_keypairs SELECT id, private_key, public_key FROM keypairs;
817+
818+
INSERT OR IGNORE
819+
INTO config (keyname, value)
820+
VALUES
821+
('key_id', (SELECT id FROM new_keypairs
822+
WHERE private_key=
823+
(SELECT private_key FROM keypairs
824+
WHERE addr=(SELECT value FROM config WHERE keyname='configured_addr')
825+
AND is_default=1)));
826+
827+
-- We do not drop the old `keypairs` table for now,
828+
-- but move it to `old_keypairs`. We can remove it later
829+
-- in next migrations. This may be needed for recovery
830+
-- in case something is wrong with the migration.
831+
ALTER TABLE keypairs RENAME TO old_keypairs;
832+
ALTER TABLE new_keypairs RENAME TO keypairs;
833+
",
834+
107,
835+
)
836+
.await?;
837+
}
838+
809839
let new_version = sql
810840
.get_raw_config_int(VERSION_CFG)
811841
.await?

0 commit comments

Comments
 (0)