You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

118 lines
4.0 KiB

  1. # Copyright 2016 OpenMarket Ltd
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import copy
  15. from typing import Any, Dict, List, Optional
  16. from synapse.push.rulekinds import PRIORITY_CLASS_INVERSE_MAP, PRIORITY_CLASS_MAP
  17. from synapse.synapse_rust.push import FilteredPushRules, PushRule
  18. from synapse.types import UserID
  19. def format_push_rules_for_user(
  20. user: UserID, ruleslist: FilteredPushRules
  21. ) -> Dict[str, Dict[str, list]]:
  22. """Converts a list of rawrules and a enabled map into nested dictionaries
  23. to match the Matrix client-server format for push rules"""
  24. rules: Dict[str, Dict[str, List[Dict[str, Any]]]] = {
  25. "global": {},
  26. "device": {},
  27. }
  28. rules["global"] = _add_empty_priority_class_arrays(rules["global"])
  29. for r, enabled in ruleslist.rules():
  30. template_name = _priority_class_to_template_name(r.priority_class)
  31. rulearray = rules["global"][template_name]
  32. template_rule = _rule_to_template(r)
  33. if not template_rule:
  34. continue
  35. rulearray.append(template_rule)
  36. template_rule["enabled"] = enabled
  37. if "conditions" not in template_rule:
  38. # Not all formatted rules have explicit conditions, e.g. "room"
  39. # rules omit them as they can be derived from the kind and rule ID.
  40. #
  41. # If the formatted rule has no conditions then we can skip the
  42. # formatting of conditions.
  43. continue
  44. # Remove internal stuff.
  45. template_rule["conditions"] = copy.deepcopy(template_rule["conditions"])
  46. for c in template_rule["conditions"]:
  47. c.pop("_cache_key", None)
  48. pattern_type = c.pop("pattern_type", None)
  49. if pattern_type == "user_id":
  50. c["pattern"] = user.to_string()
  51. elif pattern_type == "user_localpart":
  52. c["pattern"] = user.localpart
  53. sender_type = c.pop("sender_type", None)
  54. if sender_type == "user_id":
  55. c["sender"] = user.to_string()
  56. return rules
  57. def _add_empty_priority_class_arrays(d: Dict[str, list]) -> Dict[str, list]:
  58. for pc in PRIORITY_CLASS_MAP.keys():
  59. d[pc] = []
  60. return d
  61. def _rule_to_template(rule: PushRule) -> Optional[Dict[str, Any]]:
  62. templaterule: Dict[str, Any]
  63. unscoped_rule_id = _rule_id_from_namespaced(rule.rule_id)
  64. template_name = _priority_class_to_template_name(rule.priority_class)
  65. if template_name in ["override", "underride"]:
  66. templaterule = {"conditions": rule.conditions, "actions": rule.actions}
  67. elif template_name in ["sender", "room"]:
  68. templaterule = {"actions": rule.actions}
  69. unscoped_rule_id = rule.conditions[0]["pattern"]
  70. elif template_name == "content":
  71. if len(rule.conditions) != 1:
  72. return None
  73. thecond = rule.conditions[0]
  74. if "pattern" not in thecond:
  75. return None
  76. templaterule = {"actions": rule.actions}
  77. templaterule["pattern"] = thecond["pattern"]
  78. else:
  79. # This should not be reached unless this function is not kept in sync
  80. # with PRIORITY_CLASS_INVERSE_MAP.
  81. raise ValueError("Unexpected template_name: %s" % (template_name,))
  82. if unscoped_rule_id:
  83. templaterule["rule_id"] = unscoped_rule_id
  84. if rule.default:
  85. templaterule["default"] = True
  86. return templaterule
  87. def _rule_id_from_namespaced(in_rule_id: str) -> str:
  88. return in_rule_id.split("/")[-1]
  89. def _priority_class_to_template_name(pc: int) -> str:
  90. return PRIORITY_CLASS_INVERSE_MAP[pc]