Rename deletions to redactions

This commit is contained in:
Erik Johnston 2014-09-24 15:27:59 +01:00
parent 7d9a84a445
commit 70899d3ab2
16 changed files with 77 additions and 74 deletions

View file

@ -20,7 +20,7 @@ from twisted.internet import defer
from synapse.api.constants import Membership, JoinRules from synapse.api.constants import Membership, JoinRules
from synapse.api.errors import AuthError, StoreError, Codes, SynapseError from synapse.api.errors import AuthError, StoreError, Codes, SynapseError
from synapse.api.events.room import ( from synapse.api.events.room import (
RoomMemberEvent, RoomPowerLevelsEvent, RoomDeletionEvent, RoomMemberEvent, RoomPowerLevelsEvent, RoomRedactionEvent,
) )
from synapse.util.logutils import log_function from synapse.util.logutils import log_function
@ -72,8 +72,8 @@ class Auth(object):
if event.type == RoomPowerLevelsEvent.TYPE: if event.type == RoomPowerLevelsEvent.TYPE:
yield self._check_power_levels(event) yield self._check_power_levels(event)
if event.type == RoomDeletionEvent.TYPE: if event.type == RoomRedactionEvent.TYPE:
yield self._check_deletion(event) yield self._check_redaction(event)
defer.returnValue(True) defer.returnValue(True)
else: else:
@ -327,7 +327,7 @@ class Auth(object):
) )
@defer.inlineCallbacks @defer.inlineCallbacks
def _check_deletion(self, event): def _check_redaction(self, event):
user_level = yield self.store.get_power_level( user_level = yield self.store.get_power_level(
event.room_id, event.room_id,
event.user_id, event.user_id,
@ -338,15 +338,15 @@ class Auth(object):
else: else:
user_level = 0 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: if not redact_level:
delete_level = 50 redact_level = 50
if user_level < delete_level: if user_level < redact_level:
raise AuthError( raise AuthError(
403, 403,
"You don't have permission to delete events" "You don't have permission to redact events"
) )
@defer.inlineCallbacks @defer.inlineCallbacks

View file

@ -59,7 +59,7 @@ class SynapseEvent(JsonEncodedObject):
"age_ts", "age_ts",
"prev_content", "prev_content",
"prev_state", "prev_state",
"pruned_because", "redacted_because",
] ]
internal_keys = [ internal_keys = [
@ -70,7 +70,7 @@ class SynapseEvent(JsonEncodedObject):
"origin", "origin",
"outlier", "outlier",
"power_level", "power_level",
"deleted", "redacted",
] ]
required_keys = [ required_keys = [

View file

@ -18,7 +18,7 @@ from synapse.api.events.room import (
InviteJoinEvent, RoomConfigEvent, RoomNameEvent, GenericEvent, InviteJoinEvent, RoomConfigEvent, RoomNameEvent, GenericEvent,
RoomPowerLevelsEvent, RoomJoinRulesEvent, RoomOpsPowerLevelsEvent, RoomPowerLevelsEvent, RoomJoinRulesEvent, RoomOpsPowerLevelsEvent,
RoomCreateEvent, RoomAddStateLevelEvent, RoomSendEventLevelEvent, RoomCreateEvent, RoomAddStateLevelEvent, RoomSendEventLevelEvent,
RoomDeletionEvent, RoomRedactionEvent,
) )
from synapse.util.stringutils import random_string from synapse.util.stringutils import random_string
@ -40,7 +40,7 @@ class EventFactory(object):
RoomAddStateLevelEvent, RoomAddStateLevelEvent,
RoomSendEventLevelEvent, RoomSendEventLevelEvent,
RoomOpsPowerLevelsEvent, RoomOpsPowerLevelsEvent,
RoomDeletionEvent, RoomRedactionEvent,
] ]
def __init__(self, hs): def __init__(self, hs):

View file

@ -182,10 +182,10 @@ class RoomAliasesEvent(SynapseStateEvent):
return {} return {}
class RoomDeletionEvent(SynapseEvent): class RoomRedactionEvent(SynapseEvent):
TYPE = "m.room.deletion" TYPE = "m.room.redaction"
valid_keys = SynapseEvent.valid_keys + ["deletes"] valid_keys = SynapseEvent.valid_keys + ["redacts"]
def get_content_template(self): def get_content_template(self):
return {} return {}

View file

