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
872 let mut connections = match active_connection.try_lock() {
873 Ok(conns) => conns,
874 Err(_) => continue,
875 };
876
877 if let Some(Handle) = connections.get_mut(&connection_id) {
878 let is_healthy = checker.check_connection_health(Handle).await;
879
880 Handle.update_health(is_healthy);
881
882 if !Handle.is_healthy() {
883 dev_log!(
884 "ipc",
885 "Connection {} marked as unhealthy (score: {:.1})",
886 Handle.id,
887 Handle.health_score
888 );
889 }
890 } else {
891 break;
893 }
894 }
895 });
896 }
897}
898
899struct ConnectionHealthChecker {}
901
902impl ConnectionHealthChecker {
903 fn new() -> Self { Self {} }
904
905 async fn check_connection_health(&self, Handle:&mut ConnectionHandle) -> bool { Handle.is_alive() }
909}
910
911#[derive(Debug, Clone, Default)]
913pub struct ConnectionStats {
914 pub total_connections:usize,
915
916 pub healthy_connections:usize,
917
918 pub max_connections:usize,
919
920 pub available_permits:usize,
921
922 pub connection_timeout:Duration,
923}
924
925pub struct SecureMessageChannel {
927 encryption_key:LessSafeKey,
928
929 hmac_key:Vec<u8>,
930}
931
932impl SecureMessageChannel {
933 pub fn new() -> Result<Self, String> {
935 let rng = SystemRandom::new();
936
937 let mut encryption_key_bytes = vec![0u8; 32];
939
940 rng.fill(&mut encryption_key_bytes)
941 .map_err(|e| format!("Failed to generate encryption key: {}", e))?;
942
943 let unbound_key = UnboundKey::new(&AES_256_GCM, &encryption_key_bytes)
944 .map_err(|e| format!("Failed to create unbound key: {}", e))?;
945
946 let encryption_key = LessSafeKey::new(unbound_key);
947
948 let mut hmac_key = vec![0u8; 32];
950
951 rng.fill(&mut hmac_key)
952 .map_err(|e| format!("Failed to generate HMAC key: {}", e))?;
953
954 Ok(Self { encryption_key, hmac_key })
955 }
956
957 pub fn encrypt_message(&self, Message:&TauriIPCMessage) -> Result<EncryptedMessage, String> {
959 let serialized_message =
960 serde_json::to_vec(Message).map_err(|e| format!("Failed to serialize Message: {}", e))?;
961
962 let mut nonce = [0u8; 12];
964
965 SystemRandom::new()
966 .fill(&mut nonce)
967 .map_err(|e| format!("Failed to generate nonce: {}", e))?;
968
969 let mut in_out = serialized_message.clone();
971
972 self.encryption_key
973 .seal_in_place_append_tag(aead::Nonce::assume_unique_for_key(nonce), aead::Aad::empty(), &mut in_out)
974 .map_err(|e| format!("Encryption failed: {}", e))?;
975
976 let hmac_key = hmac::Key::new(hmac::HMAC_SHA256, &self.hmac_key);
978
979 let hmac_tag = hmac::sign(&hmac_key, &in_out);
980
981 Ok(EncryptedMessage { nonce:nonce.to_vec(), ciphertext:in_out, hmac_tag:hmac_tag.as_ref().to_vec() })
982 }
983
984 pub fn decrypt_message(&self, encrypted:&EncryptedMessage) -> Result<TauriIPCMessage, String> {
986 let hmac_key = hmac::Key::new(hmac::HMAC_SHA256, &self.hmac_key);
988
989 hmac::verify(&hmac_key, &encrypted.ciphertext, &encrypted.hmac_tag)
990 .map_err(|_| "HMAC verification failed".to_string())?;
991
992 let mut in_out = encrypted.ciphertext.clone();
994
995 let nonce_slice:&[u8] = &encrypted.nonce;
996
997 let nonce_array:[u8; 12] = nonce_slice.try_into().map_err(|_| "Invalid nonce length".to_string())?;
998
999 let nonce = aead::Nonce::assume_unique_for_key(nonce_array);
1000
1001 self.encryption_key
1002 .open_in_place(nonce, aead::Aad::empty(), &mut in_out)
1003 .map_err(|e| format!("Decryption failed: {}", e))?;
1004
1005 let plaintext_len = in_out.len() - AES_256_GCM.tag_len();
1007
1008 in_out.truncate(plaintext_len);
1009
1010 serde_json::from_slice(&in_out).map_err(|e| format!("Failed to deserialize Message: {}", e))
1012 }
1013
1014 pub fn rotate_keys(&mut self) -> Result<(), String> {
1016 *self = Self::new()?;
1017 Ok(())
1018 }
1019}
1020
1021#[derive(Debug, Clone, Serialize, Deserialize)]
1023pub struct EncryptedMessage {
1024 nonce:Vec<u8>,
1025
1026 ciphertext:Vec<u8>,
1027
1028 hmac_tag:Vec<u8>,
1029}
1030
1031#[tauri::command]
1033pub async fn mountain_ipc_receive_message(app_handle:tauri::AppHandle, Message:TauriIPCMessage) -> Result<(), String> {
1034 dev_log!(
1035 "ipc",
1036 "[TauriIPCServer] Received IPC Message from Wind on channel: {}",
1037 Message.channel
1038 );
1039
1040 if let Some(ipc_server) = app_handle.try_state::<TauriIPCServer>() {
1042 if let Err(e) = ipc_server.validate_message_permissions(&Message).await {
1044 dev_log!(
1045 "ipc",
1046 "error: [TauriIPCServer] Permission validation failed for channel {}: {}",
1047 Message.channel,
1048 e
1049 );
1050
1051 ipc_server
1053 .log_security_event(SecurityEvent {
1054 event_type:SecurityEventType::PermissionDenied,
1055 user_id:Message.sender.clone().unwrap_or("unknown".to_string()),
1056 operation:Message.channel.clone(),
1057 timestamp:std::time::SystemTime::now(),
1058 details:Some(format!("Permission denied: {}", e)),
1059 })
1060 .await;
1061
1062 return Err(format!("Permission denied: {}", e));
1063 }
1064
1065 let start_time = std::time::Instant::now();
1067
1068 let result = ipc_server.IncomingMessage(Message.clone()).await;
1069
1070 let duration = start_time.elapsed();
1071
1072 ipc_server
1074 .record_performance_metrics(Message.channel, duration, result.is_ok())
1075 .await;
1076
1077 result
1078 } else {
1079 Err("IPC Server not found in application state".to_string())
1080 }
1081}
1082
1083#[tauri::command]
1095pub async fn mountain_ipc_get_status(app_handle:tauri::AppHandle) -> Result<ConnectionStatus, String> {
1096 if let Some(ipc_server) = app_handle.try_state::<TauriIPCServer>() {
1097 let connected = ipc_server
1098 .get_connection_status()
1099 .map_err(|e| format!("Failed to get connection status: {}", e))?;
1100
1101 Ok(ConnectionStatus { connected })
1102 } else {
1103 Err("IPC Server not found in application state".to_string())
1104 }
1105}
1106
1107#[derive(Debug, Clone, Serialize, Deserialize)]
1109pub struct SecurityContext {
1110 pub user_id:String,
1111
1112 pub roles:Vec<String>,
1113
1114 pub permissions:Vec<String>,
1115
1116 pub ip_address:String,
1117
1118 pub timestamp:std::time::SystemTime,
1119}
1120
1121pub struct PermissionManager {
1123 roles:Arc<RwLock<HashMap<String, Role>>>,
1124
1125 permissions:Arc<RwLock<HashMap<String, Permission>>>,
1126
1127 audit_log:Arc<RwLock<Vec<SecurityEvent>>>,
1128}
1129
1130#[derive(Debug, Clone, Serialize, Deserialize)]
1132pub struct SecurityEvent {
1133 pub event_type:SecurityEventType,
1134
1135 pub user_id:String,
1136
1137 pub operation:String,
1138
1139 pub timestamp:std::time::SystemTime,
1140
1141 pub details:Option<String>,
1142}
1143
1144#[derive(Debug, Clone, Serialize, Deserialize)]
1145pub enum SecurityEventType {
1146 PermissionDenied,
1147
1148 AccessGranted,
1149
1150 ConfigurationChange,
1151
1152 SecurityViolation,
1153
1154 PerformanceAnomaly,
1155}
1156
1157#[derive(Debug, Clone, Serialize, Deserialize)]
1159pub struct Role {
1160 pub name:String,
1161
1162 pub permissions:Vec<String>,
1163
1164 pub description:String,
1165}
1166
1167#[derive(Debug, Clone, Serialize, Deserialize)]
1169pub struct Permission {
1170 pub name:String,
1171
1172 pub description:String,
1173
1174 pub category:String,
1175}
1176
1177impl PermissionManager {
1178 pub fn new() -> Self {
1179 Self {
1180 roles:Arc::new(RwLock::new(HashMap::new())),
1181
1182 permissions:Arc::new(RwLock::new(HashMap::new())),
1183
1184 audit_log:Arc::new(RwLock::new(Vec::new())),
1185 }
1186 }
1187
1188 pub async fn validate_permission(&self, operation:&str, context:&SecurityContext) -> Result<(), String> {
1190 let required_permissions = self.get_required_permissions(operation).await;
1192
1193 if required_permissions.is_empty() {
1194 return Ok(()); }
1196
1197 let mut user_permissions:Vec<String> = context.permissions.iter().cloned().collect();
1199
1200 for role in context.roles.iter() {
1201 let role_perms = self.get_role_permissions(role).await;
1202
1203 user_permissions.extend(role_perms);
1204 }
1205
1206 for required in required_permissions {
1207 if !user_permissions.contains(&required) {
1208 return Err(format!("Missing permission: {}", required));
1209 }
1210 }
1211
1212 self.log_security_event(SecurityEvent {
1214 event_type:SecurityEventType::AccessGranted,
1215 user_id:context.user_id.clone(),
1216 operation:operation.to_string(),
1217 timestamp:std::time::SystemTime::now(),
1218 details:Some(format!("Access granted for operation: {}", operation)),
1219 })
1220 .await;
1221
1222 Ok(())
1223 }
1224
1225 async fn get_required_permissions(&self, operation:&str) -> Vec<String> {
1227 match operation {
1229 "file:write" | "file:delete" => vec!["file.write".to_string()],
1230
1231 "configuration:update" => vec!["config.update".to_string()],
1232
1233 "storage:set" => vec!["storage.write".to_string()],
1234
1235 "native:openExternal" => vec!["system.external".to_string()],
1236
1237 _ => Vec::new(),
1239 }
1240 }
1241
1242 async fn get_role_permissions(&self, role_name:&str) -> Vec<String> {
1244 let roles = self.roles.read().await;
1245
1246 roles.get(role_name).map(|role| role.permissions.clone()).unwrap_or_default()
1247 }
1248
1249 pub async fn log_security_event(&self, event:SecurityEvent) {
1251 let mut audit_log = self.audit_log.write().await;
1252
1253 audit_log.push(event);
1254
1255 if audit_log.len() > 1000 {
1257 audit_log.remove(0);
1258 }
1259 }
1260
1261 pub async fn get_audit_log(&self, limit:usize) -> Vec<SecurityEvent> {
1263 let audit_log = self.audit_log.read().await;
1264
1265 audit_log.iter().rev().take(limit).cloned().collect()
1266 }
1267
1268 pub async fn initialize_defaults(&self) {
1270 let mut permissions = self.permissions.write().await;
1271
1272 let mut roles = self.roles.write().await;
1273
1274 let standard_permissions = vec![
1276 ("file.read", "Read file operations"),
1277 ("file.write", "Write file operations"),
1278 ("config.read", "Read configuration"),
1279 ("config.update", "Update configuration"),
1280 ("storage.read", "Read storage"),
1281 ("storage.write", "Write storage"),
1282 ("system.external", "Access external system resources"),
1283 ];
1284
1285 for (name, description) in standard_permissions {
1286 permissions.insert(
1287 name.to_string(),
1288 Permission {
1289 name:name.to_string(),
1290 description:description.to_string(),
1291 category:"standard".to_string(),
1292 },
1293 );
1294 }
1295
1296 let standard_roles = vec![
1298 ("user", vec!["file.read", "config.read", "storage.read"]),
1299 (
1300 "developer",
1301 vec!["file.read", "file.write", "config.read", "storage.read", "storage.write"],
1302 ),
1303 (
1304 "admin",
1305 vec![
1306 "file.read",
1307 "file.write",
1308 "config.read",
1309 "config.update",
1310 "storage.read",
1311 "storage.write",
1312 "system.external",
1313 ],
1314 ),
1315 ];
1316
1317 for (name, role_permissions) in standard_roles {
1318 roles.insert(
1319 name.to_string(),
1320 Role {
1321 name:name.to_string(),
1322 permissions:role_permissions.iter().map(|p| p.to_string()).collect(),
1323 description:format!("{} role with standard permissions", name),
1324 },
1325 );
1326 }
1327 }
1328}