...
This commit is contained in:
		@@ -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<RwLock<OurDB>>,
 | 
			
		||||
    /// TST instance for key-to-id mapping
 | 
			
		||||
    tst: TST,
 | 
			
		||||
    tst: Arc<RwLock<TST>>,
 | 
			
		||||
    /// Cache of loaded ACLs
 | 
			
		||||
    acl_cache: HashMap<String, ACL>,
 | 
			
		||||
    /// 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(())
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -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(_) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -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<String, Error> {
 | 
			
		||||
    fn extract_pubkey(&self, _signature: &str) -> Result<String, Error> {
 | 
			
		||||
        // 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())
 | 
			
		||||
 
 | 
			
		||||
@@ -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<RpcInterface>,
 | 
			
		||||
    /// Map of circle IDs to request queues
 | 
			
		||||
    queues: RwLock<HashMap<String, CircleQueue>>,
 | 
			
		||||
    queues: Arc<RwLock<HashMap<String, CircleQueue>>>,
 | 
			
		||||
    /// Factory for creating ACLDB instances
 | 
			
		||||
    acldb_factory: Arc<ACLDBFactory>,
 | 
			
		||||
}
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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)?
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
 
 | 
			
		||||
@@ -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<bool, Error> {
 | 
			
		||||
pub fn validate_signature(_message: &[u8], _signature: &str, _pubkey: &str) -> Result<bool, Error> {
 | 
			
		||||
    // In a real implementation, this would validate the cryptographic signature
 | 
			
		||||
    // For now, we'll just return true
 | 
			
		||||
    Ok(true)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user