opendal_service_onedrive/
backend.rs1use std::sync::Arc;
19
20use http::StatusCode;
21
22use opendal_core::raw::*;
23use opendal_core::*;
24
25use super::core::OneDriveCore;
26use super::core::parse_error;
27use super::core::parse_error_with_retry;
28use super::deleter::OneDriveDeleter;
29use super::lister::OneDriveLister;
30use super::reader::*;
31use super::writer::OneDriveWriter;
32
33use std::fmt::Debug;
34
35use asyncband::mutex::Mutex;
36use log::debug;
37
38use super::ONEDRIVE_SCHEME;
39use super::config::OnedriveConfig;
40use super::core::OneDriveSigner;
41
42#[doc = include_str!("docs.md")]
44#[derive(Default)]
45pub struct OnedriveBuilder {
46 pub(super) config: OnedriveConfig,
47}
48
49impl Debug for OnedriveBuilder {
50 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51 f.debug_struct("OnedriveBuilder")
52 .field("config", &self.config)
53 .finish_non_exhaustive()
54 }
55}
56
57impl OnedriveBuilder {
58 pub fn root(mut self, root: &str) -> Self {
60 self.config.root = if root.is_empty() {
61 None
62 } else {
63 Some(root.to_string())
64 };
65
66 self
67 }
68
69 pub fn access_token(mut self, access_token: &str) -> Self {
79 self.config.access_token = Some(access_token.to_string());
80 self
81 }
82
83 pub fn refresh_token(mut self, refresh_token: &str) -> Self {
91 self.config.refresh_token = Some(refresh_token.to_string());
92 self
93 }
94
95 pub fn client_id(mut self, client_id: &str) -> Self {
99 self.config.client_id = Some(client_id.to_string());
100 self
101 }
102
103 pub fn client_secret(mut self, client_secret: &str) -> Self {
108 self.config.client_secret = Some(client_secret.to_string());
109 self
110 }
111
112 #[deprecated(
114 since = "0.57.0",
115 note = "OneDrive supports version listing without this option."
116 )]
117 pub fn enable_versioning(self, _enabled: bool) -> Self {
118 self
119 }
120}
121
122impl Builder for OnedriveBuilder {
123 type Config = OnedriveConfig;
124
125 fn build(self) -> Result<impl Service> {
126 let root = normalize_root(&self.config.root.unwrap_or_default());
127 debug!("backend use root {root}");
128
129 let info = ServiceInfo::new(ONEDRIVE_SCHEME, &root, "");
130 let capability = Capability {
131 read: true,
132 read_with_suffix: true,
133 read_with_if_none_match: true,
134
135 write: true,
136 write_with_if_match: true,
137 #[cfg(target_pointer_width = "64")]
139 write_total_max_size: Some(250 * 1024 * 1024 * 1024), copy: true,
142 rename: true,
143
144 stat: true,
145 stat_with_if_none_match: true,
146 delete: true,
150 create_dir: true,
151
152 list: true,
153 list_with_limit: true,
154 list_with_start_after: true,
155 list_with_versions: true,
156
157 shared: true,
158
159 ..Default::default()
160 };
161
162 let accessor_info = info;
163 let mut signer = OneDriveSigner::new();
164
165 match (self.config.access_token, self.config.refresh_token) {
170 (Some(access_token), None) => {
171 signer.access_token = access_token;
172 signer.expires_in = Timestamp::MAX;
173 }
174 (None, Some(refresh_token)) => {
175 let client_id = self.config.client_id.ok_or_else(|| {
176 Error::new(
177 ErrorKind::ConfigInvalid,
178 "client_id must be set when refresh_token is set",
179 )
180 .with_context("service", ONEDRIVE_SCHEME)
181 })?;
182
183 signer.refresh_token = refresh_token;
184 signer.client_id = client_id;
185 if let Some(client_secret) = self.config.client_secret {
186 signer.client_secret = client_secret;
187 }
188 }
189 (Some(_), Some(_)) => {
190 return Err(Error::new(
191 ErrorKind::ConfigInvalid,
192 "access_token and refresh_token cannot be set at the same time",
193 )
194 .with_context("service", ONEDRIVE_SCHEME));
195 }
196 (None, None) => {
197 return Err(Error::new(
198 ErrorKind::ConfigInvalid,
199 "access_token or refresh_token must be set",
200 )
201 .with_context("service", ONEDRIVE_SCHEME));
202 }
203 };
204
205 let core = Arc::new(OneDriveCore {
206 info: accessor_info,
207 capability,
208 root,
209 signer: Arc::new(Mutex::new(signer)),
210 });
211
212 Ok(OnedriveBackend { core })
213 }
214}
215
216#[derive(Clone, Debug)]
217pub struct OnedriveBackend {
218 pub core: Arc<OneDriveCore>,
219}
220
221impl Service for OnedriveBackend {
222 type Reader = oio::StreamReader<OnedriveReader>;
223 type Writer = oio::OneShotWriter<OneDriveWriter>;
224 type Lister = oio::PageLister<OneDriveLister>;
225 type Deleter = oio::OneShotDeleter<OneDriveDeleter>;
226 type Copier = oio::OneShotCopier;
227
228 fn info(&self) -> ServiceInfo {
229 self.core.info.clone()
230 }
231
232 fn capability(&self) -> Capability {
233 self.core.capability
234 }
235
236 async fn create_dir(
237 &self,
238 ctx: &OperationContext,
239 path: &str,
240 _args: OpCreateDir,
241 ) -> Result<RpCreateDir> {
242 if path == "/" {
243 return Ok(RpCreateDir::default());
245 }
246
247 let response = self.core.onedrive_create_dir(ctx, path).await?;
248 match response.status() {
249 StatusCode::CREATED | StatusCode::OK => Ok(RpCreateDir::default()),
250 StatusCode::BAD_REQUEST => Err(parse_error_with_retry(response)),
251 _ => Err(parse_error(response)),
252 }
253 }
254
255 async fn stat(&self, ctx: &OperationContext, path: &str, args: OpStat) -> Result<RpStat> {
256 let meta = self.core.onedrive_stat(ctx, path, args).await?;
257
258 Ok(RpStat::new(meta))
259 }
260 fn read(&self, ctx: &OperationContext, path: &str, args: OpRead) -> Result<Self::Reader> {
261 let output: oio::StreamReader<OnedriveReader> = {
262 Ok(oio::StreamReader::new(OnedriveReader::new(
263 self.clone(),
264 ctx.clone(),
265 path,
266 args,
267 )))
268 }?;
269
270 Ok(output)
271 }
272
273 fn write(&self, ctx: &OperationContext, path: &str, args: OpWrite) -> Result<Self::Writer> {
274 let output: oio::OneShotWriter<OneDriveWriter> = {
275 Ok(oio::OneShotWriter::new(OneDriveWriter::new(
276 self.core.clone(),
277 ctx.clone(),
278 args,
279 path.to_string(),
280 )))
281 }?;
282
283 Ok(output)
284 }
285
286 fn delete(&self, ctx: &OperationContext) -> Result<Self::Deleter> {
287 let output: oio::OneShotDeleter<OneDriveDeleter> = {
288 Ok(oio::OneShotDeleter::new(OneDriveDeleter::new(
289 self.core.clone(),
290 ctx.clone(),
291 )))
292 }?;
293
294 Ok(output)
295 }
296
297 fn copy(
298 &self,
299 ctx: &OperationContext,
300 from: &str,
301 to: &str,
302 _args: OpCopy,
303 _opts: OpCopier,
304 ) -> Result<Self::Copier> {
305 let core = self.core.clone();
306 let ctx = ctx.clone();
307 let from = from.to_string();
308 let to = to.to_string();
309
310 Ok(oio::OneShotCopier::new(async move {
311 let monitor_url = core.initialize_copy(&ctx, &from, &to).await?;
312 core.wait_until_complete(&ctx, monitor_url).await?;
313 Ok(Metadata::default())
314 }))
315 }
316
317 async fn rename(
318 &self,
319 ctx: &OperationContext,
320 from: &str,
321 to: &str,
322 _args: OpRename,
323 ) -> Result<RpRename> {
324 if from == to {
325 return Ok(RpRename::default());
326 }
327
328 self.core.onedrive_move(ctx, from, to).await?;
329
330 Ok(RpRename::default())
331 }
332
333 fn list(&self, ctx: &OperationContext, path: &str, args: OpList) -> Result<Self::Lister> {
334 let output: oio::PageLister<OneDriveLister> = {
335 let l = OneDriveLister::new(path.to_string(), self.core.clone(), ctx.clone(), &args);
336 Ok(oio::PageLister::new(l))
337 }?;
338
339 Ok(output)
340 }
341
342 async fn presign(
343 &self,
344 _ctx: &OperationContext,
345 _path: &str,
346 _args: OpPresign,
347 ) -> Result<RpPresign> {
348 Err(Error::new(
349 ErrorKind::Unsupported,
350 "operation is not supported",
351 ))
352 }
353}