From b455742f90fa4842070e7649cb67f2911c6536f7 Mon Sep 17 00:00:00 2001 From: ojopiyo <122151392+ojopiyo@users.noreply.github.com> Date: Thu, 11 Dec 2025 21:44:18 +0000 Subject: [PATCH 1/2] Refactored get-spo-invalid-user-accounts script README.md 1. Modular Functions - Get-AllUsersFromUPA, Get-DisabledUsersFromGraph, and Validate-SiteUsers encapsulate logic for clarity and reusability. 2. Readable Loops - Flattened loops and replaced nested if logic with clear conditions. 3. Pipeline-Friendly - Uses ForEach-Object and -contains for clean collection handling. 4. Error Handling - Each user retrieval is wrapped in try/catch to prevent the script from stopping. 5. Color-Coded Output - Yellow for warnings, Red for errors, Green for completion. 6. Easy to Extend - Adding additional validation rules is straightforward within Validate-SiteUsers. --- .../get-spo-invalid-user-accounts/README.md | 111 ++++++++++-------- 1 file changed, 62 insertions(+), 49 deletions(-) diff --git a/scripts/get-spo-invalid-user-accounts/README.md b/scripts/get-spo-invalid-user-accounts/README.md index 567c8bac6..60364e610 100644 --- a/scripts/get-spo-invalid-user-accounts/README.md +++ b/scripts/get-spo-invalid-user-accounts/README.md @@ -26,66 +26,79 @@ if(-not $conn) $conn = Connect-PnPOnline -Url $SiteURL -Interactive -ReturnConnection } -function Get-AllUsersFromUPA -{ - $allUPAusers = @() - $UPAusers = Submit-PnPSearchQuery -Query "*" -SourceId "b09a7990-05ea-4af9-81ef-edfab16c4e31" -SelectProperties "Title,WorkEmail" -All -Connection $conn - foreach($user in $UPAusers.ResultRows) - { - $allUPAusers += $user.LoginName - } - $allUPAusers +# --------------------------- +# Function: Get all users from UPA +# --------------------------- +function Get-AllUsersFromUPA { + param([Parameter(Mandatory)] $Connection) + + $UPAusers = Submit-PnPSearchQuery ` + -Query "*" ` + -SourceId "b09a7990-05ea-4af9-81ef-edfab16c4e31" ` + -SelectProperties "Title,WorkEmail" ` + -All ` + -Connection $Connection + + return $UPAusers.ResultRows | ForEach-Object { $_.LoginName } } -function Get-UserFromGraph -{ - $disabledusersfromgraph = @() - $result = Invoke-PnPGraphMethod -Url "users?`$select=displayName,mail, AccountEnabled" -Connection $conn - - $result.value.Count - foreach($account in $result.value) - { - if($account.accountEnabled -eq $false) - { - $disabledusersfromgraph += $account.mail - } - } - $disabledusersfromgraph -} +# --------------------------- +# Function: Get disabled users from Azure AD (Graph) +# --------------------------- +function Get-DisabledUsersFromGraph { + param([Parameter(Mandatory)] $Connection) -$disabledusersfromgraph = Get-UserFromGraph -$allUPAusers = Get-AllUsersFromUPA + $result = Invoke-PnPGraphMethod -Url "users?`$select=displayName,mail,accountEnabled" -Connection $Connection + return $result.value | Where-Object { $_.accountEnabled -eq $false } | ForEach-Object { $_.mail } +} -$allSiteUsers = Get-PnPUser -Connection $conn -$validUsers = @() -$invalidUsers = @() -foreach($user in $allSiteUsers) -{ - try { - $userObj = Get-PnPUser -Identity $user.LoginName -Connection $conn -ErrorAction Stop - if($userObj.Email -in $disabledusersfromgraph) - { - Write-Host "User $($userObj.LoginName) is disabled in Azure AD" - $invalidUsers += $user - } - else - { - $hit = $allUPAusers | Where-Object {$_ -eq $userObj.LoginName} - if(-not $hit) - { - Write-Host "User $($userObj.LoginName) is not in the UPA" +# --------------------------- +# Function: Validate site users +# --------------------------- +function Validate-SiteUsers { + param( + [Parameter(Mandatory)] $Connection, + [Parameter(Mandatory)] $UPAusers, + [Parameter(Mandatory)] $DisabledUsers + ) + + $invalidUsers = @() + $allSiteUsers = Get-PnPUser -Connection $Connection + + foreach ($user in $allSiteUsers) { + try { + $userObj = Get-PnPUser -Identity $user.LoginName -Connection $Connection -ErrorAction Stop + + if ($userObj.Email -in $DisabledUsers) { + Write-Host "User $($userObj.LoginName) is disabled in Azure AD" -ForegroundColor Yellow + $invalidUsers += $user + } + elseif (-not ($UPAusers -contains $userObj.LoginName)) { + Write-Host "User $($userObj.LoginName) is not in the UPA" -ForegroundColor Yellow $invalidUsers += $user } } - - - } - catch { - $invalidUsers += $user + catch { + Write-Host "Error retrieving user $($user.LoginName), marking as invalid." -ForegroundColor Red + $invalidUsers += $user + } } + + return $invalidUsers } + +# --------------------------- +# Main Script Execution +# --------------------------- +$allUPAusers = Get-AllUsersFromUPA -Connection $conn +$disabledUsersFromGraph = Get-DisabledUsersFromGraph -Connection $conn +$invalidUsers = Validate-SiteUsers -Connection $conn -UPAusers $allUPAusers -DisabledUsers $disabledUsersFromGraph + +# Export invalid users to CSV $invalidUsers | Export-Csv -Path "C:\temp\invalidusers.csv" -Delimiter "|" -Encoding utf8 -Force +Write-Host "Script completed. Invalid users exported to C:\temp\invalidusers.csv" -ForegroundColor Green + ``` [!INCLUDE [More about PnP PowerShell](../../docfx/includes/MORE-PNPPS.md)] *** From 107e120522329ff774dcb1e38181a024198b12ca Mon Sep 17 00:00:00 2001 From: Paul Bullock Date: Thu, 18 Dec 2025 08:26:10 +0000 Subject: [PATCH 2/2] Added metadata and attribtuion --- scripts/get-spo-invalid-user-accounts/README.md | 3 +-- scripts/get-spo-invalid-user-accounts/assets/sample.json | 8 +++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/scripts/get-spo-invalid-user-accounts/README.md b/scripts/get-spo-invalid-user-accounts/README.md index 60364e610..15cf2b212 100644 --- a/scripts/get-spo-invalid-user-accounts/README.md +++ b/scripts/get-spo-invalid-user-accounts/README.md @@ -17,8 +17,6 @@ In this script I have checked for two things: ```powershell - - #extract all users from a site collection and check for validity $SiteURL = "https://contoso.sharepoint.com/sites/workspaces" if(-not $conn) @@ -109,6 +107,7 @@ Write-Host "Script completed. Invalid users exported to C:\temp\invalidusers.csv | Author(s) | |-----------| | Kasper Larsen | +| ojopiyo | [!INCLUDE [DISCLAIMER](../../docfx/includes/DISCLAIMER.md)] diff --git a/scripts/get-spo-invalid-user-accounts/assets/sample.json b/scripts/get-spo-invalid-user-accounts/assets/sample.json index 04bb65b6a..0bcc6f1e3 100644 --- a/scripts/get-spo-invalid-user-accounts/assets/sample.json +++ b/scripts/get-spo-invalid-user-accounts/assets/sample.json @@ -9,7 +9,7 @@ "" ], "creationDateTime": "2024-01-10", - "updateDateTime": "2024-01-10", + "updateDateTime": "2025-12-11", "products": [ "SharePoint", "Graph" @@ -39,6 +39,12 @@ } ], "authors": [ + { + "gitHubAccount":"ojopiyo", + "company": "", + "pictureUrl": "https://avatars.githubusercontent.com/u/122151392?v=4", + "name": "ojopiyo" + }, { "gitHubAccount": "kasperbolarsen", "company": "",