From 5b4fbd5df60f489dde97d817ebca0990618eb53e Mon Sep 17 00:00:00 2001 From: servius Date: Mon, 26 Jan 2026 21:00:56 +0530 Subject: [PATCH] feat(store): add SecretStore, ApiKey, remove Store trait --- Cargo.lock | 10 ++ store/Cargo.toml | 3 +- store/src/lib.rs | 16 +- store/src/redb.rs | 442 +++++++++++++++++++++++----------------------- 4 files changed, 241 insertions(+), 230 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d9ccc2..6d831d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6603,6 +6603,15 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "secrecy" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a" +dependencies = [ + "zeroize", +] + [[package]] name = "security-framework" version = "2.11.1" @@ -7124,6 +7133,7 @@ dependencies = [ "futures", "parking_lot", "redb", + "secrecy", "serde", "tokio", "uuid", diff --git a/store/Cargo.toml b/store/Cargo.toml index 33577e0..7dc01d4 100644 --- a/store/Cargo.toml +++ b/store/Cargo.toml @@ -8,6 +8,7 @@ bson = { version = "3.1.0", features = ["serde"] } futures = "0.3.31" parking_lot = "0.12.5" redb = { version = "3.1.0", features = ["uuid"] } +secrecy = "0.10.3" serde = "1.0.228" tokio = { version = "1.48.0", features = ["rt"] } -uuid = "1.18.1" +uuid = { version = "1.18.1", features = ["v4"] } diff --git a/store/src/lib.rs b/store/src/lib.rs index 8fe7884..21d5868 100644 --- a/store/src/lib.rs +++ b/store/src/lib.rs @@ -1,10 +1,10 @@ -pub mod redb; -pub mod sqlite; -pub mod toml; +use std::collections::BTreeMap; -pub trait Store { - fn image(&self, id: &str) -> Option>; - fn save_image(&mut self, id: &str, data: &[u8]); +use uuid::Uuid; + +pub struct ApiKey { + inner: secrecy::SecretBox, +} +pub struct SecretStore { + api_keys: BTreeMap, } - -pub struct Settings {} diff --git a/store/src/redb.rs b/store/src/redb.rs index 5c38e35..7f9ce0f 100644 --- a/store/src/redb.rs +++ b/store/src/redb.rs @@ -1,225 +1,225 @@ -use std::{ - borrow::Borrow, - collections::VecDeque, - marker::PhantomData, - path::Path, - sync::{Arc, RwLock, atomic::AtomicBool}, -}; - -use futures::task::AtomicWaker; -use redb::{Error, Key, ReadableDatabase, TableDefinition, Value}; -use serde::{Serialize, de::DeserializeOwned}; - -const USERS: TableDefinition> = TableDefinition::new("users"); -const SERVERS: TableDefinition> = TableDefinition::new("servers"); -const SETTINGS: TableDefinition> = TableDefinition::new("settings"); - -#[derive(Debug)] -pub struct TableInner { - db: Arc, -} - -impl Clone for TableInner { - fn clone(&self) -> Self { - Self { - db: Arc::clone(&self.db), - } - } -} - -impl TableInner { - fn new(db: Arc) -> Self { - Self { db } - } -} - -impl TableInner { - async fn get<'a, K: Key, V: Serialize + DeserializeOwned>( - &self, - table: TableDefinition<'static, K, Vec>, - key: impl Borrow>, - ) -> Result> { - let db: &redb::Database = &self.db.as_ref().database; - let db_reader = db.begin_read()?; - let table = db_reader.open_table(table)?; - table - .get(key)? - .map(|value| bson::deserialize_from_slice(&value.value())) - .transpose() - .map_err(|e| redb::Error::Io(std::io::Error::other(e))) - } - - async fn insert< - 'a, - 'b, - K: Key + Send + Sync, - V: Serialize + DeserializeOwned + Send + Sync + 'a, - >( - &'b self, - table: TableDefinition<'static, K, Vec>, - key: impl Borrow> + Send + 'b, - value: V, - ) -> Result> { - let db: &redb::Database = &self.db.as_ref().database; - // self.db - // .writing - // .store(true, std::sync::atomic::Ordering::SeqCst); - - // let out = tokio::task::spawn_blocking(move || -> Result> - - let out = tokio::task::spawn_blocking(|| -> Result> { - let db_writer = db.begin_write()?; - let out = { - let mut table = db_writer.open_table(table)?; - let serialized_value = bson::serialize_to_vec(&value) - .map_err(|e| redb::Error::Io(std::io::Error::other(e)))?; - let previous = table.insert(key, &serialized_value)?; - let out = previous - .map(|value| bson::deserialize_from_slice(&value.value())) - .transpose() - .map_err(|e| redb::Error::Io(std::io::Error::other(e))); - out - }; - db_writer.commit()?; - out - }) - .await - .expect("Task panicked"); - - out - } -} - -// impl Table for TableInner { -// async fn get(&self, key: K) -> Result> {} -// async fn insert(&self, key: K, value: V) -> Result> {} -// async fn modify(&self, key: K, v: FnOnce(V) -> V) -> Result {} -// async fn remove(&self, key: K) -> Result> {} +// use std::{ +// borrow::Borrow, +// collections::VecDeque, +// marker::PhantomData, +// path::Path, +// sync::{Arc, RwLock, atomic::AtomicBool}, +// }; +// +// use futures::task::AtomicWaker; +// use redb::{Error, Key, ReadableDatabase, TableDefinition, Value}; +// use serde::{Serialize, de::DeserializeOwned}; +// +// const USERS: TableDefinition> = TableDefinition::new("users"); +// const SERVERS: TableDefinition> = TableDefinition::new("servers"); +// const SETTINGS: TableDefinition> = TableDefinition::new("settings"); +// +// #[derive(Debug)] +// pub struct TableInner { +// db: Arc, // } - -#[derive(Debug)] -pub struct Users(TableInner); - -impl Clone for Users { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} -impl Users { - const TABLE: TableDefinition<'static, uuid::Uuid, Vec> = USERS; -} - -#[derive(Debug)] -pub struct Servers(TableInner); -impl Clone for Servers { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} -impl Servers { - const TABLE: TableDefinition<'static, uuid::Uuid, Vec> = SERVERS; -} - -#[derive(Debug)] -pub struct Settings(TableInner); -impl Clone for Settings { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} -impl Settings { - const TABLE: TableDefinition<'static, uuid::Uuid, Vec> = SETTINGS; -} - -#[derive(Debug, Clone)] -pub struct Database { - users: Users, - servers: Servers, - settings: Settings, - handle: Arc, -} - -#[derive(Debug)] -pub struct DatabaseHandle { - database: redb::Database, - writing: AtomicBool, - wakers: RwLock>, -} - -#[derive(Debug)] -pub struct DatabaseWriterGuard<'a> { - handle: &'a DatabaseHandle, - dropper: Arc, -} - -// impl Drop for DatabaseWriterGuard<'_> { -// fn drop(&mut self) { -// self.handle -// .writing -// .store(false, std::sync::atomic::Ordering::SeqCst); -// let is_panicking = std::thread::panicking(); -// let Ok(writer) = self.handle.wakers.write() else { -// if is_panicking { -// return; -// } else { -// panic!("Wakers lock poisoned"); -// } +// +// impl Clone for TableInner { +// fn clone(&self) -> Self { +// Self { +// db: Arc::clone(&self.db), // } -// if let Some(waker) = (self.handle.wakers.write()).pop() { -// waker.wake(); -// }; -// // let mut wakers = self.handle.wakers.write().expect(); -// // if let Some(waker) = self.handle.wakers.write().expect("Wakers lock poisoned").pop_front() { -// // waker.wake(); -// // } -// // while let Some(waker) = wakers.pop_front() { -// // waker.wake(); -// // } // } // } - -type Result = core::result::Result; - -pub trait Table { - fn insert( - &self, - key: K, - value: V, - ) -> impl Future>> + Send; - fn modify( - &self, - key: K, - v: impl FnOnce(V) -> O, - ) -> impl Future> + Send; - fn remove( - &self, - key: K, - ) -> impl Future>> + Send; - fn get( - &self, - key: K, - ) -> impl Future>> + Send; -} - -impl Database { - pub fn create(path: impl AsRef) -> Result { - let writing = AtomicBool::new(false); - let wakers = RwLock::new(VecDeque::new()); - let db = redb::Database::create(path)?; - let db = Arc::new(DatabaseHandle { - database: db, - writing, - wakers, - }); - let table_inner = TableInner::new(Arc::clone(&db)); - let users = Users(table_inner.clone()); - let servers = Servers(table_inner.clone()); - let settings = Settings(table_inner.clone()); - Ok(Self { - servers, - users, - settings, - handle: db, - }) - } -} +// +// impl TableInner { +// fn new(db: Arc) -> Self { +// Self { db } +// } +// } +// +// impl TableInner { +// async fn get<'a, K: Key, V: Serialize + DeserializeOwned>( +// &self, +// table: TableDefinition<'static, K, Vec>, +// key: impl Borrow>, +// ) -> Result> { +// let db: &redb::Database = &self.db.as_ref().database; +// let db_reader = db.begin_read()?; +// let table = db_reader.open_table(table)?; +// table +// .get(key)? +// .map(|value| bson::deserialize_from_slice(&value.value())) +// .transpose() +// .map_err(|e| redb::Error::Io(std::io::Error::other(e))) +// } +// +// async fn insert< +// 'a, +// 'b, +// K: Key + Send + Sync, +// V: Serialize + DeserializeOwned + Send + Sync + 'a, +// >( +// &'b self, +// table: TableDefinition<'static, K, Vec>, +// key: impl Borrow> + Send + 'b, +// value: V, +// ) -> Result> { +// let db: &redb::Database = &self.db.as_ref().database; +// // self.db +// // .writing +// // .store(true, std::sync::atomic::Ordering::SeqCst); +// +// // let out = tokio::task::spawn_blocking(move || -> Result> +// +// let out = tokio::task::spawn_blocking(|| -> Result> { +// let db_writer = db.begin_write()?; +// let out = { +// let mut table = db_writer.open_table(table)?; +// let serialized_value = bson::serialize_to_vec(&value) +// .map_err(|e| redb::Error::Io(std::io::Error::other(e)))?; +// let previous = table.insert(key, &serialized_value)?; +// let out = previous +// .map(|value| bson::deserialize_from_slice(&value.value())) +// .transpose() +// .map_err(|e| redb::Error::Io(std::io::Error::other(e))); +// out +// }; +// db_writer.commit()?; +// out +// }) +// .await +// .expect("Task panicked"); +// +// out +// } +// } +// +// // impl Table for TableInner { +// // async fn get(&self, key: K) -> Result> {} +// // async fn insert(&self, key: K, value: V) -> Result> {} +// // async fn modify(&self, key: K, v: FnOnce(V) -> V) -> Result {} +// // async fn remove(&self, key: K) -> Result> {} +// // } +// +// #[derive(Debug)] +// pub struct Users(TableInner); +// +// impl Clone for Users { +// fn clone(&self) -> Self { +// Self(self.0.clone()) +// } +// } +// impl Users { +// const TABLE: TableDefinition<'static, uuid::Uuid, Vec> = USERS; +// } +// +// #[derive(Debug)] +// pub struct Servers(TableInner); +// impl Clone for Servers { +// fn clone(&self) -> Self { +// Self(self.0.clone()) +// } +// } +// impl Servers { +// const TABLE: TableDefinition<'static, uuid::Uuid, Vec> = SERVERS; +// } +// +// #[derive(Debug)] +// pub struct Settings(TableInner); +// impl Clone for Settings { +// fn clone(&self) -> Self { +// Self(self.0.clone()) +// } +// } +// impl Settings { +// const TABLE: TableDefinition<'static, uuid::Uuid, Vec> = SETTINGS; +// } +// +// #[derive(Debug, Clone)] +// pub struct Database { +// users: Users, +// servers: Servers, +// settings: Settings, +// handle: Arc, +// } +// +// #[derive(Debug)] +// pub struct DatabaseHandle { +// database: redb::Database, +// writing: AtomicBool, +// wakers: RwLock>, +// } +// +// #[derive(Debug)] +// pub struct DatabaseWriterGuard<'a> { +// handle: &'a DatabaseHandle, +// dropper: Arc, +// } +// +// // impl Drop for DatabaseWriterGuard<'_> { +// // fn drop(&mut self) { +// // self.handle +// // .writing +// // .store(false, std::sync::atomic::Ordering::SeqCst); +// // let is_panicking = std::thread::panicking(); +// // let Ok(writer) = self.handle.wakers.write() else { +// // if is_panicking { +// // return; +// // } else { +// // panic!("Wakers lock poisoned"); +// // } +// // } +// // if let Some(waker) = (self.handle.wakers.write()).pop() { +// // waker.wake(); +// // }; +// // // let mut wakers = self.handle.wakers.write().expect(); +// // // if let Some(waker) = self.handle.wakers.write().expect("Wakers lock poisoned").pop_front() { +// // // waker.wake(); +// // // } +// // // while let Some(waker) = wakers.pop_front() { +// // // waker.wake(); +// // // } +// // } +// // } +// +// type Result = core::result::Result; +// +// pub trait Table { +// fn insert( +// &self, +// key: K, +// value: V, +// ) -> impl Future>> + Send; +// fn modify( +// &self, +// key: K, +// v: impl FnOnce(V) -> O, +// ) -> impl Future> + Send; +// fn remove( +// &self, +// key: K, +// ) -> impl Future>> + Send; +// fn get( +// &self, +// key: K, +// ) -> impl Future>> + Send; +// } +// +// impl Database { +// pub fn create(path: impl AsRef) -> Result { +// let writing = AtomicBool::new(false); +// let wakers = RwLock::new(VecDeque::new()); +// let db = redb::Database::create(path)?; +// let db = Arc::new(DatabaseHandle { +// database: db, +// writing, +// wakers, +// }); +// let table_inner = TableInner::new(Arc::clone(&db)); +// let users = Users(table_inner.clone()); +// let servers = Servers(table_inner.clone()); +// let settings = Settings(table_inner.clone()); +// Ok(Self { +// servers, +// users, +// settings, +// handle: db, +// }) +// } +// }