cloudillo_action/native_hooks/
fshr.rs1use crate::hooks::{HookContext, HookResult};
8use crate::prelude::*;
9use cloudillo_core::app::App;
10use cloudillo_types::meta_adapter::{CreateFile, FileStatus, UpdateActionDataOptions};
11use cloudillo_types::types::Patch;
12
13pub async fn on_receive(app: App, context: HookContext) -> ClResult<HookResult> {
19 let tn_id = TnId(context.tenant_id as u32);
20
21 tracing::debug!(
22 "Native hook: FSHR on_receive for action {} from {} to {:?}",
23 context.action_id,
24 context.issuer,
25 context.audience
26 );
27
28 let is_audience = context.audience.as_ref() == Some(&context.tenant_tag);
30
31 if is_audience && context.subtype.as_deref() != Some("DEL") {
33 tracing::info!(
34 "FSHR: Received file share from {} - setting status to confirmation required",
35 context.issuer
36 );
37
38 let update_opts =
39 UpdateActionDataOptions { status: Patch::Value('C'), ..Default::default() };
40
41 if let Err(e) = app
42 .meta_adapter
43 .update_action_data(tn_id, &context.action_id, &update_opts)
44 .await
45 {
46 tracing::warn!("FSHR: Failed to update action status to 'C': {}", e);
47 }
48 }
49
50 Ok(HookResult::default())
51}
52
53pub async fn on_accept(app: App, context: HookContext) -> ClResult<HookResult> {
59 let tn_id = TnId(context.tenant_id as u32);
60
61 tracing::debug!(
62 "Native hook: FSHR on_accept for action {} from {}",
63 context.action_id,
64 context.issuer
65 );
66
67 let content = match &context.content {
69 Some(c) => c,
70 None => {
71 tracing::warn!("FSHR on_accept: Missing content");
72 return Ok(HookResult::default());
73 }
74 };
75
76 let content_type = match content.get("contentType").and_then(|v| v.as_str()) {
77 Some(ct) => ct,
78 None => {
79 tracing::warn!("FSHR on_accept: Missing contentType in content");
80 return Ok(HookResult::default());
81 }
82 };
83
84 let file_name = match content.get("fileName").and_then(|v| v.as_str()) {
85 Some(fn_) => fn_,
86 None => {
87 tracing::warn!("FSHR on_accept: Missing fileName in content");
88 return Ok(HookResult::default());
89 }
90 };
91
92 let file_tp = match content.get("fileTp").and_then(|v| v.as_str()) {
93 Some(ft) => ft,
94 None => {
95 tracing::warn!("FSHR on_accept: Missing fileTp in content");
96 return Ok(HookResult::default());
97 }
98 };
99
100 let file_id = match &context.subject {
102 Some(s) => s,
103 None => {
104 tracing::warn!("FSHR on_accept: Missing subject (file_id)");
105 return Ok(HookResult::default());
106 }
107 };
108
109 tracing::info!(
110 "FSHR: Accepting file share - creating file entry for {} from {} (type: {})",
111 file_id,
112 context.issuer,
113 file_tp
114 );
115
116 let create_opts = CreateFile {
118 orig_variant_id: None,
119 file_id: Some(file_id.clone().into()),
120 parent_id: None,
121 owner_tag: Some(context.issuer.clone().into()), creator_tag: None,
123 preset: None,
124 content_type: content_type.into(),
125 file_name: file_name.into(),
126 file_tp: Some(file_tp.into()),
127 created_at: None,
128 tags: None,
129 x: None,
130 visibility: None, status: Some(FileStatus::Active),
132 };
133
134 match app.meta_adapter.create_file(tn_id, create_opts).await {
135 Ok(file_result) => {
136 tracing::info!("FSHR: Created shared file entry: {:?}", file_result);
137 }
138 Err(e) => {
139 tracing::error!("FSHR: Failed to create file entry: {}", e);
140 return Err(e);
141 }
142 }
143
144 Ok(HookResult::default())
145}
146
147