Skip to content

Commit

Permalink
Implement other parts of the sync call
Browse files Browse the repository at this point in the history
  • Loading branch information
Hinton committed Oct 13, 2023
1 parent 78996ea commit 5888919
Show file tree
Hide file tree
Showing 10 changed files with 229 additions and 4 deletions.
3 changes: 3 additions & 0 deletions crates/bitwarden/src/admin_console/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod policy;

pub use policy::Policy;
64 changes: 64 additions & 0 deletions crates/bitwarden/src/admin_console/policy.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use std::collections::HashMap;

use bitwarden_api_api::models::PolicyResponseModel;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use uuid::Uuid;

#[derive(Serialize, Deserialize, Debug, JsonSchema)]
pub struct Policy {
id: Uuid,
organization_id: Uuid,
r#type: PolicyType,
data: Option<HashMap<String, serde_json::Value>>,
enabled: bool,
}

#[derive(Serialize, Deserialize, Debug, JsonSchema)]
pub enum PolicyType {
TwoFactorAuthentication = 0, // Requires users to have 2fa enabled
MasterPassword = 1, // Sets minimum requirements for master password complexity
PasswordGenerator = 2, // Sets minimum requirements/default type for generated passwords/passphrases
SingleOrg = 3, // Allows users to only be apart of one organization
RequireSso = 4, // Requires users to authenticate with SSO
PersonalOwnership = 5, // Disables personal vault ownership for adding/cloning items
DisableSend = 6, // Disables the ability to create and edit Bitwarden Sends
SendOptions = 7, // Sets restrictions or defaults for Bitwarden Sends
ResetPassword = 8, // Allows orgs to use reset password : also can enable auto-enrollment during invite flow
MaximumVaultTimeout = 9, // Sets the maximum allowed vault timeout
DisablePersonalVaultExport = 10, // Disable personal vault export
ActivateAutofill = 11, // Activates autofill with page load on the browser extension
}

impl From<PolicyResponseModel> for Policy {
fn from(policy: PolicyResponseModel) -> Self {
Policy {
id: policy.id.unwrap(),
organization_id: policy.organization_id.unwrap(),
r#type: policy.r#type.unwrap().into(),
data: policy.data,
enabled: policy.enabled.unwrap(),
}
}
}

impl From<bitwarden_api_api::models::PolicyType> for PolicyType {
fn from(policy_type: bitwarden_api_api::models::PolicyType) -> Self {
match policy_type {
bitwarden_api_api::models::PolicyType::Variant0 => PolicyType::TwoFactorAuthentication,
bitwarden_api_api::models::PolicyType::Variant1 => PolicyType::MasterPassword,
bitwarden_api_api::models::PolicyType::Variant2 => PolicyType::PasswordGenerator,
bitwarden_api_api::models::PolicyType::Variant3 => PolicyType::SingleOrg,
bitwarden_api_api::models::PolicyType::Variant4 => PolicyType::RequireSso,
bitwarden_api_api::models::PolicyType::Variant5 => PolicyType::PersonalOwnership,
bitwarden_api_api::models::PolicyType::Variant6 => PolicyType::DisableSend,
bitwarden_api_api::models::PolicyType::Variant7 => PolicyType::SendOptions,
bitwarden_api_api::models::PolicyType::Variant8 => PolicyType::ResetPassword,
bitwarden_api_api::models::PolicyType::Variant9 => PolicyType::MaximumVaultTimeout,
bitwarden_api_api::models::PolicyType::Variant10 => {
PolicyType::DisablePersonalVaultExport
}
bitwarden_api_api::models::PolicyType::Variant11 => PolicyType::ActivateAutofill,
}
}
}
2 changes: 2 additions & 0 deletions crates/bitwarden/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
#[cfg(feature = "mobile")]
uniffi::setup_scaffolding!();

#[cfg(feature = "mobile")]
pub mod admin_console;
pub mod auth;
pub mod client;
pub mod crypto;
Expand Down
19 changes: 19 additions & 0 deletions crates/bitwarden/src/platform/domain.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug, JsonSchema)]
pub struct GlobalDomains {
pub r#type: i32,
pub domains: Vec<String>,
pub excluded: bool,
}

impl From<bitwarden_api_api::models::GlobalDomains> for GlobalDomains {
fn from(global_domains: bitwarden_api_api::models::GlobalDomains) -> Self {
GlobalDomains {
r#type: 0,
domains: global_domains.domains.unwrap(),
excluded: global_domains.excluded.unwrap(),
}
}
}
1 change: 1 addition & 0 deletions crates/bitwarden/src/platform/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod domain;
mod generate_fingerprint;
mod get_user_api_key;
mod secret_verification_request;
Expand Down
58 changes: 55 additions & 3 deletions crates/bitwarden/src/platform/sync.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use bitwarden_api_api::models::{
ProfileOrganizationResponseModel, ProfileResponseModel, SyncResponseModel,
DomainsResponseModel, ProfileOrganizationResponseModel, ProfileResponseModel, SyncResponseModel,
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use uuid::Uuid;

use crate::{
admin_console::Policy,
client::{encryption_settings::EncryptionSettings, Client},
error::{Error, Result},
vault::Cipher,
vault::{Cipher, Collection, Folder},
};

#[derive(Serialize, Deserialize, Debug, JsonSchema)]
Expand Down Expand Up @@ -57,13 +58,25 @@ pub struct ProfileOrganizationResponse {
pub id: Uuid,
}

#[derive(Serialize, Deserialize, Debug, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct DomainResponse {
pub equivalent_domains: Vec<Vec<String>>,
pub global_equivalent_domains: Vec<String>,
}

#[derive(Serialize, Deserialize, Debug, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct SyncResponse {
/// Data about the user, including their encryption keys and the organizations they are a part of
pub profile: ProfileResponse,
/// List of ciphers accesible by the user
pub folders: Vec<Folder>,
pub collections: Vec<Collection>,
/// List of ciphers accessible by the user
pub ciphers: Vec<Cipher>,
pub domains: DomainResponse,
pub policies: Vec<Policy>,
pub sends: Vec<crate::vault::Send>,
}

impl SyncResponse {
Expand All @@ -76,7 +89,32 @@ impl SyncResponse {

Ok(SyncResponse {
profile: ProfileResponse::process_response(profile, enc)?,
folders: response
.folders
.ok_or(Error::MissingFields)?
.into_iter()
.map(|f| f.into())
.collect(),
collections: response
.collections
.ok_or(Error::MissingFields)?
.into_iter()
.map(|c| c.into())
.collect(),
ciphers: ciphers.into_iter().map(|c| c.into()).collect(),
domains: response.domains.unwrap().into(),
policies: response
.policies
.ok_or(Error::MissingFields)?
.into_iter()
.map(|p| p.into())
.collect(),
sends: response
.sends
.ok_or(Error::MissingFields)?
.into_iter()
.map(|s| s.into())
.collect(),
})
}
}
Expand Down Expand Up @@ -111,3 +149,17 @@ impl ProfileResponse {
})
}
}

impl From<DomainsResponseModel> for DomainResponse {
fn from(value: DomainsResponseModel) -> Self {
DomainResponse {
equivalent_domains: value.equivalent_domains.unwrap_or_default(),
global_equivalent_domains: value
.global_equivalent_domains
.unwrap_or_default()
.into_iter()
.map(|s| s.into())
.collect(),
}
}
}
2 changes: 1 addition & 1 deletion crates/bitwarden/src/tool/exporters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub(super) async fn export_vault_attachments(client: &mut Client) -> Result<()>
})
.await?;

debug!("{:?}", sync);
debug!("{:#?}", sync);

info!("Vault synced got {} ciphers", sync.ciphers.len());

Expand Down
16 changes: 16 additions & 0 deletions crates/bitwarden/src/vault/collection.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use std::str::FromStr;

use bitwarden_api_api::models::CollectionDetailsResponseModel;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
Expand Down Expand Up @@ -52,3 +55,16 @@ impl Decryptable<CollectionView> for Collection {
})
}
}

impl From<CollectionDetailsResponseModel> for Collection {
fn from(collection: CollectionDetailsResponseModel) -> Self {
Collection {
id: collection.id.unwrap(),
organization_id: collection.organization_id.unwrap(),
name: EncString::from_str(&collection.name.unwrap()).unwrap(),
external_id: collection.external_id,
hide_passwords: collection.hide_passwords.unwrap_or(false),
read_only: collection.read_only.unwrap_or(false),
}
}
}
13 changes: 13 additions & 0 deletions crates/bitwarden/src/vault/folder.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use std::str::FromStr;

use bitwarden_api_api::models::FolderResponseModel;
use chrono::{DateTime, Utc};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -46,3 +49,13 @@ impl Decryptable<FolderView> for Folder {
})
}
}

impl From<FolderResponseModel> for Folder {
fn from(folder: FolderResponseModel) -> Self {
Folder {
id: folder.id.unwrap(),
name: EncString::from_str(&folder.name.unwrap()).unwrap(),
revision_date: folder.revision_date.unwrap().parse().unwrap(),
}
}
}
55 changes: 55 additions & 0 deletions crates/bitwarden/src/vault/send.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use std::str::FromStr;

use bitwarden_api_api::models::{SendFileModel, SendResponseModel, SendTextModel};
use chrono::{DateTime, Utc};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -277,6 +280,58 @@ impl Encryptable<Send> for SendView {
}
}

impl From<SendResponseModel> for Send {
fn from(send: SendResponseModel) -> Self {
Send {
id: send.id.unwrap(),
access_id: send.access_id.unwrap(),
name: EncString::from_str(&send.name.unwrap()).unwrap(),
notes: send.notes.map(|s| EncString::from_str(&s).unwrap()),
key: EncString::from_str(&send.key.unwrap()).unwrap(),
password: send.password,
r#type: send.r#type.unwrap().into(),
file: send.file.map(|f| Into::<SendFile>::into(*f)),
text: send.text.map(|t| Into::<SendText>::into(*t)),
max_access_count: send.max_access_count.map(|s| s as u32),
access_count: send.access_count.unwrap() as u32,
disabled: send.disabled.unwrap_or(false),
hide_email: send.hide_email.unwrap_or(false),
revision_date: send.revision_date.unwrap().parse().unwrap(),
deletion_date: send.deletion_date.unwrap().parse().unwrap(),
expiration_date: send.expiration_date.map(|s| s.parse().unwrap()),
}
}
}

impl From<bitwarden_api_api::models::SendType> for SendType {
fn from(t: bitwarden_api_api::models::SendType) -> Self {
match t {
bitwarden_api_api::models::SendType::Variant0 => SendType::Text,
bitwarden_api_api::models::SendType::Variant1 => SendType::File,
}
}
}

impl From<SendFileModel> for SendFile {
fn from(file: SendFileModel) -> Self {
SendFile {
id: file.id.unwrap(),
file_name: EncString::from_str(&file.file_name.unwrap()).unwrap(),
size: file.size.unwrap().to_string(),
size_name: file.size_name.unwrap(),
}
}
}

impl From<SendTextModel> for SendText {
fn from(text: SendTextModel) -> Self {
SendText {
text: EncString::from_str(&text.text.unwrap()).unwrap(),
hidden: text.hidden.unwrap_or(false),
}
}
}

#[cfg(test)]
mod tests {
use super::Send;
Expand Down

0 comments on commit 5888919

Please sign in to comment.