Skip to content

Commit 1b1a0fb

Browse files
committed
feat(WidgetDriver): Pass matrix api errors to the widget
1 parent b8a61cf commit 1b1a0fb

File tree

9 files changed

+190
-74
lines changed

9 files changed

+190
-74
lines changed

crates/matrix-sdk/src/widget/machine/driver_req.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ where
7676

7777
pub(crate) fn then(
7878
self,
79-
response_handler: impl FnOnce(Result<T, String>, &mut WidgetMachine) -> Vec<Action>
79+
response_handler: impl FnOnce(Result<T, crate::Error>, &mut WidgetMachine) -> Vec<Action>
8080
+ Send
8181
+ 'static,
8282
) {

crates/matrix-sdk/src/widget/machine/from_widget.rs

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,22 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use std::fmt;
15+
use std::collections::HashMap;
1616

1717
use ruma::{
18-
api::client::delayed_events::{
19-
delayed_message_event, delayed_state_event, update_delayed_event,
18+
api::client::{
19+
delayed_events::{delayed_message_event, delayed_state_event, update_delayed_event},
20+
error::ErrorBody,
2021
},
2122
events::{AnyTimelineEvent, MessageLikeEventType, StateEventType},
2223
serde::Raw,
2324
OwnedEventId, OwnedRoomId,
2425
};
2526
use serde::{Deserialize, Serialize};
27+
use serde_json::{json, Value};
2628

2729
use super::{SendEventRequest, UpdateDelayedEventRequest};
28-
use crate::widget::StateKeySelector;
30+
use crate::{widget::StateKeySelector, Error, HttpError};
2931

3032
#[derive(Deserialize, Debug)]
3133
#[serde(tag = "action", rename_all = "snake_case", content = "data")]
@@ -46,17 +48,63 @@ pub(super) struct FromWidgetErrorResponse {
4648
error: FromWidgetError,
4749
}
4850

49-
impl FromWidgetErrorResponse {
50-
pub(super) fn new(e: impl fmt::Display) -> Self {
51-
Self { error: FromWidgetError { message: e.to_string() } }
51+
impl From<&HttpError> for FromWidgetErrorResponse {
52+
fn from(error: &HttpError) -> Self {
53+
Self {
54+
error: FromWidgetError {
55+
message: error.to_string(),
56+
matrix_api_error: error.as_client_api_error().and_then(
57+
|api_error| match &api_error.body {
58+
ErrorBody::Standard { kind, message } => Some(FromWidgetMatrixErrorBody {
59+
http_status: api_error.status_code.as_u16().into(),
60+
http_headers: HashMap::new(),
61+
url: "".to_owned(),
62+
response: json!({"errcode": kind.to_string(), "error": message }),
63+
}),
64+
_ => None,
65+
},
66+
),
67+
},
68+
}
69+
}
70+
}
71+
72+
impl From<&Error> for FromWidgetErrorResponse {
73+
fn from(error: &Error) -> Self {
74+
match &error {
75+
Error::Http(e) => e.into(),
76+
Error::UnknownError(e) => e.to_string().into(),
77+
_ => error.to_string().into(),
78+
}
79+
}
80+
}
81+
82+
impl From<String> for FromWidgetErrorResponse {
83+
fn from(error: String) -> Self {
84+
Self { error: FromWidgetError { message: error, matrix_api_error: None } }
85+
}
86+
}
87+
88+
impl From<&str> for FromWidgetErrorResponse {
89+
fn from(error: &str) -> Self {
90+
error.to_string().into()
5291
}
5392
}
5493

5594
#[derive(Serialize)]
5695
struct FromWidgetError {
5796
message: String,
97+
matrix_api_error: Option<FromWidgetMatrixErrorBody>,
5898
}
5999

100+
#[derive(Serialize)]
101+
struct FromWidgetMatrixErrorBody {
102+
http_status: u32,
103+
// TODO: figure out the which type to use here.
104+
http_headers: HashMap<String, String>,
105+
url: String,
106+
response: Value,
107+
}
60108
#[derive(Serialize)]
61109
pub(super) struct SupportedApiVersionsResponse {
62110
supported_versions: Vec<ApiVersion>,

crates/matrix-sdk/src/widget/machine/incoming.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub(crate) enum IncomingMessage {
3838
request_id: Uuid,
3939

4040
/// The result of the request: response data or error message.
41-
response: Result<MatrixDriverResponse, String>,
41+
response: Result<MatrixDriverResponse, crate::Error>,
4242
},
4343

4444
/// The `MatrixDriver` notified the `WidgetMachine` of a new matrix event.

crates/matrix-sdk/src/widget/machine/mod.rs

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
1717
#![warn(unreachable_pub)]
1818

19-
use std::{fmt, iter, time::Duration};
19+
use std::{iter, time::Duration};
2020

2121
use driver_req::UpdateDelayedEventRequest;
2222
use from_widget::UpdateDelayedEventResponse;
@@ -50,11 +50,11 @@ use self::{
5050
#[cfg(doc)]
5151
use super::WidgetDriver;
5252
use super::{
53-
capabilities,
53+
capabilities::{self, SEND_DELAYED_EVENT, UPDATE_DELAYED_EVENT},
5454
filter::{MatrixEventContent, MatrixEventFilterInput},
5555
Capabilities, StateKeySelector,
5656
};
57-
use crate::widget::EventFilter;
57+
use crate::{widget::EventFilter, Error};
5858

5959
mod driver_req;
6060
mod from_widget;
@@ -203,7 +203,9 @@ impl WidgetMachine {
203203
) -> Vec<Action> {
204204
let request = match raw_request.deserialize() {
205205
Ok(r) => r,
206-
Err(e) => return vec![self.send_from_widget_error_response(raw_request, e)],
206+
Err(e) => {
207+
return vec![self.send_from_widget_error_response(raw_request, Error::SerdeJson(e))]
208+
}
207209
};
208210

209211
match request {
@@ -252,28 +254,29 @@ impl WidgetMachine {
252254
let CapabilitiesState::Negotiated(capabilities) = &self.capabilities else {
253255
let text =
254256
"Received send update delayed event request before capabilities were negotiated";
255-
return vec![self.send_from_widget_error_response(raw_request, text)];
257+
return vec![self.send_from_widget_error_response(raw_request, text.into())];
256258
};
257259
if !capabilities.update_delayed_event {
258260
return vec![self.send_from_widget_error_response(
259261
raw_request,
260-
format!(
261-
"Not allowed: missing the {} capability.",
262-
capabilities::UPDATE_DELAYED_EVENT
263-
),
262+
format!("Not allowed: missing the {UPDATE_DELAYED_EVENT} capability.")
263+
.into(),
264264
)];
265265
}
266266
let (request, request_action) =
267267
self.send_matrix_driver_request(UpdateDelayedEventRequest {
268268
action: req.action,
269269
delay_id: req.delay_id,
270270
});
271-
request.then(|res, machine| {
271+
request.then(|result, machine| {
272272
vec![machine.send_from_widget_result_response(
273273
raw_request,
274274
// This is mapped to another type because the update_delay_event::Response
275275
// does not impl Serialize
276-
res.map(Into::<UpdateDelayedEventResponse>::into),
276+
match result {
277+
Ok(response) => Ok(Into::<UpdateDelayedEventResponse>::into(response)),
278+
Err(e) => Err((&e).into()),
279+
},
277280
)]
278281
});
279282
request_action.map(|a| vec![a]).unwrap_or_default()
@@ -288,7 +291,7 @@ impl WidgetMachine {
288291
) -> Option<Action> {
289292
let CapabilitiesState::Negotiated(capabilities) = &self.capabilities else {
290293
let text = "Received read event request before capabilities were negotiated";
291-
return Some(self.send_from_widget_error_response(raw_request, text));
294+
return Some(self.send_from_widget_error_response(raw_request, text.into()));
292295
};
293296

294297
match request {
@@ -297,7 +300,7 @@ impl WidgetMachine {
297300
if !capabilities.read.iter().any(filter_fn) {
298301
return Some(self.send_from_widget_error_response(
299302
raw_request,
300-
"Not allowed to read message like event",
303+
"Not allowed to read message like event".into(),
301304
));
302305
}
303306

@@ -306,16 +309,32 @@ impl WidgetMachine {
306309
let request = ReadMessageLikeEventRequest { event_type, limit };
307310
let (request, action) = self.send_matrix_driver_request(request);
308311
request.then(|result, machine| {
309-
let response = result.and_then(|mut events| {
310-
let CapabilitiesState::Negotiated(capabilities) = &machine.capabilities
311-
else {
312-
let err = "Received read event request before capabilities negotiation";
313-
return Err(err.into());
314-
};
312+
let response = match (result, &machine.capabilities) {
313+
(Ok(mut events), CapabilitiesState::Negotiated(capabilities)) => {
314+
events.retain(|e| capabilities.raw_event_matches_read_filter(e));
315+
Ok(ReadEventResponse { events })
316+
}
317+
(Ok(_), _) => {
318+
Err("Received read event request before capabilities negotiation"
319+
.into())
320+
}
321+
(Err(e), _) => Err((&e).into()),
322+
};
315323

316-
events.retain(|e| capabilities.raw_event_matches_read_filter(e));
317-
Ok(ReadEventResponse { events })
318-
});
324+
// let response = result
325+
// .and_then(|mut events| {
326+
// let CapabilitiesState::Negotiated(capabilities) = &machine.capabilities
327+
// else {
328+
// return Err(Error::UnknownError(
329+
// "Received read event request before capabilities negotiation"
330+
// .into(),
331+
// ));
332+
// };
333+
334+
// events.retain(|e| capabilities.raw_event_matches_read_filter(e));
335+
// Ok(ReadEventResponse { events })
336+
// })
337+
// .map_err(|e| (&e).into());
319338
vec![machine.send_from_widget_result_response(raw_request, response)]
320339
});
321340
action
@@ -343,14 +362,16 @@ impl WidgetMachine {
343362
let request = ReadStateEventRequest { event_type, state_key };
344363
let (request, action) = self.send_matrix_driver_request(request);
345364
request.then(|result, machine| {
346-
let response = result.map(|events| ReadEventResponse { events });
365+
let response = result
366+
.map(|events| ReadEventResponse { events })
367+
.map_err(|e| (&e).into());
347368
vec![machine.send_from_widget_result_response(raw_request, response)]
348369
});
349370
action
350371
} else {
351372
Some(self.send_from_widget_error_response(
352373
raw_request,
353-
"Not allowed to read state event",
374+
"Not allowed to read state event".into(),
354375
))
355376
}
356377
}
@@ -380,15 +401,15 @@ impl WidgetMachine {
380401
if !capabilities.send_delayed_event && request.delay.is_some() {
381402
return Some(self.send_from_widget_error_response(
382403
raw_request,
383-
format!(
384-
"Not allowed: missing the {} capability.",
385-
capabilities::SEND_DELAYED_EVENT
386-
),
404+
format!("Not allowed: missing the {SEND_DELAYED_EVENT} capability.").into(),
387405
));
388406
}
389407
if !capabilities.send.iter().any(|filter| filter.matches(&filter_in)) {
390408
return Some(
391-
self.send_from_widget_error_response(raw_request, "Not allowed to send event"),
409+
self.send_from_widget_error_response(
410+
raw_request,
411+
"Not allowed to send event".into(),
412+
),
392413
);
393414
}
394415

@@ -397,7 +418,8 @@ impl WidgetMachine {
397418
if let Ok(r) = result.as_mut() {
398419
r.set_room_id(machine.room_id.clone());
399420
}
400-
vec![machine.send_from_widget_result_response(raw_request, result)]
421+
vec![machine
422+
.send_from_widget_result_response(raw_request, result.map_err(|e| (&e).into()))]
401423
});
402424
action
403425
}
@@ -439,7 +461,7 @@ impl WidgetMachine {
439461
fn process_matrix_driver_response(
440462
&mut self,
441463
request_id: Uuid,
442-
response: Result<MatrixDriverResponse, String>,
464+
response: Result<MatrixDriverResponse, Error>,
443465
) -> Vec<Action> {
444466
match self.pending_matrix_driver_requests.extract(&request_id) {
445467
Ok(request) => request
@@ -472,15 +494,15 @@ impl WidgetMachine {
472494
fn send_from_widget_error_response(
473495
&self,
474496
raw_request: Raw<FromWidgetRequest>,
475-
error: impl fmt::Display,
497+
error: FromWidgetErrorResponse,
476498
) -> Action {
477-
self.send_from_widget_response(raw_request, FromWidgetErrorResponse::new(error))
499+
self.send_from_widget_response(raw_request, error)
478500
}
479501

480502
fn send_from_widget_result_response(
481503
&self,
482504
raw_request: Raw<FromWidgetRequest>,
483-
result: Result<impl Serialize, impl fmt::Display>,
505+
result: Result<impl Serialize, FromWidgetErrorResponse>,
484506
) -> Action {
485507
match result {
486508
Ok(res) => self.send_from_widget_response(raw_request, res),
@@ -586,7 +608,7 @@ impl ToWidgetRequestMeta {
586608
}
587609

588610
type MatrixDriverResponseFn =
589-
Box<dyn FnOnce(Result<MatrixDriverResponse, String>, &mut WidgetMachine) -> Vec<Action> + Send>;
611+
Box<dyn FnOnce(Result<MatrixDriverResponse, Error>, &mut WidgetMachine) -> Vec<Action> + Send>;
590612

591613
pub(crate) struct MatrixDriverRequestMeta {
592614
response_fn: Option<MatrixDriverResponseFn>,

crates/matrix-sdk/src/widget/machine/tests/capabilities.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ fn capabilities_failure_results_into_empty_capabilities() {
114114

115115
machine.process(IncomingMessage::MatrixDriverResponse {
116116
request_id,
117-
response: Err("OHMG!".into()),
117+
response: Err(crate::Error::UnknownError("OHMG!".into())),
118118
})
119119
};
120120

crates/matrix-sdk/src/widget/machine/tests/openid.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ fn openid_fail_results_in_response_blocked() {
162162

163163
machine.process(IncomingMessage::MatrixDriverResponse {
164164
request_id,
165-
response: Err("Unlucky one".into()),
165+
response: Err(crate::Error::UnknownError("Unlucky one".into())),
166166
})
167167
};
168168

0 commit comments

Comments
 (0)