Skip to main content

tuwunel_api/client/push/
pushrules_global.rs

1use axum::extract::State;
2use ruma::{
3	CanonicalJsonObject, CanonicalJsonValue,
4	api::client::push::get_pushrules_global_scope,
5	events::{
6		GlobalAccountDataEventType,
7		push_rules::{PushRulesEvent, PushRulesEventContent},
8	},
9	push::{PredefinedContentRuleId, PredefinedOverrideRuleId, Ruleset},
10};
11use tuwunel_core::{Result, err};
12
13use crate::Ruma;
14
15/// # `GET /_matrix/client/r0/pushrules/global/`
16///
17/// Retrieves the push rules event for this user.
18///
19/// This appears to be the exact same as `GET /_matrix/client/r0/pushrules/`.
20pub(crate) async fn get_pushrules_global_route(
21	State(services): State<crate::State>,
22	body: Ruma<get_pushrules_global_scope::v3::Request>,
23) -> Result<get_pushrules_global_scope::v3::Response> {
24	let sender_user = body.sender_user();
25
26	let Some(content_value) = services
27		.account_data
28		.get_global::<CanonicalJsonObject>(sender_user, GlobalAccountDataEventType::PushRules)
29		.await
30		.ok()
31		.and_then(|event| event.get("content").cloned())
32		.filter(CanonicalJsonValue::is_object)
33	else {
34		// user somehow has non-existent push rule event. recreate it and return server
35		// default silently
36
37		let ty = GlobalAccountDataEventType::PushRules;
38		let event = PushRulesEvent {
39			content: PushRulesEventContent {
40				global: Ruleset::server_default(sender_user),
41			},
42		};
43
44		services
45			.account_data
46			.update(None, sender_user, ty.to_string().into(), &serde_json::to_value(event)?)
47			.await?;
48
49		return Ok(get_pushrules_global_scope::v3::Response {
50			global: Ruleset::server_default(sender_user),
51		});
52	};
53
54	let account_data_content =
55		serde_json::from_value::<PushRulesEventContent>(content_value.into()).map_err(|e| {
56			err!(Database(warn!("Invalid push rules account data event in database: {e}")))
57		})?;
58
59	let mut global_ruleset = account_data_content.global;
60
61	// remove old deprecated mentions push rules as per MSC4210
62	// and update the stored server default push rules
63	#[expect(deprecated)]
64	{
65		use ruma::push::RuleKind::*;
66		if global_ruleset
67			.get(Override, PredefinedOverrideRuleId::ContainsDisplayName.as_str())
68			.is_some()
69			|| global_ruleset
70				.get(Override, PredefinedOverrideRuleId::RoomNotif.as_str())
71				.is_some()
72			|| global_ruleset
73				.get(Content, PredefinedContentRuleId::ContainsUserName.as_str())
74				.is_some()
75		{
76			global_ruleset
77				.remove(Override, PredefinedOverrideRuleId::ContainsDisplayName)
78				.ok();
79			global_ruleset
80				.remove(Override, PredefinedOverrideRuleId::RoomNotif)
81				.ok();
82			global_ruleset
83				.remove(Content, PredefinedContentRuleId::ContainsUserName)
84				.ok();
85
86			global_ruleset.update_with_server_default(Ruleset::server_default(sender_user));
87
88			services
89				.account_data
90				.update(
91					None,
92					sender_user,
93					GlobalAccountDataEventType::PushRules
94						.to_string()
95						.into(),
96					&serde_json::to_value(PushRulesEvent {
97						content: PushRulesEventContent { global: global_ruleset.clone() },
98					})
99					.expect("to json always works"),
100				)
101				.await?;
102		}
103	};
104
105	Ok(get_pushrules_global_scope::v3::Response { global: global_ruleset })
106}