From 20af0f0daaa67dbb34184b5f855a75c2eb1864d3 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Wed, 29 Oct 2025 15:21:41 +0800 Subject: Update actions.rs --- crates/vcs_actions/src/actions.rs | 113 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) (limited to 'crates/vcs_actions/src') diff --git a/crates/vcs_actions/src/actions.rs b/crates/vcs_actions/src/actions.rs index 20bd037..858695a 100644 --- a/crates/vcs_actions/src/actions.rs +++ b/crates/vcs_actions/src/actions.rs @@ -1,5 +1,118 @@ +use std::sync::Arc; + +use action_system::action::ActionContext; +use tcp_connection::{error::TcpTargetError, instance::ConnectionInstance}; +use tokio::sync::Mutex; +use vcs_data::{ + constants::SERVER_PATH_MEMBER_PUB, + data::{local::LocalWorkspace, user::UserDirectory, vault::Vault}, +}; + pub mod local_actions; pub mod sheet_actions; pub mod user_actions; pub mod vault_actions; pub mod virtual_file_actions; + +/// Check if the connection instance is valid in the given context. +/// This function is used to verify the connection instance in actions that require remote calls. +pub fn check_connection_instance( + ctx: &ActionContext, +) -> Result<&Arc>, TcpTargetError> { + let Some(instance) = ctx.instance() else { + return Err(TcpTargetError::NotFound( + "Connection instance lost.".to_string(), + )); + }; + Ok(instance) +} + +/// Try to get the Vault instance from the context. +pub fn try_get_vault(ctx: &ActionContext) -> Result, TcpTargetError> { + let Some(vault) = ctx.get_arc::() else { + return Err(TcpTargetError::NotFound( + "Vault instance not found".to_string(), + )); + }; + Ok(vault) +} + +/// Try to get the LocalWorkspace instance from the context. +pub fn try_get_local_workspace(ctx: &ActionContext) -> Result, TcpTargetError> { + let Some(local_workspace) = ctx.get_arc::() else { + return Err(TcpTargetError::NotFound( + "LocalWorkspace instance not found".to_string(), + )); + }; + Ok(local_workspace) +} + +/// Try to get the UserDirectory instance from the context. +pub fn try_get_user_directory(ctx: &ActionContext) -> Result, TcpTargetError> { + let Some(user_directory) = ctx.get_arc::() else { + return Err(TcpTargetError::NotFound( + "UserDirectory instance not found".to_string(), + )); + }; + Ok(user_directory) +} + +/// Authenticate member based on whether the process is running locally or remotely +pub async fn auth_member( + ctx: &ActionContext, + instance: &Arc>, +) -> Result<(), TcpTargetError> { + // Start Challenge (Remote) + if ctx.is_proc_on_remote() { + let vault = try_get_vault(ctx)?; + let result = instance + .lock() + .await + .challenge(vault.vault_path().join(SERVER_PATH_MEMBER_PUB)) + .await; + + return match result { + Ok(pass) => { + if !pass { + // Send false to inform the client that authentication failed + instance.lock().await.write(false).await?; + Err(TcpTargetError::Authentication( + "Authenticate failed.".to_string(), + )) + } else { + // Send true to inform the client that authentication was successful + instance.lock().await.write(true).await?; + Ok(()) + } + } + Err(e) => Err(e), + }; + } + + // Accept Challenge (Local) + if ctx.is_proc_on_local() { + let local_workspace = try_get_local_workspace(ctx)?; + let user_directory = try_get_user_directory(ctx)?; + + // Member name & Private key + let member_name = local_workspace.config().lock().await.current_account(); + let private_key = user_directory.account_private_key_path(&member_name); + let _ = instance + .lock() + .await + .accept_challenge(private_key, &member_name) + .await?; + + // Read result + let challenge_result = instance.lock().await.read::().await?; + if challenge_result { + return Ok(()); + } else { + return Err(TcpTargetError::Authentication( + "Authenticate failed.".to_string(), + )); + } + } + + Err(TcpTargetError::NoResult("Auth failed.".to_string())) +} -- cgit