fix(assignments): use bulk /assign endpoint for removals on all types
Settings Catalog and other bulk-assign types do not support DELETE on individual assignments. Removal now reloads existing assignments, filters out selected targets, sanitizes remaining payloads, and re-POSTs to <API>/<id>/assign. This mirrors the add flow and works universally across all supported object types.
This commit is contained in:
@@ -648,6 +648,29 @@ elseif($action -eq "Remove assignments")
|
|||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Helper: compute TargetDesc for an assignment
|
||||||
|
function Get-AssignmentTargetDesc
|
||||||
|
{
|
||||||
|
param($Ass)
|
||||||
|
$tt = $Ass.target."@odata.type"
|
||||||
|
switch($tt)
|
||||||
|
{
|
||||||
|
"#microsoft.graph.groupAssignmentTarget"
|
||||||
|
{
|
||||||
|
$grp = $groups | Where-Object { $_.id -eq $Ass.target.groupId } | Select-Object -First 1
|
||||||
|
return "Include: $(if($grp){$grp.displayName}else{$Ass.target.groupId})"
|
||||||
|
}
|
||||||
|
"#microsoft.graph.exclusionGroupAssignmentTarget"
|
||||||
|
{
|
||||||
|
$grp = $groups | Where-Object { $_.id -eq $Ass.target.groupId } | Select-Object -First 1
|
||||||
|
return "Exclude: $(if($grp){$grp.displayName}else{$Ass.target.groupId})"
|
||||||
|
}
|
||||||
|
"#microsoft.graph.allLicensedUsersAssignmentTarget" { return "All Users" }
|
||||||
|
"#microsoft.graph.allDevicesAssignmentTarget" { return "All Devices" }
|
||||||
|
default { return "Unknown" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Execute
|
# Execute
|
||||||
$success = 0
|
$success = 0
|
||||||
$failed = 0
|
$failed = 0
|
||||||
@@ -657,15 +680,42 @@ elseif($action -eq "Remove assignments")
|
|||||||
if($objAssignments.Count -eq 0) { continue }
|
if($objAssignments.Count -eq 0) { continue }
|
||||||
|
|
||||||
Write-Host "`nProcessing: $($obj."$($objectType.NameProp)")" -ForegroundColor Cyan
|
Write-Host "`nProcessing: $($obj."$($objectType.NameProp)")" -ForegroundColor Cyan
|
||||||
foreach($ass in $objAssignments)
|
try
|
||||||
{
|
{
|
||||||
try
|
$existing = Invoke-GraphRequest "$($objectType.API)/$($obj.id)/assignments"
|
||||||
|
$remaining = @()
|
||||||
|
foreach($ea in $existing.value)
|
||||||
|
{
|
||||||
|
$desc = Get-AssignmentTargetDesc -Ass $ea
|
||||||
|
if($desc -in $selectedTargetDisplays)
|
||||||
|
{
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
# Sanitize for re-post
|
||||||
|
$clean = $ea | ConvertTo-Json -Depth 50 | ConvertFrom-Json
|
||||||
|
if($clean.PSObject.Properties["id"]) { $clean.PSObject.Properties.Remove("id") }
|
||||||
|
if($clean.PSObject.Properties["source"]) { $clean.PSObject.Properties.Remove("source") }
|
||||||
|
if(-not $clean."@odata.type")
|
||||||
|
{
|
||||||
|
$clean | Add-Member -NotePropertyName "@odata.type" -NotePropertyValue $objectType.AssignmentODataType -Force
|
||||||
|
}
|
||||||
|
$remaining += $clean
|
||||||
|
}
|
||||||
|
|
||||||
|
$assignPayload = @{
|
||||||
|
$objectType.AssignmentsType = $remaining
|
||||||
|
} | ConvertTo-Json -Depth 50 -Compress
|
||||||
|
|
||||||
|
$null = Invoke-GraphRequest "$($objectType.API)/$($obj.id)/assign" -HttpMethod POST -Content $assignPayload
|
||||||
|
foreach($ass in $objAssignments)
|
||||||
{
|
{
|
||||||
$null = Invoke-GraphRequest "$($objectType.API)/$($obj.id)/assignments/$($ass.AssignmentId)" -HttpMethod DELETE
|
|
||||||
Write-Host " OK: Removed $($ass.TargetDesc)" -ForegroundColor Green
|
Write-Host " OK: Removed $($ass.TargetDesc)" -ForegroundColor Green
|
||||||
$success++
|
$success++
|
||||||
}
|
}
|
||||||
catch
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
foreach($ass in $objAssignments)
|
||||||
{
|
{
|
||||||
Write-Host " ERROR: Failed to remove $($ass.TargetDesc). $($_.Exception.Message)" -ForegroundColor Red
|
Write-Host " ERROR: Failed to remove $($ass.TargetDesc). $($_.Exception.Message)" -ForegroundColor Red
|
||||||
$failed++
|
$failed++
|
||||||
|
|||||||
Reference in New Issue
Block a user