1pub fn get_sql_setting(key: String) -> Result<Option<String>, String> {
5 let conn = super::get_db_connection_guard_static()?;
6 let result: Option<String> = conn.query_row(
7 "SELECT value FROM settings WHERE key = ?1",
8 rusqlite::params![key],
9 |row| row.get(0),
10 ).ok();
11 Ok(result)
12}
13
14pub fn set_sql_setting(key: String, value: String) -> Result<(), String> {
16 let conn = super::get_write_connection_guard_static()?;
17 conn.execute(
18 "INSERT OR REPLACE INTO settings (key, value) VALUES (?1, ?2)",
19 rusqlite::params![key, value],
20 ).map_err(|e| format!("Failed to set setting: {}", e))?;
21 Ok(())
22}
23
24pub fn advance_u64_setting(key: String, value: u64) -> Result<(), String> {
29 let conn = super::get_write_connection_guard_static()?;
30 conn.execute(
31 "INSERT INTO settings (key, value) VALUES (?1, ?2)
32 ON CONFLICT(key) DO UPDATE SET value = excluded.value
33 WHERE CAST(excluded.value AS INTEGER) > CAST(value AS INTEGER)",
34 rusqlite::params![key, value.to_string()],
35 ).map_err(|e| format!("Failed to advance setting: {}", e))?;
36 Ok(())
37}
38
39pub fn remove_setting(key: &str) -> Result<(), String> {
41 let conn = super::get_write_connection_guard_static()?;
42 conn.execute("DELETE FROM settings WHERE key = ?1", rusqlite::params![key])
43 .map_err(|e| format!("Failed to remove setting: {}", e))?;
44 Ok(())
45}
46
47pub fn get_pkey() -> Result<Option<String>, String> {
49 let conn = super::get_db_connection_guard_static()?;
50 Ok(conn.query_row(
51 "SELECT value FROM settings WHERE key = 'pkey'",
52 [],
53 |row| row.get(0),
54 ).ok())
55}
56
57pub fn set_pkey(pkey: &str) -> Result<(), String> {
59 let conn = super::get_write_connection_guard_static()?;
60 conn.execute(
61 "INSERT OR REPLACE INTO settings (key, value) VALUES ('pkey', ?1)",
62 rusqlite::params![pkey],
63 ).map_err(|e| format!("Failed to set pkey: {}", e))?;
64 Ok(())
65}
66
67pub fn get_seed() -> Result<Option<String>, String> {
69 let conn = super::get_db_connection_guard_static()?;
70 Ok(conn.query_row(
71 "SELECT value FROM settings WHERE key = 'seed'",
72 [],
73 |row| row.get(0),
74 ).ok())
75}
76
77pub fn set_seed(seed: &str) -> Result<(), String> {
79 let conn = super::get_write_connection_guard_static()?;
80 conn.execute(
81 "INSERT OR REPLACE INTO settings (key, value) VALUES ('seed', ?1)",
82 rusqlite::params![seed],
83 ).map_err(|e| format!("Failed to set seed: {}", e))?;
84 Ok(())
85}
86
87pub fn commit_account_setup(
102 pkey: &str,
103 encryption_enabled: bool,
104 security_type: Option<&str>,
105 encrypted_seed: Option<&str>,
106 biometric_wrap: Option<&str>,
107) -> Result<(), String> {
108 let mut conn = super::get_write_connection_guard_static()?;
109 let tx = conn.transaction()
110 .map_err(|e| format!("Failed to begin tx: {}", e))?;
111 tx.execute(
112 "INSERT OR REPLACE INTO settings (key, value) VALUES ('pkey', ?1)",
113 rusqlite::params![pkey],
114 ).map_err(|e| format!("Failed to set pkey: {}", e))?;
115 tx.execute(
116 "INSERT OR REPLACE INTO settings (key, value) VALUES ('encryption_enabled', ?1)",
117 rusqlite::params![if encryption_enabled { "true" } else { "false" }],
118 ).map_err(|e| format!("Failed to set encryption_enabled: {}", e))?;
119 if let Some(st) = security_type {
120 tx.execute(
121 "INSERT OR REPLACE INTO settings (key, value) VALUES ('security_type', ?1)",
122 rusqlite::params![st],
123 ).map_err(|e| format!("Failed to set security_type: {}", e))?;
124 } else {
125 tx.execute(
128 "DELETE FROM settings WHERE key = 'security_type'",
129 [],
130 ).map_err(|e| format!("Failed to clear security_type: {}", e))?;
131 }
132 if let Some(seed) = encrypted_seed {
133 tx.execute(
134 "INSERT OR REPLACE INTO settings (key, value) VALUES ('seed', ?1)",
135 rusqlite::params![seed],
136 ).map_err(|e| format!("Failed to set seed: {}", e))?;
137 }
138 tx.execute(
143 "INSERT OR REPLACE INTO settings (key, value) VALUES ('signer_type', 'local')",
144 [],
145 ).map_err(|e| format!("Failed to set signer_type: {}", e))?;
146 match biometric_wrap {
151 Some(w) => {
152 tx.execute(
153 "INSERT OR REPLACE INTO settings (key, value) VALUES ('biometric_wrapped_key', ?1)",
154 rusqlite::params![w],
155 ).map_err(|e| format!("Failed to set biometric wrap: {}", e))?;
156 }
157 None => {
158 tx.execute(
159 "DELETE FROM settings WHERE key = 'biometric_wrapped_key'",
160 [],
161 ).map_err(|e| format!("Failed to clear biometric wrap: {}", e))?;
162 }
163 }
164
165 tx.commit().map_err(|e| format!("Failed to commit tx: {}", e))?;
166 Ok(())
167}
168
169pub fn get_signer_type() -> Result<String, String> {
187 let conn = super::get_db_connection_guard_static()?;
188 Ok(conn.query_row(
189 "SELECT value FROM settings WHERE key = 'signer_type'",
190 [],
191 |row| row.get::<_, String>(0),
192 ).unwrap_or_else(|_| "local".to_string()))
193}
194
195pub fn set_signer_type(value: &str) -> Result<(), String> {
199 let conn = super::get_write_connection_guard_static()?;
200 conn.execute(
201 "INSERT OR REPLACE INTO settings (key, value) VALUES ('signer_type', ?1)",
202 rusqlite::params![value],
203 ).map_err(|e| format!("Failed to set signer_type: {}", e))?;
204 Ok(())
205}
206
207pub async fn get_bunker_url() -> Result<Option<String>, String> {
211 let raw: Option<String> = {
212 let conn = super::get_db_connection_guard_static()?;
213 conn.query_row(
214 "SELECT value FROM settings WHERE key = 'bunker_url'",
215 [],
216 |row| row.get::<_, String>(0),
217 ).ok()
218 };
219 match raw {
220 Some(s) => match crate::crypto::maybe_decrypt(s).await {
221 Ok(plain) => Ok(Some(plain)),
222 Err(_) => Err("bunker_url decryption failed (account locked?)".into()),
223 },
224 None => Ok(None),
225 }
226}
227
228pub async fn set_bunker_url(url: &str) -> Result<(), String> {
231 let stored = crate::crypto::maybe_encrypt(url.to_string()).await;
232 let conn = super::get_write_connection_guard_static()?;
233 conn.execute(
234 "INSERT OR REPLACE INTO settings (key, value) VALUES ('bunker_url', ?1)",
235 rusqlite::params![stored],
236 ).map_err(|e| format!("Failed to set bunker_url: {}", e))?;
237 Ok(())
238}
239
240pub fn get_bunker_remote_pubkey() -> Result<Option<String>, String> {
245 let conn = super::get_db_connection_guard_static()?;
246 Ok(conn.query_row(
247 "SELECT value FROM settings WHERE key = 'bunker_remote_pubkey'",
248 [],
249 |row| row.get::<_, String>(0),
250 ).ok())
251}
252
253pub fn set_bunker_remote_pubkey(pubkey_hex: &str) -> Result<(), String> {
257 let conn = super::get_write_connection_guard_static()?;
258 conn.execute(
259 "INSERT OR REPLACE INTO settings (key, value) VALUES ('bunker_remote_pubkey', ?1)",
260 rusqlite::params![pubkey_hex],
261 ).map_err(|e| format!("Failed to set bunker_remote_pubkey: {}", e))?;
262 Ok(())
263}
264
265pub fn commit_bunker_account_setup(
276 pkey: &str,
277 encryption_enabled: bool,
278 security_type: Option<&str>,
279 bunker_url_stored: &str,
280 bunker_remote_pubkey_hex: &str,
281 biometric_wrap: Option<&str>,
282) -> Result<(), String> {
283 let mut conn = super::get_write_connection_guard_static()?;
284 let tx = conn.transaction()
285 .map_err(|e| format!("Failed to begin tx: {}", e))?;
286 tx.execute(
287 "INSERT OR REPLACE INTO settings (key, value) VALUES ('pkey', ?1)",
288 rusqlite::params![pkey],
289 ).map_err(|e| format!("Failed to set pkey: {}", e))?;
290 tx.execute(
291 "INSERT OR REPLACE INTO settings (key, value) VALUES ('encryption_enabled', ?1)",
292 rusqlite::params![if encryption_enabled { "true" } else { "false" }],
293 ).map_err(|e| format!("Failed to set encryption_enabled: {}", e))?;
294 if let Some(st) = security_type {
295 tx.execute(
296 "INSERT OR REPLACE INTO settings (key, value) VALUES ('security_type', ?1)",
297 rusqlite::params![st],
298 ).map_err(|e| format!("Failed to set security_type: {}", e))?;
299 } else {
300 tx.execute(
301 "DELETE FROM settings WHERE key = 'security_type'",
302 [],
303 ).map_err(|e| format!("Failed to clear security_type: {}", e))?;
304 }
305 tx.execute(
306 "INSERT OR REPLACE INTO settings (key, value) VALUES ('signer_type', 'bunker')",
307 [],
308 ).map_err(|e| format!("Failed to set signer_type: {}", e))?;
309 tx.execute(
310 "INSERT OR REPLACE INTO settings (key, value) VALUES ('bunker_url', ?1)",
311 rusqlite::params![bunker_url_stored],
312 ).map_err(|e| format!("Failed to set bunker_url: {}", e))?;
313 tx.execute(
314 "INSERT OR REPLACE INTO settings (key, value) VALUES ('bunker_remote_pubkey', ?1)",
315 rusqlite::params![bunker_remote_pubkey_hex],
316 ).map_err(|e| format!("Failed to set bunker_remote_pubkey: {}", e))?;
317 tx.execute("DELETE FROM settings WHERE key = 'seed'", [])
319 .map_err(|e| format!("Failed to clear stale seed: {}", e))?;
320 match biometric_wrap {
325 Some(w) => {
326 tx.execute(
327 "INSERT OR REPLACE INTO settings (key, value) VALUES ('biometric_wrapped_key', ?1)",
328 rusqlite::params![w],
329 ).map_err(|e| format!("Failed to set biometric wrap: {}", e))?;
330 }
331 None => {
332 tx.execute(
333 "DELETE FROM settings WHERE key = 'biometric_wrapped_key'",
334 [],
335 ).map_err(|e| format!("Failed to clear biometric wrap: {}", e))?;
336 }
337 }
338
339 tx.commit().map_err(|e| format!("Failed to commit tx: {}", e))?;
340 Ok(())
341}
342
343pub fn get_nip55_user_pubkey() -> Result<Option<String>, String> {
363 let conn = super::get_db_connection_guard_static()?;
364 Ok(conn.query_row(
365 "SELECT value FROM settings WHERE key = 'nip55_user_pubkey'",
366 [],
367 |row| row.get::<_, String>(0),
368 ).ok())
369}
370
371pub fn set_nip55_user_pubkey(pubkey_hex: &str) -> Result<(), String> {
373 let conn = super::get_write_connection_guard_static()?;
374 conn.execute(
375 "INSERT OR REPLACE INTO settings (key, value) VALUES ('nip55_user_pubkey', ?1)",
376 rusqlite::params![pubkey_hex],
377 ).map_err(|e| format!("Failed to set nip55_user_pubkey: {}", e))?;
378 Ok(())
379}
380
381pub fn get_nip55_signer_package() -> Result<Option<String>, String> {
384 let conn = super::get_db_connection_guard_static()?;
385 Ok(conn.query_row(
386 "SELECT value FROM settings WHERE key = 'nip55_signer_package'",
387 [],
388 |row| row.get::<_, String>(0),
389 ).ok())
390}
391
392pub fn set_nip55_signer_package(package: &str) -> Result<(), String> {
394 let conn = super::get_write_connection_guard_static()?;
395 conn.execute(
396 "INSERT OR REPLACE INTO settings (key, value) VALUES ('nip55_signer_package', ?1)",
397 rusqlite::params![package],
398 ).map_err(|e| format!("Failed to set nip55_signer_package: {}", e))?;
399 Ok(())
400}
401
402pub fn commit_nip55_account_setup(
409 user_pubkey_hex: &str,
410 signer_package: &str,
411 encryption_enabled: bool,
412 security_type: Option<&str>,
413 biometric_wrap: Option<&str>,
414 pin_canary: Option<&str>,
415) -> Result<(), String> {
416 let mut conn = super::get_write_connection_guard_static()?;
417 let tx = conn.transaction()
418 .map_err(|e| format!("Failed to begin tx: {}", e))?;
419 tx.execute(
420 "INSERT OR REPLACE INTO settings (key, value) VALUES ('encryption_enabled', ?1)",
421 rusqlite::params![if encryption_enabled { "true" } else { "false" }],
422 ).map_err(|e| format!("Failed to set encryption_enabled: {}", e))?;
423 if let Some(st) = security_type {
424 tx.execute(
425 "INSERT OR REPLACE INTO settings (key, value) VALUES ('security_type', ?1)",
426 rusqlite::params![st],
427 ).map_err(|e| format!("Failed to set security_type: {}", e))?;
428 } else {
429 tx.execute(
430 "DELETE FROM settings WHERE key = 'security_type'",
431 [],
432 ).map_err(|e| format!("Failed to clear security_type: {}", e))?;
433 }
434 tx.execute(
435 "INSERT OR REPLACE INTO settings (key, value) VALUES ('signer_type', 'nip55')",
436 [],
437 ).map_err(|e| format!("Failed to set signer_type: {}", e))?;
438 tx.execute(
439 "INSERT OR REPLACE INTO settings (key, value) VALUES ('nip55_user_pubkey', ?1)",
440 rusqlite::params![user_pubkey_hex],
441 ).map_err(|e| format!("Failed to set nip55_user_pubkey: {}", e))?;
442 tx.execute(
443 "INSERT OR REPLACE INTO settings (key, value) VALUES ('nip55_signer_package', ?1)",
444 rusqlite::params![signer_package],
445 ).map_err(|e| format!("Failed to set nip55_signer_package: {}", e))?;
446 for stale in ["pkey", "seed", "bunker_url", "bunker_remote_pubkey"] {
449 tx.execute(
450 "DELETE FROM settings WHERE key = ?1",
451 rusqlite::params![stale],
452 ).map_err(|e| format!("Failed to clear stale {}: {}", stale, e))?;
453 }
454 match biometric_wrap {
459 Some(w) => {
460 tx.execute(
461 "INSERT OR REPLACE INTO settings (key, value) VALUES ('biometric_wrapped_key', ?1)",
462 rusqlite::params![w],
463 ).map_err(|e| format!("Failed to set biometric wrap: {}", e))?;
464 }
465 None => {
466 tx.execute(
467 "DELETE FROM settings WHERE key = 'biometric_wrapped_key'",
468 [],
469 ).map_err(|e| format!("Failed to clear biometric wrap: {}", e))?;
470 }
471 }
472
473 match pin_canary {
477 Some(c) => {
478 tx.execute(
479 "INSERT OR REPLACE INTO settings (key, value) VALUES ('nip55_pin_check', ?1)",
480 rusqlite::params![c],
481 ).map_err(|e| format!("Failed to set pin canary: {}", e))?;
482 }
483 None => {
484 tx.execute(
485 "DELETE FROM settings WHERE key = 'nip55_pin_check'",
486 [],
487 ).map_err(|e| format!("Failed to clear pin canary: {}", e))?;
488 }
489 }
490
491 tx.commit().map_err(|e| format!("Failed to commit tx: {}", e))?;
492 Ok(())
493}