Expand description
§dco3 - DRACOON API wrapper in Rust
dco3
is an async wrapper around API calls in DRACOON.
DRACOON is a cloud service provider - more information can be found on https://dracoon.com.
The name is based on several other projects pointing to oxide (Rust) and DRACOON.
§Usage
All API calls are implemented by the Dracoon
struct. It can be created by using the builder()
method.
In order to access specific API calls, the Dracoon
struct needs to be in the Connected
state.
This can be achieved by calling the connect
method.
To use specific endpoints, you need to import relevant traits.
Currently, the following traits are implemented:
- User - for user account management
- UserAccountKeyPairs - for user keypair management
- Nodes - for node operations (folders, rooms, upload and download are excluded)
- Download - for downloading files
- Upload - for uploading files
- Folders - for folder operations
- Rooms - for room operations
- DownloadShares - for download share operations
- UploadShares - for upload share operations
- Groups - for group operations
- Users - for user management operations
- CustomerProvisioning - for customer provisioning operations
- MissingFileKeys - for distributing missing keys using the user keypair
- RescueKeyPair - for distributing missing keys using the rescue key
- Config - for general configuration information
- AuthenticationMethods - for authentication methods information
- Eventlog - for eventlog information
- Public - for public information
- PublicDownload - for public download via share
- PublicUpload - for public upload via file request
- Roles - for role operations
§Example
use dco3::{Dracoon, OAuth2Flow, User};
#[tokio::main]
async fn main() {
let dracoon = Dracoon::builder()
.with_base_url("https://dracoon.team")
.with_client_id("client_id")
.with_client_secret("client_secret")
.build()
.unwrap()
.connect(OAuth2Flow::password_flow("username", "password"))
.await
.unwrap();
let user_info = dracoon.user().get_user_account().await.unwrap();
println!("User info: {:?}", user_info);
}
§Authentication
All supported OAuth2 flows are implemented.
§Password Flow
use dco3::{Dracoon, OAuth2Flow};
#[tokio::main]
async fn main() {
// you can instantiate the required flow by using the `OAuth2Flow` enum
let password_flow = OAuth2Flow::password_flow("username", "password");
let dracoon = Dracoon::builder()
.with_base_url("https://dracoon.team")
.with_client_id("client_id")
.with_client_secret("client_secret")
.build()
.unwrap()
.connect(password_flow)
.await
.unwrap();
}
§Authorization Code Flow
use dco3::{Dracoon, OAuth2Flow};
#[tokio::main]
async fn main() {
let mut dracoon = Dracoon::builder()
.with_base_url("https://dracoon.team")
.with_client_id("client_id")
.with_client_secret("client_secret")
.with_redirect_uri("https://redirect.uri")
.build()
.unwrap();
// initiate the authorization code flow
let authorize_url = dracoon.get_authorize_url();
// get auth code
let auth_code = "some_auth_code";
// you can instantiate the required flow by using the `OAuth2Flow` enum
let auth_code_flow = OAuth2Flow::authorization_code(auth_code);
let dracoon = dracoon.connect(auth_code_flow).await.unwrap();
}
§Refresh Token
use dco3::{Dracoon, OAuth2Flow};
#[tokio::main]
async fn main() {
let refresh_token = "some_refresh_token";
let dracoon = Dracoon::builder()
.with_base_url("https://dracoon.team")
.with_client_id("client_id")
.with_client_secret("client_secret")
.build()
.unwrap()
.connect(OAuth2Flow::refresh_token(refresh_token))
.await
.unwrap();
}
§Simple
use dco3::{Dracoon, OAuth2Flow};
#[tokio::main]
async fn main() {
// you can also pass the access token directly
let dracoon = Dracoon::builder()
.with_base_url("https://dracoon.team")
.with_client_id("client_id")
.with_client_secret("client_secret")
.build()
.unwrap()
.connect(OAuth2Flow::simple("access_token"))
.await
.unwrap();
// be aware that the access token refresh will *not* work
// once the token is expired, you need to pass a new token
}
§Error handling
All errors are wrapped in the DracoonClientError enum.
Most errrors are related to general usage (like missing parameters).
All API errors are wrapped in the DracoonClientError::Http
variant.
The variant contains response with relevant status code and message.
You can check if the underlying error message if a specific API error by using the is_*
methods.
use dco3::{Dracoon, OAuth2Flow, Nodes};
#[tokio::main]
async fn main() {
let dracoon = Dracoon::builder()
.with_base_url("https://dracoon.team")
.with_client_id("client_id")
.with_client_secret("client_secret")
.build()
.unwrap()
.connect(OAuth2Flow::PasswordFlow("username".into(), "password".into()))
.await
.unwrap();
let node = dracoon.nodes().get_node(123).await;
match node {
Ok(node) => println!("Node info: {:?}", node),
Err(err) => {
if err.is_not_found() {
println!("Node not found");
} else {
println!("Error: {:?}", err);
}
}
}
}
If you need more information about the error, you can use the get_http_error
method.
use dco3::{Dracoon, OAuth2Flow, Nodes};
#[tokio::main]
async fn main() {
let dracoon = Dracoon::builder()
.with_base_url("https://dracoon.team")
.with_client_id("client_id")
.with_client_secret("client_secret")
.build()
.unwrap()
.connect(OAuth2Flow::PasswordFlow("username".into(), "password".into()))
.await
.unwrap();
let node = dracoon.nodes().get_node(123).await;
match node {
Ok(node) => println!("Node info: {:?}", node),
Err(err) => {
if let Some(http_err) = err.get_http_error() {
// check error type
if http_err.is_not_found() {
// do something
println!("Node not found");
// check error message
println!("Error message: {}", http_err.error_message());
// access error details
println!("Error details: {}", http_err.debug_info().unwrap());
}
}
}
}
}
§Retries
The client will automatically retry failed requests. You can configure the retry behavior by passing your config during client creation.
Default values are: 5 retries, min delay 600ms, max delay 20s. Keep in mind that you cannot set arbitrary values - for all values, minimum and maximum values are defined.
use dco3::{Dracoon, OAuth2Flow};
#[tokio::main]
async fn main() {
let dracoon = Dracoon::builder()
.with_base_url("https://dracoon.team")
.with_client_id("client_id")
.with_client_secret("client_secret")
.with_max_retries(3)
.with_min_retry_delay(400)
.with_max_retry_delay(1000)
.build();
}
§Building requests
All API calls are implemented as traits. Each API call that requires a sepcific payload has a corresponding builder. To access the builder, you can call the builder() method.
let room = CreateRoomRequest::builder("My Room")
.with_parent_id(123)
.with_admin_ids(vec![1, 2, 3])
.build();
let room = dracoon.nodes().create_room(room).await.unwrap();
Some requests do not have any complicated fields - in these cases, use the new()
method.
// this takes a mandatory name and optional expiration
let group = CreateGroupRequest::new("My Group", None);
let group = dracoon.groups().create_group(group).await.unwrap();
§Pagination
GET endpoints are limited to 500 returned items - therefore you must paginate the content to fetch remaining items.
// This fetches the first 500 nodes without any param
let mut nodes = dracoon.nodes().get_nodes(None, None, None).await.unwrap();
// Iterate over the remaining nodes
for offset in (0..nodes.range.total).step_by(500) {
let params = ListAllParams::builder()
.with_offset(offset)
.build();
let next_nodes = dracoon.nodes().get_nodes(None, None, Some(params)).await.unwrap();
nodes.items.extend(next_nodes.items);
};
§Cryptography support
All API calls (specifically up- and downloads) support encryption and decryption. In order to use encryption, you can pass the encryption password while building the client.
use dco3::{Dracoon, OAuth2Flow};
#[tokio::main]
async fn main() {
let dracoon = Dracoon::builder()
.with_base_url("https://dracoon.team")
.with_client_id("client_id")
.with_client_secret("client_secret")
.with_encryption_password("my secret")
.build()
.unwrap()
.connect(OAuth2Flow::password_flow("username", "password"))
.await
.unwrap();
// keypair is now set and can be fetched without passing a secret
let kp = dracoon.get_keypair(None).await.unwrap();
It is also possible to pass the encryption secret after connecting by using the get_keypair
method.
use dco3::{Dracoon, OAuth2Flow};
#[tokio::main]
async fn main() {
let dracoon = Dracoon::builder()
.with_base_url("https://dracoon.team")
.with_client_id("client_id")
.with_client_secret("client_secret")
.build()
.unwrap()
.connect(OAuth2Flow::password_flow("username", "password"))
.await
.unwrap();
// check and provide the keypair by passing the encryption secret
let secret = "my secret".to_string();
let kp = dracoon.get_keypair(Some(secret)).await.unwrap();
§Provisioning
In order to use the provisioning API to manage customers of a tenant, you can instantiate
a client with the Provisioning
state.
All API calls are implemented in the CustomerProvisioning trait.
use dco3::{Dracoon, OAuth2Flow, CustomerProvisioning};
#[tokio::main]
async fn main() {
// the client only requires passing the base url and a provisioning token
// other API calls are *not* supported in this state.
let dracoon = Dracoon::builder()
.with_base_url("https://dracoon.team")
.with_provisioning_token("some_token")
.build_provisioning()
.unwrap();
// the client is now in the provisioning state and can be used to manage customers
let customers = dracoon.provisioning().get_customers(None).await.unwrap();
}
§Examples
For an example client implementation, see the dccmd-rs repository.
Re-exports§
pub use self::client::errors::DracoonClientError;
pub use self::client::OAuth2Flow;
pub use self::config::Config;
pub use self::eventlog::Eventlog;
pub use self::groups::Groups;
pub use self::nodes::Download;
pub use self::nodes::Folders;
pub use self::nodes::MissingFileKeys;
pub use self::nodes::Nodes;
pub use self::nodes::Rooms;
pub use self::nodes::Upload;
pub use self::provisioning::CustomerProvisioning;
pub use self::public::Public;
pub use self::public::PublicDownload;
pub use self::public::PublicUpload;
pub use self::roles::Roles;
pub use self::settings::RescueKeyPair;
pub use self::system::AuthenticationMethods;
pub use self::user::User;
pub use self::user::UserAccountKeyPairs;
pub use self::users::Users;
pub use self::models::*;
Modules§
- auth
- client
- This module is responsible for the authentication with DRACOON and implements the DracoonClient struct which is used to interact with the DRACOON API.
- config
- constants
- This module contains all constants, specifically to address API endpoints and default configuration values.
- errors
- re-export client errors for auth
- eventlog
- groups
- models
- This module implments basic models for the DRACOON API.
- nodes
- This module implements a subset of the nodes DRACOON API. Documentation can be found here: https://download.dracoon.com/api/swagger-ui/index.html?configUrl=/api/spec_v4/swagger-config#/nodes
- provisioning
- public
- roles
- settings
- shares
- This module implements the shares DRACOON API. Documentation can be found here: https://download.dracoon.com/api/swagger-ui/index.html?configUrl=/api/spec_v4/swagger-config#/shares
- system
- user
- This module implements a subset of the DRACOON user API. Documentation can be found here: https://download.dracoon.com/api/swagger-ui/index.html?configUrl=/api/spec_v4/swagger-config#/user
- users
- utils
Structs§
- Dracoon
- DRACOON struct - implements all API calls via traits
- Dracoon
Builder - Builder for the
Dracoon
struct. Requires a base url, client id and client secret. Optionally, a redirect uri can be provided. For convenience, use the Dracoon builder method.