Join policy server PoC

This commit is contained in:
Erik Johnston
2025-03-22 18:53:11 +00:00
parent 64e2a843c3
commit 4a66a22c14
2 changed files with 91 additions and 58 deletions

View File

@@ -8,50 +8,50 @@ 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. Please see LICENSE files in the repository root for full details.
*/ */
import React, { type ReactNode } from "react";
import * as utils from "matrix-js-sdk/src/utils";
import { MatrixError, JoinRule, type Room, type MatrixEvent } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import { logger } from "matrix-js-sdk/src/logger";
import { type ViewRoom as ViewRoomEvent } from "@matrix-org/analytics-events/types/typescript/ViewRoom";
import { type JoinedRoom as JoinedRoomEvent } from "@matrix-org/analytics-events/types/typescript/JoinedRoom"; import { type JoinedRoom as JoinedRoomEvent } from "@matrix-org/analytics-events/types/typescript/JoinedRoom";
import { type Optional } from "matrix-events-sdk"; import { type ViewRoom as ViewRoomEvent } from "@matrix-org/analytics-events/types/typescript/ViewRoom";
import EventEmitter from "events";
import { import {
RoomViewLifecycle, RoomViewLifecycle,
type ViewRoomOpts, type ViewRoomOpts,
} from "@matrix-org/react-sdk-module-api/lib/lifecycles/RoomViewLifecycle"; } from "@matrix-org/react-sdk-module-api/lib/lifecycles/RoomViewLifecycle";
import EventEmitter from "events";
import { type Optional } from "matrix-events-sdk";
import { logger } from "matrix-js-sdk/src/logger";
import { JoinRule, MatrixError, type MatrixEvent, type Room } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import * as utils from "matrix-js-sdk/src/utils";
import React, { type ReactNode } from "react";
import { type MatrixDispatcher } from "../dispatcher/dispatcher"; import ErrorDialog from "../components/views/dialogs/ErrorDialog";
import { MatrixClientPeg } from "../MatrixClientPeg";
import Modal from "../Modal";
import { _t } from "../languageHandler";
import { getCachedRoomIDForAlias, storeRoomAliasInCache } from "../RoomAliasCache";
import { Action } from "../dispatcher/actions";
import { retry } from "../utils/promise";
import { TimelineRenderingType } from "../contexts/RoomContext"; import { TimelineRenderingType } from "../contexts/RoomContext";
import { type ViewRoomPayload } from "../dispatcher/payloads/ViewRoomPayload"; import { type SdkContextClass } from "../contexts/SDKContext";
import DMRoomMap from "../utils/DMRoomMap"; import { Action } from "../dispatcher/actions";
import { isMetaSpace, MetaSpace } from "./spaces"; import { type MatrixDispatcher } from "../dispatcher/dispatcher";
import { type ActionPayload } from "../dispatcher/payloads";
import { type ActiveRoomChangedPayload } from "../dispatcher/payloads/ActiveRoomChangedPayload";
import { type CancelAskToJoinPayload } from "../dispatcher/payloads/CancelAskToJoinPayload";
import { type JoinRoomErrorPayload } from "../dispatcher/payloads/JoinRoomErrorPayload";
import { type JoinRoomPayload } from "../dispatcher/payloads/JoinRoomPayload"; import { type JoinRoomPayload } from "../dispatcher/payloads/JoinRoomPayload";
import { type JoinRoomReadyPayload } from "../dispatcher/payloads/JoinRoomReadyPayload"; import { type JoinRoomReadyPayload } from "../dispatcher/payloads/JoinRoomReadyPayload";
import { type JoinRoomErrorPayload } from "../dispatcher/payloads/JoinRoomErrorPayload";
import { type ViewRoomErrorPayload } from "../dispatcher/payloads/ViewRoomErrorPayload";
import ErrorDialog from "../components/views/dialogs/ErrorDialog";
import { type ActiveRoomChangedPayload } from "../dispatcher/payloads/ActiveRoomChangedPayload";
import SettingsStore from "../settings/SettingsStore";
import { awaitRoomDownSync } from "../utils/RoomUpgrade";
import { UPDATE_EVENT } from "./AsyncStore";
import { type SdkContextClass } from "../contexts/SDKContext";
import { CallStore } from "./CallStore";
import { type ThreadPayload } from "../dispatcher/payloads/ThreadPayload";
import { type ActionPayload } from "../dispatcher/payloads";
import { type CancelAskToJoinPayload } from "../dispatcher/payloads/CancelAskToJoinPayload";
import { type SubmitAskToJoinPayload } from "../dispatcher/payloads/SubmitAskToJoinPayload"; import { type SubmitAskToJoinPayload } from "../dispatcher/payloads/SubmitAskToJoinPayload";
import { ModuleRunner } from "../modules/ModuleRunner"; import { type ThreadPayload } from "../dispatcher/payloads/ThreadPayload";
import { setMarkedUnreadState } from "../utils/notifications"; import { type ViewRoomErrorPayload } from "../dispatcher/payloads/ViewRoomErrorPayload";
import { type ViewRoomPayload } from "../dispatcher/payloads/ViewRoomPayload";
import { _t } from "../languageHandler";
import { MatrixClientPeg } from "../MatrixClientPeg";
import Modal from "../Modal";
import { ConnectionState, ElementCall } from "../models/Call"; import { ConnectionState, ElementCall } from "../models/Call";
import { ModuleRunner } from "../modules/ModuleRunner";
import { getCachedRoomIDForAlias, storeRoomAliasInCache } from "../RoomAliasCache";
import SettingsStore from "../settings/SettingsStore";
import DMRoomMap from "../utils/DMRoomMap";
import { setMarkedUnreadState } from "../utils/notifications";
import { retry } from "../utils/promise";
import { awaitRoomDownSync } from "../utils/RoomUpgrade";
import { isVideoRoom } from "../utils/video-rooms"; import { isVideoRoom } from "../utils/video-rooms";
import { UPDATE_EVENT } from "./AsyncStore";
import { CallStore } from "./CallStore";
import { isMetaSpace, MetaSpace } from "./spaces";
const NUM_JOIN_RETRY = 5; const NUM_JOIN_RETRY = 5;
@@ -265,14 +265,14 @@ export class RoomViewStore extends EventEmitter {
numMembers > 1000 numMembers > 1000
? "MoreThanAThousand" ? "MoreThanAThousand"
: numMembers > 100 : numMembers > 100
? "OneHundredAndOneToAThousand" ? "OneHundredAndOneToAThousand"
: numMembers > 10 : numMembers > 10
? "ElevenToOneHundred" ? "ElevenToOneHundred"
: numMembers > 2 : numMembers > 2
? "ThreeToTen" ? "ThreeToTen"
: numMembers > 1 : numMembers > 1
? "Two" ? "Two"
: "One"; : "One";
this.stores.posthogAnalytics.trackEvent<JoinedRoomEvent>({ this.stores.posthogAnalytics.trackEvent<JoinedRoomEvent>({
eventName: "JoinedRoom", eventName: "JoinedRoom",
@@ -537,6 +537,33 @@ export class RoomViewStore extends EventEmitter {
metricsTrigger: payload.metricsTrigger, metricsTrigger: payload.metricsTrigger,
}); });
} catch (err) { } catch (err) {
if (err instanceof MatrixError) {
if (err.errcode === "RE_JKI_JOIN_POLICY_URL") {
const redirect_url = [
window.location.origin,
window.location.pathname.replace(/\/$/, ""), // Remove trailing slash if present
"/static/join_room_redirect.html"
].join("")
const url = err.data["re.jki.join_policy_url"] + "?redirect_url=" + redirect_url;
window.addEventListener("message", (event) => {
if (event.data instanceof Object) {
if ("action" in event.data && event.data.action == "join") {
payload.opts = payload.opts || {};
payload.opts.token = event.data.token;
this.joinRoom(payload);
}
}
})
window.open(url, "join_window");
return;
}
}
this.dis?.dispatch({ this.dis?.dispatch({
action: Action.JoinRoomError, action: Action.JoinRoomError,
roomId, roomId,

View File

@@ -176,14 +176,14 @@ module.exports = (env, argv) => {
minimize: enableMinification, minimize: enableMinification,
minimizer: enableMinification minimizer: enableMinification
? [ ? [
new TerserPlugin({ new TerserPlugin({
// Already minified and includes an auto-generated license comment // Already minified and includes an auto-generated license comment
// that the plugin would otherwise pointlessly extract into a separate // that the plugin would otherwise pointlessly extract into a separate
// file. We add the actual license using CopyWebpackPlugin below. // file. We add the actual license using CopyWebpackPlugin below.
exclude: "jitsi_external_api.min.js", exclude: "jitsi_external_api.min.js",
}), }),
new CssMinimizerPlugin(), new CssMinimizerPlugin(),
] ]
: [], : [],
// Set the value of `process.env.NODE_ENV` for libraries like React // Set the value of `process.env.NODE_ENV` for libraries like React
@@ -625,6 +625,12 @@ module.exports = (env, argv) => {
minify: false, minify: false,
chunks: [], chunks: [],
}), }),
new HtmlWebpackPlugin({
template: "./src/vector/static/join_room_redirect.html",
filename: "static/join_room_redirect.html",
minify: false,
chunks: [],
}),
new HtmlWebpackPlugin({ new HtmlWebpackPlugin({
template: "./src/vector/static/incompatible-browser.html", template: "./src/vector/static/incompatible-browser.html",
filename: "static/incompatible-browser.html", filename: "static/incompatible-browser.html",
@@ -648,16 +654,16 @@ module.exports = (env, argv) => {
// This plugin throws an error on import on some platforms like ppc64le & s390x even if the plugin isn't called, // This plugin throws an error on import on some platforms like ppc64le & s390x even if the plugin isn't called,
// so we require it conditionally. // so we require it conditionally.
process.env.SENTRY_DSN && process.env.SENTRY_DSN &&
require("@sentry/webpack-plugin").sentryWebpackPlugin({ require("@sentry/webpack-plugin").sentryWebpackPlugin({
release: process.env.VERSION, release: process.env.VERSION,
sourcemaps: { sourcemaps: {
paths: "./webapp/bundles/**", paths: "./webapp/bundles/**",
}, },
errorHandler: (err) => { errorHandler: (err) => {
console.warn("Sentry CLI Plugin: " + err.message); console.warn("Sentry CLI Plugin: " + err.message);
console.log(`::warning title=Sentry error::${err.message}`); console.log(`::warning title=Sentry error::${err.message}`);
}, },
}), }),
new CopyWebpackPlugin({ new CopyWebpackPlugin({
patterns: [ patterns: [