mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2026-01-05 18:47:41 +00:00
Compare commits
12 Commits
users/sind
...
users/rbac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72eca5ed79 | ||
|
|
473a6d34bd | ||
|
|
805d72c55b | ||
|
|
eb7c737066 | ||
|
|
478467bda5 | ||
|
|
fd3a83dcd8 | ||
|
|
713df1869a | ||
|
|
192a275139 | ||
|
|
77ee359adb | ||
|
|
a50108c375 | ||
|
|
d3fb5eabdb | ||
|
|
4792e2d1c7 |
@@ -133,7 +133,6 @@ export enum MongoBackendEndpointType {
|
||||
export class BackendApi {
|
||||
public static readonly GenerateToken: string = "GenerateToken";
|
||||
public static readonly PortalSettings: string = "PortalSettings";
|
||||
public static readonly AccountRestrictions: string = "AccountRestrictions";
|
||||
}
|
||||
|
||||
export class PortalBackendEndpoints {
|
||||
@@ -186,9 +185,6 @@ export class CassandraProxyAPIs {
|
||||
export class Queries {
|
||||
public static CustomPageOption: string = "custom";
|
||||
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 unlimitedItemsPerPage: number = 100; // TODO: Figure out appropriate value so it works for accounts with a large number of partitions
|
||||
public static containersPerPage: number = 50;
|
||||
|
||||
@@ -31,18 +31,9 @@ export const tokenProvider = async (requestInfo: Cosmos.RequestInfo) => {
|
||||
}
|
||||
const AUTH_PREFIX = `type=aad&ver=1.0&sig=`;
|
||||
const authorizationToken = `${AUTH_PREFIX}${userContext.aadToken}`;
|
||||
console.log(`Returning Auth token`);
|
||||
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) {
|
||||
// TODO This SDK method mutates the headers object. Find a better one or fix the SDK.
|
||||
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) {
|
||||
// TODO This SDK method mutates the headers object. Find a better one or fix the SDK.
|
||||
await Cosmos.setAuthorizationTokenHeaderUsingMasterKey(
|
||||
@@ -133,10 +118,6 @@ export const tokenProvider = async (requestInfo: Cosmos.RequestInfo) => {
|
||||
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) => {
|
||||
requestContext.endpoint = new URL(configContext.PROXY_PATH, window.location.href).href;
|
||||
requestContext.headers["x-ms-proxy-target"] = endpoint();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { FabricMessageTypes } from "Contracts/FabricMessageTypes";
|
||||
import Q from "q";
|
||||
import * as _ from "underscore";
|
||||
import * as Logger from "../Common/Logger";
|
||||
import { MessageTypes } from "../Contracts/ExplorerContracts";
|
||||
import { getDataExplorerWindow } from "../Utils/WindowUtils";
|
||||
import * as Constants from "./Constants";
|
||||
@@ -97,18 +96,10 @@ const _sendMessage = (message: any): void => {
|
||||
const portalChildWindow = getDataExplorerWindow(window) || window;
|
||||
if (portalChildWindow === window) {
|
||||
// Current window is a child of portal, send message to portal window
|
||||
if (portalChildWindow.document.referrer) {
|
||||
portalChildWindow.parent.postMessage(message, portalChildWindow.document.referrer);
|
||||
} else {
|
||||
Logger.logError("Iframe failed to send message to portal", "MessageHandler");
|
||||
}
|
||||
portalChildWindow.parent.postMessage(message, portalChildWindow.document.referrer || "*");
|
||||
} else {
|
||||
// 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);
|
||||
} else {
|
||||
Logger.logError("Iframe failed to send message to data explorer", "MessageHandler");
|
||||
}
|
||||
portalChildWindow.postMessage(message, portalChildWindow.location.origin || "*");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -710,4 +710,3 @@ async function errorHandling(response: Response, action: string, params: unknown
|
||||
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}`;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { CosmosClient } from "@azure/cosmos";
|
||||
import { sampleDataClient } from "Common/SampleDataClient";
|
||||
import { userContext } from "UserContext";
|
||||
import * as DataModels from "../../Contracts/DataModels";
|
||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||
import { client } from "../CosmosClient";
|
||||
import { handleError } from "../ErrorHandlingUtils";
|
||||
|
||||
@@ -30,6 +31,7 @@ export async function readCollectionInternal(
|
||||
collectionId: string,
|
||||
): Promise<DataModels.Collection> {
|
||||
let collection: DataModels.Collection;
|
||||
const clearMessage = logConsoleProgress(`Querying container ${collectionId}`);
|
||||
try {
|
||||
const response = await cosmosClient.database(databaseId).container(collectionId).read();
|
||||
collection = response.resource as DataModels.Collection;
|
||||
@@ -37,5 +39,6 @@ export async function readCollectionInternal(
|
||||
handleError(error, "ReadCollection", `Error while querying container ${collectionId}`);
|
||||
throw error;
|
||||
}
|
||||
clearMessage();
|
||||
return collection;
|
||||
}
|
||||
|
||||
@@ -109,14 +109,14 @@ let configContext: Readonly<ConfigContext> = {
|
||||
PORTAL_BACKEND_ENDPOINT: PortalBackendEndpoints.Prod,
|
||||
MONGO_PROXY_ENDPOINT: MongoProxyEndpoints.Prod,
|
||||
NEW_MONGO_APIS: [
|
||||
// "resourcelist",
|
||||
// "queryDocuments",
|
||||
// "createDocument",
|
||||
// "readDocument",
|
||||
// "updateDocument",
|
||||
// "deleteDocument",
|
||||
// "createCollectionWithProxy",
|
||||
// "legacyMongoShell",
|
||||
"resourcelist",
|
||||
"queryDocuments",
|
||||
"createDocument",
|
||||
"readDocument",
|
||||
"updateDocument",
|
||||
"deleteDocument",
|
||||
"createCollectionWithProxy",
|
||||
"legacyMongoShell",
|
||||
],
|
||||
MONGO_PROXY_OUTBOUND_IPS_ALLOWLISTED: false,
|
||||
CASSANDRA_PROXY_ENDPOINT: CassandraProxyEndpoints.Prod,
|
||||
|
||||
@@ -162,7 +162,7 @@ export const addRootChildToGraph = (
|
||||
* @param value
|
||||
*/
|
||||
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
|
||||
*/
|
||||
export const escapeSingleQuotes = (value: string): string => {
|
||||
return value === undefined ? value : value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
||||
return value === undefined ? value : value.replace(/'/g, "\\'");
|
||||
};
|
||||
|
||||
@@ -576,7 +576,9 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
</TooltipHost>
|
||||
</Stack>
|
||||
|
||||
<Text variant="small">{this.getPartitionKeySubtext()}</Text>
|
||||
<Text variant="small" aria-label="pkDescription">
|
||||
{this.getPartitionKeySubtext()}
|
||||
</Text>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
|
||||
@@ -264,7 +264,7 @@ export const ChangePartitionKeyPane: React.FC<ChangePartitionKeyPaneProps> = ({
|
||||
</TooltipHost>
|
||||
</Stack>
|
||||
|
||||
<Text variant="small">
|
||||
<Text variant="small" aria-label="pkDescription">
|
||||
{getPartitionKeySubtext(userContext.features.partitionKeyDefault, userContext.apiType)}
|
||||
</Text>
|
||||
|
||||
|
||||
@@ -223,6 +223,7 @@ exports[`AddCollectionPanel should render Default properly 1`] = `
|
||||
</StyledTooltipHostBase>
|
||||
</Stack>
|
||||
<Text
|
||||
aria-label="pkDescription"
|
||||
variant="small"
|
||||
/>
|
||||
<input
|
||||
|
||||
@@ -363,24 +363,18 @@ export class CassandraAPIDataClient extends TableDataClient {
|
||||
entitiesToDelete: Entities.ITableEntity[],
|
||||
): Promise<any> {
|
||||
const query = `DELETE FROM ${collection.databaseId}.${collection.id()} WHERE `;
|
||||
const partitionKeys: CassandraTableKey[] = collection.cassandraKeys.partitionKeys;
|
||||
const partitionKeyProperty = this.getCassandraPartitionKeyProperty(collection);
|
||||
|
||||
await Promise.all(
|
||||
entitiesToDelete.map(async (currEntityToDelete: Entities.ITableEntity) => {
|
||||
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 {
|
||||
await this.queryDocuments(collection, currQuery);
|
||||
NotificationConsoleUtils.logConsoleInfo(`Successfully deleted row ${currEntityToDelete.RowKey._}`);
|
||||
@@ -755,10 +749,6 @@ export class CassandraAPIDataClient extends TableDataClient {
|
||||
CassandraProxyEndpoints.Prod,
|
||||
];
|
||||
let canAccessCassandraProxy: boolean = userContext.databaseAccount.properties.publicNetworkAccess === "Enabled";
|
||||
if (
|
||||
configContext.CASSANDRA_PROXY_ENDPOINT !== CassandraProxyEndpoints.Development &&
|
||||
userContext.databaseAccount.properties.ipRules?.length > 0
|
||||
) {
|
||||
if (
|
||||
configContext.CASSANDRA_PROXY_ENDPOINT !== CassandraProxyEndpoints.Development &&
|
||||
userContext.databaseAccount.properties.ipRules?.length > 0
|
||||
@@ -773,4 +763,3 @@ export class CassandraAPIDataClient extends TableDataClient {
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,7 +340,7 @@ describe("Documents tab (noSql API)", () => {
|
||||
isPreferredApiMongoDB: false,
|
||||
documentIds: [],
|
||||
collection: undefined,
|
||||
partitionKey: { kind: "Hash", paths: ["/foo"], version: 2 },
|
||||
partitionKey: undefined,
|
||||
onLoadStartKey: 0,
|
||||
tabTitle: "",
|
||||
onExecutionErrorChange: (isExecutionError: boolean): void => {
|
||||
|
||||
@@ -7,10 +7,7 @@ import { getErrorMessage, getErrorStack } from "Common/ErrorHandlingUtils";
|
||||
import MongoUtility from "Common/MongoUtility";
|
||||
import { StyleConstants } from "Common/StyleConstants";
|
||||
import { createDocument } from "Common/dataAccess/createDocument";
|
||||
import {
|
||||
deleteDocument as deleteNoSqlDocument,
|
||||
deleteDocuments as deleteNoSqlDocuments,
|
||||
} from "Common/dataAccess/deleteDocument";
|
||||
import { deleteDocuments as deleteNoSqlDocuments } from "Common/dataAccess/deleteDocument";
|
||||
import { queryDocuments } from "Common/dataAccess/queryDocuments";
|
||||
import { readDocument } from "Common/dataAccess/readDocument";
|
||||
import { updateDocument } from "Common/dataAccess/updateDocument";
|
||||
@@ -827,7 +824,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
||||
}, [initialDocumentContent, selectedDocumentContentBaseline, setSelectedDocumentContent]);
|
||||
|
||||
/**
|
||||
* Implementation using bulk delete NoSQL API
|
||||
* Implementation using bulk delete
|
||||
*/
|
||||
let _deleteDocuments = useCallback(
|
||||
async (toDeleteDocumentIds: DocumentId[]): Promise<DocumentId[]> => {
|
||||
@@ -837,14 +834,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
||||
tabTitle,
|
||||
});
|
||||
setIsExecuting(true);
|
||||
|
||||
// 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)
|
||||
)
|
||||
return deleteNoSqlDocuments(_collection, toDeleteDocumentIds)
|
||||
.then(
|
||||
(deletedIds) => {
|
||||
TelemetryProcessor.traceSuccess(
|
||||
@@ -1810,8 +1800,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
||||
size={tableContainerSizePx}
|
||||
columnHeaders={columnHeaders}
|
||||
isSelectionDisabled={
|
||||
(partitionKey.systemKey && !isPreferredApiMongoDB) ||
|
||||
(configContext.platform === Platform.Fabric && userContext.fabricContext?.isReadOnly)
|
||||
configContext.platform === Platform.Fabric && userContext.fabricContext?.isReadOnly
|
||||
}
|
||||
/>
|
||||
{tableItems.length > 0 && (
|
||||
|
||||
@@ -132,7 +132,7 @@ export default class MongoShellTabComponent extends Component<
|
||||
data: {
|
||||
resourceId: resourceId,
|
||||
accountName: accountName,
|
||||
mongoEndpoint: this._useMongoProxyEndpoint ? documentEndpoint : mongoEndpoint,
|
||||
mongoEndpoint: mongoEndpoint,
|
||||
authorization: authorization,
|
||||
databaseId: databaseId,
|
||||
collectionId: collectionId,
|
||||
|
||||
@@ -51,18 +51,13 @@ export const fetchEncryptedToken_ToBeDeprecated = async (connectionString: strin
|
||||
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 url = configContext.BACKEND_ENDPOINT + "/api/guest/accountrestrictions/checkconnectionstringlogin";
|
||||
const response = await fetch(url, { headers, method: "POST" });
|
||||
if (!response.ok) {
|
||||
throw response;
|
||||
}
|
||||
|
||||
return (await response.text()).toLowerCase() === "true";
|
||||
return (await response.text()) === "True";
|
||||
};
|
||||
|
||||
export const ConnectExplorer: React.FunctionComponent<Props> = ({
|
||||
|
||||
@@ -14,7 +14,6 @@ export type Features = {
|
||||
readonly enableTtl: boolean;
|
||||
readonly executeSproc: boolean;
|
||||
readonly enableAadDataPlane: boolean;
|
||||
readonly enableDataPlaneRbac: boolean;
|
||||
readonly enableResourceGraph: boolean;
|
||||
readonly enableKoResourceTree: boolean;
|
||||
readonly hostedDataExplorer: boolean;
|
||||
@@ -70,7 +69,6 @@ export function extractFeatures(given = new URLSearchParams(window.location.sear
|
||||
canExceedMaximumValue: "true" === get("canexceedmaximumvalue"),
|
||||
cosmosdb: "true" === get("cosmosdb"),
|
||||
enableAadDataPlane: "true" === get("enableaaddataplane"),
|
||||
enableDataPlaneRbac: "true" === get("enabledataplanerbac"),
|
||||
enableResourceGraph: "true" === get("enableresourcegraph"),
|
||||
enableChangeFeedPolicy: "true" === get("enablechangefeedpolicy"),
|
||||
enableFixedCollectionWithSharedThroughput: "true" === get("enablefixedcollectionwithsharedthroughput"),
|
||||
|
||||
@@ -73,7 +73,6 @@ export interface UserContext {
|
||||
readonly fabricContext?: FabricContext;
|
||||
readonly authType?: AuthType;
|
||||
readonly masterKey?: string;
|
||||
readonly listKeysFetchInProgress?: boolean;
|
||||
readonly subscriptionId?: string;
|
||||
readonly resourceGroup?: string;
|
||||
readonly databaseAccount?: DatabaseAccount;
|
||||
|
||||
@@ -164,7 +164,6 @@ export function useNewPortalBackendEndpoint(backendApi: string): boolean {
|
||||
PortalBackendEndpoints.Mpac,
|
||||
PortalBackendEndpoints.Prod,
|
||||
],
|
||||
[BackendApi.AccountRestrictions]: [PortalBackendEndpoints.Development, PortalBackendEndpoints.Mpac],
|
||||
};
|
||||
|
||||
if (!newBackendApiEnvironmentMap[backendApi] || !configContext.PORTAL_BACKEND_ENDPOINT) {
|
||||
|
||||
@@ -52,17 +52,11 @@ export async function fetchDatabaseAccountsFromGraph(
|
||||
const body = {
|
||||
query: databaseAccountsQuery,
|
||||
subscriptions: [subscriptionId],
|
||||
...(skipToken
|
||||
? {
|
||||
options: {
|
||||
$skipToken: skipToken,
|
||||
} as QueryRequestOptions,
|
||||
}
|
||||
: {
|
||||
options: {
|
||||
$top: 150,
|
||||
} as QueryRequestOptions,
|
||||
}),
|
||||
...(skipToken && {
|
||||
options: {
|
||||
$skipToken: skipToken,
|
||||
} as QueryRequestOptions,
|
||||
}),
|
||||
};
|
||||
|
||||
const response = await fetch(managementResourceGraphAPIURL, {
|
||||
|
||||
@@ -290,11 +290,6 @@ async function configureHostedWithAAD(config: AAD): Promise<Explorer> {
|
||||
}
|
||||
|
||||
updateUserContext({ dataPlaneRbacEnabled });
|
||||
} else {
|
||||
const dataPlaneRbacEnabled = account.properties.disableLocalAuth;
|
||||
|
||||
updateUserContext({ dataPlaneRbacEnabled });
|
||||
useDataPlaneRbac.setState({ dataPlaneRbacEnabled: dataPlaneRbacEnabled });
|
||||
}
|
||||
} else {
|
||||
const keys: DatabaseAccountListKeysResult = await listKeys(subscriptionId, resourceGroup, account.name);
|
||||
@@ -421,10 +416,8 @@ async function configurePortal(): Promise<Explorer> {
|
||||
updateUserContext({
|
||||
authType: AuthType.AAD,
|
||||
});
|
||||
|
||||
|
||||
let explorer: Explorer;
|
||||
return new Promise(async (resolve) => {
|
||||
return new Promise((resolve) => {
|
||||
// In development mode, try to load the iframe message from session storage.
|
||||
// This allows webpack hot reload to function properly in the portal
|
||||
if (process.env.NODE_ENV === "development" && !window.location.search.includes("disablePortalInitCache")) {
|
||||
@@ -437,8 +430,6 @@ async function configurePortal(): Promise<Explorer> {
|
||||
console.dir(message);
|
||||
updateContextsFromPortalMessage(message);
|
||||
explorer = new Explorer();
|
||||
|
||||
|
||||
// In development mode, save the iframe message from the portal in session storage.
|
||||
// This allows webpack hot reload to funciton properly
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
@@ -462,7 +453,7 @@ async function configurePortal(): Promise<Explorer> {
|
||||
|
||||
// Check for init message
|
||||
const message: PortalMessage = event.data?.data;
|
||||
const inputs = message?.inputs;
|
||||
const inputs = message?.inputs;
|
||||
const openAction = message?.openAction;
|
||||
if (inputs) {
|
||||
if (
|
||||
@@ -494,18 +485,14 @@ async function configurePortal(): Promise<Explorer> {
|
||||
dataPlaneRbacEnabled = isDataPlaneRbacSetting === Constants.RBACOptions.setTrueRBACOption;
|
||||
}
|
||||
|
||||
updateUserContext({ dataPlaneRbacEnabled });
|
||||
useDataPlaneRbac.setState({ dataPlaneRbacEnabled: dataPlaneRbacEnabled });
|
||||
} else {
|
||||
const dataPlaneRbacEnabled = account.properties.disableLocalAuth;
|
||||
|
||||
updateUserContext({ dataPlaneRbacEnabled });
|
||||
useDataPlaneRbac.setState({ dataPlaneRbacEnabled: dataPlaneRbacEnabled });
|
||||
}
|
||||
} else {
|
||||
(async () => {
|
||||
await fetchAndUpdateKeys(subscriptionId, resourceGroup, account.name);
|
||||
})();
|
||||
const keys: DatabaseAccountListKeysResult = await listKeys(subscriptionId, resourceGroup, account.name);
|
||||
updateUserContext({
|
||||
masterKey: keys.primaryMasterKey,
|
||||
});
|
||||
}
|
||||
|
||||
if (openAction) {
|
||||
@@ -528,23 +515,9 @@ async function configurePortal(): Promise<Explorer> {
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
||||
|
||||
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) {
|
||||
@@ -584,7 +557,6 @@ function updateContextsFromPortalMessage(inputs: DataExplorerInputsFrame) {
|
||||
collectionCreationDefaults: inputs.defaultCollectionThroughput,
|
||||
isTryCosmosDBSubscription: inputs.isTryCosmosDBSubscription,
|
||||
feedbackPolicies: inputs.feedbackPolicies,
|
||||
listKeysFetchInProgress: false,
|
||||
});
|
||||
|
||||
if (inputs.isPostgresAccount) {
|
||||
|
||||
@@ -51,17 +51,11 @@ export async function fetchSubscriptionsFromGraph(accessToken: string): Promise<
|
||||
do {
|
||||
const body = {
|
||||
query: subscriptionsQuery,
|
||||
...(skipToken
|
||||
? {
|
||||
options: {
|
||||
$skipToken: skipToken,
|
||||
} as QueryRequestOptions,
|
||||
}
|
||||
: {
|
||||
options: {
|
||||
$top: 150,
|
||||
} as QueryRequestOptions,
|
||||
}),
|
||||
...(skipToken && {
|
||||
options: {
|
||||
$skipToken: skipToken,
|
||||
} as QueryRequestOptions,
|
||||
}),
|
||||
};
|
||||
|
||||
const response = await fetch(managementResourceGraphAPIURL, {
|
||||
|
||||
@@ -16,7 +16,7 @@ test("Tables CRUD", async ({ page }) => {
|
||||
|
||||
const databaseNode = explorer.treeNode("DATA/TablesDB");
|
||||
await databaseNode.expand();
|
||||
|
||||
|
||||
const tableNode = explorer.treeNode(`DATA/TablesDB/${tableId}`);
|
||||
await expect(tableNode.element).toBeAttached();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user