merge branches and cleanup db
This commit is contained in:
258
_archive/acldb/src/rpc.rs
Normal file
258
_archive/acldb/src/rpc.rs
Normal file
@@ -0,0 +1,258 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
use crate::error::Error;
|
||||
use crate::acl::ACLRight;
|
||||
use std::collections::HashMap;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// RPC request structure
|
||||
///
|
||||
/// This structure represents an RPC request to the ACLDB API.
|
||||
/// It contains the method name, parameters, and a signature for authentication.
|
||||
#[derive(Debug, Clone, Deserialize, ToSchema)]
|
||||
pub struct RpcRequest {
|
||||
/// Method name
|
||||
pub method: String,
|
||||
/// JSON-encoded arguments
|
||||
pub params: serde_json::Value,
|
||||
/// Signature of the JSON data
|
||||
pub signature: String,
|
||||
}
|
||||
|
||||
/// RPC response structure
|
||||
///
|
||||
/// This structure represents the response from an RPC request.
|
||||
/// It contains either a result or an error message.
|
||||
#[derive(Debug, Clone, Serialize, ToSchema)]
|
||||
pub struct RpcResponse {
|
||||
/// Result of the operation
|
||||
pub result: Option<serde_json::Value>,
|
||||
/// Error message if any
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
||||
/// ACL update request parameters
|
||||
///
|
||||
/// Parameters for updating or creating an ACL with specified permissions.
|
||||
/// Used with the `acl_update` method.
|
||||
#[derive(Debug, Deserialize, ToSchema)]
|
||||
pub struct AclUpdateParams {
|
||||
/// Public key of the requesting user
|
||||
pub caller_pubkey: String,
|
||||
/// ID of the circle where the ACL exists
|
||||
pub circle_id: String,
|
||||
/// Unique name for the ACL within the circle
|
||||
pub name: String,
|
||||
/// Array of public keys to grant permissions to
|
||||
pub pubkeys: Vec<String>,
|
||||
/// Permission level
|
||||
pub right: String,
|
||||
}
|
||||
|
||||
/// ACL remove request parameters
|
||||
///
|
||||
/// Parameters for removing specific public keys from an existing ACL.
|
||||
/// Used with the `acl_remove` method.
|
||||
#[derive(Debug, Deserialize, ToSchema)]
|
||||
pub struct AclRemoveParams {
|
||||
/// Public key of the requesting user
|
||||
pub caller_pubkey: String,
|
||||
/// ID of the circle where the ACL exists
|
||||
pub circle_id: String,
|
||||
/// Name of the ACL to modify
|
||||
pub name: String,
|
||||
/// Array of public keys to remove from the ACL
|
||||
pub pubkeys: Vec<String>,
|
||||
}
|
||||
|
||||
/// ACL delete request parameters
|
||||
///
|
||||
/// Parameters for deleting an entire ACL.
|
||||
/// Used with the `acl_del` method.
|
||||
#[derive(Debug, Deserialize, ToSchema)]
|
||||
pub struct AclDelParams {
|
||||
/// Public key of the requesting user
|
||||
pub caller_pubkey: String,
|
||||
/// ID of the circle where the ACL exists
|
||||
pub circle_id: String,
|
||||
/// Name of the ACL to delete
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// Set request parameters
|
||||
///
|
||||
/// Parameters for storing data with optional ACL protection.
|
||||
/// Used with the `set` method.
|
||||
#[derive(Debug, Deserialize, ToSchema)]
|
||||
pub struct SetParams {
|
||||
/// Public key of the requesting user
|
||||
pub caller_pubkey: String,
|
||||
/// ID of the circle where the data belongs
|
||||
pub circle_id: String,
|
||||
/// String identifier for the database category
|
||||
pub topic: String,
|
||||
/// Optional string key for the record
|
||||
pub key: Option<String>,
|
||||
/// Optional numeric ID for direct access
|
||||
pub id: Option<u32>,
|
||||
/// Base64-encoded data to store
|
||||
pub value: String,
|
||||
/// ID of the ACL to protect this record (0 for public access)
|
||||
pub acl_id: Option<u32>,
|
||||
}
|
||||
|
||||
/// Delete request parameters
|
||||
///
|
||||
/// Parameters for deleting data with ACL verification.
|
||||
/// Used with the `del` method.
|
||||
#[derive(Debug, Deserialize, ToSchema)]
|
||||
pub struct DelParams {
|
||||
/// Public key of the requesting user
|
||||
pub caller_pubkey: String,
|
||||
/// ID of the circle where the data belongs
|
||||
pub circle_id: String,
|
||||
/// String identifier for the database category
|
||||
pub topic: String,
|
||||
/// Optional string key for the record
|
||||
pub key: Option<String>,
|
||||
/// Optional numeric ID for direct access
|
||||
pub id: Option<u32>,
|
||||
}
|
||||
|
||||
/// Get request parameters
|
||||
///
|
||||
/// Parameters for retrieving data with ACL verification.
|
||||
/// Used with the `get` method.
|
||||
#[derive(Debug, Deserialize, ToSchema)]
|
||||
pub struct GetParams {
|
||||
/// Public key of the requesting user
|
||||
pub caller_pubkey: String,
|
||||
/// ID of the circle where the data belongs
|
||||
pub circle_id: String,
|
||||
/// String identifier for the database category
|
||||
pub topic: String,
|
||||
/// Optional string key for the record
|
||||
pub key: Option<String>,
|
||||
/// Optional numeric ID for direct access
|
||||
pub id: Option<u32>,
|
||||
}
|
||||
|
||||
/// Prefix request parameters
|
||||
///
|
||||
/// Parameters for searching for keys with a specific prefix.
|
||||
/// Used with the `prefix` method.
|
||||
#[derive(Debug, Deserialize, ToSchema)]
|
||||
pub struct PrefixParams {
|
||||
/// Public key of the requesting user
|
||||
pub caller_pubkey: String,
|
||||
/// ID of the circle where the data belongs
|
||||
pub circle_id: String,
|
||||
/// String identifier for the database category
|
||||
pub topic: String,
|
||||
/// Prefix to search for
|
||||
pub prefix: String,
|
||||
}
|
||||
|
||||
/// RPC interface for handling client requests
|
||||
pub struct RpcInterface {
|
||||
/// Map of method names to handler functions
|
||||
handlers: HashMap<String, Box<dyn Fn(serde_json::Value) -> Result<serde_json::Value, Error> + Send + Sync>>,
|
||||
}
|
||||
|
||||
impl RpcInterface {
|
||||
/// Creates a new RPC interface
|
||||
pub fn new() -> Self {
|
||||
RpcInterface {
|
||||
handlers: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Registers a handler for a method
|
||||
pub fn register<F>(&mut self, method: &str, handler: F)
|
||||
where
|
||||
F: Fn(serde_json::Value) -> Result<serde_json::Value, Error> + Send + Sync + 'static,
|
||||
{
|
||||
self.handlers.insert(method.to_string(), Box::new(handler));
|
||||
}
|
||||
|
||||
/// Handles an RPC request
|
||||
pub fn handle(&self, request: RpcRequest) -> RpcResponse {
|
||||
// Verify the signature
|
||||
if let Err(err) = self.verify_signature(&request) {
|
||||
return RpcResponse {
|
||||
result: None,
|
||||
error: Some(err.to_string()),
|
||||
};
|
||||
}
|
||||
|
||||
// Extract the caller's public key from the signature
|
||||
let _caller_pubkey = self.extract_pubkey(&request.signature).unwrap_or_default();
|
||||
|
||||
// Call the appropriate handler
|
||||
match self.handlers.get(&request.method) {
|
||||
Some(handler) => {
|
||||
match handler(request.params) {
|
||||
Ok(result) => RpcResponse {
|
||||
result: Some(result),
|
||||
error: None,
|
||||
},
|
||||
Err(err) => RpcResponse {
|
||||
result: None,
|
||||
error: Some(err.to_string()),
|
||||
},
|
||||
}
|
||||
}
|
||||
None => RpcResponse {
|
||||
result: None,
|
||||
error: Some(format!("Method not found: {}", request.method)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Verifies the signature of an RPC request
|
||||
fn verify_signature(&self, request: &RpcRequest) -> Result<(), Error> {
|
||||
// In a real implementation, this would verify the cryptographic signature
|
||||
// For now, we'll just check that the signature is not empty
|
||||
if request.signature.is_empty() {
|
||||
return Err(Error::SignatureError("Empty signature".to_string()));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Extracts the public key from a signature
|
||||
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())
|
||||
}
|
||||
|
||||
/// Parses a string to an ACLRight enum
|
||||
pub fn parse_acl_right(right_str: &str) -> Result<ACLRight, Error> {
|
||||
match right_str.to_lowercase().as_str() {
|
||||
"read" => Ok(ACLRight::Read),
|
||||
"write" => Ok(ACLRight::Write),
|
||||
"delete" => Ok(ACLRight::Delete),
|
||||
"execute" => Ok(ACLRight::Execute),
|
||||
"admin" => Ok(ACLRight::Admin),
|
||||
_ => Err(Error::InvalidRequest(format!("Invalid ACL right: {}", right_str))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_parse_acl_right() {
|
||||
let rpc = RpcInterface::new();
|
||||
|
||||
assert_eq!(RpcInterface::parse_acl_right("read").unwrap(), ACLRight::Read);
|
||||
assert_eq!(RpcInterface::parse_acl_right("write").unwrap(), ACLRight::Write);
|
||||
assert_eq!(RpcInterface::parse_acl_right("delete").unwrap(), ACLRight::Delete);
|
||||
assert_eq!(RpcInterface::parse_acl_right("execute").unwrap(), ACLRight::Execute);
|
||||
assert_eq!(RpcInterface::parse_acl_right("admin").unwrap(), ACLRight::Admin);
|
||||
|
||||
assert!(RpcInterface::parse_acl_right("invalid").is_err());
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user