mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-25 11:51:07 +00:00
152 lines
6.1 KiB
TypeScript
152 lines
6.1 KiB
TypeScript
import { useBoolean } from "@fluentui/react-hooks";
|
|
import { userContext } from "UserContext";
|
|
import { useNewPortalBackendEndpoint } from "Utils/EndpointUtils";
|
|
import * as React from "react";
|
|
import ConnectImage from "../../../../images/HdeConnectCosmosDB.svg";
|
|
import ErrorImage from "../../../../images/error.svg";
|
|
import { AuthType } from "../../../AuthType";
|
|
import { BackendApi, HttpHeaders } from "../../../Common/Constants";
|
|
import { configContext } from "../../../ConfigContext";
|
|
import { GenerateTokenResponse } from "../../../Contracts/DataModels";
|
|
import { isResourceTokenConnectionString } from "../Helpers/ResourceTokenUtils";
|
|
|
|
interface Props {
|
|
connectionString: string;
|
|
login: () => void;
|
|
setEncryptedToken: (token: string) => void;
|
|
setConnectionString: (connectionString: string) => void;
|
|
setAuthType: (authType: AuthType) => void;
|
|
}
|
|
|
|
export const fetchEncryptedToken = async (connectionString: string): Promise<string> => {
|
|
if (!useNewPortalBackendEndpoint(BackendApi.GenerateToken)) {
|
|
return await fetchEncryptedToken_ToBeDeprecated(connectionString);
|
|
}
|
|
|
|
const headers = new Headers();
|
|
headers.append(HttpHeaders.connectionString, connectionString);
|
|
const url = configContext.PORTAL_BACKEND_ENDPOINT + "/api/connectionstring/token/generatetoken";
|
|
const response = await fetch(url, { headers, method: "POST" });
|
|
if (!response.ok) {
|
|
throw response;
|
|
}
|
|
|
|
const encryptedTokenResponse: string = await response.json();
|
|
return decodeURIComponent(encryptedTokenResponse);
|
|
};
|
|
|
|
export const fetchEncryptedToken_ToBeDeprecated = async (connectionString: string): Promise<string> => {
|
|
const headers = new Headers();
|
|
headers.append(HttpHeaders.connectionString, connectionString);
|
|
const url = configContext.BACKEND_ENDPOINT + "/api/guest/tokens/generateToken";
|
|
const response = await fetch(url, { headers, method: "POST" });
|
|
if (!response.ok) {
|
|
throw response;
|
|
}
|
|
// This API has a quirk where it must be parsed twice
|
|
const result: GenerateTokenResponse = JSON.parse(await response.json());
|
|
return decodeURIComponent(result.readWrite || result.read);
|
|
};
|
|
|
|
export const isAccountRestrictedForConnectionStringLogin = async (connectionString: string): Promise<boolean> => {
|
|
const headers = new Headers();
|
|
headers.append(HttpHeaders.connectionString, connectionString);
|
|
|
|
const backendEndpoint: string = useNewPortalBackendEndpoint(BackendApi.PortalSettings)
|
|
? configContext.PORTAL_BACKEND_ENDPOINT
|
|
: configContext.BACKEND_ENDPOINT;
|
|
|
|
const url = backendEndpoint + "/api/guest/accountrestrictions/checkconnectionstringlogin";
|
|
const response = await fetch(url, { headers, method: "POST" });
|
|
if (!response.ok) {
|
|
throw response;
|
|
}
|
|
|
|
return (await response.text()).toLowerCase() === "true";
|
|
};
|
|
|
|
export const ConnectExplorer: React.FunctionComponent<Props> = ({
|
|
setEncryptedToken,
|
|
login,
|
|
setAuthType,
|
|
connectionString,
|
|
setConnectionString,
|
|
}: Props) => {
|
|
const [isFormVisible, { setTrue: showForm }] = useBoolean(false);
|
|
const [errorMessage, setErrorMessage] = React.useState("");
|
|
const enableConnectionStringLogin = !userContext.features.disableConnectionStringLogin;
|
|
|
|
return (
|
|
<div id="connectExplorer" className="connectExplorerContainer" style={{ display: "flex" }}>
|
|
<div className="connectExplorerFormContainer">
|
|
<div className="connectExplorer">
|
|
<p className="connectExplorerContent">
|
|
<img src={ConnectImage} alt="Azure Cosmos DB" />
|
|
</p>
|
|
<p className="welcomeText">Welcome to Azure Cosmos DB</p>
|
|
{isFormVisible && enableConnectionStringLogin ? (
|
|
<form
|
|
id="connectWithConnectionString"
|
|
onSubmit={async (event) => {
|
|
event.preventDefault();
|
|
setErrorMessage("");
|
|
|
|
if (await isAccountRestrictedForConnectionStringLogin(connectionString)) {
|
|
setErrorMessage(
|
|
"This account has been blocked from connection-string login. Please go to cosmos.azure.com/aad for AAD based login.",
|
|
);
|
|
return;
|
|
}
|
|
|
|
if (isResourceTokenConnectionString(connectionString)) {
|
|
setAuthType(AuthType.ResourceToken);
|
|
return;
|
|
}
|
|
|
|
const encryptedToken = await fetchEncryptedToken(connectionString);
|
|
setEncryptedToken(encryptedToken);
|
|
setAuthType(AuthType.ConnectionString);
|
|
}}
|
|
>
|
|
<p className="connectExplorerContent connectStringText">Connect to your account with connection string</p>
|
|
<p className="connectExplorerContent">
|
|
<input
|
|
className="inputToken"
|
|
type="text"
|
|
required
|
|
placeholder="Please enter a connection string"
|
|
value={connectionString}
|
|
onChange={(event) => {
|
|
setConnectionString(event.target.value);
|
|
}}
|
|
/>
|
|
{errorMessage.length > 0 && (
|
|
<span className="errorDetailsInfoTooltip">
|
|
<img className="errorImg" src={ErrorImage} alt="Error notification" />
|
|
<span className="errorDetails">{errorMessage}</span>
|
|
</span>
|
|
)}
|
|
</p>
|
|
<p className="connectExplorerContent">
|
|
<input className="filterbtnstyle" type="submit" value="Connect" />
|
|
</p>
|
|
<p className="switchConnectTypeText" onClick={login}>
|
|
Sign In with Azure Account
|
|
</p>
|
|
</form>
|
|
) : (
|
|
<div id="connectWithAad">
|
|
<input className="filterbtnstyle" type="button" value="Sign In" onClick={login} />
|
|
{enableConnectionStringLogin && (
|
|
<p className="switchConnectTypeText" data-test="Link:SwitchConnectionType" onClick={showForm}>
|
|
Connect to your account with connection string
|
|
</p>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|