1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
use action_system::{action::ActionContext, macros::action_gen};
use serde::{Deserialize, Serialize};
use tcp_connection::error::TcpTargetError;
use vcs_data::{
constants::VAULT_HOST_NAME,
data::{local::workspace_analyzer::FromRelativePathBuf, sheet::SheetName},
};
use crate::{
remote_actions::{
auth_member, check_connection_instance, get_current_sheet_name, try_get_vault,
},
write_and_return,
};
#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct ShareMappingArguments {
pub mappings: Vec<FromRelativePathBuf>,
pub description: String,
// None = current sheet,
// Some(sheet_name) = other ref(public) sheet
pub from_sheet: Option<SheetName>,
pub to_sheet: SheetName,
}
#[derive(Serialize, Deserialize, Default)]
pub enum ShareMappingActionResult {
Success,
// Fail
AuthorizeFailed(String),
TargetSheetNotFound(SheetName),
TargetIsSelf,
MappingNotFound(FromRelativePathBuf),
#[default]
Unknown,
}
#[action_gen]
pub async fn share_mapping_action(
ctx: ActionContext,
args: ShareMappingArguments,
) -> Result<ShareMappingActionResult, TcpTargetError> {
let instance = check_connection_instance(&ctx)?;
// Auth Member
let (member_id, _is_host_mode) = match auth_member(&ctx, instance).await {
Ok(id) => id,
Err(e) => {
return Ok(ShareMappingActionResult::AuthorizeFailed(e.to_string()));
}
};
// Check sheet
let sheet_name = args.from_sheet.unwrap_or(
get_current_sheet_name(&ctx, instance, &member_id, true)
.await?
.0,
);
if ctx.is_proc_on_remote() {
let vault = try_get_vault(&ctx)?;
let sheet = vault.sheet(&sheet_name).await?;
// Tip: Because sheet_name may specify a sheet that does not belong to the user,
// a secondary verification is required.
// Check if the sheet holder is Some and matches the member_id or is the host
let Some(holder) = sheet.holder() else {
// If there's no holder, the sheet cannot be shared from
write_and_return!(
instance,
ShareMappingActionResult::AuthorizeFailed("Sheet has no holder".to_string())
);
};
// Verify the holder is either the current member or the host
if holder != &member_id && holder != VAULT_HOST_NAME {
write_and_return!(
instance,
ShareMappingActionResult::AuthorizeFailed(
"Not sheet holder or ref sheet".to_string()
)
);
}
let to_sheet_name = args.to_sheet;
// Verify target sheet exists
if !vault.sheet_names()?.contains(&to_sheet_name) {
// Does not exist
write_and_return!(
instance,
ShareMappingActionResult::TargetSheetNotFound(to_sheet_name.clone())
);
}
// Verify sheet is not self
if sheet_name == to_sheet_name {
// Is self
write_and_return!(instance, ShareMappingActionResult::TargetIsSelf);
}
// Verify all mappings are correct
for mapping in args.mappings.iter() {
if !sheet.mapping().contains_key(mapping) {
// If any mapping is invalid, indicate failure
write_and_return!(
instance,
ShareMappingActionResult::MappingNotFound(mapping.clone())
);
}
}
// Execute sharing logic
sheet
.share_mappings(&to_sheet_name, args.mappings, &member_id, args.description)
.await?;
// Sharing successful
write_and_return!(instance, ShareMappingActionResult::Success);
}
if ctx.is_proc_on_local() {
let result = instance
.lock()
.await
.read::<ShareMappingActionResult>()
.await?;
return Ok(result);
}
Ok(ShareMappingActionResult::Success)
}
|