blob: c7a2786d6da36e1d9fd632ed6bd335838aea1b3a [file] [view]
## Capabilities
This service can be used to:
- [x] create_dir
- [x] stat
- [x] read
- [x] write
- [x] delete
- [x] list
- [x] copy
- [x] rename
- [ ] presign
## Notes
Currently, OpenDAL supports OneDrive Personal only.
### Write Operations and OneDrive Behavior
For write-related operations, such as:
- write
- rename
- copy
- create_dir
OpenDAL's OneDrive service replaces the destination folder instead of rename it.
### Consistency Issues with Concurrent Requests
OneDrive does not guarantee consistency when handling a large number of concurrent requests write operations.
In some extreme cases, OneDrive may acknowledge an operation as successful but fail to commit the changes.
This inconsistency can cause subsequent operations to fail, returning errors like:
- 400 Bad Request: OneDrive considers folders in the path are not there yet
- 404 Not Found: OneDrive doesn't recognize the created folder
- 409 Conflict: OneDrive can't replace an existing folder
You should consider [`RetryLayer`] and monitor your operations carefully.
## Configuration
- `access_token`: Set a short-live access token for Microsoft Graph API (also, OneDrive API)
- `refresh_token`: Set a long term access token for Microsoft Graph API
- `client_id`: Set the client ID for a Microsoft Graph API application (available though Azure's registration portal)
- `client_secret`: Set the client secret for a Microsoft Graph API application
- `root`: Set the work directory for OneDrive backend
- `enable_versioning`: Enable versioning support for OneDrive items
The configuration for tokens is one of the following:
- `access_token` only, for short-lived access. Once the `access_token` expires, you must recreate the operator with a new token.
- `refresh_token`, `client_id`, and an optional `client_secret`, for long-lived access. The operator will automatically get and refresh the access token.
## How to get tokens
1. Create an application: navigate to [Microsoft Entra Admin Center](https://entra.microsoft.com/) -> Applications -> App Registrations -> New registration
2. In "Supported account types", choose "Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox)"
3. Or in an existing application -> manifest, make sure `signInAudience` is `"AzureADandPersonalMicrosoftAccount"`. That's because we're calling Graph API with `/common` path segment.
4. The platform you choose determines whether you have to provide a `client_secret` or not. See [Public and confidential client apps](https://learn.microsoft.com/en-us/entra/identity-platform/msal-client-applications) for more information.
1. In short, if you choose "Mobile and desktop applications" or "Single-page application" (Public Client), you must not provide `client_secret`.
2. If you choose "Web" (Confidential Client), create a secret in "Certificates & secrets -> Client secrets -> New client secret", and provide it as `client_secret`.
5. Follow the [code grant flow](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow) or other flows to get the access_token. The minimum scope is `Files.ReadWrite`. And make sure the access token represents a user, because it's accessing the user's onedrive by `/me/drive`. So "client credentials flow" won't work.
6. If you need `refresh_token` for long-lived access, add an additional `offline_access` scope.
Read more at [`OnedriveBuilder`].
## Example
### Via Builder
When you have a current access token:
```rust,no_run
use opendal_core::Operator;
use opendal_core::Result;
use opendal_service_onedrive::Onedrive;
#[tokio::main]
async fn main() -> Result<()> {
// create backend builder
let mut builder = Onedrive::default()
.access_token("my_access_token")
.root("/root/folder/for/operator");
let op: Operator = Operator::new(builder)?.finish();
Ok(())
}
```
When you have an Application with a refresh token:
```rust,no_run
use opendal_core::Operator;
use opendal_core::Result;
use opendal_service_onedrive::Onedrive;
#[tokio::main]
async fn main() -> Result<()> {
// create backend builder
let mut builder = Onedrive::default()
.refresh_token("my_refresh_token")
.client_id("my_client_id")
.root("/root/folder/for/operator");
let op: Operator = Operator::new(builder)?.finish();
Ok(())
}
```
[conflict-behavior]: https://learn.microsoft.com/en-us/graph/api/resources/driveitem?view=graph-rest-1.0#instance-attributes