#![warn(rust_2018_idioms, missing_debug_implementations)]
use derive_setters::Setters;
use serde::{Deserialize, Serialize};
use serde_repr::Serialize_repr as SerializeRepr;
use std::{result::Result as StdResult, time::SystemTime};
use url::Url;
use uuid::Uuid;
pub use client::{AnonymousClient, Client, ClientBuilder};
pub use error::{Error, RequestResponseError};
pub use rwarden_crypto as crypto;
#[macro_use]
mod util;
mod client;
mod error;
pub mod account;
pub mod cache;
pub mod cipher;
pub mod collection;
pub mod folder;
pub mod response;
pub mod settings;
pub mod sync;
pub type Result<TOk, TCacheError> = StdResult<TOk, Error<TCacheError>>;
pub trait Request<'request, 'client, TCache> {
type Output;
fn send(&'request self, client: &'client mut Client<TCache>) -> Self::Output;
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub struct Urls {
pub base: Url,
pub auth: Url,
}
impl Urls {
pub fn official() -> Self {
Self {
base: Url::parse("https://api.bitwarden.com").unwrap(),
auth: Url::parse("https://identity.bitwarden.com/connect/token").unwrap(),
}
}
pub fn custom<S: AsRef<str>>(url: S) -> StdResult<Self, url::ParseError> {
let url = Url::parse(url.as_ref())?;
Ok(Self {
base: url.join("api")?,
auth: url.join("identity/connect/token")?,
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct AccessTokenData {
pub access_token: String,
pub expiry_time: SystemTime,
}
impl AccessTokenData {
fn token_has_expired(&self) -> bool {
self.expiry_time < SystemTime::now()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, SerializeRepr)]
#[repr(u8)]
pub enum DeviceType {
Android = 0,
Ios = 1,
ChromeExtension = 2,
FirefoxExtension = 3,
OperaExtension = 4,
EdgeExtension = 5,
WindowsDesktop = 6,
MacOsDesktop = 7,
LinuxDesktop = 8,
ChromeBrowser = 9,
FirefoxBrowser = 10,
OperaBrowser = 11,
EdgeBrowser = 12,
IeBrowser = 13,
UnknownBrowser = 14,
AndroidAmazon = 15,
Uwp = 16,
SafariBrowser = 17,
VivaldiBrowser = 18,
VivaldiExtension = 19,
SafariExtension = 20,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, SerializeRepr)]
#[repr(u8)]
pub enum TwoFactorProvider {
Authenticator = 0,
Email = 1,
Duo = 2,
YubiKey = 3,
U2f = 4,
Remember = 5,
OrganizationDuo = 6,
WebAuthn = 7,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Setters)]
#[setters(strip_option, prefix = "with_")]
pub struct LoginData {
#[setters(skip)]
pub email: String,
#[setters(skip)]
pub password: String,
#[setters(skip)]
pub client_id: String,
#[setters(into)]
pub device_name: Option<String>,
pub device_type: Option<DeviceType>,
#[setters(into)]
pub device_push_token: Option<String>,
pub two_factor_provider: Option<TwoFactorProvider>,
#[setters(into)]
pub two_factor_token: Option<String>,
pub two_factor_remember: bool,
}
impl LoginData {
pub fn new<E, P, C>(email: E, password: P, client_id: C) -> Self
where
E: Into<String>,
P: Into<String>,
C: Into<String>,
{
Self {
client_id: client_id.into(),
email: email.into(),
password: password.into(),
device_name: None,
device_type: None,
device_push_token: None,
two_factor_provider: None,
two_factor_token: None,
two_factor_remember: false,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Setters)]
#[setters(strip_option, prefix = "with_")]
pub struct RegisterData {
#[setters(skip)]
pub email: String,
#[setters(skip)]
pub password: String,
#[setters(into)]
pub password_hint: Option<String>,
#[setters(into)]
pub name: Option<String>,
pub organization_user_id: Option<Uuid>,
pub kdf_type: Option<crypto::KdfType>,
pub kdf_iterations: Option<u32>,
}
impl RegisterData {
pub fn new<E, P>(email: E, password: P) -> Self
where
E: Into<String>,
P: Into<String>,
{
Self {
email: email.into(),
password: password.into(),
password_hint: None,
name: None,
organization_user_id: None,
kdf_type: None,
kdf_iterations: None,
}
}
}