-
-
Notifications
You must be signed in to change notification settings - Fork 606
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix merging of default push rules #4135
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,8 +25,8 @@ import { | |
ICallStartedPrefixCondition, | ||
IContainsDisplayNameCondition, | ||
IEventMatchCondition, | ||
IEventPropertyIsCondition, | ||
IEventPropertyContainsCondition, | ||
IEventPropertyIsCondition, | ||
IPushRule, | ||
IPushRules, | ||
IRoomMemberCountCondition, | ||
|
@@ -49,6 +49,10 @@ const RULEKINDS_IN_ORDER = [ | |
PushRuleKind.Underride, | ||
]; | ||
|
||
const UserDefinedRules = Symbol("UserDefinedRules"); | ||
t3chguy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
type OrderedRules = Array<string | typeof UserDefinedRules>; | ||
t3chguy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// The default override rules to apply to the push rules that arrive from the server. | ||
// We do this for two reasons: | ||
// 1. Synapse is unlikely to send us the push rule in an incremental sync - see | ||
|
@@ -115,8 +119,9 @@ const DEFAULT_OVERRIDE_RULES: Record<string, IPushRule> = { | |
}, | ||
}; | ||
|
||
const EXPECTED_DEFAULT_OVERRIDE_RULE_IDS = [ | ||
const EXPECTED_DEFAULT_OVERRIDE_RULE_IDS: OrderedRules = [ | ||
RuleId.Master, | ||
UserDefinedRules, | ||
RuleId.SuppressNotices, | ||
RuleId.InviteToSelf, | ||
RuleId.MemberEvent, | ||
|
@@ -151,7 +156,8 @@ const DEFAULT_UNDERRIDE_RULES: Record<string, IPushRule> = { | |
}, | ||
}; | ||
|
||
const EXPECTED_DEFAULT_UNDERRIDE_RULE_IDS = [ | ||
const EXPECTED_DEFAULT_UNDERRIDE_RULE_IDS: OrderedRules = [ | ||
UserDefinedRules, | ||
RuleId.IncomingCall, | ||
RuleId.EncryptedDM, | ||
RuleId.DM, | ||
|
@@ -162,24 +168,31 @@ const EXPECTED_DEFAULT_UNDERRIDE_RULE_IDS = [ | |
/** | ||
* Make sure that each of the rules listed in `defaultRuleIds` is listed in the given set of push rules. | ||
* | ||
* @param kind - the kind of push rule set being merged. | ||
* @param incomingRules - the existing set of known push rules for the user. | ||
* @param defaultRules - a lookup table for the default definitions of push rules. | ||
* @param defaultRuleIds - the IDs of the expected default push rules, in order. | ||
t3chguy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* | ||
* @returns A copy of `incomingRules`, with any missing default rules inserted in the right place. | ||
*/ | ||
function mergeRulesWithDefaults( | ||
kind: PushRuleKind, | ||
t3chguy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
incomingRules: IPushRule[], | ||
defaultRules: Record<string, IPushRule>, | ||
defaultRuleIds: string[], | ||
defaultRuleIds: OrderedRules, | ||
t3chguy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
): IPushRule[] { | ||
// Calculate the index after the last default rule in `incomingRules` | ||
// to allow us to split the incomingRules into defaults and custom | ||
let firstCustomRuleIndex = incomingRules.findIndex((r) => !r.default); | ||
if (firstCustomRuleIndex < 0) firstCustomRuleIndex = incomingRules.length; | ||
|
||
function insertDefaultPushRule(ruleId: string): void { | ||
if (ruleId in defaultRules) { | ||
// Find the indices of the edges of the user-defined rules in the incoming rules | ||
const incomingRulesEnabled = incomingRules.map((rule) => rule.enabled); | ||
t3chguy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const userDefinedRulesRange: [number, number] = [ | ||
incomingRulesEnabled.indexOf(false), | ||
incomingRulesEnabled.lastIndexOf(false), | ||
]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we're actually doing quite a lot of iterating and copying of incomingRules. I'd instead start just by partitioning them:
... and I think everything else can then be more easily written in terms of those, instead of Not a blocker, just a thought. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Splitting them as per your example would mean you lose track of the location of the user-defined rules. Right now only There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't really follow. We insert the custom rules into
Yeah, I'm arguing this rather more from the PoV of clarity than performance. Just saying: it's not like doing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
incomingRules is in the order of:
Your proposed code would merge the default rules into one list and the default orders wouldn't account for any rules in the first bucket other than
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I don't think so. In such a scenario, the new rule would end up as the second entry in
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Turns out this was due to missing |
||
|
||
function insertDefaultPushRule(ruleId: OrderedRules[number]): void { | ||
if (ruleId === UserDefinedRules) { | ||
// Re-insert any user-defined rules that were in `incomingRules` | ||
newRules.push(...incomingRules.slice(...userDefinedRulesRange)); | ||
} else if (ruleId in defaultRules) { | ||
logger.warn(`Adding default global push rule ${ruleId}`); | ||
newRules.push(defaultRules[ruleId]); | ||
} else { | ||
|
@@ -189,7 +202,11 @@ function mergeRulesWithDefaults( | |
|
||
let nextExpectedRuleIdIndex = 0; | ||
const newRules: IPushRule[] = []; | ||
for (const rule of incomingRules.slice(0, firstCustomRuleIndex)) { | ||
// Process the default rules by merging them with defaults | ||
t3chguy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for (const rule of [ | ||
...incomingRules.slice(0, userDefinedRulesRange[0]), | ||
...incomingRules.slice(userDefinedRulesRange[1]), | ||
]) { | ||
const ruleIndex = defaultRuleIds.indexOf(rule.rule_id); | ||
if (ruleIndex === -1) { | ||
// an unrecognised rule; copy it over | ||
|
@@ -212,8 +229,6 @@ function mergeRulesWithDefaults( | |
insertDefaultPushRule(ruleId); | ||
} | ||
|
||
// Finally any non-default rules that were in `incomingRules` | ||
newRules.push(...incomingRules.slice(firstCustomRuleIndex)); | ||
return newRules; | ||
} | ||
|
||
|
@@ -281,12 +296,14 @@ export class PushProcessor { | |
|
||
// Merge the client-level defaults with the ones from the server | ||
newRules.global.override = mergeRulesWithDefaults( | ||
PushRuleKind.Override, | ||
newRules.global.override, | ||
DEFAULT_OVERRIDE_RULES, | ||
EXPECTED_DEFAULT_OVERRIDE_RULE_IDS, | ||
); | ||
|
||
newRules.global.underride = mergeRulesWithDefaults( | ||
PushRuleKind.Underride, | ||
newRules.global.underride, | ||
DEFAULT_UNDERRIDE_RULES, | ||
EXPECTED_DEFAULT_UNDERRIDE_RULE_IDS, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ftr I am generally deeply ambivalent about using symbolic constants in test code: using the literal gives us a chance to check that the constant is doing what we expect.
(This brought to you on the back of a Synapse bug where we had a test which used what we thought was a constant but turned out not to be.)
YMMV though, not a particular request to change this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its preferable to
@ts-ignore
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean I'd argue your problem here is forcing msc3914RoomCallRule to be an IPushRule, but whatever
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if I remove that type cast there, then I'd get the failure in the call to
rewritePushRules
The only reason it was fine before this PR is because we passed
matrixClient.pushRules!
torewritePushRules
and hadto make TS happy with the types of
pushRules
within the mockmatrixClient
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.