when opening hosted explorer from portal, jump to selected sub/account

This commit is contained in:
Ashley Stanton-Nurse 2024-06-07 12:05:46 -07:00
parent 4866d3c902
commit 2bd913acbb
No known key found for this signature in database
7 changed files with 37 additions and 48 deletions

View File

@ -6,13 +6,15 @@ import * as React from "react";
export const OpenFullScreen: React.FunctionComponent = () => { export const OpenFullScreen: React.FunctionComponent = () => {
const searchParams = new URLSearchParams(); const searchParams = new URLSearchParams();
searchParams.append("openFrom", "portal");
let hasAccountContext = false; let hasAccountContext = false;
let requiresConnectionString = false; let requiresConnectionString = false;
if (userContext.authType === AuthType.AAD) { if (userContext.authType === AuthType.AAD) {
if (userContext.subscriptionId && userContext.databaseAccount) { if (userContext.subscriptionId && userContext.databaseAccount) {
searchParams.append("subscription", userContext.subscriptionId); searchParams.append("subscription", userContext.subscriptionId);
searchParams.append("account", userContext.databaseAccount.id); searchParams.append("account", userContext.databaseAccount.name);
searchParams.append("authType", "entra"); searchParams.append("authType", "entra");
hasAccountContext = true; hasAccountContext = true;
} }

View File

@ -1,7 +1,6 @@
import { initializeIcons } from "@fluentui/react"; import { initializeIcons } from "@fluentui/react";
import { useBoolean } from "@fluentui/react-hooks"; import { useBoolean } from "@fluentui/react-hooks";
import { AadAuthorizationFailure } from "Platform/Hosted/Components/AadAuthorizationFailure"; import { AadAuthorizationFailure } from "Platform/Hosted/Components/AadAuthorizationFailure";
import { getMsalInstance } from "Utils/AuthorizationUtils";
import * as React from "react"; import * as React from "react";
import { render } from "react-dom"; import { render } from "react-dom";
import ChevronRight from "../images/chevron-right.svg"; import ChevronRight from "../images/chevron-right.svg";
@ -34,7 +33,7 @@ const App: React.FunctionComponent = () => {
// For showing/hiding panel // For showing/hiding panel
const [isOpen, { setTrue: openPanel, setFalse: dismissPanel }] = useBoolean(false); const [isOpen, { setTrue: openPanel, setFalse: dismissPanel }] = useBoolean(false);
const config = useConfig(); 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(); useAADAuth();
const [databaseAccount, setDatabaseAccount] = React.useState<DatabaseAccount>(); const [databaseAccount, setDatabaseAccount] = React.useState<DatabaseAccount>();
const [authType, setAuthType] = React.useState<AuthType>(encryptedToken ? AuthType.EncryptedToken : undefined); const [authType, setAuthType] = React.useState<AuthType>(encryptedToken ? AuthType.EncryptedToken : undefined);
@ -43,23 +42,6 @@ const App: React.FunctionComponent = () => {
const ref = React.useRef<HTMLIFrameElement>(); const ref = React.useRef<HTMLIFrameElement>();
React.useEffect(() => { 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 is undefined no iframe has been rendered
if (ref.current) { if (ref.current) {
// In hosted mode, we can set global properties directly on the child iframe. // In hosted mode, we can set global properties directly on the child iframe.

View File

@ -1,5 +1,4 @@
import { getMsalInstance } from "Utils/AuthorizationUtils"; import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
import Arrow from "../images/Arrow.svg"; import Arrow from "../images/Arrow.svg";
import CosmosDB_20170829 from "../images/CosmosDB_20170829.svg"; import CosmosDB_20170829 from "../images/CosmosDB_20170829.svg";
@ -14,14 +13,6 @@ const Index = (): JSX.Element => {
setNavigationSelection("quickstart"); setNavigationSelection("quickstart");
}; };
useEffect(() => {
(async () => {
const msalInstance = await getMsalInstance();
console.log("handleRedirectPromise");
await msalInstance.handleRedirectPromise();
})();
}, []);
const explorer_click = () => { const explorer_click = () => {
setNavigationSelection("explorer"); setNavigationSelection("explorer");
}; };

View File

@ -2,6 +2,7 @@
/* eslint-disable react/display-name */ /* eslint-disable react/display-name */
import { DefaultButton, IButtonStyles, IContextualMenuItem } from "@fluentui/react"; import { DefaultButton, IButtonStyles, IContextualMenuItem } from "@fluentui/react";
import { urlContext } from "Utils/UrlContext";
import * as React from "react"; import * as React from "react";
import { FunctionComponent, useEffect, useState } from "react"; import { FunctionComponent, useEffect, useState } from "react";
import { StyleConstants } from "../../../Common/StyleConstants"; import { StyleConstants } from "../../../Common/StyleConstants";
@ -50,12 +51,12 @@ interface Props {
export const AccountSwitcher: FunctionComponent<Props> = ({ armToken, setDatabaseAccount }: Props) => { export const AccountSwitcher: FunctionComponent<Props> = ({ armToken, setDatabaseAccount }: Props) => {
const subscriptions = useSubscriptions(armToken); const subscriptions = useSubscriptions(armToken);
const [selectedSubscriptionId, setSelectedSubscriptionId] = useState<string>(() => const [selectedSubscriptionId, setSelectedSubscriptionId] = useState<string>(() =>
localStorage.getItem("cachedSubscriptionId"), urlContext.subscription || localStorage.getItem("cachedSubscriptionId"),
); );
const selectedSubscription = subscriptions?.find((sub) => sub.subscriptionId === selectedSubscriptionId); const selectedSubscription = subscriptions?.find((sub) => sub.subscriptionId === selectedSubscriptionId);
const accounts = useDatabaseAccounts(selectedSubscription?.subscriptionId, armToken); const accounts = useDatabaseAccounts(selectedSubscription?.subscriptionId, armToken);
const [selectedAccountName, setSelectedAccountName] = useState<string>(() => const [selectedAccountName, setSelectedAccountName] = useState<string>(() =>
localStorage.getItem("cachedDatabaseAccountName"), urlContext.account || localStorage.getItem("cachedDatabaseAccountName"),
); );
const selectedAccount = accounts?.find((account) => account.name === selectedAccountName); const selectedAccount = accounts?.find((account) => account.name === selectedAccountName);

View File

@ -1,6 +1,7 @@
import { useBoolean } from "@fluentui/react-hooks"; import { useBoolean } from "@fluentui/react-hooks";
import { userContext } from "UserContext"; import { userContext } from "UserContext";
import { useNewPortalBackendEndpoint } from "Utils/EndpointUtils"; import { useNewPortalBackendEndpoint } from "Utils/EndpointUtils";
import { OpenedFrom, RequestedAuthType, urlContext } from "Utils/UrlContext";
import * as React from "react"; import * as React from "react";
import ConnectImage from "../../../../images/HdeConnectCosmosDB.svg"; import ConnectImage from "../../../../images/HdeConnectCosmosDB.svg";
import ErrorImage from "../../../../images/error.svg"; import ErrorImage from "../../../../images/error.svg";
@ -69,7 +70,9 @@ export const ConnectExplorer: React.FunctionComponent<Props> = ({
}: Props) => { }: Props) => {
const [isFormVisible, { setTrue: showForm }] = useBoolean(false); const [isFormVisible, { setTrue: showForm }] = useBoolean(false);
const [errorMessage, setErrorMessage] = React.useState(""); const [errorMessage, setErrorMessage] = React.useState("");
const enableConnectionStringLogin = !userContext.features.disableConnectionStringLogin; const enableConnectionStringLogin =
urlContext.authType !== RequestedAuthType.Entra &&
!userContext.features.disableConnectionStringLogin;
return ( return (
<div id="connectExplorer" className="connectExplorerContainer" style={{ display: "flex" }}> <div id="connectExplorer" className="connectExplorerContainer" style={{ display: "flex" }}>
@ -137,6 +140,11 @@ export const ConnectExplorer: React.FunctionComponent<Props> = ({
Connect to your account with connection string Connect to your account with connection string
</p> </p>
)} )}
{urlContext.openFrom === OpenedFrom.Portal && (
<p className="switchConnectTypeText">
Click sign in to continue your session from the Azure Portal.
</p>
)}
</div> </div>
)} )}
</div> </div>

17
src/Utils/UrlContext.ts Normal file
View File

@ -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"),
};

View File

@ -13,7 +13,7 @@ interface ReturnType {
isLoggedIn: boolean; isLoggedIn: boolean;
graphToken: string; graphToken: string;
armToken: string; armToken: string;
login: (userTriggered?: boolean) => void; login: () => void;
logout: () => void; logout: () => void;
tenantId: string; tenantId: string;
account: msal.AccountInfo; account: msal.AccountInfo;
@ -37,21 +37,9 @@ export function useAADAuth(): ReturnType {
const [armToken, setArmToken] = React.useState<string>(); const [armToken, setArmToken] = React.useState<string>();
const [authFailure, setAuthFailure] = React.useState<AadAuthFailure>(undefined); const [authFailure, setAuthFailure] = React.useState<AadAuthFailure>(undefined);
console.log("Current AAD State", {
isLoggedIn, account, tenantId
});
msalInstance.setActiveAccount(account); msalInstance.setActiveAccount(account);
const login = React.useCallback(async (userTriggered: boolean = true) => {
if (!userTriggered) { const login = React.useCallback(async () => {
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 response = await msalInstance.loginPopup({ const response = await msalInstance.loginPopup({
redirectUri: configContext.msalRedirectURI, redirectUri: configContext.msalRedirectURI,
scopes: [], scopes: [],