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

Commit 9013104

Browse files
authored
Don't create an empty room when checking for MAU limits (#12713)
1 parent aec69d2 commit 9013104

File tree

4 files changed

+66
-56
lines changed

4 files changed

+66
-56
lines changed

changelog.d/12713.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a bug introduced in Synapse 1.30.0 where empty rooms could be automatically created if a monthly active users limit is set.

synapse/server_notices/resource_limits_server_notices.py

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
ServerNoticeMsgType,
2222
)
2323
from synapse.api.errors import AuthError, ResourceLimitError, SynapseError
24-
from synapse.server_notices.server_notices_manager import SERVER_NOTICE_ROOM_TAG
2524

2625
if TYPE_CHECKING:
2726
from synapse.server import HomeServer
@@ -71,18 +70,19 @@ async def maybe_send_server_notice_to_user(self, user_id: str) -> None:
7170
# In practice, not sure we can ever get here
7271
return
7372

74-
room_id = await self._server_notices_manager.get_or_create_notice_room_for_user(
73+
# Check if there's a server notice room for this user.
74+
room_id = await self._server_notices_manager.maybe_get_notice_room_for_user(
7575
user_id
7676
)
7777

78-
if not room_id:
79-
logger.warning("Failed to get server notices room")
80-
return
81-
82-
await self._check_and_set_tags(user_id, room_id)
83-
84-
# Determine current state of room
85-
currently_blocked, ref_events = await self._is_room_currently_blocked(room_id)
78+
if room_id is not None:
79+
# Determine current state of room
80+
currently_blocked, ref_events = await self._is_room_currently_blocked(
81+
room_id
82+
)
83+
else:
84+
currently_blocked = False
85+
ref_events = []
8686

8787
limit_msg = None
8888
limit_type = None
@@ -161,26 +161,6 @@ async def _apply_limit_block_notification(
161161
user_id, content, EventTypes.Pinned, ""
162162
)
163163

164-
async def _check_and_set_tags(self, user_id: str, room_id: str) -> None:
165-
"""
166-
Since server notices rooms were originally not with tags,
167-
important to check that tags have been set correctly
168-
Args:
169-
user_id(str): the user in question
170-
room_id(str): the server notices room for that user
171-
"""
172-
tags = await self._store.get_tags_for_room(user_id, room_id)
173-
need_to_set_tag = True
174-
if tags:
175-
if SERVER_NOTICE_ROOM_TAG in tags:
176-
# tag already present, nothing to do here
177-
need_to_set_tag = False
178-
if need_to_set_tag:
179-
max_id = await self._account_data_handler.add_tag_to_room(
180-
user_id, room_id, SERVER_NOTICE_ROOM_TAG, {}
181-
)
182-
self._notifier.on_new_event("account_data_key", max_id, users=[user_id])
183-
184164
async def _is_room_currently_blocked(self, room_id: str) -> Tuple[bool, List[str]]:
185165
"""
186166
Determines if the room is currently blocked

synapse/server_notices/server_notices_manager.py

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,35 @@ async def send_notice(
9090
)
9191
return event
9292

93+
@cached()
94+
async def maybe_get_notice_room_for_user(self, user_id: str) -> Optional[str]:
95+
"""Try to look up the server notice room for this user if it exists.
96+
97+
Does not create one if none can be found.
98+
99+
Args:
100+
user_id: the user we want a server notice room for.
101+
102+
Returns:
103+
The room's ID, or None if no room could be found.
104+
"""
105+
rooms = await self._store.get_rooms_for_local_user_where_membership_is(
106+
user_id, [Membership.INVITE, Membership.JOIN]
107+
)
108+
for room in rooms:
109+
# it's worth noting that there is an asymmetry here in that we
110+
# expect the user to be invited or joined, but the system user must
111+
# be joined. This is kinda deliberate, in that if somebody somehow
112+
# manages to invite the system user to a room, that doesn't make it
113+
# the server notices room.
114+
user_ids = await self._store.get_users_in_room(room.room_id)
115+
if len(user_ids) <= 2 and self.server_notices_mxid in user_ids:
116+
# we found a room which our user shares with the system notice
117+
# user
118+
return room.room_id
119+
120+
return None
121+
93122
@cached()
94123
async def get_or_create_notice_room_for_user(self, user_id: str) -> str:
95124
"""Get the room for notices for a given user
@@ -112,31 +141,20 @@ async def get_or_create_notice_room_for_user(self, user_id: str) -> str:
112141
self.server_notices_mxid, authenticated_entity=self._server_name
113142
)
114143

