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

add default_power_level_content_override config option. #12618

Merged
merged 36 commits into from
May 12, 2022
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
0a6f1d1
add default_power_level_content_override config option.
ara4n Apr 23, 2022
8cb9abe
changelog
ara4n Apr 23, 2022
ba33466
update sample config
ara4n Apr 23, 2022
f415534
Merge branch 'develop' into matthew/configurable_default_pl
andybalaam May 3, 2022
c3a8159
Apply default_power_level_content_override before power_level_content…
andybalaam May 3, 2022
20e2a51
Provide an example of a default_power_level_content_override
andybalaam May 3, 2022
f7eed3a
Generate docs
andybalaam May 3, 2022
7531942
Add a config manual entry for default_power_level_content_override
andybalaam May 3, 2022
50b0b1e
Re-order room permissions config
andybalaam May 3, 2022
9da3abc
Move changelog file to correct name for this PR
andybalaam May 4, 2022
45da8d0
Tests for power level overrides
andybalaam May 4, 2022
bbea127
Merge branch 'develop' into configurable_default_pl
andybalaam May 4, 2022
0cb64bf
Update test config to match documentation
andybalaam May 4, 2022
f863ad9
Document the way power level overrides overwrite per key
andybalaam May 4, 2022
eba1ed4
Reformat changelog for default_power_level_content_override
andybalaam May 6, 2022
9d70d83
Explicitly mention that the config will be overlaid
andybalaam May 9, 2022
e860ec6
Expand 12618 changelog entry
andybalaam May 9, 2022
4309993
Delete extranous sentence about MSC3779 and MSC3761
andybalaam May 9, 2022
3aed63a
More realistic example for default_power_level_content_override
andybalaam May 9, 2022
9c99926
Fix indent of example config
andybalaam May 10, 2022
52197b0
Fix case of create in default power level tests
andybalaam May 10, 2022
55e1ecc
Spread out multi-line docstring
andybalaam May 10, 2022
21459d8
Use Python native string literal concatenation
andybalaam May 10, 2022
08b00e1
Reduce the user of Cucumber-style Given/And comments to be more readable
andybalaam May 10, 2022
9adeaa7
Document allowed keys inside default_power_level_content_override
andybalaam May 10, 2022
4dda230
Move default_power_level_content_override into a member
andybalaam May 10, 2022
ae9421c
Remove assumptions about default power levels from tests
andybalaam May 10, 2022
aa43bb1
Generate sample config
andybalaam May 10, 2022
d84ba9a
Code formatting
andybalaam May 10, 2022
990b7fa
Tidy default override if, and check against None instead of falsey
andybalaam May 12, 2022
8122c1b
Fix typo use->used
andybalaam May 12, 2022
a91a043
Remove extraneous null presets in example config
andybalaam May 12, 2022
383e021
Regenerate sample config
andybalaam May 12, 2022
b2ae9c9
Add wording "per room preset"
andybalaam May 12, 2022
e1a913d
Quotes for config key example
andybalaam May 12, 2022
8a639df
Make config example valid yaml
andybalaam May 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion changelog.d/12618.feature
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Add default_power_level_content_override config option.
Add a `default_power_level_content_override` config option to set default room power levels.
andybalaam marked this conversation as resolved.
Show resolved Hide resolved
30 changes: 26 additions & 4 deletions docs/sample_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2458,18 +2458,40 @@ push:
# Override the default power levels for rooms created on this server, per
# room creation preset.
#
# The appropriate dictionary for the room preset will be applied on top
# of the existing power levels content.
#
# Useful if you know that your users need special permissions in rooms
# that they create (e.g. to send particular types of state events without
# needing an elevated power level). This takes the same shape as the
# `power_level_content_override` parameter in the /createRoom API, but
# is applied before that parameter.
#
# This is something of a workaround in the absence of MSC3779 or MSC3761.
# Valid keys are some or all of `private_chat`, `trusted_private_chat`
# and `public_chat`. Inside each of those should be any of the
# properties allowed in `power_level_content_override` in the
# /createRoom API. If any property is missing, its default value will
# continue to be use. If any property is present, it will overwrite
# the existing default completely (so if the `events` property exists,
# the default event power levels will be ignored).
#
#default_power_level_content_override:
# private_chat: { "events": { "com.example.foo" : 0 } }
# trusted_private_chat: null
# public_chat: null
# private_chat: {
# "events": {
# "com.example.myeventtype" : 0,
# "m.room.avatar": 50,
# "m.room.canonical_alias": 50,
# "m.room.encryption": 100,
# "m.room.history_visibility": 100,
# "m.room.name": 50,
# "m.room.power_levels": 100,
# "m.room.server_acl": 100,
# "m.room.tombstone": 100
# },
# "events_default": 1
# }
# trusted_private_chat: null
# public_chat: null


