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

Commit 5f97943

Browse files
committed
Merge branch 'develop' of github.com:matrix-org/synapse into anoa/msc2403_complement_build_flag
2 parents 2a83572 + 437a8ed commit 5f97943

File tree

16 files changed

+176
-46
lines changed

16 files changed

+176
-46
lines changed

changelog.d/12310.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add a configuration option to remove a specific set of rooms from sync responses.

changelog.d/12326.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix typechecker problems exposed by signedjson 1.1.2.

docs/sample_config.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,15 @@ templates:
539539
#
540540
#custom_template_directory: /path/to/custom/templates/
541541

542+
# List of rooms to exclude from sync responses. This is useful for server
543+
# administrators wishing to group users into a room without these users being able
544+
# to see it from their client.
545+
#
546+
# By default, no room is excluded.
547+
#
548+
#exclude_rooms_from_sync:
549+
# - !foo:example.com
550+
542551

543552
# Message retention policy at the server level.
544553
#

mypy.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,9 @@ ignore_missing_imports = True
273273
[mypy-ijson.*]
274274
ignore_missing_imports = True
275275

276+
[mypy-importlib_metadata.*]
277+
ignore_missing_imports = True
278+
276279
[mypy-jaeger_client.*]
277280
ignore_missing_imports = True
278281

synapse/config/key.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import hashlib
1717
import logging
1818
import os
19-
from typing import Any, Dict, Iterator, List, Optional
19+
from typing import TYPE_CHECKING, Any, Dict, Iterator, List, Optional
2020

2121
import attr
2222
import jsonschema
@@ -38,6 +38,9 @@
3838

3939
from ._base import Config, ConfigError
4040

41+
if TYPE_CHECKING:
42+
from signedjson.key import VerifyKeyWithExpiry
43+
4144
INSECURE_NOTARY_ERROR = """\
4245
Your server is configured to accept key server responses without signature
4346
validation or TLS certificate validation. This is likely to be very insecure. If
@@ -300,16 +303,16 @@ def read_signing_keys(self, signing_key_path: str, name: str) -> List[SigningKey
300303

301304
def read_old_signing_keys(
302305
self, old_signing_keys: Optional[JsonDict]
303-
) -> Dict[str, VerifyKey]:
306+
) -> Dict[str, "VerifyKeyWithExpiry"]:
304307
if old_signing_keys is None:
305308
return {}
306309
keys = {}
307310
for key_id, key_data in old_signing_keys.items():
308311
if is_signing_algorithm_supported(key_id):
309312
key_base64 = key_data["key"]
310313
key_bytes = decode_base64(key_base64)
311-
verify_key = decode_verify_key_bytes(key_id, key_bytes)
312-
verify_key.expired_ts = key_data["expired_ts"]
314+
verify_key: "VerifyKeyWithExpiry" = decode_verify_key_bytes(key_id, key_bytes) # type: ignore[assignment]
315+
verify_key.expired = key_data["expired_ts"]
313316
keys[key_id] = verify_key
314317
else:
315318
raise ConfigError(
@@ -422,7 +425,7 @@ def _parse_key_servers(
422425
server_name = server["server_name"]
423426
result = TrustedKeyServer(server_name=server_name)
424427

425-
verify_keys = server.get("verify_keys")
428+
verify_keys: Optional[Dict[str, str]] = server.get("verify_keys")
426429
if verify_keys is not None:
427430
result.verify_keys = {}
428431
for key_id, key_base64 in verify_keys.items():

synapse/config/server.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,10 @@ def read_config(self, config, **kwargs):
680680
config.get("use_account_validity_in_account_status") or False
681681
)
682682

683+
self.rooms_to_exclude_from_sync: List[str] = (
684+
config.get("exclude_rooms_from_sync") or []
685+
)
686+
683687
def has_tls_listener(self) -> bool:
684688
return any(listener.tls for listener in self.listeners)
685689

@@ -1234,6 +1238,15 @@ def generate_config_section(
12341238
# information about using custom templates.
12351239
#
12361240
#custom_template_directory: /path/to/custom/templates/
1241+
1242+
# List of rooms to exclude from sync responses. This is useful for server
1243+
# administrators wishing to group users into a room without these users being able
1244+
# to see it from their client.
1245+
#
1246+
# By default, no room is excluded.
1247+
#
1248+
#exclude_rooms_from_sync:
1249+
# - !foo:example.com
12371250
"""
12381251
% locals()
12391252
)

