From 9de44fd313d007201949e854705ee9b4e36214ad Mon Sep 17 00:00:00 2001 From: Half-Shot Date: Thu, 28 Sep 2023 11:15:38 +0100 Subject: [PATCH 1/6] Show screen before login if using start_sso or start_cas --- src/components/structures/MatrixChat.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 7dd885503ea..94f157619ee 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -395,7 +395,8 @@ export default class MatrixChat extends React.PureComponent { return; } - if (firstScreen === "login" || firstScreen === "register" || firstScreen === "forgot_password") { + // If the first screen is an auth screen, we don't want to wait for login. + if (firstScreen !== null && AUTH_SCREENS.includes(firstScreen)) { this.showScreenAfterLogin(); } } From 3ed3a565b5fd41c8e7f2fb75a013c943e16d14b8 Mon Sep 17 00:00:00 2001 From: Half-Shot Date: Thu, 28 Sep 2023 14:04:23 +0100 Subject: [PATCH 2/6] Add tests --- .../components/structures/MatrixChat-test.tsx | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/test/components/structures/MatrixChat-test.tsx b/test/components/structures/MatrixChat-test.tsx index c01b0025abe..be6b71969af 100644 --- a/test/components/structures/MatrixChat-test.tsx +++ b/test/components/structures/MatrixChat-test.tsx @@ -41,6 +41,7 @@ import { MockClientWithEventEmitter, mockPlatformPeg, resetJsDomAfterEach, + unmockClientPeg, } from "../../test-utils"; import * as leaveRoomUtils from "../../../src/utils/leave-behaviour"; import * as voiceBroadcastUtils from "../../../src/voice-broadcast/utils/cleanUpBroadcasts"; @@ -51,6 +52,7 @@ import { PosthogAnalytics } from "../../../src/PosthogAnalytics"; import PlatformPeg from "../../../src/PlatformPeg"; import EventIndexPeg from "../../../src/indexing/EventIndexPeg"; import * as Lifecycle from "../../../src/Lifecycle"; +import { SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY } from "../../../src/BasePlatform"; jest.mock("matrix-js-sdk/src/oidc/authorize", () => ({ completeAuthorizationCodeGrant: jest.fn(), @@ -69,6 +71,7 @@ describe("", () => { setCanResetTimelineCallback: jest.fn(), isInitialSyncComplete: jest.fn(), getSyncState: jest.fn(), + getSsoLoginUrl: jest.fn(), getSyncStateData: jest.fn().mockReturnValue(null), getThirdpartyProtocols: jest.fn().mockResolvedValue({}), getClientWellKnown: jest.fn().mockReturnValue({}), @@ -1107,6 +1110,52 @@ describe("", () => { }); }); + describe("automatic SSO selection", () => { + let ssoClient: ReturnType; + let hrefSetter: jest.Mock; + beforeEach(() => { + ssoClient = getMockClientWithEventEmitter({ + ...getMockClientMethods(), + getHomeserverUrl: jest.fn().mockReturnValue("matrix.example.com"), + getIdentityServerUrl: jest.fn().mockReturnValue("ident.example.com"), + getSsoLoginUrl: jest.fn().mockReturnValue("http://my-sso-url"), + }); + // this is used to create a temporary client to cleanup after logout + jest.spyOn(MatrixJs, "createClient").mockClear().mockReturnValue(ssoClient); + mockPlatformPeg(); + // Ensure we don't have a client peg as we aren't logged in. + unmockClientPeg(); + + + hrefSetter = jest.fn(); + const originalHref = window.location.href.toString(); + Object.defineProperty(window, "location", { + value: { + get href() { + return originalHref; + }, + set href(href) { + hrefSetter(href); + } + }, + writable: true, + }); + }); + + it("should automatically setup and redirect to SSO login", async () => { + getComponent({ + initialScreenAfterLogin: { + screen: 'start_sso', + } + }); + await flushPromises(); + expect(ssoClient.getSsoLoginUrl).toHaveBeenCalledWith('http://localhost/', 'sso', undefined, undefined); + expect(window.localStorage.getItem(SSO_HOMESERVER_URL_KEY)).toEqual("matrix.example.com"); + expect(window.localStorage.getItem(SSO_ID_SERVER_URL_KEY)).toEqual("ident.example.com"); + expect(hrefSetter).toHaveBeenCalledWith("http://my-sso-url"); + }); + }); + describe("Multi-tab lockout", () => { afterEach(() => { Lifecycle.setSessionLockNotStolen(); From 87ab26954b6c0d47956f03765e8883c9a5d53330 Mon Sep 17 00:00:00 2001 From: Half-Shot Date: Thu, 28 Sep 2023 14:08:43 +0100 Subject: [PATCH 3/6] Fix lint --- test/components/structures/MatrixChat-test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/components/structures/MatrixChat-test.tsx b/test/components/structures/MatrixChat-test.tsx index be6b71969af..32b8e372cfb 100644 --- a/test/components/structures/MatrixChat-test.tsx +++ b/test/components/structures/MatrixChat-test.tsx @@ -1152,7 +1152,7 @@ describe("", () => { expect(ssoClient.getSsoLoginUrl).toHaveBeenCalledWith('http://localhost/', 'sso', undefined, undefined); expect(window.localStorage.getItem(SSO_HOMESERVER_URL_KEY)).toEqual("matrix.example.com"); expect(window.localStorage.getItem(SSO_ID_SERVER_URL_KEY)).toEqual("ident.example.com"); - expect(hrefSetter).toHaveBeenCalledWith("http://my-sso-url"); + expect(hrefSetter).toBeCalledWith("http://my-sso-url"); }); }); From 45997af48f5ac2a14bcb84d7245a4c75a4d3810b Mon Sep 17 00:00:00 2001 From: Half-Shot Date: Thu, 28 Sep 2023 14:08:54 +0100 Subject: [PATCH 4/6] Fix lint --- test/components/structures/MatrixChat-test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/components/structures/MatrixChat-test.tsx b/test/components/structures/MatrixChat-test.tsx index 32b8e372cfb..be6b71969af 100644 --- a/test/components/structures/MatrixChat-test.tsx +++ b/test/components/structures/MatrixChat-test.tsx @@ -1152,7 +1152,7 @@ describe("", () => { expect(ssoClient.getSsoLoginUrl).toHaveBeenCalledWith('http://localhost/', 'sso', undefined, undefined); expect(window.localStorage.getItem(SSO_HOMESERVER_URL_KEY)).toEqual("matrix.example.com"); expect(window.localStorage.getItem(SSO_ID_SERVER_URL_KEY)).toEqual("ident.example.com"); - expect(hrefSetter).toBeCalledWith("http://my-sso-url"); + expect(hrefSetter).toHaveBeenCalledWith("http://my-sso-url"); }); }); From d9f2e0058635d326eb7b96b85382b2e9624912ef Mon Sep 17 00:00:00 2001 From: Half-Shot Date: Thu, 28 Sep 2023 14:11:55 +0100 Subject: [PATCH 5/6] Add one for CAS --- test/components/structures/MatrixChat-test.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/components/structures/MatrixChat-test.tsx b/test/components/structures/MatrixChat-test.tsx index be6b71969af..24980ae9ad4 100644 --- a/test/components/structures/MatrixChat-test.tsx +++ b/test/components/structures/MatrixChat-test.tsx @@ -1154,6 +1154,19 @@ describe("", () => { expect(window.localStorage.getItem(SSO_ID_SERVER_URL_KEY)).toEqual("ident.example.com"); expect(hrefSetter).toHaveBeenCalledWith("http://my-sso-url"); }); + + it("should automatically setup and redirect to CAS login", async () => { + getComponent({ + initialScreenAfterLogin: { + screen: 'start_cas', + } + }); + await flushPromises(); + expect(ssoClient.getSsoLoginUrl).toHaveBeenCalledWith('http://localhost/', 'cas', undefined, undefined); + expect(window.localStorage.getItem(SSO_HOMESERVER_URL_KEY)).toEqual("matrix.example.com"); + expect(window.localStorage.getItem(SSO_ID_SERVER_URL_KEY)).toEqual("ident.example.com"); + expect(hrefSetter).toHaveBeenCalledWith("http://my-sso-url"); + }); }); describe("Multi-tab lockout", () => { From 2921c4e7e592394a83a4213bc144d0a5a59a8d4c Mon Sep 17 00:00:00 2001 From: Half-Shot Date: Thu, 28 Sep 2023 14:55:59 +0100 Subject: [PATCH 6/6] prettier --- test/components/structures/MatrixChat-test.tsx | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/test/components/structures/MatrixChat-test.tsx b/test/components/structures/MatrixChat-test.tsx index 24980ae9ad4..ac8ad257f71 100644 --- a/test/components/structures/MatrixChat-test.tsx +++ b/test/components/structures/MatrixChat-test.tsx @@ -71,7 +71,7 @@ describe("", () => { setCanResetTimelineCallback: jest.fn(), isInitialSyncComplete: jest.fn(), getSyncState: jest.fn(), - getSsoLoginUrl: jest.fn(), + getSsoLoginUrl: jest.fn(), getSyncStateData: jest.fn().mockReturnValue(null), getThirdpartyProtocols: jest.fn().mockResolvedValue({}), getClientWellKnown: jest.fn().mockReturnValue({}), @@ -1126,7 +1126,6 @@ describe("", () => { // Ensure we don't have a client peg as we aren't logged in. unmockClientPeg(); - hrefSetter = jest.fn(); const originalHref = window.location.href.toString(); Object.defineProperty(window, "location", { @@ -1136,7 +1135,7 @@ describe("", () => { }, set href(href) { hrefSetter(href); - } + }, }, writable: true, }); @@ -1145,11 +1144,11 @@ describe("", () => { it("should automatically setup and redirect to SSO login", async () => { getComponent({ initialScreenAfterLogin: { - screen: 'start_sso', - } + screen: "start_sso", + }, }); await flushPromises(); - expect(ssoClient.getSsoLoginUrl).toHaveBeenCalledWith('http://localhost/', 'sso', undefined, undefined); + expect(ssoClient.getSsoLoginUrl).toHaveBeenCalledWith("http://localhost/", "sso", undefined, undefined); expect(window.localStorage.getItem(SSO_HOMESERVER_URL_KEY)).toEqual("matrix.example.com"); expect(window.localStorage.getItem(SSO_ID_SERVER_URL_KEY)).toEqual("ident.example.com"); expect(hrefSetter).toHaveBeenCalledWith("http://my-sso-url"); @@ -1158,11 +1157,11 @@ describe("", () => { it("should automatically setup and redirect to CAS login", async () => { getComponent({ initialScreenAfterLogin: { - screen: 'start_cas', - } + screen: "start_cas", + }, }); await flushPromises(); - expect(ssoClient.getSsoLoginUrl).toHaveBeenCalledWith('http://localhost/', 'cas', undefined, undefined); + expect(ssoClient.getSsoLoginUrl).toHaveBeenCalledWith("http://localhost/", "cas", undefined, undefined); expect(window.localStorage.getItem(SSO_HOMESERVER_URL_KEY)).toEqual("matrix.example.com"); expect(window.localStorage.getItem(SSO_ID_SERVER_URL_KEY)).toEqual("ident.example.com"); expect(hrefSetter).toHaveBeenCalledWith("http://my-sso-url");