1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-08-06 12:02:40 +03:00

Implement MSC3873 to handle escaped dots in push rule keys (#3134)

* Add comments.

* Implment MSC3873 to handle escaped dots in keys.

* Add some comments about tests.

* Clarify spec behavior.

* Fix typo.

* Don't manually iterate string.

* Clean-up tests.

* Simplify tests.

* Add more tests & fix bug with empty parts.

* Add more edge cases.

* Add a regular expression solution.

This is ~80% slower than the basic split(".").

* Split on a simpler regular expression.

This is ~50% slower than a simple split(".").

* Remove redundant case in regex.

* Enable sticky regex.

* Rollback use of regex.

* Cache values in the PushProcessor.

* Use more each in tests.

* Pre-calculate the key parts instead of caching them.

* Fix typo.

* Switch back to external cache, but clean out obsolete cached values.

* Remove obsolete property.

* Remove more obsolete properties.
This commit is contained in:
Patrick Cloke
2023-03-01 07:23:40 -05:00
committed by GitHub
parent 437128d11b
commit c8a4d9b88a
5 changed files with 238 additions and 12 deletions

View File

@@ -1,6 +1,6 @@
import * as utils from "../test-utils/test-utils";
import { IActionsObject, PushProcessor } from "../../src/pushprocessor";
import { EventType, IContent, MatrixClient, MatrixEvent } from "../../src";
import { ConditionKind, EventType, IContent, MatrixClient, MatrixEvent } from "../../src";
describe("NotificationService", function () {
const testUserId = "@ali:matrix.org";
@@ -287,6 +287,13 @@ describe("NotificationService", function () {
expect(actions.tweaks.highlight).toEqual(true);
});
// TODO: This is not spec compliant behaviour.
//
// See https://spec.matrix.org/v1.5/client-server-api/#conditions-1 which
// describes pattern should glob:
//
// 1. * matches 0 or more characters;
// 2. ? matches exactly one character
it("should bing on character group ([abc]) bing words.", function () {
testEvent.event.content!.body = "Ping!";
let actions = pushProcessor.actionsForEvent(testEvent);
@@ -296,12 +303,14 @@ describe("NotificationService", function () {
expect(actions.tweaks.highlight).toEqual(true);
});
// TODO: This is not spec compliant behaviour. (See above.)
it("should bing on character range ([a-z]) bing words.", function () {
testEvent.event.content!.body = "I ate 6 pies";
const actions = pushProcessor.actionsForEvent(testEvent);
expect(actions.tweaks.highlight).toEqual(true);
});
// TODO: This is not spec compliant behaviour. (See above.)
it("should bing on character negation ([!a]) bing words.", function () {
testEvent.event.content!.body = "boke";
let actions = pushProcessor.actionsForEvent(testEvent);
@@ -330,6 +339,8 @@ describe("NotificationService", function () {
// invalid
it("should gracefully handle bad input.", function () {
// The following body is an object (not a string) and thus is invalid
// for matching against.
testEvent.event.content!.body = { foo: "bar" };
const actions = pushProcessor.actionsForEvent(testEvent);
expect(actions.tweaks.highlight).toEqual(false);
@@ -493,4 +504,82 @@ describe("NotificationService", function () {
});
});
});
it.each([
// The properly escaped key works.
{ key: "content.m\\.test.foo", pattern: "bar", expected: true },
// An unescaped version does not match.
{ key: "content.m.test.foo", pattern: "bar", expected: false },
// Over escaping does not match.
{ key: "content.m\\.test\\.foo", pattern: "bar", expected: false },
// Escaping backslashes should match.
{ key: "content.m\\\\example", pattern: "baz", expected: true },
// An unnecessary escape sequence leaves the backslash and still matches.
{ key: "content.m\\example", pattern: "baz", expected: true },
])("test against escaped dotted paths '$key'", ({ key, pattern, expected }) => {
testEvent = utils.mkEvent({
type: "m.room.message",
room: testRoomId,
user: "@alfred:localhost",
event: true,
content: {
// A dot in the field name.
"m.test": { foo: "bar" },
// A backslash in a field name.
"m\\example": "baz",
},
});
expect(
pushProcessor.ruleMatchesEvent(
{
rule_id: "rule1",
actions: [],
conditions: [
{
kind: ConditionKind.EventMatch,
key: key,
pattern: pattern,
},
],
default: false,
enabled: true,
},
testEvent,
),
).toBe(expected);
});
});
describe("Test PushProcessor.partsForDottedKey", function () {
it.each([
// A field with no dots.
["m", ["m"]],
// Simple dotted fields.
["m.foo", ["m", "foo"]],
["m.foo.bar", ["m", "foo", "bar"]],
// Backslash is used as an escape character.
["m\\.foo", ["m.foo"]],
["m\\\\.foo", ["m\\", "foo"]],
["m\\\\\\.foo", ["m\\.foo"]],
["m\\\\\\\\.foo", ["m\\\\", "foo"]],
["m\\foo", ["m\\foo"]],
["m\\\\foo", ["m\\foo"]],
["m\\\\\\foo", ["m\\\\foo"]],
["m\\\\\\\\foo", ["m\\\\foo"]],
// Ensure that escapes at the end don't cause issues.
["m.foo\\", ["m", "foo\\"]],
["m.foo\\\\", ["m", "foo\\"]],
["m.foo\\.", ["m", "foo."]],
["m.foo\\\\.", ["m", "foo\\", ""]],
["m.foo\\\\\\.", ["m", "foo\\."]],
// Empty parts (corresponding to properties which are an empty string) are allowed.
[".m", ["", "m"]],
["..m", ["", "", "m"]],
["m.", ["m", ""]],
["m..", ["m", "", ""]],
["m..foo", ["m", "", "foo"]],
])("partsFotDottedKey for %s", (path: string, expected: string[]) => {
expect(PushProcessor.partsForDottedKey(path)).toStrictEqual(expected);
});
});