1use std::collections::HashMap;
18
19use zeroize::Zeroize;
20
21use crate::{datacrypt, errors};
22
23use super::Entry;
24
25#[derive(Clone, Debug)]
30pub(crate) struct Safe {
31 pub(crate) entries: Vec<Entry>,
32 filtered_entries: Vec<Entry>,
33 map_filtered_to_unfiltered: HashMap<usize, usize>,
35 password_cryptor: datacrypt::EntryPasswordCryptor,
36 filter: String,
37}
38
39impl Drop for Safe {
40 fn drop(&mut self) {
41 self.zeroize();
42 }
43}
44
45impl Zeroize for Safe {
46 fn zeroize(&mut self) {
47 self.entries.zeroize();
48 self.filtered_entries.zeroize();
49 self.password_cryptor.zeroize();
50 self.filter.zeroize();
51 }
52}
53
54impl Default for Safe {
55 fn default() -> Self {
56 Safe {
57 entries: Vec::new(),
58 filtered_entries: Vec::new(),
59 map_filtered_to_unfiltered: HashMap::new(),
60 password_cryptor: datacrypt::EntryPasswordCryptor::new(),
61 filter: "".to_string(),
62 }
63 }
64}
65
66impl Safe {
67 pub(crate) fn new() -> Safe {
68 Safe {
69 entries: Vec::new(),
70 filtered_entries: Vec::new(),
71 map_filtered_to_unfiltered: HashMap::new(),
72 password_cryptor: datacrypt::EntryPasswordCryptor::new(),
73 filter: "".to_string(),
74 }
75 }
76
77 pub(crate) fn add_entry(&mut self, new_entry: Entry) {
79 self.entries.push(new_entry.encrypted(&self.password_cryptor));
80 self.apply_filter();
81 }
82
83 pub(crate) fn replace_entry(&mut self, index: usize, entry: Entry) -> errors::Result<()> {
85 self.entries.push(entry.encrypted(&self.password_cryptor));
87 let res = match self.map_filtered_to_unfiltered.get(&index) {
89 Some(index_in_main_vec) => {
90 self.entries.swap_remove(*index_in_main_vec);
92 Ok(())
93 }
94 None => {
95 Err(errors::RustKeylockError::GeneralError(dbg!("The entry being replaced was not found in the Entries... \
96 This may be an indication of race conditions..\
97 Please consider opening a bug to \
98 the developers.")
99 .to_string()))
100 }
101 };
102 self.apply_filter();
104 res
105 }
106
107 pub(crate) fn remove_entry(&mut self, index: usize) -> errors::Result<()> {
109 let res = match self.map_filtered_to_unfiltered.get(&index) {
110 Some(index_in_main_vec) => {
111 self.entries.remove(*index_in_main_vec);
113 Ok(())
114 }
115 None => {
116 Err(errors::RustKeylockError::GeneralError("The entry being replaced was not found in the Entries... If the entries \
117 changed meanwhile, this is normal. If not, please consider opening a bug to \
118 the developers."
119 .to_string()))
120 }
121 };
122 self.apply_filter();
124 res
125 }
126
127 pub(crate) fn merge(&mut self, incoming: Vec<Entry>) {
129 let mut to_add = {
130 incoming.into_iter()
131 .filter(|entry| {
132 let mut main_iter = self.entries.iter();
133 let opt = main_iter.find(|main_entry| {
134 let enrypted_entry = entry.encrypted(&self.password_cryptor);
135 main_entry.name == enrypted_entry.name && main_entry.url == enrypted_entry.url &&
136 main_entry.user == enrypted_entry.user && main_entry.pass == enrypted_entry.pass && main_entry.desc == enrypted_entry.desc
137 });
138 opt.is_none()
139 })
140 .map(|entry| entry.encrypted(&self.password_cryptor))
141 .collect()
142 };
143
144 self.entries.append(&mut to_add);
145 self.apply_filter();
146 }
147
148 pub(crate) fn add_all(&mut self, incoming: Vec<Entry>) {
150 let mut to_add = {
151 incoming.into_iter()
152 .map(|entry| entry.encrypted(&self.password_cryptor))
153 .collect()
154 };
155
156 self.entries.append(&mut to_add);
157 self.apply_filter();
158 }
159
160 pub(crate) fn get_entry(&self, index: usize) -> &Entry {
162 &self.get_entries()[index]
163 }
164
165 pub(crate) fn get_entry_decrypted(&self, index: usize) -> Entry {
167 self.get_entry(index).decrypted(&self.password_cryptor)
168 }
169
170 pub(crate) fn get_entries(&self) -> &[Entry] {
172 &self.filtered_entries
173 }
174
175 pub(crate) fn get_entries_decrypted(&self) -> Vec<Entry> {
177 self.get_entries()
178 .iter()
179 .map(|entry| entry.decrypted(&self.password_cryptor))
180 .collect()
181 }
182
183 pub(crate) fn set_filter(&mut self, filter: String) {
185 self.filter = filter;
186 self.apply_filter();
187 }
188
189 pub(crate) fn get_filter(&self) -> String {
191 self.filter.clone()
192 }
193
194 fn apply_filter(&mut self) {
195 let m: Vec<Entry> = if !self.filter.is_empty() {
196 let lower_filter = self.filter.to_lowercase();
197 let mut indexes_vec = Vec::new();
198 let mut vec = Vec::new();
199
200 {
201 let iter = self.entries
202 .iter()
203 .enumerate()
204 .filter(|&(_, entry)| {
205 entry.name.to_lowercase().contains(&lower_filter) || entry.url.to_lowercase().contains(&lower_filter) ||
206 entry.user.to_lowercase().contains(&lower_filter) || entry.desc.to_lowercase().contains(&lower_filter)
207 });
208 for tup in iter {
209 vec.push(tup.1.clone());
211 indexes_vec.push(tup.0);
213 }
214 }
215
216 self.map_filtered_to_unfiltered.clear();
218 indexes_vec.iter().enumerate().for_each(|(index_in_filtered_vec, index_in_main_vec)| {
219 self.map_filtered_to_unfiltered.insert(index_in_filtered_vec, *index_in_main_vec);
220 });
221
222 vec
223 } else {
224 self.map_filtered_to_unfiltered.clear();
227 for index in 0..self.entries.len() {
228 self.map_filtered_to_unfiltered.insert(index, index);
229 }
230 self.entries.clone()
231 };
232
233 self.filtered_entries = m;
234 }
235
236 pub(crate) fn clear(&mut self) {
237 self.filtered_entries = Vec::new();
238 self.entries = Vec::new();
239 self.map_filtered_to_unfiltered.clear();
240 self.filter = "".to_string();
241 }
242}
243
244#[cfg(test)]
245mod safe_unit_tests {
246 use crate::api::{Entry, EntryMeta};
247
248 #[test]
249 fn merge_entries() {
250 let mut safe = super::Safe::new();
251 assert!(safe.entries.len() == 0);
252
253 let all = vec![
255 Entry::new("1".to_string(), "1".to_string(), "1".to_string(), "1".to_string(), "1".to_string(), EntryMeta::default()),
256 Entry::new("2".to_string(), "2".to_string(), "2".to_string(), "2".to_string(), "2".to_string(), EntryMeta::default())];
257 safe.add_all(all);
258
259 let first = vec![Entry::new("3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), EntryMeta::default())];
261 safe.merge(first);
262 assert!(safe.entries.len() == 3);
263
264 let second = vec![Entry::new("1".to_string(), "1".to_string(), "1".to_string(), "1".to_string(), "1".to_string(), EntryMeta::default())];
266 safe.merge(second);
267 assert!(safe.entries.len() == 3);
268
269 let third = vec![Entry::new("1".to_string(), "1".to_string(), "1".to_string(), "1".to_string(), "3".to_string(), EntryMeta::default())];
271 safe.merge(third);
272 assert!(safe.entries.len() == 4);
273 }
274
275 #[test]
276 fn add_entry() {
277 let mut safe = super::Safe::new();
278 let entry = Entry::new("3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), EntryMeta::default());
279 safe.add_entry(entry.clone());
280 assert!(safe.entries.len() == 1);
281 assert!(safe.entries[0].name == entry.name);
282 assert!(safe.entries[0].url == entry.url);
283 assert!(safe.entries[0].user == entry.user);
284 assert!(safe.entries[0].pass != entry.pass);
285 assert!(safe.entries[0].desc == entry.desc);
286 }
287
288 #[test]
289 fn replace_entry() {
290 let mut safe = super::Safe::new();
291 let entry = Entry::new("3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), EntryMeta::default());
292 safe.add_entry(entry.clone());
293 let new_entry = Entry::new("33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), EntryMeta::default());
294 let _ = safe.replace_entry(0, new_entry.clone());
295
296 assert!(safe.entries.len() == 1);
297 let replaced_entry = safe.get_entry_decrypted(0);
298 assert!(replaced_entry.name == new_entry.name);
299 assert!(replaced_entry.url == new_entry.url);
300 assert!(replaced_entry.user == new_entry.user);
301 assert!(replaced_entry.pass == new_entry.pass);
302 assert!(replaced_entry.desc == new_entry.desc);
303 }
304
305 #[test]
306 fn replace_entry_after_filter() {
307 let mut safe = super::Safe::new();
308 let entry1 = Entry::new("1".to_string(), "1".to_string(), "1".to_string(), "1".to_string(), "1".to_string(), EntryMeta::default());
309 let entry2 = Entry::new("2".to_string(), "2".to_string(), "2".to_string(), "2".to_string(), "2".to_string(), EntryMeta::default());
310 let entry3 = Entry::new("3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), EntryMeta::default());
311 safe.add_entry(entry1.clone());
312 safe.add_entry(entry2.clone());
313 safe.add_entry(entry3.clone());
314 let new_entry = Entry::new("33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), EntryMeta::default());
315
316 safe.set_filter("3".to_string());
317 let _ = safe.replace_entry(0, new_entry.clone());
318 safe.set_filter("".to_string());
319
320 assert!(safe.entries.len() == 3);
321 let replaced_entry = safe.get_entry_decrypted(2);
322 assert!(replaced_entry.name == new_entry.name);
323 assert!(replaced_entry.url == new_entry.url);
324 assert!(replaced_entry.user == new_entry.user);
325 assert!(replaced_entry.pass == new_entry.pass);
326 assert!(replaced_entry.desc == new_entry.desc);
327 }
328
329 #[test]
330 fn remove_entry() {
331 let mut safe = super::Safe::new();
332 let entry1 = Entry::new("3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), EntryMeta::default());
333 let entry2 = Entry::new("33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), EntryMeta::default());
334 safe.add_entry(entry1.clone());
335 safe.add_entry(entry2.clone());
336
337 let _ = safe.remove_entry(1);
338
339 assert!(safe.entries.len() == 1);
340 assert!(safe.entries[0].name == entry1.name);
341 assert!(safe.entries[0].url == entry1.url);
342 assert!(safe.entries[0].user == entry1.user);
343 assert!(safe.entries[0].pass != entry1.pass);
344 assert!(safe.entries[0].desc == entry1.desc);
345 }
346
347 #[test]
348 fn remove_entry_after_filter() {
349 let mut safe = super::Safe::new();
350 let entry1 = Entry::new("3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), EntryMeta::default());
351 let entry2 = Entry::new("33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), EntryMeta::default());
352 safe.add_entry(entry1.clone());
353 safe.add_entry(entry2.clone());
354
355 safe.set_filter("33".to_string());
356 let _ = safe.remove_entry(0);
357 safe.set_filter("".to_string());
358
359 assert!(safe.entries.len() == 1);
360 let decrypted_entry = safe.get_entry_decrypted(0);
361 assert!(decrypted_entry.name == entry1.name);
362 assert!(decrypted_entry.url == entry1.url);
363 assert!(decrypted_entry.user == entry1.user);
364 assert!(decrypted_entry.pass == entry1.pass);
365 assert!(decrypted_entry.desc == entry1.desc);
366 }
367
368 #[test]
369 fn add_all() {
370 let mut safe = super::Safe::new();
371 let entry1 = Entry::new("3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), EntryMeta::default());
372 let entry2 = Entry::new("33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), EntryMeta::default());
373 let entries = vec![entry1.clone(), entry2.clone()];
374
375 safe.add_all(entries);
376
377 assert!(safe.entries.len() == 2);
378 assert!(safe.entries[0].pass != entry1.pass && safe.entries[0].pass != entry2.pass);
379 assert!(safe.entries[1].pass != entry1.pass && safe.entries[0].pass != entry2.pass);
380 }
381
382 #[test]
383 fn get_entry() {
384 let mut safe = super::Safe::new();
385 let entry1 = Entry::new("3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), EntryMeta::default());
386 let entry2 = Entry::new("33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), EntryMeta::default());
387 let entries = vec![entry1.clone(), entry2.clone()];
388 safe.add_all(entries);
389
390 let got_entry = safe.get_entry(1);
391 assert!(got_entry.name == entry2.name);
392 assert!(got_entry.url == entry2.url);
393 assert!(got_entry.user == entry2.user);
394 assert!(got_entry.pass != entry2.pass);
395 assert!(got_entry.desc == entry2.desc);
396 }
397
398 #[test]
399 fn get_entry_decrypted() {
400 let mut safe = super::Safe::new();
401 let entry1 = Entry::new("3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), EntryMeta::default());
402 let entry2 = Entry::new("33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), EntryMeta::default());
403 let entries = vec![entry1.clone(), entry2.clone()];
404 safe.add_all(entries);
405
406 let got_entry = safe.get_entry_decrypted(1);
407 assert!(got_entry.name == entry2.name);
408 assert!(got_entry.url == entry2.url);
409 assert!(got_entry.user == entry2.user);
410 assert!(got_entry.pass == entry2.pass);
411 assert!(got_entry.desc == entry2.desc);
412 }
413
414 #[test]
415 fn get_entries() {
416 let mut safe = super::Safe::new();
417 let entry1 = Entry::new("3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), EntryMeta::default());
418 let entry2 = Entry::new("33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), EntryMeta::default());
419 let entries = vec![entry1.clone(), entry2.clone()];
420 safe.add_all(entries);
421
422 let got_entries = safe.get_entries();
423 assert!(got_entries.len() == 2);
424 }
425
426 #[test]
427 fn get_entries_decrypted() {
428 let mut safe = super::Safe::new();
429 let entry1 = Entry::new("3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), EntryMeta::default());
430 let entry2 = Entry::new("33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), "33".to_string(), EntryMeta::default());
431 let entries = vec![entry1.clone(), entry2.clone()];
432 safe.add_all(entries);
433
434 let got_entries = safe.get_entries_decrypted();
435 assert!(got_entries.len() == 2);
436 assert!(got_entries[0].pass == entry1.pass);
437 assert!(got_entries[1].pass == entry2.pass);
438 }
439
440 #[test]
441 fn set_filter() {
442 let mut safe = super::Safe::new();
443 let entry1 = Entry::new("1".to_string(), "2".to_string(), "3".to_string(), "5".to_string(), "4".to_string(), EntryMeta::default());
444 let entry2 = Entry::new("11".to_string(), "12".to_string(), "13".to_string(), "15".to_string(), "14".to_string(), EntryMeta::default());
445 let entries = vec![entry1, entry2];
446 safe.add_all(entries);
447
448 safe.set_filter("1".to_string());
450 assert!(safe.get_entries().len() == 2);
451 safe.set_filter("11".to_string());
452 assert!(safe.get_entries().len() == 1);
453
454 safe.set_filter("2".to_string());
455 assert!(safe.get_entries().len() == 2);
456 safe.set_filter("12".to_string());
457 assert!(safe.get_entries().len() == 1);
458
459 safe.set_filter("3".to_string());
460 assert!(safe.get_entries().len() == 2);
461 safe.set_filter("13".to_string());
462 assert!(safe.get_entries().len() == 1);
463
464 safe.set_filter("4".to_string());
465 assert!(safe.get_entries().len() == 2);
466 safe.set_filter("14".to_string());
467 assert!(safe.get_entries().len() == 1);
468
469 safe.set_filter("5".to_string());
471 assert!(safe.get_entries().len() == 0);
472
473 let entry3 = Entry::new("NAME".to_string(), "Url".to_string(), "User".to_string(), "pass".to_string(), "Desc".to_string(), EntryMeta::default());
475 safe.add_entry(entry3);
476 safe.set_filter("name".to_string());
477 assert!(safe.get_entries().len() == 1);
478 }
479
480 #[test]
481 fn get_filter() {
482 let mut safe = super::Safe::new();
483 safe.set_filter("33".to_string());
484 assert!(safe.get_filter() == "33".to_string());
485 }
486
487 #[test]
488 fn clear() {
489 let mut safe = super::Safe::new();
490 let entry = Entry::new("3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), "3".to_string(), EntryMeta::default());
491 safe.add_entry(entry.clone());
492 safe.set_filter("a_filter".to_string());
493
494 safe.clear();
495
496 assert!(safe.entries.len() == 0);
497 assert!(safe.filtered_entries.len() == 0);
498 assert!(safe.filter.len() == 0);
499 }
500}