mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2026-04-19 12:59:12 +01:00
116 lines
3.5 KiB
TypeScript
116 lines
3.5 KiB
TypeScript
import { configContext } from "ConfigContext";
|
|
import { buildArmUrl } from "Utils/arm/armUtils";
|
|
import { armRequest } from "Utils/arm/request";
|
|
import { getCopyJobAuthorizationHeader } from "../CopyJobAuthUtils";
|
|
|
|
export type FetchAccountDetailsParams = {
|
|
subscriptionId: string;
|
|
resourceGroupName: string;
|
|
accountName: string;
|
|
};
|
|
|
|
export type RoleAssignmentPropertiesType = {
|
|
roleDefinitionId: string;
|
|
principalId: string;
|
|
scope: string;
|
|
};
|
|
|
|
export type RoleAssignmentType = {
|
|
id: string;
|
|
name: string;
|
|
properties: RoleAssignmentPropertiesType;
|
|
type: string;
|
|
};
|
|
|
|
type RoleDefinitionDataActions = {
|
|
dataActions: string[];
|
|
};
|
|
|
|
export type RoleDefinitionType = {
|
|
assignableScopes: string[];
|
|
id: string;
|
|
name: string;
|
|
permissions: RoleDefinitionDataActions[];
|
|
resourceGroup: string;
|
|
roleName: string;
|
|
type: string;
|
|
typePropertiesType: string;
|
|
};
|
|
|
|
const apiVersion = "2025-04-15";
|
|
|
|
const handleResponse = async (response: Response, context: string) => {
|
|
if (!response.ok) {
|
|
const body = await response.text().catch(() => "");
|
|
throw new Error(`Failed to fetch ${context}. Status: ${response.status}. ${body || ""}`);
|
|
}
|
|
return response.json();
|
|
};
|
|
|
|
export const fetchRoleAssignments = async (
|
|
subscriptionId: string,
|
|
resourceGroupName: string,
|
|
accountName: string,
|
|
principalId: string,
|
|
): Promise<RoleAssignmentType[]> => {
|
|
const uri = buildArmUrl(
|
|
`/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlRoleAssignments`,
|
|
apiVersion,
|
|
);
|
|
|
|
const response = await fetch(uri, { method: "GET", headers: getCopyJobAuthorizationHeader() });
|
|
const data = await handleResponse(response, "role assignments");
|
|
|
|
return (data.value || []).filter(
|
|
(assignment: RoleAssignmentType) => assignment?.properties?.principalId === principalId,
|
|
);
|
|
};
|
|
|
|
export const fetchRoleDefinitions = async (roleAssignments: RoleAssignmentType[]): Promise<RoleDefinitionType[]> => {
|
|
const roleDefinitionIds = roleAssignments.map((assignment) => assignment.properties.roleDefinitionId);
|
|
const uniqueRoleDefinitionIds = Array.from(new Set(roleDefinitionIds));
|
|
|
|
const headers = getCopyJobAuthorizationHeader();
|
|
const roleDefinitionUris = uniqueRoleDefinitionIds.map((id) => buildArmUrl(id, apiVersion));
|
|
|
|
const promises = roleDefinitionUris.map((url) => fetch(url, { method: "GET", headers }));
|
|
const responses = await Promise.all(promises);
|
|
|
|
const roleDefinitions = await Promise.all(
|
|
responses.map((res, i) => handleResponse(res, `role definition ${uniqueRoleDefinitionIds[i]}`)),
|
|
);
|
|
|
|
return roleDefinitions;
|
|
};
|
|
|
|
export const assignRole = async (
|
|
subscriptionId: string,
|
|
resourceGroupName: string,
|
|
accountName: string,
|
|
principalId: string,
|
|
): Promise<RoleAssignmentType | null> => {
|
|
if (!principalId) {
|
|
return null;
|
|
}
|
|
const accountScope = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}`;
|
|
const roleDefinitionId = `${accountScope}/sqlRoleDefinitions/00000000-0000-0000-0000-000000000002`; // Built-in Contributor role definition ID for Cosmos DB
|
|
const roleAssignmentName = crypto.randomUUID();
|
|
const path = `${accountScope}/sqlRoleAssignments/${roleAssignmentName}`;
|
|
|
|
const body = {
|
|
properties: {
|
|
roleDefinitionId,
|
|
scope: `${accountScope}/`,
|
|
principalId,
|
|
},
|
|
};
|
|
const response: RoleAssignmentType = await armRequest({
|
|
host: configContext.ARM_ENDPOINT,
|
|
path,
|
|
method: "PUT",
|
|
apiVersion,
|
|
body,
|
|
});
|
|
return response;
|
|
};
|