Compare commits

..

12 Commits

Author SHA1 Message Date
Senthamil Sindhu
72eca5ed79 Fix Tables test 2024-06-28 10:49:01 -07:00
Senthamil Sindhu
473a6d34bd Add new fixes 2024-06-27 23:20:05 -07:00
Senthamil Sindhu
805d72c55b Minor fix 2024-06-27 09:49:00 -07:00
Senthamil Sindhu
eb7c737066 Address feedback comments 2024-06-27 09:37:08 -07:00
Senthamil Sindhu
478467bda5 Fix enable AAD dataplane feature flag behavior 2024-06-25 16:27:40 -07:00
Senthamil Sindhu
fd3a83dcd8 Fix enableAadDataPlane feature flag behavior 2024-06-25 15:37:08 -07:00
Senthamil Sindhu
713df1869a Run npm format 2024-06-25 12:15:59 -07:00
Senthamil Sindhu
192a275139 Remove unnecessary code 2024-06-25 12:09:43 -07:00
Senthamil Sindhu
77ee359adb Fix unit tests 2024-06-25 10:23:01 -07:00
Senthamil Sindhu
a50108c375 Run format 2024-06-25 09:59:21 -07:00
Senthamil Sindhu
d3fb5eabdb Cleanup DP RBAC code 2024-06-25 09:28:08 -07:00
Senthamil Sindhu
4792e2d1c7 Address errors and checks 2024-06-19 21:00:55 -07:00
22 changed files with 54 additions and 152 deletions

View File

