Skip to content

Commit 0e054de

Browse files
authored
fix(sdk): Allow legacy push rules to be missing when changing NotificationSettings
They are being removed from the spec with MSC4210, so we can't error if they are not found.
1 parent d2b7dc6 commit 0e054de

File tree

4 files changed

+141
-11
lines changed

4 files changed

+141
-11
lines changed

crates/matrix-sdk/src/error.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,13 @@ pub enum NotificationSettingsError {
710710
UnableToSavePushRules,
711711
}
712712

713+
impl NotificationSettingsError {
714+
/// Whether this error is the [`RuleNotFound`](Self::RuleNotFound) variant.
715+
pub fn is_rule_not_found(&self) -> bool {
716+
matches!(self, Self::RuleNotFound(_))
717+
}
718+
}
719+
713720
impl From<InsertPushRuleError> for NotificationSettingsError {
714721
fn from(_: InsertPushRuleError) -> Self {
715722
Self::UnableToAddPushRule

crates/matrix-sdk/src/notification_settings/mod.rs

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -585,8 +585,8 @@ mod tests {
585585
};
586586
use ruma::{
587587
push::{
588-
Action, AnyPushRuleRef, NewPatternedPushRule, NewPushRule, PredefinedOverrideRuleId,
589-
PredefinedUnderrideRuleId, RuleKind,
588+
Action, AnyPushRuleRef, NewPatternedPushRule, NewPushRule, PredefinedContentRuleId,
589+
PredefinedOverrideRuleId, PredefinedUnderrideRuleId, RuleKind,
590590
},
591591
OwnedRoomId, RoomId,
592592
};
@@ -604,7 +604,7 @@ mod tests {
604604
notification_settings::{
605605
IsEncrypted, IsOneToOne, NotificationSettings, RoomNotificationMode,
606606
},
607-
test_utils::logged_in_client,
607+
test_utils::{logged_in_client, mocks::MatrixMockServer},
608608
Client,
609609
};
610610

@@ -1682,4 +1682,81 @@ mod tests {
16821682

16831683
assert_matches!(result, Err(NotificationSettingsError::InvalidParameter(_)));
16841684
}
1685+
1686+
#[async_test]
1687+
#[allow(deprecated)]
1688+
async fn test_enable_mention_ignore_missing_legacy_push_rules() {
1689+
let server = MatrixMockServer::new().await;
1690+
let client = server.client_builder().build().await;
1691+
let mut ruleset = get_server_default_ruleset();
1692+
1693+
// Make sure that the legacy mention push rules are missing.
1694+
if let Some(idx) = ruleset
1695+
.override_
1696+
.iter()
1697+
.position(|rule| rule.rule_id == PredefinedOverrideRuleId::ContainsDisplayName.as_ref())
1698+
{
1699+
ruleset.override_.shift_remove_index(idx);
1700+
}
1701+
1702+
if let Some(idx) = ruleset
1703+
.override_
1704+
.iter()
1705+
.position(|rule| rule.rule_id == PredefinedOverrideRuleId::RoomNotif.as_ref())
1706+
{
1707+
ruleset.override_.shift_remove_index(idx);
1708+
}
1709+
1710+
if let Some(idx) = ruleset
1711+
.content
1712+
.iter()
1713+
.position(|rule| rule.rule_id == PredefinedContentRuleId::ContainsUserName.as_ref())
1714+
{
1715+
ruleset.content.shift_remove_index(idx);
1716+
}
1717+
1718+
assert_matches!(
1719+
ruleset.iter().find(|rule| {
1720+
rule.rule_id() == PredefinedOverrideRuleId::ContainsDisplayName.as_ref()
1721+
|| rule.rule_id() == PredefinedOverrideRuleId::RoomNotif.as_ref()
1722+
|| rule.rule_id() == PredefinedContentRuleId::ContainsUserName.as_ref()
1723+
}),
1724+
None,
1725+
"ruleset must not have legacy mention push rules"
1726+
);
1727+
1728+
let settings = NotificationSettings::new(client, ruleset);
1729+
1730+
server
1731+
.mock_enable_push_rule(RuleKind::Override, PredefinedOverrideRuleId::IsUserMention)
1732+
.ok()
1733+
.mock_once()
1734+
.named("is_user_mention")
1735+
.mount()
1736+
.await;
1737+
settings
1738+
.set_push_rule_enabled(
1739+
RuleKind::Override,
1740+
PredefinedOverrideRuleId::IsUserMention,
1741+
false,
1742+
)
1743+
.await
1744+
.unwrap();
1745+
1746+
server
1747+
.mock_enable_push_rule(RuleKind::Override, PredefinedOverrideRuleId::IsRoomMention)
1748+
.ok()
1749+
.mock_once()
1750+
.named("is_room_mention")
1751+
.mount()
1752+
.await;
1753+
settings
1754+
.set_push_rule_enabled(
1755+
RuleKind::Override,
1756+
PredefinedOverrideRuleId::IsRoomMention,
1757+
false,
1758+
)
1759+
.await
1760+
.unwrap();
1761+
}
16851762
}

crates/matrix-sdk/src/notification_settings/rule_commands.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -133,22 +133,32 @@ impl RuleCommands {
133133
)?;
134134

135135
// For compatibility purpose, we still need to add commands for
136-
// `ContainsUserName` and `ContainsDisplayName` (deprecated rules).
136+
// `ContainsUserName` and `ContainsDisplayName` (removed rules).
137137
#[allow(deprecated)]
138138
{
139139
// `ContainsUserName`
140-
self.set_enabled_internal(
140+
if let Err(err) = self.set_enabled_internal(
141141
RuleKind::Content,
142142
PredefinedContentRuleId::ContainsUserName.as_str(),
143143
enabled,
144-
)?;
144+
) {
145+
// This rule has been removed from the spec, so it's fine if it wasn't found.
146+
if !err.is_rule_not_found() {
147+
return Err(err);
148+
}
149+
}
145150

146151
// `ContainsDisplayName`
147-
self.set_enabled_internal(
152+
if let Err(err) = self.set_enabled_internal(
148153
RuleKind::Override,
149154
PredefinedOverrideRuleId::ContainsDisplayName.as_str(),
150155
enabled,
151-
)?;
156+
) {
157+
// This rule has been removed from the spec, so it's fine if it wasn't found.
158+
if !err.is_rule_not_found() {
159+
return Err(err);
160+
}
161+
}
152162
}
153163

154164
Ok(())
@@ -164,14 +174,19 @@ impl RuleCommands {
164174
enabled,
165175
)?;
166176

167-
// For compatibility purpose, we still need to set `RoomNotif` (deprecated
177+
// For compatibility purpose, we still need to set `RoomNotif` (removed
168178
// rule).
169179
#[allow(deprecated)]
170-
self.set_enabled_internal(
180+
if let Err(err) = self.set_enabled_internal(
171181
RuleKind::Override,
172182
PredefinedOverrideRuleId::RoomNotif.as_str(),
173183
enabled,
174-
)?;
184+
) {
185+
// This rule has been removed from the spec, so it's fine if it wasn't found.
186+
if !err.is_rule_not_found() {
187+
return Err(err);
188+
}
189+
}
175190

176191
Ok(())
177192
}

