Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Don't remember enabled of deleted push rules and properly return 404 for missing push rules in .../actions and .../enabled #7796

Merged
merged 32 commits into from
Sep 9, 2020
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ab3c6ba
Write some relevant tests (some failing)
reivilibre Jul 6, 2020
4b5bfc7
Fix test bug
reivilibre Jul 7, 2020
7f6791f
Make test_actions_404_when_put_inexistent_server_rule pass
reivilibre Jul 7, 2020
d01e536
Delete push_rule_enable row on rule deletion
reivilibre Jul 7, 2020
bdfef69
Use M_NOTFOUND code for missing push rules
reivilibre Jul 7, 2020
3911200
Check for nonexistant rules first
reivilibre Jul 7, 2020
271a937
Check non-server-default push rules exist before enabling/disabling
reivilibre Jul 7, 2020
cc3dfa7
Add SQL migration to remove dangling push_rules_enabled rows.
reivilibre Jul 7, 2020
e0cb3d2
Antilint
reivilibre Jul 7, 2020
9e66462
Newsfile
reivilibre Jul 7, 2020
7987fb9
I sort, you sort, we all sort!
reivilibre Jul 7, 2020
aebeb9f
Apply magic from Rich
reivilibre Jul 17, 2020
0cc3f02
Move delta to correct place and simplify.
reivilibre Jul 17, 2020
afea1e5
inexistent could be said to be non-existent
reivilibre Jul 17, 2020
0118ac5
Tighten to StoreError
reivilibre Jul 17, 2020
872a39c
Wow, I did not find the NotFoundError :)
reivilibre Jul 17, 2020
e8ea6a8
Antilint
reivilibre Jul 17, 2020
6667e27
Change syntax to support old SQLite3s
reivilibre Jul 17, 2020
7565a44
Docstrings, type annotations and minor changes for readability
reivilibre Aug 4, 2020
ee165dc
Always create an enabled row for push rules.
reivilibre Aug 18, 2020
58d7498
Merge branch 'develop' into rei/pushrules_latent_enabled
reivilibre Aug 18, 2020
32c1c2a
Use FOR KEY SHARE
reivilibre Aug 18, 2020
d5b63b9
rowcount is not what I thought
reivilibre Aug 18, 2020
5f211a6
Oops, 1 is truthy
reivilibre Aug 19, 2020
cca039d
For key share is a Postgresqlism
reivilibre Aug 19, 2020
bd1fad6
Fix test docstrings
reivilibre Aug 19, 2020
52035df
Fix old SQLite3 support
reivilibre Aug 19, 2020
1ae92c4
Merge branch 'develop' into rei/pushrules_latent_enabled
reivilibre Aug 19, 2020
ce94cc8
Cosmetic changes
reivilibre Aug 21, 2020
114b01f
Antilint
reivilibre Aug 27, 2020
80c7dd1
Merge branch 'develop' into rei/pushrules_latent_enabled
reivilibre Aug 27, 2020
62c096e
Merge remote-tracking branch 'origin/develop' into rei/pushrules_late…
reivilibre Sep 2, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/7796.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix inconsistent handling of nonexistant push rules' and no longer latently track the 'enabled' bit of removed push rules.
reivilibre marked this conversation as resolved.
Show resolved Hide resolved
29 changes: 19 additions & 10 deletions synapse/rest/client/v1/push_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