synapse/crypto/keyring.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ def __init__(
176176
self._local_verify_keys: Dict[str, FetchKeyResult] = {}
177177
for key_id, key in hs.config.key.old_signing_keys.items():
178178
self._local_verify_keys[key_id] = FetchKeyResult(
179-
verify_key=key, valid_until_ts=key.expired_ts
179+
verify_key=key, valid_until_ts=key.expired
180180
)
181181

182182
vk = get_verify_key(hs.signing_key)

synapse/events/builder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union
1616

1717
import attr
18-
from nacl.signing import SigningKey
18+
from signedjson.types import SigningKey
1919

2020
from synapse.api.constants import MAX_DEPTH
2121
from synapse.api.room_versions import (

synapse/handlers/sync.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,8 @@ def __init__(self, hs: "HomeServer"):
298298
expiry_ms=LAZY_LOADED_MEMBERS_CACHE_MAX_AGE,
299299
)
300300

301+
self.rooms_to_exclude = hs.config.server.rooms_to_exclude_from_sync
302+
301303
async def wait_for_sync_for_user(
302304
self,
303305
requester: Requester,
@@ -1607,13 +1609,15 @@ async def _generate_sync_entry_for_rooms(
16071609
ignored_users = await self.store.ignored_users(user_id)
16081610
if since_token:
16091611
room_changes = await self._get_rooms_changed(
1610-
sync_result_builder, ignored_users
1612+
sync_result_builder, ignored_users, self.rooms_to_exclude
16111613
)
16121614
tags_by_room = await self.store.get_updated_tags(
16131615
user_id, since_token.account_data_key
16141616
)
16151617
else:
1616-
room_changes = await self._get_all_rooms(sync_result_builder, ignored_users)
1618+
room_changes = await self._get_all_rooms(
1619+
sync_result_builder, ignored_users, self.rooms_to_exclude
1620+
)
16171621
tags_by_room = await self.store.get_tags_for_user(user_id)
16181622

16191623
log_kv({"rooms_changed": len(room_changes.room_entries)})
@@ -1689,7 +1693,10 @@ async def _have_rooms_changed(
16891693
return False
16901694

16911695
async def _get_rooms_changed(
1692-
self, sync_result_builder: "SyncResultBuilder", ignored_users: FrozenSet[str]
1696+
self,
1697+
sync_result_builder: "SyncResultBuilder",
1698+
ignored_users: FrozenSet[str],
1699+
excluded_rooms: List[str],
16931700
) -> _RoomChanges:
16941701
"""Determine the changes in rooms to report to the user.
16951702
@@ -1721,7 +1728,7 @@ async def _get_rooms_changed(
17211728
# _have_rooms_changed. We could keep the results in memory to avoid a
17221729
# second query, at the cost of more complicated source code.
17231730
membership_change_events = await self.store.get_membership_changes_for_user(
1724-
user_id, since_token.room_key, now_token.room_key
1731+
user_id, since_token.room_key, now_token.room_key, excluded_rooms
17251732
)
17261733

17271734
mem_change_events_by_room_id: Dict[str, List[EventBase]] = {}
@@ -1922,7 +1929,10 @@ async def _get_rooms_changed(
19221929
)
19231930

19241931
async def _get_all_rooms(
1925-
self, sync_result_builder: "SyncResultBuilder", ignored_users: FrozenSet[str]
1932+
self,
1933+
sync_result_builder: "SyncResultBuilder",
1934+
ignored_users: FrozenSet[str],
1935+
ignored_rooms: List[str],
19261936
) -> _RoomChanges:
19271937
"""Returns entries for all rooms for the user.
19281938
@@ -1933,7 +1943,7 @@ async def _get_all_rooms(
19331943
Args:
19341944
sync_result_builder
19351945
ignored_users: Set of users ignored by user.
1936-
1946+
ignored_rooms: List of rooms to ignore.
19371947
"""
19381948

19391949
user_id = sync_result_builder.sync_config.user.to_string()
@@ -1944,6 +1954,7 @@ async def _get_all_rooms(
19441954
room_list = await self.store.get_rooms_for_local_user_where_membership_is(
19451955
user_id=user_id,
19461956
membership_list=Membership.LIST,
1957+
excluded_rooms=ignored_rooms,
19471958
)
19481959

19491960
room_entries = []

synapse/rest/key/v2/local_key_resource.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,17 @@ def update_response_body(self, time_now_msec: int) -> None:
7676

7777
def response_json_object(self) -> JsonDict:
7878
verify_keys = {}
79-
for key in self.config.key.signing_key:
80-
verify_key_bytes = key.verify_key.encode()
81-
key_id = "%s:%s" % (key.alg, key.version)
79+
for signing_key in self.config.key.signing_key:
80+
verify_key_bytes = signing_key.verify_key.encode()
81+
key_id = "%s:%s" % (signing_key.alg, signing_key.version)
8282
verify_keys[key_id] = {"key": encode_base64(verify_key_bytes)}
8383

8484
old_verify_keys = {}
85-
for key_id, key in self.config.key.old_signing_keys.items():
86-
verify_key_bytes = key.encode()
85+
for key_id, old_signing_key in self.config.key.old_signing_keys.items():
86+
verify_key_bytes = old_signing_key.encode()
8787
old_verify_keys[key_id] = {
8888
"key": encode_base64(verify_key_bytes),
89-
"expired_ts": key.expired_ts,
89+
"expired_ts": old_signing_key.expired,
9090
}
9191

9292
json_object = {

synapse/rest/key/v2/remote_key_resource.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# limitations under the License.
1414

1515
import logging
16-
from typing import TYPE_CHECKING, Dict
16+
from typing import TYPE_CHECKING, Dict, Set
1717

1818
from signedjson.sign import sign_json
1919

@@ -149,7 +149,7 @@ async def query_keys(
149149

150150
cached = await self.store.get_server_keys_json(store_queries)
151151

152-
json_results = set()
152+
json_results: Set[bytes] = set()
153153

154154
time_now_ms = self.clock.time_msec()
155155

@@ -234,8 +234,8 @@ async def query_keys(
234234
await self.query_keys(request, query, query_remote_on_cache_miss=False)
235235
else:
236236
signed_keys = []
237-
for key_json in json_results:
238-
key_json = json_decoder.decode(key_json.decode("utf-8"))
237+
for key_json_raw in json_results:
238+
key_json = json_decoder.decode(key_json_raw.decode("utf-8"))
239239
for signing_key in self.config.key.key_server_signing_keys:
240240
key_json = sign_json(
241241
key_json, self.config.server.server_name, signing_key

synapse/storage/databases/main/roommember.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,10 @@ async def get_invite_for_local_user_in_room(
361361
return None
362362

363363
async def get_rooms_for_local_user_where_membership_is(
364-
self, user_id: str, membership_list: Collection[str]
364+
self,
365+
user_id: str,
366+
membership_list: Collection[str],
367+
excluded_rooms: Optional[List[str]] = None,
365368
) -> List[RoomsForUser]:
366369
"""Get all the rooms for this *local* user where the membership for this user
367370
matches one in the membership list.
@@ -372,6 +375,7 @@ async def get_rooms_for_local_user_where_membership_is(
372375
user_id: The user ID.
373376
membership_list: A list of synapse.api.constants.Membership
374377
values which the user must be in.
378+
excluded_rooms: A list of rooms to ignore.
375379
376380
Returns:
377381
The RoomsForUser that the user matches the membership types.
@@ -386,12 +390,19 @@ async def get_rooms_for_local_user_where_membership_is(
386390
membership_list,
387391
)
388392

389-
# Now we filter out forgotten rooms
390-
forgotten_rooms = await self.get_forgotten_rooms_for_user(user_id)
391-
return [room for room in rooms if room.room_id not in forgotten_rooms]
393+
# Now we filter out forgotten and excluded rooms
394+
rooms_to_exclude: Set[str] = await self.get_forgotten_rooms_for_user(user_id)
395+
396+
if excluded_rooms is not None:
397+
rooms_to_exclude.update(set(excluded_rooms))
398+
399+
return [room for room in rooms if room.room_id not in rooms_to_exclude]
392400

393401
def _get_rooms_for_local_user_where_membership_is_txn(
394-
self, txn, user_id: str, membership_list: List[str]
402+
self,
403+
txn,
404+
user_id: str,
405+
membership_list: List[str],
395406
) -> List[RoomsForUser]:
396407
# Paranoia check.
397408
if not self.hs.is_mine_id(user_id):

synapse/storage/databases/main/stream.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"""
3737

3838
import logging
39-
from typing import TYPE_CHECKING, Collection, Dict, List, Optional, Set, Tuple
39+
from typing import TYPE_CHECKING, Any, Collection, Dict, List, Optional, Set, Tuple
4040

4141
import attr
4242
from frozendict import frozendict
@@ -585,7 +585,11 @@ def f(txn: LoggingTransaction) -> List[_EventDictReturn]:
585585
return ret, key
586586

587587
async def get_membership_changes_for_user(
588-
self, user_id: str, from_key: RoomStreamToken, to_key: RoomStreamToken
588+
self,
589+
user_id: str,
590+
from_key: RoomStreamToken,
591+
to_key: RoomStreamToken,
592+
excluded_rooms: Optional[List[str]] = None,
589593
) -> List[EventBase]:
590594
"""Fetch membership events for a given user.
591595
@@ -610,23 +614,29 @@ def f(txn: LoggingTransaction) -> List[_EventDictReturn]:
610614
min_from_id = from_key.stream
611615
max_to_id = to_key.get_max_stream_pos()
612616

617+
args: List[Any] = [user_id, min_from_id, max_to_id]
618+
619+
ignore_room_clause = ""
620+
if excluded_rooms is not None and len(excluded_rooms) > 0:
621+
ignore_room_clause = "AND e.room_id NOT IN (%s)" % ",".join(
622+
"?" for _ in excluded_rooms
623+
)
624+
args = args + excluded_rooms
625+
613626
sql = """
614627
SELECT m.event_id, instance_name, topological_ordering, stream_ordering
615628
FROM events AS e, room_memberships AS m
616629
WHERE e.event_id = m.event_id
617630
AND m.user_id = ?
618631
AND e.stream_ordering > ? AND e.stream_ordering <= ?
632+
%s
619633
ORDER BY e.stream_ordering ASC
620-
"""
621-
txn.execute(
622-
sql,
623-
(
624-
user_id,
625-
min_from_id,
626-
max_to_id,
627-
),
634+
""" % (
635+
ignore_room_clause,
628636
)
629637

638+
txn.execute(sql, args)
639+
630640
rows = [
631641
_EventDictReturn(event_id, None, stream_ordering)
632642
for event_id, instance_name, topological_ordering, stream_ordering in txn

tests/crypto/test_event_signing.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
SIGNING_KEY_SEED = decode_base64("YJDBA9Xnr2sVqXD9Vj7XVUnmFZcZrlw8Md7kMW+3XA1")
2929

3030
KEY_ALG = "ed25519"
31-
KEY_VER = 1
32-
KEY_NAME = "%s:%d" % (KEY_ALG, KEY_VER)
31+
KEY_VER = "1"
32+
KEY_NAME = "%s:%s" % (KEY_ALG, KEY_VER)
3333

3434
HOSTNAME = "domain"
3535

@@ -39,7 +39,7 @@ def setUp(self):
3939
# NB: `signedjson` expects `nacl.signing.SigningKey` instances which have been
4040
# monkeypatched to include new `alg` and `version` attributes. This is captured
4141
# by the `signedjson.types.SigningKey` protocol.
42-
self.signing_key: signedjson.types.SigningKey = nacl.signing.SigningKey(
42+
self.signing_key: signedjson.types.SigningKey = nacl.signing.SigningKey( # type: ignore[assignment]
4343
SIGNING_KEY_SEED
4444
)
4545
self.signing_key.alg = KEY_ALG

0 commit comments

Comments
 (0)