25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

162 lines
5.4 KiB

  1. # Copyright 2018 New Vector Ltd
  2. # Copyright 2021 Matrix.org Foundation C.I.C.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. from typing import Any, Collection
  16. from matrix_common.regex import glob_to_regex
  17. from synapse.types import JsonDict
  18. from ._base import Config, ConfigError
  19. class RoomDirectoryConfig(Config):
  20. section = "roomdirectory"
  21. def read_config(self, config: JsonDict, **kwargs: Any) -> None:
  22. self.enable_room_list_search = config.get("enable_room_list_search", True)
  23. alias_creation_rules = config.get("alias_creation_rules")
  24. if alias_creation_rules is not None:
  25. self._alias_creation_rules = [
  26. _RoomDirectoryRule("alias_creation_rules", rule)
  27. for rule in alias_creation_rules
  28. ]
  29. else:
  30. self._alias_creation_rules = [
  31. _RoomDirectoryRule("alias_creation_rules", {"action": "allow"})
  32. ]
  33. room_list_publication_rules = config.get("room_list_publication_rules")
  34. if room_list_publication_rules is not None:
  35. self._room_list_publication_rules = [
  36. _RoomDirectoryRule("room_list_publication_rules", rule)
  37. for rule in room_list_publication_rules
  38. ]
  39. else:
  40. self._room_list_publication_rules = [
  41. _RoomDirectoryRule("room_list_publication_rules", {"action": "allow"})
  42. ]
  43. def is_alias_creation_allowed(self, user_id: str, room_id: str, alias: str) -> bool:
  44. """Checks if the given user is allowed to create the given alias
  45. Args:
  46. user_id: The user to check.
  47. room_id: The room ID for the alias.
  48. alias: The alias being created.
  49. Returns:
  50. True if user is allowed to create the alias
  51. """
  52. for rule in self._alias_creation_rules:
  53. if rule.matches(user_id, room_id, [alias]):
  54. return rule.action == "allow"
  55. return False
  56. def is_publishing_room_allowed(
  57. self, user_id: str, room_id: str, aliases: Collection[str]
  58. ) -> bool:
  59. """Checks if the given user is allowed to publish the room
  60. Args:
  61. user_id: The user ID publishing the room.
  62. room_id: The room being published.
  63. aliases: any local aliases associated with the room
  64. Returns:
  65. True if user can publish room
  66. """
  67. for rule in self._room_list_publication_rules:
  68. if rule.matches(user_id, room_id, aliases):
  69. return rule.action == "allow"
  70. return False
  71. class _RoomDirectoryRule:
  72. """Helper class to test whether a room directory action is allowed, like
  73. creating an alias or publishing a room.
  74. """
  75. def __init__(self, option_name: str, rule: JsonDict):
  76. """
  77. Args:
  78. option_name: Name of the config option this rule belongs to
  79. rule: The rule as specified in the config
  80. """
  81. action = rule["action"]
  82. user_id = rule.get("user_id", "*")
  83. room_id = rule.get("room_id", "*")
  84. alias = rule.get("alias", "*")
  85. if action in ("allow", "deny"):
  86. self.action = action
  87. else:
  88. raise ConfigError(
  89. "%s rules can only have action of 'allow' or 'deny'" % (option_name,)
  90. )
  91. self._alias_matches_all = alias == "*"
  92. try:
  93. self._user_id_regex = glob_to_regex(user_id)
  94. self._alias_regex = glob_to_regex(alias)
  95. self._room_id_regex = glob_to_regex(room_id)
  96. except Exception as e:
  97. raise ConfigError("Failed to parse glob into regex") from e
  98. def matches(self, user_id: str, room_id: str, aliases: Collection[str]) -> bool:
  99. """Tests if this rule matches the given user_id, room_id and aliases.
  100. Args:
  101. user_id: The user ID to check.
  102. room_id: The room ID to check.
  103. aliases: The associated aliases to the room. Will be a single element
  104. for testing alias creation, and can be empty for testing room
  105. publishing.
  106. Returns:
  107. True if the rule matches.
  108. """
  109. # Note: The regexes are anchored at both ends
  110. if not self._user_id_regex.match(user_id):
  111. return False
  112. if not self._room_id_regex.match(room_id):
  113. return False
  114. # We only have alias checks left, so we can short circuit if the alias
  115. # rule matches everything.
  116. if self._alias_matches_all:
  117. return True
  118. # If we are not given any aliases then this rule only matches if the
  119. # alias glob matches all aliases, which we checked above.
  120. if not aliases:
  121. return False
  122. # Otherwise, we just need one alias to match
  123. for alias in aliases:
  124. if self._alias_regex.match(alias):
  125. return True
  126. return False