fortress-api-server 1.0.1

REST API server for Fortress secure database system
use crate::grpc::types::*;
use crate::error::ServerError;
use fortress_core::encryption::{Aegis256, EncryptionAlgorithm};
use fortress_core::key::KeyManager;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use tracing::{info, error, debug};
use hex;

/// gRPC service implementation for Fortress
/// 
/// This struct provides the main gRPC service interface for the Fortress
/// secure storage system, handling database operations and encryption.
#[derive(Clone)]
pub struct FortressGrpcService {
    /// Database instance (placeholder)
    database: Arc<RwLock<Option<()>>>, // Placeholder for FortressDatabase
    /// Encryption manager instance
    encryption_manager: Arc<Aegis256>,
    /// Key manager instance
    key_manager: Arc<dyn KeyManager>,
}

impl FortressGrpcService {
    /// Create a new Fortress gRPC service instance
    pub fn new(encryption_manager: Arc<Aegis256>, key_manager: Arc<dyn KeyManager>) -> Self {
        Self {
            database: Arc::new(RwLock::new(None)),
            encryption_manager,
            key_manager,
        }
    }

    /// Set the database for the service (placeholder implementation)
    pub async fn set_database(&self, _database: ()) {
        let mut db = self.database.write().await;
        *db = Some(()); // Placeholder
    }

    /// Map server errors to gRPC error strings
    fn map_error(err: ServerError) -> String {
        error!("gRPC service error: {:?}", err);
        err.to_string()
    }
}

// Basic gRPC service implementation using HTTP/JSON for now
// This can be upgraded to full protobuf-based gRPC later
impl FortressGrpcService {
    /// Create a new database
    pub async fn create_database(
        &self,
        request: CreateDatabaseRequest,
    ) -> Result<DatabaseResponse, String> {
        info!("Creating database: {}", request.name);

        let database = Database {
            id: uuid::Uuid::new_v4().to_string(),
            name: request.name,
            description: request.description,
            created_at: chrono::Utc::now(),
            updated_at: chrono::Utc::now(),
            config: request.config.unwrap_or_default(),
        };

        Ok(DatabaseResponse { database })
    }

    /// Get a database by ID
    pub async fn get_database(
        &self,
        request: GetDatabaseRequest,
    ) -> Result<DatabaseResponse, String> {
        debug!("Getting database: {}", request.database_id);

        // Implementation would fetch from storage
        Err("Database not found".to_string())
    }

    /// List all databases
    pub async fn list_databases(
        &self,
        _request: ListDatabasesRequest,
    ) -> Result<ListDatabasesResponse, String> {
        info!("Listing databases");
        
        // Implementation would list from storage
        Ok(ListDatabasesResponse {
            databases: vec![],
            next_page_token: "".to_string(),
        })
    }

    /// Delete a database
    pub async fn delete_database(
        &self,
        request: DeleteDatabaseRequest,
    ) -> Result<(), String> {
        info!("Deleting database: {}", request.database_id);

        // Implementation would delete from storage
        Ok(())
    }

    /// Encrypt data for a database
    pub async fn encrypt_data(
        &self,
        request: EncryptRequest,
    ) -> Result<EncryptResponse, String> {
        debug!("Encrypting data for database: {}", request.database_id);

        // Validate request
        if request.plaintext.is_empty() {
            return Err("Data to encrypt cannot be empty".to_string());
        }

        if request.key_id.as_ref().map_or(true, |s| s.is_empty()) {
            return Err("Key ID cannot be empty".to_string());
        }

        // Get the encryption key
        let key_id = request.key_id.clone().unwrap_or_default();
        let key = match self.key_manager.retrieve_key(&key_id).await {
            Ok(key) => key,
            Err(e) => {
                error!("Failed to get encryption key: {}", e);
                return Err(format!("Key not found: {}", e));
            }
        };

        // Encrypt the data
        match self.encryption_manager.encrypt(
            &request.plaintext,
            key.0.as_bytes(), // Use only the SecureKey part
        ) {
            Ok(encrypted_data) => {
                info!("Successfully encrypted {} bytes for database {}", 
                      request.plaintext.len(), request.database_id);
                
                Ok(EncryptResponse {
                    ciphertext: encrypted_data,
                    key_id: key_id,
                    encrypted_at: chrono::Utc::now(),
                    metadata: HashMap::new(),
                })
            }
            Err(e) => {
                error!("Failed to encrypt data: {}", e);
                Err(format!("Encryption failed: {}", e))
            }
        }
    }

    /// Decrypt data for a database
    pub async fn decrypt_data(
        &self,
        request: DecryptRequest,
    ) -> Result<DecryptResponse, String> {
        debug!("Decrypting data for database: {}", request.database_id);

        // Validate request
        if request.ciphertext.is_empty() {
            return Err("Encrypted data cannot be empty".to_string());
        }

        if request.key_id.is_empty() {
            return Err("Key ID cannot be empty".to_string());
        }

        // Get the decryption key
        let key = match self.key_manager.retrieve_key(&request.key_id).await {
            Ok(key) => key,
            Err(e) => {
                error!("Failed to get decryption key: {}", e);
                return Err(format!("Key not found: {}", e));
            }
        };

        // Decrypt the data
        match self.encryption_manager.decrypt(
            &request.ciphertext,
            key.0.as_bytes(), // Use only the SecureKey part
        ) {
            Ok(decrypted_data) => {
                info!("Successfully decrypted {} bytes for database {}", 
                      decrypted_data.len(), request.database_id);
                
                Ok(DecryptResponse {
                    plaintext: decrypted_data,
                    decrypted_at: chrono::Utc::now(),
                    metadata: HashMap::new(),
                })
            }
            Err(e) => {
                error!("Failed to decrypt data: {}", e);
                Err(format!("Decryption failed: {}", e))
            }
        }
    }

