summary refs log tree commit diff
diff options
context:
space:
mode:
authorSean Quah <seanq@element.io>2021-11-18 16:06:38 +0000
committerSean Quah <seanq@element.io>2021-11-18 16:06:38 +0000
commite5751a6350a796ff5229a9cf29042fc83b15ca86 (patch)
treefea61c4f9e68204e6f4ecd52543d2b6765ee0af5
parentFix bug/redundant code to do with handling of the root space id (diff)
downloadsynapse-e5751a6350a796ff5229a9cf29042fc83b15ca86.tar.xz
Revert "Convert strings in `synapse.api.constants` to enums or `Final`"
This reverts commit b43d085472390c77691fbbd86b3e66b4a1a0cb6d.
-rw-r--r--changelog.d/11356.misc2
-rw-r--r--synapse/api/auth.py4
-rw-r--r--synapse/api/constants.py235
-rw-r--r--synapse/event_auth.py2
-rw-r--r--synapse/events/validator.py4
-rw-r--r--synapse/handlers/auth.py5
-rw-r--r--synapse/handlers/federation.py2
-rw-r--r--synapse/push/bulk_push_rule_evaluator.py5
-rw-r--r--synapse/rest/admin/users.py14
-rw-r--r--synapse/rest/client/register.py2
-rw-r--r--synapse/state/v1.py6
-rw-r--r--synapse/util/enum.py27
12 files changed, 135 insertions, 173 deletions
diff --git a/changelog.d/11356.misc b/changelog.d/11356.misc
index e93b3ddd38..01ce6a306c 100644
--- a/changelog.d/11356.misc
+++ b/changelog.d/11356.misc
@@ -1 +1 @@
-Convert most string constants in `synapse.api.constants` into enums, so that they are usable as `Literal`s, and make the rest `Final`.
+Add `Final` annotation to string constants in `synapse.api.constants` so that they get typed as `Literal`s.
diff --git a/synapse/api/auth.py b/synapse/api/auth.py
index 3004f06fdd..44883c6663 100644
--- a/synapse/api/auth.py
+++ b/synapse/api/auth.py
@@ -34,7 +34,7 @@ from synapse.http import get_request_user_agent
 from synapse.http.site import SynapseRequest
 from synapse.logging import opentracing as opentracing
 from synapse.storage.databases.main.registration import TokenLookupResult
-from synapse.types import MutableStateMap, Requester, StateMap, UserID, create_requester
+from synapse.types import Requester, StateMap, UserID, create_requester
 from synapse.util.caches.lrucache import LruCache
 from synapse.util.macaroons import get_value_from_macaroon, satisfy_expiry
 
@@ -511,7 +511,7 @@ class Auth:
             room_id, EventTypes.PowerLevels, ""
         )
 
-        auth_events: MutableStateMap[EventBase] = {}
+        auth_events = {}
         if power_level_event:
             auth_events[(EventTypes.PowerLevels, "")] = power_level_event
 
diff --git a/synapse/api/constants.py b/synapse/api/constants.py
index e3ed86f57b..f7d29b4319 100644
--- a/synapse/api/constants.py
+++ b/synapse/api/constants.py
@@ -19,8 +19,6 @@
 
 from typing_extensions import Final
 
-from synapse.util.enum import StrEnum
-
 # the max size of a (canonical-json-encoded) event
 MAX_PDU_SIZE = 65536
 
@@ -39,49 +37,51 @@ MAX_GROUP_CATEGORYID_LENGTH = 255
 MAX_GROUP_ROLEID_LENGTH = 255
 
 
-class Membership(StrEnum):
+class Membership:
+
     """Represents the membership states of a user in a room."""
 
-    INVITE = "invite"
-    JOIN = "join"
-    KNOCK = "knock"
-    LEAVE = "leave"
-    BAN = "ban"
+    INVITE: Final = "invite"
+    JOIN: Final = "join"
+    KNOCK: Final = "knock"
+    LEAVE: Final = "leave"
+    BAN: Final = "ban"
+    LIST: Final = (INVITE, JOIN, KNOCK, LEAVE, BAN)
 
 
-class PresenceState(StrEnum):
+class PresenceState:
     """Represents the presence state of a user."""
 
