diff --git a/synapse/rest/client/v1/push_rule.py b/synapse/rest/client/v1/push_rule.py
index 96633a176c..970a019223 100644
--- a/synapse/rest/client/v1/push_rule.py
+++ b/synapse/rest/client/v1/push_rule.py
@@ -22,7 +22,7 @@ from .base import ClientV1RestServlet, client_path_patterns
from synapse.storage.push_rule import (
InconsistentRuleException, RuleNotFoundException
)
-import synapse.push.baserules as baserules
+from synapse.push.baserules import list_with_base_rules, BASE_RULE_IDS
from synapse.push.rulekinds import (
PRIORITY_CLASS_MAP, PRIORITY_CLASS_INVERSE_MAP
)
@@ -55,12 +55,15 @@ class PushRuleRestServlet(ClientV1RestServlet):
yield self.set_rule_attr(requester.user.to_string(), spec, content)
defer.returnValue((200, {}))
+ if spec['rule_id'].startswith('.'):
+ # Rule ids starting with '.' are reserved for server default rules.
+ raise SynapseError(400, "cannot add new rule_ids that start with '.'")
+
try:
(conditions, actions) = _rule_tuple_from_request_object(
spec['template'],
spec['rule_id'],
content,
- device=spec['device'] if 'device' in spec else None
)
except InvalidRuleException as e:
raise SynapseError(400, e.message)
@@ -129,7 +132,7 @@ class PushRuleRestServlet(ClientV1RestServlet):
ruleslist.append(rule)
# We're going to be mutating this a lot, so do a deep copy
- ruleslist = copy.deepcopy(baserules.list_with_base_rules(ruleslist))
+ ruleslist = copy.deepcopy(list_with_base_rules(ruleslist))
rules = {'global': {}, 'device': {}}
@@ -153,23 +156,7 @@ class PushRuleRestServlet(ClientV1RestServlet):
elif pattern_type == "user_localpart":
c["pattern"] = user.localpart
- if r['priority_class'] > PRIORITY_CLASS_MAP['override']:
- # per-device rule
- profile_tag = _profile_tag_from_conditions(r["conditions"])
- r = _strip_device_condition(r)
- if not profile_tag:
- continue
- if profile_tag not in rules['device']:
- rules['device'][profile_tag] = {}
- rules['device'][profile_tag] = (
- _add_empty_priority_class_arrays(
- rules['device'][profile_tag]
- )
- )
-
- rulearray = rules['device'][profile_tag][template_name]
- else:
- rulearray = rules['global'][template_name]
+ rulearray = rules['global'][template_name]
template_rule = _rule_to_template(r)
if template_rule:
@@ -195,24 +182,6 @@ class PushRuleRestServlet(ClientV1RestServlet):
path = path[1:]
result = _filter_ruleset_with_path(rules['global'], path)
defer.returnValue((200, result))
- elif path[0] == 'device':
- path = path[1:]
- if path == []:
- raise UnrecognizedRequestError(
- PushRuleRestServlet.SLIGHTLY_PEDANTIC_TRAILING_SLASH_ERROR
- )
- if path[0] == '':
- defer.returnValue((200, rules['device']))
-
- profile_tag = path[0]
- path = path[1:]
- if profile_tag not in rules['device']:
- ret = {}
- ret = _add_empty_priority_class_arrays(ret)
- defer.returnValue((200, ret))
- ruleset = rules['device'][profile_tag]
- result = _filter_ruleset_with_path(ruleset, path)
- defer.returnValue((200, result))
else:
raise UnrecognizedRequestError()
@@ -232,13 +201,17 @@ class PushRuleRestServlet(ClientV1RestServlet):
return self.hs.get_datastore().set_push_rule_enabled(
user_id, namespaced_rule_id, val
)
- else:
- raise UnrecognizedRequestError()
-
- def get_rule_attr(self, user_id, namespaced_rule_id, attr):
- if attr == 'enabled':
- return self.hs.get_datastore().get_push_rule_enabled_by_user_rule_id(
- user_id, namespaced_rule_id
+ elif spec['attr'] == 'actions':
+ actions = val.get('actions')
+ _check_actions(actions)
+ namespaced_rule_id = _namespaced_rule_id_from_spec(spec)
+ rule_id = spec['rule_id']
+ is_default_rule = rule_id.startswith(".")
+ if is_default_rule:
+ if namespaced_rule_id not in BASE_RULE_IDS:
+ raise SynapseError(404, "Unknown rule %r" % (namespaced_rule_id,))
+ return self.hs.get_datastore().set_push_rule_actions(
+ user_id, namespaced_rule_id, actions, is_default_rule
)
else:
raise UnrecognizedRequestError()
@@ -252,16 +225,9 @@ def _rule_spec_from_path(path):
scope = path[1]
path = path[2:]
- if scope not in ['global', 'device']:
+ if scope != 'global':
raise UnrecognizedRequestError()
- device = None
- if scope == 'device':
- if len(path) == 0:
- raise UnrecognizedRequestError()
- device = path[0]
- path = path[1:]
-
if len(path) == 0:
raise UnrecognizedRequestError()
@@ -278,8 +244,6 @@ def _rule_spec_from_path(path):
'template': template,
'rule_id': rule_id
}
- if device:
- spec['profile_tag'] = device
path = path[1:]
@@ -289,7 +253,7 @@ def _rule_spec_from_path(path):
return spec
-def _rule_tuple_from_request_object(rule_template, rule_id, req_obj, device=None):
+def _rule_tuple_from_request_object(rule_template, rule_id, req_obj):
if rule_template in ['override', 'underride']:
if 'conditions' not in req_obj:
raise InvalidRuleException("Missing 'conditions'")
@@ -322,16 +286,19 @@ def _rule_tuple_from_request_object(rule_template, rule_id, req_obj, device=None
else:
raise InvalidRuleException("Unknown rule template: %s" % (rule_template,))
- if device:
- conditions.append({
- 'kind': 'device',
- 'profile_tag': device
- })
-
if 'actions' not in req_obj:
raise InvalidRuleException("No actions found")
actions = req_obj['actions']
+ _check_actions(actions)
+
+ return conditions, actions
+
+
+def _check_actions(actions):
+ if not isinstance(actions, list):
+ raise InvalidRuleException("No actions found")
+
for a in actions:
if a in ['notify', 'dont_notify', 'coalesce']:
pass
@@ -340,8 +307,6 @@ def _rule_tuple_from_request_object(rule_template, rule_id, req_obj, device=None
else:
raise InvalidRuleException("Unrecognised action")
- return conditions, actions
-
def _add_empty_priority_class_arrays(d):
for pc in PRIORITY_CLASS_MAP.keys():
@@ -349,17 +314,6 @@ def _add_empty_priority_class_arrays(d):
return d
-def _profile_tag_from_conditions(conditions):
- """
- Given a list of conditions, return the profile tag of the
- device rule if there is one
- """
- for c in conditions:
- if c['kind'] == 'device':
- return c['profile_tag']
- return None
-
-
def _filter_ruleset_with_path(ruleset, path):
if path == []:
raise UnrecognizedRequestError(
@@ -393,29 +347,23 @@ def _filter_ruleset_with_path(ruleset, path):
attr = path[0]
if attr in the_rule:
- return the_rule[attr]
+ # Make sure we return a JSON object as the attribute may be a
+ # JSON value.
+ return {attr: the_rule[attr]}
else:
raise UnrecognizedRequestError()
def _priority_class_from_spec(spec):
if spec['template'] not in PRIORITY_CLASS_MAP.keys():
- raise InvalidRuleException("Unknown template: %s" % (spec['kind']))
+ raise InvalidRuleException("Unknown template: %s" % (spec['template']))
pc = PRIORITY_CLASS_MAP[spec['template']]
- if spec['scope'] == 'device':
- pc += len(PRIORITY_CLASS_MAP)
-
return pc
def _priority_class_to_template_name(pc):
- if pc > PRIORITY_CLASS_MAP['override']:
- # per-device
- prio_class_index = pc - len(PRIORITY_CLASS_MAP)
- return PRIORITY_CLASS_INVERSE_MAP[prio_class_index]
- else:
- return PRIORITY_CLASS_INVERSE_MAP[pc]
+ return PRIORITY_CLASS_INVERSE_MAP[pc]
def _rule_to_template(rule):
@@ -445,23 +393,12 @@ def _rule_to_template(rule):
return templaterule
-def _strip_device_condition(rule):
- for i, c in enumerate(rule['conditions']):
- if c['kind'] == 'device':
- del rule['conditions'][i]
- return rule
-
-
def _namespaced_rule_id_from_spec(spec):
return _namespaced_rule_id(spec, spec['rule_id'])
def _namespaced_rule_id(spec, rule_id):
- if spec['scope'] == 'global':
- scope = 'global'
- else:
- scope = 'device/%s' % (spec['profile_tag'])
- return "%s/%s/%s" % (scope, spec['template'], rule_id)
+ return "global/%s/%s" % (spec['template'], rule_id)
def _rule_id_from_namespaced(in_rule_id):
|