forked from MirrorHub/synapse
Rename deletions to redactions
This commit is contained in:
parent
7d9a84a445
commit
70899d3ab2
16 changed files with 77 additions and 74 deletions
|
@ -20,7 +20,7 @@ from twisted.internet import defer
|
|||
from synapse.api.constants import Membership, JoinRules
|
||||
from synapse.api.errors import AuthError, StoreError, Codes, SynapseError
|
||||
from synapse.api.events.room import (
|
||||
RoomMemberEvent, RoomPowerLevelsEvent, RoomDeletionEvent,
|
||||
RoomMemberEvent, RoomPowerLevelsEvent, RoomRedactionEvent,
|
||||
)
|
||||
from synapse.util.logutils import log_function
|
||||
|
||||
|
@ -72,8 +72,8 @@ class Auth(object):
|
|||
if event.type == RoomPowerLevelsEvent.TYPE:
|
||||
yield self._check_power_levels(event)
|
||||
|
||||
if event.type == RoomDeletionEvent.TYPE:
|
||||
yield self._check_deletion(event)
|
||||
if event.type == RoomRedactionEvent.TYPE:
|
||||
yield self._check_redaction(event)
|
||||
|
||||
defer.returnValue(True)
|
||||
else:
|
||||
|
@ -327,7 +327,7 @@ class Auth(object):
|
|||
)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def _check_deletion(self, event):
|
||||
def _check_redaction(self, event):
|
||||
user_level = yield self.store.get_power_level(
|
||||
event.room_id,
|
||||
event.user_id,
|
||||
|
@ -338,15 +338,15 @@ class Auth(object):
|
|||
else:
|
||||
user_level = 0
|
||||
|
||||
_, _, delete_level = yield self.store.get_ops_levels(event.room_id)
|
||||
_, _, redact_level = yield self.store.get_ops_levels(event.room_id)
|
||||
|
||||
if not delete_level:
|
||||
delete_level = 50
|
||||
if not redact_level:
|
||||
redact_level = 50
|
||||
|
||||
if user_level < delete_level:
|
||||
if user_level < redact_level:
|
||||
raise AuthError(
|
||||
403,
|
||||
"You don't have permission to delete events"
|
||||
"You don't have permission to redact events"
|
||||
)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
|
|
|
@ -59,7 +59,7 @@ class SynapseEvent(JsonEncodedObject):
|
|||
"age_ts",
|
||||
"prev_content",
|
||||
"prev_state",
|
||||
"pruned_because",
|
||||
"redacted_because",
|
||||
]
|
||||
|
||||
internal_keys = [
|
||||
|
@ -70,7 +70,7 @@ class SynapseEvent(JsonEncodedObject):
|
|||
"origin",
|
||||
"outlier",
|
||||
"power_level",
|
||||
"deleted",
|
||||
"redacted",
|
||||
]
|
||||
|
||||
required_keys = [
|
||||
|
|
|
@ -18,7 +18,7 @@ from synapse.api.events.room import (
|
|||
InviteJoinEvent, RoomConfigEvent, RoomNameEvent, GenericEvent,
|
||||
RoomPowerLevelsEvent, RoomJoinRulesEvent, RoomOpsPowerLevelsEvent,
|
||||
RoomCreateEvent, RoomAddStateLevelEvent, RoomSendEventLevelEvent,
|
||||
RoomDeletionEvent,
|
||||
RoomRedactionEvent,
|
||||
)
|
||||
|
||||
from synapse.util.stringutils import random_string
|
||||
|
@ -40,7 +40,7 @@ class EventFactory(object):
|
|||
RoomAddStateLevelEvent,
|
||||
RoomSendEventLevelEvent,
|
||||
RoomOpsPowerLevelsEvent,
|
||||
RoomDeletionEvent,
|
||||
RoomRedactionEvent,
|
||||
]
|
||||
|
||||
def __init__(self, hs):
|
||||
|
|
|
@ -182,10 +182,10 @@ class RoomAliasesEvent(SynapseStateEvent):
|
|||
return {}
|
||||
|
||||
|
||||
class RoomDeletionEvent(SynapseEvent):
|
||||
TYPE = "m.room.deletion"
|
||||
class RoomRedactionEvent(SynapseEvent):
|
||||
TYPE = "m.room.redaction"
|
||||
|
||||
valid_keys = SynapseEvent.valid_keys + ["deletes"]
|
||||
valid_keys = SynapseEvent.valid_keys + ["redacts"]
|
||||
|
||||
def get_content_template(self):
|
||||
return {}
|
||||
|
|
|
@ -23,7 +23,7 @@ def prune_event(event):
|
|||
""" Prunes the given event of all keys we don't know about or think could
|
||||
potentially be dodgy.
|
||||
|
||||
This is used when we "delete" an event. We want to remove all fields that
|
||||
This is used when we "redact" an event. We want to remove all fields that
|
||||
the user has specified, but we do want to keep necessary information like
|
||||
type, state_key etc.
|
||||
"""
|
||||
|
@ -55,7 +55,7 @@ def prune_event(event):
|
|||
elif event.type == RoomSendEventLevelEvent.TYPE:
|
||||
add_fields("level")
|
||||
elif event.type == RoomOpsPowerLevelsEvent.TYPE:
|
||||
add_fields("kick_level", "ban_level", "delete_level")
|
||||
add_fields("kick_level", "ban_level", "redact_level")
|
||||
elif event.type == RoomAliasesEvent.TYPE:
|
||||
add_fields("aliases")
|
||||
|
||||
|
|
|
@ -255,7 +255,7 @@ class RoomCreationHandler(BaseHandler):
|
|||
etype=RoomOpsPowerLevelsEvent.TYPE,
|
||||
ban_level=50,
|
||||
kick_level=50,
|
||||
delete_level=50,
|
||||
redact_level=50,
|
||||
)
|
||||
|
||||
return [
|
||||
|
|
|
@ -19,7 +19,7 @@ from twisted.internet import defer
|
|||
from base import RestServlet, client_path_pattern
|
||||
from synapse.api.errors import SynapseError, Codes
|
||||
from synapse.streams.config import PaginationConfig
|
||||
from synapse.api.events.room import RoomMemberEvent, RoomDeletionEvent
|
||||
from synapse.api.events.room import RoomMemberEvent, RoomRedactionEvent
|
||||
from synapse.api.constants import Membership
|
||||
|
||||
import json
|
||||
|
@ -430,9 +430,9 @@ class RoomMembershipRestServlet(RestServlet):
|
|||
self.txns.store_client_transaction(request, txn_id, response)
|
||||
defer.returnValue(response)
|
||||
|
||||
class RoomDeleteEventRestServlet(RestServlet):
|
||||
class RoomRedactEventRestServlet(RestServlet):
|
||||
def register(self, http_server):
|
||||
PATTERN = ("/rooms/(?P<room_id>[^/]*)/delete/(?P<event_id>[^/]*)")
|
||||
PATTERN = ("/rooms/(?P<room_id>[^/]*)/redact/(?P<event_id>[^/]*)")
|
||||
register_txn_path(self, PATTERN, http_server)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
|
@ -441,11 +441,11 @@ class RoomDeleteEventRestServlet(RestServlet):
|
|||
content = _parse_json(request)
|
||||
|
||||
event = self.event_factory.create_event(
|
||||
etype=RoomDeletionEvent.TYPE,
|
||||
etype=RoomRedactionEvent.TYPE,
|
||||
room_id=urllib.unquote(room_id),
|
||||
user_id=user.to_string(),
|
||||
content=content,
|
||||
deletes=event_id,
|
||||
redacts=event_id,
|
||||
)
|
||||
|
||||
msg_handler = self.handlers.message_handler
|
||||
|
@ -520,4 +520,4 @@ def register_servlets(hs, http_server):
|
|||
PublicRoomListRestServlet(hs).register(http_server)
|
||||
RoomStateRestServlet(hs).register(http_server)
|
||||
RoomInitialSyncRestServlet(hs).register(http_server)
|
||||
RoomDeleteEventRestServlet(hs).register(http_server)
|
||||
RoomRedactEventRestServlet(hs).register(http_server)
|
||||
|
|
|
@ -24,7 +24,7 @@ from synapse.api.events.room import (
|
|||
RoomAddStateLevelEvent,
|
||||
RoomSendEventLevelEvent,
|
||||
RoomOpsPowerLevelsEvent,
|
||||
RoomDeletionEvent,
|
||||
RoomRedactionEvent,
|
||||
)
|
||||
|
||||
from synapse.util.logutils import log_function
|
||||
|
@ -57,7 +57,7 @@ SCHEMAS = [
|
|||
"presence",
|
||||
"im",
|
||||
"room_aliases",
|
||||
"deletions",
|
||||
"redactions",
|
||||
]
|
||||
|
||||
|
||||
|
@ -184,8 +184,8 @@ class DataStore(RoomMemberStore, RoomStore,
|
|||
self._store_send_event_level(txn, event)
|
||||
elif event.type == RoomOpsPowerLevelsEvent.TYPE:
|
||||
self._store_ops_level(txn, event)
|
||||
elif event.type == RoomDeletionEvent.TYPE:
|
||||
self._store_deletion(txn, event)
|
||||
elif event.type == RoomRedactionEvent.TYPE:
|
||||
self._store_redaction(txn, event)
|
||||
|
||||
vals = {
|
||||
"topological_ordering": event.depth,
|
||||
|
@ -207,7 +207,7 @@ class DataStore(RoomMemberStore, RoomStore,
|
|||
unrec = {
|
||||
k: v
|
||||
for k, v in event.get_full_dict().items()
|
||||
if k not in vals.keys() and k not in ["deleted", "pruned_because"]
|
||||
if k not in vals.keys() and k not in ["redacted", "redacted_because"]
|
||||
}
|
||||
vals["unrecognized_keys"] = json.dumps(unrec)
|
||||
|
||||
|
@ -245,25 +245,26 @@ class DataStore(RoomMemberStore, RoomStore,
|
|||
}
|
||||
)
|
||||
|
||||
def _store_deletion(self, txn, event):
|
||||
def _store_redaction(self, txn, event):
|
||||
txn.execute(
|
||||
"INSERT INTO deletions (event_id, deletes) VALUES (?,?) OR IGNORE",
|
||||
(event.event_id, event.deletes)
|
||||
"INSERT OR IGNORE INTO redactions "
|
||||
"(event_id, redacts) VALUES (?,?)",
|
||||
(event.event_id, event.redacts)
|
||||
)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def get_current_state(self, room_id, event_type=None, state_key=""):
|
||||
del_sql = (
|
||||
"SELECT event_id FROM deletions WHERE deletes = e.event_id"
|
||||
"SELECT event_id FROM redactions WHERE redacts = e.event_id"
|
||||
)
|
||||
|
||||
sql = (
|
||||
"SELECT e.*, (%(deleted)s) AS deleted FROM events as e "
|
||||
"SELECT e.*, (%(redacted)s) AS redacted FROM events as e "
|
||||
"INNER JOIN current_state_events as c ON e.event_id = c.event_id "
|
||||
"INNER JOIN state_events as s ON e.event_id = s.event_id "
|
||||
"WHERE c.room_id = ? "
|
||||
) % {
|
||||
"deleted": del_sql,
|
||||
"redacted": del_sql,
|
||||
}
|
||||
|
||||
if event_type:
|
||||
|
|
|
@ -383,14 +383,14 @@ class SQLBaseStore(object):
|
|||
prev = self._parse_event_from_row(prevs[0])
|
||||
ev.prev_content = prev.content
|
||||
|
||||
if not hasattr(ev, "deleted"):
|
||||
logger.debug("Doesn't have deleted key: %s", ev)
|
||||
ev.deleted = self._has_been_deleted_txn(txn, ev)
|
||||
if not hasattr(ev, "redacted"):
|
||||
logger.debug("Doesn't have redacted key: %s", ev)
|
||||
ev.redacted = self._has_been_redacted_txn(txn, ev)
|
||||
|
||||
if ev.deleted:
|
||||
# Get the deletion event.
|
||||
if ev.redacted:
|
||||
# Get the redaction event.
|
||||
sql = "SELECT * FROM events WHERE event_id = ?"
|
||||
txn.execute(sql, (ev.deleted,))
|
||||
txn.execute(sql, (ev.redacted,))
|
||||
|
||||
del_evs = self._parse_events_txn(
|
||||
txn, self.cursor_to_dict(txn)
|
||||
|
@ -398,12 +398,12 @@ class SQLBaseStore(object):
|
|||
|
||||
if del_evs:
|
||||
prune_event(ev)
|
||||
ev.pruned_because = del_evs[0]
|
||||
ev.redacted_because = del_evs[0]
|
||||
|
||||
return events
|
||||
|
||||
def _has_been_deleted_txn(self, txn, event):
|
||||
sql = "SELECT event_id FROM deletions WHERE deletes = ?"
|
||||
def _has_been_redacted_txn(self, txn, event):
|
||||
sql = "SELECT event_id FROM redactions WHERE redacts = ?"
|
||||
txn.execute(sql, (event.event_id,))
|
||||
result = txn.fetchone()
|
||||
return result[0] if result else None
|
||||
|
|
|
@ -27,7 +27,7 @@ import logging
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
OpsLevel = collections.namedtuple("OpsLevel", ("ban_level", "kick_level", "delete_level"))
|
||||
OpsLevel = collections.namedtuple("OpsLevel", ("ban_level", "kick_level", "redact_level"))
|
||||
|
||||
|
||||
class RoomStore(SQLBaseStore):
|
||||
|
@ -189,7 +189,7 @@ class RoomStore(SQLBaseStore):
|
|||
|
||||
def _get_ops_levels(self, txn, room_id):
|
||||
sql = (
|
||||
"SELECT ban_level, kick_level, delete_level "
|
||||
"SELECT ban_level, kick_level, redact_level "
|
||||
"FROM room_ops_levels as r "
|
||||
"INNER JOIN current_state_events as c "
|
||||
"ON r.event_id = c.event_id "
|
||||
|
@ -327,8 +327,8 @@ class RoomStore(SQLBaseStore):
|
|||
if "ban_level" in event.content:
|
||||
content["ban_level"] = event.content["ban_level"]
|
||||
|
||||
if "delete_level" in event.content:
|
||||
content["delete_level"] = event.content["delete_level"]
|
||||
if "redact_level" in event.content:
|
||||
content["redact_level"] = event.content["redact_level"]
|
||||
|
||||
self._simple_insert_txn(
|
||||
txn,
|
||||
|
|
|
@ -183,18 +183,18 @@ class RoomMemberStore(SQLBaseStore):
|
|||
|
||||
def _get_members_query_txn(self, txn, where_clause, where_values):
|
||||
del_sql = (
|
||||
"SELECT event_id FROM deletions WHERE deletes = e.event_id"
|
||||
"SELECT event_id FROM redactions WHERE redacts = e.event_id"
|
||||
)
|
||||
|
||||
sql = (
|
||||
"SELECT e.*, (%(deleted)s) AS deleted FROM events as e "
|
||||
"SELECT e.*, (%(redacted)s) AS redacted FROM events as e "
|
||||
"INNER JOIN room_memberships as m "
|
||||
"ON e.event_id = m.event_id "
|
||||
"INNER JOIN current_state_events as c "
|
||||
"ON m.event_id = c.event_id "
|
||||
"WHERE %(where)s "
|
||||
) % {
|
||||
"deleted": del_sql,
|
||||
"redacted": del_sql,
|
||||
"where": where_clause,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
CREATE TABLE IF NOT EXISTS deletions (
|
||||
event_id TEXT NOT NULL,
|
||||
deletes TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS deletions_event_id ON deletions (event_id);
|
||||
CREATE INDEX IF NOT EXISTS deletions_deletes ON deletions (deletes);
|
|
@ -1,11 +1,12 @@
|
|||
CREATE TABLE IF NOT EXISTS deletions (
|
||||
CREATE TABLE IF NOT EXISTS redactions (
|
||||
event_id TEXT NOT NULL,
|
||||
deletes TEXT NOT NULL
|
||||
redacts TEXT NOT NULL,
|
||||
CONSTRAINT ev_uniq UNIQUE (event_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS deletions_event_id ON deletions (event_id);
|
||||
CREATE INDEX IF NOT EXISTS deletions_deletes ON deletions (deletes);
|
||||
CREATE INDEX IF NOT EXISTS redactions_event_id ON redactions (event_id);
|
||||
CREATE INDEX IF NOT EXISTS redactions_redacts ON redactions (redacts);
|
||||
|
||||
ALTER TABLE room_ops_levels ADD COLUMN delete_level INTEGER;
|
||||
ALTER TABLE room_ops_levels ADD COLUMN redact_level INTEGER;
|
||||
|
||||
PRAGMA user_version = 4;
|
||||
|
|
|
@ -151,7 +151,7 @@ CREATE TABLE IF NOT EXISTS room_ops_levels(
|
|||
room_id TEXT NOT NULL,
|
||||
ban_level INTEGER,
|
||||
kick_level INTEGER,
|
||||
delete_level INTEGER
|
||||
redact_level INTEGER
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS room_ops_levels_event_id ON room_ops_levels(event_id);
|
||||
|
|
8
synapse/storage/schema/redactions.sql
Normal file
8
synapse/storage/schema/redactions.sql
Normal file
|
@ -0,0 +1,8 @@
|
|||
CREATE TABLE IF NOT EXISTS redactions (
|
||||
event_id TEXT NOT NULL,
|
||||
redacts TEXT NOT NULL,
|
||||
CONSTRAINT ev_uniq UNIQUE (event_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS redactions_event_id ON redactions (event_id);
|
||||
CREATE INDEX IF NOT EXISTS redactions_redacts ON redactions (redacts);
|
|
@ -158,7 +158,7 @@ class StreamStore(SQLBaseStore):
|
|||
)
|
||||
|
||||
del_sql = (
|
||||
"SELECT event_id FROM deletions WHERE deletes = e.event_id"
|
||||
"SELECT event_id FROM redactions WHERE redacts = e.event_id"
|
||||
)
|
||||
|
||||
if limit:
|
||||
|
@ -175,14 +175,14 @@ class StreamStore(SQLBaseStore):
|
|||
return
|
||||
|
||||
sql = (
|
||||
"SELECT *, (%(deleted)s) AS deleted FROM events AS e WHERE "
|
||||
"SELECT *, (%(redacted)s) AS redacted FROM events AS e WHERE "
|
||||
"((room_id IN (%(current)s)) OR "
|
||||
"(event_id IN (%(invites)s))) "
|
||||
"AND e.stream_ordering > ? AND e.stream_ordering <= ? "
|
||||
"AND e.outlier = 0 "
|
||||
"ORDER BY stream_ordering ASC LIMIT %(limit)d "
|
||||
) % {
|
||||
"deleted": del_sql,
|
||||
"redacted": del_sql,
|
||||
"current": current_room_membership_sql,
|
||||
"invites": membership_sql,
|
||||
"limit": limit
|
||||
|
@ -230,15 +230,15 @@ class StreamStore(SQLBaseStore):
|
|||
limit_str = ""
|
||||
|
||||
del_sql = (
|
||||
"SELECT event_id FROM deletions WHERE deletes = events.event_id"
|
||||
"SELECT event_id FROM redactions WHERE redacts = events.event_id"
|
||||
)
|
||||
|
||||
sql = (
|
||||
"SELECT *, (%(deleted)s) AS deleted FROM events "
|
||||
"SELECT *, (%(redacted)s) AS redacted FROM events "
|
||||
"WHERE outlier = 0 AND room_id = ? AND %(bounds)s "
|
||||
"ORDER BY topological_ordering %(order)s, stream_ordering %(order)s %(limit)s "
|
||||
) % {
|
||||
"deleted": del_sql,
|
||||
"redacted": del_sql,
|
||||
"bounds": bounds,
|
||||
"order": order,
|
||||
"limit": limit_str
|
||||
|
@ -272,15 +272,15 @@ class StreamStore(SQLBaseStore):
|
|||
# TODO (erikj): Handle compressed feedback
|
||||
|
||||
del_sql = (
|
||||
"SELECT event_id FROM deletions WHERE deletes = events.event_id"
|
||||
"SELECT event_id FROM redactions WHERE redacts = events.event_id"
|
||||
)
|
||||
|
||||
sql = (
|
||||
"SELECT *, (%(deleted)s) AS deleted FROM events "
|
||||
"SELECT *, (%(redacted)s) AS redacted FROM events "
|
||||
"WHERE room_id = ? AND stream_ordering <= ? "
|
||||
"ORDER BY topological_ordering DESC, stream_ordering DESC LIMIT ? "
|
||||
) % {
|
||||
"deleted": del_sql,
|
||||
"redacted": del_sql,
|
||||
}
|
||||
|
||||
rows = yield self._execute_and_decode(
|
||||
|
|
Loading…
Reference in a new issue