diff --git a/src/base-apis.js b/src/base-apis.js index 988d3738c..6a3d59083 100644 --- a/src/base-apis.js +++ b/src/base-apis.js @@ -29,6 +29,7 @@ import logger from './logger'; const httpApi = require("./http-api"); const utils = require("./utils"); +const PushProcessor = require("./pushprocessor"); function termsUrlForService(serviceType, baseUrl) { switch (serviceType) { @@ -1477,7 +1478,9 @@ MatrixBaseApis.prototype.setPusher = function(pusher, callback) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.getPushRules = function(callback) { - return this._http.authedRequest(callback, "GET", "/pushrules/"); + return this._http.authedRequest(callback, "GET", "/pushrules/").then(rules => { + return PushProcessor.rewriteDefaultRules(rules); + }); }; /** diff --git a/src/pushprocessor.js b/src/pushprocessor.js index 54202b412..0cf05cacf 100644 --- a/src/pushprocessor.js +++ b/src/pushprocessor.js @@ -43,6 +43,11 @@ const DEFAULT_OVERRIDE_RULES = [ key: "type", pattern: "m.room.tombstone", }, + { + kind: "event_match", + key: "state_key", + pattern: "", + }, ], actions: [ "notify", @@ -455,6 +460,38 @@ PushProcessor.actionListToActionsObject = function(actionlist) { return actionobj; }; +/** + * Rewrites conditions on a client's push rules to match the defaults + * where applicable. Useful for upgrading push rules to more strict + * conditions when the server is falling behind on defaults. + * @param {object} incomingRules The client's existing push rules + * @returns {object} The rewritten rules + */ +PushProcessor.rewriteDefaultRules = function(incomingRules) { + let newRules = JSON.parse(JSON.stringify(incomingRules)); // deep clone + + // These lines are mostly to make the tests happy. We shouldn't run into these + // properties missing in practice. + if (!newRules) newRules = {}; + if (!newRules.global) newRules.global = {}; + if (!newRules.global.override) newRules.global.override = []; + + // Fix default override rules + newRules.global.override = newRules.global.override.map(r => { + const defaultRule = DEFAULT_OVERRIDE_RULES.find(d => d.rule_id === r.rule_id); + if (!defaultRule) return r; + + // Copy over the actions, default, and conditions. Don't touch the user's + // preference. + r.default = defaultRule.default; + r.conditions = defaultRule.conditions; + r.actions = defaultRule.actions; + return r; + }); + + return newRules; +}; + /** * @typedef {Object} PushAction * @type {Object} diff --git a/src/sync.js b/src/sync.js index 12775903e..765bf73b6 100644 --- a/src/sync.js +++ b/src/sync.js @@ -32,6 +32,7 @@ const Group = require('./models/group'); const utils = require("./utils"); const Filter = require("./filter"); const EventTimeline = require("./models/event-timeline"); +const PushProcessor = require("./pushprocessor"); import logger from '../src/logger'; import {InvalidStoreError} from './errors'; @@ -1030,8 +1031,9 @@ SyncApi.prototype._processSyncResponse = async function( // honour push rules that were previously cached. Base rules // will be updated when we recieve push rules via getPushRules // (see SyncApi.prototype.sync) before syncing over the network. - if (accountDataEvent.getType() == 'm.push_rules') { - client.pushRules = accountDataEvent.getContent(); + if (accountDataEvent.getType() === 'm.push_rules') { + const rules = accountDataEvent.getContent(); + client.pushRules = PushProcessor.rewriteDefaultRules(rules); } client.emit("accountData", accountDataEvent); return accountDataEvent;