${tex}`)
+ }
+ });
+ return phtml.html();
}
// ensure removal of escape backslashes in non-Markdown messages
if (md.indexOf("\\") > -1) {
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 1b54d33bf9..c5e308b52a 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -755,6 +755,7 @@
"%(senderName)s: %(reaction)s": "%(senderName)s: %(reaction)s",
"%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s",
"Change notification settings": "Change notification settings",
+ "Render LaTeX maths in messages": "Render LaTeX maths in messages",
"Communities v2 prototypes. Requires compatible homeserver. Highly experimental - use with caution.": "Communities v2 prototypes. Requires compatible homeserver. Highly experimental - use with caution.",
"New spinner design": "New spinner design",
"Message Pinning": "Message Pinning",
@@ -836,8 +837,10 @@
"When rooms are upgraded": "When rooms are upgraded",
"My Ban List": "My Ban List",
"This is your list of users/servers you have blocked - don't leave the room!": "This is your list of users/servers you have blocked - don't leave the room!",
- "Active call": "Active call",
- "Call Paused": "Call Paused",
+ "Video Call": "Video Call",
+ "Voice Call": "Voice Call",
+ "Fill Screen": "Fill Screen",
+ "Return to call": "Return to call",
"Unknown caller": "Unknown caller",
"Incoming voice call": "Incoming voice call",
"Incoming video call": "Incoming video call",
@@ -2286,10 +2289,11 @@
"Nice, strong password!": "Nice, strong password!",
"Password is allowed, but unsafe": "Password is allowed, but unsafe",
"Keep going...": "Keep going...",
- "The email field must not be blank.": "The email field must not be blank.",
- "The username field must not be blank.": "The username field must not be blank.",
- "The phone number field must not be blank.": "The phone number field must not be blank.",
- "The password field must not be blank.": "The password field must not be blank.",
+ "Enter username": "Enter username",
+ "Enter email address": "Enter email address",
+ "Doesn't look like a valid email address": "Doesn't look like a valid email address",
+ "Enter phone number": "Enter phone number",
+ "Doesn't look like a valid phone number": "Doesn't look like a valid phone number",
"Email": "Email",
"Username": "Username",
"Phone": "Phone",
@@ -2300,12 +2304,9 @@
"If you don't specify an email address, you won't be able to reset your password. Are you sure?": "If you don't specify an email address, you won't be able to reset your password. Are you sure?",
"Use an email address to recover your account": "Use an email address to recover your account",
"Enter email address (required on this homeserver)": "Enter email address (required on this homeserver)",
- "Doesn't look like a valid email address": "Doesn't look like a valid email address",
"Other users can invite you to rooms using your contact details": "Other users can invite you to rooms using your contact details",
"Enter phone number (required on this homeserver)": "Enter phone number (required on this homeserver)",
- "Doesn't look like a valid phone number": "Doesn't look like a valid phone number",
"Use lowercase letters, numbers, dashes and underscores only": "Use lowercase letters, numbers, dashes and underscores only",
- "Enter username": "Enter username",
"Email (optional)": "Email (optional)",
"Phone (optional)": "Phone (optional)",
"Register": "Register",
@@ -2440,10 +2441,6 @@
"%(count)s of your messages have not been sent.|one": "Your message was not sent.",
"%(count)s
Resend all or
cancel all now. You can also select individual messages to resend or cancel.|other": "
Resend all or
cancel all now. You can also select individual messages to resend or cancel.",
"%(count)s
Resend all or
cancel all now. You can also select individual messages to resend or cancel.|one": "
Resend message or
cancel message now.",
- "Calling...": "Calling...",
- "Call connecting...": "Call connecting...",
- "Starting camera...": "Starting camera...",
- "Starting microphone...": "Starting microphone...",
"Connectivity to the server has been lost.": "Connectivity to the server has been lost.",
"Sent messages will be stored until your connection has returned.": "Sent messages will be stored until your connection has returned.",
"You seem to be uploading files, are you sure you want to quit?": "You seem to be uploading files, are you sure you want to quit?",
@@ -2455,11 +2452,6 @@
"Failed to reject invite": "Failed to reject invite",
"You have %(count)s unread notifications in a prior version of this room.|other": "You have %(count)s unread notifications in a prior version of this room.",
"You have %(count)s unread notifications in a prior version of this room.|one": "You have %(count)s unread notification in a prior version of this room.",
- "Fill screen": "Fill screen",
- "Click to unmute video": "Click to unmute video",
- "Click to mute video": "Click to mute video",
- "Click to unmute audio": "Click to unmute audio",
- "Click to mute audio": "Click to mute audio",
"Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.",
"Tried to load a specific point in this room's timeline, but was unable to find it.": "Tried to load a specific point in this room's timeline, but was unable to find it.",
"Failed to load timeline position": "Failed to load timeline position",
@@ -2467,6 +2459,8 @@
"Uploading %(filename)s and %(count)s others|zero": "Uploading %(filename)s",
"Uploading %(filename)s and %(count)s others|one": "Uploading %(filename)s and %(count)s other",
"Failed to find the general chat for this community": "Failed to find the general chat for this community",
+ "Got an account?
Sign in": "Got an account?
Sign in",
+ "New here?
Create an account": "New here?
Create an account",
"Notification settings": "Notification settings",
"Security & privacy": "Security & privacy",
"All settings": "All settings",
@@ -2512,7 +2506,6 @@
"Incorrect username and/or password.": "Incorrect username and/or password.",
"Please note you are logging into the %(hs)s server, not matrix.org.": "Please note you are logging into the %(hs)s server, not matrix.org.",
"Failed to perform homeserver discovery": "Failed to perform homeserver discovery",
- "The phone number entered looks invalid": "The phone number entered looks invalid",
"This homeserver doesn't offer any login flows which are supported by this client.": "This homeserver doesn't offer any login flows which are supported by this client.",
"Error: Problem communicating with the given homeserver.": "Error: Problem communicating with the given homeserver.",
"Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or
enable unsafe scripts.": "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or
enable unsafe scripts.",
diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts
index cc6fd29fe3..31e133be72 100644
--- a/src/settings/Settings.ts
+++ b/src/settings/Settings.ts
@@ -117,6 +117,12 @@ export interface ISetting {
}
export const SETTINGS: {[setting: string]: ISetting} = {
+ "feature_latex_maths": {
+ isFeature: true,
+ displayName: _td("Render LaTeX maths in messages"),
+ supportedLevels: LEVELS_FEATURE,
+ default: false,
+ },
"feature_communities_v2_prototypes": {
isFeature: true,
displayName: _td(
diff --git a/src/stores/ModalWidgetStore.ts b/src/stores/ModalWidgetStore.ts
index 0485afd106..c0b64d76fe 100644
--- a/src/stores/ModalWidgetStore.ts
+++ b/src/stores/ModalWidgetStore.ts
@@ -64,7 +64,7 @@ export class ModalWidgetStore extends AsyncStoreWithClient
{
this.openSourceWidgetId = null;
this.modalInstance = null;
},
- });
+ }, null, /* priority = */ false, /* static = */ true);
};
public closeModalWidget = (sourceWidget: Widget, data?: IModalWidgetReturnData) => {
diff --git a/src/stores/widgets/StopGapWidget.ts b/src/stores/widgets/StopGapWidget.ts
index 04e27dd5fc..cc2934aec1 100644
--- a/src/stores/widgets/StopGapWidget.ts
+++ b/src/stores/widgets/StopGapWidget.ts
@@ -17,8 +17,6 @@
import { Room } from "matrix-js-sdk/src/models/room";
import {
ClientWidgetApi,
- IGetOpenIDActionRequest,
- IGetOpenIDActionResponseData,
IStickerActionRequest,
IStickyActionRequest,
ITemplateParams,
@@ -27,10 +25,8 @@ import {
IWidgetApiRequestEmptyData,
IWidgetData,
MatrixCapabilities,
- OpenIDRequestState,
runTemplate,
Widget,
- WidgetApiToWidgetAction,
WidgetApiFromWidgetAction,
IModalWidgetOpenRequest,
IWidgetApiErrorResponseData,
@@ -50,8 +46,6 @@ import ActiveWidgetStore from "../ActiveWidgetStore";
import { objectShallowClone } from "../../utils/objects";
import defaultDispatcher from "../../dispatcher/dispatcher";
import { ElementWidgetActions, IViewRoomApiRequest } from "./ElementWidgetActions";
-import Modal from "../../Modal";
-import WidgetOpenIDPermissionsDialog from "../../components/views/dialogs/WidgetOpenIDPermissionsDialog";
import {ModalWidgetStore} from "../ModalWidgetStore";
import ThemeWatcher from "../../settings/watchers/ThemeWatcher";
import {getCustomTheme} from "../../theme";
@@ -74,9 +68,9 @@ interface IAppTileProps {
}
// TODO: Don't use this because it's wrong
-class ElementWidget extends Widget {
- constructor(w) {
- super(w);
+export class ElementWidget extends Widget {
+ constructor(private rawDefinition: IWidget) {
+ super(rawDefinition);
}
public get templateUrl(): string {
@@ -137,12 +131,7 @@ class ElementWidget extends Widget {
public getCompleteUrl(params: ITemplateParams, asPopout=false): string {
return runTemplate(asPopout ? this.popoutTemplateUrl : this.templateUrl, {
- // we need to supply a whole widget to the template, but don't have
- // easy access to the definition the superclass is using, so be sad
- // and gutwrench it.
- // This isn't a problem when the widget architecture is fixed and this
- // subclass gets deleted.
- ...super['definition'], // XXX: Private member access
+ ...this.rawDefinition,
data: this.rawData,
}, params);
}
@@ -240,55 +229,6 @@ export class StopGapWidget extends EventEmitter {
return this.messaging.widget.id;
}
- private onOpenIdReq = async (ev: CustomEvent) => {
- ev.preventDefault();
-
- const rawUrl = this.appTileProps.app.url;
- const widgetSecurityKey = WidgetUtils.getWidgetSecurityKey(this.widgetId, rawUrl, this.appTileProps.userWidget);
-
- const settings = SettingsStore.getValue("widgetOpenIDPermissions");
- if (settings.deny && settings.deny.includes(widgetSecurityKey)) {
- this.messaging.transport.reply(ev.detail, {
- state: OpenIDRequestState.Blocked,
- });
- return;
- }
- if (settings.allow && settings.allow.includes(widgetSecurityKey)) {
- const credentials = await MatrixClientPeg.get().getOpenIdToken();
- this.messaging.transport.reply(ev.detail, {
- state: OpenIDRequestState.Allowed,
- ...credentials,
- });
- return;
- }
-
- // Confirm that we received the request
- this.messaging.transport.reply(ev.detail, {
- state: OpenIDRequestState.PendingUserConfirmation,
- });
-
- // Actually ask for permission to send the user's data
- Modal.createTrackedDialog("OpenID widget permissions", '', WidgetOpenIDPermissionsDialog, {
- widgetUrl: rawUrl,
- widgetId: this.widgetId,
- isUserWidget: this.appTileProps.userWidget,
-
- onFinished: async (confirm) => {
- const responseBody: IGetOpenIDActionResponseData = {
- state: confirm ? OpenIDRequestState.Allowed : OpenIDRequestState.Blocked,
- original_request_id: ev.detail.requestId, // eslint-disable-line camelcase
- };
- if (confirm) {
- const credentials = await MatrixClientPeg.get().getOpenIdToken();
- Object.assign(responseBody, credentials);
- }
- this.messaging.transport.send(WidgetApiToWidgetAction.OpenIDCredentials, responseBody).catch(error => {
- console.error("Failed to send OpenID credentials: ", error);
- });
- },
- });
- };
-
private onOpenModal = async (ev: CustomEvent) => {
ev.preventDefault();
if (ModalWidgetStore.instance.canOpenModalWidget()) {
@@ -306,11 +246,10 @@ export class StopGapWidget extends EventEmitter {
public start(iframe: HTMLIFrameElement) {
if (this.started) return;
const allowedCapabilities = this.appTileProps.whitelistCapabilities || [];
- const driver = new StopGapWidgetDriver( allowedCapabilities, this.mockWidget, this.kind);
+ const driver = new StopGapWidgetDriver(allowedCapabilities, this.mockWidget, this.kind, this.roomId);
this.messaging = new ClientWidgetApi(this.mockWidget, iframe, driver);
this.messaging.on("preparing", () => this.emit("preparing"));
this.messaging.on("ready", () => this.emit("ready"));
- this.messaging.on(`action:${WidgetApiFromWidgetAction.GetOpenIDCredentials}`, this.onOpenIdReq);
this.messaging.on(`action:${WidgetApiFromWidgetAction.OpenModalWidget}`, this.onOpenModal);
WidgetMessagingStore.instance.storeMessaging(this.mockWidget, this.messaging);
@@ -351,18 +290,39 @@ export class StopGapWidget extends EventEmitter {
MatrixClientPeg.get().on('event', this.onEvent);
MatrixClientPeg.get().on('Event.decrypted', this.onEventDecrypted);
- if (WidgetType.JITSI.matches(this.mockWidget.type)) {
- this.messaging.on("action:set_always_on_screen",
- (ev: CustomEvent) => {
- if (this.messaging.hasCapability(MatrixCapabilities.AlwaysOnScreen)) {
+ this.messaging.on(`action:${WidgetApiFromWidgetAction.UpdateAlwaysOnScreen}`,
+ (ev: CustomEvent) => {
+ if (this.messaging.hasCapability(MatrixCapabilities.AlwaysOnScreen)) {
+ if (WidgetType.JITSI.matches(this.mockWidget.type)) {
CountlyAnalytics.instance.trackJoinCall(this.appTileProps.room.roomId, true, true);
- ActiveWidgetStore.setWidgetPersistence(this.mockWidget.id, ev.detail.data.value);
- ev.preventDefault();
- this.messaging.transport.reply(ev.detail, {}); // ack
}
- },
- );
- } else if (WidgetType.STICKERPICKER.matches(this.mockWidget.type)) {
+ ActiveWidgetStore.setWidgetPersistence(this.mockWidget.id, ev.detail.data.value);
+ ev.preventDefault();
+ this.messaging.transport.reply(ev.detail, {}); // ack
+ }
+ },
+ );
+
+ // TODO: Replace this event listener with appropriate driver functionality once the API
+ // establishes a sane way to send events back and forth.
+ this.messaging.on(`action:${WidgetApiFromWidgetAction.SendSticker}`,
+ (ev: CustomEvent) => {
+ if (this.messaging.hasCapability(MatrixCapabilities.StickerSending)) {
+ // Acknowledge first
+ ev.preventDefault();
+ this.messaging.transport.reply(ev.detail, {});
+
+ // Send the sticker
+ defaultDispatcher.dispatch({
+ action: 'm.sticker',
+ data: ev.detail.data,
+ widgetId: this.mockWidget.id,
+ });
+ }
+ },
+ );
+
+ if (WidgetType.STICKERPICKER.matches(this.mockWidget.type)) {
this.messaging.on(`action:${ElementWidgetActions.OpenIntegrationManager}`,
(ev: CustomEvent) => {
// Acknowledge first
@@ -394,23 +354,6 @@ export class StopGapWidget extends EventEmitter {
}
},
);
-
- // TODO: Replace this event listener with appropriate driver functionality once the API
- // establishes a sane way to send events back and forth.
- this.messaging.on(`action:${WidgetApiFromWidgetAction.SendSticker}`,
- (ev: CustomEvent) => {
- // Acknowledge first
- ev.preventDefault();
- this.messaging.transport.reply(ev.detail, {});
-
- // Send the sticker
- defaultDispatcher.dispatch({
- action: 'm.sticker',
- data: ev.detail.data,
- widgetId: this.mockWidget.id,
- });
- },
- );
}
}
diff --git a/src/stores/widgets/StopGapWidgetDriver.ts b/src/stores/widgets/StopGapWidgetDriver.ts
index 722c7d8f49..60988040d3 100644
--- a/src/stores/widgets/StopGapWidgetDriver.ts
+++ b/src/stores/widgets/StopGapWidgetDriver.ts
@@ -16,19 +16,30 @@
import {
Capability,
+ EventDirection,
+ IOpenIDCredentials,
+ IOpenIDUpdate,
ISendEventDetails,
MatrixCapabilities,
+ OpenIDRequestState,
+ SimpleObservable,
Widget,
WidgetDriver,
+ WidgetEventCapability,
WidgetKind,
} from "matrix-widget-api";
import { iterableDiff, iterableUnion } from "../../utils/iterables";
import { MatrixClientPeg } from "../../MatrixClientPeg";
import ActiveRoomObserver from "../../ActiveRoomObserver";
import Modal from "../../Modal";
+import WidgetOpenIDPermissionsDialog from "../../components/views/dialogs/WidgetOpenIDPermissionsDialog";
import WidgetCapabilitiesPromptDialog, {
getRememberedCapabilitiesForWidget,
} from "../../components/views/dialogs/WidgetCapabilitiesPromptDialog";
+import { WidgetPermissionCustomisations } from "../../customisations/WidgetPermissions";
+import { OIDCState, WidgetPermissionStore } from "./WidgetPermissionStore";
+import { WidgetType } from "../../widgets/WidgetType";
+import { EventType } from "matrix-js-sdk/src/@types/event";
// TODO: Purge this from the universe
@@ -36,13 +47,27 @@ export class StopGapWidgetDriver extends WidgetDriver {
private allowedCapabilities: Set;
// TODO: Refactor widgetKind into the Widget class
- constructor(allowedCapabilities: Capability[], private forWidget: Widget, private forWidgetKind: WidgetKind) {
+ constructor(
+ allowedCapabilities: Capability[],
+ private forWidget: Widget,
+ private forWidgetKind: WidgetKind,
+ private inRoomId?: string,
+ ) {
super();
// Always allow screenshots to be taken because it's a client-induced flow. The widget can't
// spew screenshots at us and can't request screenshots of us, so it's up to us to provide the
// button if the widget says it supports screenshots.
this.allowedCapabilities = new Set([...allowedCapabilities, MatrixCapabilities.Screenshots]);
+
+ // Grant the permissions that are specific to given widget types
+ if (WidgetType.JITSI.matches(this.forWidget.type) && forWidgetKind === WidgetKind.Room) {
+ this.allowedCapabilities.add(MatrixCapabilities.AlwaysOnScreen);
+ } else if (WidgetType.STICKERPICKER.matches(this.forWidget.type) && forWidgetKind === WidgetKind.Account) {
+ const stickerSendingCap = WidgetEventCapability.forRoomEvent(EventDirection.Send, EventType.Sticker).raw;
+ this.allowedCapabilities.add(MatrixCapabilities.StickerSending); // legacy as far as MSC2762 is concerned
+ this.allowedCapabilities.add(stickerSendingCap);
+ }
}
public async validateCapabilities(requested: Set): Promise> {
@@ -52,7 +77,19 @@ export class StopGapWidgetDriver extends WidgetDriver {
const diff = iterableDiff(requested, this.allowedCapabilities);
const missing = new Set(diff.removed); // "removed" is "in A (requested) but not in B (allowed)"
const allowedSoFar = new Set(this.allowedCapabilities);
- getRememberedCapabilitiesForWidget(this.forWidget).forEach(cap => allowedSoFar.add(cap));
+ getRememberedCapabilitiesForWidget(this.forWidget).forEach(cap => {
+ allowedSoFar.add(cap);
+ missing.delete(cap);
+ });
+ if (WidgetPermissionCustomisations.preapproveCapabilities) {
+ const approved = await WidgetPermissionCustomisations.preapproveCapabilities(this.forWidget, requested);
+ if (approved) {
+ approved.forEach(cap => {
+ allowedSoFar.add(cap);
+ missing.delete(cap);
+ });
+ }
+ }
// TODO: Do something when the widget requests new capabilities not yet asked for
if (missing.size > 0) {
try {
@@ -79,7 +116,7 @@ export class StopGapWidgetDriver extends WidgetDriver {
if (!client || !roomId) throw new Error("Not in a room or not attached to a client");
- let r: {event_id: string} = null; // eslint-disable-line camelcase
+ let r: { event_id: string } = null; // eslint-disable-line camelcase
if (stateKey !== null) {
// state event
r = await client.sendStateEvent(roomId, eventType, content, stateKey);
@@ -90,4 +127,37 @@ export class StopGapWidgetDriver extends WidgetDriver {
return {roomId, eventId: r.event_id};
}
+
+ public async askOpenID(observer: SimpleObservable) {
+ const oidcState = WidgetPermissionStore.instance.getOIDCState(
+ this.forWidget, this.forWidgetKind, this.inRoomId,
+ );
+
+ const getToken = (): Promise => {
+ return MatrixClientPeg.get().getOpenIdToken();
+ };
+
+ if (oidcState === OIDCState.Denied) {
+ return observer.update({state: OpenIDRequestState.Blocked});
+ }
+ if (oidcState === OIDCState.Allowed) {
+ return observer.update({state: OpenIDRequestState.Allowed, token: await getToken()});
+ }
+
+ observer.update({state: OpenIDRequestState.PendingUserConfirmation});
+
+ Modal.createTrackedDialog("OpenID widget permissions", '', WidgetOpenIDPermissionsDialog, {
+ widget: this.forWidget,
+ widgetKind: this.forWidgetKind,
+ inRoomId: this.inRoomId,
+
+ onFinished: async (confirm) => {
+ if (!confirm) {
+ return observer.update({state: OpenIDRequestState.Blocked});
+ }
+
+ return observer.update({state: OpenIDRequestState.Allowed, token: await getToken()});
+ },
+ });
+ }
}
diff --git a/src/stores/widgets/WidgetPermissionStore.ts b/src/stores/widgets/WidgetPermissionStore.ts
new file mode 100644
index 0000000000..41e8bc6652
--- /dev/null
+++ b/src/stores/widgets/WidgetPermissionStore.ts
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import SettingsStore from "../../settings/SettingsStore";
+import { Widget, WidgetKind } from "matrix-widget-api";
+import { MatrixClientPeg } from "../../MatrixClientPeg";
+import { SettingLevel } from "../../settings/SettingLevel";
+
+export enum OIDCState {
+ Allowed, // user has set the remembered value as allowed
+ Denied, // user has set the remembered value as disallowed
+ Unknown, // user has not set a remembered value
+}
+
+export class WidgetPermissionStore {
+ private static internalInstance: WidgetPermissionStore;
+
+ private constructor() {
+ }
+
+ public static get instance(): WidgetPermissionStore {
+ if (!WidgetPermissionStore.internalInstance) {
+ WidgetPermissionStore.internalInstance = new WidgetPermissionStore();
+ }
+ return WidgetPermissionStore.internalInstance;
+ }
+
+ // TODO (all functions here): Merge widgetKind with the widget definition
+
+ private packSettingKey(widget: Widget, kind: WidgetKind, roomId?: string): string {
+ let location = roomId;
+ if (kind !== WidgetKind.Room) {
+ location = MatrixClientPeg.get().getUserId();
+ }
+ if (kind === WidgetKind.Modal) {
+ location = '*MODAL*-' + location; // to guarantee differentiation from whatever spawned it
+ }
+ if (!location) {
+ throw new Error("Failed to determine a location to check the widget's OIDC state with");
+ }
+
+ return encodeURIComponent(`${location}::${widget.templateUrl}`);
+ }
+
+ public getOIDCState(widget: Widget, kind: WidgetKind, roomId?: string): OIDCState {
+ const settingsKey = this.packSettingKey(widget, kind, roomId);
+ const settings = SettingsStore.getValue("widgetOpenIDPermissions");
+ if (settings?.deny?.includes(settingsKey)) {
+ return OIDCState.Denied;
+ }
+ if (settings?.allow?.includes(settingsKey)) {
+ return OIDCState.Allowed;
+ }
+ return OIDCState.Unknown;
+ }
+
+ public setOIDCState(widget: Widget, kind: WidgetKind, roomId: string, newState: OIDCState) {
+ const settingsKey = this.packSettingKey(widget, kind, roomId);
+
+ const currentValues = SettingsStore.getValue("widgetOpenIDPermissions");
+ if (!currentValues.allow) currentValues.allow = [];
+ if (!currentValues.deny) currentValues.deny = [];
+
+ if (newState === OIDCState.Allowed) {
+ currentValues.allow.push(settingsKey);
+ } else if (newState === OIDCState.Denied) {
+ currentValues.deny.push(settingsKey);
+ } else {
+ currentValues.allow = currentValues.allow.filter(c => c !== settingsKey);
+ currentValues.deny = currentValues.deny.filter(c => c !== settingsKey);
+ }
+
+ SettingsStore.setValue("widgetOpenIDPermissions", null, SettingLevel.DEVICE, currentValues);
+ }
+}
diff --git a/src/utils/WidgetUtils.ts b/src/utils/WidgetUtils.ts
index 526c2d5ce7..986c68342c 100644
--- a/src/utils/WidgetUtils.ts
+++ b/src/utils/WidgetUtils.ts
@@ -22,7 +22,6 @@ import SdkConfig from "../SdkConfig";
import dis from '../dispatcher/dispatcher';
import WidgetEchoStore from '../stores/WidgetEchoStore';
import SettingsStore from "../settings/SettingsStore";
-import ActiveWidgetStore from "../stores/ActiveWidgetStore";
import {IntegrationManagers} from "../integrations/IntegrationManagers";
import {Room} from "matrix-js-sdk/src/models/room";
import {WidgetType} from "../widgets/WidgetType";
@@ -457,27 +456,6 @@ export default class WidgetUtils {
return capWhitelist;
}
- static getWidgetSecurityKey(widgetId: string, widgetUrl: string, isUserWidget: boolean): string {
- let widgetLocation = ActiveWidgetStore.getRoomId(widgetId);
-
- if (isUserWidget) {
- const userWidget = WidgetUtils.getUserWidgetsArray()
- .find((w) => w.id === widgetId && w.content && w.content.url === widgetUrl);
-
- if (!userWidget) {
- throw new Error("No matching user widget to form security key");
- }
-
- widgetLocation = userWidget.sender;
- }
-
- if (!widgetLocation) {
- throw new Error("Failed to locate where the widget resides");
- }
-
- return encodeURIComponent(`${widgetLocation}::${widgetUrl}`);
- }
-
static getLocalJitsiWrapperUrl(opts: {forLocalRender?: boolean, auth?: string} = {}) {
// NB. we can't just encodeURIComponent all of these because the $ signs need to be there
const queryStringParts = [
diff --git a/test/components/views/messages/TextualBody-test.js b/test/components/views/messages/TextualBody-test.js
index 07cd51edbd..bf55e9c430 100644
--- a/test/components/views/messages/TextualBody-test.js
+++ b/test/components/views/messages/TextualBody-test.js
@@ -36,6 +36,7 @@ describe("", () => {
MatrixClientPeg.matrixClient = {
getRoom: () => mkStubRoom("room_id"),
getAccountData: () => undefined,
+ isGuest: () => false,
};
const ev = mkEvent({
@@ -59,6 +60,7 @@ describe("", () => {
MatrixClientPeg.matrixClient = {
getRoom: () => mkStubRoom("room_id"),
getAccountData: () => undefined,
+ isGuest: () => false,
};
const ev = mkEvent({
@@ -83,6 +85,7 @@ describe("", () => {
MatrixClientPeg.matrixClient = {
getRoom: () => mkStubRoom("room_id"),
getAccountData: () => undefined,
+ isGuest: () => false,
};
});
@@ -135,6 +138,7 @@ describe("", () => {
getHomeserverUrl: () => "https://my_server/",
on: () => undefined,
removeListener: () => undefined,
+ isGuest: () => false,
};
});
diff --git a/yarn.lock b/yarn.lock
index 3a8e945b59..c06494d319 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6206,6 +6206,13 @@ jsx-ast-utils@^2.4.1:
array-includes "^3.1.1"
object.assign "^4.1.0"
+katex@^0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/katex/-/katex-0.12.0.tgz#2fb1c665dbd2b043edcf8a1f5c555f46beaa0cb9"
+ integrity sha512-y+8btoc/CK70XqcHqjxiGWBOeIL8upbS0peTPXTvgrh21n1RiWWcIpSWM+4uXq+IAgNh9YYQWdc7LVDPDAEEAg==
+ dependencies:
+ commander "^2.19.0"
+
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
version "3.2.2"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
@@ -6506,8 +6513,8 @@ mathml-tag-names@^2.0.1:
integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop":
- version "9.1.0"
- resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/5ac00e346593f29f324b3af8e322928a6e1c427a"
+ version "9.2.0"
+ resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/6661bde6088e6e43f31198e8532432e162aef33c"
dependencies:
"@babel/runtime" "^7.11.2"
another-json "^0.2.0"
@@ -6532,10 +6539,10 @@ matrix-react-test-utils@^0.2.2:
resolved "https://registry.yarnpkg.com/matrix-react-test-utils/-/matrix-react-test-utils-0.2.2.tgz#c87144d3b910c7edc544a6699d13c7c2bf02f853"
integrity sha512-49+7gfV6smvBIVbeloql+37IeWMTD+fiywalwCqk8Dnz53zAFjKSltB3rmWHso1uecLtQEcPtCijfhzcLXAxTQ==
-matrix-widget-api@^0.1.0-beta.9:
- version "0.1.0-beta.9"
- resolved "https://registry.yarnpkg.com/matrix-widget-api/-/matrix-widget-api-0.1.0-beta.9.tgz#83952132c1610e013acb3e695f923f971ddd5637"
- integrity sha512-nXo4iaquSya6hYLXccX8o1K960ckSQ0YXIubRDha+YmB+L09F5a7bUPS5JN2tYANOMzyfFAzWVuFwjHv4+K+rg==
+matrix-widget-api@^0.1.0-beta.10:
+ version "0.1.0-beta.10"
+ resolved "https://registry.yarnpkg.com/matrix-widget-api/-/matrix-widget-api-0.1.0-beta.10.tgz#2e4d658d90ff3152c5567089b4ddd21fb44ec1dd"
+ integrity sha512-yX2UURjM1zVp7snPiOFcH9+FDBdHfAdt5HEAyDUHGJ7w/F2zOtcK/y0dMlZ1+XhxY7Wv0IBZH0US8X/ioJRX1A==
dependencies:
events "^3.2.0"