@@ -2,26 +2,159 @@ use std::cell::RefCell;
22use std:: collections:: HashMap ;
33use std:: rc:: Rc ;
44
5+ use async_trait:: async_trait;
6+
7+ #[ derive( Clone ) ]
8+ pub struct KeyringItem {
9+ attributes : HashMap < String , String > ,
10+ // we could zero-out this region of memory
11+ secret : Vec < u8 >
12+ }
13+
14+ impl KeyringItem {
15+ async fn attributes ( & self ) -> HashMap < String , String > {
16+ self . attributes . clone ( )
17+ }
18+ async fn secret ( & self ) -> & [ u8 ] {
19+ & self . secret [ ..]
20+ }
21+ }
22+
23+ #[ async_trait]
24+ trait LightKeyring {
25+ async fn search_items (
26+ & self ,
27+ attributes : HashMap < & str , & str > ,
28+ ) -> anyhow:: Result < Vec < KeyringItem > > ;
29+ async fn create_item (
30+ & self ,
31+ label : & str ,
32+ attributes : HashMap < & str , & str > ,
33+ secret : & str ,
34+ replace : bool ,
35+ ) -> anyhow:: Result < ( ) > ;
36+ async fn delete ( & self , attributes : HashMap < & str , & str > ) -> anyhow:: Result < ( ) > ;
37+ }
38+
39+ struct RealKeyring {
40+ keyring : oo7:: Keyring ,
41+ }
42+
43+ #[ async_trait]
44+ impl LightKeyring for RealKeyring {
45+ async fn search_items (
46+ & self ,
47+ attributes : HashMap < & str , & str > ,
48+ ) -> anyhow:: Result < Vec < KeyringItem > > {
49+ let items = self . keyring . search_items ( attributes) . await ?;
50+
51+ let mut out_items = vec ! [ ] ;
52+ for item in items {
53+ out_items. push ( KeyringItem {
54+ attributes : item. attributes ( ) . await ?,
55+ secret : item. secret ( ) . await ?. to_vec ( ) ,
56+ } ) ;
57+ }
58+ Ok ( out_items)
59+ }
60+
61+ async fn create_item (
62+ & self ,
63+ label : & str ,
64+ attributes : HashMap < & str , & str > ,
65+ secret : & str ,
66+ replace : bool ,
67+ ) -> anyhow:: Result < ( ) > {
68+ self . keyring
69+ . create_item ( label, attributes, secret, replace)
70+ . await ?;
71+ Ok ( ( ) )
72+ }
73+
74+ async fn delete ( & self , attributes : HashMap < & str , & str > ) -> anyhow:: Result < ( ) > {
75+ self . keyring . delete ( attributes) . await ?;
76+ Ok ( ( ) )
77+ }
78+ }
79+
80+ struct NullableKeyring {
81+ search_response : Vec < KeyringItem > ,
82+ }
83+
84+ impl NullableKeyring {
85+ pub fn new ( search_response : Vec < KeyringItem > ) -> Self {
86+ Self { search_response }
87+ }
88+ }
89+
90+ #[ async_trait]
91+ impl LightKeyring for NullableKeyring {
92+ async fn search_items (
93+ & self ,
94+ _attributes : HashMap < & str , & str > ,
95+ ) -> anyhow:: Result < Vec < KeyringItem > > {
96+ Ok ( self . search_response . clone ( ) )
97+ }
98+
99+ async fn create_item (
100+ & self ,
101+ _label : & str ,
102+ _attributes : HashMap < & str , & str > ,
103+ _secret : & str ,
104+ _replace : bool ,
105+ ) -> anyhow:: Result < ( ) > {
106+ Ok ( ( ) )
107+ }
108+
109+ async fn delete ( & self , _attributes : HashMap < & str , & str > ) -> anyhow:: Result < ( ) > {
110+ Ok ( ( ) )
111+ }
112+ }
113+ impl NullableKeyring {
114+ pub fn with_credentials ( credentials : Vec < Credential > ) -> Self {
115+ let mut search_response = vec ! [ ] ;
116+
117+ for cred in credentials {
118+ let attributes = HashMap :: from ( [
119+ ( "type" . to_string ( ) , "password" . to_string ( ) ) ,
120+ ( "username" . to_string ( ) , cred. username . clone ( ) ) ,
121+ ( "server" . to_string ( ) , cred. password . clone ( ) ) ,
122+ ] ) ;
123+ search_response. push ( KeyringItem { attributes, secret : cred. password . into_bytes ( ) } ) ;
124+ }
125+
126+ Self { search_response }
127+ }
128+ }
129+
5130#[ derive( Debug , Clone ) ]
6131pub struct Credential {
7132 pub username : String ,
8133 pub password : String ,
9134}
10135
11- #[ derive( Debug , Clone ) ]
136+ #[ derive( Clone ) ]
12137pub struct Credentials {
13- keyring : Rc < oo7 :: Keyring > ,
138+ keyring : Rc < dyn LightKeyring > ,
14139 creds : Rc < RefCell < HashMap < String , Credential > > > ,
15140}
16141
17142impl Credentials {
18143 pub async fn new ( ) -> anyhow:: Result < Self > {
19144 let mut this = Self {
20- keyring : Rc :: new (
21- oo7:: Keyring :: new ( )
145+ keyring : Rc :: new ( RealKeyring {
146+ keyring : oo7:: Keyring :: new ( )
22147 . await
23148 . expect ( "Failed to start Secret Service" ) ,
24- ) ,
149+ } ) ,
150+ creds : Default :: default ( ) ,
151+ } ;
152+ this. load ( ) . await ?;
153+ Ok ( this)
154+ }
155+ pub async fn new_nullable ( credentials : Vec < Credential > ) -> anyhow:: Result < Self > {
156+ let mut this = Self {
157+ keyring : Rc :: new ( NullableKeyring :: with_credentials ( credentials) ) ,
25158 creds : Default :: default ( ) ,
26159 } ;
27160 this. load ( ) . await ?;
@@ -39,13 +172,12 @@ impl Credentials {
39172 for item in values {
40173 let attrs = item
41174 . attributes ( )
42- . await
43- . map_err ( |e| capnp:: Error :: failed ( e. to_string ( ) ) ) ?;
175+ . await ;
44176 self . creds . borrow_mut ( ) . insert (
45177 attrs[ "server" ] . to_string ( ) ,
46178 Credential {
47179 username : attrs[ "username" ] . to_string ( ) ,
48- password : std:: str:: from_utf8 ( & item. secret ( ) . await ? ) ?. to_string ( ) ,
180+ password : std:: str:: from_utf8 ( & item. secret ( ) . await ) ?. to_string ( ) ,
49181 } ,
50182 ) ;
51183 }
0 commit comments