summaryrefslogtreecommitdiff
path: root/actions/src/remote_actions.rs
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-02-05 22:35:05 +0800
committer魏曹先生 <1992414357@qq.com>2026-02-05 22:35:05 +0800
commit27f6414ad1ff451feb0044af62f37dc2a6255ffa (patch)
treecb5693bc014cc8579dcf02a730fd4d2a5dfcf1a5 /actions/src/remote_actions.rs
parentade2fcb9302a4ab759795820dbde3b2b269490ee (diff)
Remove examples and legacy code, update .gitignore
- Delete examples directory and its example action system - Rename actions/ to legacy_actions/ and data/ to legacy_data/ - Update Cargo.toml license file reference - Move setup scripts to scripts/dev/ directory - Add todo.txt patterns to .gitignore
Diffstat (limited to 'actions/src/remote_actions.rs')
-rw-r--r--actions/src/remote_actions.rs288
1 files changed, 0 insertions, 288 deletions
diff --git a/actions/src/remote_actions.rs b/actions/src/remote_actions.rs
deleted file mode 100644
index d15edc9..0000000
--- a/actions/src/remote_actions.rs
+++ /dev/null
@@ -1,288 +0,0 @@
-use std::sync::Arc;
-
-use action_system::action::ActionContext;
-use cfg_file::config::ConfigFile;
-use tcp_connection::{error::TcpTargetError, instance::ConnectionInstance};
-use tokio::sync::{Mutex, mpsc::Sender};
-use vcs_data::{
- constants::{SERVER_PATH_MEMBER_PUB, VAULT_HOST_NAME},
- data::{
- local::{LocalWorkspace, latest_info::LatestInfo, workspace_config::LocalConfig},
- member::MemberId,
- sheet::SheetName,
- user::UserDirectory,
- vault::Vault,
- },
-};
-
-pub mod content_manage;
-pub mod edit_right_manage;
-pub mod mapping_manage;
-pub mod sheet_manage;
-pub mod workspace_manage;
-
-/// 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)
-}
-
-/// Try to get the LocalWorkspace instance from the context.
-pub fn try_get_local_output(ctx: &ActionContext) -> Result<Arc<Sender<String>>, TcpTargetError> {
- let Some(output) = ctx.get_arc::<Sender<String>>() else {
- return Err(TcpTargetError::NotFound(
- "Client sender not found".to_string(),
- ));
- };
- Ok(output)
-}
-
-/// Authenticate member based on context and return MemberId
-pub async fn auth_member(
- ctx: &ActionContext,
- instance: &Arc<Mutex<ConnectionInstance>>,
-) -> Result<(MemberId, bool), TcpTargetError> {
- // Window开服Linux连接 -> 此函数内产生 early eof
- // ~ WS # jv update
- // 身份认证失败:I/O error: early eof!
-
- // 分析相应流程:
- // 1. 服务端发起挑战,客户端接受
- // 2. 服务端发送结果,客户端接受
- // 3. 推测此时发生 early eof ---> 无 ack,导致客户端尝试拿到结果时,服务端已经结束
- // 这很有可能是 Windows 和 Linux 对于连接处理的方案差异导致的问题,需要进一步排查
-
- // Start Challenge (Remote)
- if ctx.is_proc_on_remote() {
- let mut mut_instance = instance.lock().await;
- let vault = try_get_vault(ctx)?;
-
- let using_host_mode = mut_instance.read_msgpack::<bool>().await?;
-
- let result = mut_instance
- .challenge(vault.vault_path().join(SERVER_PATH_MEMBER_PUB))
- .await;
-
- return match result {
- Ok((pass, member_id)) => {
- if !pass {
- // Send false to inform the client that authentication failed
- mut_instance.write(false).await?;
- Err(TcpTargetError::Authentication(
- "Authenticate failed.".to_string(),
- ))
- } else {
- if using_host_mode {
- if vault.config().vault_host_list().contains(&member_id) {
- // Using Host mode authentication, and is indeed an administrator
- mut_instance.write(true).await?;
- Ok((member_id, true))
- } else {
- // Using Host mode authentication, but not an administrator
- mut_instance.write(false).await?;
- Err(TcpTargetError::Authentication(
- "Authenticate failed.".to_string(),
- ))
- }
- } else {
- // Not using Host mode authentication
- mut_instance.write(true).await?;
- Ok((member_id, false))
- }
- }
- }
- Err(e) => Err(e),
- };
- }
-
- // Accept Challenge (Local)
- if ctx.is_proc_on_local() {
- let mut mut_instance = instance.lock().await;
- let local_workspace = try_get_local_workspace(ctx)?;
- let (is_host_mode, member_name) = {
- let cfg = local_workspace.config().lock_owned().await;
- (cfg.is_host_mode(), cfg.current_account())
- };
- let user_directory = try_get_user_directory(ctx)?;
-
- // Inform remote whether to authenticate in Host mode
- mut_instance.write_msgpack(is_host_mode).await?;
-
- // Member name & Private key
- let private_key = user_directory.account_private_key_path(&member_name);
- let _ = mut_instance
- .accept_challenge(private_key, &member_name)
- .await?;
-
- // Read result
- let challenge_result = mut_instance.read::<bool>().await?;
- if challenge_result {
- return Ok((member_name.clone(), is_host_mode));
- } else {
- return Err(TcpTargetError::Authentication(
- "Authenticate failed.".to_string(),
- ));
- }
- }
-
- Err(TcpTargetError::NoResult("Auth failed.".to_string()))
-}
-
-/// Get the current sheet name based on the context (local or remote).
-/// This function handles the communication between local and remote instances
-/// to verify and retrieve the current sheet name and whether it's a reference sheet.
-///
-/// On local:
-/// - Reads the current sheet from local configuration
-/// - Sends the sheet name to remote for verification
-/// - Returns the sheet name and whether it's a reference sheet if remote confirms it exists
-///
-/// On remote:
-/// - Receives sheet name from local
-/// - Verifies the sheet exists in the vault
-/// - Checks if the sheet is a reference sheet
-/// - If allow_ref is true, reference sheets are allowed to pass verification
-/// - Sends confirmation and reference status back to local
-///
-/// Returns a tuple of (SheetName, bool) where the bool indicates if it's a reference sheet,
-/// or an error if the sheet doesn't exist or doesn't meet the verification criteria.
-pub async fn get_current_sheet_name(
- ctx: &ActionContext,
- instance: &Arc<Mutex<ConnectionInstance>>,
- member_id: &MemberId,
- allow_ref: bool,
-) -> Result<(SheetName, bool), TcpTargetError> {
- let mut mut_instance = instance.lock().await;
- if ctx.is_proc_on_local() {
- let workspace = try_get_local_workspace(ctx)?;
- let config = LocalConfig::read().await?;
- let latest = LatestInfo::read_from(LatestInfo::latest_info_path(
- workspace.local_path(),
- member_id,
- ))
- .await?;
- if let Some(sheet_name) = config.sheet_in_use() {
- // Send sheet name
- mut_instance.write_msgpack(sheet_name).await?;
-
- // Read result
- if mut_instance.read_msgpack::<bool>().await? {
- // Check if sheet is a reference sheet
- let is_ref_sheet = latest.reference_sheets.contains(sheet_name);
- if allow_ref {
- // Allow reference sheets, directly return the determination result
- return Ok((sheet_name.clone(), is_ref_sheet));
- } else if is_ref_sheet {
- // Not allowed but it's a reference sheet, return an error
- return Err(TcpTargetError::ReferenceSheetNotAllowed(
- "Reference sheet not allowed".to_string(),
- ));
- } else {
- // Not allowed but not a reference sheet, return normally
- return Ok((sheet_name.clone(), false));
- }
- } else {
- return Err(TcpTargetError::NotFound("Sheet not found".to_string()));
- }
- }
- // Send empty sheet_name
- mut_instance.write_msgpack("".to_string()).await?;
-
- // Read result, since we know it's impossible to pass here, we just consume this result
- let _ = mut_instance.read_msgpack::<bool>().await?;
-
- return Err(TcpTargetError::NotFound("Sheet not found".to_string()));
- }
- if ctx.is_proc_on_remote() {
- let vault = try_get_vault(ctx)?;
-
- // Read sheet name
- let sheet_name: SheetName = mut_instance.read_msgpack().await?;
-
- // Check if sheet exists
- if let Ok(sheet) = vault.sheet(&sheet_name).await
- && let Some(holder) = sheet.holder()
- {
- let is_ref_sheet = holder == VAULT_HOST_NAME;
- if allow_ref {
- // Allow reference sheets, directly return the determination result
- if holder == member_id || holder == VAULT_HOST_NAME {
- mut_instance.write_msgpack(true).await?;
- return Ok((sheet.name().clone(), is_ref_sheet));
- }
- } else if is_ref_sheet {
- // Not allowed but it's a reference sheet, return an error
- mut_instance.write_msgpack(true).await?;
- return Err(TcpTargetError::ReferenceSheetNotAllowed(
- "Reference sheet not allowed".to_string(),
- ));
- } else {
- // Not allowed but not a reference sheet, return normally
- if holder == member_id {
- mut_instance.write_msgpack(true).await?;
- return Ok((sheet_name.clone(), false));
- }
- }
- }
- // Tell local the check is not passed
- mut_instance.write_msgpack(false).await?;
- return Err(TcpTargetError::NotFound("Sheet not found".to_string()));
- }
- Err(TcpTargetError::NoResult("NoResult".to_string()))
-}
-
-/// The macro to write and return a result.
-#[macro_export]
-macro_rules! write_and_return {
- ($instance:expr, $result:expr) => {{
- $instance.lock().await.write($result).await?;
- return Ok($result);
- }};
-}
-
-/// The macro to send formatted string to output channel.
-/// Usage: local_println!(output, "format string", arg1, arg2, ...)
-#[macro_export]
-macro_rules! local_println {
- ($output:expr, $($arg:tt)*) => {{
- let formatted = format!($($arg)*);
- let _ = $output.send(formatted).await;
- }};
-}