@@ -9,7 +9,9 @@ use crate::{
99use cipherstash_client:: encryption:: Plaintext ;
1010use std:: collections:: HashMap ;
1111
12- /// Wrapper to indicate that a value is NOT encrypted
12+ /// Wrapper to which values are added prior to being encrypted.
13+ /// Values added as "protected" (e.g. via [Unsealed::add_protected]) will be encrypted.
14+ /// Values added as "unprotected" (e.g. via [Unsealed::add_unprotected]) will not be encrypted.
1315pub struct Unsealed {
1416 /// Protected plaintexts with their descriptors
1517 protected : NormalizedProtectedAttributes ,
@@ -38,18 +40,20 @@ impl Unsealed {
3840 }
3941 }
4042
41- // TODO: Change this to take_unprotected
43+ # [ deprecated ( since = "0.7.3" , note = "Use `Unsealed:: take_unprotected` instead" ) ]
4244 pub fn get_plaintext ( & self , name : impl Into < AttributeName > ) -> TableAttribute {
4345 self . unprotected
4446 . get ( name)
4547 . cloned ( )
4648 . unwrap_or ( TableAttribute :: Null )
4749 }
4850
51+ /// Add a new protected attribute, `name`, with the given plaintext.
4952 pub fn add_protected ( & mut self , name : impl Into < String > , plaintext : impl Into < Plaintext > ) {
5053 self . protected . insert ( name, plaintext. into ( ) ) ;
5154 }
5255
56+ /// Add a new protected map, `name`, with the given map of plaintexts.
5357 pub fn add_protected_map ( & mut self , name : impl Into < String > , map : HashMap < String , Plaintext > ) {
5458 self . protected . insert_map ( name, map) ;
5559 }
@@ -68,6 +72,7 @@ impl Unsealed {
6872 . insert_and_update_map ( name, subkey, value. into ( ) ) ;
6973 }
7074
75+ /// Add a new unprotected attribute, `name`, with the given plaintext.
7176 pub fn add_unprotected (
7277 & mut self ,
7378 name : impl Into < AttributeName > ,
@@ -76,6 +81,16 @@ impl Unsealed {
7681 self . unprotected . insert ( name, attribute) ;
7782 }
7883
84+ /// Removes and returns the unprotected attribute, `name`.
85+ /// See also [TableAttribute].
86+ ///
87+ /// If the attribute does not exist, `TableAttribute::Null` is returned.
88+ pub fn take_unprotected ( & mut self , name : impl Into < AttributeName > ) -> TableAttribute {
89+ self . unprotected
90+ . remove ( name)
91+ . unwrap_or ( TableAttribute :: Null )
92+ }
93+
7994 /// Removes and returns the protected attribute, `name`.
8095 pub fn take_protected ( & mut self , name : & str ) -> Option < Plaintext > {
8196 self . protected . take ( name)
@@ -103,63 +118,105 @@ impl Unsealed {
103118 unsealed
104119 }
105120
121+ /// Convert `self` into `T` using the attributes stored in `self`.
122+ /// The [Decryptable] trait must be implemented for `T` and this method calls [Decryptable::from_unsealed].
106123 pub fn into_value < T : Decryptable > ( self ) -> Result < T , SealError > {
107124 T :: from_unsealed ( self )
108125 }
109126}
110127
111128#[ cfg( test) ]
112129mod tests {
113- /*use std::collections::BTreeMap;
114-
115130 use super :: * ;
131+ use std:: collections:: BTreeMap ;
116132
117133 #[ test]
118- fn test_nested_protected () {
134+ fn test_protected_field ( ) {
119135 let mut unsealed = Unsealed :: new_with_descriptor ( "test" ) ;
120- unsealed.add_protected("test.a", Plaintext::from("a"));
121- unsealed.add_protected("test.b", Plaintext::from("b"));
122- unsealed.add_protected("test.c", Plaintext::from("c"));
123- unsealed.add_protected("test.d", Plaintext::from("d"));
124-
125- let nested = unsealed
126- .nested_protected("test")
127- .collect::<BTreeMap<_, _>>();
136+ unsealed. add_protected ( "test" , "value" ) ;
128137
129- assert_eq!(nested.len(), 4);
130- assert_eq!(nested["a"], Plaintext::from("a"));
131- assert_eq!(nested["b"], Plaintext::from("b"));
132- assert_eq!(nested["c"], Plaintext::from("c"));
133- assert_eq!(nested["d"], Plaintext::from("d"));
138+ let plaintext = unsealed. take_protected ( "test" ) . unwrap ( ) ;
139+ assert_eq ! ( plaintext, Plaintext :: from( "value" ) ) ;
134140 }
135141
136142 #[ test]
137- fn test_flatted_protected_value() {
143+ fn test_protected_map ( ) {
144+ let mut unsealed = Unsealed :: new_with_descriptor ( "test" ) ;
138145 let mut map = HashMap :: new ( ) ;
139146 map. insert ( "a" . to_string ( ) , Plaintext :: from ( "value-a" ) ) ;
140147 map. insert ( "b" . to_string ( ) , Plaintext :: from ( "value-b" ) ) ;
141148 map. insert ( "c" . to_string ( ) , Plaintext :: from ( "value-c" ) ) ;
142- map.insert("d".to_string(), Plaintext::from("value-d"));
143-
144- let protected = NormalizedValue::Map(map, "test".to_string());
145- let flattened = protected.flatten();
146-
147- assert_eq!(flattened.len(), 4);
148- assert!(flattened.contains(&NormalizedValue::Scalar(
149- Plaintext::from("value-a"),
150- "test.a".to_string()
151- )));
152- assert!(flattened.contains(&NormalizedValue::Scalar(
153- Plaintext::from("value-b"),
154- "test.b".to_string()
155- )));
156- assert!(flattened.contains(&NormalizedValue::Scalar(
157- Plaintext::from("value-c"),
158- "test.c".to_string()
159- )));
160- assert!(flattened.contains(&NormalizedValue::Scalar(
161- Plaintext::from("value-d"),
162- "test.d".to_string()
163- )));
164- }*/
149+ unsealed. add_protected_map ( "test" , map) ;
150+
151+ let nested: BTreeMap < String , Plaintext > = unsealed
152+ . take_protected_map ( "test" )
153+ . unwrap ( )
154+ . into_iter ( )
155+ . collect ( ) ;
156+
157+ assert_eq ! ( nested. len( ) , 3 ) ;
158+ assert_eq ! ( nested[ "a" ] , Plaintext :: from( "value-a" ) ) ;
159+ assert_eq ! ( nested[ "b" ] , Plaintext :: from( "value-b" ) ) ;
160+ assert_eq ! ( nested[ "c" ] , Plaintext :: from( "value-c" ) ) ;
161+ }
162+
163+ #[ test]
164+ fn test_protected_map_field ( ) {
165+ let mut unsealed = Unsealed :: new_with_descriptor ( "test" ) ;
166+ unsealed. add_protected_map_field ( "test" , "a" , "value-a" ) ;
167+ unsealed. add_protected_map_field ( "test" , "b" , "value-b" ) ;
168+ unsealed. add_protected_map_field ( "test" , "c" , "value-c" ) ;
169+
170+ let nested: BTreeMap < String , Plaintext > = unsealed
171+ . take_protected_map ( "test" )
172+ . unwrap ( )
173+ . into_iter ( )
174+ . collect ( ) ;
175+
176+ assert_eq ! ( nested. len( ) , 3 ) ;
177+ assert_eq ! ( nested[ "a" ] , Plaintext :: from( "value-a" ) ) ;
178+ assert_eq ! ( nested[ "b" ] , Plaintext :: from( "value-b" ) ) ;
179+ assert_eq ! ( nested[ "c" ] , Plaintext :: from( "value-c" ) ) ;
180+ }
181+
182+ #[ test]
183+ fn test_protected_mixed ( ) {
184+ let mut unsealed = Unsealed :: new_with_descriptor ( "test" ) ;
185+ unsealed. add_protected ( "test" , "value" ) ;
186+ unsealed. add_protected_map_field ( "attrs" , "a" , "value-a" ) ;
187+ unsealed. add_protected_map_field ( "attrs" , "b" , "value-b" ) ;
188+ unsealed. add_protected_map_field ( "attrs" , "c" , "value-c" ) ;
189+
190+ let plaintext = unsealed. take_protected ( "test" ) . unwrap ( ) ;
191+ assert_eq ! ( plaintext, Plaintext :: from( "value" ) ) ;
192+
193+ let nested: BTreeMap < String , Plaintext > = unsealed
194+ . take_protected_map ( "attrs" )
195+ . unwrap ( )
196+ . into_iter ( )
197+ . collect ( ) ;
198+
199+ assert_eq ! ( nested. len( ) , 3 ) ;
200+ assert_eq ! ( nested[ "a" ] , Plaintext :: from( "value-a" ) ) ;
201+ assert_eq ! ( nested[ "b" ] , Plaintext :: from( "value-b" ) ) ;
202+ assert_eq ! ( nested[ "c" ] , Plaintext :: from( "value-c" ) ) ;
203+ }
204+
205+ #[ test]
206+ #[ should_panic]
207+ fn test_protected_map_override ( ) {
208+ let mut unsealed = Unsealed :: new_with_descriptor ( "test" ) ;
209+ unsealed. add_protected ( "test" , "value" ) ;
210+ // Panics because "test" is already a protected scalar
211+ unsealed. add_protected_map_field ( "test" , "a" , "value-a" ) ;
212+ }
213+
214+ #[ test]
215+ fn test_unprotected ( ) {
216+ let mut unsealed = Unsealed :: new_with_descriptor ( "test" ) ;
217+ unsealed. add_unprotected ( "test" , "value" ) ;
218+
219+ let attribute = unsealed. take_unprotected ( "test" ) ;
220+ assert ! ( attribute == "value" . into( ) , "values do not match" ) ;
221+ }
165222}
0 commit comments