tuwunel_service/account_data/
push_rules.rs1use ruma::{
7 RoomId, UserId,
8 events::{GlobalAccountDataEventType, push_rules::PushRulesEvent},
9 push::{AnyPushRuleRef, NewPushRule, NewSimplePushRule, RuleKind},
10};
11use tuwunel_core::{Result, debug_warn, err, implement, utils::json::serialized_len};
12
13use super::{MAX_RULE_BYTES, admits_rule};
14
15#[implement(super::Service)]
25pub async fn copy_room_push_rule(
26 &self,
27 user_id: &UserId,
28 from_room: &RoomId,
29 to_room: &RoomId,
30) -> Result {
31 let Ok(mut account_data): Result<PushRulesEvent> = self
32 .get_global(user_id, GlobalAccountDataEventType::PushRules)
33 .await
34 else {
35 return Ok(());
36 };
37
38 let ruleset = &mut account_data.content.global;
39
40 let Some(AnyPushRuleRef::Room(rule)) = ruleset.get(RuleKind::Room, from_room) else {
41 return Ok(());
42 };
43
44 let actions = rule.actions.clone();
45 let enabled = rule.enabled;
46
47 if !admits_rule(ruleset, RuleKind::Room, to_room.as_str())
48 || serialized_len(&actions)? > MAX_RULE_BYTES
49 {
50 debug_warn!(%user_id, %to_room, "Ruleset has no room for the copied push rule");
51
52 return Ok(());
53 }
54
55 let rule = NewPushRule::Room(NewSimplePushRule::new(to_room.to_owned(), actions));
56 let is_new = ruleset.get(RuleKind::Room, to_room).is_none();
57
58 ruleset
59 .insert(rule, None, None)
60 .map_err(|e| err!(Request(InvalidParam("Failed to copy room push rule: {e}"))))?;
61
62 if is_new {
64 ruleset
65 .set_enabled(RuleKind::Room, to_room, enabled)
66 .map_err(|e| err!(Request(InvalidParam("Failed to copy push rule state: {e}"))))?;
67 }
68
69 let ty = GlobalAccountDataEventType::PushRules;
70 let data = serde_json::to_value(account_data)?;
71
72 self.update(None, user_id, ty.to_string().into(), &data)
73 .await
74}