bitwarden_importers/importers/onepassword/access/model.rs
1//! What a download yields: vaults holding items, each item still in its decrypted 1Password shape.
2//!
3//! Mapping these onto Bitwarden ciphers is the importer's job and happens elsewhere.
4
5use super::wire::{VaultItemDetails, VaultItemOverview};
6
7/// Everything recovered from an account, including source data that could not be read.
8pub struct DownloadedAccount {
9 /// Vaults that were opened, possibly with individual skipped items.
10 pub vaults: Vec<Vault>,
11 /// Vaults that could not be opened.
12 pub skipped_vaults: Vec<SkippedVault>,
13}
14
15/// A decrypted vault with its items.
16pub struct Vault {
17 /// The vault's 1Password uuid. The import goes by name.
18 #[allow(dead_code)]
19 pub id: String,
20 /// The vault's display name.
21 pub name: String,
22 /// Every item in the vault except the trashed ones.
23 pub items: Vec<Item>,
24 /// Non-trashed items whose encrypted payloads could not be read.
25 pub skipped_items: Vec<SkippedItem>,
26}
27
28/// A vault that could not be opened.
29#[derive(serde::Serialize, serde::Deserialize)]
30#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
31#[bitwarden_ffi::wasm_record]
32pub struct SkippedVault {
33 /// The vault's 1Password uuid.
34 pub id: String,
35 /// The active item count advertised by 1Password, when present.
36 pub item_count: Option<u32>,
37 /// Why the vault could not be opened.
38 pub reason: SkippedReason,
39}
40
41/// An item that could not be read from an otherwise accessible vault.
42#[derive(serde::Serialize, serde::Deserialize)]
43#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
44#[bitwarden_ffi::wasm_record]
45pub struct SkippedItem {
46 /// The item's 1Password uuid.
47 pub id: String,
48 /// The title, when the overview decrypted before another payload failed.
49 pub name: Option<String>,
50 /// The item's category, available without decrypting its payloads.
51 pub category: ItemCategory,
52 /// Why the item could not be read.
53 pub reason: SkippedReason,
54}
55
56/// A safe, structured reason for leaving source data unimported.
57#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
58#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
59#[bitwarden_ffi::wasm_record]
60pub enum SkippedReason {
61 /// The account does not have the key or permission required to read the data.
62 NoAccess,
63 /// The source data is encrypted with a scheme the importer does not support.
64 Unsupported,
65}
66
67/// A decrypted item: its identity plus both payloads exactly as 1Password sends them.
68pub struct Item {
69 /// The item's 1Password uuid. The server assigns imported ciphers their own.
70 #[allow(dead_code)]
71 pub id: String,
72 /// The item's category, derived from its template id.
73 pub category: ItemCategory,
74 /// The decrypted `encOverview`: title, websites, tags.
75 pub overview: VaultItemOverview,
76 /// The decrypted `encDetails`: login fields, sections, note.
77 pub details: VaultItemDetails,
78}
79
80/// The kind of a vault item, mapped from its template id. The ids are 1Password's standard
81/// category template UUIDs; an unrecognized id is preserved as [`ItemCategory::Unknown`] so nothing
82/// is lost.
83#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
84#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
85#[bitwarden_ffi::wasm_record]
86pub enum ItemCategory {
87 /// Template `001`.
88 Login,
89 /// Template `002`.
90 CreditCard,
91 /// Template `003`.
92 SecureNote,
93 /// Template `004`.
94 Identity,
95 /// Template `005`.
96 Password,
97 /// Template `006`.
98 Document,
99 /// Template `100`.
100 SoftwareLicense,
101 /// Template `101`.
102 BankAccount,
103 /// Template `102`.
104 Database,
105 /// Template `103`.
106 DriverLicense,
107 /// Template `104`.
108 OutdoorLicense,
109 /// Template `105`.
110 Membership,
111 /// Template `106`.
112 Passport,
113 /// Template `107`.
114 RewardProgram,
115 /// Template `108`.
116 SocialSecurityNumber,
117 /// Template `109`.
118 WirelessRouter,
119 /// Template `110`.
120 Server,
121 /// Template `111`.
122 EmailAccount,
123 /// Template `112`.
124 ApiCredential,
125 /// Template `113`.
126 MedicalRecord,
127 /// Template `114`.
128 SshKey,
129 /// A template id this crate does not know, kept verbatim.
130 Unknown(String),
131}
132
133impl ItemCategory {
134 /// Maps a 1Password template id to a category. Extends the `TemplateId` handling in
135 /// `Client.ConvertVaultItem` to the full standard template set.
136 pub(super) fn from_template_id(id: &str) -> ItemCategory {
137 match id {
138 "001" => ItemCategory::Login,
139 "002" => ItemCategory::CreditCard,
140 "003" => ItemCategory::SecureNote,
141 "004" => ItemCategory::Identity,
142 "005" => ItemCategory::Password,
143 "006" => ItemCategory::Document,
144 "100" => ItemCategory::SoftwareLicense,
145 "101" => ItemCategory::BankAccount,
146 "102" => ItemCategory::Database,
147 "103" => ItemCategory::DriverLicense,
148 "104" => ItemCategory::OutdoorLicense,
149 "105" => ItemCategory::Membership,
150 "106" => ItemCategory::Passport,
151 "107" => ItemCategory::RewardProgram,
152 "108" => ItemCategory::SocialSecurityNumber,
153 "109" => ItemCategory::WirelessRouter,
154 "110" => ItemCategory::Server,
155 "111" => ItemCategory::EmailAccount,
156 "112" => ItemCategory::ApiCredential,
157 "113" => ItemCategory::MedicalRecord,
158 "114" => ItemCategory::SshKey,
159 other => ItemCategory::Unknown(other.to_string()),
160 }
161 }
162}