Skip to main content

tuwunel_api/client/push/
pushrules_rule.rs

1use axum::extract::State;
2use ruma::{
3	api::client::push::{
4		delete_pushrule,
5		get_pushrule::{self, v3::Response},
6		set_pushrule,
7	},
8	push::{InsertPushRuleError, RemovePushRuleError},
9};
10use tuwunel_core::{Err, Result};
11
12use crate::Ruma;
13
14/// # `GET /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}`
15///
16/// Retrieves a single specified push rule for this user.
17pub(crate) async fn get_pushrule_route(
18	State(services): State<crate::State>,
19	body: Ruma<get_pushrule::v3::Request>,
20) -> Result<Response> {
21	let sender_user = body
22		.sender_user
23		.as_ref()
24		.expect("user is authenticated");
25
26	if super::is_deprecated_mention_rule(body.rule_id.as_str()) {
27		return Err!(Request(NotFound("Push rule not found.")));
28	}
29
30	let event = super::load_push_rules(&services, sender_user).await?;
31
32	event
33		.content
34		.global
35		.get(body.kind.clone(), &body.rule_id)
36		.map(Into::into)
37		.map_or_else(
38			|| Err!(Request(NotFound("Push rule not found."))),
39			|rule| Ok(Response { rule }),
40		)
41}
42
43/// # `PUT /_matrix/client/r0/pushrules/global/{kind}/{ruleId}`
44///
45/// Creates a single specified push rule for this user.
46pub(crate) async fn set_pushrule_route(
47	State(services): State<crate::State>,
48	body: Ruma<set_pushrule::v3::Request>,
49) -> Result<set_pushrule::v3::Response> {
50	let sender_user = body.sender_user();
51	let mut account_data = super::load_push_rules(&services, sender_user).await?;
52
53	super::check_rule_admission(&account_data.content.global, &body.rule)?;
54
55	if let Err(error) = account_data.content.global.insert(
56		body.rule.clone(),
57		body.after.as_deref(),
58		body.before.as_deref(),
59	) {
60		use InsertPushRuleError::*;
61
62		return match error {
63			| ServerDefaultRuleId => Err!(Request(InvalidParam(
64				"Rule IDs starting with a dot are reserved for server-default rules."
65			))),
66			| RelativeToServerDefaultRule => Err!(Request(InvalidParam(
67				"Can't place a push rule relatively to a server-default rule."
68			))),
69			| BeforeHigherThanAfter => Err!(Request(InvalidParam(
70				"The before rule has a higher priority than the after rule."
71			))),
72			| InvalidRuleId =>
73				Err!(Request(InvalidParam("Rule ID containing invalid characters."))),
74
75			| UnknownRuleId =>
76				Err!(Request(NotFound("The before or after rule could not be found."))),
77
78			| _ => Err!(Request(InvalidParam("Invalid data."))),
79		};
80	}
81
82	super::check_rule_size(&account_data.content.global, body.rule.kind(), body.rule.rule_id())?;
83
84	super::save_push_rules(&services, sender_user, &account_data).await?;
85
86	Ok(set_pushrule::v3::Response {})
87}
88
89/// # `DELETE /_matrix/client/r0/pushrules/global/{kind}/{ruleId}`
90///
91/// Deletes a single specified push rule for this user.
92pub(crate) async fn delete_pushrule_route(
93	State(services): State<crate::State>,
94	body: Ruma<delete_pushrule::v3::Request>,
95) -> Result<delete_pushrule::v3::Response> {
96	let sender_user = body.sender_user();
97	let mut account_data = super::load_push_rules(&services, sender_user).await?;
98
99	if let Err(error) = account_data
100		.content
101		.global
102		.remove(body.kind.clone(), &body.rule_id)
103	{
104		return match error {
105			| RemovePushRuleError::ServerDefault =>
106				Err!(Request(InvalidParam("Cannot delete a server-default pushrule."))),
107
108			| RemovePushRuleError::NotFound => Err!(Request(NotFound("Push rule not found."))),
109
110			| _ => Err!(Request(InvalidParam("Invalid data."))),
111		};
112	}
113
114	super::save_push_rules(&services, sender_user, &account_data).await?;
115
116	Ok(delete_pushrule::v3::Response {})
117}