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