# Uncomment to allow non-server-admin users to create groups on this server
Expand Down
30 changes: 26 additions & 4 deletions synapse/config/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,38 @@ def generate_config_section(self, **kwargs: Any) -> str:
# Override the default power levels for rooms created on this server, per
# room creation preset.
#
# The appropriate dictionary for the room preset will be applied on top
# of the existing power levels content.
#
# Useful if you know that your users need special permissions in rooms
# that they create (e.g. to send particular types of state events without
# needing an elevated power level). This takes the same shape as the
# `power_level_content_override` parameter in the /createRoom API, but
# is applied before that parameter.
#
# This is something of a workaround in the absence of MSC3779 or MSC3761.
# Valid keys are some or all of `private_chat`, `trusted_private_chat`
# and `public_chat`. Inside each of those should be any of the
# properties allowed in `power_level_content_override` in the
# /createRoom API. If any property is missing, its default value will
# continue to be use. If any property is present, it will overwrite
andybalaam marked this conversation as resolved.
Show resolved Hide resolved
# the existing default completely (so if the `events` property exists,
# the default event power levels will be ignored).
#
#default_power_level_content_override:
# private_chat: { "events": { "com.example.foo" : 0 } }
# trusted_private_chat: null
# public_chat: null
# private_chat: {
andybalaam marked this conversation as resolved.
Show resolved Hide resolved
# "events": {
# "com.example.myeventtype" : 0,
# "m.room.avatar": 50,
# "m.room.canonical_alias": 50,
# "m.room.encryption": 100,
# "m.room.history_visibility": 100,
# "m.room.name": 50,
# "m.room.power_levels": 100,
# "m.room.server_acl": 100,
# "m.room.tombstone": 100
# },
# "events_default": 1
# }
# trusted_private_chat: null
# public_chat: null
andybalaam marked this conversation as resolved.
Show resolved Hide resolved
"""
13 changes: 7 additions & 6 deletions synapse/handlers/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ def __init__(self, hs: "HomeServer"):
)
preset_config["encrypted"] = encrypted

self._default_power_level_content_override = (
self.config.room.default_power_level_content_override
)

self._replication = hs.get_replication_data_handler()

# linearizer to stop two upgrades happening at once
Expand Down Expand Up @@ -1046,15 +1050,12 @@ async def send(etype: str, content: JsonDict, **kwargs: Any) -> int:

# If the server config contains default_power_level_content_override,
# and that contains information for this room preset, apply it.
default_power_level_content_override = (
self.config.room.default_power_level_content_override
)
if (
default_power_level_content_override
and default_power_level_content_override.get(preset_config)
self._default_power_level_content_override
and self._default_power_level_content_override.get(preset_config)
):
power_level_content.update(
default_power_level_content_override.get(preset_config)
self._default_power_level_content_override.get(preset_config)
)

# Finally, if the user supplied specific permissions for this room,
Expand Down
102 changes: 23 additions & 79 deletions tests/rest/client/test_rooms.py
Original file line number Diff line number Diff line change
Expand Up @@ -1136,33 +1136,6 @@ def power_levels(self, room_id: str) -> Dict[str, Any]:
room_id, "m.room.power_levels", self.admin_access_token
)

def test_default_power_levels_without_override(self) -> None:
room_id = self.helper.create_room_as(self.user_id)
self.assertEqual(
{
"ban": 50,
"events": {
"m.room.avatar": 50,
"m.room.canonical_alias": 50,
"m.room.encryption": 100,
"m.room.history_visibility": 100,
"m.room.name": 50,
"m.room.power_levels": 100,
"m.room.server_acl": 100,
"m.room.tombstone": 100,
},
"events_default": 0,
"historical": 100,
"invite": 50,
"kick": 50,
"redact": 50,
"state_default": 50,
"users": {"@sid1:red": 100},
"users_default": 0,
},
self.power_levels(room_id),
)

def test_default_power_levels_with_room_override(self) -> None:
"""
Create a room, providing power level overrides.
Expand All @@ -1181,20 +1154,9 @@ def test_default_power_levels_with_room_override(self) -> None:
)
self.assertEqual(
{
"ban": 50,
"events": {
"custom.event": 0,
},
"events_default": 0,
"historical": 100,
"invite": 50,
"kick": 50,
"redact": 50,
"state_default": 50,
"users": {"@sid1:red": 100},
"users_default": 0,
"custom.event": 0,
},
self.power_levels(room_id),
self.power_levels(room_id)["events"],
)

