feat: v1.0.5, auto repair table keys

This commit is contained in:
2024-11-23 23:05:22 +08:00
parent 1cad0ee922
commit 4796b53aae
3 changed files with 68 additions and 15 deletions

2
Cargo.lock generated
View File

@@ -997,7 +997,7 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]]
name = "local-mini-kms"
version = "1.0.4"
version = "1.0.5"
dependencies = [
"aes-gcm-stream",
"aes-kw",

View File

@@ -1,6 +1,6 @@
[package]
name = "local-mini-kms"
version = "1.0.4"
version = "1.0.5"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@@ -24,24 +24,73 @@ pub fn open_db(db: &str) -> XResult<Connection> {
}
pub fn init_db(conn: &Connection) -> XResult<bool> {
let mut stmt = conn.prepare(
"SELECT name FROM sqlite_master WHERE type='table' AND name='keys'")?;
let mut rows = stmt.query(())?;
if rows.next()?.is_some() {
log::info!("Table keys exists, skip init");
return Ok(false);
if let Ok(false) = check_table_keys(conn) {
repair_table_keys(conn)?;
}
let _ = conn.execute(r##"
Ok(true)
}
fn repair_table_keys(conn: &Connection) -> XResult<()> {
let field_names = list_table_fields(conn, "keys")?;
let field_names = field_names.iter().map(|n| n.as_str()).collect::<Vec<_>>();
if !field_names.contains(&"comment") {
log::info!("Repair table keys, add column comment");
let _ = conn.execute("ALTER TABLE keys ADD COLUMN comment TEXT", ())?;
}
Ok(())
}
fn list_table_fields(conn: &Connection, table: &str) -> XResult<Vec<String>> {
let mut stmt_query_fields = conn.prepare(&format!("pragma table_info({})", table))?;
let mut rows_query_field = stmt_query_fields.query(())?;
let mut field_names = vec![];
let mut next_query_field_opt = rows_query_field.next()?;
while let Some(next_query_field) = next_query_field_opt {
// cid|name|type|notnull|dflt_value|pk
// ^ ^ ^ ^ ^ ^
// | | | | | [5] - Is column PK
// | | | | [4] Column default value
// | | | [3] Is column not null
// | | [2] Column type
// | [1] Column name
// [0] Column index
let field_name: String = next_query_field.get(1)?;
field_names.push(field_name.to_lowercase());
next_query_field_opt = rows_query_field.next()?;
}
log::trace!("Table {} fields: {:?}", table, field_names);
Ok(field_names)
}
fn check_table_keys(conn: &Connection) -> XResult<bool> {
let mut stmt =
conn.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='keys'")?;
let mut rows = stmt.query(())?;
if rows.next()?.is_none() {
log::info!("Create table keys");
create_table_keys(conn)?;
Ok(true)
} else {
Ok(false)
}
}
fn create_table_keys(conn: &Connection) -> XResult<()> {
let _ = conn.execute(
r##"
CREATE TABLE keys (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
value TEXT,
comment TEXT
)
"##, ())?;
log::info!("Table keys created");
Ok(true)
)"##,
(),
)?;
Ok(())
}
pub fn insert_key(conn: &Connection, key: &Key) -> XResult<()> {
@@ -49,7 +98,11 @@ pub fn insert_key(conn: &Connection, key: &Key) -> XResult<()> {
log::debug!("insert key name={}", &key.name);
let _ = conn.execute(
"INSERT INTO keys (name, value, comment) VALUES (?1, ?2, ?3)",
(&key.name, &key.encrypted_key, key.comment.as_ref().unwrap_or(&default_comment)),
(
&key.name,
&key.encrypted_key,
key.comment.as_ref().unwrap_or(&default_comment),
),
)?;
Ok(())
}
@@ -90,4 +143,4 @@ pub fn find_key(conn: &Connection, name: &str) -> XResult<Option<Key>> {
}
Some(Err(e)) => simple_error!("Find key failed: {}", e),
}
}
}