#![allow(dead_code)]
#![allow(unused_variables)]
use std::{marker::PhantomData, sync::Arc};
use client::{GetClient, Provisioning};
use config::ConfigEndpoint;
use dco3_crypto::PlainUserKeyPairContainer;
use eventlog::EventlogEndpoint;
use groups::GroupsEndpoint;
use nodes::NodesEndpoint;
use provisioning::ProvisioningEndpoint;
use public::{PublicEndpoint, SystemInfo};
use reqwest::Url;
use roles::RolesEndpoint;
use secrecy::{ExposeSecret, SecretBox, SecretString};
use settings::SettingsEndpoint;
use shares::SharesEndpoint;
use system::SystemEndpoint;
use user::UserEndpoint;
use users::UsersEndpoint;
use self::{
client::{Connected, Disconnected},
client::{DracoonClient, DracoonClientBuilder},
user::models::UserAccount,
};
pub use self::{
client::errors::DracoonClientError,
client::OAuth2Flow,
config::Config,
eventlog::Eventlog,
groups::Groups,
models::*,
nodes::{Download, Folders, MissingFileKeys, Nodes, Rooms, Upload},
provisioning::CustomerProvisioning,
public::{Public, PublicDownload, PublicUpload},
roles::Roles,
settings::RescueKeyPair,
shares::{DownloadShares, UploadShares},
system::AuthenticationMethods,
user::{User, UserAccountKeyPairs},
users::Users,
};
pub mod client;
pub mod config;
pub mod constants;
pub mod eventlog;
pub mod groups;
pub mod models;
pub mod nodes;
pub mod provisioning;
pub mod public;
pub mod roles;
pub mod settings;
pub mod shares;
pub mod system;
mod tests;
pub mod user;
pub mod users;
pub mod utils;
#[derive(Clone)]
pub struct Dracoon<State = Disconnected> {
client: Arc<DracoonClient<State>>,
state: PhantomData<State>,
user_info: Container<UserAccount>,
keypair: Container<SecretBox<WrappedUserKeypair>>,
system_info: Container<SystemInfo>,
encryption_secret: Option<SecretString>,
endpoints: Endpoints<State>,
}
impl<S: Send + Sync> GetClient<S> for Dracoon<S> {
fn get_client(&self) -> &DracoonClient<S> {
&self.client
}
}
#[derive(Default)]
pub struct DracoonBuilder {
client_builder: DracoonClientBuilder,
encryption_secret: Option<SecretString>,
}
impl DracoonBuilder {
pub fn new() -> Self {
let client_builder = DracoonClientBuilder::new();
Self {
client_builder,
encryption_secret: None,
}
}
pub fn with_encryption_password(mut self, encryption_secret: impl Into<String>) -> Self {
self.encryption_secret = Some(SecretString::from(encryption_secret.into()));
self
}
pub fn with_base_url(mut self, base_url: impl Into<String>) -> Self {
self.client_builder = self.client_builder.with_base_url(base_url);
self
}
pub fn with_client_id(mut self, client_id: impl Into<String>) -> Self {
self.client_builder = self.client_builder.with_client_id(client_id);
self
}
pub fn with_client_secret(mut self, client_secret: impl Into<String>) -> Self {
self.client_builder = self.client_builder.with_client_secret(client_secret);
self
}
pub fn with_redirect_uri(mut self, redirect_uri: impl Into<String>) -> Self {
self.client_builder = self.client_builder.with_redirect_uri(redirect_uri);
self
}
pub fn with_user_agent(mut self, user_agent: impl Into<String>) -> Self {
self.client_builder = self.client_builder.with_user_agent(user_agent);
self
}
pub fn with_max_retries(mut self, max_retries: u32) -> Self {
self.client_builder = self.client_builder.with_max_retries(max_retries);
self
}
pub fn with_min_retry_delay(mut self, min_retry_delay: u64) -> Self {
self.client_builder = self.client_builder.with_min_retry_delay(min_retry_delay);
self
}
pub fn with_max_retry_delay(mut self, max_retry_delay: u64) -> Self {
self.client_builder = self.client_builder.with_max_retry_delay(max_retry_delay);
self
}
pub fn with_provisioning_token(mut self, provisioning_token: impl Into<String>) -> Self {
self.client_builder = self
.client_builder
.with_provisioning_token(provisioning_token);
self
}
#[doc(hidden)]
pub fn with_token_rotation(mut self, token_rotation: u8) -> Self {
self.client_builder = self.client_builder.with_token_rotation(token_rotation);
self
}
fn build_endpoints<S>(client: &Arc<DracoonClient<S>>) -> Endpoints<S> {
client.into()
}
pub fn build(self) -> Result<Dracoon<Disconnected>, DracoonClientError> {
let dracoon = self.client_builder.build()?;
let dracoon = Arc::new(dracoon);
let endpoints = Self::build_endpoints(&dracoon);
Ok(Dracoon {
client: dracoon,
state: PhantomData,
user_info: Container::new(),
keypair: Container::new(),
system_info: Container::new(),
encryption_secret: self.encryption_secret,
endpoints,
})
}
pub fn build_provisioning(self) -> Result<Dracoon<Provisioning>, DracoonClientError> {
let dracoon = self.client_builder.build_provisioning()?;
let dracoon = Arc::new(dracoon);
let endpoints = Self::build_endpoints(&dracoon);
Ok(Dracoon {
client: dracoon,
state: PhantomData,
user_info: Container::new(),
keypair: Container::new(),
system_info: Container::new(),
encryption_secret: None,
endpoints,
})
}
}
impl Dracoon<Disconnected> {
pub fn builder() -> DracoonBuilder {
DracoonBuilder::new()
}
pub async fn connect(
self,
oauth_flow: OAuth2Flow,
) -> Result<Dracoon<Connected>, DracoonClientError> {
let client = self.client.connect(oauth_flow).await?;
let connected_client = Arc::new(client);
let endpoints = DracoonBuilder::build_endpoints(&connected_client);
let mut dracoon = Dracoon {
client: connected_client,
state: PhantomData,
user_info: Container::new(),
keypair: Container::new(),
system_info: Container::new(),
encryption_secret: self.encryption_secret,
endpoints,
};
if let Some(ref encryption_secret) = dracoon.encryption_secret {
let kp = dracoon
.user()
.get_user_keypair(encryption_secret.expose_secret())
.await?;
dracoon.encryption_secret = None;
dracoon
.keypair
.set(SecretBox::new(Box::new(WrappedUserKeypair::new(kp))))
.await;
}
Ok(dracoon)
}
pub fn get_authorize_url(&self) -> String {
self.client.get_authorize_url()
}
}
impl Dracoon<Connected> {
pub async fn get_auth_header(&self) -> Result<String, DracoonClientError> {
self.client.get_auth_header().await
}
pub fn get_base_url(&self) -> &Url {
self.client.get_base_url()
}
pub async fn get_refresh_token(&self) -> String {
self.client.get_refresh_token().await
}
pub async fn get_user_info(&self) -> Result<UserAccount, DracoonClientError> {
if self.user_info.is_none().await {
let user_info = self.user().get_user_account().await?;
self.user_info.set(user_info).await;
}
let user_info = self.user_info.get().await.expect("No user info set");
Ok(user_info)
}
pub async fn get_system_info(&self) -> Result<SystemInfo, DracoonClientError> {
if self.system_info.is_none().await {
let system_info = self.public().get_system_info().await?;
self.system_info.set(system_info).await;
}
let system_info = self.system_info.get().await.expect("No system info set");
Ok(system_info)
}
pub async fn get_keypair(
&self,
secret: Option<String>,
) -> Result<PlainUserKeyPairContainer, DracoonClientError> {
if self.keypair.is_none().await {
if let Some(secret) = secret {
let keypair = self.user().get_user_keypair(&secret).await?;
self.keypair
.set(SecretBox::new(Box::new(WrappedUserKeypair::new(keypair))))
.await;
} else {
return Err(DracoonClientError::MissingEncryptionSecret);
}
}
let keypair = self.keypair.get().await.expect("No keypair set");
Ok(keypair.expose_secret().keypair().clone())
}
}
impl Dracoon<Provisioning> {
pub fn get_service_token(&self) -> String {
self.client.get_service_token()
}
pub fn provisioning(&self) -> &ProvisioningEndpoint<Provisioning> {
&self.endpoints.provisioning
}
}
impl<S> Dracoon<S> {
pub fn public(&self) -> &PublicEndpoint<S> {
&self.endpoints.public
}
}
impl<S: ConnectedClient> Dracoon<S> {
pub fn build_api_url(&self, url_part: &str) -> Url {
self.client
.get_base_url()
.join(url_part)
.expect("Invalid base url")
}
}
impl Dracoon<Connected> {
pub fn config(&self) -> &ConfigEndpoint<Connected> {
&self.endpoints.config
}
pub fn eventlog(&self) -> &EventlogEndpoint<Connected> {
&self.endpoints.eventlog
}
pub fn groups(&self) -> &GroupsEndpoint<Connected> {
&self.endpoints.groups
}
pub fn nodes(&self) -> &NodesEndpoint<Connected> {
&self.endpoints.nodes
}
pub fn roles(&self) -> &RolesEndpoint<Connected> {
&self.endpoints.roles
}
pub fn settings(&self) -> &SettingsEndpoint<Connected> {
&self.endpoints.settings
}
pub fn shares(&self) -> &SharesEndpoint<Connected> {
&self.endpoints.shares
}
pub fn system(&self) -> &SystemEndpoint<Connected> {
&self.endpoints.system
}
pub fn user(&self) -> &UserEndpoint<Connected> {
&self.endpoints.user
}
pub fn users(&self) -> &UsersEndpoint<Connected> {
&self.endpoints.users
}
}
pub mod auth {
pub use crate::client::{Connected, Disconnected, OAuth2Flow, Provisioning};
pub mod models {
pub use crate::client::models::{DracoonAuthErrorResponse, DracoonErrorResponse};
}
}
pub mod errors {
pub use crate::client::errors::DracoonClientError;
}