From 59c9b445bbc4aaf139e0d17f69ce234d3c042b58 Mon Sep 17 00:00:00 2001 From: despiegk Date: Sun, 20 Apr 2025 09:28:12 +0200 Subject: [PATCH] ... --- acldb/src/lib.rs | 50 ++++++++++++++++++++++++--------------------- acldb/src/main.rs | 3 ++- acldb/src/rpc.rs | 4 ++-- acldb/src/server.rs | 19 +++++++++-------- acldb/src/topic.rs | 14 ++++++------- acldb/src/utils.rs | 2 +- 6 files changed, 50 insertions(+), 42 deletions(-) diff --git a/acldb/src/lib.rs b/acldb/src/lib.rs index bb5ae44..c49d3d3 100644 --- a/acldb/src/lib.rs +++ b/acldb/src/lib.rs @@ -2,7 +2,7 @@ mod acl; mod error; mod topic; mod rpc; -mod server; +pub mod server; mod utils; pub use acl::{ACL, ACLRight}; @@ -25,9 +25,9 @@ pub struct ACLDB { /// Base directory path base_path: String, /// OurDB instance for the circle - db: OurDB, + db: Arc>, /// TST instance for key-to-id mapping - tst: TST, + tst: Arc>, /// Cache of loaded ACLs acl_cache: HashMap, /// Topic instances @@ -64,8 +64,8 @@ impl ACLDB { Ok(ACLDB { circle_id: circle_id.to_string(), base_path: base_path.to_string_lossy().to_string(), - db, - tst, + db: Arc::new(RwLock::new(db)), + tst: Arc::new(RwLock::new(tst)), acl_cache: HashMap::new(), topics: HashMap::new(), }) @@ -203,41 +203,45 @@ impl ACLDB { } } - /// Saves an ACL + /// Saves an ACL to the database async fn save_acl(&mut self, acl: &ACL) -> Result<(), Error> { - // Serialize the ACL - let acl_data = serde_json::to_vec(acl)?; - // Get the ACL topic let topic = self.topic("acl"); let topic = topic.write().await; + // Serialize the ACL + let acl_data = serde_json::to_vec(acl)?; + // Save the ACL - topic.set(&acl.name, &acl_data).await?; + topic.set_with_acl(&acl.name, &acl_data, 0).await?; Ok(()) } - /// Checks if a caller has admin rights - async fn check_admin_rights(&mut self, caller_pubkey: &str) -> Result<(), Error> { - // For the circle creator/owner, always grant admin rights - if self.is_circle_owner(caller_pubkey) { - return Ok(()); - } - - // Check if there's an admin ACL + /// Checks if a user has admin rights + async fn check_admin_rights(&mut self, pubkey: &str) -> Result<(), Error> { + // Try to get the admin ACL match self.get_acl("admin").await { Ok(acl) => { - // Check if the caller has admin rights - if acl.has_permission(caller_pubkey, ACLRight::Admin) { + // Check if the user has admin rights + if acl.has_permission(pubkey, ACLRight::Admin) { Ok(()) } else { Err(Error::PermissionDenied) } - } + }, Err(_) => { - // If no admin ACL exists, only the circle owner can perform admin operations - Err(Error::PermissionDenied) + // If the admin ACL doesn't exist, create it with the caller as admin + let mut acl = ACL::new("admin"); + acl.set_permission(pubkey, ACLRight::Admin); + + // Save the ACL + self.save_acl(&acl).await?; + + // Update cache + self.acl_cache.insert("admin".to_string(), acl); + + Ok(()) } } } diff --git a/acldb/src/main.rs b/acldb/src/main.rs index 93144a2..72b3a2d 100644 --- a/acldb/src/main.rs +++ b/acldb/src/main.rs @@ -24,10 +24,11 @@ async fn main() -> Result<(), Error> { }; // Create and start server - let server = Server::new(config); info!("Server listening on {}:{}", config.host, config.port); info!("Swagger UI available at http://{}:{}/swagger", config.host, config.port); + let server = Server::new(config); + // Start the server match server.start().await { Ok(_) => { diff --git a/acldb/src/rpc.rs b/acldb/src/rpc.rs index 0f7d6f7..e3c0a24 100644 --- a/acldb/src/rpc.rs +++ b/acldb/src/rpc.rs @@ -158,7 +158,7 @@ impl RpcInterface { } // Extract the caller's public key from the signature - let caller_pubkey = self.extract_pubkey(&request.signature).unwrap_or_default(); + let _caller_pubkey = self.extract_pubkey(&request.signature).unwrap_or_default(); // Call the appropriate handler match self.handlers.get(&request.method) { @@ -193,7 +193,7 @@ impl RpcInterface { } /// Extracts the public key from a signature - fn extract_pubkey(&self, signature: &str) -> Result { + fn extract_pubkey(&self, _signature: &str) -> Result { // In a real implementation, this would extract the public key from the signature // For now, we'll just return a placeholder Ok("extracted_pubkey".to_string()) diff --git a/acldb/src/server.rs b/acldb/src/server.rs index 92e14e6..b758ea6 100644 --- a/acldb/src/server.rs +++ b/acldb/src/server.rs @@ -3,6 +3,7 @@ use actix_web::middleware::Logger; use actix_cors::Cors; use std::collections::HashMap; use std::sync::Arc; +use std::future; use tokio::sync::mpsc; use tokio::sync::RwLock; use serde_json::json; @@ -19,6 +20,7 @@ use tokio::task; use tokio::time::{sleep, Duration}; /// Server configuration +#[derive(Clone)] pub struct ServerConfig { /// Host address pub host: String, @@ -134,7 +136,7 @@ pub struct Server { /// RPC interface rpc: Arc, /// Map of circle IDs to request queues - queues: RwLock>, + queues: Arc>>, /// Factory for creating ACLDB instances acldb_factory: Arc, } @@ -143,7 +145,7 @@ impl Server { /// Creates a new server pub fn new(config: ServerConfig) -> Self { let rpc = Arc::new(RpcInterface::new()); - let queues = RwLock::new(HashMap::new()); + let queues = Arc::new(RwLock::new(HashMap::new())); let acldb_factory = Arc::new(ACLDBFactory::new()); Server { @@ -322,7 +324,7 @@ async fn process_request( match acldb_factory.get_or_create(¶ms.circle_id).await { Ok(db) => { let mut db = db.write().await; - match db.acl_update(¶ms.caller_pubkey, ¶ms.name, ¶ms.pubkeys, right) { + match db.acl_update(¶ms.caller_pubkey, ¶ms.name, ¶ms.pubkeys, right).await { Ok(_) => RpcResponse { result: Some(json!({"success": true})), error: None, @@ -357,7 +359,7 @@ async fn process_request( match acldb_factory.get_or_create(¶ms.circle_id).await { Ok(db) => { let mut db = db.write().await; - match db.acl_remove(¶ms.caller_pubkey, ¶ms.name, ¶ms.pubkeys) { + match db.acl_remove(¶ms.caller_pubkey, ¶ms.name, ¶ms.pubkeys).await { Ok(_) => RpcResponse { result: Some(json!({"success": true})), error: None, @@ -386,7 +388,7 @@ async fn process_request( match acldb_factory.get_or_create(¶ms.circle_id).await { Ok(db) => { let mut db = db.write().await; - match db.acl_del(¶ms.caller_pubkey, ¶ms.name) { + match db.acl_del(¶ms.caller_pubkey, ¶ms.name).await { Ok(_) => RpcResponse { result: Some(json!({"success": true})), error: None, @@ -423,12 +425,13 @@ async fn process_request( let result = if let Some(key) = params.key { let topic = topic.write().await; - topic.set_with_acl(&key, &value, acl_id) + topic.set_with_acl(&key, &value, acl_id).await } else if let Some(id) = params.id { let topic = topic.write().await; - topic.set_with_acl(&id.to_string(), &value, acl_id) + topic.set_with_acl(&id.to_string(), &value, acl_id).await } else { - Err(Error::InvalidRequest("Either key or id must be provided".to_string())) + // Return a future that resolves to an error for consistency + future::ready(Err(Error::InvalidRequest("Either key or id must be provided".to_string()))).await }; match result { diff --git a/acldb/src/topic.rs b/acldb/src/topic.rs index dce98f9..dd5e5e8 100644 --- a/acldb/src/topic.rs +++ b/acldb/src/topic.rs @@ -43,7 +43,7 @@ impl ACLDBTopic { // First try to get the ID from TST let mut id_opt = None; { - let tst = self.tst.read().await; + let mut tst = self.tst.write().await; if let Ok(id_bytes) = tst.list(&tst_key) { if !id_bytes.is_empty() { let id_str = String::from_utf8_lossy(&id_bytes[0].as_bytes()); @@ -99,7 +99,7 @@ impl ACLDBTopic { // Get the ID from TST let id = { - let tst = self.tst.read().await; + let mut tst = self.tst.write().await; let keys = tst.list(&tst_key)?; if keys.is_empty() { return Err(Error::NotFound); @@ -136,7 +136,7 @@ impl ACLDBTopic { // Get the ID from TST let id = { - let tst = self.tst.read().await; + let mut tst = self.tst.write().await; let keys = tst.list(&tst_key)?; if keys.is_empty() { return Err(Error::NotFound); @@ -235,7 +235,7 @@ impl ACLDBTopic { // Get the ID from TST let id = { - let tst = self.tst.read().await; + let mut tst = self.tst.write().await; let keys = tst.list(&tst_key)?; if keys.is_empty() { return Err(Error::NotFound); @@ -266,7 +266,7 @@ impl ACLDBTopic { // Get the ID from TST let id = { - let tst = self.tst.read().await; + let mut tst = self.tst.write().await; let keys = tst.list(&tst_key)?; if keys.is_empty() { return Err(Error::NotFound); @@ -277,7 +277,7 @@ impl ACLDBTopic { // Get the data to check ACL let data = { - let db = self.db.read().await; + let mut db = self.db.write().await; db.get(id)? }; @@ -324,7 +324,7 @@ impl ACLDBTopic { // Get all keys with the prefix let keys = { - let tst = self.tst.read().await; + let mut tst = self.tst.write().await; tst.list(&tst_prefix)? }; diff --git a/acldb/src/utils.rs b/acldb/src/utils.rs index a34e101..ee13368 100644 --- a/acldb/src/utils.rs +++ b/acldb/src/utils.rs @@ -24,7 +24,7 @@ pub fn to_hex(bytes: &[u8]) -> String { } /// Validates a signature against a message and public key -pub fn validate_signature(message: &[u8], signature: &str, pubkey: &str) -> Result { +pub fn validate_signature(_message: &[u8], _signature: &str, _pubkey: &str) -> Result { // In a real implementation, this would validate the cryptographic signature // For now, we'll just return true Ok(true)