tuwunel_api/client/push/
mod.rs1mod notifications;
2mod pushers;
3mod pushers_set;
4mod pushrules;
5mod pushrules_global;
6mod pushrules_rule;
7mod pushrules_rule_actions;
8mod pushrules_rule_enabled;
9#[cfg(test)]
10mod tests;
11
12use ruma::{
13 UserId,
14 events::{GlobalAccountDataEventType, push_rules::PushRulesEvent},
15 push::{
16 AnyPushRuleRef, NewPushRule, PredefinedContentRuleId, PredefinedOverrideRuleId, RuleKind,
17 Ruleset, SimplePushRule,
18 },
19};
20use tuwunel_core::{Err, Result, err, utils::json::serialized_len};
21use tuwunel_service::{
22 Services,
23 account_data::{MAX_RULE_BYTES, MAX_RULE_ID_BYTES, admits_rule},
24};
25
26pub(crate) use self::{
27 notifications::get_notifications_route,
28 pushers::get_pushers_route,
29 pushers_set::set_pushers_route,
30 pushrules::get_pushrules_all_route,
31 pushrules_global::get_pushrules_global_route,
32 pushrules_rule::{delete_pushrule_route, get_pushrule_route, set_pushrule_route},
33 pushrules_rule_actions::{get_pushrule_actions_route, set_pushrule_actions_route},
34 pushrules_rule_enabled::{get_pushrule_enabled_route, set_pushrule_enabled_route},
35};
36
37async fn load_push_rules(services: &Services, sender_user: &UserId) -> Result<PushRulesEvent> {
38 services
39 .account_data
40 .get_global(sender_user, GlobalAccountDataEventType::PushRules)
41 .await
42 .map_err(|_| err!(Request(NotFound("PushRules event not found."))))
43}
44
45async fn save_push_rules(
46 services: &Services,
47 sender_user: &UserId,
48 event: &PushRulesEvent,
49) -> Result {
50 let ty = GlobalAccountDataEventType::PushRules;
51
52 services
53 .account_data
54 .update(None, sender_user, ty.to_string().into(), &serde_json::to_value(event)?)
55 .await
56}
57
58fn check_rule_admission(ruleset: &Ruleset, rule: &NewPushRule) -> Result {
59 let rule_id = rule.rule_id();
60
61 if rule_id.len() > MAX_RULE_ID_BYTES {
62 return Err!(Request(TooLarge("Push rule ID is too long.")));
63 }
64
65 if !admits_rule(ruleset, rule.kind(), rule_id) {
66 return Err!(Request(InvalidParam("Account has too many push rules.")));
67 }
68
69 Ok(())
70}
71
72fn check_rule_size(ruleset: &Ruleset, kind: RuleKind, rule_id: &str) -> Result {
73 let rule = ruleset
74 .get(kind, rule_id)
75 .ok_or_else(|| err!(Request(NotFound("Push rule not found."))))?;
76
77 let size = match rule {
78 | AnyPushRuleRef::Override(rule) | AnyPushRuleRef::Underride(rule) =>
79 serialized_len(&(&rule.conditions, &rule.actions))?,
80
81 | AnyPushRuleRef::Content(rule) => serialized_len(&(&rule.pattern, &rule.actions))?,
82
83 | AnyPushRuleRef::Room(SimplePushRule { actions, .. })
84 | AnyPushRuleRef::Sender(SimplePushRule { actions, .. }) => serialized_len(actions)?,
85 };
86
87 if size > MAX_RULE_BYTES {
88 return Err!(Request(TooLarge("Push rule is too large.")));
89 }
90
91 Ok(())
92}
93
94#[expect(deprecated)]
96fn is_deprecated_mention_rule(rule_id: &str) -> bool {
97 rule_id == PredefinedContentRuleId::ContainsUserName.as_str()
98 || rule_id == PredefinedOverrideRuleId::ContainsDisplayName.as_str()
99 || rule_id == PredefinedOverrideRuleId::RoomNotif.as_str()
100}