-    OFFLINE = "offline"
-    UNAVAILABLE = "unavailable"
-    ONLINE = "online"
-    BUSY = "org.matrix.msc3026.busy"
+    OFFLINE: Final = "offline"
+    UNAVAILABLE: Final = "unavailable"
+    ONLINE: Final = "online"
+    BUSY: Final = "org.matrix.msc3026.busy"
 
 
-class JoinRules(StrEnum):
-    PUBLIC = "public"
-    KNOCK = "knock"
-    INVITE = "invite"
-    PRIVATE = "private"
+class JoinRules:
+    PUBLIC: Final = "public"
+    KNOCK: Final = "knock"
+    INVITE: Final = "invite"
+    PRIVATE: Final = "private"
     # As defined for MSC3083.
-    RESTRICTED = "restricted"
+    RESTRICTED: Final = "restricted"
 
 
-class RestrictedJoinRuleTypes(StrEnum):
+class RestrictedJoinRuleTypes:
     """Understood types for the allow rules in restricted join rules."""
 
-    ROOM_MEMBERSHIP = "m.room_membership"
+    ROOM_MEMBERSHIP: Final = "m.room_membership"
 
 
-class LoginType(StrEnum):
-    PASSWORD = "m.login.password"
-    EMAIL_IDENTITY = "m.login.email.identity"
-    MSISDN = "m.login.msisdn"
-    RECAPTCHA = "m.login.recaptcha"
-    TERMS = "m.login.terms"
-    SSO = "m.login.sso"
-    DUMMY = "m.login.dummy"
-    REGISTRATION_TOKEN = "org.matrix.msc3231.login.registration_token"
+class LoginType:
+    PASSWORD: Final = "m.login.password"
+    EMAIL_IDENTITY: Final = "m.login.email.identity"
+    MSISDN: Final = "m.login.msisdn"
+    RECAPTCHA: Final = "m.login.recaptcha"
+    TERMS: Final = "m.login.terms"
+    SSO: Final = "m.login.sso"
+    DUMMY: Final = "m.login.dummy"
+    REGISTRATION_TOKEN: Final = "org.matrix.msc3231.login.registration_token"
 
 
 # This is used in the `type` parameter for /register when called by
@@ -89,168 +89,169 @@ class LoginType(StrEnum):
 APP_SERVICE_REGISTRATION_TYPE: Final = "m.login.application_service"
 
 
-class EventTypes(StrEnum):
-    Member = "m.room.member"
-    Create = "m.room.create"
-    Tombstone = "m.room.tombstone"
-    JoinRules = "m.room.join_rules"
-    PowerLevels = "m.room.power_levels"
-    Aliases = "m.room.aliases"
-    Redaction = "m.room.redaction"
-    ThirdPartyInvite = "m.room.third_party_invite"
-    RelatedGroups = "m.room.related_groups"
-
-    RoomHistoryVisibility = "m.room.history_visibility"
-    CanonicalAlias = "m.room.canonical_alias"
-    Encrypted = "m.room.encrypted"
-    RoomAvatar = "m.room.avatar"
-    RoomEncryption = "m.room.encryption"
-    GuestAccess = "m.room.guest_access"
+class EventTypes:
+    Member: Final = "m.room.member"
+    Create: Final = "m.room.create"
+    Tombstone: Final = "m.room.tombstone"
+    JoinRules: Final = "m.room.join_rules"
+    PowerLevels: Final = "m.room.power_levels"
+    Aliases: Final = "m.room.aliases"
+    Redaction: Final = "m.room.redaction"
+    ThirdPartyInvite: Final = "m.room.third_party_invite"
+    RelatedGroups: Final = "m.room.related_groups"
+
+    RoomHistoryVisibility: Final = "m.room.history_visibility"
+    CanonicalAlias: Final = "m.room.canonical_alias"
+    Encrypted: Final = "m.room.encrypted"
+    RoomAvatar: Final = "m.room.avatar"
+    RoomEncryption: Final = "m.room.encryption"
+    GuestAccess: Final = "m.room.guest_access"
 
     # These are used for validation
