Private/AD/Get-ADUserGroupsToUpdate.ps1
|
<# .SYNOPSIS Diff proposed vs current AD group membership for active linked users. .DESCRIPTION For each active, AD-provisioned, linked user, compares GroupsProposed against ADCurrentGroups and builds an Add list (proposed groups that exist in AD and the user isn't already in) and a Remove list (current groups no longer proposed). Adds are limited to groups present in CurrentADGroups. Users with ProcessGroupsAD = $false are skipped entirely (no adds, no removes) - an empty proposed list would otherwise strip all of their groups - and the skipped count is logged at Trace. .PARAMETER UserList The enriched source records. .PARAMETER CurrentADGroups The group names that exist in AD (null allowed); a proposed group must be in this set to be added. .OUTPUTS [pscustomobject] @{ Add; Remove }, each an array of @{ PersonID; ADCurrentUserID; Groups }. .EXAMPLE $groups = Get-ADUserGroupsToUpdate -UserList $sourceData -CurrentADGroups $adData.Groups .NOTES Created by: Sam Cattanach Modified: 2026-10-09 #> function Get-ADUserGroupsToUpdate { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] $UserList, [Parameter(Mandatory = $true)] [AllowNull()] $CurrentADGroups ) $itemListAdd = @() $itemListRemove = @() $skippedCount = 0 foreach ($item in $UserList | Where-Object {$_.IDBActive -eq $true -and $_.ProvisionAD -eq $true -and $_.ADCurrentUserID}) { #Opted out of AD group processing - leave the user's groups untouched (no adds, no removes) if ($item.ProcessGroupsAD -eq $false) { $skippedCount++ continue } #Create list for adding groups $userGroupsAdd = @() foreach ($groupAdd in $item.GroupsProposed | Where-Object {$_ -in $CurrentADGroups}) { if ($groupAdd -notin $item.ADCurrentGroups) { $userGroupsAdd += $groupAdd } } if ($userGroupsAdd.Count -gt 0) { Write-Log -Message "AD: Proposed: Add Groups: $($item.personID) $($item.NameFirst) $($item.NameLast): $($userGroupsAdd -join ', ')" $itemListAdd += [PSCustomObject]@{ PersonID = $item.PersonID ADCurrentUserID = $item.ADCurrentUserID Groups = $userGroupsAdd } } #Create list for removing groups $userGroupsRemove = @() foreach ($groupCurrent in $item.ADCurrentGroups) { if ($groupCurrent -notin $item.GroupsProposed) { $userGroupsRemove += $groupCurrent } } if ($userGroupsRemove.Count -gt 0) { Write-Log -Message "AD: Proposed: Remove Groups: $($item.personID) $($item.NameFirst) $($item.NameLast): $($userGroupsRemove -join ', ')" $itemListRemove += [PSCustomObject]@{ PersonID = $item.PersonID ADCurrentUserID = $item.ADCurrentUserID Groups = $userGroupsRemove } } } if ($skippedCount -gt 0) { Write-Log -Message "AD: Group processing skipped for $($skippedCount) user(s) with ProcessGroupsAD = `$false." -Level Trace } return [PSCustomObject]@{ Add = $itemListAdd Remove = $itemListRemove } } |