Skip to main content

tuwunel_service/account_data/
push_rules.rs

1use ruma::{
2	RoomId, UserId,
3	events::{GlobalAccountDataEventType, push_rules::PushRulesEvent},
4	push::{AnyPushRuleRef, NewPushRule, NewSimplePushRule, RuleKind},
5};
6use tuwunel_core::{Result, debug_warn, err, implement, utils::json::serialized_len};
7
8use super::{MAX_RULE_BYTES, admits_rule};
9
10#[implement(super::Service)]
11pub async fn copy_room_push_rule(
12	&self,
13	user_id: &UserId,
14	from_room: &RoomId,
15	to_room: &RoomId,
16) -> Result {
17	let Ok(mut account_data): Result<PushRulesEvent> = self
18		.get_global(user_id, GlobalAccountDataEventType::PushRules)
19		.await
20	else {
21		return Ok(());
22	};
23
24	let ruleset = &mut account_data.content.global;
25
26	let Some(AnyPushRuleRef::Room(rule)) = ruleset.get(RuleKind::Room, from_room) else {
27		return Ok(());
28	};
29
30	let actions = rule.actions.clone();
31
32	if !admits_rule(ruleset, RuleKind::Room, to_room.as_str())
33		|| serialized_len(&actions)? > MAX_RULE_BYTES
34	{
35		debug_warn!(%user_id, %to_room, "Ruleset has no room for the copied push rule");
36
37		return Ok(());
38	}
39
40	let rule = NewPushRule::Room(NewSimplePushRule::new(to_room.to_owned(), actions));
41
42	ruleset
43		.insert(rule, None, None)
44		.map_err(|e| err!(Request(InvalidParam("Failed to copy room push rule: {e}"))))?;
45
46	let ty = GlobalAccountDataEventType::PushRules;
47	let data = serde_json::to_value(account_data)?;
48
49	self.update(None, user_id, ty.to_string().into(), &data)
50		.await
51}