diff --git a/src/@types/PushRules.ts b/src/@types/PushRules.ts index 7864fe07c..fa404c43a 100644 --- a/src/@types/PushRules.ts +++ b/src/@types/PushRules.ts @@ -90,6 +90,8 @@ export interface ISenderNotificationPermissionCondition key: string; } +// XXX: custom conditions are possible but always fail, and break the typescript discriminated union so ignore them here +// IPushRuleCondition> unfortunately does not resolve this at the time of writing. export type PushRuleCondition = IEventMatchCondition | IContainsDisplayNameCondition | IRoomMemberCountCondition diff --git a/src/interactive-auth.ts b/src/interactive-auth.ts index 7070bb7d5..28829e3f1 100644 --- a/src/interactive-auth.ts +++ b/src/interactive-auth.ts @@ -81,6 +81,15 @@ export interface IAuthDict { threepidCreds?: any; } +class NoAuthFlowFoundError extends Error { + public name = "NoAuthFlowFoundError"; + + // eslint-disable-next-line @typescript-eslint/naming-convention, camelcase + constructor(m: string, public readonly required_stages: string[], public readonly flows: IFlow[]) { + super(m); + } +} + interface IOpts { matrixClient: MatrixClient; authData?: IAuthData; @@ -574,16 +583,13 @@ export class InteractiveAuth { return flow; } } - // Throw an error with a fairly generic description, but with more - // information such that the app can give a better one if so desired. - const err = new Error("No appropriate authentication flow found"); - err.name = 'NoAuthFlowFoundError'; + const requiredStages: string[] = []; if (haveEmail) requiredStages.push(EMAIL_STAGE_TYPE); if (haveMsisdn) requiredStages.push(MSISDN_STAGE_TYPE); - (err as any).required_stages = requiredStages; - (err as any).available_flows = flows; - throw err; + // Throw an error with a fairly generic description, but with more + // information such that the app can give a better one if so desired. + throw new NoAuthFlowFoundError("No appropriate authentication flow found", requiredStages, flows); } /** diff --git a/src/pushprocessor.ts b/src/pushprocessor.ts index 8a8d86a33..7e551202c 100644 --- a/src/pushprocessor.ts +++ b/src/pushprocessor.ts @@ -24,12 +24,14 @@ import { IContainsDisplayNameCondition, IEventMatchCondition, IPushRule, + IPushRules, IRoomMemberCountCondition, ISenderNotificationPermissionCondition, PushRuleAction, PushRuleActionName, PushRuleCondition, PushRuleKind, + PushRuleSet, TweakName, } from "./@types/PushRules"; @@ -45,18 +47,6 @@ const RULEKINDS_IN_ORDER = [ PushRuleKind.Underride, ]; -interface IRuleset { - [PushRuleKind.ContentSpecific]: IPushRule[]; - [PushRuleKind.Override]: IPushRule[]; - [PushRuleKind.RoomSpecific]: IPushRule[]; - [PushRuleKind.SenderSpecific]: IPushRule[]; - [PushRuleKind.Underride]: IPushRule[]; -} - -export interface IRulesets { - global: IRuleset; -} - // 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 @@ -114,6 +104,13 @@ export interface IActionsObject { } export class PushProcessor { + /** + * Construct a Push Processor. + * @constructor + * @param {Object} client The Matrix client object to use + */ + constructor(private readonly client: MatrixClient) {} + /** * Convert a list of actions into a object with the actions as keys and their values * eg. [ 'notify', { set_tweak: 'sound', value: 'default' } ] @@ -145,13 +142,13 @@ export class PushProcessor { * @param {object} incomingRules The client's existing push rules * @returns {object} The rewritten rules */ - public static rewriteDefaultRules(incomingRules: IRulesets): IRulesets { - let newRules: IRulesets = JSON.parse(JSON.stringify(incomingRules)); // deep clone + public static rewriteDefaultRules(incomingRules: IPushRules): IPushRules { + let newRules: IPushRules = 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 = {} as IRulesets; - if (!newRules.global) newRules.global = {} as IRuleset; + if (!newRules) newRules = {} as IPushRules; + if (!newRules.global) newRules.global = {} as PushRuleSet; if (!newRules.global.override) newRules.global.override = []; // Merge the client-level defaults with the ones from the server @@ -179,14 +176,7 @@ export class PushProcessor { private static cachedGlobToRegex: Record = {}; // $glob: RegExp - /** - * Construct a Push Processor. - * @constructor - * @param {Object} client The Matrix client object to use - */ - constructor(private readonly client: MatrixClient) {} - - private matchingRuleFromKindSet(ev: MatrixEvent, kindset: IRuleset): IAnnotatedPushRule { + private matchingRuleFromKindSet(ev: MatrixEvent, kindset: PushRuleSet): IAnnotatedPushRule { for (let ruleKindIndex = 0; ruleKindIndex < RULEKINDS_IN_ORDER.length; ++ruleKindIndex) { const kind = RULEKINDS_IN_ORDER[ruleKindIndex]; const ruleset = kindset[kind]; diff --git a/src/sync.ts b/src/sync.ts index 776e7847a..70cefef7b 100644 --- a/src/sync.ts +++ b/src/sync.ts @@ -30,7 +30,7 @@ import * as utils from "./utils"; import { IDeferred } from "./utils"; import { Filter } from "./filter"; import { EventTimeline } from "./models/event-timeline"; -import { IRulesets, PushProcessor } from "./pushprocessor"; +import { PushProcessor } from "./pushprocessor"; import { logger } from './logger'; import { InvalidStoreError } from './errors'; import { IStoredClientOpts, MatrixClient, PendingEventOrdering } from "./client"; @@ -53,6 +53,7 @@ import { MatrixEvent } from "./models/event"; import { MatrixError } from "./http-api"; import { ISavedSync } from "./store"; import { EventType } from "./@types/event"; +import { IPushRules } from "./@types/PushRules"; const DEBUG = true; @@ -1067,7 +1068,7 @@ export class SyncApi { // will be updated when we receive push rules via getPushRules // (see sync) before syncing over the network. if (accountDataEvent.getType() === EventType.PushRules) { - const rules = accountDataEvent.getContent(); + const rules = accountDataEvent.getContent(); client.pushRules = PushProcessor.rewriteDefaultRules(rules); } const prevEvent = prevEventsMap[accountDataEvent.getId()];