@unittest.override_config(
Expand All @@ -1217,20 +1179,9 @@ def test_power_levels_with_server_override(self) -> None:
room_id = self.helper.create_room_as(self.user_id)
self.assertEqual(
{
"ban": 50,
"events": {
"custom.event": 0,
},
"events_default": 0,
"historical": 100,
"invite": 50,
"kick": 50,
"redact": 50,
"state_default": 50,
"users": {"@sid1:red": 100},
"users_default": 0,
"custom.event": 0,
},
self.power_levels(room_id),
self.power_levels(room_id)["events"],
)

@unittest.override_config(
Expand All @@ -1246,7 +1197,7 @@ def test_power_levels_with_server_override(self) -> None:
def test_power_levels_with_server_and_room_overrides(self) -> None:
"""
With a server configured to modify the room-level defaults,
Create a room, providing different overrides.
create a room, providing different overrides.
Confirm that the room's power levels reflect both overrides, and
choose the room overrides where they clash.
"""
Expand All @@ -1258,28 +1209,21 @@ def test_power_levels_with_server_and_room_overrides(self) -> None:
},
)

# Room override wins over server config
self.assertEqual(
{
"ban": 13, # From server config override
"events": {
"room.event": 0, # From room override
},
"events_default": 0,
"historical": 100,
"invite": 50,
"kick": 50,
"redact": 50,
"state_default": 50,
"users": {"@sid1:red": 100},
"users_default": 0,
},
self.power_levels(room_id),
{"room.event": 0},
self.power_levels(room_id)["events"],
)

# But where there is no room override, server config wins
self.assertEqual(13, self.power_levels(room_id)["ban"])


class RoomPowerLevelOverridesInPracticeTestCase(RoomBase):
"""Tests that we can really do various otherwise-prohibited actions
based on overriding the power levels in config."""
"""
Tests that we can really do various otherwise-prohibited actions
based on overriding the power levels in config.
"""

user_id = "@sid1:red"

Expand Down Expand Up @@ -1311,7 +1255,7 @@ def test_normal_user_can_not_post_state_event(self) -> None:
self.assertEqual(403, channel.code, msg=channel.result["body"])
self.assertEqual(
"You don't have permission to post that to the room. "
+ "user_level (0) < send_level (50)",
"user_level (0) < send_level (50)",
channel.json_body["error"],
)

Expand All @@ -1323,8 +1267,8 @@ def test_normal_user_can_not_post_state_event(self) -> None:
},
)
def test_with_config_override_normal_user_can_post_state_event(self) -> None:
# Given the server has config allowing normal users to post my event type
# And I am a normal member of a room
# Given the server has config allowing normal users to post my event type,
# and I am a normal member of a room
room_id = self.helper.create_room_as("@some_other_guy:red")
self.helper.join(room=room_id, user=self.user_id)

Expand Down Expand Up @@ -1373,9 +1317,9 @@ def test_any_room_override_defeats_config_override(self) -> None:
},
)
def test_specific_room_override_defeats_config_override(self) -> None:
# Given the server has config allowing normal users to post my event type
# And I am a normal member of a room
# But the room was created with special permissions for this event type
# Given the server has config allowing normal users to post my event type,
# and I am a normal member of a room,
# but the room was created with special permissions for this event type
extra_content = {
"power_level_content_override": {"events": {"custom.event": 1}},
}
Expand Down Expand Up @@ -1408,8 +1352,8 @@ def test_specific_room_override_defeats_config_override(self) -> None:
},
)
def test_config_override_applies_only_to_specific_preset(self) -> None:
# Given the server has config for public_chats
# And I am a normal member of a private_chat room
# Given the server has config for public_chats,
# and I am a normal member of a private_chat room
room_id = self.helper.create_room_as("@some_other_guy:red", is_public=False)
self.helper.invite(room=room_id, src="@some_other_guy:red", targ=self.user_id)
self.helper.join(room=room_id, user=self.user_id)
Expand Down