Skip to content

Commit

Permalink
Add bypass_for_users config (#6)
Browse files Browse the repository at this point in the history
Co-authored-by: mcalinghee <mcalinghee.dev@gmail.com>
  • Loading branch information
MatMaul and mcalinghee authored Jun 27, 2024
1 parent e8c00a0 commit 66e3a94
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 1 deletion.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ modules:
# Identity server to use when checking the homeserver an email address belongs to
# using the /info endpoint. Required.
id_server: "vector.im"
# Disable access rules for this list of users
bypass_for_users: []
```
## Development and Testing
Expand Down
30 changes: 30 additions & 0 deletions room_access_rules/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class AccessRules:
@attr.s(frozen=True, auto_attribs=True)
class RoomAccessRulesConfig:
id_server: str
bypass_for_users: List[str] = []
domains_forbidden_when_restricted: List[str] = []
fix_admins_for_dm_power_levels: bool = False
add_live_location_power_levels: bool = False
Expand Down Expand Up @@ -306,6 +307,12 @@ async def on_create_room(
access_rule = None
join_rule = None

if (
is_requester_admin
or requester.user.to_string() in self.config.bypass_for_users
):
return True

# If there's a rules event in the initial state, check if it complies with the
# spec for im.vector.room.access_rules and deny the request if not.
for event in config.get("initial_state", []):
Expand Down Expand Up @@ -486,6 +493,14 @@ async def check_threepid_can_be_invited(

return True

async def _user_can_bypass_rules(self, user_id: str) -> bool:
if (
user_id in self.config.bypass_for_users
or await self.module_api.is_user_admin(user_id)
):
return True
return False

async def check_event_allowed(
self,
event: EventBase,
Expand All @@ -504,6 +519,9 @@ async def check_event_allowed(
allowed, False if it should be rejected. The second entry is always
None because this module doesn't replace event contents.
"""
if await self._user_can_bypass_rules(event.sender):
return True, None

# We check the rules when altering the state of the room, so only go further if
# the event is a state event.
if event.is_state():
Expand Down Expand Up @@ -643,6 +661,18 @@ async def _on_membership_or_invite(
Returns:
A boolean indicating whether the event is allowed.
"""

# Let's ignore rules if the user is accepting an invite coming from
# an user in the bypass list or an admin
if event.type == EventTypes.Member and event.membership == Membership.JOIN:
previous_membership = state_events.get((EventTypes.Member, event.state_key))
if (
previous_membership
and previous_membership.membership == Membership.INVITE
):
if await self._user_can_bypass_rules(previous_membership.sender):
return True

if rule == AccessRules.RESTRICTED:
ret = self._on_membership_or_invite_restricted(event)
elif rule == AccessRules.UNRESTRICTED:
Expand Down
3 changes: 2 additions & 1 deletion tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import Any, Dict, Optional
from unittest.mock import Mock
from unittest.mock import AsyncMock, Mock

import attr
from synapse.module_api import ModuleApi, UserID
Expand Down Expand Up @@ -87,6 +87,7 @@ def create_module(
module_api.http_client = MockHttpClient()
module_api.public_room_list_manager = MockPublicRoomListManager()
module_api._hs = MockHomeserver()
module_api.is_user_admin = AsyncMock(return_value=False)

if config_override is None:
config_override = {}
Expand Down

0 comments on commit 66e3a94

Please sign in to comment.