1use crate::crypto::keys::RecipientKey;
2use chrono::Utc;
3use rusqlite::params;
4use std::sync::{Arc, Mutex};
5use uuid::Uuid;
6
7#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
8pub struct RegisteredKey {
9 pub id: Uuid,
10 pub alias: String,
11 pub key_type: String,
12 pub public_key: String,
13 pub is_default: bool,
14 pub added_at: chrono::DateTime<Utc>,
15}
16
17pub struct KeyStore {
19 conn: Arc<Mutex<rusqlite::Connection>>,
20}
21
22impl KeyStore {
23 pub fn new(conn: Arc<Mutex<rusqlite::Connection>>) -> Self {
24 Self { conn }
25 }
26
27 pub fn add(&self, alias: &str, key: &RecipientKey) -> crate::error::Result<RegisteredKey> {
29 let id = Uuid::new_v4();
30 let now = Utc::now().to_rfc3339();
31 let conn = self
32 .conn
33 .lock()
34 .map_err(|_| crate::error::MnemeError::Config("mutex poisoned".into()))?;
35 conn.execute(
36 "INSERT INTO encryption_keys (id, alias, key_type, public_key, is_default, added_at)
37 VALUES (?1, ?2, ?3, ?4, 0, ?5)",
38 params![
39 id.to_string(),
40 alias,
41 key.key_type(),
42 key.public_key_string(),
43 now
44 ],
45 )?;
46 Ok(RegisteredKey {
47 id,
48 alias: alias.to_string(),
49 key_type: key.key_type().to_string(),
50 public_key: key.public_key_string(),
51 is_default: false,
52 added_at: Utc::now(),
53 })
54 }
55
56 pub fn remove(&self, key_id: Uuid) -> crate::error::Result<()> {
58 let conn = self
59 .conn
60 .lock()
61 .map_err(|_| crate::error::MnemeError::Config("mutex poisoned".into()))?;
62 let n = conn.execute(
63 "DELETE FROM encryption_keys WHERE id = ?1",
64 params![key_id.to_string()],
65 )?;
66 if n == 0 {
67 return Err(crate::error::MnemeError::KeyNotFound(key_id.to_string()));
68 }
69 Ok(())
70 }
71
72 pub fn list(&self) -> crate::error::Result<Vec<RegisteredKey>> {
74 let conn = self
75 .conn
76 .lock()
77 .map_err(|_| crate::error::MnemeError::Config("mutex poisoned".into()))?;
78 let mut stmt = conn.prepare(
79 "SELECT id, alias, key_type, public_key, is_default, added_at FROM encryption_keys ORDER BY added_at DESC"
80 )?;
81 let keys = stmt
82 .query_map([], |row| {
83 let id_str: String = row.get(0)?;
84 let added_str: String = row.get(5)?;
85 Ok((
86 id_str,
87 row.get::<_, String>(1)?,
88 row.get::<_, String>(2)?,
89 row.get::<_, String>(3)?,
90 row.get::<_, bool>(4)?,
91 added_str,
92 ))
93 })?
94 .filter_map(|r| r.ok())
95 .map(|(id_s, alias, key_type, public_key, is_default, added_s)| {
96 let id = Uuid::parse_str(&id_s).unwrap_or_else(|_| Uuid::new_v4());
97 let added_at = chrono::DateTime::parse_from_rfc3339(&added_s)
98 .map(|d| d.with_timezone(&Utc))
99 .unwrap_or_else(|_| Utc::now());
100 RegisteredKey {
101 id,
102 alias,
103 key_type,
104 public_key,
105 is_default,
106 added_at,
107 }
108 })
109 .collect();
110 Ok(keys)
111 }
112
113 pub fn get_default(&self) -> crate::error::Result<Option<RegisteredKey>> {
115 let all = self.list()?;
116 Ok(all.into_iter().find(|k| k.is_default))
117 }
118
119 pub fn set_default(&self, key_id: Uuid) -> crate::error::Result<()> {
121 let conn = self
122 .conn
123 .lock()
124 .map_err(|_| crate::error::MnemeError::Config("mutex poisoned".into()))?;
125 conn.execute("UPDATE encryption_keys SET is_default = 0", [])?;
126 let n = conn.execute(
127 "UPDATE encryption_keys SET is_default = 1 WHERE id = ?1",
128 params![key_id.to_string()],
129 )?;
130 if n == 0 {
131 return Err(crate::error::MnemeError::KeyNotFound(key_id.to_string()));
132 }
133 Ok(())
134 }
135
136 pub fn load_all_recipients(&self) -> crate::error::Result<Vec<RecipientKey>> {
138 let keys = self.list()?;
139 let mut recipients = Vec::new();
140 for key in keys {
141 match RecipientKey::from_string(&key.public_key) {
142 Ok(r) => recipients.push(r),
143 Err(e) => {
144 tracing::warn!(key_id = %key.id, error = %e, "failed to parse registered key, skipping");
145 }
146 }
147 }
148 Ok(recipients)
149 }
150}