fix: db types conversion

This commit is contained in:
kaichaosun 2026-02-27 14:09:18 +08:00
parent f3aa5d5cf0
commit e099d5fd15
No known key found for this signature in database
GPG Key ID: 223E0F992F4F03BF
4 changed files with 37 additions and 15 deletions

View File

@ -24,6 +24,13 @@ impl Identity {
}
}
pub fn from_secret(name: impl Into<String>, secret: PrivateKey) -> Self {
Self {
name: name.into(),
secret,
}
}
pub fn public_key(&self) -> PublicKey {
PublicKey::from(&self.secret)
}

View File

@ -12,6 +12,7 @@ const CHAT_SCHEMA: &str = "
-- Identity table (single row)
CREATE TABLE IF NOT EXISTS identity (
id INTEGER PRIMARY KEY CHECK (id = 1),
name TEXT NOT NULL,
secret_key BLOB NOT NULL
);
@ -61,10 +62,12 @@ impl ChatStorage {
/// Saves the identity (secret key).
pub fn save_identity(&mut self, identity: &Identity) -> Result<(), StorageError> {
let record = IdentityRecord::from(identity);
self.db.connection().execute(
"INSERT OR REPLACE INTO identity (id, secret_key) VALUES (1, ?1)",
params![record.secret_key.as_slice()],
"INSERT OR REPLACE INTO identity (id, name, secret_key) VALUES (1, ?1, ?2)",
params![
identity.get_name(),
identity.secret().DANGER_to_bytes().as_slice()
],
)?;
Ok(())
}
@ -74,19 +77,23 @@ impl ChatStorage {
let mut stmt = self
.db
.connection()
.prepare("SELECT secret_key FROM identity WHERE id = 1")?;
.prepare("SELECT name, secret_key FROM identity WHERE id = 1")?;
let result = stmt.query_row([], |row| {
let secret_key: Vec<u8> = row.get(0)?;
Ok(secret_key)
let name: String = row.get(0)?;
let secret_key: Vec<u8> = row.get(1)?;
Ok((name, secret_key))
});
match result {
Ok(secret_key) => {
Ok((name, secret_key)) => {
let bytes: [u8; 32] = secret_key
.try_into()
.map_err(|_| StorageError::InvalidData("Invalid secret key length".into()))?;
let record = IdentityRecord { secret_key: bytes };
let record = IdentityRecord {
name,
secret_key: bytes,
};
Ok(Some(Identity::from(record)))
}
Err(RusqliteError::QueryReturnedNoRows) => Ok(None),
@ -229,13 +236,13 @@ mod tests {
assert!(storage.load_identity().unwrap().is_none());
// Save identity
let identity = Identity::new();
let address = identity.address();
let identity = Identity::new("default");
let pubkey = identity.public_key();
storage.save_identity(&identity).unwrap();
// Load identity
let loaded = storage.load_identity().unwrap().unwrap();
assert_eq!(loaded.address(), address);
assert_eq!(loaded.public_key(), pubkey);
}
#[test]

View File

@ -3,13 +3,16 @@
//! Note: Ratchet state types (RatchetStateRecord, SkippedKeyRecord) are in
//! double_ratchets::storage module and handled by RatchetStorage.
use x25519_dalek::{PublicKey, StaticSecret};
use x25519_dalek::PublicKey;
use crate::crypto::PrivateKey;
use crate::identity::Identity;
/// Record for storing identity (secret key).
#[derive(Debug)]
pub struct IdentityRecord {
/// The identity name.
pub name: String,
/// The secret key bytes (32 bytes).
pub secret_key: [u8; 32],
}
@ -17,15 +20,16 @@ pub struct IdentityRecord {
impl From<&Identity> for IdentityRecord {
fn from(identity: &Identity) -> Self {
Self {
secret_key: identity.secret().to_bytes(),
name: identity.get_name().to_string(),
secret_key: identity.secret().DANGER_to_bytes(),
}
}
}
impl From<IdentityRecord> for Identity {
fn from(record: IdentityRecord) -> Self {
let secret = StaticSecret::from(record.secret_key);
Identity::from_secret(secret)
let secret = PrivateKey::from(record.secret_key);
Identity::from_secret(record.name, secret)
}
}

View File

@ -26,6 +26,10 @@ pub enum StorageError {
/// Transaction error.
#[error("transaction error: {0}")]
Transaction(String),
/// Invalid data error.
#[error("invalid data: {0}")]
InvalidData(String),
}
impl From<rusqlite::Error> for StorageError {