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 => { 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 => { 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 => { 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; };