-    Message = "m.room.message"
-    Topic = "m.room.topic"
-    Name = "m.room.name"
+    Message: Final = "m.room.message"
+    Topic: Final = "m.room.topic"
+    Name: Final = "m.room.name"
 
-    ServerACL = "m.room.server_acl"
-    Pinned = "m.room.pinned_events"
+    ServerACL: Final = "m.room.server_acl"
+    Pinned: Final = "m.room.pinned_events"
 
-    Retention = "m.room.retention"
+    Retention: Final = "m.room.retention"
 
-    Dummy = "org.matrix.dummy_event"
+    Dummy: Final = "org.matrix.dummy_event"
 
-    SpaceChild = "m.space.child"
-    SpaceParent = "m.space.parent"
+    SpaceChild: Final = "m.space.child"
+    SpaceParent: Final = "m.space.parent"
 
-    MSC2716_INSERTION = "org.matrix.msc2716.insertion"
-    MSC2716_BATCH = "org.matrix.msc2716.batch"
-    MSC2716_MARKER = "org.matrix.msc2716.marker"
+    MSC2716_INSERTION: Final = "org.matrix.msc2716.insertion"
+    MSC2716_BATCH: Final = "org.matrix.msc2716.batch"
+    MSC2716_MARKER: Final = "org.matrix.msc2716.marker"
 
 
-class ToDeviceEventTypes(StrEnum):
-    RoomKeyRequest = "m.room_key_request"
+class ToDeviceEventTypes:
+    RoomKeyRequest: Final = "m.room_key_request"
 
 
-class DeviceKeyAlgorithms(StrEnum):
+class DeviceKeyAlgorithms:
     """Spec'd algorithms for the generation of per-device keys"""
 
-    ED25519 = "ed25519"
-    CURVE25519 = "curve25519"
-    SIGNED_CURVE25519 = "signed_curve25519"
+    ED25519: Final = "ed25519"
+    CURVE25519: Final = "curve25519"
+    SIGNED_CURVE25519: Final = "signed_curve25519"
 
 
-class EduTypes(StrEnum):
-    Presence = "m.presence"
+class EduTypes:
+    Presence: Final = "m.presence"
 
 
-class RejectedReason(StrEnum):
-    AUTH_ERROR = "auth_error"
+class RejectedReason:
+    AUTH_ERROR: Final = "auth_error"
 
 
-class RoomCreationPreset(StrEnum):
-    PRIVATE_CHAT = "private_chat"
-    PUBLIC_CHAT = "public_chat"
-    TRUSTED_PRIVATE_CHAT = "trusted_private_chat"
+class RoomCreationPreset:
+    PRIVATE_CHAT: Final = "private_chat"
+    PUBLIC_CHAT: Final = "public_chat"
+    TRUSTED_PRIVATE_CHAT: Final = "trusted_private_chat"
 
 
-class ThirdPartyEntityKind(StrEnum):
-    USER = "user"
-    LOCATION = "location"
+class ThirdPartyEntityKind:
+    USER: Final = "user"
+    LOCATION: Final = "location"
 
 
 ServerNoticeMsgType: Final = "m.server_notice"
 ServerNoticeLimitReached: Final = "m.server_notice.usage_limit_reached"
 
 
-class UserTypes(StrEnum):
+class UserTypes:
     """Allows for user type specific behaviour. With the benefit of hindsight
     'admin' and 'guest' users should also be UserTypes. Normal users are type None
     """
 
-    SUPPORT = "support"
-    BOT = "bot"
+    SUPPORT: Final = "support"
+    BOT: Final = "bot"
+    ALL_USER_TYPES: Final = (SUPPORT, BOT)
 
 
-class RelationTypes(StrEnum):
+class RelationTypes:
     """The types of relations known to this server."""
 
-    ANNOTATION = "m.annotation"
-    REPLACE = "m.replace"
-    REFERENCE = "m.reference"
-    THREAD = "io.element.thread"
+    ANNOTATION: Final = "m.annotation"
+    REPLACE: Final = "m.replace"
+    REFERENCE: Final = "m.reference"
+    THREAD: Final = "io.element.thread"
 
 
-class LimitBlockingTypes(StrEnum):
+class LimitBlockingTypes:
     """Reasons that a server may be blocked"""
 
