1use std::{
150 collections::HashMap,
151 io::{Read, Write},
152 sync::{Arc, Mutex},
153 time::Duration,
154};
155
156use base64::{Engine, engine::general_purpose};
157use flate2::{Compression, read::GzDecoder, write::GzEncoder};
158use ring::{
159 aead::{self, AES_256_GCM, LessSafeKey, UnboundKey},
160 hmac,
161 rand::{SecureRandom, SystemRandom},
162};
163use serde::{Deserialize, Serialize};
164use tauri::{AppHandle, Emitter, Manager};
165use tokio::{
166 sync::{Mutex as AsyncMutex, RwLock, Semaphore},
167 time::timeout,
168};
169
170use crate::dev_log;
171
172#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct TauriIPCMessage {
175 pub channel:String,
176
177 pub data:serde_json::Value,
178
179 pub sender:Option<String>,
180
181 pub timestamp:u64,
182}
183
184#[derive(Debug, Clone, Serialize, Deserialize)]
186pub struct ConnectionStatus {
187 pub connected:bool,
188}
189
190type ListenerCallback = Box<dyn Fn(serde_json::Value) -> Result<(), String> + Send + Sync>;
192
193#[derive(Clone)]
195pub struct TauriIPCServer {
196 app_handle:AppHandle,
197
198 listeners:Arc<Mutex<HashMap<String, Vec<ListenerCallback>>>>,
199
200 is_connected:Arc<Mutex<bool>>,
201
202 message_queue:Arc<Mutex<Vec<TauriIPCMessage>>>,
203}
204
205pub struct MessageCompressor {
207 CompressionLevel:u32,
208
209 BatchSize:usize,
210}
211
212impl MessageCompressor {
213 pub fn new(CompressionLevel:u32, BatchSize:usize) -> Self { Self { CompressionLevel, BatchSize } }
215
216 pub fn compress_messages(&self, Messages:Vec<TauriIPCMessage>) -> Result<Vec<u8>, String> {
218 let SerializedMessages =
219 serde_json::to_vec(&Messages).map_err(|e| format!("Failed to serialize messages: {}", e))?;
220
221 let mut encoder = GzEncoder::new(Vec::new(), Compression::new(self.CompressionLevel));
222
223 encoder
224 .write_all(&SerializedMessages)
225 .map_err(|e| format!("Failed to compress messages: {}", e))?;
226
227 encoder.finish().map_err(|e| format!("Failed to finish compression: {}", e))
228 }
229
230 pub fn decompress_messages(&self, CompressedData:&[u8]) -> Result<Vec<TauriIPCMessage>, String> {
232 let mut decoder = GzDecoder::new(CompressedData);
233
234 let mut DecompressedData = Vec::new();
235
236 decoder
237 .read_to_end(&mut DecompressedData)
238 .map_err(|e| format!("Failed to decompress data: {}", e))?;
239
240 serde_json::from_slice(&DecompressedData).map_err(|e| format!("Failed to deserialize messages: {}", e))
241 }
242
243 pub fn should_batch(&self, MessagesCount:usize) -> bool { MessagesCount >= self.BatchSize }
245}
246
247impl TauriIPCServer {
248 pub fn new(app_handle:AppHandle) -> Self {
250 dev_log!("ipc", "[TauriIPCServer] Initializing Mountain IPC Server");
251
252 Self {
253 app_handle,
254
255 listeners:Arc::new(Mutex::new(HashMap::new())),
256
257 is_connected:Arc::new(Mutex::new(false)),
258
259 message_queue:Arc::new(Mutex::new(Vec::new())),
260 }
261 }
262
263 pub async fn initialize(&self) -> Result<(), String> {
265 dev_log!("ipc", "[TauriIPCServer] Setting up IPC listeners");
266
267 {
269 let mut is_connected = self
270 .is_connected
271 .lock()
272 .map_err(|e| format!("Failed to lock connection status: {}", e))?;
273
274 *is_connected = true;
275 }
276
277 self.send_connection_status(true)
279 .await
280 .map_err(|e| format!("Failed to send connection status: {}", e))?;
281
282 dev_log!("ipc", "[TauriIPCServer] IPC Server initialized successfully");
283
284 self.process_message_queue().await;
286
287 Ok(())
288 }
289
290 pub async fn send(&self, channel:&str, data:serde_json::Value) -> Result<(), String> {
292 let Message = TauriIPCMessage {
293 channel:channel.to_string(),
294
295 data,
296
297 sender:Some("mountain".to_string()),
298
299 timestamp:std::time::SystemTime::now()
300 .duration_since(std::time::UNIX_EPOCH)
301 .unwrap_or_default()
302 .as_millis() as u64,
303 };
304
305 let is_connected = {
306 let guard = self
307 .is_connected
308 .lock()
309 .map_err(|e| format!("Failed to check connection status: {}", e))?;
310
311 *guard
312 };
313
314 if !is_connected {
315 let mut queue = self
317 .message_queue
318 .lock()
319 .map_err(|e| format!("Failed to access Message queue: {}", e))?;
320
321 queue.push(Message);
322
323 dev_log!(
324 "ipc",
325 "[TauriIPCServer] Message queued (channel: {}, queue size: {})",
326 channel,
327 queue.len()
328 );
329
330 return Ok(());
331 }
332
333 self.emit_message(&Message).await
335 }
336
337 pub fn on(&self, channel:&str, callback:ListenerCallback) -> Result<(), String> {
339 let mut listeners = self
340 .listeners
341 .lock()
342 .map_err(|e| format!("Failed to access listeners: {}", e))?;
343
344 listeners.entry(channel.to_string()).or_insert_with(Vec::new).push(callback);
345
346 dev_log!("ipc", "[TauriIPCServer] Listener registered for channel: {}", channel);
347
348 Ok(())
349 }
350
351 pub fn off(&self, channel:&str, callback:&ListenerCallback) -> Result<(), String> {
353 let mut listeners = self
354 .listeners
355 .lock()
356 .map_err(|e| format!("Failed to access listeners: {}", e))?;
357
358 if let Some(channel_listeners) = listeners.get_mut(channel) {
359 channel_listeners.retain(|cb| !std::ptr::eq(cb as *const _, callback as *const _));
360
361 if channel_listeners.is_empty() {
362 listeners.remove(channel);
363 }
364 }
365
366 dev_log!("ipc", "[TauriIPCServer] Listener removed from channel: {}", channel);
367
368 Ok(())
369 }
370
371 pub async fn IncomingMessage(&self, Message:TauriIPCMessage) -> Result<(), String> {
373 dev_log!("ipc", "[TauriIPCServer] Received Message on channel: {}", Message.channel);
374
375 let listeners = self
376 .listeners
377 .lock()
378 .map_err(|e| format!("Failed to access listeners: {}", e))?;
379
380 if let Some(channel_listeners) = listeners.get(&Message.channel) {
381 for callback in channel_listeners {
382 if let Err(e) = callback(Message.data.clone()) {
383 dev_log!(
384 "ipc",
385 "error: [TauriIPCServer] Error in listener for channel {}: {}",
386 Message.channel,
387 e
388 );
389 }
390 }
391 } else {
392 dev_log!("ipc", "[TauriIPCServer] No listeners found for channel: {}", Message.channel);
393 }
394
395 Ok(())
396 }
397
398 async fn send_connection_status(&self, connected:bool) -> Result<(), String> {
400 let status = ConnectionStatus { connected };
401
402 self.app_handle
403 .emit("vscode-ipc-status", status)
404 .map_err(|e| format!("Failed to emit connection status: {}", e))?;
405
406 dev_log!("ipc", "[TauriIPCServer] Connection status sent: {}", connected);
407
408 Ok(())
409 }
410
411 async fn emit_message(&self, Message:&TauriIPCMessage) -> Result<(), String> {
413 self.app_handle
414 .emit("vscode-ipc-Message", Message)
415 .map_err(|e| format!("Failed to emit Message: {}", e))?;
416
417 dev_log!("ipc", "[TauriIPCServer] Message emitted on channel: {}", Message.channel);
418
419 Ok(())
420 }
421
422 async fn process_message_queue(&self) {
424 let mut queue = match self.message_queue.lock() {
425 Ok(queue) => queue,
426
427 Err(e) => {
428 dev_log!("ipc", "error: [TauriIPCServer] Failed to access Message queue: {}", e);
429
430 return;
431 },
432 };
433
434 while let Some(Message) = queue.pop() {
435 if let Err(e) = self.emit_message(&Message).await {
436 dev_log!("ipc", "error: [TauriIPCServer] Failed to send queued Message: {}", e);
437
438 queue.insert(0, Message);
440
441 break;
442 }
443 }
444
445 dev_log!(
446 "ipc",
447 "[TauriIPCServer] Message queue processed, {} messages remaining",
448 queue.len()
449 );
450 }
451
452 pub fn get_connection_status(&self) -> Result<bool, String> {
454 let guard = self
455 .is_connected
456 .lock()
457 .map_err(|e| format!("Failed to get connection status: {}", e))?;
458
459 Ok(*guard)
460 }
461
462 pub fn get_queue_size(&self) -> Result<usize, String> {
464 let guard = self
465 .message_queue
466 .lock()
467 .map_err(|e| format!("Failed to get queue size: {}", e))?;
468
469 Ok(guard.len())
470 }
471
472 pub fn dispose(&self) -> Result<(), String> {
474 {
475 let mut listeners = self
476 .listeners
477 .lock()
478 .map_err(|e| format!("Failed to access listeners: {}", e))?;
479
480 listeners.clear();
481 }
482
483 {
484 let mut queue = self
485 .message_queue
486 .lock()
487 .map_err(|e| format!("Failed to access Message queue: {}", e))?;
488
489 queue.clear();
490 }
491
492 {
493 let mut is_connected = self
494 .is_connected
495 .lock()
496 .map_err(|e| format!("Failed to access connection status: {}", e))?;
497
498 *is_connected = false;
499 }
500
501 dev_log!("ipc", "[TauriIPCServer] IPC Server disposed");
502
503 Ok(())
504 }
505
506 pub async fn validate_message_permissions(&self, Message:&TauriIPCMessage) -> Result<(), String> {
508 let permission_manager = PermissionManager::new();
509
510 permission_manager.initialize_defaults().await;
511
512 let context = self.create_security_context(Message);
513
514 let operation = Message.channel.replace("mountain_", "");
516
517 permission_manager.validate_permission(&operation, &context).await
519 }
520
521 fn create_security_context(&self, Message:&TauriIPCMessage) -> SecurityContext {
523 SecurityContext {
524 user_id:Message.sender.clone().unwrap_or("unknown".to_string()),
525
526 roles:vec!["user".to_string()],
528
529 permissions:vec![],
530
531 ip_address:"127.0.0.1".to_string(),
533
534 timestamp:std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_millis(Message.timestamp),
535 }
536 }
537
538 pub async fn log_security_event(&self, event:SecurityEvent) {
540 let permission_manager = PermissionManager::new();
541
542 permission_manager.log_security_event(event).await;
543 }
544
545 pub async fn record_performance_metrics(&self, channel:String, duration:std::time::Duration, success:bool) {
547 dev_log!(
549 "ipc",
550 "[TauriIPCServer] Performance recorded - Channel: {}, Duration: {:?}, Success: {}",
551 channel,
552 duration,
553 success
554 );
555 }
556
557 pub async fn get_security_audit_log(&self, limit:usize) -> Result<Vec<SecurityEvent>, String> {
559 let permission_manager = PermissionManager::new();
560
561 Ok(permission_manager.get_audit_log(limit).await)
562 }
563
564 pub async fn send_compressed_batch(&self, channel:&str, messages:Vec<TauriIPCMessage>) -> Result<(), String> {
566 let compressor = MessageCompressor::new(6, 10);
569
570 let compressed_data = compressor
571 .compress_messages(messages)
572 .map_err(|e| format!("Failed to compress batch: {}", e))?;
573
574 let batch_message = TauriIPCMessage {
575 channel:"compressed_batch".to_string(),
576
577 data:serde_json::Value::String(general_purpose::STANDARD.encode(&compressed_data)),
578
579 sender:Some("mountain".to_string()),
580
581 timestamp:std::time::SystemTime::now()
582 .duration_since(std::time::UNIX_EPOCH)
583 .unwrap_or_default()
584 .as_millis() as u64,
585 };
586
587 self.send(channel, serde_json::to_value(batch_message).unwrap()).await
588 }
589
590 pub async fn CompressedBatch(&self, Message:TauriIPCMessage) -> Result<(), String> {
592 let compressed_data_base64 = Message.data.as_str().ok_or("Compressed batch data must be a string")?;
593
594 let compressed_data = general_purpose::STANDARD
595 .decode(compressed_data_base64)
596 .map_err(|e| format!("Failed to decode base64: {}", e))?;
597
598 let compressor = MessageCompressor::new(6, 10);
599
600 let messages = compressor
601 .decompress_messages(&compressed_data)
602 .map_err(|e| format!("Failed to decompress batch: {}", e))?;
603
604 for Message in messages {
606 self.IncomingMessage(Message).await?;
607 }
608
609 Ok(())
610 }
611
612 pub async fn send_with_pool(&self, channel:&str, data:serde_json::Value) -> Result<(), String> {
614 let pool = Arc::new(ConnectionPool::new(10, Duration::from_secs(30)));
615
616 let Handle = pool
617 .GetConnection()
618 .await
619 .map_err(|e| format!("Failed to get connection: {}", e))?;
620
621 let result = self.send(channel, data).await;
622
623 pool.ReleaseConnection(Handle).await;
624
625 result
626 }
627
628 pub async fn get_connection_stats(&self) -> Result<ConnectionStats, String> {
630 let pool = Arc::new(ConnectionPool::new(10, Duration::from_secs(30)));
631
632 Ok(pool.GetStats().await)
633 }
634
635 pub async fn send_secure(&self, channel:&str, data:serde_json::Value) -> Result<(), String> {
637 let secure_channel =
638 SecureMessageChannel::new().map_err(|e| format!("Failed to create secure channel: {}", e))?;
639
640 let Message = TauriIPCMessage {
641 channel:channel.to_string(),
642
643 data,
644
645 sender:Some("mountain".to_string()),
646
647 timestamp:std::time::SystemTime::now()
648 .duration_since(std::time::UNIX_EPOCH)
649 .unwrap_or_default()
650 .as_millis() as u64,
651 };
652
653 let encrypted_message = secure_channel
654 .encrypt_message(&Message)
655 .map_err(|e| format!("Failed to encrypt Message: {}", e))?;
656
657 let encrypted_data = serde_json::to_value(encrypted_message)
658 .map_err(|e| format!("Failed to serialize encrypted Message: {}", e))?;
659
660 self.send("secure_message", encrypted_data).await
661 }
662
663 pub async fn SecureMessage(&self, encrypted_data:serde_json::Value) -> Result<(), String> {
665 let encrypted_message:EncryptedMessage = serde_json::from_value(encrypted_data)
666 .map_err(|e| format!("Failed to deserialize encrypted Message: {}", e))?;
667
668 let secure_channel =
669 SecureMessageChannel::new().map_err(|e| format!("Failed to create secure channel: {}", e))?;
670
671 let Message = secure_channel
672 .decrypt_message(&encrypted_message)
673 .map_err(|e| format!("Failed to decrypt Message: {}", e))?;
674
675 self.IncomingMessage(Message).await
676 }
677
678 pub async fn MessageWithPermissions(&self, Message:TauriIPCMessage) -> Result<(), String> {
680 let permission_manager = PermissionManager::new();
681
682 let context = self.create_security_context(&Message);
683
684 let operation = Message.channel.replace("mountain_", "");
686
687 permission_manager.validate_permission(&operation, &context).await?;
689
690 self.IncomingMessage(Message).await
692 }
693}
694
695pub struct ConnectionPool {
702 MaxConnections:usize,
703
704 ConnectionTimeout:Duration,
705
706 Semaphore:Arc<Semaphore>,
707
708 ActiveConnection:Arc<AsyncMutex<HashMap<String, ConnectionHandle>>>,
709
710 HealthChecker:Arc<AsyncMutex<ConnectionHealthChecker>>,
711}
712
713#[derive(Clone)]
715pub struct ConnectionHandle {
716 pub id:String,
717
718 pub created_at:std::time::Instant,
719
720 pub last_used:std::time::Instant,
721
722 pub health_score:f64,
723
724 pub error_count:usize,
725}
726
727impl ConnectionHandle {
728 pub fn new() -> Self {
730 Self {
731 id:uuid::Uuid::new_v4().to_string(),
732
733 created_at:std::time::Instant::now(),
734
735 last_used:std::time::Instant::now(),
736
737 health_score:100.0,
738
739 error_count:0,
740 }
741 }
742
743 pub fn update_health(&mut self, success:bool) {
745 if success {
746 self.health_score = (self.health_score + 10.0).min(100.0);
747
748 self.error_count = 0;
749 } else {
750 self.health_score = (self.health_score - 25.0).max(0.0);
751
752 self.error_count += 1;
753 }
754
755 self.last_used = std::time::Instant::now();
756 }
757
758 pub fn is_healthy(&self) -> bool { self.health_score > 50.0 && self.error_count < 5 }
760
761 pub fn is_alive(&self) -> bool { self.health_score > 0.0 && self.error_count < 10 }
763}
764
765impl ConnectionPool {
766 pub fn new(MaxConnections:usize, ConnectionTimeout:Duration) -> Self {
768 Self {
769 MaxConnections,
770
771 ConnectionTimeout,
772
773 Semaphore:Arc::new(Semaphore::new(MaxConnections)),
774
775 ActiveConnection:Arc::new(AsyncMutex::new(HashMap::new())),
776
777 HealthChecker:Arc::new(AsyncMutex::new(ConnectionHealthChecker::new())),
778 }
779 }
780
781 pub async fn GetConnection(&self) -> Result<ConnectionHandle, String> {
783 let _permit = timeout(self.ConnectionTimeout, self.Semaphore.acquire())
784 .await
785 .map_err(|_| "Connection timeout")?
786 .map_err(|e| format!("Failed to acquire connection: {}", e))?;
787
788 let Handle = ConnectionHandle::new();
789
790 {
791 let mut connections = self.ActiveConnection.lock().await;
792
793 connections.insert(Handle.id.clone(), Handle.clone());
794 }
795
796 self.StartHealthMonitoring(&Handle.id).await;
798
799 Ok(Handle)
800 }
801
802 pub async fn ReleaseConnection(&self, Handle:ConnectionHandle) {
804 {
805 let mut connections = self.ActiveConnection.lock().await;
806
807 connections.remove(&Handle.id);
808 }
809
810 }
812
813 pub async fn GetStats(&self) -> ConnectionStats {
815 let connections = self.ActiveConnection.lock().await;
816
817 let healthy_connections = connections.values().filter(|h| h.is_healthy()).count();
818
819 ConnectionStats {
820 total_connections:connections.len(),
821
822 healthy_connections,
823
824 max_connections:self.MaxConnections,
825
826 available_permits:self.Semaphore.available_permits(),
827
828 connection_timeout:self.ConnectionTimeout,
829 }
830 }
831
832 pub async fn CleanUpStaleConnections(&self) -> usize {
834 let mut connections = self.ActiveConnection.lock().await;
835
836 let now = std::time::Instant::now();
837
838 let stale_threshold = Duration::from_secs(300);
840
841 let stale_ids:Vec<String> = connections
842 .iter()
843 .filter(|(_, Handle)| now.duration_since(Handle.last_used) > stale_threshold || !Handle.is_healthy())
844 .map(|(id, _)| id.clone())
845 .collect();
846
847 let stale_count = stale_ids.len();
848
849 for id in stale_ids {
850 connections.remove(&id);
851 }
852
853 stale_count
854 }
855
856 async fn StartHealthMonitoring(&self, connection_id:&str) {
858 let health_checker = self.HealthChecker.clone();
859
860 let active_connection = self.ActiveConnection.clone();
861
862 let connection_id = connection_id.to_string();
863
864 tokio::spawn(async move {
865 let mut interval = tokio::time::interval(Duration::from_secs(30));
866
867 loop {
868 interval.tick().await;
869
870 let checker = health_checker.lock().await;
871 let mut connections = match active_connection.try_lock() {
872 Ok(conns) => conns,
873 Err(_) => continue,
874 };
875
876 if let Some(Handle) = connections.get_mut(&connection_id) {
877 let is_healthy = checker.check_connection_health(Handle).await;
878 Handle.update_health(is_healthy);
879
880 if !Handle.is_healthy() {
881 dev_log!(
882 "ipc",
883 "Connection {} marked as unhealthy (score: {:.1})",
884 Handle.id,
885 Handle.health_score
886 );
887 }
888 } else {
889 break;
891 }
892 }
893 });
894 }
895}
896
897struct ConnectionHealthChecker {}
899
900impl ConnectionHealthChecker {
901 fn new() -> Self { Self {} }
902
903 async fn check_connection_health(&self, Handle:&mut ConnectionHandle) -> bool { Handle.is_alive() }
907}
908
909#[derive(Debug, Clone, Default)]
911pub struct ConnectionStats {
912 pub total_connections:usize,
913
914 pub healthy_connections:usize,
915
916 pub max_connections:usize,
917
918 pub available_permits:usize,
919
920 pub connection_timeout:Duration,
921}
922
923pub struct SecureMessageChannel {
925 encryption_key:LessSafeKey,
926
927 hmac_key:Vec<u8>,
928}
929
930impl SecureMessageChannel {
931 pub fn new() -> Result<Self, String> {
933 let rng = SystemRandom::new();
934
935 let mut encryption_key_bytes = vec![0u8; 32];
937
938 rng.fill(&mut encryption_key_bytes)
939 .map_err(|e| format!("Failed to generate encryption key: {}", e))?;
940
941 let unbound_key = UnboundKey::new(&AES_256_GCM, &encryption_key_bytes)
942 .map_err(|e| format!("Failed to create unbound key: {}", e))?;
943
944 let encryption_key = LessSafeKey::new(unbound_key);
945
946 let mut hmac_key = vec![0u8; 32];
948
949 rng.fill(&mut hmac_key)
950 .map_err(|e| format!("Failed to generate HMAC key: {}", e))?;
951
952 Ok(Self { encryption_key, hmac_key })
953 }
954
955 pub fn encrypt_message(&self, Message:&TauriIPCMessage) -> Result<EncryptedMessage, String> {
957 let serialized_message =
958 serde_json::to_vec(Message).map_err(|e| format!("Failed to serialize Message: {}", e))?;
959
960 let mut nonce = [0u8; 12];
962
963 SystemRandom::new()
964 .fill(&mut nonce)
965 .map_err(|e| format!("Failed to generate nonce: {}", e))?;
966
967 let mut in_out = serialized_message.clone();
969
970 self.encryption_key
971 .seal_in_place_append_tag(aead::Nonce::assume_unique_for_key(nonce), aead::Aad::empty(), &mut in_out)
972 .map_err(|e| format!("Encryption failed: {}", e))?;
973
974 let hmac_key = hmac::Key::new(hmac::HMAC_SHA256, &self.hmac_key);
976
977 let hmac_tag = hmac::sign(&hmac_key, &in_out);
978
979 Ok(EncryptedMessage { nonce:nonce.to_vec(), ciphertext:in_out, hmac_tag:hmac_tag.as_ref().to_vec() })
980 }
981
982 pub fn decrypt_message(&self, encrypted:&EncryptedMessage) -> Result<TauriIPCMessage, String> {
984 let hmac_key = hmac::Key::new(hmac::HMAC_SHA256, &self.hmac_key);
986
987 hmac::verify(&hmac_key, &encrypted.ciphertext, &encrypted.hmac_tag)
988 .map_err(|_| "HMAC verification failed".to_string())?;
989
990 let mut in_out = encrypted.ciphertext.clone();
992
993 let nonce_slice:&[u8] = &encrypted.nonce;
994
995 let nonce_array:[u8; 12] = nonce_slice.try_into().map_err(|_| "Invalid nonce length".to_string())?;
996
997 let nonce = aead::Nonce::assume_unique_for_key(nonce_array);
998
999 self.encryption_key
1000 .open_in_place(nonce, aead::Aad::empty(), &mut in_out)
1001 .map_err(|e| format!("Decryption failed: {}", e))?;
1002
1003 let plaintext_len = in_out.len() - AES_256_GCM.tag_len();
1005
1006 in_out.truncate(plaintext_len);
1007
1008 serde_json::from_slice(&in_out).map_err(|e| format!("Failed to deserialize Message: {}", e))
1010 }
1011
1012 pub fn rotate_keys(&mut self) -> Result<(), String> {
1014 *self = Self::new()?;
1015 Ok(())
1016 }
1017}
1018
1019#[derive(Debug, Clone, Serialize, Deserialize)]
1021pub struct EncryptedMessage {
1022 nonce:Vec<u8>,
1023
1024 ciphertext:Vec<u8>,
1025
1026 hmac_tag:Vec<u8>,
1027}
1028
1029#[tauri::command]
1031pub async fn mountain_ipc_receive_message(app_handle:tauri::AppHandle, Message:TauriIPCMessage) -> Result<(), String> {
1032 dev_log!(
1033 "ipc",
1034 "[TauriIPCServer] Received IPC Message from Wind on channel: {}",
1035 Message.channel
1036 );
1037
1038 if let Some(ipc_server) = app_handle.try_state::<TauriIPCServer>() {
1040 if let Err(e) = ipc_server.validate_message_permissions(&Message).await {
1042 dev_log!(
1043 "ipc",
1044 "error: [TauriIPCServer] Permission validation failed for channel {}: {}",
1045 Message.channel,
1046 e
1047 );
1048
1049 ipc_server
1051 .log_security_event(SecurityEvent {
1052 event_type:SecurityEventType::PermissionDenied,
1053 user_id:Message.sender.clone().unwrap_or("unknown".to_string()),
1054 operation:Message.channel.clone(),
1055 timestamp:std::time::SystemTime::now(),
1056 details:Some(format!("Permission denied: {}", e)),
1057 })
1058 .await;
1059
1060 return Err(format!("Permission denied: {}", e));
1061 }
1062
1063 let start_time = std::time::Instant::now();
1065
1066 let result = ipc_server.IncomingMessage(Message.clone()).await;
1067
1068 let duration = start_time.elapsed();
1069
1070 ipc_server
1072 .record_performance_metrics(Message.channel, duration, result.is_ok())
1073 .await;
1074
1075 result
1076 } else {
1077 Err("IPC Server not found in application state".to_string())
1078 }
1079}
1080
1081#[tauri::command]
1093pub async fn mountain_ipc_get_status(app_handle:tauri::AppHandle) -> Result<ConnectionStatus, String> {
1094 if let Some(ipc_server) = app_handle.try_state::<TauriIPCServer>() {
1095 let connected = ipc_server
1096 .get_connection_status()
1097 .map_err(|e| format!("Failed to get connection status: {}", e))?;
1098
1099 Ok(ConnectionStatus { connected })
1100 } else {
1101 Err("IPC Server not found in application state".to_string())
1102 }
1103}
1104
1105#[derive(Debug, Clone, Serialize, Deserialize)]
1107pub struct SecurityContext {
1108 pub user_id:String,
1109
1110 pub roles:Vec<String>,
1111
1112 pub permissions:Vec<String>,
1113
1114 pub ip_address:String,
1115
1116 pub timestamp:std::time::SystemTime,
1117}
1118
1119pub struct PermissionManager {
1121 roles:Arc<RwLock<HashMap<String, Role>>>,
1122
1123 permissions:Arc<RwLock<HashMap<String, Permission>>>,
1124
1125 audit_log:Arc<RwLock<Vec<SecurityEvent>>>,
1126}
1127
1128#[derive(Debug, Clone, Serialize, Deserialize)]
1130pub struct SecurityEvent {
1131 pub event_type:SecurityEventType,
1132
1133 pub user_id:String,
1134
1135 pub operation:String,
1136
1137 pub timestamp:std::time::SystemTime,
1138
1139 pub details:Option<String>,
1140}
1141
1142#[derive(Debug, Clone, Serialize, Deserialize)]
1143pub enum SecurityEventType {
1144 PermissionDenied,
1145
1146 AccessGranted,
1147
1148 ConfigurationChange,
1149
1150 SecurityViolation,
1151
1152 PerformanceAnomaly,
1153}
1154
1155#[derive(Debug, Clone, Serialize, Deserialize)]
1157pub struct Role {
1158 pub name:String,
1159
1160 pub permissions:Vec<String>,
1161
1162 pub description:String,
1163}
1164
1165#[derive(Debug, Clone, Serialize, Deserialize)]
1167pub struct Permission {
1168 pub name:String,
1169
1170 pub description:String,
1171
1172 pub category:String,
1173}
1174
1175impl PermissionManager {
1176 pub fn new() -> Self {
1177 Self {
1178 roles:Arc::new(RwLock::new(HashMap::new())),
1179
1180 permissions:Arc::new(RwLock::new(HashMap::new())),
1181
1182 audit_log:Arc::new(RwLock::new(Vec::new())),
1183 }
1184 }
1185
1186 pub async fn validate_permission(&self, operation:&str, context:&SecurityContext) -> Result<(), String> {
1188 let required_permissions = self.get_required_permissions(operation).await;
1190
1191 if required_permissions.is_empty() {
1192 return Ok(()); }
1194
1195 let mut user_permissions:Vec<String> = context.permissions.iter().cloned().collect();
1197
1198 for role in context.roles.iter() {
1199 let role_perms = self.get_role_permissions(role).await;
1200
1201 user_permissions.extend(role_perms);
1202 }
1203
1204 for required in required_permissions {
1205 if !user_permissions.contains(&required) {
1206 return Err(format!("Missing permission: {}", required));
1207 }
1208 }
1209
1210 self.log_security_event(SecurityEvent {
1212 event_type:SecurityEventType::AccessGranted,
1213 user_id:context.user_id.clone(),
1214 operation:operation.to_string(),
1215 timestamp:std::time::SystemTime::now(),
1216 details:Some(format!("Access granted for operation: {}", operation)),
1217 })
1218 .await;
1219
1220 Ok(())
1221 }
1222
1223 async fn get_required_permissions(&self, operation:&str) -> Vec<String> {
1225 match operation {
1227 "file:write" | "file:delete" => vec!["file.write".to_string()],
1228
1229 "configuration:update" => vec!["config.update".to_string()],
1230
1231 "storage:set" => vec!["storage.write".to_string()],
1232
1233 "native:openExternal" => vec!["system.external".to_string()],
1234
1235 _ => Vec::new(),
1237 }
1238 }
1239
1240 async fn get_role_permissions(&self, role_name:&str) -> Vec<String> {
1242 let roles = self.roles.read().await;
1243
1244 roles.get(role_name).map(|role| role.permissions.clone()).unwrap_or_default()
1245 }
1246
1247 pub async fn log_security_event(&self, event:SecurityEvent) {
1249 let mut audit_log = self.audit_log.write().await;
1250
1251 audit_log.push(event);
1252
1253 if audit_log.len() > 1000 {
1255 audit_log.remove(0);
1256 }
1257 }
1258
1259 pub async fn get_audit_log(&self, limit:usize) -> Vec<SecurityEvent> {
1261 let audit_log = self.audit_log.read().await;
1262
1263 audit_log.iter().rev().take(limit).cloned().collect()
1264 }
1265
1266 pub async fn initialize_defaults(&self) {
1268 let mut permissions = self.permissions.write().await;
1269
1270 let mut roles = self.roles.write().await;
1271
1272 let standard_permissions = vec![
1274 ("file.read", "Read file operations"),
1275 ("file.write", "Write file operations"),
1276 ("config.read", "Read configuration"),
1277 ("config.update", "Update configuration"),
1278 ("storage.read", "Read storage"),
1279 ("storage.write", "Write storage"),
1280 ("system.external", "Access external system resources"),
1281 ];
1282
1283 for (name, description) in standard_permissions {
1284 permissions.insert(
1285 name.to_string(),
1286 Permission {
1287 name:name.to_string(),
1288 description:description.to_string(),
1289 category:"standard".to_string(),
1290 },
1291 );
1292 }
1293
1294 let standard_roles = vec![
1296 ("user", vec!["file.read", "config.read", "storage.read"]),
1297 (
1298 "developer",
1299 vec!["file.read", "file.write", "config.read", "storage.read", "storage.write"],
1300 ),
1301 (
1302 "admin",
1303 vec![
1304 "file.read",
1305 "file.write",
1306 "config.read",
1307 "config.update",
1308 "storage.read",
1309 "storage.write",
1310 "system.external",
1311 ],
1312 ),
1313 ];
1314
1315 for (name, role_permissions) in standard_roles {
1316 roles.insert(
1317 name.to_string(),
1318 Role {
1319 name:name.to_string(),
1320 permissions:role_permissions.iter().map(|p| p.to_string()).collect(),
1321 description:format!("{} role with standard permissions", name),
1322 },
1323 );
1324 }
1325 }
1326}