Add stable support for MSC4380 invite blocking (#31966)

* Add stable support for MSC4380 invite blocking

MSC4380 has completed FCP, so we can add stable support for it.

* Set account data to empty value when allowing invites

... because that's what the spec says

* Use identifiers from js-sdk
This commit is contained in:
Richard van der Hoff 2026-02-26 11:41:04 +00:00 committed by GitHub
parent 7ddd645f4d
commit 18c1b37206
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 19 additions and 21 deletions

View File

@ -6,7 +6,6 @@ Please see LICENSE files in the repository root for full details.
*/
export const INVITE_RULES_ACCOUNT_DATA_TYPE = "org.matrix.msc4155.invite_permission_config";
export const MSC4380_INVITE_RULES_ACCOUNT_DATA_TYPE = "org.matrix.msc4380.invite_permission_config";
export interface InviteConfigAccountData {
allowed_users?: string[];

View File

@ -15,11 +15,7 @@ import type { EmptyObject } from "matrix-js-sdk/src/matrix";
import type { DeviceClientInformation } from "../utils/device/types.ts";
import type { UserWidget } from "../utils/WidgetUtils-types.ts";
import { type MediaPreviewConfig } from "./media_preview.ts";
import {
type INVITE_RULES_ACCOUNT_DATA_TYPE,
type InviteConfigAccountData,
type MSC4380_INVITE_RULES_ACCOUNT_DATA_TYPE,
} from "./invite-rules.ts";
import { type INVITE_RULES_ACCOUNT_DATA_TYPE, type InviteConfigAccountData } from "./invite-rules.ts";
// Extend Matrix JS SDK types via Typescript declaration merging to support unspecced event fields and types
declare module "matrix-js-sdk/src/types" {
@ -96,8 +92,6 @@ declare module "matrix-js-sdk/src/types" {
// MSC4155: Invite filtering
[INVITE_RULES_ACCOUNT_DATA_TYPE]: InviteConfigAccountData;
[MSC4380_INVITE_RULES_ACCOUNT_DATA_TYPE]: { default_action?: "allow" | "block" };
"io.element.msc4278.media_preview_config": MediaPreviewConfig;
// Indicate whether recovery is enabled or disabled

View File

@ -5,8 +5,9 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { EventType } from "matrix-js-sdk/src/matrix";
import { type SettingLevel } from "../SettingLevel.ts";
import { MSC4380_INVITE_RULES_ACCOUNT_DATA_TYPE } from "../../@types/invite-rules.ts";
import { _td } from "../../languageHandler.tsx";
import ServerSupportUnstableFeatureController from "./ServerSupportUnstableFeatureController.ts";
import { defaultWatchManager, type SettingKey } from "../Settings.tsx";
@ -17,11 +18,17 @@ import { defaultWatchManager, type SettingKey } from "../Settings.tsx";
*/
export default class BlockInvitesConfigController extends ServerSupportUnstableFeatureController {
public constructor(settingName: SettingKey) {
super(settingName, defaultWatchManager, [["org.matrix.msc4380"]], undefined, _td("settings|not_supported"));
super(
settingName,
defaultWatchManager,
[["org.matrix.msc4380.stable"]],
"v1.18",
_td("settings|not_supported"),
);
}
public getValueOverride(_level: SettingLevel): boolean {
const accountData = this.client?.getAccountData(MSC4380_INVITE_RULES_ACCOUNT_DATA_TYPE)?.getContent();
const accountData = this.client?.getAccountData(EventType.InvitePermissionConfig)?.getContent();
return accountData?.default_action == "block";
}
@ -29,8 +36,8 @@ export default class BlockInvitesConfigController extends ServerSupportUnstableF
if (!this.client) {
return false;
}
const newDefault = newValue ? "block" : "allow";
await this.client.setAccountData(MSC4380_INVITE_RULES_ACCOUNT_DATA_TYPE, { default_action: newDefault });
await this.client.setAccountData(EventType.InvitePermissionConfig, newValue ? { default_action: "block" } : {});
return true;
}
}

View File

@ -34,7 +34,7 @@ describe("BlockInvitesConfigController", () => {
beforeEach(async () => {
cli = stubClient();
cli.doesServerSupportUnstableFeature = jest.fn(async (feature) => {
return feature == "org.matrix.msc4380";
return feature == "org.matrix.msc4380.stable";
});
MatrixClientBackedController.matrixClient = cli;
});
@ -65,7 +65,7 @@ describe("BlockInvitesConfigController", () => {
const controller = SETTINGS.blockInvites.controller!;
await controller.beforeChange(SettingLevel.DEVICE, null, true);
expect(cli.setAccountData).toHaveBeenCalledTimes(1);
expect(cli.setAccountData).toHaveBeenCalledWith("org.matrix.msc4380.invite_permission_config", {
expect(cli.setAccountData).toHaveBeenCalledWith("m.invite_permission_config", {
default_action: "block",
});
});
@ -74,9 +74,7 @@ describe("BlockInvitesConfigController", () => {
const controller = SETTINGS.blockInvites.controller!;
await controller.beforeChange(SettingLevel.DEVICE, null, false);
expect(cli.setAccountData).toHaveBeenCalledTimes(1);
expect(cli.setAccountData).toHaveBeenCalledWith("org.matrix.msc4380.invite_permission_config", {
default_action: "allow",
});
expect(cli.setAccountData).toHaveBeenCalledWith("m.invite_permission_config", {});
});
});
});
@ -84,13 +82,13 @@ describe("BlockInvitesConfigController", () => {
/**
* Add a mock implementation for {@link MatrixClient.getAccountData} which will return the given data
* in respomsnse to any request for `org.matrix.msc4380.invite_permission_config`.
* in response to any request for `m.invite_permission_config`.
*/
function mockAccountData(cli: MatrixClient, mockAccountData: object) {
mocked(cli.getAccountData).mockImplementation((eventType) => {
if (eventType == "org.matrix.msc4380.invite_permission_config") {
if (eventType == "m.invite_permission_config") {
return new MatrixEvent({
type: "org.matrix.msc4380.invite_permission_config",
type: "m.invite_permission_config",
content: mockAccountData,
});
} else {