    /// Batch encrypt multiple data items
    pub async fn batch_encrypt_data(
        &self,
        request: BatchEncryptRequest,
    ) -> Result<BatchEncryptResponse, String> {
        debug!("Batch encrypting {} items for database: {}", request.items.len(), request.database_id);

        if request.items.is_empty() {
            return Err("Items cannot be empty".to_string());
        }

        let mut results = Vec::new();
        let mut errors = Vec::new();

        for (index, item) in request.items.into_iter().enumerate() {
            let encrypt_request = EncryptRequest {
                database_id: request.database_id.clone(),
                plaintext: item.data,
                key_id: Some(item.key_id.clone()),
                metadata: HashMap::new(),
            };

            match self.encrypt_data(encrypt_request).await {
                Ok(response) => {
                    results.push(BatchEncryptResult {
                        index: index as u32,
                        encrypted_data: hex::encode(&response.ciphertext),
                        algorithm: "aes-256-gcm".to_string(),
                        key_id: response.key_id,
                        timestamp: response.encrypted_at,
                        success: true,
                        error: None,
                    });
                }
                Err(e) => {
                    errors.push(BatchEncryptError {
                        index: index as u32,
                        error: e.clone(),
                    });
                    results.push(BatchEncryptResult {
                        index: index as u32,
                        encrypted_data: String::new(),
                        algorithm: String::new(),
                        key_id: String::new(),
                        timestamp: chrono::Utc::now(),
                        success: false,
                        error: Some(e),
                    });
                }
            }
        }

        info!("Batch encryption completed: {} successful, {} failed", 
              results.iter().filter(|r| r.success).count(),
              errors.len());

        Ok(BatchEncryptResponse {
            results: results.clone(),
            errors: errors.clone(),
            total_items: results.len() as u32,
            successful_items: results.iter().filter(|r| r.success).count() as u32,
            failed_items: errors.len() as u32,
        })
    }

    /// Batch decrypt multiple data items
    pub async fn batch_decrypt_data(
        &self,
        request: BatchDecryptRequest,
    ) -> Result<BatchDecryptResponse, String> {
        debug!("Batch decrypting {} items for database: {}", request.items.len(), request.database_id);

        if request.items.is_empty() {
            return Err("Items cannot be empty".to_string());
        }

        let mut results = Vec::new();
        let mut errors = Vec::new();

        for (index, item) in request.items.into_iter().enumerate() {
            let decrypt_request = DecryptRequest {
                database_id: request.database_id.clone(),
                ciphertext: item.encrypted_data.as_bytes().to_vec(),
                key_id: item.key_id.clone(),
            };

            match self.decrypt_data(decrypt_request).await {
                Ok(response) => {
                    results.push(BatchDecryptResult {
                        index: index as u32,
                        data: response.plaintext,
                        algorithm: "aes-256-gcm".to_string(),
                        key_id: "".to_string(),
                        timestamp: response.decrypted_at,
                        success: true,
                        error: None,
                    });
                }
                Err(e) => {
                    errors.push(BatchDecryptError {
                        index: index as u32,
                        error: e.clone(),
                    });
                    results.push(BatchDecryptResult {
                        index: index as u32,
                        data: Vec::new(),
                        algorithm: String::new(),
                        key_id: String::new(),
                        timestamp: chrono::Utc::now(),
                        success: false,
                        error: Some(e),
                    });
                }
            }
        }

        info!("Batch decryption completed: {} successful, {} failed", 
              results.iter().filter(|r| r.success).count(),
              errors.len());

        Ok(BatchDecryptResponse {
            results: results.clone(),
            errors: errors.clone(),
            total_items: results.len() as u32,
            successful_items: results.iter().filter(|r| r.success).count() as u32,
            failed_items: errors.len() as u32,
        })
    }

    /// Perform health check
    pub async fn health_check(
        &self,
    ) -> Result<HealthResponse, String> {
        debug!("Health check requested");

        let components = vec![
            ComponentHealth {
                name: "encryption".to_string(),
                status: 1, // Healthy
                message: "All encryption systems operational".to_string(),
            },
            ComponentHealth {
                name: "storage".to_string(),
                status: 1, // Healthy
                message: "Storage backend operational".to_string(),
            },
        ];

        let response = HealthResponse {
            status: 1, // Healthy
            version: "0.1.0".to_string(),
            timestamp: chrono::Utc::now(),
            components,
        };

        Ok(response)
    }

    /// Get system metrics
    pub async fn get_metrics(
        &self,
    ) -> Result<MetricsResponse, String> {
        debug!("Metrics requested");

        // Implementation would collect actual metrics
        let response = MetricsResponse {
            timestamp: chrono::Utc::now(),
            counters: HashMap::new(),
            gauges: HashMap::new(),
            histograms: HashMap::new(),
        };

        Ok(response)
    }
}