mirror of
https://github.com/element-hq/synapse
synced 2024-09-04 18:20:07 +00:00
Amalgamate all power levels.
Remove concept of reqired power levels, something similiar can be done using the new power level event.
This commit is contained in:
parent
233969bb58
commit
351c64e99e
8 changed files with 103 additions and 396 deletions
|
@ -21,8 +21,8 @@ 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, RoomRedactionEvent,
|
RoomMemberEvent, RoomPowerLevelsEvent, RoomRedactionEvent,
|
||||||
RoomJoinRulesEvent, RoomOpsPowerLevelsEvent, InviteJoinEvent,
|
RoomJoinRulesEvent, InviteJoinEvent,
|
||||||
RoomCreateEvent, RoomSendEventLevelEvent, RoomAddStateLevelEvent,
|
RoomCreateEvent,
|
||||||
)
|
)
|
||||||
from synapse.util.logutils import log_function
|
from synapse.util.logutils import log_function
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ class Auth(object):
|
||||||
if event.old_state_events is None:
|
if event.old_state_events is None:
|
||||||
# Oh, we don't know what the state of the room was, so we
|
# Oh, we don't know what the state of the room was, so we
|
||||||
# are trusting that this is allowed (at least for now)
|
# are trusting that this is allowed (at least for now)
|
||||||
|
logger.warn("Trusting event: %s", event.event_id)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if hasattr(event, "outlier") and event.outlier is True:
|
if hasattr(event, "outlier") and event.outlier is True:
|
||||||
|
@ -64,7 +65,7 @@ class Auth(object):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if event.type == RoomMemberEvent.TYPE:
|
if event.type == RoomMemberEvent.TYPE:
|
||||||
self._can_replace_state(event)
|
self._can_send_event(event)
|
||||||
allowed = self.is_membership_change_allowed(event)
|
allowed = self.is_membership_change_allowed(event)
|
||||||
if allowed:
|
if allowed:
|
||||||
logger.debug("Allowing! %s", event)
|
logger.debug("Allowing! %s", event)
|
||||||
|
@ -72,16 +73,7 @@ class Auth(object):
|
||||||
logger.debug("Denying! %s", event)
|
logger.debug("Denying! %s", event)
|
||||||
return allowed
|
return allowed
|
||||||
|
|
||||||
if not event.type == InviteJoinEvent.TYPE:
|
self._can_send_event(event)
|
||||||
self.check_event_sender_in_room(event)
|
|
||||||
|
|
||||||
if is_state:
|
|
||||||
# TODO (erikj): This really only should be called for *new*
|
|
||||||
# state
|
|
||||||
self._can_add_state(event)
|
|
||||||
self._can_replace_state(event)
|
|
||||||
else:
|
|
||||||
self._can_send_event(event)
|
|
||||||
|
|
||||||
if event.type == RoomPowerLevelsEvent.TYPE:
|
if event.type == RoomPowerLevelsEvent.TYPE:
|
||||||
self._check_power_levels(event)
|
self._check_power_levels(event)
|
||||||
|
@ -239,21 +231,21 @@ class Auth(object):
|
||||||
power_level_event = event.old_state_events.get(key)
|
power_level_event = event.old_state_events.get(key)
|
||||||
level = None
|
level = None
|
||||||
if power_level_event:
|
if power_level_event:
|
||||||
level = power_level_event.content.get(user_id)
|
level = power_level_event.content.get("users", {}).get(user_id)
|
||||||
if not level:
|
if not level:
|
||||||
level = power_level_event.content.get("default", 0)
|
level = power_level_event.content.get("users_default", 0)
|
||||||
|
|
||||||
return level
|
return level
|
||||||
|
|
||||||
def _get_ops_level_from_event_state(self, event):
|
def _get_ops_level_from_event_state(self, event):
|
||||||
key = (RoomOpsPowerLevelsEvent.TYPE, "", )
|
key = (RoomPowerLevelsEvent.TYPE, "", )
|
||||||
ops_event = event.old_state_events.get(key)
|
power_level_event = event.old_state_events.get(key)
|
||||||
|
|
||||||
if ops_event:
|
if power_level_event:
|
||||||
return (
|
return (
|
||||||
ops_event.content.get("ban_level"),
|
power_level_event.content.get("ban", 50),
|
||||||
ops_event.content.get("kick_level"),
|
power_level_event.content.get("kick", 50),
|
||||||
ops_event.content.get("redact_level"),
|
power_level_event.content.get("redact", 50),
|
||||||
)
|
)
|
||||||
return None, None, None,
|
return None, None, None,
|
||||||
|
|
||||||
|
@ -325,13 +317,22 @@ class Auth(object):
|
||||||
|
|
||||||
@log_function
|
@log_function
|
||||||
def _can_send_event(self, event):
|
def _can_send_event(self, event):
|
||||||
key = (RoomSendEventLevelEvent.TYPE, "", )
|
key = (RoomPowerLevelsEvent.TYPE, "", )
|
||||||
send_level_event = event.old_state_events.get(key)
|
send_level_event = event.old_state_events.get(key)
|
||||||
send_level = None
|
send_level = None
|
||||||
if send_level_event:
|
if send_level_event:
|
||||||
send_level = send_level_event.content.get(event.user_id)
|
send_level = send_level_event.content.get("events", {}).get(
|
||||||
|
event.type
|
||||||
|
)
|
||||||
if not send_level:
|
if not send_level:
|
||||||
send_level = send_level_event.content.get("level", 0)
|
if hasattr(event, "state_key"):
|
||||||
|
send_level = send_level_event.content.get(
|
||||||
|
"state_default", 50
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
send_level = send_level_event.content.get(
|
||||||
|
"events_default", 0
|
||||||
|
)
|
||||||
|
|
||||||
if send_level:
|
if send_level:
|
||||||
send_level = int(send_level)
|
send_level = int(send_level)
|
||||||
|
@ -350,85 +351,21 @@ class Auth(object):
|
||||||
|
|
||||||
if user_level < send_level:
|
if user_level < send_level:
|
||||||
raise AuthError(
|
raise AuthError(
|
||||||
403, "You don't have permission to post to the room"
|
403, "You don't have permission to post that to the room"
|
||||||
)
|
)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _can_add_state(self, event):
|
|
||||||
key = (RoomAddStateLevelEvent.TYPE, "", )
|
|
||||||
add_level_event = event.old_state_events.get(key)
|
|
||||||
add_level = None
|
|
||||||
if add_level_event:
|
|
||||||
add_level = add_level_event.content.get(event.user_id)
|
|
||||||
if not add_level:
|
|
||||||
add_level = add_level_event.content.get("level", 0)
|
|
||||||
|
|
||||||
if add_level:
|
|
||||||
add_level = int(add_level)
|
|
||||||
else:
|
|
||||||
add_level = 0
|
|
||||||
|
|
||||||
user_level = self._get_power_level_from_event_state(
|
|
||||||
event,
|
|
||||||
event.user_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
user_level = int(user_level)
|
|
||||||
|
|
||||||
if user_level < add_level:
|
|
||||||
raise AuthError(
|
|
||||||
403, "You don't have permission to add state to the room"
|
|
||||||
)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _can_replace_state(self, event):
|
|
||||||
user_level = self._get_power_level_from_event_state(
|
|
||||||
event,
|
|
||||||
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
|
|
||||||
)
|
|
||||||
|
|
||||||
key = (event.type, event.state_key, )
|
|
||||||
current_state = event.old_state_events.get(key)
|
|
||||||
|
|
||||||
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"
|
|
||||||
)
|
|
||||||
|
|
||||||
def _check_redaction(self, event):
|
def _check_redaction(self, event):
|
||||||
user_level = self._get_power_level_from_event_state(
|
user_level = self._get_power_level_from_event_state(
|
||||||
event,
|
event,
|
||||||
event.user_id,
|
event.user_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
if user_level:
|
|
||||||
user_level = int(user_level)
|
|
||||||
else:
|
|
||||||
user_level = 0
|
|
||||||
|
|
||||||
_, _, redact_level = self._get_ops_level_from_event_state(
|
_, _, redact_level = self._get_ops_level_from_event_state(
|
||||||
event
|
event
|
||||||
)
|
)
|
||||||
|
|
||||||
if not redact_level:
|
|
||||||
redact_level = 50
|
|
||||||
|
|
||||||
if user_level < redact_level:
|
if user_level < redact_level:
|
||||||
raise AuthError(
|
raise AuthError(
|
||||||
403,
|
403,
|
||||||
|
@ -436,14 +373,9 @@ class Auth(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
def _check_power_levels(self, event):
|
def _check_power_levels(self, event):
|
||||||
for k, v in event.content.items():
|
user_list = event.content.get("users", {})
|
||||||
if k == "default":
|
# Validate users
|
||||||
continue
|
for k, v in user_list.items():
|
||||||
|
|
||||||
# FIXME (erikj): We don't want hsob_Ts in content.
|
|
||||||
if k == "hsob_ts":
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.hs.parse_userid(k)
|
self.hs.parse_userid(k)
|
||||||
except:
|
except:
|
||||||
|
@ -459,72 +391,63 @@ class Auth(object):
|
||||||
|
|
||||||
if not current_state:
|
if not current_state:
|
||||||
return
|
return
|
||||||
else:
|
|
||||||
current_state = current_state[0]
|
|
||||||
|
|
||||||
user_level = self._get_power_level_from_event_state(
|
user_level = self._get_power_level_from_event_state(
|
||||||
event,
|
event,
|
||||||
event.user_id,
|
event.user_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
if user_level:
|
# Check other levels:
|
||||||
user_level = int(user_level)
|
levels_to_check = [
|
||||||
else:
|
("users_default", []),
|
||||||
user_level = 0
|
("events_default", []),
|
||||||
|
("ban", []),
|
||||||
|
("redact", []),
|
||||||
|
("kick", []),
|
||||||
|
]
|
||||||
|
|
||||||
old_list = current_state.content
|
old_list = current_state.content.get("users")
|
||||||
|
for user in set(old_list.keys() + user_list.keys()):
|
||||||
|
levels_to_check.append(
|
||||||
|
(user, ["users"])
|
||||||
|
)
|
||||||
|
|
||||||
# FIXME (erikj)
|
old_list = current_state.content.get("events")
|
||||||
old_people = {k: v for k, v in old_list.items() if k.startswith("@")}
|
new_list = event.content.get("events")
|
||||||
new_people = {
|
for ev_id in set(old_list.keys() + new_list.keys()):
|
||||||
k: v for k, v in event.content.items()
|
levels_to_check.append(
|
||||||
if k.startswith("@")
|
(ev_id, ["events"])
|
||||||
}
|
)
|
||||||
|
|
||||||
removed = set(old_people.keys()) - set(new_people.keys())
|
old_state = current_state.content
|
||||||
added = set(new_people.keys()) - set(old_people.keys())
|
new_state = event.content
|
||||||
same = set(old_people.keys()) & set(new_people.keys())
|
|
||||||
|
|
||||||
for r in removed:
|
for level_to_check, dir in levels_to_check:
|
||||||
if int(old_list[r]) > user_level:
|
old_loc = old_state
|
||||||
raise AuthError(
|
for d in dir:
|
||||||
403,
|
old_loc = old_loc.get(d, {})
|
||||||
"You don't have permission to remove user: %s" % (r, )
|
|
||||||
)
|
|
||||||
|
|
||||||
for n in added:
|
new_loc = new_state
|
||||||
if int(event.content[n]) > user_level:
|
for d in dir:
|
||||||
|
new_loc = new_loc.get(d, {})
|
||||||
|
|
||||||
|
if level_to_check in old_loc:
|
||||||
|
old_level = int(old_loc[level_to_check])
|
||||||
|
else:
|
||||||
|
old_level = None
|
||||||
|
|
||||||
|
if level_to_check in new_loc:
|
||||||
|
new_level = int(new_loc[level_to_check])
|
||||||
|
else:
|
||||||
|
new_level = None
|
||||||
|
|
||||||
|
if new_level is not None and old_level is not None:
|
||||||
|
if new_level == old_level:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if old_level > user_level or new_level > user_level:
|
||||||
raise AuthError(
|
raise AuthError(
|
||||||
403,
|
403,
|
||||||
"You don't have permission to add ops level greater "
|
"You don't have permission to add ops level greater "
|
||||||
"than your own"
|
"than your own"
|
||||||
)
|
)
|
||||||
|
|
||||||
for s in same:
|
|
||||||
if int(event.content[s]) != int(old_list[s]):
|
|
||||||
if int(event.content[s]) > user_level:
|
|
||||||
raise AuthError(
|
|
||||||
403,
|
|
||||||
"You don't have permission to add ops level greater "
|
|
||||||
"than your own"
|
|
||||||
)
|
|
||||||
|
|
||||||
if "default" in old_list:
|
|
||||||
old_default = int(old_list["default"])
|
|
||||||
|
|
||||||
if old_default > user_level:
|
|
||||||
raise AuthError(
|
|
||||||
403,
|
|
||||||
"You don't have permission to add ops level greater than "
|
|
||||||
"your own"
|
|
||||||
)
|
|
||||||
|
|
||||||
if "default" in event.content:
|
|
||||||
new_default = int(event.content["default"])
|
|
||||||
|
|
||||||
if new_default > user_level:
|
|
||||||
raise AuthError(
|
|
||||||
403,
|
|
||||||
"You don't have permission to add ops level greater "
|
|
||||||
"than your own"
|
|
||||||
)
|
|
||||||
|
|
|
@ -56,12 +56,12 @@ 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",
|
|
||||||
"age_ts",
|
"age_ts",
|
||||||
"prev_content",
|
"prev_content",
|
||||||
"replaces_state",
|
"replaces_state",
|
||||||
"redacted_because",
|
"redacted_because",
|
||||||
"origin_server_ts",
|
"origin_server_ts",
|
||||||
|
"auth_chains",
|
||||||
]
|
]
|
||||||
|
|
||||||
internal_keys = [
|
internal_keys = [
|
||||||
|
@ -70,7 +70,6 @@ class SynapseEvent(JsonEncodedObject):
|
||||||
"destinations",
|
"destinations",
|
||||||
"origin",
|
"origin",
|
||||||
"outlier",
|
"outlier",
|
||||||
"power_level",
|
|
||||||
"redacted",
|
"redacted",
|
||||||
"prev_events",
|
"prev_events",
|
||||||
"hashes",
|
"hashes",
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
from synapse.api.events.room import (
|
from synapse.api.events.room import (
|
||||||
RoomTopicEvent, MessageEvent, RoomMemberEvent, FeedbackEvent,
|
RoomTopicEvent, MessageEvent, RoomMemberEvent, FeedbackEvent,
|
||||||
InviteJoinEvent, RoomConfigEvent, RoomNameEvent, GenericEvent,
|
InviteJoinEvent, RoomConfigEvent, RoomNameEvent, GenericEvent,
|
||||||
RoomPowerLevelsEvent, RoomJoinRulesEvent, RoomOpsPowerLevelsEvent,
|
RoomPowerLevelsEvent, RoomJoinRulesEvent,
|
||||||
RoomCreateEvent, RoomAddStateLevelEvent, RoomSendEventLevelEvent,
|
RoomCreateEvent,
|
||||||
RoomRedactionEvent,
|
RoomRedactionEvent,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -39,9 +39,6 @@ class EventFactory(object):
|
||||||
RoomPowerLevelsEvent,
|
RoomPowerLevelsEvent,
|
||||||
RoomJoinRulesEvent,
|
RoomJoinRulesEvent,
|
||||||
RoomCreateEvent,
|
RoomCreateEvent,
|
||||||
RoomAddStateLevelEvent,
|
|
||||||
RoomSendEventLevelEvent,
|
|
||||||
RoomOpsPowerLevelsEvent,
|
|
||||||
RoomRedactionEvent,
|
RoomRedactionEvent,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -153,28 +153,6 @@ class RoomPowerLevelsEvent(SynapseStateEvent):
|
||||||
def get_content_template(self):
|
def get_content_template(self):
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
class RoomAddStateLevelEvent(SynapseStateEvent):
|
|
||||||
TYPE = "m.room.add_state_level"
|
|
||||||
|
|
||||||
def get_content_template(self):
|
|
||||||
return {}
|
|
||||||
|
|
||||||
|
|
||||||
class RoomSendEventLevelEvent(SynapseStateEvent):
|
|
||||||
TYPE = "m.room.send_event_level"
|
|
||||||
|
|
||||||
def get_content_template(self):
|
|
||||||
return {}
|
|
||||||
|
|
||||||
|
|
||||||
class RoomOpsPowerLevelsEvent(SynapseStateEvent):
|
|
||||||
TYPE = "m.room.ops_levels"
|
|
||||||
|
|
||||||
def get_content_template(self):
|
|
||||||
return {}
|
|
||||||
|
|
||||||
|
|
||||||
class RoomAliasesEvent(SynapseStateEvent):
|
class RoomAliasesEvent(SynapseStateEvent):
|
||||||
TYPE = "m.room.aliases"
|
TYPE = "m.room.aliases"
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
|
|
||||||
from .room import (
|
from .room import (
|
||||||
RoomMemberEvent, RoomJoinRulesEvent, RoomPowerLevelsEvent,
|
RoomMemberEvent, RoomJoinRulesEvent, RoomPowerLevelsEvent,
|
||||||
RoomAddStateLevelEvent, RoomSendEventLevelEvent, RoomOpsPowerLevelsEvent,
|
|
||||||
RoomAliasesEvent, RoomCreateEvent,
|
RoomAliasesEvent, RoomCreateEvent,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -52,17 +51,17 @@ def _prune_event_or_pdu(event_type, event):
|
||||||
elif event_type == RoomJoinRulesEvent.TYPE:
|
elif event_type == RoomJoinRulesEvent.TYPE:
|
||||||
add_fields("join_rule")
|
add_fields("join_rule")
|
||||||
elif event_type == RoomPowerLevelsEvent.TYPE:
|
elif event_type == RoomPowerLevelsEvent.TYPE:
|
||||||
# TODO: Actually check these are valid user_ids etc.
|
add_fields(
|
||||||
add_fields("default")
|
"users",
|
||||||
for k, v in event.content.items():
|
"users_default",
|
||||||
if k.startswith("@") and isinstance(v, (int, long)):
|
"events",
|
||||||
new_content[k] = v
|
"events_default",
|
||||||
elif event_type == RoomAddStateLevelEvent.TYPE:
|
"events_default",
|
||||||
add_fields("level")
|
"state_default",
|
||||||
elif event_type == RoomSendEventLevelEvent.TYPE:
|
"ban",
|
||||||
add_fields("level")
|
"kick",
|
||||||
elif event_type == RoomOpsPowerLevelsEvent.TYPE:
|
"redact",
|
||||||
add_fields("kick_level", "ban_level", "redact_level")
|
)
|
||||||
elif event_type == RoomAliasesEvent.TYPE:
|
elif event_type == RoomAliasesEvent.TYPE:
|
||||||
add_fields("aliases")
|
add_fields("aliases")
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,7 @@ from synapse.api.constants import Membership, JoinRules
|
||||||
from synapse.api.errors import StoreError, SynapseError
|
from synapse.api.errors import StoreError, SynapseError
|
||||||
from synapse.api.events.room import (
|
from synapse.api.events.room import (
|
||||||
RoomMemberEvent, RoomCreateEvent, RoomPowerLevelsEvent,
|
RoomMemberEvent, RoomCreateEvent, RoomPowerLevelsEvent,
|
||||||
RoomJoinRulesEvent, RoomAddStateLevelEvent, RoomTopicEvent,
|
RoomTopicEvent, RoomNameEvent, RoomJoinRulesEvent,
|
||||||
RoomSendEventLevelEvent, RoomOpsPowerLevelsEvent, RoomNameEvent,
|
|
||||||
)
|
)
|
||||||
from synapse.util import stringutils
|
from synapse.util import stringutils
|
||||||
from ._base import BaseHandler
|
from ._base import BaseHandler
|
||||||
|
@ -139,7 +138,6 @@ class RoomCreationHandler(BaseHandler):
|
||||||
etype=RoomNameEvent.TYPE,
|
etype=RoomNameEvent.TYPE,
|
||||||
room_id=room_id,
|
room_id=room_id,
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
required_power_level=50,
|
|
||||||
content={"name": name},
|
content={"name": name},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -151,7 +149,6 @@ class RoomCreationHandler(BaseHandler):
|
||||||
etype=RoomTopicEvent.TYPE,
|
etype=RoomTopicEvent.TYPE,
|
||||||
room_id=room_id,
|
room_id=room_id,
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
required_power_level=50,
|
|
||||||
content={"topic": topic},
|
content={"topic": topic},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -196,7 +193,6 @@ class RoomCreationHandler(BaseHandler):
|
||||||
event_keys = {
|
event_keys = {
|
||||||
"room_id": room_id,
|
"room_id": room_id,
|
||||||
"user_id": creator.to_string(),
|
"user_id": creator.to_string(),
|
||||||
"required_power_level": 100,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def create(etype, **content):
|
def create(etype, **content):
|
||||||
|
@ -213,7 +209,21 @@ class RoomCreationHandler(BaseHandler):
|
||||||
|
|
||||||
power_levels_event = self.event_factory.create_event(
|
power_levels_event = self.event_factory.create_event(
|
||||||
etype=RoomPowerLevelsEvent.TYPE,
|
etype=RoomPowerLevelsEvent.TYPE,
|
||||||
content={creator.to_string(): 100, "default": 0},
|
content={
|
||||||
|
"users": {
|
||||||
|
creator.to_string(): 100,
|
||||||
|
},
|
||||||
|
"users_default": 0,
|
||||||
|
"events": {
|
||||||
|
RoomNameEvent.TYPE: 100,
|
||||||
|
RoomPowerLevelsEvent.TYPE: 100,
|
||||||
|
},
|
||||||
|
"events_default": 0,
|
||||||
|
"state_default": 50,
|
||||||
|
"ban": 50,
|
||||||
|
"kick": 50,
|
||||||
|
"redact": 50
|
||||||
|
},
|
||||||
**event_keys
|
**event_keys
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -223,30 +233,10 @@ class RoomCreationHandler(BaseHandler):
|
||||||
join_rule=join_rule,
|
join_rule=join_rule,
|
||||||
)
|
)
|
||||||
|
|
||||||
add_state_event = create(
|
|
||||||
etype=RoomAddStateLevelEvent.TYPE,
|
|
||||||
level=100,
|
|
||||||
)
|
|
||||||
|
|
||||||
send_event = create(
|
|
||||||
etype=RoomSendEventLevelEvent.TYPE,
|
|
||||||
level=0,
|
|
||||||
)
|
|
||||||
|
|
||||||
ops = create(
|
|
||||||
etype=RoomOpsPowerLevelsEvent.TYPE,
|
|
||||||
ban_level=50,
|
|
||||||
kick_level=50,
|
|
||||||
redact_level=50,
|
|
||||||
)
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
creation_event,
|
creation_event,
|
||||||
power_levels_event,
|
power_levels_event,
|
||||||
join_rules_event,
|
join_rules_event,
|
||||||
add_state_event,
|
|
||||||
send_event,
|
|
||||||
ops,
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -388,16 +378,6 @@ class RoomMemberHandler(BaseHandler):
|
||||||
else:
|
else:
|
||||||
# This is not a JOIN, so we can handle it normally.
|
# This is not a JOIN, so we can handle it normally.
|
||||||
|
|
||||||
# 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({})
|
||||||
|
|
|
@ -17,13 +17,9 @@ from twisted.internet import defer
|
||||||
|
|
||||||
from synapse.api.events.room import (
|
from synapse.api.events.room import (
|
||||||
RoomMemberEvent, RoomTopicEvent, FeedbackEvent,
|
RoomMemberEvent, RoomTopicEvent, FeedbackEvent,
|
||||||
# RoomConfigEvent,
|
|
||||||
RoomNameEvent,
|
RoomNameEvent,
|
||||||
RoomJoinRulesEvent,
|
RoomJoinRulesEvent,
|
||||||
RoomPowerLevelsEvent,
|
RoomPowerLevelsEvent,
|
||||||
RoomAddStateLevelEvent,
|
|
||||||
RoomSendEventLevelEvent,
|
|
||||||
RoomOpsPowerLevelsEvent,
|
|
||||||
RoomRedactionEvent,
|
RoomRedactionEvent,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -166,14 +162,6 @@ class DataStore(RoomMemberStore, RoomStore,
|
||||||
self._store_room_topic_txn(txn, event)
|
self._store_room_topic_txn(txn, event)
|
||||||
elif event.type == RoomJoinRulesEvent.TYPE:
|
elif event.type == RoomJoinRulesEvent.TYPE:
|
||||||
self._store_join_rule(txn, event)
|
self._store_join_rule(txn, event)
|
||||||
elif event.type == RoomPowerLevelsEvent.TYPE:
|
|
||||||
self._store_power_levels(txn, event)
|
|
||||||
elif event.type == RoomAddStateLevelEvent.TYPE:
|
|
||||||
self._store_add_state_level(txn, event)
|
|
||||||
elif event.type == RoomSendEventLevelEvent.TYPE:
|
|
||||||
self._store_send_event_level(txn, event)
|
|
||||||
elif event.type == RoomOpsPowerLevelsEvent.TYPE:
|
|
||||||
self._store_ops_level(txn, event)
|
|
||||||
elif event.type == RoomRedactionEvent.TYPE:
|
elif event.type == RoomRedactionEvent.TYPE:
|
||||||
self._store_redaction(txn, event)
|
self._store_redaction(txn, event)
|
||||||
|
|
||||||
|
|
|
@ -148,85 +148,6 @@ class RoomStore(SQLBaseStore):
|
||||||
else:
|
else:
|
||||||
defer.returnValue(None)
|
defer.returnValue(None)
|
||||||
|
|
||||||
def get_power_level(self, room_id, user_id):
|
|
||||||
return self.runInteraction(
|
|
||||||
"get_power_level",
|
|
||||||
self._get_power_level,
|
|
||||||
room_id, user_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
def _get_power_level(self, txn, room_id, user_id):
|
|
||||||
sql = (
|
|
||||||
"SELECT level FROM room_power_levels as r "
|
|
||||||
"INNER JOIN current_state_events as c "
|
|
||||||
"ON r.event_id = c.event_id "
|
|
||||||
"WHERE c.room_id = ? AND r.user_id = ? "
|
|
||||||
)
|
|
||||||
|
|
||||||
rows = txn.execute(sql, (room_id, user_id,)).fetchall()
|
|
||||||
|
|
||||||
if len(rows) == 1:
|
|
||||||
return rows[0][0]
|
|
||||||
|
|
||||||
sql = (
|
|
||||||
"SELECT level FROM room_default_levels as r "
|
|
||||||
"INNER JOIN current_state_events as c "
|
|
||||||
"ON r.event_id = c.event_id "
|
|
||||||
"WHERE c.room_id = ? "
|
|
||||||
)
|
|
||||||
|
|
||||||
rows = txn.execute(sql, (room_id,)).fetchall()
|
|
||||||
|
|
||||||
if len(rows) == 1:
|
|
||||||
return rows[0][0]
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_ops_levels(self, room_id):
|
|
||||||
return self.runInteraction(
|
|
||||||
"get_ops_levels",
|
|
||||||
self._get_ops_levels,
|
|
||||||
room_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
def _get_ops_levels(self, txn, room_id):
|
|
||||||
sql = (
|
|
||||||
"SELECT ban_level, kick_level, redact_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 = ? "
|
|
||||||
)
|
|
||||||
|
|
||||||
rows = txn.execute(sql, (room_id,)).fetchall()
|
|
||||||
|
|
||||||
if len(rows) == 1:
|
|
||||||
return OpsLevel(rows[0][0], rows[0][1], rows[0][2])
|
|
||||||
else:
|
|
||||||
return OpsLevel(None, None)
|
|
||||||
|
|
||||||
def get_add_state_level(self, room_id):
|
|
||||||
return self._get_level_from_table("room_add_state_levels", room_id)
|
|
||||||
|
|
||||||
def get_send_event_level(self, room_id):
|
|
||||||
return self._get_level_from_table("room_send_event_levels", room_id)
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def _get_level_from_table(self, table, room_id):
|
|
||||||
sql = (
|
|
||||||
"SELECT level FROM %(table)s as r "
|
|
||||||
"INNER JOIN current_state_events as c "
|
|
||||||
"ON r.event_id = c.event_id "
|
|
||||||
"WHERE c.room_id = ? "
|
|
||||||
) % {"table": table}
|
|
||||||
|
|
||||||
rows = yield self._execute(None, sql, room_id)
|
|
||||||
|
|
||||||
if len(rows) == 1:
|
|
||||||
defer.returnValue(rows[0][0])
|
|
||||||
else:
|
|
||||||
defer.returnValue(None)
|
|
||||||
|
|
||||||
def _store_room_topic_txn(self, txn, event):
|
def _store_room_topic_txn(self, txn, event):
|
||||||
self._simple_insert_txn(
|
self._simple_insert_txn(
|
||||||
txn,
|
txn,
|
||||||
|
@ -260,84 +181,6 @@ class RoomStore(SQLBaseStore):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
def _store_power_levels(self, txn, event):
|
|
||||||
for user_id, level in event.content.items():
|
|
||||||
if user_id == "default":
|
|
||||||
self._simple_insert_txn(
|
|
||||||
txn,
|
|
||||||
"room_default_levels",
|
|
||||||
{
|
|
||||||
"event_id": event.event_id,
|
|
||||||
"room_id": event.room_id,
|
|
||||||
"level": level,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
self._simple_insert_txn(
|
|
||||||
txn,
|
|
||||||
"room_power_levels",
|
|
||||||
{
|
|
||||||
"event_id": event.event_id,
|
|
||||||
"room_id": event.room_id,
|
|
||||||
"user_id": user_id,
|
|
||||||
"level": level
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
def _store_default_level(self, txn, event):
|
|
||||||
self._simple_insert_txn(
|
|
||||||
txn,
|
|
||||||
"room_default_levels",
|
|
||||||
{
|
|
||||||
"event_id": event.event_id,
|
|
||||||
"room_id": event.room_id,
|
|
||||||
"level": event.content["default_level"],
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
def _store_add_state_level(self, txn, event):
|
|
||||||
self._simple_insert_txn(
|
|
||||||
txn,
|
|
||||||
"room_add_state_levels",
|
|
||||||
{
|
|
||||||
"event_id": event.event_id,
|
|
||||||
"room_id": event.room_id,
|
|
||||||
"level": event.content["level"],
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
def _store_send_event_level(self, txn, event):
|
|
||||||
self._simple_insert_txn(
|
|
||||||
txn,
|
|
||||||
"room_send_event_levels",
|
|
||||||
{
|
|
||||||
"event_id": event.event_id,
|
|
||||||
"room_id": event.room_id,
|
|
||||||
"level": event.content["level"],
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
def _store_ops_level(self, txn, event):
|
|
||||||
content = {
|
|
||||||
"event_id": event.event_id,
|
|
||||||
"room_id": event.room_id,
|
|
||||||
}
|
|
||||||
|
|
||||||
if "kick_level" in event.content:
|
|
||||||
content["kick_level"] = event.content["kick_level"]
|
|
||||||
|
|
||||||
if "ban_level" in event.content:
|
|
||||||
content["ban_level"] = event.content["ban_level"]
|
|
||||||
|
|
||||||
if "redact_level" in event.content:
|
|
||||||
content["redact_level"] = event.content["redact_level"]
|
|
||||||
|
|
||||||
self._simple_insert_txn(
|
|
||||||
txn,
|
|
||||||
"room_ops_levels",
|
|
||||||
content,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class RoomsTable(Table):
|
class RoomsTable(Table):
|
||||||
table_name = "rooms"
|
table_name = "rooms"
|
||||||
|
|
Loading…
Reference in a new issue