mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-05-06 11:34:59 -04:00
Don't remember enabled
of deleted push rules and properly return 404 for missing push rules in .../actions
and .../enabled
(#7796)
Signed-off-by: Olivier Wilkinson (reivilibre) <olivier@librepush.net> Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>
This commit is contained in:
parent
e45b834119
commit
a5370072b5
5 changed files with 610 additions and 13 deletions
|
@ -13,11 +13,11 @@
|
|||
# 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.
|
||||
|
||||
import abc
|
||||
import logging
|
||||
from typing import List, Tuple, Union
|
||||
|
||||
from synapse.api.errors import NotFoundError, StoreError
|
||||
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, db_to_json
|
||||
|
@ -27,6 +27,7 @@ from synapse.storage.databases.main.events_worker import EventsWorkerStore
|
|||
from synapse.storage.databases.main.pusher import PusherWorkerStore
|
||||
from synapse.storage.databases.main.receipts import ReceiptsWorkerStore
|
||||
from synapse.storage.databases.main.roommember import RoomMemberWorkerStore
|
||||
from synapse.storage.engines import PostgresEngine, Sqlite3Engine
|
||||
from synapse.storage.push_rule import InconsistentRuleException, RuleNotFoundException
|
||||
from synapse.storage.util.id_generators import StreamIdGenerator
|
||||
from synapse.util import json_encoder
|
||||
|
@ -540,6 +541,25 @@ class PushRuleStore(PushRulesWorkerStore):
|
|||
},
|
||||
)
|
||||
|
||||
# ensure we have a push_rules_enable row
|
||||
# enabledness defaults to true
|
||||
if isinstance(self.database_engine, PostgresEngine):
|
||||
sql = """
|
||||
INSERT INTO push_rules_enable (id, user_name, rule_id, enabled)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT DO NOTHING
|
||||
"""
|
||||
elif isinstance(self.database_engine, Sqlite3Engine):
|
||||
sql = """
|
||||
INSERT OR IGNORE INTO push_rules_enable (id, user_name, rule_id, enabled)
|
||||
VALUES (?, ?, ?, ?)
|
||||
"""
|
||||
else:
|
||||
raise RuntimeError("Unknown database engine")
|
||||
|
||||
new_enable_id = self._push_rules_enable_id_gen.get_next()
|
||||
txn.execute(sql, (new_enable_id, user_id, rule_id, 1))
|
||||
|
||||
async def delete_push_rule(self, user_id: str, rule_id: str) -> None:
|
||||
"""
|
||||
Delete a push rule. Args specify the row to be deleted and can be
|
||||
|
@ -552,6 +572,12 @@ class PushRuleStore(PushRulesWorkerStore):
|
|||
"""
|
||||
|
||||
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_pool.simple_delete_txn(
|
||||
txn, "push_rules_enable", {"user_name": user_id, "rule_id": rule_id}
|
||||
)
|
||||
|
||||
self.db_pool.simple_delete_one_txn(
|
||||
txn, "push_rules", {"user_name": user_id, "rule_id": rule_id}
|
||||
)
|
||||
|
@ -570,10 +596,29 @@ class PushRuleStore(PushRulesWorkerStore):
|
|||
event_stream_ordering,
|
||||
)
|
||||
|
||||
async def set_push_rule_enabled(self, user_id, rule_id, enabled) -> None:
|
||||
async def set_push_rule_enabled(
|
||||
self, user_id: str, rule_id: str, enabled: bool, is_default_rule: bool
|
||||
) -> None:
|
||||
"""
|
||||
Sets the `enabled` state of a push rule.
|
||||
|
||||
Args:
|
||||
user_id: the user ID of the user who wishes to enable/disable the rule
|
||||
e.g. '@tina:example.org'
|
||||
rule_id: the full rule ID of the rule to be enabled/disabled
|
||||
e.g. 'global/override/.m.rule.roomnotif'
|
||||
or 'global/override/myCustomRule'
|
||||
enabled: True if the rule is to be enabled, False if it is to be
|
||||
disabled
|
||||
is_default_rule: True if and only if this is a server-default rule.
|
||||
This skips the check for existence (as only user-created rules
|
||||
are always stored in the database `push_rules` table).
|
||||
|
||||
Raises:
|
||||
NotFoundError if the rule does not exist.
|
||||
"""
|
||||
with await self._push_rules_stream_id_gen.get_next() as stream_id:
|
||||
event_stream_ordering = self._stream_id_gen.get_current_token()
|
||||
|
||||
await self.db_pool.runInteraction(
|
||||
"_set_push_rule_enabled_txn",
|
||||
self._set_push_rule_enabled_txn,
|
||||
|
@ -582,12 +627,47 @@ class PushRuleStore(PushRulesWorkerStore):
|
|||
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:
|
||||
# first check it exists; we need to lock for key share so that a
|
||||
# transaction that deletes the push rule will conflict with this one.
|
||||
# We also need a push_rule_enable row to exist for every push_rules
|
||||
# row, otherwise it is possible to simultaneously delete a push rule
|
||||
# (that has no _enable row) and enable it, resulting in a dangling
|
||||
# _enable row. To solve this: we either need to use SERIALISABLE or
|
||||
# ensure we always have a push_rule_enable row for every push_rule
|
||||
# row. We chose the latter.
|
||||
for_key_share = "FOR KEY SHARE"
|
||||
if not isinstance(self.database_engine, PostgresEngine):
|
||||
# For key share is not applicable/available on SQLite
|
||||
for_key_share = ""
|
||||
sql = (
|
||||
"""
|
||||
SELECT 1 FROM push_rules
|
||||
WHERE user_name = ? AND rule_id = ?
|
||||
%s
|
||||
"""
|
||||
% for_key_share
|
||||
)
|
||||
txn.execute(sql, (user_id, rule_id))
|
||||
if txn.fetchone() is None:
|
||||
# needed to set NOT_FOUND code.
|
||||
raise NotFoundError("Push rule does not exist.")
|
||||
|
||||
self.db_pool.simple_upsert_txn(
|
||||
txn,
|
||||
"push_rules_enable",
|
||||
|
@ -606,8 +686,30 @@ class PushRuleStore(PushRulesWorkerStore):
|
|||
)
|
||||
|
||||
async def set_push_rule_actions(
|
||||
self, user_id, rule_id, actions, is_default_rule
|
||||
self,
|
||||
user_id: str,
|
||||
rule_id: str,
|
||||
actions: List[Union[dict, str]],
|
||||
is_default_rule: bool,
|
||||
) -> None:
|
||||
"""
|
||||
Sets the `actions` state of a push rule.
|
||||
|
||||
Will throw NotFoundError if the rule does not exist; the Code for this
|
||||
is NOT_FOUND.
|
||||
|
||||
Args:
|
||||
user_id: the user ID of the user who wishes to enable/disable the rule
|
||||
e.g. '@tina:example.org'
|
||||
rule_id: the full rule ID of the rule to be enabled/disabled
|
||||
e.g. 'global/override/.m.rule.roomnotif'
|
||||
or 'global/override/myCustomRule'
|
||||
actions: A list of actions (each action being a dict or string),
|
||||
e.g. ["notify", {"set_tweak": "highlight", "value": false}]
|
||||
is_default_rule: True if and only if this is a server-default rule.
|
||||
This skips the check for existence (as only user-created rules
|
||||
are always stored in the database `push_rules` table).
|
||||
"""
|
||||
actions_json = json_encoder.encode(actions)
|
||||
|
||||
def set_push_rule_actions_txn(txn, stream_id, event_stream_ordering):
|
||||
|
@ -629,12 +731,19 @@ class PushRuleStore(PushRulesWorkerStore):
|
|||
update_stream=False,
|
||||
)
|
||||
else:
|
||||
self.db_pool.simple_update_one_txn(
|
||||
txn,
|
||||
"push_rules",
|
||||
{"user_name": user_id, "rule_id": rule_id},
|
||||
{"actions": actions_json},
|
||||
)
|
||||
try:
|
||||
self.db_pool.simple_update_one_txn(
|
||||
txn,
|
||||
"push_rules",
|
||||
{"user_name": user_id, "rule_id": rule_id},
|
||||
{"actions": actions_json},
|
||||
)
|
||||
except StoreError as serr:
|
||||
if serr.code == 404:
|
||||
# this sets the NOT_FOUND error Code
|
||||
raise NotFoundError("Push rule does not exist")
|
||||
else:
|
||||
raise
|
||||
|
||||
self._insert_push_rules_update_txn(
|
||||
txn,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue