1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
//! Common vault traits for plugin-crates
//!
//! The core of this crate has no functionality and is dependant
//! on other libraries to fill those holes. To make this easer
//! (and sometimes possible), we defined a few common behaviours
//! in traits to expand on in implementations specific to the
//! library.
//!
//! Each trait is documented in more detail and provides default
//! implementations with `unimplemented!` macros to make
//! compilation work without external crates but not calling
//! functions at runtime.
use record::{EncryptedBody, Header, Payload, Record};
use serde::{de::DeserializeOwned, Serialize};
use users::User;
use base64;
use serde_json::{self, Error as SerdeError};
/// A Body trait that can be implemented to hook into the generic Record
/// data module.
///
/// This allows working with both encrypted and cleartext data bodies.
pub trait Body: DeserializeOwned + Serialize {
///Get the value of a field from this body
fn get_field(&self, key: &str) -> Option<&Payload>;
/// Set the value of a field
fn set_field(&mut self, key: &str, value: Payload) -> Option<()>;
/// Remove versioning and flatten the data tree to a single level.
fn flatten(&mut self) -> Option<()>;
}
/// A simple trait that allows libraries to hook into the
/// `body()` and `record()` hooks for vault records.
pub trait LoadRecord<T: Body> {
fn header() -> Header {
unimplemented!()
}
fn body() -> T {
unimplemented!()
}
}
pub trait UserLogin {
/// Login a user and return it with a token
fn login(name: &str, password: &str, salt: &str) -> Option<User>;
}
/// A set of utility function that need to be implemented in order
/// for a type to be encryptable or decryptable.
pub trait Encryptable: AutoEncoder {}
/// A base trait that describes the basic functionality of
/// an encryption backend which handles encrypted files.
///
/// Encryption is never done directly on the bodies, only via
/// this scheduler type with the help of the [[Encryptable]] trait.
pub trait EncryptionHandler<T>
where
T: Encryptable + AutoEncoder + Body,
{
fn encrypt(&mut self, item: T) -> EncryptedBody;
fn decrypt(&mut self, item: EncryptedBody) -> Option<T>;
}
/// A trait that abstracts file or record loading for
/// any backend which wants to implement storage functions
pub trait Loading {
fn load(_path: &str) -> Box<Self> {
unimplemented!()
}
fn save(&mut self, _path: &str) {
unimplemented!()
}
}
/// Trait for an in-memory representation of a lockchain vault.
///
/// By itself it represents vault metadata (name, users, location)
/// as well as a list of record headers.
///
/// To provide on-disk functionality it requires the `-storage`
/// trait library and for encrypted file access the `-crypto`
/// crate.
///
/// The body backend is being being generic with the `Body` trait.
pub trait Vault<T>
where
T: Body,
{
/// A shared constructor for all vault implementations
fn new(name: &str, location: &str) -> Self;
/// Fetch metadata headers for all records
fn fetch(&mut self);
/// Pull a specific record from the backend
fn pull(&mut self, name: &str);
/// Sync all changes back to the backend
fn sync(&mut self);
/// Get a complete record from this vault
fn get_record(&self, name: &str) -> Option<&Record<T>>;
/// Probe if a record is contained
fn contains(&self, name: &str) -> bool;
/// Add a new record to this vault
fn add_record(&mut self, key: &str, category: &str, tags: Vec<&str>);
/// Delete a record from this vault
fn delete_record(&mut self, record: &str) -> Option<Record<T>>;
/// Add data to an existing record, overwriting existing fields
fn add_data(&mut self, record: &str, key: &str, data: Payload) -> Option<()>;
/// Get the (latest) value of a specific record data field
fn get_data(&self, record: &str, key: &str) -> Option<&Payload>;
}
/// Auto-implement this trait to serialise types to json
pub trait AutoEncoder: Serialize + DeserializeOwned {
fn encode(&self) -> Result<String, SerdeError> {
serde_json::to_string_pretty(self)
}
fn decode(s: &str) -> Result<Self, SerdeError> {
serde_json::from_str(s)
}
}
/// Include this trait to monkey-patch base64 functions onto String types
pub trait Base64AutoEncoder {
fn to_base64(&self) -> String;
fn from_base64(base64: &str) -> String;
}
impl Base64AutoEncoder for String {
/// Automatically encode this string to base64
fn to_base64(&self) -> String {
base64::encode(self.as_bytes())
}
/// Craft a string from an existing base64 string slice
fn from_base64(base64: &str) -> String {
String::from_utf8(base64::decode(base64).unwrap()).unwrap()
}
}
|