@ -23,7 +23,7 @@ def prune_event(event):
""" Prunes the given event of all keys we don't know about or think could """ Prunes the given event of all keys we don't know about or think could
potentially be dodgy. 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 the user has specified, but we do want to keep necessary information like
type, state_key etc. type, state_key etc.
""" """
@ -55,7 +55,7 @@ def prune_event(event):
elif event.type == RoomSendEventLevelEvent.TYPE: elif event.type == RoomSendEventLevelEvent.TYPE:
add_fields("level") add_fields("level")
elif event.type == RoomOpsPowerLevelsEvent.TYPE: 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: elif event.type == RoomAliasesEvent.TYPE:
add_fields("aliases") add_fields("aliases")

View file

@ -255,7 +255,7 @@ class RoomCreationHandler(BaseHandler):
etype=RoomOpsPowerLevelsEvent.TYPE, etype=RoomOpsPowerLevelsEvent.TYPE,
ban_level=50, ban_level=50,
kick_level=50, kick_level=50,
delete_level=50, redact_level=50,
) )
return [ return [

View file

@ -19,7 +19,7 @@ from twisted.internet import defer
from base import RestServlet, client_path_pattern from base import RestServlet, client_path_pattern
from synapse.api.errors import SynapseError, Codes from synapse.api.errors import SynapseError, Codes
from synapse.streams.config import PaginationConfig 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 from synapse.api.constants import Membership
import json import json
@ -430,9 +430,9 @@ class RoomMembershipRestServlet(RestServlet):
self.txns.store_client_transaction(request, txn_id, response) self.txns.store_client_transaction(request, txn_id, response)
defer.returnValue(response) defer.returnValue(response)
class RoomDeleteEventRestServlet(RestServlet): class RoomRedactEventRestServlet(RestServlet):
def register(self, http_server): 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) register_txn_path(self, PATTERN, http_server)
@defer.inlineCallbacks @defer.inlineCallbacks
@ -441,11 +441,11 @@ class RoomDeleteEventRestServlet(RestServlet):
content = _parse_json(request) content = _parse_json(request)
event = self.event_factory.create_event( event = self.event_factory.create_event(
etype=RoomDeletionEvent.TYPE, etype=RoomRedactionEvent.TYPE,
room_id=urllib.unquote(room_id), room_id=urllib.unquote(room_id),
user_id=user.to_string(), user_id=user.to_string(),
content=content, content=content,
deletes=event_id, redacts=event_id,
) )
msg_handler = self.handlers.message_handler msg_handler = self.handlers.message_handler
@ -520,4 +520,4 @@ def register_servlets(hs, http_server):
PublicRoomListRestServlet(hs).register(http_server) PublicRoomListRestServlet(hs).register(http_server)
RoomStateRestServlet(hs).register(http_server) RoomStateRestServlet(hs).register(http_server)
RoomInitialSyncRestServlet(hs).register(http_server) RoomInitialSyncRestServlet(hs).register(http_server)
RoomDeleteEventRestServlet(hs).register(http_server) RoomRedactEventRestServlet(hs).register(http_server)

View file

@ -24,7 +24,7 @@ from synapse.api.events.room import (
RoomAddStateLevelEvent, RoomAddStateLevelEvent,
RoomSendEventLevelEvent, RoomSendEventLevelEvent,
RoomOpsPowerLevelsEvent, RoomOpsPowerLevelsEvent,
RoomDeletionEvent, RoomRedactionEvent,
) )
from synapse.util.logutils import log_function from synapse.util.logutils import log_function
@ -57,7 +57,7 @@ SCHEMAS = [
"presence", "presence",
"im", "im",
"room_aliases", "room_aliases",
"deletions", "redactions",
] ]
@ -184,8 +184,8 @@ class DataStore(RoomMemberStore, RoomStore,
self._store_send_event_level(txn, event) self._store_send_event_level(txn, event)
elif event.type == RoomOpsPowerLevelsEvent.TYPE: elif event.type == RoomOpsPowerLevelsEvent.TYPE:
self._store_ops_level(txn, event) self._store_ops_level(txn, event)
elif event.type == RoomDeletionEvent.TYPE: elif event.type == RoomRedactionEvent.TYPE:
self._store_deletion(txn, event) self._store_redaction(txn, event)
vals = { vals = {
"topological_ordering": event.depth, "topological_ordering": event.depth,
@ -207,7 +207,7 @@ class DataStore(RoomMemberStore, RoomStore,
unrec = { unrec = {
k: v k: v
for k, v in event.get_full_dict().items() 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) 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( txn.execute(
"INSERT INTO deletions (event_id, deletes) VALUES (?,?) OR IGNORE", "INSERT OR IGNORE INTO redactions "
(event.event_id, event.deletes) "(event_id, redacts) VALUES (?,?)",
(event.event_id, event.redacts)
) )
@defer.inlineCallbacks @defer.inlineCallbacks
def get_current_state(self, room_id, event_type=None, state_key=""): def get_current_state(self, room_id, event_type=None, state_key=""):
del_sql = ( del_sql = (
"SELECT event_id FROM deletions WHERE deletes = e.event_id" "SELECT event_id FROM redactions WHERE redacts = e.event_id"
) )
sql = ( 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 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 " "INNER JOIN state_events as s ON e.event_id = s.event_id "
"WHERE c.room_id = ? " "WHERE c.room_id = ? "
) % { ) % {
"deleted": del_sql, "redacted": del_sql,
} }
if event_type: if event_type:

View file

@ -383,14 +383,14 @@ class SQLBaseStore(object):
prev = self._parse_event_from_row(prevs[0]) prev = self._parse_event_from_row(prevs[0])
ev.prev_content = prev.content ev.prev_content = prev.content
if not hasattr(ev, "deleted"): if not hasattr(ev, "redacted"):
logger.debug("Doesn't have deleted key: %s", ev) logger.debug("Doesn't have redacted key: %s", ev)
ev.deleted = self._has_been_deleted_txn(txn, ev) ev.redacted = self._has_been_redacted_txn(txn, ev)
if ev.deleted: if ev.redacted:
# Get the deletion event. # Get the redaction event.
sql = "SELECT * FROM events WHERE event_id = ?" sql = "SELECT * FROM events WHERE event_id = ?"
txn.execute(sql, (ev.deleted,)) txn.execute(sql, (ev.redacted,))
del_evs = self._parse_events_txn( del_evs = self._parse_events_txn(
txn, self.cursor_to_dict(txn) txn, self.cursor_to_dict(txn)
@ -398,12 +398,12 @@ class SQLBaseStore(object):
if del_evs: if del_evs:
prune_event(ev) prune_event(ev)
ev.pruned_because = del_evs[0] ev.redacted_because = del_evs[0]
return events return events
def _has_been_deleted_txn(self, txn, event): def _has_been_redacted_txn(self, txn, event):
sql = "SELECT event_id FROM deletions WHERE deletes = ?" sql = "SELECT event_id FROM redactions WHERE redacts = ?"
txn.execute(sql, (event.event_id,)) txn.execute(sql, (event.event_id,))
result = txn.fetchone() result = txn.fetchone()
return result[0] if result else None return result[0] if result else None

View file

@ -27,7 +27,7 @@ import logging
logger = logging.getLogger(__name__) 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): class RoomStore(SQLBaseStore):
@ -189,7 +189,7 @@ class RoomStore(SQLBaseStore):
def _get_ops_levels(self, txn, room_id): def _get_ops_levels(self, txn, room_id):
sql = ( sql = (
"SELECT ban_level, kick_level, delete_level " "SELECT ban_level, kick_level, redact_level "
"FROM room_ops_levels as r " "FROM room_ops_levels as r "
"INNER JOIN current_state_events as c " "INNER JOIN current_state_events as c "
"ON r.event_id = c.event_id " "ON r.event_id = c.event_id "
@ -327,8 +327,8 @@ class RoomStore(SQLBaseStore):
if "ban_level" in event.content: if "ban_level" in event.content:
content["ban_level"] = event.content["ban_level"] content["ban_level"] = event.content["ban_level"]
if "delete_level" in event.content: if "redact_level" in event.content:
content["delete_level"] = event.content["delete_level"] content["redact_level"] = event.content["redact_level"]
self._simple_insert_txn( self._simple_insert_txn(
txn, txn,

View file

@ -183,18 +183,18 @@ class RoomMemberStore(SQLBaseStore):
def _get_members_query_txn(self, txn, where_clause, where_values): def _get_members_query_txn(self, txn, where_clause, where_values):
del_sql = ( del_sql = (
"SELECT event_id FROM deletions WHERE deletes = e.event_id" "SELECT event_id FROM redactions WHERE redacts = e.event_id"
) )
sql = ( 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 " "INNER JOIN room_memberships as m "
"ON e.event_id = m.event_id " "ON e.event_id = m.event_id "
"INNER JOIN current_state_events as c " "INNER JOIN current_state_events as c "
"ON m.event_id = c.event_id " "ON m.event_id = c.event_id "
"WHERE %(where)s " "WHERE %(where)s "
) % { ) % {
"deleted": del_sql, "redacted": del_sql,
"where": where_clause, "where": where_clause,
} }

View file

@ -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);

View file

@ -1,11 +1,12 @@
CREATE TABLE IF NOT EXISTS deletions ( CREATE TABLE IF NOT EXISTS redactions (
event_id TEXT NOT NULL, 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 redactions_event_id ON redactions (event_id);
CREATE INDEX IF NOT EXISTS deletions_deletes ON deletions (deletes); 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; PRAGMA user_version = 4;

View file

@ -151,7 +151,7 @@ CREATE TABLE IF NOT EXISTS room_ops_levels(
room_id TEXT NOT NULL, room_id TEXT NOT NULL,
ban_level INTEGER, ban_level INTEGER,
kick_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); CREATE INDEX IF NOT EXISTS room_ops_levels_event_id ON room_ops_levels(event_id);

View 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);

View file

@ -158,7 +158,7 @@ class StreamStore(SQLBaseStore):
) )
del_sql = ( del_sql = (
"SELECT event_id FROM deletions WHERE deletes = e.event_id" "SELECT event_id FROM redactions WHERE redacts = e.event_id"
) )
if limit: if limit:
@ -175,14 +175,14 @@ class StreamStore(SQLBaseStore):
return return
sql = ( 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 " "((room_id IN (%(current)s)) OR "
"(event_id IN (%(invites)s))) " "(event_id IN (%(invites)s))) "
"AND e.stream_ordering > ? AND e.stream_ordering <= ? " "AND e.stream_ordering > ? AND e.stream_ordering <= ? "
"AND e.outlier = 0 " "AND e.outlier = 0 "
"ORDER BY stream_ordering ASC LIMIT %(limit)d " "ORDER BY stream_ordering ASC LIMIT %(limit)d "
) % { ) % {
"deleted": del_sql, "redacted": del_sql,
"current": current_room_membership_sql, "current": current_room_membership_sql,
"invites": membership_sql, "invites": membership_sql,
"limit": limit "limit": limit
@ -230,15 +230,15 @@ class StreamStore(SQLBaseStore):
limit_str = "" limit_str = ""
del_sql = ( del_sql = (
"SELECT event_id FROM deletions WHERE deletes = events.event_id" "SELECT event_id FROM redactions WHERE redacts = events.event_id"
) )
sql = ( sql = (
"SELECT *, (%(deleted)s) AS deleted FROM events " "SELECT *, (%(redacted)s) AS redacted FROM events "
"WHERE outlier = 0 AND room_id = ? AND %(bounds)s " "WHERE outlier = 0 AND room_id = ? AND %(bounds)s "
"ORDER BY topological_ordering %(order)s, stream_ordering %(order)s %(limit)s " "ORDER BY topological_ordering %(order)s, stream_ordering %(order)s %(limit)s "
) % { ) % {
"deleted": del_sql, "redacted": del_sql,
"bounds": bounds, "bounds": bounds,
"order": order, "order": order,
"limit": limit_str "limit": limit_str
@ -272,15 +272,15 @@ class StreamStore(SQLBaseStore):
# TODO (erikj): Handle compressed feedback # TODO (erikj): Handle compressed feedback
del_sql = ( del_sql = (
"SELECT event_id FROM deletions WHERE deletes = events.event_id" "SELECT event_id FROM redactions WHERE redacts = events.event_id"
) )
sql = ( sql = (
"SELECT *, (%(deleted)s) AS deleted FROM events " "SELECT *, (%(redacted)s) AS redacted FROM events "
"WHERE room_id = ? AND stream_ordering <= ? " "WHERE room_id = ? AND stream_ordering <= ? "
"ORDER BY topological_ordering DESC, stream_ordering DESC LIMIT ? " "ORDER BY topological_ordering DESC, stream_ordering DESC LIMIT ? "
) % { ) % {
"deleted": del_sql, "redacted": del_sql,
} }
rows = yield self._execute_and_decode( rows = yield self._execute_and_decode(