diff --git a/changelogs/client_server/newsfragments/1464.clarification b/changelogs/client_server/newsfragments/1464.clarification new file mode 100644 index 00000000..f5bd822e --- /dev/null +++ b/changelogs/client_server/newsfragments/1464.clarification @@ -0,0 +1 @@ +Disambiguate using property names with dots in them during push rule processing, per [MSC3873](https://github.com/matrix-org/matrix-spec-proposals/pull/3873) and [MSC3980](https://github.com/matrix-org/matrix-spec-proposals/pull/3980). diff --git a/changelogs/client_server/newsfragments/1464.feature b/changelogs/client_server/newsfragments/1464.feature new file mode 100644 index 00000000..7c1c01ec --- /dev/null +++ b/changelogs/client_server/newsfragments/1464.feature @@ -0,0 +1 @@ +Add new push rule conditions: `event_property_is` and `event_property_contains` from [MSC3758](https://github.com/matrix-org/matrix-spec-proposals/pull/3758) and [MSC3966](https://github.com/matrix-org/matrix-spec-proposals/pull/3966). diff --git a/content/appendices.md b/content/appendices.md index 446e709a..ee028d24 100644 --- a/content/appendices.md +++ b/content/appendices.md @@ -946,6 +946,22 @@ uses the following rules: * The character `*` matches zero or more characters. * `?` matches exactly one character. +## Dot-separated property paths + +It is useful to express the "path" to an event property by concatenating property +names with dots, e.g. `content.body` would represent a `body` property in the +event's `content`. + +To handle ambiguity when a property name contains a dot, any literal dot or +backslash found in a property name should be escaped with a backslash. E.g. a +property `m.relates_to` in the `content` would be expressed as +`content.m\.relates_to`. Similarly, a `content` property named `m\foo` would be +expressed as `content.m\\foo`. + +Other escape sequences are left as-is, e.g. a `\x` would be treated as a literal +backslash followed by 'x'. It is recommended that implementations do not redundantly +escape characters, as other escape sequences are reserved for future use. + ## Security Threat Model ### Denial of Service diff --git a/content/client-server-api/modules/push.md b/content/client-server-api/modules/push.md index d5056119..a0680649 100644 --- a/content/client-server-api/modules/push.md +++ b/content/client-server-api/modules/push.md @@ -212,15 +212,15 @@ The following conditions are defined: **`event_match`** -This is a glob pattern match on a field of the event. Parameters: +This is a glob pattern match on a property of the event. Parameters: -- `key`: The dot-separated path of the property of the event to match, e.g. - `content.body`. +- `key`: The [dot-separated path of the property](/appendices#dot-separated-property-paths) + of the event to match, e.g. `content.body`. - `pattern`: The [glob-style pattern](/appendices#glob-style-matching) to match against. The match is performed case-insensitively, and must match the entire value of -the event field given by `key` (though see below regarding `content.body`). The +the event property given by `key` (though see below regarding `content.body`). The exact meaning of "case insensitive" is defined by the implementation of the homeserver. @@ -267,7 +267,7 @@ following event will match: ```json { "content": { - "body": "An example event.", + "body": "An example event." }, "event_id": "$143273976499sgjks:example.org", "room_id": "!636q39766251:example.com", @@ -293,6 +293,96 @@ For an example of this, see the default rule [`.m.rule.tombstone`](#mruletombstone) below. {{% /boxes/warning %}} +**`event_property_is`** + +This is an exact value match on a property of the event. Parameters: + +- `key`: The [dot-separated path of the property](/appendices#dot-separated-property-paths) + of the event to match, e.g. `content.body`. + +- `value`: The value to match against. + +The match is performed exactly and only supports non-compound [canonical JSON](/appendices#canonical-json) +values: strings, integers in the range of `[-(2**53)+1, (2**53)-1]`, booleans, and +`null`. + +If the property specified by `key` is completely absent from the event, or does +not have a string, integer, boolean, or `null` value, then the condition will not +match. + +{{% boxes/note %}} +For example, if `key` is `content.m\.federate`, and `value` is `true`, then +the following event will match: + +```json +{ + "content": { + "creator": "@example:example.org", + "m.federate": true, + "predecessor": { + "event_id": "$something:example.org", + "room_id": "!oldroom:example.org" + }, + "room_version": "1" + }, + "event_id": "$143273582443PhrSn:example.org", + "room_id": "!636q39766251:example.com", + "sender": "@example:example.org", + "state_key": "", + "type": "m.room.create" +} +``` + +The following `m.federate` values will NOT match: + * `"true"` (note the string value) + * `1` (do not cast types) +{{% /boxes/note %}} + +**`event_property_contains`** + +This matches if an array property of an event exactly contains a value. Parameters: + +- `key`: The [dot-separated path of the property](/appendices#dot-separated-property-paths) + of the event to match, e.g. `content.body`. + +- `value`: The value to match against. + +The array values are matched exactly and only supports non-compound [canonical JSON](/appendices#canonical-json) +values: strings, integers in the range of `[-(2**53)+1, (2**53)-1]`, booleans, +and `null`. Array values not of those types are ignored. + +If the property specified by `key` is completely absent from the event, or is not +an array, then the condition will not match. + +{{% boxes/note %}} +For example, if `key` is `content.alt_aliases`, and `value` is `"#myroom:example.com"`, +then the following event will match: + +```json +{ + "content": { + "alias": "#somewhere:localhost", + "alt_aliases": [ + "#somewhere:example.org", + "#myroom:example.com" + ] + }, + "event_id": "$143273582443PhrSn:example.org", + "origin_server_ts": 1432735824653, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "state_key": "", + "type": "m.room.canonical_alias", + "unsigned": { + "age": 1234 + } +} +``` + +The following `alt_aliases` values will NOT match: + * `":example.com"` (partial values do not match) +{{% /boxes/note %}} + **`contains_display_name`** This matches messages where `content.body` contains the owner's display name in diff --git a/data/api/client-server/definitions/sync_filter.yaml b/data/api/client-server/definitions/sync_filter.yaml index 0ea6e9c2..1b98db1f 100644 --- a/data/api/client-server/definitions/sync_filter.yaml +++ b/data/api/client-server/definitions/sync_filter.yaml @@ -16,10 +16,9 @@ title: Filter properties: event_fields: description: List of event fields to include. If this list is absent then all - fields are included. The entries may include '.' characters to indicate sub-fields. - So ['content.body'] will include the 'body' field of the 'content' object. A - literal '.' character in a field name may be escaped using a '\\'. A server may - include more fields than were requested. + fields are included. The entries are [dot-separated paths for each property](/appendices#dot-separated-property-paths) + to include. So ['content.body'] will include the 'body' field of the 'content' object. + A server may include more fields than were requested. items: type: string type: array