-    MONTHLY_ACTIVE_USER = "monthly_active_user"
-    HS_DISABLED = "hs_disabled"
+    MONTHLY_ACTIVE_USER: Final = "monthly_active_user"
+    HS_DISABLED: Final = "hs_disabled"
 
 
-class EventContentFields(StrEnum):
+class EventContentFields:
     """Fields found in events' content, regardless of type."""
 
     # Labels for the event, cf https://github.com/matrix-org/matrix-doc/pull/2326
-    LABELS = "org.matrix.labels"
+    LABELS: Final = "org.matrix.labels"
 
     # Timestamp to delete the event after
     # cf https://github.com/matrix-org/matrix-doc/pull/2228
-    SELF_DESTRUCT_AFTER = "org.matrix.self_destruct_after"
+    SELF_DESTRUCT_AFTER: Final = "org.matrix.self_destruct_after"
 
     # cf https://github.com/matrix-org/matrix-doc/pull/1772
-    ROOM_TYPE = "type"
+    ROOM_TYPE: Final = "type"
 
     # Whether a room can federate.
-    FEDERATE = "m.federate"
+    FEDERATE: Final = "m.federate"
 
     # The creator of the room, as used in `m.room.create` events.
-    ROOM_CREATOR = "creator"
+    ROOM_CREATOR: Final = "creator"
 
     # Used in m.room.guest_access events.
-    GUEST_ACCESS = "guest_access"
+    GUEST_ACCESS: Final = "guest_access"
 
     # Used on normal messages to indicate they were historically imported after the fact
-    MSC2716_HISTORICAL = "org.matrix.msc2716.historical"
+    MSC2716_HISTORICAL: Final = "org.matrix.msc2716.historical"
     # For "insertion" events to indicate what the next batch ID should be in
     # order to connect to it
-    MSC2716_NEXT_BATCH_ID = "org.matrix.msc2716.next_batch_id"
+    MSC2716_NEXT_BATCH_ID: Final = "org.matrix.msc2716.next_batch_id"
     # Used on "batch" events to indicate which insertion event it connects to
-    MSC2716_BATCH_ID = "org.matrix.msc2716.batch_id"
+    MSC2716_BATCH_ID: Final = "org.matrix.msc2716.batch_id"
     # For "marker" events
-    MSC2716_MARKER_INSERTION = "org.matrix.msc2716.marker.insertion"
+    MSC2716_MARKER_INSERTION: Final = "org.matrix.msc2716.marker.insertion"
 
     # The authorising user for joining a restricted room.
-    AUTHORISING_USER = "join_authorised_via_users_server"
+    AUTHORISING_USER: Final = "join_authorised_via_users_server"
 
 
-class RoomTypes(StrEnum):
+class RoomTypes:
     """Understood values of the room_type field of m.room.create events."""
 
-    SPACE = "m.space"
+    SPACE: Final = "m.space"
 
 
-class RoomEncryptionAlgorithms(StrEnum):
-    MEGOLM_V1_AES_SHA2 = "m.megolm.v1.aes-sha2"
-    DEFAULT = MEGOLM_V1_AES_SHA2
+class RoomEncryptionAlgorithms:
+    MEGOLM_V1_AES_SHA2: Final = "m.megolm.v1.aes-sha2"
+    DEFAULT: Final = MEGOLM_V1_AES_SHA2
 
 
-class AccountDataTypes(StrEnum):
-    DIRECT = "m.direct"
-    IGNORED_USER_LIST = "m.ignored_user_list"
+class AccountDataTypes:
+    DIRECT: Final = "m.direct"
+    IGNORED_USER_LIST: Final = "m.ignored_user_list"
 
 
-class HistoryVisibility(StrEnum):
-    INVITED = "invited"
-    JOINED = "joined"
-    SHARED = "shared"
-    WORLD_READABLE = "world_readable"
+class HistoryVisibility:
+    INVITED: Final = "invited"
+    JOINED: Final = "joined"
+    SHARED: Final = "shared"
+    WORLD_READABLE: Final = "world_readable"
 
 
-class GuestAccess(StrEnum):
-    CAN_JOIN = "can_join"
+class GuestAccess:
+    CAN_JOIN: Final = "can_join"
     # anything that is not "can_join" is considered "forbidden", but for completeness:
