summaryrefslogtreecommitdiff
path: root/crates/vcs_actions
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2025-10-29 15:21:41 +0800
committer魏曹先生 <1992414357@qq.com>2025-10-29 15:22:01 +0800
commit20af0f0daaa67dbb34184b5f855a75c2eb1864d3 (patch)
tree8f4d111860738ba15ac6150f91a972a422f9a0d8 /crates/vcs_actions
parentd0f214b6eceecbf444ef023bd1b406790aee384b (diff)
Update actions.rs
Diffstat (limited to 'crates/vcs_actions')
-rw-r--r--crates/vcs_actions/src/actions.rs113
1 files changed, 113 insertions, 0 deletions
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<Mutex<ConnectionInstance>>, 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<Arc<Vault>, TcpTargetError> {
+ let Some(vault) = ctx.get_arc::<Vault>() 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<Arc<LocalWorkspace>, TcpTargetError> {
+ let Some(local_workspace) = ctx.get_arc::<LocalWorkspace>() 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<Arc<UserDirectory>, TcpTargetError> {
+ let Some(user_directory) = ctx.get_arc::<UserDirectory>() 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<Mutex<ConnectionInstance>>,
+) -> 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::<bool>().await?;
+ if challenge_result {
+ return Ok(());
+ } else {
+ return Err(TcpTargetError::Authentication(
+ "Authenticate failed.".to_string(),
+ ));
+ }
+ }
+
+ Err(TcpTargetError::NoResult("Auth failed.".to_string()))
+}