Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit be2db93

Browse files
authored
Do not assume that the contents dictionary includes history_visibility. (#8945)
1 parent 0133368 commit be2db93

File tree

9 files changed

+58
-28
lines changed

9 files changed

+58
-28
lines changed

changelog.d/8945.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a bug where 500 errors would be returned if the `m.room_history_visibility` event had invalid content.

synapse/api/auth.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import synapse.types
2424
from synapse import event_auth
2525
from synapse.api.auth_blocking import AuthBlocking
26-
from synapse.api.constants import EventTypes, Membership
26+
from synapse.api.constants import EventTypes, HistoryVisibility, Membership
2727
from synapse.api.errors import (
2828
AuthError,
2929
Codes,
@@ -648,7 +648,8 @@ async def check_user_in_room_or_world_readable(
648648
)
649649
if (
650650
visibility
651-
and visibility.content["history_visibility"] == "world_readable"
651+
and visibility.content.get("history_visibility")
652+
== HistoryVisibility.WORLD_READABLE
652653
):
653654
return Membership.JOIN, None
654655
raise AuthError(

synapse/api/constants.py

+7
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,10 @@ class RoomEncryptionAlgorithms:
160160
class AccountDataTypes:
161161
DIRECT = "m.direct"
162162
IGNORED_USER_LIST = "m.ignored_user_list"
163+
164+
165+
class HistoryVisibility:
166+
INVITED = "invited"
167+
JOINED = "joined"
168+
SHARED = "shared"
169+
WORLD_READABLE = "world_readable"

synapse/handlers/room.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
from synapse.api.constants import (
2929
EventTypes,
30+
HistoryVisibility,
3031
JoinRules,
3132
Membership,
3233
RoomCreationPreset,
@@ -81,21 +82,21 @@ def __init__(self, hs: "HomeServer"):
8182
self._presets_dict = {
8283
RoomCreationPreset.PRIVATE_CHAT: {
8384
"join_rules": JoinRules.INVITE,
84-
"history_visibility": "shared",
85+
"history_visibility": HistoryVisibility.SHARED,
8586
"original_invitees_have_ops": False,
8687
"guest_can_join": True,
8788
"power_level_content_override": {"invite": 0},
8889
},
8990
RoomCreationPreset.TRUSTED_PRIVATE_CHAT: {
9091
"join_rules": JoinRules.INVITE,
91-
"history_visibility": "shared",
92+
"history_visibility": HistoryVisibility.SHARED,
9293
"original_invitees_have_ops": True,
9394
"guest_can_join": True,
9495
"power_level_content_override": {"invite": 0},
9596
},
9697
RoomCreationPreset.PUBLIC_CHAT: {
9798
"join_rules": JoinRules.PUBLIC,
98-
"history_visibility": "shared",
99+
"history_visibility": HistoryVisibility.SHARED,
99100
"original_invitees_have_ops": False,
100101
"guest_can_join": False,
101102
"power_level_content_override": {},

synapse/handlers/room_list.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import msgpack
2121
from unpaddedbase64 import decode_base64, encode_base64
2222

23-
from synapse.api.constants import EventTypes, JoinRules
23+
from synapse.api.constants import EventTypes, HistoryVisibility, JoinRules
2424
from synapse.api.errors import Codes, HttpResponseException
2525
from synapse.types import ThirdPartyInstanceID
2626
from synapse.util.caches.descriptors import cached
@@ -159,7 +159,8 @@ def build_room_entry(room):
159159
"canonical_alias": room["canonical_alias"],
160160
"num_joined_members": room["joined_members"],
161161
"avatar_url": room["avatar"],
162-
"world_readable": room["history_visibility"] == "world_readable",
162+
"world_readable": room["history_visibility"]
163+
== HistoryVisibility.WORLD_READABLE,
163164
"guest_can_join": room["guest_access"] == "can_join",
164165
}
165166

@@ -317,7 +318,7 @@ async def generate_room_entry(
317318
visibility = None
318319
if visibility_event:
319320
visibility = visibility_event.content.get("history_visibility", None)
320-
result["world_readable"] = visibility == "world_readable"
321+
result["world_readable"] = visibility == HistoryVisibility.WORLD_READABLE
321322

322323
guest_event = current_state.get((EventTypes.GuestAccess, ""))
323324
guest = None

synapse/handlers/user_directory.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import logging
1717

1818
import synapse.metrics
19-
from synapse.api.constants import EventTypes, JoinRules, Membership
19+
from synapse.api.constants import EventTypes, HistoryVisibility, JoinRules, Membership
2020
from synapse.handlers.state_deltas import StateDeltasHandler
2121
from synapse.metrics.background_process_metrics import run_as_background_process
2222
from synapse.storage.roommember import ProfileInfo
@@ -250,7 +250,7 @@ async def _handle_room_publicity_change(
250250
prev_event_id,
251251
event_id,
252252
key_name="history_visibility",
253-
public_value="world_readable",
253+
public_value=HistoryVisibility.WORLD_READABLE,
254254
)
255255
elif typ == EventTypes.JoinRules:
256256
change = await self._get_key_change(

synapse/notifier.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
from twisted.internet import defer
3535

3636
import synapse.server
37-
from synapse.api.constants import EventTypes, Membership
37+
from synapse.api.constants import EventTypes, HistoryVisibility, Membership
3838
from synapse.api.errors import AuthError
3939
from synapse.events import EventBase
4040
from synapse.handlers.presence import format_user_presence_state
@@ -611,7 +611,9 @@ async def _is_world_readable(self, room_id: str) -> bool:
611611
room_id, EventTypes.RoomHistoryVisibility, ""
612612
)
613613
if state and "history_visibility" in state.content:
614-
return state.content["history_visibility"] == "world_readable"
614+
return (
615+
state.content["history_visibility"] == HistoryVisibility.WORLD_READABLE
616+
)
615617
else:
616618
return False
617619

synapse/storage/databases/main/user_directory.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import re
1818
from typing import Any, Dict, Iterable, Optional, Set, Tuple
1919

20-
from synapse.api.constants import EventTypes, JoinRules
20+
from synapse.api.constants import EventTypes, HistoryVisibility, JoinRules
2121
from synapse.storage.database import DatabasePool
2222
from synapse.storage.databases.main.state import StateFilter
2323
from synapse.storage.databases.main.state_deltas import StateDeltasStore
@@ -360,7 +360,10 @@ async def is_room_world_readable_or_publicly_joinable(self, room_id):
360360
if hist_vis_id:
361361
hist_vis_ev = await self.get_event(hist_vis_id, allow_none=True)
362362
if hist_vis_ev:
363-
if hist_vis_ev.content.get("history_visibility") == "world_readable":
363+
if (
364+
hist_vis_ev.content.get("history_visibility")
365+
== HistoryVisibility.WORLD_READABLE
366+
):
364367
return True
365368

366369
return False

synapse/visibility.py

+28-14
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@
1212
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
15-
1615
import logging
1716
import operator
1817

19-
from synapse.api.constants import AccountDataTypes, EventTypes, Membership
18+
from synapse.api.constants import (
19+
AccountDataTypes,
20+
EventTypes,
21+
HistoryVisibility,
22+
Membership,
23+
)
2024
from synapse.events.utils import prune_event
2125
from synapse.storage import Storage
2226
from synapse.storage.state import StateFilter
@@ -25,7 +29,12 @@
2529
logger = logging.getLogger(__name__)
2630

2731

28-
VISIBILITY_PRIORITY = ("world_readable", "shared", "invited", "joined")
32+
VISIBILITY_PRIORITY = (
33+
HistoryVisibility.WORLD_READABLE,
34+
HistoryVisibility.SHARED,
35+
HistoryVisibility.INVITED,
36+
HistoryVisibility.JOINED,
37+
)
2938

3039

3140
MEMBERSHIP_PRIORITY = (
@@ -150,12 +159,14 @@ def allowed(event):
150159
# get the room_visibility at the time of the event.
151160
visibility_event = state.get((EventTypes.RoomHistoryVisibility, ""), None)
152161
if visibility_event:
153-
visibility = visibility_event.content.get("history_visibility", "shared")
162+
visibility = visibility_event.content.get(
163+
"history_visibility", HistoryVisibility.SHARED
164+
)
154165
else:
155-
visibility = "shared"
166+
visibility = HistoryVisibility.SHARED
156167

157168
if visibility not in VISIBILITY_PRIORITY:
158-
visibility = "shared"
169+
visibility = HistoryVisibility.SHARED
159170

160171
# Always allow history visibility events on boundaries. This is done
161172
# by setting the effective visibility to the least restrictive
@@ -165,7 +176,7 @@ def allowed(event):
165176
prev_visibility = prev_content.get("history_visibility", None)
166177

167178
if prev_visibility not in VISIBILITY_PRIORITY:
168-
prev_visibility = "shared"
179+
prev_visibility = HistoryVisibility.SHARED
169180

170181
new_priority = VISIBILITY_PRIORITY.index(visibility)
171182
old_priority = VISIBILITY_PRIORITY.index(prev_visibility)
@@ -210,17 +221,17 @@ def allowed(event):
210221

211222
# otherwise, it depends on the room visibility.
212223

213-
if visibility == "joined":
224+
if visibility == HistoryVisibility.JOINED:
214225
# we weren't a member at the time of the event, so we can't
215226
# see this event.
216227
return None
217228

218-
elif visibility == "invited":
229+
elif visibility == HistoryVisibility.INVITED:
219230
# user can also see the event if they were *invited* at the time
220231
# of the event.
221232
return event if membership == Membership.INVITE else None
222233

223-
elif visibility == "shared" and is_peeking:
234+
elif visibility == HistoryVisibility.SHARED and is_peeking:
224235
# if the visibility is shared, users cannot see the event unless
225236
# they have *subequently* joined the room (or were members at the
226237
# time, of course)
@@ -284,8 +295,10 @@ def is_sender_erased(event, erased_senders):
284295
def check_event_is_visible(event, state):
285296
history = state.get((EventTypes.RoomHistoryVisibility, ""), None)
286297
if history:
287-
visibility = history.content.get("history_visibility", "shared")
288-
if visibility in ["invited", "joined"]:
298+
visibility = history.content.get(
299+
"history_visibility", HistoryVisibility.SHARED
300+
)
301+
if visibility in [HistoryVisibility.INVITED, HistoryVisibility.JOINED]:
289302
# We now loop through all state events looking for
290303
# membership states for the requesting server to determine
291304
# if the server is either in the room or has been invited
@@ -305,7 +318,7 @@ def check_event_is_visible(event, state):
305318
if memtype == Membership.JOIN:
306319
return True
307320
elif memtype == Membership.INVITE:
308-
if visibility == "invited":
321+
if visibility == HistoryVisibility.INVITED:
309322
return True
310323
else:
311324
# server has no users in the room: redact
@@ -336,7 +349,8 @@ def check_event_is_visible(event, state):
336349
else:
337350
event_map = await storage.main.get_events(visibility_ids)
338351
all_open = all(
339-
e.content.get("history_visibility") in (None, "shared", "world_readable")
352+
e.content.get("history_visibility")
353+
in (None, HistoryVisibility.SHARED, HistoryVisibility.WORLD_READABLE)
340354
for e in event_map.values()
341355
)
342356

0 commit comments

Comments
 (0)