Skip to content

Commit cccf7a0

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

File tree

9 files changed

+181
-75
lines changed

9 files changed

+181
-75
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: 48 additions & 36 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::{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,10 @@ 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
208+
.send_from_widget_error_response(raw_request, (&Error::SerdeJson(e)).into())]
209+
}
207210
};
208211

209212
match request {
@@ -252,28 +255,29 @@ impl WidgetMachine {
252255
let CapabilitiesState::Negotiated(capabilities) = &self.capabilities else {
253256
let text =
254257
"Received send update delayed event request before capabilities were negotiated";
255-
return vec![self.send_from_widget_error_response(raw_request, text)];
258+
return vec![self.send_from_widget_error_response(raw_request, text.into())];
256259
};
257260
if !capabilities.update_delayed_event {
258261
return vec![self.send_from_widget_error_response(
259262
raw_request,
260-
format!(
261-
"Not allowed: missing the {} capability.",
262-
capabilities::UPDATE_DELAYED_EVENT
263-
),
263+
format!("Not allowed: missing the {UPDATE_DELAYED_EVENT} capability.")
264+
.into(),
264265
)];
265266
}
266267
let (request, request_action) =
267268
self.send_matrix_driver_request(UpdateDelayedEventRequest {
268269
action: req.action,
269270
delay_id: req.delay_id,
270271
});
271-
request.then(|res, machine| {
272+
request.then(|result, machine| {
272273
vec![machine.send_from_widget_result_response(
273274
raw_request,
274275
// This is mapped to another type because the update_delay_event::Response
275276
// does not impl Serialize
276-
res.map(Into::<UpdateDelayedEventResponse>::into),
277+
match result {
278+
Ok(response) => Ok(Into::<UpdateDelayedEventResponse>::into(response)),
279+
Err(e) => Err((&e).into()),
280+
},
277281
)]
278282
});
279283
request_action.map(|a| vec![a]).unwrap_or_default()
@@ -288,7 +292,7 @@ impl WidgetMachine {
288292
) -> Option<Action> {
289293
let CapabilitiesState::Negotiated(capabilities) = &self.capabilities else {
290294
let text = "Received read event request before capabilities were negotiated";
291-
return Some(self.send_from_widget_error_response(raw_request, text));
295+
return Some(self.send_from_widget_error_response(raw_request, text.into()));
292296
};
293297

294298
match request {
@@ -297,7 +301,7 @@ impl WidgetMachine {
297301
if !capabilities.read.iter().any(filter_fn) {
298302
return Some(self.send_from_widget_error_response(
299303
raw_request,
300-
"Not allowed to read message like event",
304+
"Not allowed to read message like event".into(),
301305
));
302306
}
303307

@@ -306,16 +310,21 @@ impl WidgetMachine {
306310
let request = ReadMessageLikeEventRequest { event_type, limit };
307311
let (request, action) = self.send_matrix_driver_request(request);
308312
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-
};
315-
316-
events.retain(|e| capabilities.raw_event_matches_read_filter(e));
317-
Ok(ReadEventResponse { events })
318-
});
313+
let response = match (result, &machine.capabilities) {
314+
(Ok(mut events), CapabilitiesState::Negotiated(capabilities)) => {
315+
events.retain(|e| capabilities.raw_event_matches_read_filter(e));
316+
Ok(ReadEventResponse { events })
317+
}
318+
(Ok(_), CapabilitiesState::Unset) => {
319+
Err("Received read event request before capabilities negotiation"
320+
.into())
321+
}
322+
(Ok(_), CapabilitiesState::Negotiating) => {
323+
Err("Received read event request while capabilities were negotiating"
324+
.into())
325+
}
326+
(Err(e), _) => Err((&e).into()),
327+
};
319328
vec![machine.send_from_widget_result_response(raw_request, response)]
320329
});
321330
action
@@ -343,14 +352,16 @@ impl WidgetMachine {
343352
let request = ReadStateEventRequest { event_type, state_key };
344353
let (request, action) = self.send_matrix_driver_request(request);
345354
request.then(|result, machine| {
346-
let response = result.map(|events| ReadEventResponse { events });
355+
let response = result
356+
.map(|events| ReadEventResponse { events })
357+
.map_err(|e| (&e).into());
347358
vec![machine.send_from_widget_result_response(raw_request, response)]
348359
});
349360
action
350361
} else {
351362
Some(self.send_from_widget_error_response(
352363
raw_request,
353-
"Not allowed to read state event",
364+
"Not allowed to read state event".into(),
354365
))
355366
}
356367
}
@@ -380,15 +391,15 @@ impl WidgetMachine {
380391
if !capabilities.send_delayed_event && request.delay.is_some() {
381392
return Some(self.send_from_widget_error_response(
382393
raw_request,
383-
format!(
384-
"Not allowed: missing the {} capability.",
385-
capabilities::SEND_DELAYED_EVENT
386-
),
394+
format!("Not allowed: missing the {SEND_DELAYED_EVENT} capability.").into(),
387395
));
388396
}
389397
if !capabilities.send.iter().any(|filter| filter.matches(&filter_in)) {
390398
return Some(
391-
self.send_from_widget_error_response(raw_request, "Not allowed to send event"),
399+
self.send_from_widget_error_response(
400+
raw_request,
401+
"Not allowed to send event".into(),
402+
),
392403
);
393404
}
394405

@@ -397,7 +408,8 @@ impl WidgetMachine {
397408
if let Ok(r) = result.as_mut() {
398409
r.set_room_id(machine.room_id.clone());
399410
}
400-
vec![machine.send_from_widget_result_response(raw_request, result)]
411+
vec![machine
412+
.send_from_widget_result_response(raw_request, result.map_err(|e| (&e).into()))]
401413
});
402414
action
403415
}
@@ -439,7 +451,7 @@ impl WidgetMachine {
439451
fn process_matrix_driver_response(
440452
&mut self,
441453
request_id: Uuid,
442-
response: Result<MatrixDriverResponse, String>,
454+
response: Result<MatrixDriverResponse, Error>,
443455
) -> Vec<Action> {
444456
match self.pending_matrix_driver_requests.extract(&request_id) {
445457
Ok(request) => request
@@ -472,15 +484,15 @@ impl WidgetMachine {
472484
fn send_from_widget_error_response(
473485
&self,
474486
raw_request: Raw<FromWidgetRequest>,
475-
error: impl fmt::Display,
487+
error: FromWidgetErrorResponse,
476488
) -> Action {
477-
self.send_from_widget_response(raw_request, FromWidgetErrorResponse::new(error))
489+
self.send_from_widget_response(raw_request, error)
478490
}
479491

480492
fn send_from_widget_result_response(
481493
&self,
482494
raw_request: Raw<FromWidgetRequest>,
483-
result: Result<impl Serialize, impl fmt::Display>,
495+
result: Result<impl Serialize, FromWidgetErrorResponse>,
484496
) -> Action {
485497
match result {
486498
Ok(res) => self.send_from_widget_response(raw_request, res),
@@ -586,7 +598,7 @@ impl ToWidgetRequestMeta {
586598
}
587599

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

591603
pub(crate) struct MatrixDriverRequestMeta {
592604
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)