@@ -133,7 +133,6 @@ export enum MongoBackendEndpointType {
export class BackendApi { export class BackendApi {
public static readonly GenerateToken: string = "GenerateToken"; public static readonly GenerateToken: string = "GenerateToken";
public static readonly PortalSettings: string = "PortalSettings"; public static readonly PortalSettings: string = "PortalSettings";
public static readonly AccountRestrictions: string = "AccountRestrictions";
} }
export class PortalBackendEndpoints { export class PortalBackendEndpoints {
@@ -186,9 +185,6 @@ export class CassandraProxyAPIs {
export class Queries { export class Queries {
public static CustomPageOption: string = "custom"; public static CustomPageOption: string = "custom";
public static UnlimitedPageOption: string = "unlimited"; public static UnlimitedPageOption: string = "unlimited";
public static setAutomaticRBACOption: string = "Automatic";
public static setTrueRBACOption: string = "True";
public static setFalseRBACOption: string = "False";
public static itemsPerPage: number = 100; public static itemsPerPage: number = 100;
public static unlimitedItemsPerPage: number = 100; // TODO: Figure out appropriate value so it works for accounts with a large number of partitions public static unlimitedItemsPerPage: number = 100; // TODO: Figure out appropriate value so it works for accounts with a large number of partitions
public static containersPerPage: number = 50; public static containersPerPage: number = 50;

View File

@@ -31,18 +31,9 @@ export const tokenProvider = async (requestInfo: Cosmos.RequestInfo) => {
} }
const AUTH_PREFIX = `type=aad&ver=1.0&sig=`; const AUTH_PREFIX = `type=aad&ver=1.0&sig=`;
const authorizationToken = `${AUTH_PREFIX}${userContext.aadToken}`; const authorizationToken = `${AUTH_PREFIX}${userContext.aadToken}`;
console.log(`Returning Auth token`);
return authorizationToken; return authorizationToken;
} }
if ((userContext.dataPlaneRbacEnabled) && userContext.authorizationToken) {
console.log(` Getting Portal Auth token `)
const AUTH_PREFIX = `type=aad&ver=1.0&sig=`;
const authorizationToken = `${AUTH_PREFIX}${userContext.authorizationToken}`;
console.log(`Returning Portal Auth token`);
return authorizationToken;
}
if (configContext.platform === Platform.Emulator) { if (configContext.platform === Platform.Emulator) {
// TODO This SDK method mutates the headers object. Find a better one or fix the SDK. // TODO This SDK method mutates the headers object. Find a better one or fix the SDK.
await Cosmos.setAuthorizationTokenHeaderUsingMasterKey(verb, resourceId, resourceType, headers, EmulatorMasterKey); await Cosmos.setAuthorizationTokenHeaderUsingMasterKey(verb, resourceId, resourceType, headers, EmulatorMasterKey);
@@ -90,12 +81,6 @@ export const tokenProvider = async (requestInfo: Cosmos.RequestInfo) => {
} }
} }
let retryAttempts: number = 50;
while (retryAttempts > 0 && userContext.listKeysFetchInProgress) {
retryAttempts--;
await sleep(100);
}
if (userContext.masterKey) { if (userContext.masterKey) {
// TODO This SDK method mutates the headers object. Find a better one or fix the SDK. // TODO This SDK method mutates the headers object. Find a better one or fix the SDK.
await Cosmos.setAuthorizationTokenHeaderUsingMasterKey( await Cosmos.setAuthorizationTokenHeaderUsingMasterKey(
@@ -133,10 +118,6 @@ export const tokenProvider = async (requestInfo: Cosmos.RequestInfo) => {
return decodeURIComponent(result.PrimaryReadWriteToken); return decodeURIComponent(result.PrimaryReadWriteToken);
}; };
function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
export const requestPlugin: Cosmos.Plugin<any> = async (requestContext, diagnosticNode, next) => { export const requestPlugin: Cosmos.Plugin<any> = async (requestContext, diagnosticNode, next) => {
requestContext.endpoint = new URL(configContext.PROXY_PATH, window.location.href).href; requestContext.endpoint = new URL(configContext.PROXY_PATH, window.location.href).href;
requestContext.headers["x-ms-proxy-target"] = endpoint(); requestContext.headers["x-ms-proxy-target"] = endpoint();

View File

@@ -1,7 +1,6 @@
import { FabricMessageTypes } from "Contracts/FabricMessageTypes"; import { FabricMessageTypes } from "Contracts/FabricMessageTypes";
import Q from "q"; import Q from "q";
import * as _ from "underscore"; import * as _ from "underscore";
import * as Logger from "../Common/Logger";
import { MessageTypes } from "../Contracts/ExplorerContracts"; import { MessageTypes } from "../Contracts/ExplorerContracts";
import { getDataExplorerWindow } from "../Utils/WindowUtils"; import { getDataExplorerWindow } from "../Utils/WindowUtils";
import * as Constants from "./Constants"; import * as Constants from "./Constants";
@@ -97,18 +96,10 @@ const _sendMessage = (message: any): void => {
const portalChildWindow = getDataExplorerWindow(window) || window; const portalChildWindow = getDataExplorerWindow(window) || window;
if (portalChildWindow === window) { if (portalChildWindow === window) {
// Current window is a child of portal, send message to portal window // Current window is a child of portal, send message to portal window
if (portalChildWindow.document.referrer) { portalChildWindow.parent.postMessage(message, portalChildWindow.document.referrer || "*");
portalChildWindow.parent.postMessage(message, portalChildWindow.document.referrer);
} else {
Logger.logError("Iframe failed to send message to portal", "MessageHandler");
}
} else { } else {
// Current window is not a child of portal, send message to the child window instead (which is data explorer) // Current window is not a child of portal, send message to the child window instead (which is data explorer)
if (portalChildWindow.location.origin) { portalChildWindow.postMessage(message, portalChildWindow.location.origin || "*");
portalChildWindow.postMessage(message, portalChildWindow.location.origin);
} else {
Logger.logError("Iframe failed to send message to data explorer", "MessageHandler");
}
} }
} }
}; };

View File

@@ -710,4 +710,3 @@ async function errorHandling(response: Response, action: string, params: unknown
export function getARMCreateCollectionEndpoint(params: DataModels.MongoParameters): string { export function getARMCreateCollectionEndpoint(params: DataModels.MongoParameters): string {
return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${userContext.databaseAccount.name}/mongodbDatabases/${params.db}/collections/${params.coll}`; return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${userContext.databaseAccount.name}/mongodbDatabases/${params.db}/collections/${params.coll}`;
} }

View File

@@ -2,6 +2,7 @@ import { CosmosClient } from "@azure/cosmos";
import { sampleDataClient } from "Common/SampleDataClient"; import { sampleDataClient } from "Common/SampleDataClient";
import { userContext } from "UserContext"; import { userContext } from "UserContext";
import * as DataModels from "../../Contracts/DataModels"; import * as DataModels from "../../Contracts/DataModels";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client } from "../CosmosClient"; import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils"; import { handleError } from "../ErrorHandlingUtils";
@@ -30,6 +31,7 @@ export async function readCollectionInternal(
collectionId: string, collectionId: string,
): Promise<DataModels.Collection> { ): Promise<DataModels.Collection> {
let collection: DataModels.Collection; let collection: DataModels.Collection;
const clearMessage = logConsoleProgress(`Querying container ${collectionId}`);
try { try {
const response = await cosmosClient.database(databaseId).container(collectionId).read(); const response = await cosmosClient.database(databaseId).container(collectionId).read();
collection = response.resource as DataModels.Collection; collection = response.resource as DataModels.Collection;
@@ -37,5 +39,6 @@ export async function readCollectionInternal(
handleError(error, "ReadCollection", `Error while querying container ${collectionId}`); handleError(error, "ReadCollection", `Error while querying container ${collectionId}`);
throw error; throw error;
} }
clearMessage();
return collection; return collection;
} }

View File

@@ -109,14 +109,14 @@ let configContext: Readonly<ConfigContext> = {
PORTAL_BACKEND_ENDPOINT: PortalBackendEndpoints.Prod, PORTAL_BACKEND_ENDPOINT: PortalBackendEndpoints.Prod,
MONGO_PROXY_ENDPOINT: MongoProxyEndpoints.Prod, MONGO_PROXY_ENDPOINT: MongoProxyEndpoints.Prod,
NEW_MONGO_APIS: [ NEW_MONGO_APIS: [
// "resourcelist", "resourcelist",
// "queryDocuments", "queryDocuments",
// "createDocument", "createDocument",
// "readDocument", "readDocument",
// "updateDocument", "updateDocument",
// "deleteDocument", "deleteDocument",
// "createCollectionWithProxy", "createCollectionWithProxy",
// "legacyMongoShell", "legacyMongoShell",
], ],
MONGO_PROXY_OUTBOUND_IPS_ALLOWLISTED: false, MONGO_PROXY_OUTBOUND_IPS_ALLOWLISTED: false,
CASSANDRA_PROXY_ENDPOINT: CassandraProxyEndpoints.Prod, CASSANDRA_PROXY_ENDPOINT: CassandraProxyEndpoints.Prod,

View File

@@ -162,7 +162,7 @@ export const addRootChildToGraph = (
* @param value * @param value
*/ */
export const escapeDoubleQuotes = (value: string): string => { export const escapeDoubleQuotes = (value: string): string => {
return value === undefined ? value : value.replace(/\\/g, "\\\\").replace(/"/g, '\\"'); return value === undefined ? value : value.replace(/"/g, '\\"');
}; };
/** /**
@@ -186,5 +186,5 @@ export const getQuotedPropValue = (ip: ViewModels.InputPropertyValue): string =>
* @param value * @param value
*/ */
export const escapeSingleQuotes = (value: string): string => { export const escapeSingleQuotes = (value: string): string => {
return value === undefined ? value : value.replace(/\\/g, "\\\\").replace(/'/g, "\\'"); return value === undefined ? value : value.replace(/'/g, "\\'");
}; };

View File

@@ -576,7 +576,9 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
</TooltipHost> </TooltipHost>
</Stack> </Stack>
<Text variant="small">{this.getPartitionKeySubtext()}</Text> <Text variant="small" aria-label="pkDescription">
{this.getPartitionKeySubtext()}
</Text>
<input <input
type="text" type="text"

View File

@@ -264,7 +264,7 @@ export const ChangePartitionKeyPane: React.FC<ChangePartitionKeyPaneProps> = ({
</TooltipHost> </TooltipHost>
</Stack> </Stack>
<Text variant="small"> <Text variant="small" aria-label="pkDescription">
{getPartitionKeySubtext(userContext.features.partitionKeyDefault, userContext.apiType)} {getPartitionKeySubtext(userContext.features.partitionKeyDefault, userContext.apiType)}
</Text> </Text>

View File

@@ -223,6 +223,7 @@ exports[`AddCollectionPanel should render Default properly 1`] = `
</StyledTooltipHostBase> </StyledTooltipHostBase>
</Stack> </Stack>
<Text <Text
aria-label="pkDescription"
variant="small" variant="small"
/> />
<input <input

View File

@@ -363,24 +363,18 @@ export class CassandraAPIDataClient extends TableDataClient {
entitiesToDelete: Entities.ITableEntity[], entitiesToDelete: Entities.ITableEntity[],
): Promise<any> { ): Promise<any> {
const query = `DELETE FROM ${collection.databaseId}.${collection.id()} WHERE `; const query = `DELETE FROM ${collection.databaseId}.${collection.id()} WHERE `;
const partitionKeys: CassandraTableKey[] = collection.cassandraKeys.partitionKeys; const partitionKeyProperty = this.getCassandraPartitionKeyProperty(collection);
await Promise.all( await Promise.all(
entitiesToDelete.map(async (currEntityToDelete: Entities.ITableEntity) => { entitiesToDelete.map(async (currEntityToDelete: Entities.ITableEntity) => {
const clearMessage = NotificationConsoleUtils.logConsoleProgress(`Deleting row ${currEntityToDelete.RowKey._}`); const clearMessage = NotificationConsoleUtils.logConsoleProgress(`Deleting row ${currEntityToDelete.RowKey._}`);
const partitionKeyValue = currEntityToDelete[partitionKeyProperty];
const currQuery =
query +
(this.isStringType(partitionKeyValue.$)
? `${partitionKeyProperty} = '${partitionKeyValue._}'`
: `${partitionKeyProperty} = ${partitionKeyValue._}`);
let currQuery = query;
for (let partitionKeyIndex = 0; partitionKeyIndex < partitionKeys.length; partitionKeyIndex++) {
const partitionKey: CassandraTableKey = partitionKeys[partitionKeyIndex];
const partitionKeyValue: Entities.ITableEntityAttribute = currEntityToDelete[partitionKey.property];
currQuery =
currQuery +
(this.isStringType(partitionKeyValue.$)
? `${partitionKey.property} = '${partitionKeyValue._}'`
: `${partitionKey.property} = ${partitionKeyValue._}`);
if (partitionKeyIndex < partitionKeys.length - 1) {
currQuery = `${currQuery} AND `;
}
}
try { try {
await this.queryDocuments(collection, currQuery); await this.queryDocuments(collection, currQuery);
NotificationConsoleUtils.logConsoleInfo(`Successfully deleted row ${currEntityToDelete.RowKey._}`); NotificationConsoleUtils.logConsoleInfo(`Successfully deleted row ${currEntityToDelete.RowKey._}`);
@@ -755,10 +749,6 @@ export class CassandraAPIDataClient extends TableDataClient {
CassandraProxyEndpoints.Prod, CassandraProxyEndpoints.Prod,
]; ];
let canAccessCassandraProxy: boolean = userContext.databaseAccount.properties.publicNetworkAccess === "Enabled"; let canAccessCassandraProxy: boolean = userContext.databaseAccount.properties.publicNetworkAccess === "Enabled";
if (
configContext.CASSANDRA_PROXY_ENDPOINT !== CassandraProxyEndpoints.Development &&
userContext.databaseAccount.properties.ipRules?.length > 0
) {
if ( if (
configContext.CASSANDRA_PROXY_ENDPOINT !== CassandraProxyEndpoints.Development && configContext.CASSANDRA_PROXY_ENDPOINT !== CassandraProxyEndpoints.Development &&
userContext.databaseAccount.properties.ipRules?.length > 0 userContext.databaseAccount.properties.ipRules?.length > 0
@@ -773,4 +763,3 @@ export class CassandraAPIDataClient extends TableDataClient {
); );
} }
} }
}

View File

@@ -340,7 +340,7 @@ describe("Documents tab (noSql API)", () => {
isPreferredApiMongoDB: false, isPreferredApiMongoDB: false,
documentIds: [], documentIds: [],
collection: undefined, collection: undefined,
partitionKey: { kind: "Hash", paths: ["/foo"], version: 2 }, partitionKey: undefined,
onLoadStartKey: 0, onLoadStartKey: 0,
tabTitle: "", tabTitle: "",
onExecutionErrorChange: (isExecutionError: boolean): void => { onExecutionErrorChange: (isExecutionError: boolean): void => {

View File

@@ -7,10 +7,7 @@ import { getErrorMessage, getErrorStack } from "Common/ErrorHandlingUtils";
import MongoUtility from "Common/MongoUtility"; import MongoUtility from "Common/MongoUtility";
import { StyleConstants } from "Common/StyleConstants"; import { StyleConstants } from "Common/StyleConstants";
import { createDocument } from "Common/dataAccess/createDocument"; import { createDocument } from "Common/dataAccess/createDocument";
import { import { deleteDocuments as deleteNoSqlDocuments } from "Common/dataAccess/deleteDocument";
deleteDocument as deleteNoSqlDocument,
deleteDocuments as deleteNoSqlDocuments,
} from "Common/dataAccess/deleteDocument";
import { queryDocuments } from "Common/dataAccess/queryDocuments"; import { queryDocuments } from "Common/dataAccess/queryDocuments";
import { readDocument } from "Common/dataAccess/readDocument"; import { readDocument } from "Common/dataAccess/readDocument";
import { updateDocument } from "Common/dataAccess/updateDocument"; import { updateDocument } from "Common/dataAccess/updateDocument";
@@ -827,7 +824,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
}, [initialDocumentContent, selectedDocumentContentBaseline, setSelectedDocumentContent]); }, [initialDocumentContent, selectedDocumentContentBaseline, setSelectedDocumentContent]);
/** /**
* Implementation using bulk delete NoSQL API * Implementation using bulk delete
*/ */
let _deleteDocuments = useCallback( let _deleteDocuments = useCallback(
async (toDeleteDocumentIds: DocumentId[]): Promise<DocumentId[]> => { async (toDeleteDocumentIds: DocumentId[]): Promise<DocumentId[]> => {
@@ -837,14 +834,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
tabTitle, tabTitle,
}); });
setIsExecuting(true); setIsExecuting(true);
return deleteNoSqlDocuments(_collection, toDeleteDocumentIds)
// TODO: Once JS SDK Bug fix for bulk deleting legacy containers (whose systemKey==1) is released:
// Remove the check for systemKey, remove call to deleteNoSqlDocument(). deleteNoSqlDocuments() should always be called.
return (
partitionKey.systemKey
? deleteNoSqlDocument(_collection, toDeleteDocumentIds[0]).then(() => [toDeleteDocumentIds[0]])
: deleteNoSqlDocuments(_collection, toDeleteDocumentIds)
)
.then( .then(
(deletedIds) => { (deletedIds) => {
TelemetryProcessor.traceSuccess( TelemetryProcessor.traceSuccess(
@@ -1810,8 +1800,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
size={tableContainerSizePx} size={tableContainerSizePx}
columnHeaders={columnHeaders} columnHeaders={columnHeaders}
isSelectionDisabled={ isSelectionDisabled={
(partitionKey.systemKey && !isPreferredApiMongoDB) || configContext.platform === Platform.Fabric && userContext.fabricContext?.isReadOnly
(configContext.platform === Platform.Fabric && userContext.fabricContext?.isReadOnly)
} }
/> />
{tableItems.length > 0 && ( {tableItems.length > 0 && (

View File

@@ -132,7 +132,7 @@ export default class MongoShellTabComponent extends Component<
data: { data: {
resourceId: resourceId, resourceId: resourceId,
accountName: accountName, accountName: accountName,
mongoEndpoint: this._useMongoProxyEndpoint ? documentEndpoint : mongoEndpoint, mongoEndpoint: mongoEndpoint,
authorization: authorization, authorization: authorization,
databaseId: databaseId, databaseId: databaseId,
collectionId: collectionId, collectionId: collectionId,

View File

@@ -51,18 +51,13 @@ export const fetchEncryptedToken_ToBeDeprecated = async (connectionString: strin
export const isAccountRestrictedForConnectionStringLogin = async (connectionString: string): Promise<boolean> => { export const isAccountRestrictedForConnectionStringLogin = async (connectionString: string): Promise<boolean> => {
const headers = new Headers(); const headers = new Headers();
headers.append(HttpHeaders.connectionString, connectionString); headers.append(HttpHeaders.connectionString, connectionString);
const url = configContext.BACKEND_ENDPOINT + "/api/guest/accountrestrictions/checkconnectionstringlogin";
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" }); const response = await fetch(url, { headers, method: "POST" });
if (!response.ok) { if (!response.ok) {
throw response; throw response;
} }
return (await response.text()).toLowerCase() === "true"; return (await response.text()) === "True";
}; };
export const ConnectExplorer: React.FunctionComponent<Props> = ({ export const ConnectExplorer: React.FunctionComponent<Props> = ({

View File

@@ -14,7 +14,6 @@ export type Features = {
readonly enableTtl: boolean; readonly enableTtl: boolean;
readonly executeSproc: boolean; readonly executeSproc: boolean;
readonly enableAadDataPlane: boolean; readonly enableAadDataPlane: boolean;
readonly enableDataPlaneRbac: boolean;
readonly enableResourceGraph: boolean; readonly enableResourceGraph: boolean;
readonly enableKoResourceTree: boolean; readonly enableKoResourceTree: boolean;
readonly hostedDataExplorer: boolean; readonly hostedDataExplorer: boolean;
@@ -70,7 +69,6 @@ export function extractFeatures(given = new URLSearchParams(window.location.sear
canExceedMaximumValue: "true" === get("canexceedmaximumvalue"), canExceedMaximumValue: "true" === get("canexceedmaximumvalue"),
cosmosdb: "true" === get("cosmosdb"), cosmosdb: "true" === get("cosmosdb"),
enableAadDataPlane: "true" === get("enableaaddataplane"), enableAadDataPlane: "true" === get("enableaaddataplane"),
enableDataPlaneRbac: "true" === get("enabledataplanerbac"),
enableResourceGraph: "true" === get("enableresourcegraph"), enableResourceGraph: "true" === get("enableresourcegraph"),
enableChangeFeedPolicy: "true" === get("enablechangefeedpolicy"), enableChangeFeedPolicy: "true" === get("enablechangefeedpolicy"),
enableFixedCollectionWithSharedThroughput: "true" === get("enablefixedcollectionwithsharedthroughput"), enableFixedCollectionWithSharedThroughput: "true" === get("enablefixedcollectionwithsharedthroughput"),

View File

@@ -73,7 +73,6 @@ export interface UserContext {
readonly fabricContext?: FabricContext; readonly fabricContext?: FabricContext;
readonly authType?: AuthType; readonly authType?: AuthType;
readonly masterKey?: string; readonly masterKey?: string;
readonly listKeysFetchInProgress?: boolean;
readonly subscriptionId?: string; readonly subscriptionId?: string;
readonly resourceGroup?: string; readonly resourceGroup?: string;
readonly databaseAccount?: DatabaseAccount; readonly databaseAccount?: DatabaseAccount;

View File

@@ -164,7 +164,6 @@ export function useNewPortalBackendEndpoint(backendApi: string): boolean {
PortalBackendEndpoints.Mpac, PortalBackendEndpoints.Mpac,
PortalBackendEndpoints.Prod, PortalBackendEndpoints.Prod,
], ],
[BackendApi.AccountRestrictions]: [PortalBackendEndpoints.Development, PortalBackendEndpoints.Mpac],
}; };
if (!newBackendApiEnvironmentMap[backendApi] || !configContext.PORTAL_BACKEND_ENDPOINT) { if (!newBackendApiEnvironmentMap[backendApi] || !configContext.PORTAL_BACKEND_ENDPOINT) {

View File

@@ -52,17 +52,11 @@ export async function fetchDatabaseAccountsFromGraph(
const body = { const body = {
query: databaseAccountsQuery, query: databaseAccountsQuery,
subscriptions: [subscriptionId], subscriptions: [subscriptionId],
...(skipToken ...(skipToken && {
? { options: {
options: { $skipToken: skipToken,
$skipToken: skipToken, } as QueryRequestOptions,
} as QueryRequestOptions, }),
}
: {
options: {
$top: 150,
} as QueryRequestOptions,
}),
}; };
const response = await fetch(managementResourceGraphAPIURL, { const response = await fetch(managementResourceGraphAPIURL, {

View File

@@ -290,11 +290,6 @@ async function configureHostedWithAAD(config: AAD): Promise<Explorer> {
} }
updateUserContext({ dataPlaneRbacEnabled }); updateUserContext({ dataPlaneRbacEnabled });
} else {
const dataPlaneRbacEnabled = account.properties.disableLocalAuth;
updateUserContext({ dataPlaneRbacEnabled });
useDataPlaneRbac.setState({ dataPlaneRbacEnabled: dataPlaneRbacEnabled });
} }
} else { } else {
const keys: DatabaseAccountListKeysResult = await listKeys(subscriptionId, resourceGroup, account.name); const keys: DatabaseAccountListKeysResult = await listKeys(subscriptionId, resourceGroup, account.name);
@@ -421,10 +416,8 @@ async function configurePortal(): Promise<Explorer> {
updateUserContext({ updateUserContext({
authType: AuthType.AAD, authType: AuthType.AAD,
}); });
let explorer: Explorer; let explorer: Explorer;
return new Promise(async (resolve) => { return new Promise((resolve) => {
// In development mode, try to load the iframe message from session storage. // In development mode, try to load the iframe message from session storage.
// This allows webpack hot reload to function properly in the portal // This allows webpack hot reload to function properly in the portal
if (process.env.NODE_ENV === "development" && !window.location.search.includes("disablePortalInitCache")) { if (process.env.NODE_ENV === "development" && !window.location.search.includes("disablePortalInitCache")) {
@@ -437,8 +430,6 @@ async function configurePortal(): Promise<Explorer> {
console.dir(message); console.dir(message);
updateContextsFromPortalMessage(message); updateContextsFromPortalMessage(message);
explorer = new Explorer(); explorer = new Explorer();
// In development mode, save the iframe message from the portal in session storage. // In development mode, save the iframe message from the portal in session storage.
// This allows webpack hot reload to funciton properly // This allows webpack hot reload to funciton properly
if (process.env.NODE_ENV === "development") { if (process.env.NODE_ENV === "development") {
@@ -462,7 +453,7 @@ async function configurePortal(): Promise<Explorer> {
// Check for init message // Check for init message
const message: PortalMessage = event.data?.data; const message: PortalMessage = event.data?.data;
const inputs = message?.inputs; const inputs = message?.inputs;
const openAction = message?.openAction; const openAction = message?.openAction;
if (inputs) { if (inputs) {
if ( if (
@@ -494,18 +485,14 @@ async function configurePortal(): Promise<Explorer> {
dataPlaneRbacEnabled = isDataPlaneRbacSetting === Constants.RBACOptions.setTrueRBACOption; dataPlaneRbacEnabled = isDataPlaneRbacSetting === Constants.RBACOptions.setTrueRBACOption;
} }
updateUserContext({ dataPlaneRbacEnabled });
useDataPlaneRbac.setState({ dataPlaneRbacEnabled: dataPlaneRbacEnabled });
} else {
const dataPlaneRbacEnabled = account.properties.disableLocalAuth;
updateUserContext({ dataPlaneRbacEnabled }); updateUserContext({ dataPlaneRbacEnabled });
useDataPlaneRbac.setState({ dataPlaneRbacEnabled: dataPlaneRbacEnabled }); useDataPlaneRbac.setState({ dataPlaneRbacEnabled: dataPlaneRbacEnabled });
} }
} else { } else {
(async () => { const keys: DatabaseAccountListKeysResult = await listKeys(subscriptionId, resourceGroup, account.name);
await fetchAndUpdateKeys(subscriptionId, resourceGroup, account.name); updateUserContext({
})(); masterKey: keys.primaryMasterKey,
});
} }
if (openAction) { if (openAction) {
@@ -528,23 +515,9 @@ async function configurePortal(): Promise<Explorer> {
}, },
false, false,
); );
sendReadyMessage(); sendReadyMessage();
}); });
}
async function fetchAndUpdateKeys(subscriptionId: string, resourceGroup: string, account: string) {
try {
updateUserContext({ listKeysFetchInProgress: true });
const keys = await listKeys(subscriptionId, resourceGroup, account);
updateUserContext({ masterKey: keys.primaryMasterKey, listKeysFetchInProgress: false });
} catch (error) {
updateUserContext({ listKeysFetchInProgress: false });
console.error("Error during fetching keys or updating user context:", error);
}
} }
function shouldForwardMessage(message: PortalMessage, messageOrigin: string) { function shouldForwardMessage(message: PortalMessage, messageOrigin: string) {
@@ -584,7 +557,6 @@ function updateContextsFromPortalMessage(inputs: DataExplorerInputsFrame) {
collectionCreationDefaults: inputs.defaultCollectionThroughput, collectionCreationDefaults: inputs.defaultCollectionThroughput,
isTryCosmosDBSubscription: inputs.isTryCosmosDBSubscription, isTryCosmosDBSubscription: inputs.isTryCosmosDBSubscription,
feedbackPolicies: inputs.feedbackPolicies, feedbackPolicies: inputs.feedbackPolicies,
listKeysFetchInProgress: false,
}); });
if (inputs.isPostgresAccount) { if (inputs.isPostgresAccount) {

View File

@@ -51,17 +51,11 @@ export async function fetchSubscriptionsFromGraph(accessToken: string): Promise<
do { do {
const body = { const body = {
query: subscriptionsQuery, query: subscriptionsQuery,
...(skipToken ...(skipToken && {
? { options: {
options: { $skipToken: skipToken,
$skipToken: skipToken, } as QueryRequestOptions,
} as QueryRequestOptions, }),
}
: {
options: {
$top: 150,
} as QueryRequestOptions,
}),
}; };
const response = await fetch(managementResourceGraphAPIURL, { const response = await fetch(managementResourceGraphAPIURL, {

View File

@@ -16,7 +16,7 @@ test("Tables CRUD", async ({ page }) => {
const databaseNode = explorer.treeNode("DATA/TablesDB"); const databaseNode = explorer.treeNode("DATA/TablesDB");
await databaseNode.expand(); await databaseNode.expand();
const tableNode = explorer.treeNode(`DATA/TablesDB/${tableId}`); const tableNode = explorer.treeNode(`DATA/TablesDB/${tableId}`);
await expect(tableNode.element).toBeAttached(); await expect(tableNode.element).toBeAttached();