You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-08-06 12:02:40 +03:00
Implement MSC3966: a push rule condition to check if an array contains a value (#3180)
* Support MSC3966 to match values in an array in push rule conditions. * Update to stable identifiers. * Appease the linter.
This commit is contained in:
@@ -576,6 +576,75 @@ describe("NotificationService", function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Test event property contains", () => {
|
||||||
|
it.each([
|
||||||
|
// Simple string matching.
|
||||||
|
{ value: "bar", eventValue: ["bar"], expected: true },
|
||||||
|
// Matches are case-sensitive.
|
||||||
|
{ value: "bar", eventValue: ["BAR"], expected: false },
|
||||||
|
// Values should not be type-coerced.
|
||||||
|
{ value: "bar", eventValue: [true], expected: false },
|
||||||
|
{ value: "bar", eventValue: [1], expected: false },
|
||||||
|
{ value: "bar", eventValue: [false], expected: false },
|
||||||
|
// Boolean matching.
|
||||||
|
{ value: true, eventValue: [true], expected: true },
|
||||||
|
{ value: false, eventValue: [false], expected: true },
|
||||||
|
// Types should not be coerced.
|
||||||
|
{ value: true, eventValue: ["true"], expected: false },
|
||||||
|
{ value: true, eventValue: [1], expected: false },
|
||||||
|
{ value: false, eventValue: [null], expected: false },
|
||||||
|
// Null matching.
|
||||||
|
{ value: null, eventValue: [null], expected: true },
|
||||||
|
// Types should not be coerced
|
||||||
|
{ value: null, eventValue: [false], expected: false },
|
||||||
|
{ value: null, eventValue: [0], expected: false },
|
||||||
|
{ value: null, eventValue: [""], expected: false },
|
||||||
|
{ value: null, eventValue: [undefined], expected: false },
|
||||||
|
// Non-array or empty values should never be matched.
|
||||||
|
{ value: "bar", eventValue: "bar", expected: false },
|
||||||
|
{ value: "bar", eventValue: { bar: true }, expected: false },
|
||||||
|
{ value: true, eventValue: { true: true }, expected: false },
|
||||||
|
{ value: true, eventValue: true, expected: false },
|
||||||
|
{ value: null, eventValue: [], expected: false },
|
||||||
|
{ value: null, eventValue: {}, expected: false },
|
||||||
|
{ value: null, eventValue: null, expected: false },
|
||||||
|
{ value: null, eventValue: undefined, expected: false },
|
||||||
|
])("test $value against $eventValue", ({ value, eventValue, expected }) => {
|
||||||
|
matrixClient.pushRules! = {
|
||||||
|
global: {
|
||||||
|
override: [
|
||||||
|
{
|
||||||
|
actions: [PushRuleActionName.Notify],
|
||||||
|
conditions: [
|
||||||
|
{
|
||||||
|
kind: ConditionKind.EventPropertyContains,
|
||||||
|
key: "content.foo",
|
||||||
|
value: value,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: true,
|
||||||
|
enabled: true,
|
||||||
|
rule_id: ".m.rule.test",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
testEvent = utils.mkEvent({
|
||||||
|
type: "m.room.message",
|
||||||
|
room: testRoomId,
|
||||||
|
user: "@alfred:localhost",
|
||||||
|
event: true,
|
||||||
|
content: {
|
||||||
|
foo: eventValue,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const actions = pushProcessor.actionsForEvent(testEvent);
|
||||||
|
expect(actions?.notify).toBe(expected ? true : undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
// The properly escaped key works.
|
// The properly escaped key works.
|
||||||
{ key: "content.m\\.test.foo", pattern: "bar", expected: true },
|
{ key: "content.m\\.test.foo", pattern: "bar", expected: true },
|
||||||
|
@@ -63,6 +63,7 @@ export function isDmMemberCountCondition(condition: AnyMemberCountCondition): bo
|
|||||||
export enum ConditionKind {
|
export enum ConditionKind {
|
||||||
EventMatch = "event_match",
|
EventMatch = "event_match",
|
||||||
EventPropertyIs = "event_property_is",
|
EventPropertyIs = "event_property_is",
|
||||||
|
EventPropertyContains = "event_property_contains",
|
||||||
ContainsDisplayName = "contains_display_name",
|
ContainsDisplayName = "contains_display_name",
|
||||||
RoomMemberCount = "room_member_count",
|
RoomMemberCount = "room_member_count",
|
||||||
SenderNotificationPermission = "sender_notification_permission",
|
SenderNotificationPermission = "sender_notification_permission",
|
||||||
@@ -88,6 +89,11 @@ export interface IEventPropertyIsCondition extends IPushRuleCondition<ConditionK
|
|||||||
value: string | boolean | null | number;
|
value: string | boolean | null | number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IEventPropertyContainsCondition extends IPushRuleCondition<ConditionKind.EventPropertyContains> {
|
||||||
|
key: string;
|
||||||
|
value: string | boolean | null | number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IContainsDisplayNameCondition extends IPushRuleCondition<ConditionKind.ContainsDisplayName> {
|
export interface IContainsDisplayNameCondition extends IPushRuleCondition<ConditionKind.ContainsDisplayName> {
|
||||||
// no additional fields
|
// no additional fields
|
||||||
}
|
}
|
||||||
@@ -114,6 +120,7 @@ export interface ICallStartedPrefixCondition extends IPushRuleCondition<Conditio
|
|||||||
export type PushRuleCondition =
|
export type PushRuleCondition =
|
||||||
| IEventMatchCondition
|
| IEventMatchCondition
|
||||||
| IEventPropertyIsCondition
|
| IEventPropertyIsCondition
|
||||||
|
| IEventPropertyContainsCondition
|
||||||
| IContainsDisplayNameCondition
|
| IContainsDisplayNameCondition
|
||||||
| IRoomMemberCountCondition
|
| IRoomMemberCountCondition
|
||||||
| ISenderNotificationPermissionCondition
|
| ISenderNotificationPermissionCondition
|
||||||
|
@@ -26,6 +26,7 @@ import {
|
|||||||
IContainsDisplayNameCondition,
|
IContainsDisplayNameCondition,
|
||||||
IEventMatchCondition,
|
IEventMatchCondition,
|
||||||
IEventPropertyIsCondition,
|
IEventPropertyIsCondition,
|
||||||
|
IEventPropertyContainsCondition,
|
||||||
IPushRule,
|
IPushRule,
|
||||||
IPushRules,
|
IPushRules,
|
||||||
IRoomMemberCountCondition,
|
IRoomMemberCountCondition,
|
||||||
@@ -340,6 +341,8 @@ export class PushProcessor {
|
|||||||
return this.eventFulfillsEventMatchCondition(cond, ev);
|
return this.eventFulfillsEventMatchCondition(cond, ev);
|
||||||
case ConditionKind.EventPropertyIs:
|
case ConditionKind.EventPropertyIs:
|
||||||
return this.eventFulfillsEventPropertyIsCondition(cond, ev);
|
return this.eventFulfillsEventPropertyIsCondition(cond, ev);
|
||||||
|
case ConditionKind.EventPropertyContains:
|
||||||
|
return this.eventFulfillsEventPropertyContains(cond, ev);
|
||||||
case ConditionKind.ContainsDisplayName:
|
case ConditionKind.ContainsDisplayName:
|
||||||
return this.eventFulfillsDisplayNameCondition(cond, ev);
|
return this.eventFulfillsDisplayNameCondition(cond, ev);
|
||||||
case ConditionKind.RoomMemberCount:
|
case ConditionKind.RoomMemberCount:
|
||||||
@@ -488,6 +491,24 @@ export class PushProcessor {
|
|||||||
return cond.value === this.valueForDottedKey(cond.key, ev);
|
return cond.value === this.valueForDottedKey(cond.key, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the given event matches the push rule condition by fetching
|
||||||
|
* the property from the event and comparing exactly against the condition's
|
||||||
|
* value.
|
||||||
|
* @param cond - The push rule condition to check for a match.
|
||||||
|
* @param ev - The event to check for a match.
|
||||||
|
*/
|
||||||
|
private eventFulfillsEventPropertyContains(cond: IEventPropertyContainsCondition, ev: MatrixEvent): boolean {
|
||||||
|
if (!cond.key || cond.value === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const val = this.valueForDottedKey(cond.key, ev);
|
||||||
|
if (!Array.isArray(val)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return val.includes(cond.value);
|
||||||
|
}
|
||||||
|
|
||||||
private eventFulfillsCallStartedCondition(
|
private eventFulfillsCallStartedCondition(
|
||||||
_cond: ICallStartedCondition | ICallStartedPrefixCondition,
|
_cond: ICallStartedCondition | ICallStartedPrefixCondition,
|
||||||
ev: MatrixEvent,
|
ev: MatrixEvent,
|
||||||
|
Reference in New Issue
Block a user