Skip to content

Commit db28493

Browse files
authored
Merge branch 'master' into gakonst-precision-loss
2 parents 00a30dd + 6c732fd commit db28493

File tree

11 files changed

+592
-164
lines changed

11 files changed

+592
-164
lines changed

crates/interledger-api/src/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ pub trait NodeStore: Clone + Send + Sync + 'static {
2828
account: AccountDetails,
2929
) -> Box<dyn Future<Item = Self::Account, Error = ()> + Send>;
3030

31+
fn remove_account(
32+
&self,
33+
id: <Self::Account as AccountTrait>::AccountId,
34+
) -> Box<dyn Future<Item = Self::Account, Error = ()> + Send>;
35+
3136
// TODO limit the number of results and page through them
3237
fn get_all_accounts(&self) -> Box<dyn Future<Item = Vec<Self::Account>, Error = ()> + Send>;
3338

crates/interledger-api/src/routes/accounts.rs

+45-15
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ pub struct AccountsApi<T> {
3939

4040
const MAX_RETRIES: usize = 10;
4141

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+
4253
impl_web! {
4354
impl<T, A> AccountsApi<T>
4455
where T: NodeStore<Account = A> + HttpStore<Account = A> + BalanceStore<Account = A>,
@@ -61,7 +72,7 @@ impl_web! {
6172
ok(self.store.clone())
6273
} else {
6374
error!("Admin API endpoint called with non-admin API key");
64-
err(Response::builder().status(401).body(()).unwrap())
75+
err(Response::error(401))
6576
}
6677
}
6778

@@ -73,14 +84,14 @@ impl_web! {
7384
let se_url = body.settlement_engine_url.clone();
7485
self.validate_admin(authorization)
7586
.and_then(move |store| store.insert_account(body)
76-
.map_err(|_| Response::builder().status(500).body(()).unwrap())
87+
.map_err(|_| Response::error(500))
7788
.and_then(|account| {
7889
// if the account had a SE associated with it, then register
7990
// the account in the SE.
8091
if let Some(se_url) = se_url {
8192
let id = account.id();
8293
Either::A(result(Url::parse(&se_url))
83-
.map_err(|_| Response::builder().status(500).body(()).unwrap())
94+
.map_err(|_| Response::error(500))
8495
.and_then(move |mut se_url| {
8596
se_url
8697
.path_segments_mut()
@@ -109,7 +120,7 @@ impl_web! {
109120
})
110121
};
111122
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))
113124
.and_then(move |_| {
114125
Ok(json!(account))
115126
})
@@ -126,12 +137,12 @@ impl_web! {
126137
let store = self.store.clone();
127138
if self.is_admin(&authorization) {
128139
Either::A(store.get_all_accounts()
129-
.map_err(|_| Response::builder().status(500).body(()).unwrap())
140+
.map_err(|_| Response::error(500))
130141
.and_then(|accounts| Ok(json!(accounts))))
131142
} else {
132143
// Only allow the user to see their own account
133144
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))
135146
.and_then(|account| Ok(json!(vec![account]))))
136147
}
137148
}
@@ -143,32 +154,51 @@ impl_web! {
143154
let is_admin = self.is_admin(&authorization);
144155
let parsed_id: Result<A::AccountId, ()> = A::AccountId::from_str(&id).map_err(|_| error!("Invalid id"));
145156
result(parsed_id)
146-
.map_err(|_| Response::builder().status(400).body(()).unwrap())
157+
.map_err(|_| Response::error(400))
147158
.and_then(move |id| {
148159
if is_admin {
149160
Either::A(store.get_accounts(vec![id])
150161
.map_err(move |_| {
151162
debug!("Account not found: {}", id);
152-
Response::builder().status(404).body(()).unwrap()
163+
Response::error(404)
153164
})
154165
.and_then(|mut accounts| Ok(json!(accounts.pop().unwrap()))))
155166
} else {
156167
Either::B(store.get_account_from_http_token(&authorization[BEARER_TOKEN_START..])
157168
.map_err(move |_| {
158169
debug!("No account found with auth: {}", authorization);
159-
Response::builder().status(401).body(()).unwrap()
170+
Response::error(401)
160171
})
161172
.and_then(move |account| {
162173
if account.id() == id {
163174
Ok(json!(account))
164175
} else {
165-
Err(Response::builder().status(401).body(()).unwrap())
176+
Err(Response::error(401))
166177
}
167178
}))
168179
}
169180
})
170181
}
171182

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+
172202
// TODO should this be combined into the account record?
173203
#[get("/accounts/:id/balance")]
174204
#[content_type("application/json")]
@@ -178,32 +208,32 @@ impl_web! {
178208
let is_admin = self.is_admin(&authorization);
179209
let parsed_id: Result<A::AccountId, ()> = A::AccountId::from_str(&id).map_err(|_| error!("Invalid id"));
180210
result(parsed_id)
181-
.map_err(|_| Response::builder().status(400).body(()).unwrap())
211+
.map_err(|_| Response::error(400))
182212
.and_then(move |id| {
183213
if is_admin {
184214
Either::A(store.get_accounts(vec![id])
185215
.map_err(move |_| {
186216
debug!("Account not found: {}", id);
187-
Response::builder().status(404).body(()).unwrap()
217+
Response::error(404)
188218
})
189219
.and_then(|mut accounts| Ok(accounts.pop().unwrap())))
190220
} else {
191221
Either::B(store.get_account_from_http_token(&authorization[BEARER_TOKEN_START..])
192222
.map_err(move |_| {
193223
debug!("No account found with auth: {}", authorization);
194-
Response::builder().status(401).body(()).unwrap()
224+
Response::error(401)
195225
})
196226
.and_then(move |account| {
197227
if account.id() == id {
198228
Ok(account)
199229
} else {
200-
Err(Response::builder().status(401).body(()).unwrap())
230+
Err(Response::error(401))
201231
}
202232
}))
203233
}
204234
})
205235
.and_then(move |account| store_clone.get_balance(account)
206-
.map_err(|_| Response::builder().status(500).body(()).unwrap()))
236+
.map_err(|_| Response::error(500)))
207237
.and_then(|balance| Ok(BalanceResponse {
208238
balance: balance.to_string(),
209239
}))

0 commit comments

Comments
 (0)