Skip to content

Commit

Permalink
Harden types for reading account data too
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Telatynski <[email protected]>
  • Loading branch information
t3chguy committed Dec 19, 2024
1 parent a1635c5 commit 49a43fc
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 21 deletions.
7 changes: 7 additions & 0 deletions spec/integ/matrix-client-syncing.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ import { THREAD_RELATION_TYPE } from "../../src/models/thread";
import { IActionsObject } from "../../src/pushprocessor";
import { KnownMembership } from "../../src/@types/membership";

declare module "../../src/@types/event" {
interface AccountDataEvents {
a: {};
b: {};
}
}

describe("MatrixClient syncing", () => {
const selfUserId = "@alice:localhost";
const selfAccessToken = "aseukfgwef";
Expand Down
7 changes: 7 additions & 0 deletions spec/integ/sliding-sync-sdk.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ import { emitPromise } from "../test-utils/test-utils";
import { defer } from "../../src/utils";
import { KnownMembership } from "../../src/@types/membership";

declare module "../../src/@types/event" {
interface AccountDataEvents {
global_test: {};
tester: {};
}
}

describe("SlidingSyncSdk", () => {
let client: MatrixClient | undefined;
let httpBackend: MockHttpBackend | undefined;
Expand Down
7 changes: 5 additions & 2 deletions spec/unit/rust-crypto/rust-crypto.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import fetchMock from "fetch-mock-jest";
import { RustCrypto } from "../../../src/rust-crypto/rust-crypto";
import { initRustCrypto } from "../../../src/rust-crypto";
import {
AccountDataEvents,
Device,
DeviceVerification,
encodeBase64,
Expand Down Expand Up @@ -1924,11 +1925,13 @@ class DummyAccountDataClient
super();
}

public async getAccountDataFromServer<T extends Record<string, any>>(eventType: string): Promise<T | null> {
public async getAccountDataFromServer<K extends keyof AccountDataEvents>(
eventType: K,
): Promise<AccountDataEvents[K] | null> {
const ret = this.storage.get(eventType);

if (eventType) {
return ret as T;
return ret;
} else {
return null;
}
Expand Down
21 changes: 14 additions & 7 deletions spec/unit/secret-storage.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
} from "../../src/secret-storage";
import { randomString } from "../../src/randomstring";
import { SecretInfo } from "../../src/secret-storage.ts";
import { AccountDataEvents } from "../../src";

declare module "../../src/@types/event" {
interface AccountDataEvents {
Expand Down Expand Up @@ -124,9 +125,11 @@ describe("ServerSideSecretStorageImpl", function () {
const secretStorage = new ServerSideSecretStorageImpl(accountDataAdapter, {});

const storedKey = { iv: "iv", mac: "mac" } as SecretStorageKeyDescriptionAesV1;
async function mockGetAccountData<T extends Record<string, any>>(eventType: string): Promise<T | null> {
async function mockGetAccountData<K extends keyof AccountDataEvents>(
eventType: string,
): Promise<AccountDataEvents[K] | null> {
if (eventType === "m.secret_storage.key.my_key") {
return storedKey as unknown as T;
return storedKey as any;
} else {
throw new Error(`unexpected eventType ${eventType}`);
}
Expand All @@ -142,11 +145,13 @@ describe("ServerSideSecretStorageImpl", function () {
const secretStorage = new ServerSideSecretStorageImpl(accountDataAdapter, {});

const storedKey = { iv: "iv", mac: "mac" } as SecretStorageKeyDescriptionAesV1;
async function mockGetAccountData<T extends Record<string, any>>(eventType: string): Promise<T | null> {
async function mockGetAccountData<K extends keyof AccountDataEvents>(
eventType: string,
): Promise<AccountDataEvents[K] | null> {
if (eventType === "m.secret_storage.default_key") {
return { key: "default_key_id" } as unknown as T;
return { key: "default_key_id" } as any;
} else if (eventType === "m.secret_storage.key.default_key_id") {
return storedKey as unknown as T;
return storedKey as any;
} else {
throw new Error(`unexpected eventType ${eventType}`);
}
Expand Down Expand Up @@ -243,9 +248,11 @@ describe("ServerSideSecretStorageImpl", function () {

// stub out getAccountData to return a key with an unknown algorithm
const storedKey = { algorithm: "badalg" } as SecretStorageKeyDescriptionCommon;
async function mockGetAccountData<T extends Record<string, any>>(eventType: string): Promise<T | null> {
async function mockGetAccountData<K extends keyof AccountDataEvents>(
eventType: string,
): Promise<AccountDataEvents[K] | null> {
if (eventType === "m.secret_storage.key.keyid") {
return storedKey as unknown as T;
return storedKey as any;
} else {
throw new Error(`unexpected eventType ${eventType}`);
}
Expand Down
11 changes: 9 additions & 2 deletions src/@types/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ import { SessionMembershipData } from "../matrixrtc/CallMembership.ts";
import { LocalNotificationSettings } from "./local_notifications.ts";
import { IPushRules } from "./PushRules.ts";
import { SecretInfo, SecretStorageKeyDescription } from "../secret-storage.ts";
import { POLICIES_ACCOUNT_EVENT_TYPE } from "../models/invites-ignorer-types.ts";
import {
IgnoreInvitesContent,
POLICIES_ACCOUNT_EVENT_TYPE,
UnstableIgnoreInvitesContent,
} from "../models/invites-ignorer-types.ts";

export enum EventType {
// Room state events
Expand Down Expand Up @@ -381,7 +385,6 @@ export interface AccountDataEvents {
[EventType.Direct]: { [userId: string]: string[] };
[EventType.IgnoredUserList]: { [userId: string]: {} };
"m.secret_storage.default_key": { key: string };
[POLICIES_ACCOUNT_EVENT_TYPE.name]: { [key: string]: any };
"m.identity_server": { base_url: string | null };
[key: `${typeof LOCAL_NOTIFICATION_SETTINGS_PREFIX.name}.${string}`]: LocalNotificationSettings;
[key: `m.secret_storage.key.${string}`]: SecretStorageKeyDescription;
Expand All @@ -390,4 +393,8 @@ export interface AccountDataEvents {
"m.cross_signing.self_signing": SecretInfo;
"m.cross_signing.user_signing": SecretInfo;
"org.matrix.msc3814": SecretInfo;

// Invites-ignorer events
[POLICIES_ACCOUNT_EVENT_TYPE.name]: UnstableIgnoreInvitesContent;
[POLICIES_ACCOUNT_EVENT_TYPE.altName]: IgnoreInvitesContent;
}
10 changes: 6 additions & 4 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4256,7 +4256,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
* @param eventType - The event type
* @returns The contents of the given account data event
*/
public getAccountData(eventType: string): MatrixEvent | undefined {
public getAccountData<K extends keyof AccountDataEvents>(eventType: K): MatrixEvent | undefined {
return this.store.getAccountData(eventType);
}

Expand All @@ -4268,15 +4268,17 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
* @returns Promise which resolves: The contents of the given account data event.
* @returns Rejects: with an error response.
*/
public async getAccountDataFromServer<T extends { [k: string]: any }>(eventType: string): Promise<T | null> {
public async getAccountDataFromServer<K extends keyof AccountDataEvents>(
eventType: K,
): Promise<AccountDataEvents[K] | null> {
if (this.isInitialSyncComplete()) {
const event = this.store.getAccountData(eventType);
if (!event) {
return null;
}
// The network version below returns just the content, so this branch
// does the same to match.
return event.getContent<T>();
return event.getContent<AccountDataEvents[K]>();
}
const path = utils.encodeUri("/user/$userId/account_data/$type", {
$userId: this.credentials.userId!,
Expand Down Expand Up @@ -4315,7 +4317,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
* @returns The array of users that are ignored (empty if none)
*/
public getIgnoredUsers(): string[] {
const event = this.getAccountData("m.ignored_user_list");
const event = this.getAccountData(EventType.IgnoredUserList);
if (!event?.getContent()["ignored_users"]) return [];
return Object.keys(event.getContent()["ignored_users"]);
}
Expand Down
13 changes: 13 additions & 0 deletions src/models/invites-ignorer-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@ export const IGNORE_INVITES_ACCOUNT_EVENT_KEY = new UnstableValue(
"org.matrix.msc3847.ignore.invites",
);

export interface Policies {
target?: string;
sources?: string[];
}

export interface IgnoreInvitesContent {
"m.ignore.invites": Policies;
}

export interface UnstableIgnoreInvitesContent {
"org.matrix.msc3847.ignore.invites": Policies;
}

/// The types of recommendations understood.
export enum PolicyRecommendation {
Ban = "m.ban",
Expand Down
17 changes: 11 additions & 6 deletions src/models/invites-ignorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,20 @@ limitations under the License.
*/

import { MatrixClient } from "../client.ts";
import { IContent, MatrixEvent } from "./event.ts";
import { MatrixEvent } from "./event.ts";
import { EventTimeline } from "./event-timeline.ts";
import { Preset } from "../@types/partials.ts";
import { globToRegexp } from "../utils.ts";
import { Room } from "./room.ts";
import { EventType, StateEvents } from "../@types/event.ts";
import {
IGNORE_INVITES_ACCOUNT_EVENT_KEY,
IgnoreInvitesContent,
Policies,
POLICIES_ACCOUNT_EVENT_TYPE,
PolicyRecommendation,
PolicyScope,
UnstableIgnoreInvitesContent,
} from "./invites-ignorer-types.ts";

export { IGNORE_INVITES_ACCOUNT_EVENT_KEY, POLICIES_ACCOUNT_EVENT_TYPE, PolicyRecommendation, PolicyScope };
Expand Down Expand Up @@ -304,22 +307,24 @@ export class IgnoredInvites {
* object.
*/
private getPoliciesAndIgnoreInvitesPolicies(): {
policies: { [key: string]: any };
ignoreInvitesPolicies: { [key: string]: any };
policies: Partial<IgnoreInvitesContent & UnstableIgnoreInvitesContent>;
ignoreInvitesPolicies: Policies;
} {
let policies: IContent = {};
let policies: Partial<IgnoreInvitesContent & UnstableIgnoreInvitesContent> = {};
for (const key of [POLICIES_ACCOUNT_EVENT_TYPE.name, POLICIES_ACCOUNT_EVENT_TYPE.altName]) {
if (!key) {
continue;
}
const value = this.client.getAccountData(key)?.getContent();
const value = this.client
.getAccountData(key)
?.getContent<IgnoreInvitesContent | UnstableIgnoreInvitesContent>();
if (value) {
policies = value;
break;
}
}

let ignoreInvitesPolicies = {};
let ignoreInvitesPolicies: Policies = {};
let hasIgnoreInvitesPolicies = false;
for (const key of [IGNORE_INVITES_ACCOUNT_EVENT_KEY.name, IGNORE_INVITES_ACCOUNT_EVENT_KEY.altName]) {
if (!key) {
Expand Down

0 comments on commit 49a43fc

Please sign in to comment.