-    FORBIDDEN = "forbidden"
+    FORBIDDEN: Final = "forbidden"
 
 
-class ReadReceiptEventFields(StrEnum):
-    MSC2285_HIDDEN = "org.matrix.msc2285.hidden"
+class ReadReceiptEventFields:
+    MSC2285_HIDDEN: Final = "org.matrix.msc2285.hidden"
diff --git a/synapse/event_auth.py b/synapse/event_auth.py
index 39fb4a3641..e885961698 100644
--- a/synapse/event_auth.py
+++ b/synapse/event_auth.py
@@ -840,7 +840,7 @@ def get_public_keys(invite_event: EventBase) -> List[Dict[str, Any]]:
 
 def auth_types_for_event(
     room_version: RoomVersion, event: Union[EventBase, EventBuilder]
-) -> Set[Tuple[EventTypes, str]]:
+) -> Set[Tuple[str, str]]:
     """Given an event, return a list of (EventType, StateKey) that may be
     needed to auth the event. The returned list may be a superset of what
     would actually be required depending on the full state of the room.
diff --git a/synapse/events/validator.py b/synapse/events/validator.py
index f6fa96ba3c..cf86934968 100644
--- a/synapse/events/validator.py
+++ b/synapse/events/validator.py
@@ -189,9 +189,7 @@ class EventValidator:
             if "membership" not in event.content:
                 raise SynapseError(400, "Content has not membership key")
 
-            try:
-                Membership(event.content["membership"])
-            except ValueError:
+            if event.content["membership"] not in Membership.LIST:
                 raise SynapseError(400, "Invalid membership key")
 
             self._ensure_state_event(event)
diff --git a/synapse/handlers/auth.py b/synapse/handlers/auth.py
index ab734134ee..b62e13b725 100644
--- a/synapse/handlers/auth.py
+++ b/synapse/handlers/auth.py
@@ -28,7 +28,6 @@ from typing import (
     List,
     Mapping,
     Optional,
-    Set,
     Tuple,
     Type,
     Union,
@@ -383,7 +382,7 @@ class AuthHandler:
     async def _get_available_ui_auth_types(self, user: UserID) -> Iterable[str]:
         """Get a list of the authentication types this user can use"""
 
-        ui_auth_types: Set[str] = set()
+        ui_auth_types = set()
 
         # if the HS supports password auth, and the user has a non-null password, we
         # support password auth
@@ -736,7 +735,7 @@ class AuthHandler:
         for f in flows:
             public_flows.append(f)
 
-        get_params: Dict[str, Any] = {
+        get_params = {
             LoginType.RECAPTCHA: self._get_params_recaptcha,
             LoginType.TERMS: self._get_params_terms,
         }
diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py
index 4f543973f2..3112cc88b1 100644
--- a/synapse/handlers/federation.py
+++ b/synapse/handlers/federation.py
@@ -686,7 +686,7 @@ class FederationHandler:
             )
             raise NotFoundError("Not an active room on this server")
 
-        event_content: JsonDict = {"membership": Membership.JOIN}
+        event_content = {"membership": Membership.JOIN}
 
         # If the current room is using restricted join rules, additional information
         # may need to be included in the event content in order to efficiently
diff --git a/synapse/push/bulk_push_rule_evaluator.py b/synapse/push/bulk_push_rule_evaluator.py
index 86377fbb1d..009d8e77b0 100644
--- a/synapse/push/bulk_push_rule_evaluator.py
+++ b/synapse/push/bulk_push_rule_evaluator.py
@@ -24,7 +24,6 @@ from synapse.event_auth import get_user_power_level
 from synapse.events import EventBase
 from synapse.events.snapshot import EventContext
 from synapse.state import POWER_KEY
-from synapse.types import StateMap
 from synapse.util.async_helpers import Linearizer
 from synapse.util.caches import CacheMetric, register_cache
 from synapse.util.caches.descriptors import lru_cache
@@ -171,9 +170,7 @@ class BulkPushRuleEvaluator:
         if pl_event_id:
             # fastpath: if there's a power level event, that's all we need, and
             # not having a power level event is an extreme edge case
-            auth_events: StateMap[EventBase] = {
-                POWER_KEY: await self.store.get_event(pl_event_id)
-            }
+            auth_events = {POWER_KEY: await self.store.get_event(pl_event_id)}
         else:
             auth_events_ids = self._event_auth_handler.compute_auth_events(
                 event, prev_state_ids, for_verification=False
diff --git a/synapse/rest/admin/users.py b/synapse/rest/admin/users.py
index 3f78225882..23a8bf1fdb 100644
--- a/synapse/rest/admin/users.py
+++ b/synapse/rest/admin/users.py
@@ -209,11 +209,8 @@ class UserRestServletV2(RestServlet):
                 assert_params_in_dict(external_id, ["auth_provider", "external_id"])
 
         user_type = body.get("user_type", None)
-        if user_type is not None:
-            try:
-                UserTypes(user_type)
-            except ValueError:
-                raise SynapseError(400, "Invalid user type")
+        if user_type is not None and user_type not in UserTypes.ALL_USER_TYPES:
+            raise SynapseError(400, "Invalid user type")
 
         set_admin_to = body.get("admin", False)
         if not isinstance(set_admin_to, bool):
@@ -484,11 +481,8 @@ class UserRegisterServlet(RestServlet):
         user_type = body.get("user_type", None)
         displayname = body.get("displayname", None)
 
-        if user_type is not None:
-            try:
-                UserTypes(user_type)
-            except ValueError:
-                raise SynapseError(400, "Invalid user type")
+        if user_type is not None and user_type not in UserTypes.ALL_USER_TYPES:
+            raise SynapseError(400, "Invalid user type")
 
         if "mac" not in body:
             raise SynapseError(400, "mac must be specified", errcode=Codes.BAD_JSON)
diff --git a/synapse/rest/client/register.py b/synapse/rest/client/register.py
index 9293f4f3d5..bf3cb34146 100644
--- a/synapse/rest/client/register.py
+++ b/synapse/rest/client/register.py
@@ -876,7 +876,7 @@ def _calculate_registration_flows(
                 "validation is not configured"
             )
 
-    flows: List[List[str]] = []
+    flows = []
 
     # only support 3PIDless registration if no 3PIDs are required
     if not require_email and not require_msisdn:
diff --git a/synapse/state/v1.py b/synapse/state/v1.py
index bfa676d1ac..6edadea550 100644
--- a/synapse/state/v1.py
+++ b/synapse/state/v1.py
@@ -204,7 +204,7 @@ def _create_auth_events_from_maps(
     Returns:
         A map from state key to event id.
     """
