1use crate::Lake;
2use anyhow::Result;
3use dkdc_config::SECRETS_TABLE_NAME;
4use duckdb::params;
5
6impl Lake {
7 pub fn create_secrets_table(&self) -> Result<()> {
8 let sql = format!(
9 "CREATE TABLE IF NOT EXISTS {} (
10 filepath VARCHAR,
11 filename VARCHAR,
12 filedata BLOB,
13 filesize BIGINT,
14 fileupdated TIMESTAMP
15 )",
16 SECRETS_TABLE_NAME
17 );
18 self.execute(&sql)?;
19 Ok(())
20 }
21
22 pub fn set_secret(&self, name: &str, value: &[u8]) -> Result<()> {
23 self.create_secrets_table()?;
24
25 let sql = format!(
26 "INSERT INTO {} (filepath, filename, filedata, filesize, fileupdated)
27 VALUES (?, ?, ?, ?, ?)",
28 SECRETS_TABLE_NAME
29 );
30
31 let mut stmt = self.prepare(&sql)?;
32 use chrono::Utc;
33 stmt.execute(params![
34 "./secrets",
35 name,
36 value,
37 value.len() as i64,
38 Utc::now().to_rfc3339(),
39 ])?;
40
41 Ok(())
42 }
43
44 pub fn get_secret(&self, name: &str) -> Result<Option<Vec<u8>>> {
45 let sql = format!(
46 "SELECT filedata
47 FROM {}
48 WHERE filepath = './secrets' AND filename = ?
49 ORDER BY fileupdated DESC
50 LIMIT 1",
51 SECRETS_TABLE_NAME
52 );
53
54 let mut stmt = self.prepare(&sql)?;
55 let mut rows = stmt.query(params![name])?;
56
57 if let Some(row) = rows.next()? {
58 Ok(Some(row.get(0)?))
59 } else {
60 Ok(None)
61 }
62 }
63
64 pub fn list_secrets(&self) -> Result<Vec<String>> {
65 let sql = format!(
66 "SELECT DISTINCT filename
67 FROM {}
68 WHERE filepath = './secrets'
69 ORDER BY filename",
70 SECRETS_TABLE_NAME
71 );
72
73 let mut stmt = self.prepare(&sql)?;
74 let mut rows = stmt.query([])?;
75
76 let mut secrets = Vec::new();
77 while let Some(row) = rows.next()? {
78 secrets.push(row.get(0)?);
79 }
80
81 Ok(secrets)
82 }
83
84 pub fn delete_secret(&self, name: &str) -> Result<bool> {
85 let sql = format!(
86 "DELETE FROM {} WHERE filepath = './secrets' AND filename = ?",
87 SECRETS_TABLE_NAME
88 );
89
90 let mut stmt = self.prepare(&sql)?;
91 let count = stmt.execute(params![name])?;
92
93 Ok(count > 0)
94 }
95}