summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--synapse/api/auth.py34
-rw-r--r--synapse/handlers/room.py1
-rw-r--r--synapse/storage/room.py10
-rw-r--r--synapse/storage/schema/delta/v4.sql4
4 files changed, 43 insertions, 6 deletions
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;