@@ -39,6 +39,17 @@ pub struct AccountsApi<T> {
39
39
40
40
const MAX_RETRIES : usize = 10 ;
41
41
42
+ // Convenience function to clean up error handling and reduce unwrap quantity
43
+ trait ErrorStatus {
44
+ fn error ( code : u16 ) -> Self ;
45
+ }
46
+
47
+ impl ErrorStatus for Response < ( ) > {
48
+ fn error ( code : u16 ) -> Self {
49
+ Response :: builder ( ) . status ( code) . body ( ( ) ) . unwrap ( )
50
+ }
51
+ }
52
+
42
53
impl_web ! {
43
54
impl <T , A > AccountsApi <T >
44
55
where T : NodeStore <Account = A > + HttpStore <Account = A > + BalanceStore <Account = A >,
@@ -61,7 +72,7 @@ impl_web! {
61
72
ok( self . store. clone( ) )
62
73
} else {
63
74
error!( "Admin API endpoint called with non-admin API key" ) ;
64
- err( Response :: builder ( ) . status ( 401 ) . body ( ( ) ) . unwrap ( ) )
75
+ err( Response :: error ( 401 ) )
65
76
}
66
77
}
67
78
@@ -73,14 +84,14 @@ impl_web! {
73
84
let se_url = body. settlement_engine_url. clone( ) ;
74
85
self . validate_admin( authorization)
75
86
. and_then( move |store| store. insert_account( body)
76
- . map_err( |_| Response :: builder ( ) . status ( 500 ) . body ( ( ) ) . unwrap ( ) )
87
+ . map_err( |_| Response :: error ( 500 ) )
77
88
. and_then( |account| {
78
89
// if the account had a SE associated with it, then register
79
90
// the account in the SE.
80
91
if let Some ( se_url) = se_url {
81
92
let id = account. id( ) ;
82
93
Either :: A ( result( Url :: parse( & se_url) )
83
- . map_err( |_| Response :: builder ( ) . status ( 500 ) . body ( ( ) ) . unwrap ( ) )
94
+ . map_err( |_| Response :: error ( 500 ) )
84
95
. and_then( move |mut se_url| {
85
96
se_url
86
97
. path_segments_mut( )
@@ -109,7 +120,7 @@ impl_web! {
109
120
} )
110
121
} ;
111
122
Retry :: spawn( FixedInterval :: from_millis( 2000 ) . take( MAX_RETRIES ) , action)
112
- . map_err( |_| Response :: builder ( ) . status ( 500 ) . body ( ( ) ) . unwrap ( ) )
123
+ . map_err( |_| Response :: error ( 500 ) )
113
124
. and_then( move |_| {
114
125
Ok ( json!( account) )
115
126
} )
@@ -126,12 +137,12 @@ impl_web! {
126
137
let store = self . store. clone( ) ;
127
138
if self . is_admin( & authorization) {
128
139
Either :: A ( store. get_all_accounts( )
129
- . map_err( |_| Response :: builder ( ) . status ( 500 ) . body ( ( ) ) . unwrap ( ) )
140
+ . map_err( |_| Response :: error ( 500 ) )
130
141
. and_then( |accounts| Ok ( json!( accounts) ) ) )
131
142
} else {
132
143
// Only allow the user to see their own account
133
144
Either :: B ( store. get_account_from_http_token( authorization. as_str( ) )
134
- . map_err( |_| Response :: builder ( ) . status ( 404 ) . body ( ( ) ) . unwrap ( ) )
145
+ . map_err( |_| Response :: error ( 404 ) )
135
146
. and_then( |account| Ok ( json!( vec![ account] ) ) ) )
136
147
}
137
148
}
@@ -143,32 +154,51 @@ impl_web! {
143
154
let is_admin = self . is_admin( & authorization) ;
144
155
let parsed_id: Result <A :: AccountId , ( ) > = A :: AccountId :: from_str( & id) . map_err( |_| error!( "Invalid id" ) ) ;
145
156
result( parsed_id)
146
- . map_err( |_| Response :: builder ( ) . status ( 400 ) . body ( ( ) ) . unwrap ( ) )
157
+ . map_err( |_| Response :: error ( 400 ) )
147
158
. and_then( move |id| {
148
159
if is_admin {
149
160
Either :: A ( store. get_accounts( vec![ id] )
150
161
. map_err( move |_| {
151
162
debug!( "Account not found: {}" , id) ;
152
- Response :: builder ( ) . status ( 404 ) . body ( ( ) ) . unwrap ( )
163
+ Response :: error ( 404 )
153
164
} )
154
165
. and_then( |mut accounts| Ok ( json!( accounts. pop( ) . unwrap( ) ) ) ) )
155
166
} else {
156
167
Either :: B ( store. get_account_from_http_token( & authorization[ BEARER_TOKEN_START ..] )
157
168
. map_err( move |_| {
158
169
debug!( "No account found with auth: {}" , authorization) ;
159
- Response :: builder ( ) . status ( 401 ) . body ( ( ) ) . unwrap ( )
170
+ Response :: error ( 401 )
160
171
} )
161
172
. and_then( move |account| {
162
173
if account. id( ) == id {
163
174
Ok ( json!( account) )
164
175
} else {
165
- Err ( Response :: builder ( ) . status ( 401 ) . body ( ( ) ) . unwrap ( ) )
176
+ Err ( Response :: error ( 401 ) )
166
177
}
167
178
} ) )
168
179
}
169
180
} )
170
181
}
171
182
183
+ #[ delete( "/accounts/:id" ) ]
184
+ #[ content_type( "application/json" ) ]
185
+ fn delete_account( & self , id: String , authorization: String ) -> impl Future <Item = Value , Error = Response <( ) >> {
186
+ let parsed_id: Result <A :: AccountId , ( ) > = A :: AccountId :: from_str( & id) . map_err( |_| error!( "Invalid id" ) ) ;
187
+ self . validate_admin( authorization)
188
+ . and_then( move |store| match parsed_id {
189
+ Ok ( id) => Ok ( ( store, id) ) ,
190
+ Err ( _) => Err ( Response :: error( 400 ) ) ,
191
+ } )
192
+ . and_then( move |( store, id) |
193
+ store. remove_account( id)
194
+ . map_err( |_| Response :: error( 500 ) )
195
+ . and_then( move |account| {
196
+ // TODO: deregister from SE if url is present
197
+ Ok ( json!( account) )
198
+ } )
199
+ )
200
+ }
201
+
172
202
// TODO should this be combined into the account record?
173
203
#[ get( "/accounts/:id/balance" ) ]
174
204
#[ content_type( "application/json" ) ]
@@ -178,32 +208,32 @@ impl_web! {
178
208
let is_admin = self . is_admin( & authorization) ;
179
209
let parsed_id: Result <A :: AccountId , ( ) > = A :: AccountId :: from_str( & id) . map_err( |_| error!( "Invalid id" ) ) ;
180
210
result( parsed_id)
181
- . map_err( |_| Response :: builder ( ) . status ( 400 ) . body ( ( ) ) . unwrap ( ) )
211
+ . map_err( |_| Response :: error ( 400 ) )
182
212
. and_then( move |id| {
183
213
if is_admin {
184
214
Either :: A ( store. get_accounts( vec![ id] )
185
215
. map_err( move |_| {
186
216
debug!( "Account not found: {}" , id) ;
187
- Response :: builder ( ) . status ( 404 ) . body ( ( ) ) . unwrap ( )
217
+ Response :: error ( 404 )
188
218
} )
189
219
. and_then( |mut accounts| Ok ( accounts. pop( ) . unwrap( ) ) ) )
190
220
} else {
191
221
Either :: B ( store. get_account_from_http_token( & authorization[ BEARER_TOKEN_START ..] )
192
222
. map_err( move |_| {
193
223
debug!( "No account found with auth: {}" , authorization) ;
194
- Response :: builder ( ) . status ( 401 ) . body ( ( ) ) . unwrap ( )
224
+ Response :: error ( 401 )
195
225
} )
196
226
. and_then( move |account| {
197
227
if account. id( ) == id {
198
228
Ok ( account)
199
229
} else {
200
- Err ( Response :: builder ( ) . status ( 401 ) . body ( ( ) ) . unwrap ( ) )
230
+ Err ( Response :: error ( 401 ) )
201
231
}
202
232
} ) )
203
233
}
204
234
} )
205
235
. and_then( move |account| store_clone. get_balance( account)
206
- . map_err( |_| Response :: builder ( ) . status ( 500 ) . body ( ( ) ) . unwrap ( ) ) )
236
+ . map_err( |_| Response :: error ( 500 ) ) )
207
237
. and_then( |balance| Ok ( BalanceResponse {
208
238
balance: balance. to_string( ) ,
209
239
} ) )
0 commit comments