Add all the necessary checks to make banning work.

This commit is contained in:
Erik Johnston 2014-09-01 18:24:56 +01:00
parent 3faa2ae78c
commit b8ab9f1c0a
6 changed files with 54 additions and 6 deletions

View File

@ -45,7 +45,10 @@ class Auth(object):
""" """
try: try:
if hasattr(event, "room_id"): if hasattr(event, "room_id"):
is_state = hasattr(event, "state_key")
if event.type == RoomMemberEvent.TYPE: if event.type == RoomMemberEvent.TYPE:
yield self._can_replace_state(event)
allowed = yield self.is_membership_change_allowed(event) allowed = yield self.is_membership_change_allowed(event)
defer.returnValue(allowed) defer.returnValue(allowed)
return return
@ -56,10 +59,11 @@ class Auth(object):
room_id=snapshot.room_id, room_id=snapshot.room_id,
) )
if hasattr(event, "state_key"): if is_state:
# TODO (erikj): This really only should be called for *new* # TODO (erikj): This really only should be called for *new*
# state # state
yield self._can_add_state(event) yield self._can_add_state(event)
yield self._can_replace_state(event)
else: else:
yield self._can_send_event(event) yield self._can_send_event(event)
@ -175,7 +179,7 @@ class Auth(object):
else: else:
ban_level = 5 # FIXME (erikj): What should we do here? ban_level = 5 # FIXME (erikj): What should we do here?
if ban_level < user_level: if user_level < ban_level:
raise AuthError(403, "You don't have permission to ban") raise AuthError(403, "You don't have permission to ban")
else: else:
raise AuthError(500, "Unknown membership %s" % membership) raise AuthError(500, "Unknown membership %s" % membership)
@ -267,3 +271,35 @@ class Auth(object):
) )
defer.returnValue(True) defer.returnValue(True)
@defer.inlineCallbacks
def _can_replace_state(self, event):
current_state = yield self.store.get_current_state(
event.room_id,
event.type,
event.state_key,
)
if current_state:
current_state = current_state[0]
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
logger.debug("Checking power level for %s, %s", event.user_id, user_level)
if current_state and hasattr(current_state, "required_power_level"):
req = current_state.required_power_level
logger.debug("Checked power level for %s, %s", event.user_id, req)
if user_level < req:
raise AuthError(
403,
"You don't have permission to change that state"
)

View File

@ -42,6 +42,7 @@ class SynapseEvent(JsonEncodedObject):
"user_id", # sender/initiator "user_id", # sender/initiator
"content", # HTTP body, JSON "content", # HTTP body, JSON
"state_key", "state_key",
"required_power_level",
] ]
internal_keys = [ internal_keys = [
@ -52,6 +53,7 @@ class SynapseEvent(JsonEncodedObject):
"destinations", "destinations",
"origin", "origin",
"outlier", "outlier",
"power_level",
] ]
required_keys = [ required_keys = [

View File

@ -68,6 +68,7 @@ class Pdu(JsonEncodedObject):
"power_level", "power_level",
"prev_state_id", "prev_state_id",
"prev_state_origin", "prev_state_origin",
"required_power_level",
] ]
internal_keys = [ internal_keys = [

View File

@ -166,7 +166,7 @@ class RoomCreationHandler(BaseRoomHandler):
power_levels_event = create( power_levels_event = create(
etype=RoomPowerLevelsEvent.TYPE, etype=RoomPowerLevelsEvent.TYPE,
**{creator.to_string(): 10} **{creator.to_string(): 10, "default": 0}
) )
join_rule = JoinRules.PUBLIC if is_public else JoinRules.INVITE join_rule = JoinRules.PUBLIC if is_public else JoinRules.INVITE
@ -343,6 +343,16 @@ class RoomMemberHandler(BaseRoomHandler):
if do_auth: if do_auth:
yield self.auth.check(event, snapshot, raises=True) yield self.auth.check(event, snapshot, raises=True)
# If we're banning someone, set a req power level
if event.membership == Membership.BAN:
if not hasattr(event, "required_power_level") or event.required_power_level is None:
# Add some default required_power_level
user_level = yield self.store.get_power_level(
event.room_id,
event.user_id,
)
event.required_power_level = user_level
if prev_state and prev_state.membership == event.membership: if prev_state and prev_state.membership == event.membership:
# double same action, treat this event as a NOOP. # double same action, treat this event as a NOOP.
defer.returnValue({}) defer.returnValue({})

View File

@ -165,8 +165,7 @@ class RoomStore(SQLBaseStore):
rows = txn.execute(sql, (room_id, user_id,)).fetchall() rows = txn.execute(sql, (room_id, user_id,)).fetchall()
if len(rows) == 1: if len(rows) == 1:
defer.returnValue(rows[0][0]) return rows[0][0]
return
sql = ( sql = (
"SELECT level FROM room_default_levels as r " "SELECT level FROM room_default_levels as r "

View File

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