diff --git a/synapse/api/auth.py b/synapse/api/auth.py index 8f32191b57..fb14d9a2b3 100644 --- a/synapse/api/auth.py +++ b/synapse/api/auth.py @@ -19,7 +19,9 @@ 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 +from synapse.api.events.room import ( + RoomMemberEvent, RoomPowerLevelsEvent, RoomDeletionEvent, +) from synapse.util.logutils import log_function import logging @@ -70,6 +72,9 @@ class Auth(object): if event.type == RoomPowerLevelsEvent.TYPE: yield self._check_power_levels(event) + if event.type == RoomDeletionEvent.TYPE: + yield self._check_deletion(event) + defer.returnValue(True) else: raise AuthError(500, "Unknown event: %s" % event) @@ -170,7 +175,7 @@ class Auth(object): event.room_id, event.user_id, ) - _, kick_level = yield self.store.get_ops_levels(event.room_id) + _, kick_level, _ = yield self.store.get_ops_levels(event.room_id) if kick_level: kick_level = int(kick_level) @@ -187,7 +192,7 @@ class Auth(object): event.user_id, ) - ban_level, _ = yield self.store.get_ops_levels(event.room_id) + ban_level, _, _ = yield self.store.get_ops_levels(event.room_id) if ban_level: ban_level = int(ban_level) @@ -321,6 +326,29 @@ class Auth(object): "You don't have permission to change that state" ) + @defer.inlineCallbacks + def _check_deletion(self, event): + user_level = yield self.store.get_power_level( + event.room_id, + event.user_id, + ) + + if user_level: + user_level = int(user_level) + else: + user_level = 0 + + _, _, delete_level = yield self.store.get_ops_levels(event.room_id) + + if not delete_level: + delete_level = 50 + + if user_level < delete_level: + raise AuthError( + 403, + "You don't have permission to delete events" + ) + @defer.inlineCallbacks def _check_power_levels(self, event): for k, v in event.content.items(): diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index 5bc1280432..18597c694d 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -255,6 +255,7 @@ class RoomCreationHandler(BaseHandler): etype=RoomOpsPowerLevelsEvent.TYPE, ban_level=50, kick_level=50, + delete_level=50, ) return [ diff --git a/synapse/storage/room.py b/synapse/storage/room.py index 5adf8cdf1b..b1239a0f1a 100644 --- a/synapse/storage/room.py +++ b/synapse/storage/room.py @@ -27,7 +27,7 @@ import logging logger = logging.getLogger(__name__) -OpsLevel = collections.namedtuple("OpsLevel", ("ban_level", "kick_level")) +OpsLevel = collections.namedtuple("OpsLevel", ("ban_level", "kick_level", "delete_level")) class RoomStore(SQLBaseStore): @@ -189,7 +189,8 @@ class RoomStore(SQLBaseStore): def _get_ops_levels(self, txn, room_id): sql = ( - "SELECT ban_level, kick_level FROM room_ops_levels as r " + "SELECT ban_level, kick_level, delete_level " + "FROM room_ops_levels as r " "INNER JOIN current_state_events as c " "ON r.event_id = c.event_id " "WHERE c.room_id = ? " @@ -198,7 +199,7 @@ class RoomStore(SQLBaseStore): rows = txn.execute(sql, (room_id,)).fetchall() if len(rows) == 1: - return OpsLevel(rows[0][0], rows[0][1]) + return OpsLevel(rows[0][0], rows[0][1], rows[0][2]) else: return OpsLevel(None, None) @@ -326,6 +327,9 @@ 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"] + self._simple_insert_txn( txn, "room_ops_levels", diff --git a/synapse/storage/schema/delta/v4.sql b/synapse/storage/schema/delta/v4.sql index 2e2635317a..fc8bb5ad84 100644 --- a/synapse/storage/schema/delta/v4.sql +++ b/synapse/storage/schema/delta/v4.sql @@ -5,3 +5,7 @@ CREATE TABLE IF NOT EXISTS deletions ( CREATE INDEX IF NOT EXISTS deletions_event_id ON deletions (event_id); CREATE INDEX IF NOT EXISTS deletions_deletes ON deletions (deletes); + +ALTER TABLE room_ops_levels ADD COLUMN delete_level INTEGER; + +PRAGMA user_version = 4;