files_sdk/sharing/requests.rs
1//! Request (File Request) operations
2//!
3//! Requests are files that should be uploaded by a specific user or group.
4//! They can be manually created/managed or automatically managed by automations.
5
6use crate::{FilesClient, PaginationInfo, Result};
7use serde::{Deserialize, Serialize};
8use serde_json::json;
9
10/// A Request entity (File Request)
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct RequestEntity {
13 /// Request ID
14 #[serde(skip_serializing_if = "Option::is_none")]
15 pub id: Option<i64>,
16
17 /// Folder path
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub path: Option<String>,
20
21 /// Source filename (if applicable)
22 #[serde(skip_serializing_if = "Option::is_none")]
23 pub source: Option<String>,
24
25 /// Destination filename
26 #[serde(skip_serializing_if = "Option::is_none")]
27 pub destination: Option<String>,
28
29 /// ID of automation that created this request
30 #[serde(skip_serializing_if = "Option::is_none")]
31 pub automation_id: Option<i64>,
32
33 /// User making the request (if applicable)
34 #[serde(skip_serializing_if = "Option::is_none")]
35 pub user_display_name: Option<String>,
36}
37
38/// Handler for request operations
39pub struct RequestHandler {
40 client: FilesClient,
41}
42
43impl RequestHandler {
44 /// Create a new request handler
45 pub fn new(client: FilesClient) -> Self {
46 Self { client }
47 }
48
49 /// List requests
50 ///
51 /// # Arguments
52 /// * `cursor` - Pagination cursor
53 /// * `per_page` - Results per page (max 10,000)
54 /// * `path` - Filter by path
55 /// * `mine` - Only show requests for current user
56 ///
57 /// # Returns
58 /// Tuple of (requests, pagination_info)
59 ///
60 /// # Example
61 /// ```no_run
62 /// use files_sdk::{FilesClient, RequestHandler};
63 ///
64 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
65 /// let client = FilesClient::builder().api_key("key").build()?;
66 /// let handler = RequestHandler::new(client);
67 /// let (requests, pagination) = handler.list(None, None, None, None).await?;
68 /// # Ok(())
69 /// # }
70 /// ```
71 pub async fn list(
72 &self,
73 cursor: Option<&str>,
74 per_page: Option<i64>,
75 path: Option<&str>,
76 mine: Option<bool>,
77 ) -> Result<(Vec<RequestEntity>, PaginationInfo)> {
78 let mut params = vec![];
79 if let Some(c) = cursor {
80 params.push(("cursor", c.to_string()));
81 }
82 if let Some(pp) = per_page {
83 params.push(("per_page", pp.to_string()));
84 }
85 if let Some(p) = path {
86 params.push(("path", p.to_string()));
87 }
88 if let Some(m) = mine {
89 params.push(("mine", m.to_string()));
90 }
91
92 let query = if params.is_empty() {
93 String::new()
94 } else {
95 format!(
96 "?{}",
97 params
98 .iter()
99 .map(|(k, v)| format!("{}={}", k, v))
100 .collect::<Vec<_>>()
101 .join("&")
102 )
103 };
104
105 let response = self.client.get_raw(&format!("/requests{}", query)).await?;
106 let requests: Vec<RequestEntity> = serde_json::from_value(response)?;
107
108 let pagination = PaginationInfo {
109 cursor_next: None,
110 cursor_prev: None,
111 };
112
113 Ok((requests, pagination))
114 }
115
116 /// List requests for a specific folder path
117 ///
118 /// # Arguments
119 /// * `path` - Folder path
120 /// * `cursor` - Pagination cursor
121 /// * `per_page` - Results per page
122 ///
123 /// # Returns
124 /// Tuple of (requests, pagination_info)
125 pub async fn list_for_folder(
126 &self,
127 path: &str,
128 cursor: Option<&str>,
129 per_page: Option<i64>,
130 ) -> Result<(Vec<RequestEntity>, PaginationInfo)> {
131 let mut params = vec![];
132 if let Some(c) = cursor {
133 params.push(("cursor", c.to_string()));
134 }
135 if let Some(pp) = per_page {
136 params.push(("per_page", pp.to_string()));
137 }
138
139 let query = if params.is_empty() {
140 String::new()
141 } else {
142 format!(
143 "?{}",
144 params
145 .iter()
146 .map(|(k, v)| format!("{}={}", k, v))
147 .collect::<Vec<_>>()
148 .join("&")
149 )
150 };
151
152 let response = self
153 .client
154 .get_raw(&format!("/requests/folders/{}{}", path, query))
155 .await?;
156 let requests: Vec<RequestEntity> = serde_json::from_value(response)?;
157
158 let pagination = PaginationInfo {
159 cursor_next: None,
160 cursor_prev: None,
161 };
162
163 Ok((requests, pagination))
164 }
165
166 /// Create a new request
167 ///
168 /// # Arguments
169 /// * `path` - Folder path where file should be uploaded (required)
170 /// * `destination` - Destination filename without extension (required)
171 /// * `user_ids` - Comma-separated list of user IDs to request from
172 /// * `group_ids` - Comma-separated list of group IDs to request from
173 ///
174 /// # Returns
175 /// The created request
176 ///
177 /// # Example
178 /// ```no_run
179 /// use files_sdk::{FilesClient, RequestHandler};
180 ///
181 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
182 /// let client = FilesClient::builder().api_key("key").build()?;
183 /// let handler = RequestHandler::new(client);
184 /// let request = handler.create(
185 /// "/uploads",
186 /// "monthly_report",
187 /// Some("123,456"),
188 /// None
189 /// ).await?;
190 /// # Ok(())
191 /// # }
192 /// ```
193 pub async fn create(
194 &self,
195 path: &str,
196 destination: &str,
197 user_ids: Option<&str>,
198 group_ids: Option<&str>,
199 ) -> Result<RequestEntity> {
200 let mut body = json!({
201 "path": path,
202 "destination": destination,
203 });
204
205 if let Some(uids) = user_ids {
206 body["user_ids"] = json!(uids);
207 }
208 if let Some(gids) = group_ids {
209 body["group_ids"] = json!(gids);
210 }
211
212 let response = self.client.post_raw("/requests", body).await?;
213 Ok(serde_json::from_value(response)?)
214 }
215
216 /// Delete a request
217 ///
218 /// # Arguments
219 /// * `id` - Request ID
220 ///
221 /// # Example
222 /// ```no_run
223 /// use files_sdk::{FilesClient, RequestHandler};
224 ///
225 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
226 /// let client = FilesClient::builder().api_key("key").build()?;
227 /// let handler = RequestHandler::new(client);
228 /// handler.delete(123).await?;
229 /// # Ok(())
230 /// # }
231 /// ```
232 pub async fn delete(&self, id: i64) -> Result<()> {
233 self.client.delete_raw(&format!("/requests/{}", id)).await?;
234 Ok(())
235 }
236}
237
238#[cfg(test)]
239mod tests {
240 use super::*;
241
242 #[test]
243 fn test_handler_creation() {
244 let client = FilesClient::builder().api_key("test-key").build().unwrap();
245 let _handler = RequestHandler::new(client);
246 }
247}