crates/matrix-sdk/src/test_utils/mocks/mod.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ use ruma::{
4040
RoomAccountDataEventType, StateEventType,
4141
},
4242
media::Method,
43+
push::RuleKind,
4344
serde::Raw,
4445
time::Duration,
4546
DeviceId, EventId, MilliSecondsSinceUnixEpoch, MxcUri, OwnedDeviceId, OwnedEventId,
@@ -1361,6 +1362,19 @@ impl MatrixMockServer {
13611362
self.mock_endpoint(mock, DeleteThreadSubscriptionEndpoint::default())
13621363
.expect_default_access_token()
13631364
}
1365+
1366+
/// Create a prebuilt mock for the endpoint used to enable a push rule.
1367+
pub fn mock_enable_push_rule(
1368+
&self,
1369+
kind: RuleKind,
1370+
rule_id: impl AsRef<str>,
1371+
) -> MockEndpoint<'_, EnablePushRuleEndpoint> {
1372+
let rule_id = rule_id.as_ref();
1373+
let mock = Mock::given(method("PUT")).and(path_regex(format!(
1374+
"^/_matrix/client/v3/pushrules/global/{kind}/{rule_id}/enabled",
1375+
)));
1376+
self.mock_endpoint(mock, EnablePushRuleEndpoint).expect_default_access_token()
1377+
}
13641378
}
13651379

13661380
/// Parameter to [`MatrixMockServer::sync_room`].
@@ -1625,6 +1639,12 @@ impl<'a, T> MockEndpoint<'a, T> {
16251639
self.respond_with(ResponseTemplate::new(200).set_body_json(json!({ "event_id": event_id })))
16261640
}
16271641

1642+
/// Internal helper to return a 200 OK response with an empty JSON object in
1643+
/// the body.
1644+
fn ok_empty_json(self) -> MatrixMock<'a> {
1645+
self.respond_with(ResponseTemplate::new(200).set_body_json(json!({})))
1646+
}
1647+
16281648
/// Returns an endpoint that emulates a permanent failure error (e.g. event
16291649
/// is too large).
16301650
///
@@ -3897,3 +3917,14 @@ impl<'a> MockEndpoint<'a, DeleteThreadSubscriptionEndpoint> {
38973917
self
38983918
}
38993919
}
3920+
3921+
/// A prebuilt mock for `PUT
3922+
/// /_matrix/client/v3/pushrules/global/{kind}/{ruleId}/enabled`.
3923+
pub struct EnablePushRuleEndpoint;
3924+
3925+
impl<'a> MockEndpoint<'a, EnablePushRuleEndpoint> {
3926+
/// Returns a successful empty JSON response.
3927+
pub fn ok(self) -> MatrixMock<'a> {
3928+
self.ok_empty_json()
3929+
}
3930+
}

0 commit comments

Comments
 (0)