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)
@@ -322,6 +327,29 @@ class Auth(object):
)
@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():
if k == "default":
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;
|