diff --git a/synapse/events/validator.py b/synapse/events/validator.py
index 6f0e4386d3..47203209db 100644
--- a/synapse/events/validator.py
+++ b/synapse/events/validator.py
@@ -12,11 +12,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import collections.abc
-from typing import Iterable, Type, Union, cast
+from typing import Iterable, List, Type, Union, cast
import jsonschema
+from pydantic import Field, StrictBool, StrictStr
-from synapse.api.constants import MAX_ALIAS_LENGTH, EventTypes, Membership
+from synapse.api.constants import (
+ MAX_ALIAS_LENGTH,
+ EventContentFields,
+ EventTypes,
+ Membership,
+)
from synapse.api.errors import Codes, SynapseError
from synapse.api.room_versions import EventFormatVersions
from synapse.config.homeserver import HomeServerConfig
@@ -28,6 +34,8 @@ from synapse.events.utils import (
validate_canonicaljson,
)
from synapse.federation.federation_server import server_matches_acl_event
+from synapse.http.servlet import validate_json_object
+from synapse.rest.models import RequestBodyModel
from synapse.types import EventID, JsonDict, RoomID, UserID
@@ -88,27 +96,27 @@ class EventValidator:
Codes.INVALID_PARAM,
)
- if event.type == EventTypes.Retention:
+ elif event.type == EventTypes.Retention:
self._validate_retention(event)
- if event.type == EventTypes.ServerACL:
+ elif event.type == EventTypes.ServerACL:
if not server_matches_acl_event(config.server.server_name, event):
raise SynapseError(
400, "Can't create an ACL event that denies the local server"
)
- if event.type == EventTypes.PowerLevels:
+ elif event.type == EventTypes.PowerLevels:
try:
jsonschema.validate(
instance=event.content,
schema=POWER_LEVELS_SCHEMA,
- cls=plValidator,
+ cls=POWER_LEVELS_VALIDATOR,
)
except jsonschema.ValidationError as e:
if e.path:
# example: "users_default": '0' is not of type 'integer'
# cast safety: path entries can be integers, if we fail to validate
- # items in an array. However the POWER_LEVELS_SCHEMA doesn't expect
+ # items in an array. However, the POWER_LEVELS_SCHEMA doesn't expect
# to see any arrays.
message = (
'"' + cast(str, e.path[-1]) + '": ' + e.message # noqa: B306
@@ -125,6 +133,15 @@ class EventValidator:
errcode=Codes.BAD_JSON,
)
+ # If the event contains a mentions key, validate it.
+ if (
+ EventContentFields.MSC3952_MENTIONS in event.content
+ and config.experimental.msc3952_intentional_mentions
+ ):
+ validate_json_object(
+ event.content[EventContentFields.MSC3952_MENTIONS], Mentions
+ )
+
def _validate_retention(self, event: EventBase) -> None:
"""Checks that an event that defines the retention policy for a room respects the
format enforced by the spec.
@@ -253,10 +270,15 @@ POWER_LEVELS_SCHEMA = {
}
+class Mentions(RequestBodyModel):
+ user_ids: List[StrictStr] = Field(default_factory=list)
+ room: StrictBool = False
+
+
# This could return something newer than Draft 7, but that's the current "latest"
# validator.
-def _create_power_level_validator() -> Type[jsonschema.Draft7Validator]:
- validator = jsonschema.validators.validator_for(POWER_LEVELS_SCHEMA)
+def _create_validator(schema: JsonDict) -> Type[jsonschema.Draft7Validator]:
+ validator = jsonschema.validators.validator_for(schema)
# by default jsonschema does not consider a immutabledict to be an object so
# we need to use a custom type checker
@@ -268,4 +290,4 @@ def _create_power_level_validator() -> Type[jsonschema.Draft7Validator]:
return jsonschema.validators.extend(validator, type_checker=type_checker)
-plValidator = _create_power_level_validator()
+POWER_LEVELS_VALIDATOR = _create_validator(POWER_LEVELS_SCHEMA)
|