crypto: Implement the key/value store for the sqlite store.
This commit is contained in:
parent
41529a6bff
commit
af4b00195b
3 changed files with 76 additions and 9 deletions
|
@ -172,8 +172,9 @@ impl CryptoStore for MemoryStore {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn remove_value(&self, key: &str) -> Result<Option<String>> {
|
||||
Ok(self.values.remove(key).map(|(_, v)| v))
|
||||
async fn remove_value(&self, key: &str) -> Result<()> {
|
||||
self.values.remove(key);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_value(&self, key: &str) -> Result<Option<String>> {
|
||||
|
|
|
@ -300,7 +300,7 @@ pub trait CryptoStore: Debug {
|
|||
async fn save_value(&self, key: String, value: String) -> Result<()>;
|
||||
|
||||
/// Remove a value from the store.
|
||||
async fn remove_value(&self, key: &str) -> Result<Option<String>>;
|
||||
async fn remove_value(&self, key: &str) -> Result<()>;
|
||||
|
||||
/// Load a serializeable object from the store.
|
||||
async fn get_value(&self, key: &str) -> Result<Option<String>>;
|
||||
|
|
|
@ -442,6 +442,24 @@ impl SqliteStore {
|
|||
)
|
||||
.await?;
|
||||
|
||||
connection
|
||||
.execute(
|
||||
r#"
|
||||
CREATE TABLE IF NOT EXISTS key_value (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY,
|
||||
"account_id" INTEGER NOT NULL,
|
||||
"key" TEXT NOT NULL,
|
||||
"value" TEXT NOT NULL,
|
||||
FOREIGN KEY ("account_id") REFERENCES "accounts" ("id")
|
||||
ON DELETE CASCADE
|
||||
UNIQUE(account_id,key)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "key_values_index" ON "key_value" ("account_id");
|
||||
"#,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1372,16 +1390,49 @@ impl CryptoStore for SqliteStore {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn save_value(&self, _key: String, _value: String) -> Result<()> {
|
||||
todo!()
|
||||
async fn save_value(&self, key: String, value: String) -> Result<()> {
|
||||
let account_id = self.account_id().ok_or(CryptoStoreError::AccountUnset)?;
|
||||
let mut connection = self.connection.lock().await;
|
||||
|
||||
query("REPLACE INTO key_value (account_id, key, value) VALUES (?1, ?2, ?3)")
|
||||
.bind(account_id)
|
||||
.bind(&key)
|
||||
.bind(&value)
|
||||
.execute(&mut *connection)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn remove_value(&self, _key: &str) -> Result<Option<String>> {
|
||||
todo!()
|
||||
async fn remove_value(&self, key: &str) -> Result<()> {
|
||||
let account_id = self.account_id().ok_or(CryptoStoreError::AccountUnset)?;
|
||||
let mut connection = self.connection.lock().await;
|
||||
|
||||
query(
|
||||
"DELETE FROM key_value
|
||||
WHERE account_id = ?1 and key = ?2
|
||||
",
|
||||
)
|
||||
.bind(account_id)
|
||||
.bind(key)
|
||||
.execute(&mut *connection)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_value(&self, _key: &str) -> Result<Option<String>> {
|
||||
todo!()
|
||||
async fn get_value(&self, key: &str) -> Result<Option<String>> {
|
||||
let account_id = self.account_id().ok_or(CryptoStoreError::AccountUnset)?;
|
||||
let mut connection = self.connection.lock().await;
|
||||
|
||||
let row: Option<(String,)> =
|
||||
query_as("SELECT value FROM key_value WHERE account_id = ? and key = ?")
|
||||
.bind(account_id)
|
||||
.bind(key)
|
||||
.fetch_optional(&mut *connection)
|
||||
.await?;
|
||||
|
||||
Ok(row.map(|r| r.0))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1881,4 +1932,19 @@ mod test {
|
|||
let loaded_user = store.load_user(&user_id).await.unwrap().unwrap();
|
||||
assert!(loaded_user.own().unwrap().is_verified())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn key_value_saving() {
|
||||
let (_, store, _dir) = get_loaded_store().await;
|
||||
let key = "test_key".to_string();
|
||||
let value = "secret value".to_string();
|
||||
|
||||
store.save_value(key.clone(), value.clone()).await.unwrap();
|
||||
let stored_value = store.get_value(&key).await.unwrap().unwrap();
|
||||
|
||||
assert_eq!(value, stored_value);
|
||||
|
||||
store.remove_value(&key).await.unwrap();
|
||||
assert!(store.get_value(&key).await.unwrap().is_none());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue