Skip to main content

bitwarden_importers/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use bitwarden_collections::collection::{CollectionId, CollectionType};
4use bitwarden_core::OrganizationId;
5use bitwarden_vault::{CipherType as VaultCipherType, FolderId};
6
7#[cfg(feature = "uniffi")]
8uniffi::setup_scaffolding!();
9#[cfg(feature = "uniffi")]
10mod uniffi_support;
11
12mod error;
13pub use error::ImportError;
14mod import;
15mod importer_client;
16pub use importer_client::{ImporterClient, ImporterClientExt};
17mod importers;
18pub(crate) use importers::keeper;
19pub use importers::onepassword::access::{
20    Credentials, SignInAddress, SignInDomain, TotpResult as OnePasswordTotpResult,
21    TwoFactorUi as OnePasswordTwoFactorUi,
22};
23mod pipeline;
24
25/// The 1Password access module: log in to an account and download its vaults.
26///
27/// Exposed only under the `test-utils` feature, for the out-of-tree CLI that drives it against
28/// a real account. Not part of this crate's supported API, and no stability is promised.
29// TODO: Remove once the out-of-tree CLI is retired.
30#[cfg(feature = "test-utils")]
31pub use importers::onepassword::access as onepassword_access;
32/// The 1Password conversion step: downloaded vaults to the [`ParsedImport`] the pipeline
33/// submits.
34///
35/// Exposed only under the `test-utils` feature, so the CLI can print what a real account
36/// converts to. Not part of this crate's supported API, and no stability is promised.
37// TODO: Remove once the out-of-tree CLI is retired.
38#[cfg(feature = "test-utils")]
39pub use importers::onepassword::convert as onepassword_convert;
40#[cfg(feature = "test-utils")]
41pub use pipeline::ParsedImport;
42
43/// Destination options for a vault import.
44///
45/// `organization_id` selects the destination: `None` imports into the user's personal vault (groups
46/// become personal folders), `Some` imports into that organization (ciphers are encrypted with the
47/// org key). `target_folder` (personal) and `target_collection` (organization) nest the import
48/// under an existing destination, mirroring the client's import-target behavior; each carries both
49/// its id and name together so a half-specified target can't be expressed. `restricted_types` are
50/// dropped before submission.
51#[allow(missing_docs)]
52#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
53#[cfg_attr(
54    feature = "wasm",
55    derive(serde::Serialize, serde::Deserialize, tsify::Tsify),
56    tsify(from_wasm_abi)
57)]
58pub struct ImportOptions {
59    pub organization_id: Option<OrganizationId>,
60    pub target_folder: Option<ImportTargetFolder>,
61    pub target_collection: Option<ImportTargetCollection>,
62    // `VaultCipherType` is the wasm-bindgen enum exported as `CipherType`; pin the TS name so
63    // tsify doesn't emit the Rust alias.
64    #[cfg_attr(feature = "wasm", tsify(type = "CipherType[]"))]
65    pub restricted_types: Vec<VaultCipherType>,
66}
67
68/// An existing personal folder to nest a personal import under.
69#[allow(missing_docs)]
70#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
71#[cfg_attr(
72    feature = "wasm",
73    derive(serde::Serialize, serde::Deserialize, tsify::Tsify),
74    tsify(from_wasm_abi)
75)]
76pub struct ImportTargetFolder {
77    pub id: FolderId,
78    pub name: String,
79}
80
81/// An existing organization collection to assign an org import to. `type` distinguishes the
82/// "My items" default collection (import.rs converts groups to personal folders instead of
83/// nested collections) from a normal shared collection.
84#[allow(missing_docs)]
85#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
86#[cfg_attr(
87    feature = "wasm",
88    derive(serde::Serialize, serde::Deserialize, tsify::Tsify),
89    tsify(from_wasm_abi)
90)]
91pub struct ImportTargetCollection {
92    pub id: CollectionId,
93    pub name: String,
94    pub r#type: CollectionType,
95}
96
97/// Counts of what an import submitted to the server, broken down by cipher type so the client can
98/// render its per-type result table.
99#[allow(missing_docs)]
100#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
101#[cfg_attr(
102    feature = "wasm",
103    derive(serde::Serialize, serde::Deserialize, tsify::Tsify),
104    tsify(into_wasm_abi)
105)]
106pub struct ImportSummary {
107    pub ciphers: Vec<CipherTypeCount>,
108    pub folders: u32,
109    pub collections: u32,
110}
111
112/// Number of imported ciphers of a given type.
113#[allow(missing_docs)]
114#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
115#[cfg_attr(
116    feature = "wasm",
117    derive(serde::Serialize, serde::Deserialize, tsify::Tsify),
118    tsify(into_wasm_abi)
119)]
120pub struct CipherTypeCount {
121    #[cfg_attr(feature = "wasm", tsify(type = "CipherType"))]
122    pub r#type: VaultCipherType,
123    pub count: u32,
124}