From 2bd913acbbcddcf6c548e3e71318c05f7b2ba0b9 Mon Sep 17 00:00:00 2001 From: Ashley Stanton-Nurse Date: Fri, 7 Jun 2024 12:05:46 -0700 Subject: [PATCH] when opening hosted explorer from portal, jump to selected sub/account --- src/Explorer/OpenFullScreen.tsx | 4 +++- src/HostedExplorer.tsx | 20 +------------------ src/Index.tsx | 11 +--------- .../Hosted/Components/AccountSwitcher.tsx | 5 +++-- .../Hosted/Components/ConnectExplorer.tsx | 10 +++++++++- src/Utils/UrlContext.ts | 17 ++++++++++++++++ src/hooks/useAADAuth.ts | 18 +++-------------- 7 files changed, 37 insertions(+), 48 deletions(-) create mode 100644 src/Utils/UrlContext.ts diff --git a/src/Explorer/OpenFullScreen.tsx b/src/Explorer/OpenFullScreen.tsx index 669de816b..833787663 100644 --- a/src/Explorer/OpenFullScreen.tsx +++ b/src/Explorer/OpenFullScreen.tsx @@ -6,13 +6,15 @@ import * as React from "react"; export const OpenFullScreen: React.FunctionComponent = () => { const searchParams = new URLSearchParams(); + searchParams.append("openFrom", "portal"); + let hasAccountContext = false; let requiresConnectionString = false; if (userContext.authType === AuthType.AAD) { if (userContext.subscriptionId && userContext.databaseAccount) { searchParams.append("subscription", userContext.subscriptionId); - searchParams.append("account", userContext.databaseAccount.id); + searchParams.append("account", userContext.databaseAccount.name); searchParams.append("authType", "entra"); hasAccountContext = true; } diff --git a/src/HostedExplorer.tsx b/src/HostedExplorer.tsx index f546cd42d..909f9a111 100644 --- a/src/HostedExplorer.tsx +++ b/src/HostedExplorer.tsx @@ -1,7 +1,6 @@ import { initializeIcons } from "@fluentui/react"; import { useBoolean } from "@fluentui/react-hooks"; import { AadAuthorizationFailure } from "Platform/Hosted/Components/AadAuthorizationFailure"; -import { getMsalInstance } from "Utils/AuthorizationUtils"; import * as React from "react"; import { render } from "react-dom"; import ChevronRight from "../images/chevron-right.svg"; @@ -34,7 +33,7 @@ const App: React.FunctionComponent = () => { // For showing/hiding panel const [isOpen, { setTrue: openPanel, setFalse: dismissPanel }] = useBoolean(false); const config = useConfig(); - const { isLoggedIn, armToken, graphToken, account, tenantId, logout, login, switchTenant, authFailure } = + const { isLoggedIn, armToken, graphToken, account, tenantId, logout, forgetUser, login, switchTenant, authFailure } = useAADAuth(); const [databaseAccount, setDatabaseAccount] = React.useState(); const [authType, setAuthType] = React.useState(encryptedToken ? AuthType.EncryptedToken : undefined); @@ -43,23 +42,6 @@ const App: React.FunctionComponent = () => { const ref = React.useRef(); React.useEffect(() => { - (async () => { - const params = new URLSearchParams(window.location.search); - if (params.get("authType") === "entra") { - const msalInstance = await getMsalInstance(); - const response = await msalInstance.handleRedirectPromise(); - if (response) { - console.log("Redirect Promise Response", response); - } - else { - // Send the user to log in immediately - console.log("Starting non-interactive login"); - login(false); - } - return; - } - })(); - // If ref.current is undefined no iframe has been rendered if (ref.current) { // In hosted mode, we can set global properties directly on the child iframe. diff --git a/src/Index.tsx b/src/Index.tsx index 2f9fdc6f3..9024c1dbb 100644 --- a/src/Index.tsx +++ b/src/Index.tsx @@ -1,5 +1,4 @@ -import { getMsalInstance } from "Utils/AuthorizationUtils"; -import React, { useEffect, useState } from "react"; +import React, { useState } from "react"; import ReactDOM from "react-dom"; import Arrow from "../images/Arrow.svg"; import CosmosDB_20170829 from "../images/CosmosDB_20170829.svg"; @@ -13,14 +12,6 @@ const Index = (): JSX.Element => { const quickstart_click = () => { setNavigationSelection("quickstart"); }; - - useEffect(() => { - (async () => { - const msalInstance = await getMsalInstance(); - console.log("handleRedirectPromise"); - await msalInstance.handleRedirectPromise(); - })(); - }, []); const explorer_click = () => { setNavigationSelection("explorer"); diff --git a/src/Platform/Hosted/Components/AccountSwitcher.tsx b/src/Platform/Hosted/Components/AccountSwitcher.tsx index dfff7fe5c..743f9cf21 100644 --- a/src/Platform/Hosted/Components/AccountSwitcher.tsx +++ b/src/Platform/Hosted/Components/AccountSwitcher.tsx @@ -2,6 +2,7 @@ /* eslint-disable react/display-name */ import { DefaultButton, IButtonStyles, IContextualMenuItem } from "@fluentui/react"; +import { urlContext } from "Utils/UrlContext"; import * as React from "react"; import { FunctionComponent, useEffect, useState } from "react"; import { StyleConstants } from "../../../Common/StyleConstants"; @@ -50,12 +51,12 @@ interface Props { export const AccountSwitcher: FunctionComponent = ({ armToken, setDatabaseAccount }: Props) => { const subscriptions = useSubscriptions(armToken); const [selectedSubscriptionId, setSelectedSubscriptionId] = useState(() => - localStorage.getItem("cachedSubscriptionId"), + urlContext.subscription || localStorage.getItem("cachedSubscriptionId"), ); const selectedSubscription = subscriptions?.find((sub) => sub.subscriptionId === selectedSubscriptionId); const accounts = useDatabaseAccounts(selectedSubscription?.subscriptionId, armToken); const [selectedAccountName, setSelectedAccountName] = useState(() => - localStorage.getItem("cachedDatabaseAccountName"), + urlContext.account || localStorage.getItem("cachedDatabaseAccountName"), ); const selectedAccount = accounts?.find((account) => account.name === selectedAccountName); diff --git a/src/Platform/Hosted/Components/ConnectExplorer.tsx b/src/Platform/Hosted/Components/ConnectExplorer.tsx index 513247a6c..0d6d12933 100644 --- a/src/Platform/Hosted/Components/ConnectExplorer.tsx +++ b/src/Platform/Hosted/Components/ConnectExplorer.tsx @@ -1,6 +1,7 @@ import { useBoolean } from "@fluentui/react-hooks"; import { userContext } from "UserContext"; import { useNewPortalBackendEndpoint } from "Utils/EndpointUtils"; +import { OpenedFrom, RequestedAuthType, urlContext } from "Utils/UrlContext"; import * as React from "react"; import ConnectImage from "../../../../images/HdeConnectCosmosDB.svg"; import ErrorImage from "../../../../images/error.svg"; @@ -69,7 +70,9 @@ export const ConnectExplorer: React.FunctionComponent = ({ }: Props) => { const [isFormVisible, { setTrue: showForm }] = useBoolean(false); const [errorMessage, setErrorMessage] = React.useState(""); - const enableConnectionStringLogin = !userContext.features.disableConnectionStringLogin; + const enableConnectionStringLogin = + urlContext.authType !== RequestedAuthType.Entra && + !userContext.features.disableConnectionStringLogin; return (
@@ -136,6 +139,11 @@ export const ConnectExplorer: React.FunctionComponent = ({

Connect to your account with connection string

+ )} + {urlContext.openFrom === OpenedFrom.Portal && ( +

+ Click sign in to continue your session from the Azure Portal. +

)}
)} diff --git a/src/Utils/UrlContext.ts b/src/Utils/UrlContext.ts new file mode 100644 index 000000000..f04ecacf6 --- /dev/null +++ b/src/Utils/UrlContext.ts @@ -0,0 +1,17 @@ +const urlParams = new URLSearchParams(window.location.search); + +export enum OpenedFrom { + Portal = "portal", +} + +export enum RequestedAuthType { + Entra = "entra", + ConnectionString = "connectionstring", +} + +export const urlContext = { + openFrom: urlParams.get("openFrom") as OpenedFrom, + authType: urlParams.get("authType") as RequestedAuthType, + subscription: urlParams.get("subscription"), + account: urlParams.get("account"), +}; diff --git a/src/hooks/useAADAuth.ts b/src/hooks/useAADAuth.ts index 8fbcc4621..7e019b59a 100644 --- a/src/hooks/useAADAuth.ts +++ b/src/hooks/useAADAuth.ts @@ -13,7 +13,7 @@ interface ReturnType { isLoggedIn: boolean; graphToken: string; armToken: string; - login: (userTriggered?: boolean) => void; + login: () => void; logout: () => void; tenantId: string; account: msal.AccountInfo; @@ -37,21 +37,9 @@ export function useAADAuth(): ReturnType { const [armToken, setArmToken] = React.useState(); const [authFailure, setAuthFailure] = React.useState(undefined); - console.log("Current AAD State", { - isLoggedIn, account, tenantId - }); - msalInstance.setActiveAccount(account); - const login = React.useCallback(async (userTriggered: boolean = true) => { - if (!userTriggered) { - console.log("Starting non-interactive login"); - // If the user didn't trigger the login, we don't want to pop up the login dialog - await msalInstance.acquireTokenRedirect({ - redirectUri: configContext.msalRedirectURI, - scopes: [], - }); - return; - } + + const login = React.useCallback(async () => { const response = await msalInstance.loginPopup({ redirectUri: configContext.msalRedirectURI, scopes: [],