from synapse.api.errors import (
Codes,
NotFoundError,
StoreError,
SynapseError,
Expand Down Expand Up @@ -162,6 +161,21 @@ def notify_user(self, user_id):
self.notifier.on_new_event("push_rules_key", stream_id, users=[user_id])

def set_rule_attr(self, user_id, spec, val):
if spec["attr"] not in ("enabled", "actions"):
# for the sake of potential future expansion, shouldn't report
# 404 in the case of an unknown request so check it corresponds to
# a known attribute first.
raise UnrecognizedRequestError()

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(
reivilibre marked this conversation as resolved.
Show resolved Hide resolved
404, "Unknown rule %r" % (namespaced_rule_id,), Codes.NOT_FOUND
reivilibre marked this conversation as resolved.
Show resolved Hide resolved
)

if spec["attr"] == "enabled":
if isinstance(val, dict) and "enabled" in val:
val = val["enabled"]
Expand All @@ -170,17 +184,12 @@ def set_rule_attr(self, user_id, spec, val):
# This should *actually* take a dict, but many clients pass
# bools directly, so let's not break them.
raise SynapseError(400, "Value for 'enabled' must be boolean")
namespaced_rule_id = _namespaced_rule_id_from_spec(spec)
return self.store.set_push_rule_enabled(user_id, namespaced_rule_id, val)
return self.store.set_push_rule_enabled(
user_id, namespaced_rule_id, val, is_default_rule
)
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.store.set_push_rule_actions(
user_id, namespaced_rule_id, actions, is_default_rule
)
Expand Down
51 changes: 42 additions & 9 deletions synapse/storage/data_stores/main/push_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

richvdh marked this conversation as resolved.
Show resolved Hide resolved
import abc
import logging
from typing import List, Tuple, Union
Expand All @@ -22,6 +21,7 @@

from twisted.internet import defer

from synapse.api.errors import Codes, StoreError, SynapseError
from synapse.push.baserules import list_with_base_rules
from synapse.replication.slave.storage._slaved_id_tracker import SlavedIdTracker
from synapse.storage._base import SQLBaseStore
Expand Down Expand Up @@ -627,6 +627,12 @@ def delete_push_rule(self, user_id, rule_id):
"""

def delete_push_rule_txn(txn, stream_id, event_stream_ordering):
# we don't use simple_delete_one_txn because that would fail if the
# user did not have a push_rule_enable row.
self.db.simple_delete_txn(
txn, "push_rules_enable", {"user_name": user_id, "rule_id": rule_id}
)

self.db.simple_delete_one_txn(
txn, "push_rules", {"user_name": user_id, "rule_id": rule_id}
)
Expand All @@ -645,7 +651,7 @@ def delete_push_rule_txn(txn, stream_id, event_stream_ordering):
)

@defer.inlineCallbacks
def set_push_rule_enabled(self, user_id, rule_id, enabled):
def set_push_rule_enabled(self, user_id, rule_id, enabled, is_default_rule):
reivilibre marked this conversation as resolved.
Show resolved Hide resolved
with self._push_rules_stream_id_gen.get_next() as ids:
stream_id, event_stream_ordering = ids
yield self.db.runInteraction(
Expand All @@ -656,12 +662,31 @@ def set_push_rule_enabled(self, user_id, rule_id, enabled):
user_id,
rule_id,
enabled,
is_default_rule,
)

def _set_push_rule_enabled_txn(
self, txn, stream_id, event_stream_ordering, user_id, rule_id, enabled
self,
txn,
stream_id,
event_stream_ordering,
user_id,
rule_id,
enabled,
is_default_rule,
):
new_id = self._push_rules_enable_id_gen.get_next()

if not is_default_rule:
try:
# first check it exists
self.db.simple_select_one_onecol_txn(
reivilibre marked this conversation as resolved.
Show resolved Hide resolved
txn, "push_rules", {"user_name": user_id, "rule_id": rule_id}, "id"
)
except StoreError as serr:
if serr.code == 404:
reivilibre marked this conversation as resolved.
Show resolved Hide resolved
raise StoreError(404, "Push rule does not exist.", Codes.NOT_FOUND)
reivilibre marked this conversation as resolved.
Show resolved Hide resolved

self.db.simple_upsert_txn(
txn,
"push_rules_enable",
Expand Down Expand Up @@ -702,12 +727,20 @@ def set_push_rule_actions_txn(txn, stream_id, event_stream_ordering):
update_stream=False,
)
else:
self.db.simple_update_one_txn(
txn,
"push_rules",
{"user_name": user_id, "rule_id": rule_id},
{"actions": actions_json},
)
try:
self.db.simple_update_one_txn(
txn,
"push_rules",
{"user_name": user_id, "rule_id": rule_id},
{"actions": actions_json},
)
except SynapseError as serr:
reivilibre marked this conversation as resolved.
Show resolved Hide resolved
if serr.code == 404:
raise SynapseError(
reivilibre marked this conversation as resolved.
Show resolved Hide resolved
404, "Push rule does not exist", Codes.NOT_FOUND
)
else:
raise serr
reivilibre marked this conversation as resolved.
Show resolved Hide resolved

self._insert_push_rules_update_txn(
txn,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* Copyright 2020 The Matrix.org Foundation C.I.C.
reivilibre marked this conversation as resolved.
Show resolved Hide resolved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
Delete stuck 'enabled' bits that correspond to deleted push rules.
reivilibre marked this conversation as resolved.
Show resolved Hide resolved
We ignore rules that are server-default rules because they are not defined
in the `push_rules` table.
**/

DELETE FROM push_rules_enable pre WHERE
pre.rule_id NOT LIKE 'global/override/.%'
reivilibre marked this conversation as resolved.
Show resolved Hide resolved
AND pre.rule_id NOT LIKE 'global/underride/.%'
AND pre.rule_id NOT LIKE 'global/sender/.%'
AND pre.rule_id NOT LIKE 'global/room/.%'
AND pre.rule_id NOT LIKE 'global/content/.%'
AND NOT EXISTS (
SELECT 1 FROM push_rules pr
WHERE pr.user_name = pre.user_name
AND pr.rule_id = pre.rule_id
);
Loading