diff --git a/src/HostedExplorer.test.tsx b/src/HostedExplorer.test.tsx index 4043f388b..0db2e45ce 100644 --- a/src/HostedExplorer.test.tsx +++ b/src/HostedExplorer.test.tsx @@ -1,6 +1,6 @@ jest.mock("./hooks/useAADAuth"); jest.mock("./hooks/useConfig"); -jest.mock("./Platform/Hosted/Helpers/PortalBackendClient"); +jest.mock("./Platform/Hosted/PortalBackendConnectionStringClient"); jest.mock("./Platform/Hosted/Components/ConnectExplorer"); jest.mock("./Shared/appInsights"); jest.mock("./Platform/Hosted/Components/AccountSwitcher", () => ({ @@ -29,7 +29,7 @@ import { useAADAuth } from "./hooks/useAADAuth"; import { useConfig } from "./hooks/useConfig"; import { App } from "./HostedExplorer"; import { ConnectExplorer } from "./Platform/Hosted/Components/ConnectExplorer"; -import { fetchAccessData, fetchEncryptedToken } from "./Platform/Hosted/Helpers/PortalBackendClient"; +import { fetchAccessData, fetchEncryptedToken } from "./Platform/Hosted/PortalBackendConnectionStringClient"; const mockFetchEncryptedToken = fetchEncryptedToken as jest.MockedFunction; diff --git a/src/HostedExplorer.tsx b/src/HostedExplorer.tsx index 65672e030..c468fc3ac 100644 --- a/src/HostedExplorer.tsx +++ b/src/HostedExplorer.tsx @@ -19,12 +19,12 @@ import { MeControl } from "./Platform/Hosted/Components/MeControl"; import { SignInButton } from "./Platform/Hosted/Components/SignInButton"; import "./Platform/Hosted/ConnectScreen.less"; import { parseConnectionString } from "./Platform/Hosted/Helpers/ConnectionStringParser"; -import { fetchAccessData, fetchEncryptedToken } from "./Platform/Hosted/Helpers/PortalBackendClient"; import { isResourceTokenConnectionString } from "./Platform/Hosted/Helpers/ResourceTokenUtils"; import { extractMasterKeyFromDirectLoginConnectionString, isDirectConnectionStringLoginApi, } from "./Platform/Hosted/HostedUtils"; +import { fetchAccessData, fetchEncryptedToken } from "./Platform/Hosted/PortalBackendConnectionStringClient"; import "./Shared/appInsights"; import { allowedHostedExplorerEndpoints } from "./Utils/EndpointUtils"; import { useAADAuth } from "./hooks/useAADAuth"; diff --git a/src/Platform/Hosted/Components/ConnectExplorer.tsx b/src/Platform/Hosted/Components/ConnectExplorer.tsx index 588ef778e..de77ac8a9 100644 --- a/src/Platform/Hosted/Components/ConnectExplorer.tsx +++ b/src/Platform/Hosted/Components/ConnectExplorer.tsx @@ -7,9 +7,12 @@ import ErrorImage from "../../../../images/error.svg"; import { AuthType } from "../../../AuthType"; import { AccessInputMetadata } from "../../../Contracts/DataModels"; import { parseConnectionString } from "../Helpers/ConnectionStringParser"; -import { fetchEncryptedToken, isAccountRestrictedForConnectionStringLogin } from "../Helpers/PortalBackendClient"; import { isResourceTokenConnectionString } from "../Helpers/ResourceTokenUtils"; import { isDirectConnectionStringLoginApi } from "../HostedUtils"; +import { + fetchEncryptedToken, + isAccountRestrictedForConnectionStringLogin, +} from "../PortalBackendConnectionStringClient"; interface Props { connectionString: string; diff --git a/src/Platform/Hosted/ConnectScreen.less b/src/Platform/Hosted/ConnectScreen.less index f1fb81241..d4123f23f 100644 --- a/src/Platform/Hosted/ConnectScreen.less +++ b/src/Platform/Hosted/ConnectScreen.less @@ -65,35 +65,27 @@ visibility: visible; } .connectExplorerContainer .connectExplorer .connectExplorerContent .errorDetailsInfoTooltip .errorDetails { - top: 50%; - transform: translateY(-50%); - left: 100%; - margin-left: 10px; - width: 320px; - max-height: 240px; - overflow-y: auto; + bottom: 24px; + width: 165px; visibility: hidden; background-color: #393939; color: #ffffff; position: absolute; z-index: 1; + left: -10px; padding: 6px; - text-align: left; - white-space: normal; - overflow-wrap: break-word; } -.connectExplorerContainer .connectExplorer .connectExplorerContent .errorDetailsInfoTooltip:hover:after { - border-width: 8px 8px 8px 0px; +.connectExplorerContainer .connectExplorer .connectExplorerContent .errorDetailsInfoTooltip .errorDetails:after { + border-width: 10px 10px 0px 10px; + bottom: -8px; content: ""; position: absolute; - top: 50%; - transform: translateY(-50%); - left: 100%; - margin-left: 2px; + right: 100%; border-style: solid; + left: 12px; width: 0; height: 0; - border-color: transparent #393939; + border-color: #3b3b3b transparent; } .connectExplorerContainer .connectExplorer .connectExplorerContent .errorDetailsInfoTooltip .errorImg { height: 14px; diff --git a/src/Platform/Hosted/HostedUtils.ts b/src/Platform/Hosted/HostedUtils.ts index f900548cc..561956ea5 100644 --- a/src/Platform/Hosted/HostedUtils.ts +++ b/src/Platform/Hosted/HostedUtils.ts @@ -40,9 +40,7 @@ export function getDatabaseAccountKindFromExperience(apiExperience: typeof userC return AccountKind.GlobalDocumentDB; } -// Returns the master key carried by SQL, Table, and Gremlin connection strings. Mongo and -// Cassandra do not use an AccountKey token, so they must not be passed here. The key value cannot -// contain a semicolon, so we capture everything up to the next delimiter. +// Returns the master key carried by SQL, Table, and Gremlin connection strings. export function extractMasterKeyFromDirectLoginConnectionString(connectionString: string): string | undefined { const matchedParts = connectionString?.match(/AccountKey=([^;]*)/); return (matchedParts && matchedParts.length > 1 && matchedParts[1]) || undefined; diff --git a/src/Platform/Hosted/Helpers/PortalBackendClient.ts b/src/Platform/Hosted/PortalBackendConnectionStringClient.ts similarity index 63% rename from src/Platform/Hosted/Helpers/PortalBackendClient.ts rename to src/Platform/Hosted/PortalBackendConnectionStringClient.ts index 0edf9b4ab..9822aa852 100644 --- a/src/Platform/Hosted/Helpers/PortalBackendClient.ts +++ b/src/Platform/Hosted/PortalBackendConnectionStringClient.ts @@ -1,24 +1,6 @@ -import { HttpHeaders } from "../../../Common/Constants"; -import { configContext } from "../../../ConfigContext"; -import { AccessInputMetadata } from "../../../Contracts/DataModels"; - -// A failed Portal Backend response. Carries the status so callers can tell a rejected connection string -// from a service failure. -export class PortalBackendError extends Error { - constructor( - message: string, - public readonly statusCode: number, - ) { - super(message); - // Set the prototype explicitly so `instanceof` works. - // https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-extending-built-ins-like-error-array-and-map-work - Object.setPrototypeOf(this, PortalBackendError.prototype); - } - - static async fromResponse(response: Response): Promise { - return new PortalBackendError(await response.text(), response.status); - } -} +import { HttpHeaders } from "../../Common/Constants"; +import { configContext } from "../../ConfigContext"; +import { AccessInputMetadata } from "../../Contracts/DataModels"; export async function fetchAccessData(portalToken: string): Promise { const headers = new Headers(); @@ -43,7 +25,7 @@ export async function fetchEncryptedToken(connectionString: string): Promise