From 489a4cd1cf43f930e5d8fe27a08e02f975944c2d Mon Sep 17 00:00:00 2001 From: Mark Haines <mark.haines@matrix.org> Date: Mon, 21 Dec 2015 21:10:41 +0000 Subject: Add top level filtering by room id --- synapse/api/filtering.py | 63 +++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 33 deletions(-) (limited to 'synapse/api') diff --git a/synapse/api/filtering.py b/synapse/api/filtering.py index bc03d6c287..35faa53746 100644 --- a/synapse/api/filtering.py +++ b/synapse/api/filtering.py @@ -62,10 +62,24 @@ class Filtering(object): self._check_definition(user_filter_json[key]) if "room" in user_filter_json: + self._check_definition_room_lists(user_filter_json["room"]) for key in room_level_definitions: if key in user_filter_json["room"]: self._check_definition(user_filter_json["room"][key]) + def _check_definition_room_lists(self, definition): + """Check that "rooms" and "not_rooms" are lists of room ids if they + are present + """ + # check rooms are valid room IDs + room_id_keys = ["rooms", "not_rooms"] + for key in room_id_keys: + if key in definition: + if type(definition[key]) != list: + raise SynapseError(400, "Expected %s to be a list." % key) + for room_id in definition[key]: + RoomID.from_string(room_id) + def _check_definition(self, definition): """Check if the provided definition is valid. @@ -85,14 +99,7 @@ class Filtering(object): 400, "Expected JSON object, not %s" % (definition,) ) - # check rooms are valid room IDs - room_id_keys = ["rooms", "not_rooms"] - for key in room_id_keys: - if key in definition: - if type(definition[key]) != list: - raise SynapseError(400, "Expected %s to be a list." % key) - for room_id in definition[key]: - RoomID.from_string(room_id) + self._check_definition_room_lists(definition) # check senders are valid user IDs user_id_keys = ["senders", "not_senders"] @@ -119,29 +126,19 @@ class FilterCollection(object): def __init__(self, filter_json): self.filter_json = filter_json - self.room_timeline_filter = Filter( - self.filter_json.get("room", {}).get("timeline", {}) - ) + room_filter_json = self.filter_json.get("room", {}) - self.room_state_filter = Filter( - self.filter_json.get("room", {}).get("state", {}) - ) + self.room_filter = Filter({ + k: v for k, v in room_filter_json.items() + if k in ("rooms", "not_rooms") + }) - self.room_ephemeral_filter = Filter( - self.filter_json.get("room", {}).get("ephemeral", {}) - ) - - self.room_account_data = Filter( - self.filter_json.get("room", {}).get("account_data", {}) - ) - - self.presence_filter = Filter( - self.filter_json.get("presence", {}) - ) - - self.account_data = Filter( - self.filter_json.get("account_data", {}) - ) + self.room_timeline_filter = Filter(room_filter_json.get("timeline", {})) + self.room_state_filter = Filter(room_filter_json.get("state", {})) + self.room_ephemeral_filter = Filter(room_filter_json.get("ephemeral", {})) + self.room_account_data = Filter(room_filter_json.get("account_data", {})) + self.presence_filter = Filter(self.filter_json.get("presence", {})) + self.account_data = Filter(self.filter_json.get("account_data", {})) self.include_leave = self.filter_json.get("room", {}).get( "include_leave", False @@ -163,16 +160,16 @@ class FilterCollection(object): return self.account_data.filter(events) def filter_room_state(self, events): - return self.room_state_filter.filter(events) + return self.room_state_filter.filter(self.room_filter.filter(events)) def filter_room_timeline(self, events): - return self.room_timeline_filter.filter(events) + return self.room_timeline_filter.filter(self.room_filter.filter(events)) def filter_room_ephemeral(self, events): - return self.room_ephemeral_filter.filter(events) + return self.room_ephemeral_filter.filter(self.room_filter.filter(events)) def filter_room_account_data(self, events): - return self.room_account_data.filter(events) + return self.room_account_data.filter(self.room_filter.filter(events)) class Filter(object): -- cgit 1.5.1 From 45a9e0ae0c9a4c55d4648802fefe96cc2933304f Mon Sep 17 00:00:00 2001 From: Mark Haines <mark.haines@matrix.org> Date: Tue, 22 Dec 2015 10:25:46 +0000 Subject: Allow guest access if the user provides a list of rooms in the filter --- synapse/api/filtering.py | 12 ++++++++++++ synapse/handlers/sync.py | 1 + synapse/rest/client/v2_alpha/sync.py | 10 +++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) (limited to 'synapse/api') diff --git a/synapse/api/filtering.py b/synapse/api/filtering.py index 35faa53746..8c8c7b642e 100644 --- a/synapse/api/filtering.py +++ b/synapse/api/filtering.py @@ -144,6 +144,9 @@ class FilterCollection(object): "include_leave", False ) + def list_rooms(self): + return self.room_filter.list_rooms() + def timeline_limit(self): return self.room_timeline_filter.limit() @@ -176,6 +179,15 @@ class Filter(object): def __init__(self, filter_json): self.filter_json = filter_json + def list_rooms(self): + """The list of room_id strings this filter restricts the output to + or None if the this filter doesn't list the room ids. + """ + if "rooms" in self.filter_json: + return list(set(self.filter_json["rooms"])) + else: + return None + def check(self, event): """Checks whether the filter matches the given event. diff --git a/synapse/handlers/sync.py b/synapse/handlers/sync.py index 7088c20cb4..75ef742328 100644 --- a/synapse/handlers/sync.py +++ b/synapse/handlers/sync.py @@ -29,6 +29,7 @@ logger = logging.getLogger(__name__) SyncConfig = collections.namedtuple("SyncConfig", [ "user", + "is_guest", "filter", ]) diff --git a/synapse/rest/client/v2_alpha/sync.py b/synapse/rest/client/v2_alpha/sync.py index 697df03dda..35a70ffad1 100644 --- a/synapse/rest/client/v2_alpha/sync.py +++ b/synapse/rest/client/v2_alpha/sync.py @@ -85,7 +85,9 @@ class SyncRestServlet(RestServlet): @defer.inlineCallbacks def on_GET(self, request): - user, token_id, _ = yield self.auth.get_user_by_req(request) + user, token_id, is_guest = yield self.auth.get_user_by_req( + request, allow_guest=True + ) timeout = parse_integer(request, "timeout", default=0) since = parse_string(request, "since") @@ -118,8 +120,14 @@ class SyncRestServlet(RestServlet): except: filter = FilterCollection({}) + if is_guest and filter.list_rooms() is None: + raise SynapseError( + 400, "Guest users must provide a list of rooms in the filter" + ) + sync_config = SyncConfig( user=user, + is_guest=is_guest, filter=filter, ) -- cgit 1.5.1 From 0ee01383252cafd30ed92e3b655847d07cacee3a Mon Sep 17 00:00:00 2001 From: Mark Haines <mark.haines@matrix.org> Date: Tue, 22 Dec 2015 15:49:32 +0000 Subject: Include the list of bad room ids in the error --- synapse/api/errors.py | 16 ++++++++++++++++ synapse/handlers/sync.py | 10 ++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) (limited to 'synapse/api') diff --git a/synapse/api/errors.py b/synapse/api/errors.py index d4037b3d55..8bc7b9e6db 100644 --- a/synapse/api/errors.py +++ b/synapse/api/errors.py @@ -120,6 +120,22 @@ class AuthError(SynapseError): super(AuthError, self).__init__(*args, **kwargs) +class GuestAccessError(AuthError): + """An error raised when a there is a problem with a guest user accessing + a room""" + + def __init__(self, rooms, *args, **kwargs): + self.rooms = rooms + super(GuestAccessError, self).__init__(*args, **kwargs) + + def error_dict(self): + return cs_error( + self.msg, + self.errcode, + rooms=self.rooms, + ) + + class EventSizeError(SynapseError): """An error raised when an event is too big.""" diff --git a/synapse/handlers/sync.py b/synapse/handlers/sync.py index 38c185cd54..feea407ea2 100644 --- a/synapse/handlers/sync.py +++ b/synapse/handlers/sync.py @@ -16,7 +16,7 @@ from ._base import BaseHandler from synapse.api.constants import Membership, EventTypes -from synapse.api.errors import AuthError +from synapse.api.errors import GuestAccessError from synapse.util import unwrapFirstError from twisted.internet import defer @@ -139,10 +139,16 @@ class SyncHandler(BaseHandler): """ if sync_config.is_guest: + bad_rooms = [] for room_id in sync_config.filter.list_rooms(): world_readable = yield self._is_world_readable(room_id) if not world_readable: - raise AuthError(403, "Guest access not allowed") + bad_rooms.append(room_id) + + if bad_rooms: + raise GuestAccessError( + bad_rooms, 403, "Guest access not allowed" + ) if timeout == 0 or since_token is None or full_state: # we are going to return immediately, so don't bother calling -- cgit 1.5.1