-    auth_events: MutableStateMap[str] = {}
+    auth_events = {}
     for event_ids in conflicted_state.values():
         for event_id in event_ids:
             if event_id in state_map:
@@ -269,7 +269,7 @@ def _resolve_state_events(
         3. memberships
         4. other events.
     """
-    resolved_state: MutableStateMap[EventBase] = {}
+    resolved_state = {}
     if POWER_KEY in conflicted_state:
         events = conflicted_state[POWER_KEY]
         logger.debug("Resolving conflicted power levels %r", events)
@@ -316,7 +316,7 @@ def _resolve_auth_events(
         for key in event_auth.auth_types_for_event(room_version, event)
     }
 
-    new_auth_events: MutableStateMap[EventBase] = {}
+    new_auth_events = {}
     for key in auth_keys:
         auth_event = auth_events.get(key, None)
         if auth_event:
diff --git a/synapse/util/enum.py b/synapse/util/enum.py
deleted file mode 100644
index c7a7d18437..0000000000
--- a/synapse/util/enum.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2021 The Matrix.org Foundation C.I.C.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from enum import Enum
-
-
-class StrEnum(str, Enum):
-    """Enum where members are also (and must be) strings
-
-    Similar to `IntEnum` except for strings.
-    Comparison and JSON serialization work as expected.
-    Interchangeable with regular strings when used as dictionary keys.
-    """
-
-    __str__ = str.__str__
-    __format__ = str.__format__