mirror of
https://github.com/element-hq/synapse.git
synced 2024-11-25 19:15:51 +03:00
Allow room creation but not publishing to continue if room publication rules are violated when creating a new room. (#16811)
Prior to this PR, if a request to create a public (public as in published to the rooms directory) room violated the room list publication rules set in the [config](https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#room_list_publication_rules), the request to create the room was denied and the room was not created. This PR changes the behavior such that when a request to create a room published to the directory violates room list publication rules, the room is still created but the room is not published to the directory.
This commit is contained in:
parent
1e5b32e1c9
commit
a68b48a5dd
5 changed files with 65 additions and 34 deletions
2
changelog.d/16811.misc
Normal file
2
changelog.d/16811.misc
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Allow room creation but not publishing to continue if room publication rules are violated when creating
|
||||||
|
a new room.
|
|
@ -3959,6 +3959,9 @@ The first rule that matches decides if the request is allowed or denied. If no
|
||||||
rule matches, the request is denied. In particular, this means that configuring
|
rule matches, the request is denied. In particular, this means that configuring
|
||||||
an empty list of rules will deny every alias creation request.
|
an empty list of rules will deny every alias creation request.
|
||||||
|
|
||||||
|
Requests to create a public (public as in published to the room directory) room which violates
|
||||||
|
the configured rules will result in the room being created but not published to the room directory.
|
||||||
|
|
||||||
Each rule is a YAML object containing four fields, each of which is an optional string:
|
Each rule is a YAML object containing four fields, each of which is an optional string:
|
||||||
|
|
||||||
* `user_id`: a glob pattern that matches against the user publishing the room.
|
* `user_id`: a glob pattern that matches against the user publishing the room.
|
||||||
|
|
|
@ -916,10 +916,8 @@ class RoomCreationHandler:
|
||||||
if not self.config.roomdirectory.is_publishing_room_allowed(
|
if not self.config.roomdirectory.is_publishing_room_allowed(
|
||||||
user_id, room_id, room_aliases
|
user_id, room_id, room_aliases
|
||||||
):
|
):
|
||||||
# Let's just return a generic message, as there may be all sorts of
|
# allow room creation to continue but do not publish room
|
||||||
# reasons why we said no. TODO: Allow configurable error messages
|
await self.store.set_room_is_public(room_id, False)
|
||||||
# per alias creation rule?
|
|
||||||
raise SynapseError(403, "Not allowed to publish room")
|
|
||||||
|
|
||||||
directory_handler = self.hs.get_directory_handler()
|
directory_handler = self.hs.get_directory_handler()
|
||||||
if room_alias:
|
if room_alias:
|
||||||
|
|
|
@ -17,15 +17,31 @@
|
||||||
# [This file includes modifications made by New Vector Limited]
|
# [This file includes modifications made by New Vector Limited]
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
from twisted.test.proto_helpers import MemoryReactor
|
||||||
|
|
||||||
|
import synapse.rest.admin
|
||||||
|
import synapse.rest.client.login
|
||||||
|
import synapse.rest.client.room
|
||||||
from synapse.config.room_directory import RoomDirectoryConfig
|
from synapse.config.room_directory import RoomDirectoryConfig
|
||||||
|
from synapse.server import HomeServer
|
||||||
|
from synapse.util import Clock
|
||||||
|
|
||||||
from tests import unittest
|
from tests import unittest
|
||||||
|
from tests.unittest import override_config
|
||||||
|
|
||||||
|
|
||||||
class RoomDirectoryConfigTestCase(unittest.TestCase):
|
class RoomDirectoryConfigTestCase(unittest.HomeserverTestCase):
|
||||||
|
def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
|
||||||
|
self.store = hs.get_datastores().main
|
||||||
|
|
||||||
|
servlets = [
|
||||||
|
synapse.rest.admin.register_servlets,
|
||||||
|
synapse.rest.client.login.register_servlets,
|
||||||
|
synapse.rest.client.room.register_servlets,
|
||||||
|
]
|
||||||
|
|
||||||
def test_alias_creation_acl(self) -> None:
|
def test_alias_creation_acl(self) -> None:
|
||||||
config = yaml.safe_load(
|
config = yaml.safe_load(
|
||||||
"""
|
"""
|
||||||
|
@ -167,3 +183,20 @@ class RoomDirectoryConfigTestCase(unittest.TestCase):
|
||||||
aliases=["#unofficial_st:example.com", "#blah:example.com"],
|
aliases=["#unofficial_st:example.com", "#blah:example.com"],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@override_config({"room_list_publication_rules": []})
|
||||||
|
def test_room_creation_when_publishing_denied(self) -> None:
|
||||||
|
"""
|
||||||
|
Test that when room publishing is denied via the config that new rooms can
|
||||||
|
still be created and that the newly created room is not public.
|
||||||
|
"""
|
||||||
|
|
||||||
|
user = self.register_user("alice", "pass")
|
||||||
|
token = self.login("alice", "pass")
|
||||||
|
room_id = self.helper.create_room_as(user, is_public=True, tok=token)
|
||||||
|
|
||||||
|
res = self.get_success(self.store.get_room(room_id))
|
||||||
|
assert res is not None
|
||||||
|
is_public, _ = res
|
||||||
|
|
||||||
|
self.assertFalse(is_public)
|
||||||
|
|
|
@ -496,19 +496,27 @@ class TestCreatePublishedRoomACL(unittest.HomeserverTestCase):
|
||||||
self.denied_user_id = self.register_user("denied", "pass")
|
self.denied_user_id = self.register_user("denied", "pass")
|
||||||
self.denied_access_token = self.login("denied", "pass")
|
self.denied_access_token = self.login("denied", "pass")
|
||||||
|
|
||||||
|
self.store = hs.get_datastores().main
|
||||||
|
|
||||||
def test_denied_without_publication_permission(self) -> None:
|
def test_denied_without_publication_permission(self) -> None:
|
||||||
"""
|
"""
|
||||||
Try to create a room, register an alias for it, and publish it,
|
Try to create a room, register a valid alias for it, and publish it,
|
||||||
as a user without permission to publish rooms.
|
as a user without permission to publish rooms.
|
||||||
(This is used as both a standalone test & as a helper function.)
|
The room should be created but not published.
|
||||||
"""
|
"""
|
||||||
self.helper.create_room_as(
|
room_id = self.helper.create_room_as(
|
||||||
self.denied_user_id,
|
self.denied_user_id,
|
||||||
tok=self.denied_access_token,
|
tok=self.denied_access_token,
|
||||||
extra_content=self.data,
|
extra_content=self.data,
|
||||||
is_public=True,
|
is_public=True,
|
||||||
expect_code=403,
|
expect_code=200,
|
||||||
)
|
)
|
||||||
|
res = self.get_success(self.store.get_room(room_id))
|
||||||
|
assert res is not None
|
||||||
|
is_public, _ = res
|
||||||
|
|
||||||
|
# room creation completes but room is not published to directory
|
||||||
|
self.assertEqual(is_public, False)
|
||||||
|
|
||||||
def test_allowed_when_creating_private_room(self) -> None:
|
def test_allowed_when_creating_private_room(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -526,9 +534,8 @@ class TestCreatePublishedRoomACL(unittest.HomeserverTestCase):
|
||||||
|
|
||||||
def test_allowed_with_publication_permission(self) -> None:
|
def test_allowed_with_publication_permission(self) -> None:
|
||||||
"""
|
"""
|
||||||
Try to create a room, register an alias for it, and publish it,
|
Try to create a room, register a valid alias for it, and publish it,
|
||||||
as a user WITH permission to publish rooms.
|
as a user WITH permission to publish rooms.
|
||||||
(This is used as both a standalone test & as a helper function.)
|
|
||||||
"""
|
"""
|
||||||
self.helper.create_room_as(
|
self.helper.create_room_as(
|
||||||
self.allowed_user_id,
|
self.allowed_user_id,
|
||||||
|
@ -540,38 +547,26 @@ class TestCreatePublishedRoomACL(unittest.HomeserverTestCase):
|
||||||
|
|
||||||
def test_denied_publication_with_invalid_alias(self) -> None:
|
def test_denied_publication_with_invalid_alias(self) -> None:
|
||||||
"""
|
"""
|
||||||
Try to create a room, register an alias for it, and publish it,
|
Try to create a room, register an invalid alias for it, and publish it,
|
||||||
as a user WITH permission to publish rooms.
|
as a user WITH permission to publish rooms.
|
||||||
"""
|
"""
|
||||||
self.helper.create_room_as(
|
room_id = self.helper.create_room_as(
|
||||||
self.allowed_user_id,
|
self.allowed_user_id,
|
||||||
tok=self.allowed_access_token,
|
tok=self.allowed_access_token,
|
||||||
extra_content={"room_alias_name": "foo"},
|
extra_content={"room_alias_name": "foo"},
|
||||||
is_public=True,
|
is_public=True,
|
||||||
expect_code=403,
|
expect_code=200,
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_can_create_as_private_room_after_rejection(self) -> None:
|
# the room is created with the requested alias, but the room is not published
|
||||||
"""
|
res = self.get_success(self.store.get_room(room_id))
|
||||||
After failing to publish a room with an alias as a user without publish permission,
|
assert res is not None
|
||||||
retry as the same user, but without publishing the room.
|
is_public, _ = res
|
||||||
|
|
||||||
This should pass, but used to fail because the alias was registered by the first
|
self.assertFalse(is_public)
|
||||||
request, even though the room creation was denied.
|
|
||||||
"""
|
|
||||||
self.test_denied_without_publication_permission()
|
|
||||||
self.test_allowed_when_creating_private_room()
|
|
||||||
|
|
||||||
def test_can_create_with_permission_after_rejection(self) -> None:
|
aliases = self.get_success(self.store.get_aliases_for_room(room_id))
|
||||||
"""
|
self.assertEqual(aliases[0], "#foo:test")
|
||||||
After failing to publish a room with an alias as a user without publish permission,
|
|
||||||
retry as someone with permission, using the same alias.
|
|
||||||
|
|
||||||
This also used to fail because of the alias having been registered by the first
|
|
||||||
request, leaving it unavailable for any other user's new rooms.
|
|
||||||
"""
|
|
||||||
self.test_denied_without_publication_permission()
|
|
||||||
self.test_allowed_with_publication_permission()
|
|
||||||
|
|
||||||
|
|
||||||
class TestRoomListSearchDisabled(unittest.HomeserverTestCase):
|
class TestRoomListSearchDisabled(unittest.HomeserverTestCase):
|
||||||
|
|
Loading…
Reference in a new issue