115-
rooms = await self._store.get_rooms_for_local_user_where_membership_is(
116-
user_id, [Membership.INVITE, Membership.JOIN]
117-
)
118-
for room in rooms:
119-
# it's worth noting that there is an asymmetry here in that we
120-
# expect the user to be invited or joined, but the system user must
121-
# be joined. This is kinda deliberate, in that if somebody somehow
122-
# manages to invite the system user to a room, that doesn't make it
123-
# the server notices room.
124-
user_ids = await self._store.get_users_in_room(room.room_id)
125-
if len(user_ids) <= 2 and self.server_notices_mxid in user_ids:
126-
# we found a room which our user shares with the system notice
127-
# user
128-
logger.info(
129-
"Using existing server notices room %s for user %s",
130-
room.room_id,
131-
user_id,
132-
)
133-
await self._update_notice_user_profile_if_changed(
134-
requester,
135-
room.room_id,
136-
self._config.servernotices.server_notices_mxid_display_name,
137-
self._config.servernotices.server_notices_mxid_avatar_url,
138-
)
139-
return room.room_id
144+
room_id = await self.maybe_get_notice_room_for_user(user_id)
145+
if room_id is not None:
146+
logger.info(
147+
"Using existing server notices room %s for user %s",
148+
room_id,
149+
user_id,
150+
)
151+
await self._update_notice_user_profile_if_changed(
152+
requester,
153+
room_id,
154+
self._config.servernotices.server_notices_mxid_display_name,
155+
self._config.servernotices.server_notices_mxid_avatar_url,
156+
)
157+
return room_id
140158

141159
# apparently no existing notice room: create a new one
142160
logger.info("Creating server notices room for %s", user_id)
@@ -166,6 +184,8 @@ async def get_or_create_notice_room_for_user(self, user_id: str) -> str:
166184
)
167185
room_id = info["room_id"]
168186

187+
self.maybe_get_notice_room_for_user.invalidate((user_id,))
188+
169189
max_id = await self._account_data_handler.add_tag_to_room(
170190
user_id, room_id, SERVER_NOTICE_ROOM_TAG, {}
171191
)

tests/server_notices/test_resource_limits_server_notices.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ def prepare(self, reactor, clock, hs):
7575
self._rlsn._server_notices_manager.get_or_create_notice_room_for_user = Mock(
7676
return_value=make_awaitable("!something:localhost")
7777
)
78+
self._rlsn._server_notices_manager.maybe_get_notice_room_for_user = Mock(
79+
return_value=make_awaitable("!something:localhost")
80+
)
7881
self._rlsn._store.add_tag_to_room = Mock(return_value=make_awaitable(None))
7982
self._rlsn._store.get_tags_for_room = Mock(return_value=make_awaitable({}))
8083

@@ -102,6 +105,7 @@ def test_maybe_send_server_notice_to_user_remove_blocked_notice(self):
102105
)
103106
self.get_success(self._rlsn.maybe_send_server_notice_to_user(self.user_id))
104107
# Would be better to check the content, but once == remove blocking event
108+
self._rlsn._server_notices_manager.maybe_get_notice_room_for_user.assert_called_once()
105109
self._send_notice.assert_called_once()
106110

107111
def test_maybe_send_server_notice_to_user_remove_blocked_notice_noop(self):
@@ -300,7 +304,10 @@ def test_no_invite_without_notice(self):
300304
hasn't been reached (since it's the only user and the limit is 5), so users
301305
shouldn't receive a server notice.
302306
"""
303-
self.register_user("user", "password")
307+
m = Mock(return_value=make_awaitable(None))
308+
self._rlsn._server_notices_manager.maybe_get_notice_room_for_user = m
309+
310+
user_id = self.register_user("user", "password")
304311
tok = self.login("user", "password")
305312

306313
channel = self.make_request("GET", "/sync?timeout=0", access_token=tok)
@@ -309,6 +316,8 @@ def test_no_invite_without_notice(self):
309316
"rooms", channel.json_body, "Got invites without server notice"
310317
)
311318

319+
m.assert_called_once_with(user_id)
320+
312321
def test_invite_with_notice(self):
313322
"""Tests that, if the MAU limit is hit, the server notices user invites each user
314323
to a room in which it has sent a notice.

0 commit comments

Comments
 (0)