Skip to content

Commit

Permalink
User Preferences Table (#1384)
Browse files Browse the repository at this point in the history
* check

* remove on conflict

* impl store
  • Loading branch information
codabrink authored Dec 5, 2024
1 parent 5849947 commit df1583f
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE IF EXISTS "user_preferences";
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE "user_preferences"(
-- The latest id is the current preference
id INTEGER PRIMARY KEY ASC,
-- HMAC root key
hmac_key BLOB
);
1 change: 1 addition & 0 deletions xmtp_mls/src/storage/encrypted_store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub mod refresh_state;
pub mod schema;
#[cfg(not(target_arch = "wasm32"))]
mod sqlcipher_connection;
pub mod user_preferences;
pub mod wallet_addresses;
#[cfg(target_arch = "wasm32")]
mod wasm;
Expand Down
8 changes: 8 additions & 0 deletions xmtp_mls/src/storage/encrypted_store/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ diesel::table! {
}
}

diesel::table! {
user_preferences (id) {
id -> Nullable<Integer>,
hmac_key -> Nullable<Binary>,
}
}

diesel::table! {
wallet_addresses (wallet_address) {
inbox_id -> Text,
Expand All @@ -129,5 +136,6 @@ diesel::allow_tables_to_appear_in_same_query!(
openmls_key_store,
openmls_key_value,
refresh_state,
user_preferences,
wallet_addresses,
);
76 changes: 76 additions & 0 deletions xmtp_mls/src/storage/encrypted_store/user_preferences.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use crate::{impl_store, storage::StorageError, Store};

use super::{
schema::user_preferences::{self, dsl},
DbConnection,
};
use diesel::prelude::*;

#[derive(Identifiable, Insertable, Queryable, Debug, Clone, PartialEq, Eq, Default)]
#[diesel(table_name = user_preferences)]
#[diesel(primary_key(id))]
pub struct StoredUserPreferences {
/// Primary key - latest key is the "current" preference
pub id: Option<i32>,
/// Randomly generated hmac key root
pub hmac_key: Option<Vec<u8>>,
}
impl_store!(StoredUserPreferences, user_preferences);

impl StoredUserPreferences {
pub fn load(conn: &DbConnection) -> Result<Self, StorageError> {
let query = dsl::user_preferences.order(dsl::id.desc()).limit(1);
let mut result = conn.raw_query(|conn| query.load::<StoredUserPreferences>(conn))?;

Ok(result.pop().unwrap_or_default())
}

pub fn set_hmac_key(conn: &DbConnection, hmac_key: Vec<u8>) -> Result<(), StorageError> {
let mut preferences = Self::load(conn)?;
preferences.id = None;
preferences.hmac_key = Some(hmac_key);

preferences.store(conn)?;

Ok(())
}
}

#[cfg(test)]
mod tests {
use crate::{storage::encrypted_store::tests::with_connection, Store};
#[cfg(target_arch = "wasm32")]
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker);

use super::*;

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[cfg_attr(not(target_arch = "wasm32"), tokio::test)]
async fn test_insert_and_upate_preferences() {
with_connection(|conn| {
// loads a default
let pref = StoredUserPreferences::load(conn).unwrap();
assert_eq!(pref, StoredUserPreferences::default());
assert_eq!(pref.id, None);
// save that default
pref.store(conn).unwrap();

// set an hmac key
let hmac_key = vec![1, 2, 1, 2, 1, 2, 1, 2, 1, 2];
StoredUserPreferences::set_hmac_key(conn, hmac_key.clone()).unwrap();

// load preferences from db
let pref = StoredUserPreferences::load(conn).unwrap();
assert_eq!(pref.hmac_key, Some(hmac_key));
assert_eq!(pref.id, Some(2));

// check that there are two preferences stored
let query = dsl::user_preferences.order(dsl::id.desc());
let result = conn
.raw_query(|conn| query.load::<StoredUserPreferences>(conn))
.unwrap();
assert_eq!(result.len(), 2);
})
.await;
}
}

0 comments on commit df1583f

Please sign in to comment.