Compare commits
2 Commits
robin/reve
...
t3chguy/pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc03ba64de | ||
|
|
859ba0e02c |
2
.github/workflows/dockerhub.yaml
vendored
2
.github/workflows/dockerhub.yaml
vendored
@@ -51,7 +51,7 @@ jobs:
|
||||
|
||||
- name: Build and push
|
||||
id: build-and-push
|
||||
uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6
|
||||
uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc # v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
|
||||
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@@ -104,7 +104,7 @@ jobs:
|
||||
|
||||
- name: Skip SonarCloud in merge queue
|
||||
if: github.event_name == 'merge_group' || inputs.disable_coverage == 'true'
|
||||
uses: guibranco/github-status-action-v2@ecd54a02cf761e85a8fb328fe937710fd4227cda
|
||||
uses: guibranco/github-status-action-v2@56cd38caf0615dd03f49d42ed301f1469911ac61
|
||||
with:
|
||||
authToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
state: success
|
||||
|
||||
@@ -8,13 +8,11 @@
|
||||
|
||||
#### develop
|
||||
|
||||
The develop branch holds the very latest and greatest code we have to offer, as such it may be less stable.
|
||||
It is auto-deployed on every commit to element-web or matrix-js-sdk to develop.element.io via GitHub Actions `build_develop.yml`.
|
||||
The develop branch holds the very latest and greatest code we have to offer, as such it may be less stable. It corresponds to the develop.element.io CD platform.
|
||||
|
||||
#### staging
|
||||
|
||||
The staging branch corresponds to the very latest release regardless of whether it is an RC or not. Deployed to staging.element.io manually.
|
||||
It is auto-deployed on every release of element-web to staging.element.io via GitHub Actions `deploy.yml`.
|
||||
|
||||
#### master
|
||||
|
||||
@@ -217,7 +215,7 @@ We ship Element Web to dockerhub, `*.element.io`, and packages.element.io.
|
||||
We ship Element Desktop to packages.element.io.
|
||||
|
||||
- [ ] Check that element-web has shipped to dockerhub
|
||||
- [ ] Check that the staging [deployment](https://github.com/element-hq/element-web/actions/workflows/deploy.yml) has completed successfully
|
||||
- [ ] Deploy staging.element.io. [See docs.](https://handbook.element.io/books/element-web-team/page/deploying-appstagingelementio)
|
||||
- [ ] Test staging.element.io
|
||||
|
||||
For final releases additionally do these steps:
|
||||
@@ -227,9 +225,6 @@ For final releases additionally do these steps:
|
||||
- [ ] Ensure Element Web package has shipped to packages.element.io
|
||||
- [ ] Ensure Element Desktop packages have shipped to packages.element.io
|
||||
|
||||
If you need to roll back a deployment to staging.element.io,
|
||||
you can run the `deploy.yml` automation choosing an older tag which you wish to deploy.
|
||||
|
||||
# Housekeeping
|
||||
|
||||
We have some manual housekeeping to do in order to prepare for the next release.
|
||||
|
||||
10
package.json
10
package.json
@@ -74,7 +74,7 @@
|
||||
"@types/react-dom": "18.3.5",
|
||||
"oidc-client-ts": "3.1.0",
|
||||
"jwt-decode": "4.0.0",
|
||||
"caniuse-lite": "1.0.30001692",
|
||||
"caniuse-lite": "1.0.30001690",
|
||||
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0",
|
||||
"wrap-ansi": "npm:wrap-ansi@^7.0.0"
|
||||
},
|
||||
@@ -128,7 +128,7 @@
|
||||
"matrix-encrypt-attachment": "^1.0.3",
|
||||
"matrix-events-sdk": "0.0.1",
|
||||
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
|
||||
"matrix-widget-api": "1.11.0",
|
||||
"matrix-widget-api": "^1.10.0",
|
||||
"memoize-one": "^6.0.0",
|
||||
"mime": "^4.0.4",
|
||||
"oidc-client-ts": "^3.0.1",
|
||||
@@ -178,7 +178,7 @@
|
||||
"@peculiar/webcrypto": "^1.4.3",
|
||||
"@playwright/test": "^1.40.1",
|
||||
"@principalstudio/html-webpack-inject-preload": "^1.2.7",
|
||||
"@sentry/webpack-plugin": "^3.0.0",
|
||||
"@sentry/webpack-plugin": "^2.7.1",
|
||||
"@stylistic/eslint-plugin": "^2.9.0",
|
||||
"@svgr/webpack": "^8.0.0",
|
||||
"@testcontainers/postgresql": "^10.16.0",
|
||||
@@ -230,7 +230,7 @@
|
||||
"dotenv": "^16.0.2",
|
||||
"eslint": "8.57.1",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-config-prettier": "^10.0.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-deprecate": "0.8.5",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"eslint-plugin-jest": "^28.0.0",
|
||||
@@ -287,7 +287,7 @@
|
||||
"terser-webpack-plugin": "^5.3.9",
|
||||
"testcontainers": "^10.16.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "5.7.3",
|
||||
"typescript": "5.7.2",
|
||||
"util": "^0.12.5",
|
||||
"web-streams-polyfill": "^4.0.0",
|
||||
"webpack": "^5.89.0",
|
||||
|
||||
@@ -42,7 +42,7 @@ test.describe("Memberlist", () => {
|
||||
await app.viewRoomByName(ROOM_NAME);
|
||||
const memberlist = await app.toggleMemberlistPanel();
|
||||
await expect(memberlist.locator(".mx_MemberTileView")).toHaveCount(4);
|
||||
await expect(memberlist.getByText("Invited")).toHaveCount(1);
|
||||
await expect(memberlist.getByText("(Invited)")).toHaveCount(1);
|
||||
await expect(page.locator(".mx_MemberListView")).toMatchScreenshot("with-four-members.png");
|
||||
});
|
||||
});
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
@@ -19,7 +19,7 @@ import { HomeserverContainer, StartedHomeserverContainer } from "./HomeserverCon
|
||||
import { StartedMatrixAuthenticationServiceContainer } from "./mas.ts";
|
||||
import { Api, ClientServerApi, Verb } from "../plugins/utils/api.ts";
|
||||
|
||||
const TAG = "develop@sha256:3594fba0d21ad44f407225baed4be0542da8abcb6e1a7e2e16d3be35c278a7cb";
|
||||
const TAG = "develop@sha256:5d62b61c4373eaca25df6c6bb99fc1be92f8f40b8abebd8897bf5b2af9eb137a";
|
||||
|
||||
const DEFAULT_CONFIG = {
|
||||
server_name: "localhost",
|
||||
|
||||
@@ -35,8 +35,6 @@ Please see LICENSE files in the repository root for full details.
|
||||
.mx_DisambiguatedProfile_mxid {
|
||||
margin-inline-start: 0;
|
||||
font: var(--cpd-font-body-sm-regular);
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
span:not(.mx_DisambiguatedProfile_mxid) {
|
||||
|
||||
@@ -35,7 +35,6 @@ Please see LICENSE files in the repository root for full details.
|
||||
font: var(--cpd-font-body-sm-regular);
|
||||
font-size: 13px;
|
||||
color: var(--cpd-color-text-secondary);
|
||||
margin-left: var(--cpd-space-4x);
|
||||
}
|
||||
|
||||
.mx_MemberTileView_avatar {
|
||||
|
||||
@@ -10,7 +10,6 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React, { StrictMode } from "react";
|
||||
import { createRoot, Root } from "react-dom/client";
|
||||
import classNames from "classnames";
|
||||
import { IDeferred, defer } from "matrix-js-sdk/src/utils";
|
||||
import { TypedEventEmitter } from "matrix-js-sdk/src/matrix";
|
||||
import { Glass, TooltipProvider } from "@vector-im/compound-web";
|
||||
|
||||
@@ -45,7 +44,7 @@ export interface IModal<C extends ComponentType> {
|
||||
onFinished: ComponentProps<C>["onFinished"];
|
||||
close(...args: Parameters<ComponentProps<C>["onFinished"]>): void;
|
||||
hidden?: boolean;
|
||||
deferred?: IDeferred<Parameters<ComponentProps<C>["onFinished"]>>;
|
||||
deferred?: PromiseWithResolvers<Parameters<ComponentProps<C>["onFinished"]>>;
|
||||
}
|
||||
|
||||
export interface IHandle<C extends ComponentType> {
|
||||
@@ -214,7 +213,7 @@ export class ModalManager extends TypedEventEmitter<ModalManagerEvent, HandlerMa
|
||||
modal: IModal<C>,
|
||||
props?: ComponentProps<C>,
|
||||
): [IHandle<C>["close"], IHandle<C>["finished"]] {
|
||||
modal.deferred = defer<Parameters<ComponentProps<C>["onFinished"]>>();
|
||||
modal.deferred = Promise.withResolvers<Parameters<ComponentProps<C>["onFinished"]>>();
|
||||
return [
|
||||
async (...args: Parameters<ComponentProps<C>["onFinished"]>): Promise<void> => {
|
||||
if (modal.beforeClosePromise) {
|
||||
|
||||
@@ -46,7 +46,7 @@ import {
|
||||
SlidingSync,
|
||||
} from "matrix-js-sdk/src/sliding-sync";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { defer, sleep } from "matrix-js-sdk/src/utils";
|
||||
import { sleep } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import SettingsStore from "./settings/SettingsStore";
|
||||
import SlidingSyncController from "./settings/controllers/SlidingSyncController";
|
||||
@@ -110,7 +110,7 @@ export class SlidingSyncManager {
|
||||
public slidingSync?: SlidingSync;
|
||||
private client?: MatrixClient;
|
||||
|
||||
private configureDefer = defer<void>();
|
||||
private configureDefer = Promise.withResolvers<void>();
|
||||
|
||||
public static get instance(): SlidingSyncManager {
|
||||
return SlidingSyncManager.internalInstance;
|
||||
|
||||
@@ -6,14 +6,12 @@ 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 { defer, IDeferred } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import { WorkerPayload } from "./workers/worker";
|
||||
|
||||
export class WorkerManager<Request extends {}, Response> {
|
||||
private readonly worker: Worker;
|
||||
private seq = 0;
|
||||
private pendingDeferredMap = new Map<number, IDeferred<Response>>();
|
||||
private pendingDeferredMap = new Map<number, PromiseWithResolvers<Response>>();
|
||||
|
||||
public constructor(worker: Worker) {
|
||||
this.worker = worker;
|
||||
@@ -30,7 +28,7 @@ export class WorkerManager<Request extends {}, Response> {
|
||||
|
||||
public call(request: Request): Promise<Response> {
|
||||
const seq = this.seq++;
|
||||
const deferred = defer<Response>();
|
||||
const deferred = Promise.withResolvers<Response>();
|
||||
this.pendingDeferredMap.set(seq, deferred);
|
||||
this.worker.postMessage({ seq, ...request });
|
||||
return deferred.promise;
|
||||
|
||||
@@ -9,7 +9,6 @@ Please see LICENSE files in the repository root for full details.
|
||||
import EventEmitter from "events";
|
||||
import { SimpleObservable } from "matrix-widget-api";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { defer } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import { UPDATE_EVENT } from "../stores/AsyncStore";
|
||||
import { arrayFastResample } from "../utils/arrays";
|
||||
@@ -158,7 +157,7 @@ export class Playback extends EventEmitter implements IDestroyable, PlaybackInte
|
||||
// 5mb
|
||||
logger.log("Audio file too large: processing through <audio /> element");
|
||||
this.element = document.createElement("AUDIO") as HTMLAudioElement;
|
||||
const deferred = defer<unknown>();
|
||||
const deferred = Promise.withResolvers<unknown>();
|
||||
this.element.onloadeddata = deferred.resolve;
|
||||
this.element.onerror = deferred.reject;
|
||||
this.element.src = URL.createObjectURL(new Blob([this.buf]));
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
SyncStateData,
|
||||
TimelineEvents,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { defer, IDeferred, QueryDict } from "matrix-js-sdk/src/utils";
|
||||
import { QueryDict } from "matrix-js-sdk/src/utils";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { throttle } from "lodash";
|
||||
import { CryptoEvent, KeyBackupInfo } from "matrix-js-sdk/src/crypto-api";
|
||||
@@ -217,7 +217,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||
};
|
||||
|
||||
private firstSyncComplete = false;
|
||||
private firstSyncPromise: IDeferred<void>;
|
||||
private firstSyncPromise: PromiseWithResolvers<void>;
|
||||
|
||||
private screenAfterLogin?: IScreen;
|
||||
private tokenLogin?: boolean;
|
||||
@@ -255,7 +255,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||
|
||||
// Used by _viewRoom before getting state from sync
|
||||
this.firstSyncComplete = false;
|
||||
this.firstSyncPromise = defer();
|
||||
this.firstSyncPromise = Promise.withResolvers();
|
||||
|
||||
if (this.props.config.sync_timeline_limit) {
|
||||
MatrixClientPeg.opts.initialSyncLimit = this.props.config.sync_timeline_limit;
|
||||
@@ -1503,7 +1503,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||
// since we're about to start the client and therefore about
|
||||
// to do the first sync
|
||||
this.firstSyncComplete = false;
|
||||
this.firstSyncPromise = defer();
|
||||
this.firstSyncPromise = Promise.withResolvers();
|
||||
const cli = MatrixClientPeg.safeGet();
|
||||
|
||||
// Allow the JS SDK to reap timeline events. This reduces the amount of
|
||||
|
||||
@@ -145,7 +145,7 @@ export function useMemberTileViewModel(props: MemberTileViewModelProps): MemberT
|
||||
userLabel = _t(PowerLabel[powerStatus]);
|
||||
}
|
||||
if (props.member.isInvite) {
|
||||
userLabel = _t("member_list|invited_label");
|
||||
userLabel = `(${_t("member_list|invited_label")})`;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -30,7 +30,7 @@ export function useThreePidTileViewModel(props: ThreePidTileViewModelProps): Thr
|
||||
});
|
||||
};
|
||||
|
||||
const userLabel = _t("member_list|invited_label");
|
||||
const userLabel = `(${_t("member_list|invited_label")})`;
|
||||
|
||||
return {
|
||||
name,
|
||||
|
||||
@@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import React from "react";
|
||||
import { MatrixEvent, EventType, RelationType, MatrixClient, MatrixError } from "matrix-js-sdk/src/matrix";
|
||||
import { defer } from "matrix-js-sdk/src/utils";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
@@ -58,7 +57,7 @@ export default class MessageEditHistoryDialog extends React.PureComponent<IProps
|
||||
const eventId = this.props.mxEvent.getId()!;
|
||||
const client = MatrixClientPeg.safeGet();
|
||||
|
||||
const { resolve, reject, promise } = defer<boolean>();
|
||||
const { resolve, reject, promise } = Promise.withResolvers<boolean>();
|
||||
let result: Awaited<ReturnType<MatrixClient["relations"]>>;
|
||||
|
||||
try {
|
||||
|
||||
@@ -10,7 +10,6 @@ import React, { createRef, KeyboardEvent, RefObject } from "react";
|
||||
import classNames from "classnames";
|
||||
import { flatMap } from "lodash";
|
||||
import { Room } from "matrix-js-sdk/src/matrix";
|
||||
import { defer } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import Autocompleter, { ICompletion, ISelectionRange, IProviderCompletions } from "../../../autocomplete/Autocompleter";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
@@ -173,7 +172,7 @@ export default class Autocomplete extends React.PureComponent<IProps, IState> {
|
||||
}
|
||||
}
|
||||
|
||||
const deferred = defer<void>();
|
||||
const deferred = Promise.withResolvers<void>();
|
||||
this.setState(
|
||||
{
|
||||
completions,
|
||||
|
||||
@@ -31,7 +31,8 @@ export function shouldShowQr(
|
||||
): boolean {
|
||||
const msc4108Supported = !!versions?.unstable_features?.["org.matrix.msc4108"];
|
||||
|
||||
const deviceAuthorizationGrantSupported = oidcClientConfig?.grant_types_supported.includes(DEVICE_CODE_SCOPE);
|
||||
const deviceAuthorizationGrantSupported =
|
||||
oidcClientConfig?.metadata?.grant_types_supported.includes(DEVICE_CODE_SCOPE);
|
||||
|
||||
return (
|
||||
!!deviceAuthorizationGrantSupported &&
|
||||
|
||||
@@ -7,9 +7,8 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React, { lazy, Suspense, useCallback, useContext, useEffect, useRef, useState } from "react";
|
||||
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
import { discoverAndValidateOIDCIssuerWellKnown, MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { defer } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import { _t } from "../../../../../languageHandler";
|
||||
import Modal from "../../../../../Modal";
|
||||
@@ -98,7 +97,7 @@ const useSignOut = (
|
||||
const url = getManageDeviceUrl(delegatedAuthAccountUrl, deviceId);
|
||||
window.open(url, "_blank");
|
||||
} else {
|
||||
const deferredSuccess = defer<boolean>();
|
||||
const deferredSuccess = Promise.withResolvers<boolean>();
|
||||
await deleteDevicesWithInteractiveAuth(matrixClient, deviceIds, async (success) => {
|
||||
deferredSuccess.resolve(success);
|
||||
});
|
||||
@@ -163,7 +162,10 @@ const SessionManagerTab: React.FC<{
|
||||
const clientVersions = useAsyncMemo(() => matrixClient.getVersions(), [matrixClient]);
|
||||
const oidcClientConfig = useAsyncMemo(async () => {
|
||||
try {
|
||||
return await matrixClient?.getAuthMetadata();
|
||||
const authIssuer = await matrixClient?.getAuthIssuer();
|
||||
if (authIssuer) {
|
||||
return discoverAndValidateOIDCIssuerWellKnown(authIssuer.issuer);
|
||||
}
|
||||
} catch (e) {
|
||||
logger.error("Failed to discover OIDC metadata", e);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { AccountDataEvents, ClientEvent, MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { defer } from "matrix-js-sdk/src/utils";
|
||||
import { isEqual } from "lodash";
|
||||
|
||||
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
||||
@@ -159,7 +158,7 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
||||
|
||||
// Attach a deferred *before* setting the account data to ensure we catch any requests
|
||||
// which race between different lines.
|
||||
const deferred = defer<void>();
|
||||
const deferred = Promise.withResolvers<void>();
|
||||
const handler = (event: MatrixEvent): void => {
|
||||
if (event.getType() !== eventType || !isEqual(event.getContent<AccountDataEvents[K]>()[field], value))
|
||||
return;
|
||||
|
||||
@@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { MatrixClient, MatrixEvent, Room, RoomEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { defer } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
||||
import { objectClone, objectKeyChanges } from "../../utils/objects";
|
||||
@@ -96,7 +95,7 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin
|
||||
|
||||
await this.client.setRoomAccountData(roomId, eventType, content);
|
||||
|
||||
const deferred = defer<void>();
|
||||
const deferred = Promise.withResolvers<void>();
|
||||
const handler = (event: MatrixEvent, room: Room): void => {
|
||||
if (room.roomId !== roomId || event.getType() !== eventType) return;
|
||||
if (field !== null && event.getContent()[field] !== value) return;
|
||||
|
||||
@@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { MatrixClient, MatrixEvent, RoomState, RoomStateEvent, StateEvents } from "matrix-js-sdk/src/matrix";
|
||||
import { defer } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
||||
import { objectClone, objectKeyChanges } from "../../utils/objects";
|
||||
@@ -92,7 +91,7 @@ export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandl
|
||||
|
||||
const { event_id: eventId } = await this.client.sendStateEvent(roomId, eventType, content);
|
||||
|
||||
const deferred = defer<void>();
|
||||
const deferred = Promise.withResolvers<void>();
|
||||
const handler = (event: MatrixEvent): void => {
|
||||
if (event.getId() !== eventId) return;
|
||||
this.client.off(RoomStateEvent.Events, handler);
|
||||
|
||||
@@ -50,8 +50,11 @@ export class OidcClientStore {
|
||||
} else {
|
||||
// We are not in OIDC Native mode, as we have no locally stored issuer. Check if the server delegates auth to OIDC.
|
||||
try {
|
||||
const authMetadata = await this.matrixClient.getAuthMetadata();
|
||||
this.setAccountManagementEndpoint(authMetadata.account_management_uri, authMetadata.issuer);
|
||||
const authIssuer = await this.matrixClient.getAuthIssuer();
|
||||
const { accountManagementEndpoint, metadata } = await discoverAndValidateOIDCIssuerWellKnown(
|
||||
authIssuer.issuer,
|
||||
);
|
||||
this.setAccountManagementEndpoint(accountManagementEndpoint, metadata.issuer);
|
||||
} catch (e) {
|
||||
console.log("Auth issuer not found", e);
|
||||
}
|
||||
@@ -150,11 +153,14 @@ export class OidcClientStore {
|
||||
|
||||
try {
|
||||
const clientId = getStoredOidcClientId();
|
||||
const authMetadata = await discoverAndValidateOIDCIssuerWellKnown(this.authenticatedIssuer);
|
||||
this.setAccountManagementEndpoint(authMetadata.account_management_uri, authMetadata.issuer);
|
||||
const { accountManagementEndpoint, metadata, signingKeys } = await discoverAndValidateOIDCIssuerWellKnown(
|
||||
this.authenticatedIssuer,
|
||||
);
|
||||
this.setAccountManagementEndpoint(accountManagementEndpoint, metadata.issuer);
|
||||
this.oidcClient = new OidcClient({
|
||||
authority: authMetadata.issuer,
|
||||
signingKeys: authMetadata.signingKeys ?? undefined,
|
||||
...metadata,
|
||||
authority: metadata.issuer,
|
||||
signingKeys,
|
||||
redirect_uri: PlatformPeg.get()!.getOidcCallbackUrl().href,
|
||||
client_id: clientId,
|
||||
});
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
AutoDiscovery,
|
||||
AutoDiscoveryError,
|
||||
ClientConfig,
|
||||
discoverAndValidateOIDCIssuerWellKnown,
|
||||
IClientWellKnown,
|
||||
MatrixClient,
|
||||
MatrixError,
|
||||
@@ -292,7 +293,8 @@ export default class AutoDiscoveryUtils {
|
||||
let delegatedAuthenticationError: Error | undefined;
|
||||
try {
|
||||
const tempClient = new MatrixClient({ baseUrl: preferredHomeserverUrl });
|
||||
delegatedAuthentication = await tempClient.getAuthMetadata();
|
||||
const { issuer } = await tempClient.getAuthIssuer();
|
||||
delegatedAuthentication = await discoverAndValidateOIDCIssuerWellKnown(issuer);
|
||||
} catch (e) {
|
||||
if (e instanceof MatrixError && e.httpStatus === 404 && e.errcode === "M_UNRECOGNIZED") {
|
||||
// 404 M_UNRECOGNIZED means the server does not support OIDC
|
||||
|
||||
@@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { MatrixError, MatrixClient, EventType } from "matrix-js-sdk/src/matrix";
|
||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
import { defer, IDeferred } from "matrix-js-sdk/src/utils";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import { AddressType, getAddressType } from "../UserAddress";
|
||||
@@ -51,7 +50,7 @@ export default class MultiInviter {
|
||||
private _fatal = false;
|
||||
private completionStates: CompletionStates = {}; // State of each address (invited or error)
|
||||
private errors: Record<string, IError> = {}; // { address: {errorText, errcode} }
|
||||
private deferred: IDeferred<CompletionStates> | null = null;
|
||||
private deferred: PromiseWithResolvers<CompletionStates> | null = null;
|
||||
private reason: string | undefined;
|
||||
|
||||
/**
|
||||
@@ -93,7 +92,7 @@ export default class MultiInviter {
|
||||
};
|
||||
}
|
||||
}
|
||||
this.deferred = defer<CompletionStates>();
|
||||
this.deferred = Promise.withResolvers<CompletionStates>();
|
||||
this.inviteMore(0);
|
||||
|
||||
return this.deferred.promise;
|
||||
|
||||
@@ -6,8 +6,6 @@ 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 { IDeferred, defer } from "matrix-js-sdk/src/utils";
|
||||
|
||||
/**
|
||||
A countdown timer, exposing a promise api.
|
||||
A timer starts in a non-started state,
|
||||
@@ -22,7 +20,7 @@ a new one through `clone()` or `cloneIfRun()`.
|
||||
export default class Timer {
|
||||
private timerHandle?: number;
|
||||
private startTs?: number;
|
||||
private deferred!: IDeferred<void>;
|
||||
private deferred!: PromiseWithResolvers<void>;
|
||||
|
||||
public constructor(private timeout: number) {
|
||||
this.setNotStarted();
|
||||
@@ -31,7 +29,7 @@ export default class Timer {
|
||||
private setNotStarted(): void {
|
||||
this.timerHandle = undefined;
|
||||
this.startTs = undefined;
|
||||
this.deferred = defer();
|
||||
this.deferred = Promise.withResolvers();
|
||||
this.deferred.promise = this.deferred.promise.finally(() => {
|
||||
this.timerHandle = undefined;
|
||||
});
|
||||
|
||||
@@ -13,7 +13,6 @@ import { renderToStaticMarkup } from "react-dom/server";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import escapeHtml from "escape-html";
|
||||
import { TooltipProvider } from "@vector-im/compound-web";
|
||||
import { defer } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import Exporter from "./Exporter";
|
||||
import { mediaFromMxc } from "../../customisations/Media";
|
||||
@@ -302,7 +301,7 @@ export default class HTMLExporter extends Exporter {
|
||||
if (hasAvatar) await this.saveAvatarIfNeeded(mxEv);
|
||||
// We have to wait for the component to be rendered before we can get the markup
|
||||
// so pass a deferred as a ref to the component.
|
||||
const deferred = defer<void>();
|
||||
const deferred = Promise.withResolvers<void>();
|
||||
const EventTile = this.getEventTile(mxEv, continuation, deferred.resolve);
|
||||
let eventTileMarkup: string;
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ export const startOidcLogin = async (
|
||||
const prompt = isRegistration ? "create" : undefined;
|
||||
|
||||
const authorizationUrl = await generateOidcAuthorizationUrl({
|
||||
metadata: delegatedAuthConfig,
|
||||
metadata: delegatedAuthConfig.metadata,
|
||||
redirectUri,
|
||||
clientId,
|
||||
homeserverUrl,
|
||||
|
||||
@@ -15,6 +15,8 @@ import { OidcClientConfig } from "matrix-js-sdk/src/matrix";
|
||||
* @returns whether user registration is supported
|
||||
*/
|
||||
export const isUserRegistrationSupported = (delegatedAuthConfig: OidcClientConfig): boolean => {
|
||||
const supportedPrompts = delegatedAuthConfig.prompt_values_supported;
|
||||
// The OidcMetadata type from oidc-client-ts does not include `prompt_values_supported`
|
||||
// even though it is part of the OIDC spec, so cheat TS here to access it
|
||||
const supportedPrompts = (delegatedAuthConfig.metadata as Record<string, unknown>)["prompt_values_supported"];
|
||||
return Array.isArray(supportedPrompts) && supportedPrompts?.includes("create");
|
||||
};
|
||||
|
||||
@@ -40,9 +40,9 @@ export const getOidcClientId = async (
|
||||
delegatedAuthConfig: OidcClientConfig,
|
||||
staticOidcClients?: IConfigOptions["oidc_static_clients"],
|
||||
): Promise<string> => {
|
||||
const staticClientId = getStaticOidcClientId(delegatedAuthConfig.issuer, staticOidcClients);
|
||||
const staticClientId = getStaticOidcClientId(delegatedAuthConfig.metadata.issuer, staticOidcClients);
|
||||
if (staticClientId) {
|
||||
logger.debug(`Using static clientId for issuer ${delegatedAuthConfig.issuer}`);
|
||||
logger.debug(`Using static clientId for issuer ${delegatedAuthConfig.metadata.issuer}`);
|
||||
return staticClientId;
|
||||
}
|
||||
return await registerOidcClient(delegatedAuthConfig, await PlatformPeg.get()!.getOidcClientMetadata());
|
||||
|
||||
@@ -49,6 +49,8 @@ function checkBrowserFeatures(): boolean {
|
||||
window.Modernizr.addTest("promiseprototypefinally", () => typeof window.Promise?.prototype?.finally === "function");
|
||||
// ES2020: http://262.ecma-international.org/#sec-promise.allsettled
|
||||
window.Modernizr.addTest("promiseallsettled", () => typeof window.Promise?.allSettled === "function");
|
||||
// ES2024: https://2ality.com/2024/05/proposal-promise-with-resolvers.html
|
||||
window.Modernizr.addTest("promisewithresolvers", () => typeof window.Promise?.withResolvers === "function");
|
||||
// ES2018: https://262.ecma-international.org/9.0/#sec-get-regexp.prototype.dotAll
|
||||
window.Modernizr.addTest(
|
||||
"regexpdotall",
|
||||
|
||||
@@ -5,7 +5,6 @@ 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 { defer, IDeferred } from "matrix-js-sdk/src/utils";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import { ElectronChannel } from "../../@types/global";
|
||||
@@ -17,7 +16,7 @@ interface IPCPayload {
|
||||
}
|
||||
|
||||
export class IPCManager {
|
||||
private pendingIpcCalls: { [ipcCallId: number]: IDeferred<any> } = {};
|
||||
private pendingIpcCalls: { [ipcCallId: number]: PromiseWithResolvers<any> } = {};
|
||||
private nextIpcCallId = 0;
|
||||
|
||||
public constructor(
|
||||
@@ -33,7 +32,7 @@ export class IPCManager {
|
||||
public async call(name: string, ...args: any[]): Promise<any> {
|
||||
// TODO this should be moved into the preload.js file.
|
||||
const ipcCallId = ++this.nextIpcCallId;
|
||||
const deferred = defer<any>();
|
||||
const deferred = Promise.withResolvers<any>();
|
||||
this.pendingIpcCalls[ipcCallId] = deferred;
|
||||
// Maybe add a timeout to these? Probably not necessary.
|
||||
window.electron!.send(this.sendChannel, { id: ipcCallId, name, args });
|
||||
|
||||
@@ -6,4 +6,41 @@ 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.
|
||||
*/
|
||||
|
||||
export { makeDelegatedAuthConfig, mockOpenIdConfiguration } from "matrix-js-sdk/src/testing";
|
||||
import { OidcClientConfig } from "matrix-js-sdk/src/matrix";
|
||||
import { ValidatedIssuerMetadata } from "matrix-js-sdk/src/oidc/validate";
|
||||
|
||||
/**
|
||||
* Makes a valid OidcClientConfig with minimum valid values
|
||||
* @param issuer used as the base for all other urls
|
||||
* @returns OidcClientConfig
|
||||
*/
|
||||
export const makeDelegatedAuthConfig = (issuer = "https://auth.org/"): OidcClientConfig => {
|
||||
const metadata = mockOpenIdConfiguration(issuer);
|
||||
|
||||
return {
|
||||
accountManagementEndpoint: issuer + "account",
|
||||
registrationEndpoint: metadata.registration_endpoint,
|
||||
authorizationEndpoint: metadata.authorization_endpoint,
|
||||
tokenEndpoint: metadata.token_endpoint,
|
||||
metadata,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Useful for mocking <issuer>/.well-known/openid-configuration
|
||||
* @param issuer used as the base for all other urls
|
||||
* @returns ValidatedIssuerMetadata
|
||||
*/
|
||||
export const mockOpenIdConfiguration = (issuer = "https://auth.org/"): ValidatedIssuerMetadata => ({
|
||||
issuer,
|
||||
revocation_endpoint: issuer + "revoke",
|
||||
token_endpoint: issuer + "token",
|
||||
authorization_endpoint: issuer + "auth",
|
||||
registration_endpoint: issuer + "registration",
|
||||
device_authorization_endpoint: issuer + "device",
|
||||
jwks_uri: issuer + "jwks",
|
||||
response_types_supported: ["code"],
|
||||
grant_types_supported: ["authorization_code", "refresh_token"],
|
||||
code_challenge_methods_supported: ["S256"],
|
||||
account_management_uri: issuer + "account",
|
||||
});
|
||||
|
||||
@@ -9,7 +9,6 @@ Please see LICENSE files in the repository root for full details.
|
||||
import { mocked } from "jest-mock";
|
||||
import { ISendEventResponse, MatrixClient, RelationType, UploadResponse } from "matrix-js-sdk/src/matrix";
|
||||
import { ImageInfo } from "matrix-js-sdk/src/types";
|
||||
import { defer } from "matrix-js-sdk/src/utils";
|
||||
import encrypt, { IEncryptedFile } from "matrix-encrypt-attachment";
|
||||
|
||||
import ContentMessages, { UploadCanceledError, uploadFile } from "../../src/ContentMessages";
|
||||
@@ -333,7 +332,7 @@ describe("ContentMessages", () => {
|
||||
|
||||
describe("cancelUpload", () => {
|
||||
it("should cancel in-flight upload", async () => {
|
||||
const deferred = defer<UploadResponse>();
|
||||
const deferred = Promise.withResolvers<UploadResponse>();
|
||||
mocked(client.uploadContent).mockReturnValue(deferred.promise);
|
||||
const file1 = new File([], "file1");
|
||||
const prom = contentMessages.sendContentToRoom(file1, roomId, undefined, client, undefined);
|
||||
|
||||
@@ -749,8 +749,11 @@ describe("Lifecycle", () => {
|
||||
"eyJhbGciOiJSUzI1NiIsImtpZCI6Imh4ZEhXb0Y5bW4ifQ.eyJzdWIiOiIwMUhQUDJGU0JZREU5UDlFTU04REQ3V1pIUiIsImlzcyI6Imh0dHBzOi8vYXV0aC1vaWRjLmxhYi5lbGVtZW50LmRldi8iLCJpYXQiOjE3MTUwNzE5ODUsImF1dGhfdGltZSI6MTcwNzk5MDMxMiwiY19oYXNoIjoidGt5R1RhUjU5aTk3YXoyTU4yMGdidyIsImV4cCI6MTcxNTA3NTU4NSwibm9uY2UiOiJxaXhwM0hFMmVaIiwiYXVkIjoiMDFIWDk0Mlg3QTg3REgxRUs2UDRaNjI4WEciLCJhdF9oYXNoIjoiNFlFUjdPRlVKTmRTeEVHV2hJUDlnZyJ9.HxODneXvSTfWB5Vc4cf7b8GiN2gdwUuTiyVqZuupWske2HkZiJZUt5Lsxg9BW3gz28POkE0Ln17snlkmy02B_AD3DQxKOOxQCzIIARHdfFvZxgGWsMdFcVQZDW7rtXcqgj-SpVaUQ_8acsgxSrz_DF2o0O4tto0PT6wVUiw8KlBmgWTscWPeAWe-39T-8EiQ8Wi16h6oSPcz2NzOQ7eOM_S9fDkOorgcBkRGLl1nrahrPSdWJSGAeruk5mX4YxN714YThFDyEA2t9YmKpjaiSQ2tT-Xkd7tgsZqeirNs2ni9mIiFX3bRX6t2AhUNzA7MaX9ZyizKGa6go3BESO_oDg";
|
||||
|
||||
beforeAll(() => {
|
||||
fetchMock.get(`${delegatedAuthConfig.issuer}.well-known/openid-configuration`, delegatedAuthConfig);
|
||||
fetchMock.get(`${delegatedAuthConfig.issuer}jwks`, {
|
||||
fetchMock.get(
|
||||
`${delegatedAuthConfig.metadata.issuer}.well-known/openid-configuration`,
|
||||
delegatedAuthConfig.metadata,
|
||||
);
|
||||
fetchMock.get(`${delegatedAuthConfig.metadata.issuer}jwks`, {
|
||||
status: 200,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -769,7 +772,9 @@ describe("Lifecycle", () => {
|
||||
await setLoggedIn(credentials);
|
||||
|
||||
// didn't try to initialise token refresher
|
||||
expect(fetchMock).not.toHaveFetched(`${delegatedAuthConfig.issuer}.well-known/openid-configuration`);
|
||||
expect(fetchMock).not.toHaveFetched(
|
||||
`${delegatedAuthConfig.metadata.issuer}.well-known/openid-configuration`,
|
||||
);
|
||||
});
|
||||
|
||||
it("should not try to create a token refresher without a deviceId", async () => {
|
||||
@@ -780,7 +785,9 @@ describe("Lifecycle", () => {
|
||||
});
|
||||
|
||||
// didn't try to initialise token refresher
|
||||
expect(fetchMock).not.toHaveFetched(`${delegatedAuthConfig.issuer}.well-known/openid-configuration`);
|
||||
expect(fetchMock).not.toHaveFetched(
|
||||
`${delegatedAuthConfig.metadata.issuer}.well-known/openid-configuration`,
|
||||
);
|
||||
});
|
||||
|
||||
it("should not try to create a token refresher without an issuer in session storage", async () => {
|
||||
@@ -796,7 +803,9 @@ describe("Lifecycle", () => {
|
||||
});
|
||||
|
||||
// didn't try to initialise token refresher
|
||||
expect(fetchMock).not.toHaveFetched(`${delegatedAuthConfig.issuer}.well-known/openid-configuration`);
|
||||
expect(fetchMock).not.toHaveFetched(
|
||||
`${delegatedAuthConfig.metadata.issuer}.well-known/openid-configuration`,
|
||||
);
|
||||
});
|
||||
|
||||
it("should create a client with a tokenRefreshFunction", async () => {
|
||||
|
||||
@@ -21,7 +21,7 @@ import { completeAuthorizationCodeGrant } from "matrix-js-sdk/src/oidc/authorize
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { OidcError } from "matrix-js-sdk/src/oidc/error";
|
||||
import { BearerTokenResponse } from "matrix-js-sdk/src/oidc/validate";
|
||||
import { defer, IDeferred, sleep } from "matrix-js-sdk/src/utils";
|
||||
import { sleep } from "matrix-js-sdk/src/utils";
|
||||
import { CryptoEvent, UserVerificationStatus } from "matrix-js-sdk/src/crypto-api";
|
||||
|
||||
import MatrixChat from "../../../../src/components/structures/MatrixChat";
|
||||
@@ -79,7 +79,7 @@ describe("<MatrixChat />", () => {
|
||||
const deviceId = "qwertyui";
|
||||
const accessToken = "abc123";
|
||||
const refreshToken = "def456";
|
||||
let bootstrapDeferred: IDeferred<void>;
|
||||
let bootstrapDeferred: PromiseWithResolvers<void>;
|
||||
// reused in createClient mock below
|
||||
const getMockClientMethods = () => ({
|
||||
...mockClientMethodsUser(userId),
|
||||
@@ -245,7 +245,7 @@ describe("<MatrixChat />", () => {
|
||||
{} as ValidatedServerConfig,
|
||||
);
|
||||
|
||||
bootstrapDeferred = defer();
|
||||
bootstrapDeferred = Promise.withResolvers();
|
||||
|
||||
await clearAllModals();
|
||||
});
|
||||
@@ -1439,7 +1439,7 @@ describe("<MatrixChat />", () => {
|
||||
jest.spyOn(MatrixJs, "createClient").mockReturnValue(client);
|
||||
|
||||
// intercept initCrypto and have it block until we complete the deferred
|
||||
const initCryptoCompleteDefer = defer();
|
||||
const initCryptoCompleteDefer = Promise.withResolvers<void>();
|
||||
const initCryptoCalled = new Promise<void>((resolve) => {
|
||||
client.initRustCrypto.mockImplementation(() => {
|
||||
resolve();
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
SearchResult,
|
||||
ISearchResults,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { defer } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import { RoomSearchView } from "../../../../src/components/structures/RoomSearchView";
|
||||
import ResizeNotifier from "../../../../src/utils/ResizeNotifier";
|
||||
@@ -53,7 +52,7 @@ describe("<RoomSearchView/>", () => {
|
||||
});
|
||||
|
||||
it("should show a spinner before the promise resolves", async () => {
|
||||
const deferred = defer<ISearchResults>();
|
||||
const deferred = Promise.withResolvers<ISearchResults>();
|
||||
|
||||
render(
|
||||
<RoomSearchView
|
||||
@@ -267,7 +266,7 @@ describe("<RoomSearchView/>", () => {
|
||||
});
|
||||
|
||||
it("should handle resolutions after unmounting sanely", async () => {
|
||||
const deferred = defer<ISearchResults>();
|
||||
const deferred = Promise.withResolvers<ISearchResults>();
|
||||
|
||||
const { unmount } = render(
|
||||
<MatrixClientContext.Provider value={client}>
|
||||
@@ -291,7 +290,7 @@ describe("<RoomSearchView/>", () => {
|
||||
});
|
||||
|
||||
it("should handle rejections after unmounting sanely", async () => {
|
||||
const deferred = defer<ISearchResults>();
|
||||
const deferred = Promise.withResolvers<ISearchResults>();
|
||||
|
||||
const { unmount } = render(
|
||||
<MatrixClientContext.Provider value={client}>
|
||||
@@ -315,7 +314,7 @@ describe("<RoomSearchView/>", () => {
|
||||
});
|
||||
|
||||
it("should show modal if error is encountered", async () => {
|
||||
const deferred = defer<ISearchResults>();
|
||||
const deferred = Promise.withResolvers<ISearchResults>();
|
||||
|
||||
render(
|
||||
<MatrixClientContext.Provider value={client}>
|
||||
|
||||
@@ -35,7 +35,6 @@ import {
|
||||
cleanup,
|
||||
} from "jest-matrix-react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { defer } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import {
|
||||
stubClient,
|
||||
@@ -303,7 +302,7 @@ describe("RoomView", () => {
|
||||
it("should not display the timeline when the room encryption is loading", async () => {
|
||||
jest.spyOn(room, "getMyMembership").mockReturnValue(KnownMembership.Join);
|
||||
jest.spyOn(cli, "getCrypto").mockReturnValue(crypto);
|
||||
const deferred = defer<boolean>();
|
||||
const deferred = Promise.withResolvers<boolean>();
|
||||
jest.spyOn(cli.getCrypto()!, "isEncryptionEnabledInRoom").mockImplementation(() => deferred.promise);
|
||||
|
||||
const { asFragment, container } = await mountRoomView();
|
||||
|
||||
@@ -384,7 +384,7 @@ describe("Login", function () {
|
||||
await waitForElementToBeRemoved(() => screen.queryAllByLabelText("Loading…"));
|
||||
|
||||
// didn't try to register
|
||||
expect(fetchMock).not.toHaveBeenCalledWith(delegatedAuth.registration_endpoint);
|
||||
expect(fetchMock).not.toHaveBeenCalledWith(delegatedAuth.registrationEndpoint);
|
||||
// continued with normal setup
|
||||
expect(mockClient.loginFlows).toHaveBeenCalled();
|
||||
// normal password login rendered
|
||||
@@ -394,25 +394,25 @@ describe("Login", function () {
|
||||
it("should attempt to register oidc client", async () => {
|
||||
// dont mock, spy so we can check config values were correctly passed
|
||||
jest.spyOn(registerClientUtils, "getOidcClientId");
|
||||
fetchMock.post(delegatedAuth.registration_endpoint!, { status: 500 });
|
||||
fetchMock.post(delegatedAuth.registrationEndpoint!, { status: 500 });
|
||||
getComponent(hsUrl, isUrl, delegatedAuth);
|
||||
|
||||
await waitForElementToBeRemoved(() => screen.queryAllByLabelText("Loading…"));
|
||||
|
||||
// tried to register
|
||||
expect(fetchMock).toHaveBeenCalledWith(delegatedAuth.registration_endpoint, expect.any(Object));
|
||||
expect(fetchMock).toHaveBeenCalledWith(delegatedAuth.registrationEndpoint, expect.any(Object));
|
||||
// called with values from config
|
||||
expect(registerClientUtils.getOidcClientId).toHaveBeenCalledWith(delegatedAuth, oidcStaticClientsConfig);
|
||||
});
|
||||
|
||||
it("should fallback to normal login when client registration fails", async () => {
|
||||
fetchMock.post(delegatedAuth.registration_endpoint!, { status: 500 });
|
||||
fetchMock.post(delegatedAuth.registrationEndpoint!, { status: 500 });
|
||||
getComponent(hsUrl, isUrl, delegatedAuth);
|
||||
|
||||
await waitForElementToBeRemoved(() => screen.queryAllByLabelText("Loading…"));
|
||||
|
||||
// tried to register
|
||||
expect(fetchMock).toHaveBeenCalledWith(delegatedAuth.registration_endpoint, expect.any(Object));
|
||||
expect(fetchMock).toHaveBeenCalledWith(delegatedAuth.registrationEndpoint, expect.any(Object));
|
||||
expect(logger.error).toHaveBeenCalledWith(new Error(OidcError.DynamicRegistrationFailed));
|
||||
|
||||
// continued with normal setup
|
||||
@@ -423,7 +423,7 @@ describe("Login", function () {
|
||||
|
||||
// short term during active development, UI will be added in next PRs
|
||||
it("should show continue button when oidc native flow is correctly configured", async () => {
|
||||
fetchMock.post(delegatedAuth.registration_endpoint!, { client_id: "abc123" });
|
||||
fetchMock.post(delegatedAuth.registrationEndpoint!, { client_id: "abc123" });
|
||||
getComponent(hsUrl, isUrl, delegatedAuth);
|
||||
|
||||
await waitForElementToBeRemoved(() => screen.queryAllByLabelText("Loading…"));
|
||||
@@ -455,7 +455,7 @@ describe("Login", function () {
|
||||
await waitForElementToBeRemoved(() => screen.queryAllByLabelText("Loading…"));
|
||||
|
||||
// didn't try to register
|
||||
expect(fetchMock).not.toHaveBeenCalledWith(delegatedAuth.registration_endpoint);
|
||||
expect(fetchMock).not.toHaveBeenCalledWith(delegatedAuth.registrationEndpoint);
|
||||
// continued with normal setup
|
||||
expect(mockClient.loginFlows).toHaveBeenCalled();
|
||||
// oidc-aware 'continue' button displayed
|
||||
|
||||
@@ -158,26 +158,24 @@ describe("Registration", function () {
|
||||
describe("when delegated authentication is configured and enabled", () => {
|
||||
const authConfig = makeDelegatedAuthConfig();
|
||||
const clientId = "test-client-id";
|
||||
authConfig.prompt_values_supported = ["create"];
|
||||
// @ts-ignore
|
||||
authConfig.metadata["prompt_values_supported"] = ["create"];
|
||||
|
||||
beforeEach(() => {
|
||||
// mock a statically registered client to avoid dynamic registration
|
||||
SdkConfig.put({
|
||||
oidc_static_clients: {
|
||||
[authConfig.issuer]: {
|
||||
[authConfig.metadata.issuer]: {
|
||||
client_id: clientId,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
fetchMock.get(`${defaultHsUrl}/_matrix/client/unstable/org.matrix.msc2965/auth_issuer`, {
|
||||
issuer: authConfig.issuer,
|
||||
issuer: authConfig.metadata.issuer,
|
||||
});
|
||||
fetchMock.get("https://auth.org/.well-known/openid-configuration", {
|
||||
...authConfig,
|
||||
signingKeys: undefined,
|
||||
});
|
||||
fetchMock.get(authConfig.jwks_uri!, { keys: [] });
|
||||
fetchMock.get("https://auth.org/.well-known/openid-configuration", authConfig.metadata);
|
||||
fetchMock.get(authConfig.metadata.jwks_uri!, { keys: [] });
|
||||
});
|
||||
|
||||
it("should display oidc-native continue button", async () => {
|
||||
|
||||
@@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import React from "react";
|
||||
import { fireEvent, render, screen } from "jest-matrix-react";
|
||||
import { defer } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import PowerSelector from "../../../../../src/components/views/elements/PowerSelector";
|
||||
|
||||
@@ -70,7 +69,7 @@ describe("<PowerSelector />", () => {
|
||||
});
|
||||
|
||||
it("should reset when onChange promise rejects", async () => {
|
||||
const deferred = defer<void>();
|
||||
const deferred = Promise.withResolvers<void>();
|
||||
render(
|
||||
<PowerSelector
|
||||
value={25}
|
||||
|
||||
@@ -12,7 +12,6 @@ import userEvent from "@testing-library/user-event";
|
||||
import { Mocked, mocked } from "jest-mock";
|
||||
import { Room, User, MatrixClient, RoomMember, MatrixEvent, EventType, Device } from "matrix-js-sdk/src/matrix";
|
||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
import { defer } from "matrix-js-sdk/src/utils";
|
||||
import { EventEmitter } from "events";
|
||||
import {
|
||||
UserVerificationStatus,
|
||||
@@ -795,7 +794,7 @@ describe("<DeviceItem />", () => {
|
||||
});
|
||||
|
||||
it("when userId is the same as userId from client, uses isCrossSigningVerified to determine if button is shown", async () => {
|
||||
const deferred = defer<DeviceVerificationStatus>();
|
||||
const deferred = Promise.withResolvers<DeviceVerificationStatus>();
|
||||
mockCrypto.getDeviceVerificationStatus.mockReturnValue(deferred.promise);
|
||||
|
||||
mockClient.getSafeUserId.mockReturnValueOnce(defaultUserId);
|
||||
@@ -1058,7 +1057,7 @@ describe("<UserOptionsSection />", () => {
|
||||
])(
|
||||
"clicking »message« %s should start a DM",
|
||||
async (test: string, member: RoomMember | User, expectedAvatarUrl: string | undefined) => {
|
||||
const deferred = defer<string>();
|
||||
const deferred = Promise.withResolvers<string>();
|
||||
mocked(startDmOnFirstMessage).mockReturnValue(deferred.promise);
|
||||
|
||||
renderComponent({ member });
|
||||
|
||||
@@ -228,7 +228,7 @@ exports[`MemberTileView ThreePidInviteTileView renders ThreePidInvite correctly
|
||||
<div
|
||||
class="mx_MemberTileView_userLabel"
|
||||
>
|
||||
Invited
|
||||
(Invited)
|
||||
</div>
|
||||
<div
|
||||
class="mx_Flex mx_InvitedIconView"
|
||||
|
||||
@@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import React from "react";
|
||||
import { fireEvent, render, screen, within } from "jest-matrix-react";
|
||||
import { defer, IDeferred } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import EventIndexPanel from "../../../../../src/components/views/settings/EventIndexPanel";
|
||||
import EventIndexPeg from "../../../../../src/indexing/EventIndexPeg";
|
||||
@@ -140,9 +139,9 @@ describe("<EventIndexPanel />", () => {
|
||||
});
|
||||
it("enables event indexing on enable button click", async () => {
|
||||
jest.spyOn(EventIndexPeg, "supportIsInstalled").mockReturnValue(true);
|
||||
let deferredInitEventIndex: IDeferred<boolean> | undefined;
|
||||
let deferredInitEventIndex: PromiseWithResolvers<boolean> | undefined;
|
||||
jest.spyOn(EventIndexPeg, "initEventIndex").mockImplementation(() => {
|
||||
deferredInitEventIndex = defer<boolean>();
|
||||
deferredInitEventIndex = Promise.withResolvers<boolean>();
|
||||
return deferredInitEventIndex.promise;
|
||||
});
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ import {
|
||||
Visibility,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
import { defer, IDeferred } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import {
|
||||
clearAllModals,
|
||||
@@ -160,7 +159,7 @@ describe("<JoinRuleSettings />", () => {
|
||||
});
|
||||
|
||||
it(`upgrades room when changing join rule to ${joinRule}`, async () => {
|
||||
const deferredInvites: IDeferred<any>[] = [];
|
||||
const deferredInvites: PromiseWithResolvers<any>[] = [];
|
||||
// room that doesn't support the join rule
|
||||
const room = new Room(roomId, client, userId);
|
||||
const parentSpace = new Room("!parentSpace:server.org", client, userId);
|
||||
@@ -183,7 +182,7 @@ describe("<JoinRuleSettings />", () => {
|
||||
// resolve invites by hand
|
||||
// flushPromises is too blunt to test reliably
|
||||
client.invite.mockImplementation(() => {
|
||||
const p = defer<{}>();
|
||||
const p = Promise.withResolvers<{}>();
|
||||
deferredInvites.push(p);
|
||||
return p.promise;
|
||||
});
|
||||
|
||||
@@ -11,7 +11,6 @@ import { fireEvent, getByRole, render, RenderResult, screen, waitFor } from "jes
|
||||
import { MatrixClient, EventType, MatrixEvent, Room, RoomMember, ISendEventResponse } from "matrix-js-sdk/src/matrix";
|
||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
import { mocked } from "jest-mock";
|
||||
import { defer } from "matrix-js-sdk/src/utils";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
|
||||
import RolesRoomSettingsTab from "../../../../../../../src/components/views/settings/tabs/room/RolesRoomSettingsTab";
|
||||
@@ -202,7 +201,7 @@ describe("RolesRoomSettingsTab", () => {
|
||||
});
|
||||
|
||||
it("should roll back power level change on error", async () => {
|
||||
const deferred = defer<ISendEventResponse>();
|
||||
const deferred = Promise.withResolvers<ISendEventResponse>();
|
||||
mocked(cli.sendStateEvent).mockReturnValue(deferred.promise);
|
||||
mocked(cli.getRoom).mockReturnValue(room);
|
||||
// @ts-ignore - mocked doesn't support overloads properly
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
} from "jest-matrix-react";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { CryptoApi, DeviceVerificationStatus, VerificationRequest } from "matrix-js-sdk/src/crypto-api";
|
||||
import { defer, sleep } from "matrix-js-sdk/src/utils";
|
||||
import { sleep } from "matrix-js-sdk/src/utils";
|
||||
import {
|
||||
ClientEvent,
|
||||
Device,
|
||||
@@ -57,7 +57,7 @@ import SettingsStore from "../../../../../../../src/settings/SettingsStore";
|
||||
import { getClientInformationEventType } from "../../../../../../../src/utils/device/clientInformation";
|
||||
import { SDKContext, SdkContextClass } from "../../../../../../../src/contexts/SDKContext";
|
||||
import { OidcClientStore } from "../../../../../../../src/stores/oidc/OidcClientStore";
|
||||
import { makeDelegatedAuthConfig } from "../../../../../../test-utils/oidc";
|
||||
import { mockOpenIdConfiguration } from "../../../../../../test-utils/oidc";
|
||||
import MatrixClientContext from "../../../../../../../src/contexts/MatrixClientContext";
|
||||
|
||||
mockPlatformPeg();
|
||||
@@ -215,7 +215,7 @@ describe("<SessionManagerTab />", () => {
|
||||
getPushers: jest.fn(),
|
||||
setPusher: jest.fn(),
|
||||
setLocalNotificationSettings: jest.fn(),
|
||||
getAuthMetadata: jest.fn().mockRejectedValue(new MatrixError({ errcode: "M_UNRECOGNIZED" }, 404)),
|
||||
getAuthIssuer: jest.fn().mockReturnValue(new Promise(() => {})),
|
||||
});
|
||||
jest.clearAllMocks();
|
||||
jest.spyOn(logger, "error").mockRestore();
|
||||
@@ -894,7 +894,7 @@ describe("<SessionManagerTab />", () => {
|
||||
});
|
||||
|
||||
it("deletes a device when interactive auth is not required", async () => {
|
||||
const deferredDeleteMultipleDevices = defer<{}>();
|
||||
const deferredDeleteMultipleDevices = Promise.withResolvers<{}>();
|
||||
mockClient.deleteMultipleDevices.mockReturnValue(deferredDeleteMultipleDevices.promise);
|
||||
mockClient.getDevices.mockResolvedValue({
|
||||
devices: [alicesDevice, alicesMobileDevice, alicesOlderMobileDevice],
|
||||
@@ -1103,7 +1103,7 @@ describe("<SessionManagerTab />", () => {
|
||||
// get a handle for resolving the delete call
|
||||
// because promise flushing after the confirm modal is resolving this too
|
||||
// and we want to test the loading state here
|
||||
const resolveDeleteRequest = defer<IAuthData>();
|
||||
const resolveDeleteRequest = Promise.withResolvers<IAuthData>();
|
||||
mockClient.deleteMultipleDevices.mockImplementation(() => {
|
||||
return resolveDeleteRequest.promise;
|
||||
});
|
||||
@@ -1615,6 +1615,7 @@ describe("<SessionManagerTab />", () => {
|
||||
describe("MSC4108 QR code login", () => {
|
||||
const settingsValueSpy = jest.spyOn(SettingsStore, "getValue");
|
||||
const issuer = "https://issuer.org";
|
||||
const openIdConfiguration = mockOpenIdConfiguration(issuer);
|
||||
|
||||
beforeEach(() => {
|
||||
settingsValueSpy.mockClear().mockReturnValue(true);
|
||||
@@ -1630,16 +1631,16 @@ describe("<SessionManagerTab />", () => {
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
const delegatedAuthConfig = makeDelegatedAuthConfig(issuer);
|
||||
mockClient.getAuthMetadata.mockResolvedValue({
|
||||
...delegatedAuthConfig,
|
||||
mockClient.getAuthIssuer.mockResolvedValue({ issuer });
|
||||
mockCrypto.exportSecretsBundle = jest.fn();
|
||||
fetchMock.mock(`${issuer}/.well-known/openid-configuration`, {
|
||||
...openIdConfiguration,
|
||||
grant_types_supported: [
|
||||
...delegatedAuthConfig.grant_types_supported,
|
||||
...openIdConfiguration.grant_types_supported,
|
||||
"urn:ietf:params:oauth:grant-type:device_code",
|
||||
],
|
||||
});
|
||||
mockCrypto.exportSecretsBundle = jest.fn();
|
||||
fetchMock.mock(delegatedAuthConfig.jwks_uri!, {
|
||||
fetchMock.mock(openIdConfiguration.jwks_uri!, {
|
||||
status: 200,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
||||
@@ -6,8 +6,6 @@ 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 { defer } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import defaultDispatcher from "../../../src/dispatcher/dispatcher";
|
||||
import { Action } from "../../../src/dispatcher/actions";
|
||||
import { AsyncActionPayload } from "../../../src/dispatcher/payloads";
|
||||
@@ -20,8 +18,8 @@ describe("MatrixDispatcher", () => {
|
||||
});
|
||||
|
||||
it("should execute callbacks in registered order", async () => {
|
||||
const deferred1 = defer<number>();
|
||||
const deferred2 = defer<number>();
|
||||
const deferred1 = Promise.withResolvers<number>();
|
||||
const deferred2 = Promise.withResolvers<number>();
|
||||
|
||||
const fn1 = jest.fn(() => deferred1.resolve(1));
|
||||
const fn2 = jest.fn(() => deferred2.resolve(2));
|
||||
@@ -36,8 +34,8 @@ describe("MatrixDispatcher", () => {
|
||||
});
|
||||
|
||||
it("should skip the queue for the given callback", async () => {
|
||||
const deferred1 = defer<number>();
|
||||
const deferred2 = defer<number>();
|
||||
const deferred1 = Promise.withResolvers<number>();
|
||||
const deferred2 = Promise.withResolvers<number>();
|
||||
|
||||
const fn1 = jest.fn(() => deferred1.resolve(1));
|
||||
const fn2 = jest.fn(() => deferred2.resolve(2));
|
||||
|
||||
@@ -6,7 +6,6 @@ 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 { defer } from "matrix-js-sdk/src/utils";
|
||||
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import ServerSupportUnstableFeatureController from "../../../../src/settings/controllers/ServerSupportUnstableFeatureController";
|
||||
@@ -34,7 +33,7 @@ describe("ServerSupportUnstableFeatureController", () => {
|
||||
controller,
|
||||
};
|
||||
|
||||
const deferred = defer<any>();
|
||||
const deferred = Promise.withResolvers<any>();
|
||||
watchers.watchSetting(setting, null, deferred.resolve);
|
||||
MatrixClientBackedController.matrixClient = cli;
|
||||
await deferred.promise;
|
||||
|
||||
@@ -20,7 +20,6 @@ import {
|
||||
RoomState,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
import { defer } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import SpaceStore from "../../../src/stores/spaces/SpaceStore";
|
||||
import {
|
||||
@@ -1008,7 +1007,7 @@ describe("SpaceStore", () => {
|
||||
|
||||
await run();
|
||||
|
||||
const deferred = defer<boolean>();
|
||||
const deferred = Promise.withResolvers<boolean>();
|
||||
space.loadMembersIfNeeded.mockImplementation(() => {
|
||||
const event = mkEvent({
|
||||
event: true,
|
||||
|
||||
@@ -15,7 +15,7 @@ import { OidcError } from "matrix-js-sdk/src/oidc/error";
|
||||
|
||||
import { OidcClientStore } from "../../../../src/stores/oidc/OidcClientStore";
|
||||
import { flushPromises, getMockClientWithEventEmitter, mockPlatformPeg } from "../../../test-utils";
|
||||
import { makeDelegatedAuthConfig } from "../../../test-utils/oidc";
|
||||
import { mockOpenIdConfiguration } from "../../../test-utils/oidc";
|
||||
|
||||
jest.mock("matrix-js-sdk/src/matrix", () => ({
|
||||
...jest.requireActual("matrix-js-sdk/src/matrix"),
|
||||
@@ -24,30 +24,28 @@ jest.mock("matrix-js-sdk/src/matrix", () => ({
|
||||
|
||||
describe("OidcClientStore", () => {
|
||||
const clientId = "test-client-id";
|
||||
const authConfig = makeDelegatedAuthConfig();
|
||||
const account = authConfig.issuer + "account";
|
||||
const metadata = mockOpenIdConfiguration();
|
||||
const account = metadata.issuer + "account";
|
||||
|
||||
const mockClient = getMockClientWithEventEmitter({
|
||||
getAuthMetadata: jest.fn(),
|
||||
getAuthIssuer: jest.fn(),
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
localStorage.setItem("mx_oidc_client_id", clientId);
|
||||
localStorage.setItem("mx_oidc_token_issuer", authConfig.issuer);
|
||||
localStorage.setItem("mx_oidc_token_issuer", metadata.issuer);
|
||||
|
||||
mocked(discoverAndValidateOIDCIssuerWellKnown)
|
||||
.mockClear()
|
||||
.mockResolvedValue({
|
||||
...authConfig,
|
||||
account_management_uri: account,
|
||||
authorization_endpoint: "authorization-endpoint",
|
||||
token_endpoint: "token-endpoint",
|
||||
});
|
||||
mocked(discoverAndValidateOIDCIssuerWellKnown).mockClear().mockResolvedValue({
|
||||
metadata,
|
||||
accountManagementEndpoint: account,
|
||||
authorizationEndpoint: "authorization-endpoint",
|
||||
tokenEndpoint: "token-endpoint",
|
||||
});
|
||||
jest.spyOn(logger, "error").mockClear();
|
||||
|
||||
fetchMock.get(`${authConfig.issuer}.well-known/openid-configuration`, authConfig);
|
||||
fetchMock.get(`${authConfig.issuer}jwks`, { keys: [] });
|
||||
fetchMock.get(`${metadata.issuer}.well-known/openid-configuration`, metadata);
|
||||
fetchMock.get(`${metadata.issuer}jwks`, { keys: [] });
|
||||
mockPlatformPeg();
|
||||
});
|
||||
|
||||
@@ -118,7 +116,7 @@ describe("OidcClientStore", () => {
|
||||
const client = await store.getOidcClient();
|
||||
|
||||
expect(client?.settings.client_id).toEqual(clientId);
|
||||
expect(client?.settings.authority).toEqual(authConfig.issuer);
|
||||
expect(client?.settings.authority).toEqual(metadata.issuer);
|
||||
});
|
||||
|
||||
it("should set account management endpoint when configured", async () => {
|
||||
@@ -131,19 +129,17 @@ describe("OidcClientStore", () => {
|
||||
});
|
||||
|
||||
it("should set account management endpoint to issuer when not configured", async () => {
|
||||
mocked(discoverAndValidateOIDCIssuerWellKnown)
|
||||
.mockClear()
|
||||
.mockResolvedValue({
|
||||
...authConfig,
|
||||
account_management_uri: undefined,
|
||||
authorization_endpoint: "authorization-endpoint",
|
||||
token_endpoint: "token-endpoint",
|
||||
});
|
||||
mocked(discoverAndValidateOIDCIssuerWellKnown).mockClear().mockResolvedValue({
|
||||
metadata,
|
||||
accountManagementEndpoint: undefined,
|
||||
authorizationEndpoint: "authorization-endpoint",
|
||||
tokenEndpoint: "token-endpoint",
|
||||
});
|
||||
const store = new OidcClientStore(mockClient);
|
||||
|
||||
await store.readyPromise;
|
||||
|
||||
expect(store.accountManagementEndpoint).toEqual(authConfig.issuer);
|
||||
expect(store.accountManagementEndpoint).toEqual(metadata.issuer);
|
||||
});
|
||||
|
||||
it("should reuse initialised oidc client", async () => {
|
||||
@@ -179,7 +175,7 @@ describe("OidcClientStore", () => {
|
||||
|
||||
fetchMock.resetHistory();
|
||||
fetchMock.post(
|
||||
authConfig.revocation_endpoint,
|
||||
metadata.revocation_endpoint,
|
||||
{
|
||||
status: 200,
|
||||
},
|
||||
@@ -201,7 +197,7 @@ describe("OidcClientStore", () => {
|
||||
|
||||
await store.revokeTokens(accessToken, refreshToken);
|
||||
|
||||
expect(fetchMock).toHaveFetchedTimes(2, authConfig.revocation_endpoint);
|
||||
expect(fetchMock).toHaveFetchedTimes(2, metadata.revocation_endpoint);
|
||||
expect(OidcClient.prototype.revokeToken).toHaveBeenCalledWith(accessToken, "access_token");
|
||||
expect(OidcClient.prototype.revokeToken).toHaveBeenCalledWith(refreshToken, "refresh_token");
|
||||
});
|
||||
@@ -210,14 +206,14 @@ describe("OidcClientStore", () => {
|
||||
// fail once, then succeed
|
||||
fetchMock
|
||||
.postOnce(
|
||||
authConfig.revocation_endpoint,
|
||||
metadata.revocation_endpoint,
|
||||
{
|
||||
status: 404,
|
||||
},
|
||||
{ overwriteRoutes: true, sendAsJson: true },
|
||||
)
|
||||
.post(
|
||||
authConfig.revocation_endpoint,
|
||||
metadata.revocation_endpoint,
|
||||
{
|
||||
status: 200,
|
||||
},
|
||||
@@ -230,7 +226,7 @@ describe("OidcClientStore", () => {
|
||||
"Failed to revoke tokens",
|
||||
);
|
||||
|
||||
expect(fetchMock).toHaveFetchedTimes(2, authConfig.revocation_endpoint);
|
||||
expect(fetchMock).toHaveFetchedTimes(2, metadata.revocation_endpoint);
|
||||
expect(OidcClient.prototype.revokeToken).toHaveBeenCalledWith(accessToken, "access_token");
|
||||
});
|
||||
});
|
||||
@@ -241,10 +237,7 @@ describe("OidcClientStore", () => {
|
||||
});
|
||||
|
||||
it("should resolve account management endpoint", async () => {
|
||||
mockClient.getAuthMetadata.mockResolvedValue({
|
||||
...authConfig,
|
||||
account_management_uri: account,
|
||||
});
|
||||
mockClient.getAuthIssuer.mockResolvedValue({ issuer: metadata.issuer });
|
||||
const store = new OidcClientStore(mockClient);
|
||||
await store.readyPromise;
|
||||
expect(store.accountManagementEndpoint).toBe(account);
|
||||
|
||||
@@ -355,19 +355,21 @@ describe("AutoDiscoveryUtils", () => {
|
||||
hsNameIsDifferent: true,
|
||||
hsName: serverName,
|
||||
delegatedAuthentication: expect.objectContaining({
|
||||
issuer,
|
||||
account_management_actions_supported: [
|
||||
accountManagementActionsSupported: [
|
||||
"org.matrix.profile",
|
||||
"org.matrix.sessions_list",
|
||||
"org.matrix.session_view",
|
||||
"org.matrix.session_end",
|
||||
"org.matrix.cross_signing_reset",
|
||||
],
|
||||
account_management_uri: "https://auth.matrix.org/account/",
|
||||
authorization_endpoint: "https://auth.matrix.org/auth",
|
||||
registration_endpoint: "https://auth.matrix.org/registration",
|
||||
accountManagementEndpoint: "https://auth.matrix.org/account/",
|
||||
authorizationEndpoint: "https://auth.matrix.org/auth",
|
||||
metadata: expect.objectContaining({
|
||||
issuer,
|
||||
}),
|
||||
registrationEndpoint: "https://auth.matrix.org/registration",
|
||||
signingKeys: [],
|
||||
token_endpoint: "https://auth.matrix.org/token",
|
||||
tokenEndpoint: "https://auth.matrix.org/token",
|
||||
}),
|
||||
warning: null,
|
||||
});
|
||||
|
||||
@@ -38,7 +38,7 @@ describe("TokenRefresher", () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
fetchMock.get(`${issuer}.well-known/openid-configuration`, authConfig);
|
||||
fetchMock.get(`${issuer}.well-known/openid-configuration`, authConfig.metadata);
|
||||
fetchMock.get(`${issuer}jwks`, {
|
||||
status: 200,
|
||||
headers: {
|
||||
|
||||
@@ -61,7 +61,10 @@ describe("OIDC authorization", () => {
|
||||
});
|
||||
|
||||
beforeAll(() => {
|
||||
fetchMock.get(`${delegatedAuthConfig.issuer}.well-known/openid-configuration`, delegatedAuthConfig);
|
||||
fetchMock.get(
|
||||
`${delegatedAuthConfig.metadata.issuer}.well-known/openid-configuration`,
|
||||
delegatedAuthConfig.metadata,
|
||||
);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
|
||||
@@ -58,7 +58,7 @@ describe("getOidcClientId()", () => {
|
||||
const authConfigWithoutRegistration: OidcClientConfig = makeDelegatedAuthConfig(
|
||||
"https://issuerWithoutStaticClientId.org/",
|
||||
);
|
||||
authConfigWithoutRegistration.registration_endpoint = undefined;
|
||||
authConfigWithoutRegistration.registrationEndpoint = undefined;
|
||||
await expect(getOidcClientId(authConfigWithoutRegistration, staticOidcClients)).rejects.toThrow(
|
||||
OidcError.DynamicRegistrationNotSupported,
|
||||
);
|
||||
@@ -69,7 +69,7 @@ describe("getOidcClientId()", () => {
|
||||
it("should handle when staticOidcClients object is falsy", async () => {
|
||||
const authConfigWithoutRegistration: OidcClientConfig = {
|
||||
...delegatedAuthConfig,
|
||||
registration_endpoint: undefined,
|
||||
registrationEndpoint: undefined,
|
||||
};
|
||||
await expect(getOidcClientId(authConfigWithoutRegistration)).rejects.toThrow(
|
||||
OidcError.DynamicRegistrationNotSupported,
|
||||
@@ -79,14 +79,14 @@ describe("getOidcClientId()", () => {
|
||||
});
|
||||
|
||||
it("should make correct request to register client", async () => {
|
||||
fetchMockJest.post(delegatedAuthConfig.registration_endpoint!, {
|
||||
fetchMockJest.post(delegatedAuthConfig.registrationEndpoint!, {
|
||||
status: 200,
|
||||
body: JSON.stringify({ client_id: dynamicClientId }),
|
||||
});
|
||||
expect(await getOidcClientId(delegatedAuthConfig)).toEqual(dynamicClientId);
|
||||
// didn't try to register
|
||||
expect(fetchMockJest).toHaveBeenCalledWith(
|
||||
delegatedAuthConfig.registration_endpoint!,
|
||||
delegatedAuthConfig.registrationEndpoint!,
|
||||
expect.objectContaining({
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
@@ -111,14 +111,14 @@ describe("getOidcClientId()", () => {
|
||||
});
|
||||
|
||||
it("should throw when registration request fails", async () => {
|
||||
fetchMockJest.post(delegatedAuthConfig.registration_endpoint!, {
|
||||
fetchMockJest.post(delegatedAuthConfig.registrationEndpoint!, {
|
||||
status: 500,
|
||||
});
|
||||
await expect(getOidcClientId(delegatedAuthConfig)).rejects.toThrow(OidcError.DynamicRegistrationFailed);
|
||||
});
|
||||
|
||||
it("should throw when registration response is invalid", async () => {
|
||||
fetchMockJest.post(delegatedAuthConfig.registration_endpoint!, {
|
||||
fetchMockJest.post(delegatedAuthConfig.registrationEndpoint!, {
|
||||
status: 200,
|
||||
// no clientId in response
|
||||
body: "{}",
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"outDir": "./lib",
|
||||
"declaration": true,
|
||||
"jsx": "react",
|
||||
"lib": ["es2022", "dom", "dom.iterable"],
|
||||
"lib": ["es2022", "es2024.promise", "dom", "dom.iterable"],
|
||||
"strict": true,
|
||||
"paths": {
|
||||
"jest-matrix-react": ["./test/test-utils/jest-matrix-react"]
|
||||
|
||||
Reference in New Issue
Block a user