feat(graph): add --resolve for list-app-permissions

This commit is contained in:
2026-02-08 13:19:50 +01:00
parent 2474fa79d3
commit 61111cc082
2 changed files with 93 additions and 3 deletions

View File

@@ -84,6 +84,87 @@ export async function listAppPermissions(client, appId) {
: [];
}
/**
* List required resource access in a resolved, human-readable form.
*
* @param { Object } client
* @param { string } appId
* @returns { Promise<Array> }
*/
export async function listAppPermissionsResolved(client, appId) {
const requiredResourceAccess = await listAppPermissions(client, appId);
if (!Array.isArray(requiredResourceAccess) || requiredResourceAccess.length === 0) {
return [];
}
const resourceAppIds = [...new Set(
requiredResourceAccess
.map((entry) => entry?.resourceAppId)
.filter(Boolean),
)];
const resourceDefinitions = await Promise.all(resourceAppIds.map(async (resourceAppId) => {
const result = await client
.api("/servicePrincipals")
.filter(`appId eq '${resourceAppId}'`)
.select("appId,displayName,oauth2PermissionScopes,appRoles")
.get();
const sp = Array.isArray(result?.value) && result.value.length > 0
? result.value[0]
: null;
const scopesById = new Map(
(sp?.oauth2PermissionScopes ?? []).map((scope) => [scope.id, scope]),
);
const rolesById = new Map(
(sp?.appRoles ?? []).map((role) => [role.id, role]),
);
return {
resourceAppId,
resourceDisplayName: sp?.displayName ?? null,
scopesById,
rolesById,
};
}));
const byResourceAppId = new Map(
resourceDefinitions.map((entry) => [entry.resourceAppId, entry]),
);
const rows = [];
for (const resourceEntry of requiredResourceAccess) {
const resourceMeta = byResourceAppId.get(resourceEntry.resourceAppId);
const resourceAccessItems = Array.isArray(resourceEntry?.resourceAccess)
? resourceEntry.resourceAccess
: [];
for (const item of resourceAccessItems) {
const permissionType = item?.type ?? null;
const permissionId = item?.id ?? null;
const resolved = permissionType === "Scope"
? resourceMeta?.scopesById.get(permissionId)
: resourceMeta?.rolesById.get(permissionId);
rows.push({
resourceAppId: resourceEntry.resourceAppId ?? null,
resourceDisplayName: resourceMeta?.resourceDisplayName ?? null,
permissionId,
permissionType,
permissionValue: resolved?.value ?? null,
permissionDisplayName:
resolved?.adminConsentDisplayName ??
resolved?.userConsentDisplayName ??
resolved?.displayName ??
null,
});
}
}
return rows;
}
/**
* List delegated OAuth2 permission grants for an application by appId.
*