Views/Users.ps1
|
function Show-InTUIUsersView { <# .SYNOPSIS Displays the Users management view mimicking the Intune Users blade. #> [CmdletBinding()] param() $exitView = $false while (-not $exitView) { Clear-Host Show-InTUIHeader Show-InTUIBreadcrumb -Path @('Home', 'Users') $userChoices = @( 'All Users', 'Licensed Users', 'Search Users', '-------------', 'Back to Home' ) $selection = Show-InTUIMenu -Title "[yellow]Users[/]" -Choices $userChoices Write-InTUILog -Message "Users view selection" -Context @{ Selection = $selection } switch ($selection) { 'All Users' { Show-InTUIUserList } 'Licensed Users' { Show-InTUIUserList -LicensedOnly } 'Search Users' { $searchTerm = Read-InTUITextInput -Message "[yellow]Search users by name or email[/]" if ($searchTerm) { Write-InTUILog -Message "Searching users" -Context @{ SearchTerm = $searchTerm } Show-InTUIUserList -SearchTerm $searchTerm } } 'Back to Home' { $exitView = $true } default { continue } } } } function Show-InTUIUserList { <# .SYNOPSIS Displays a paginated list of users. #> [CmdletBinding()] param( [Parameter()] [string]$SearchTerm, [Parameter()] [switch]$LicensedOnly ) $exitList = $false while (-not $exitList) { Clear-Host Show-InTUIHeader $breadcrumb = @('Home', 'Users') if ($SearchTerm) { $breadcrumb += "Search: $SearchTerm" } elseif ($LicensedOnly) { $breadcrumb += 'Licensed Users' } else { $breadcrumb += 'All Users' } Show-InTUIBreadcrumb -Path $breadcrumb $params = @{ Uri = '/users' PageSize = 25 Select = 'id,displayName,userPrincipalName,mail,jobTitle,department,accountEnabled,createdDateTime,assignedLicenses' OrderBy = 'displayName' } $filters = @() if ($SearchTerm) { $safe = ConvertTo-InTUISafeFilterValue -Value $SearchTerm $filters += "(startswith(displayName,'$safe') or startswith(userPrincipalName,'$safe') or startswith(mail,'$safe'))" } if ($LicensedOnly) { $filters += 'assignedLicenses/$count ne 0' $params['Headers'] = @{ ConsistencyLevel = 'eventual' } $params['IncludeCount'] = $true } if ($filters.Count -gt 0) { $params['Filter'] = $filters -join ' and ' } $users = Show-InTUILoading -Title "[yellow]Loading users...[/]" -ScriptBlock { Get-InTUIPagedResults @params } if ($null -eq $users -or $users.Results.Count -eq 0) { Show-InTUIWarning "No users found." Read-InTUIKey $exitList = $true continue } $filteredUsers = $users.Results $userChoices = @() foreach ($user in $filteredUsers) { $enabled = if ($user.accountEnabled) { '[green]●[/]' } else { '[red]●[/]' } $dept = if ($user.department) { $user.department } else { 'N/A' } $licenses = @($user.assignedLicenses).Count $displayName = "$enabled [white]$(ConvertTo-InTUISafeMarkup -Text $user.displayName)[/] [grey]| $($user.userPrincipalName) | $dept | $licenses license(s)[/]" $userChoices += $displayName } $choiceMap = Get-InTUIChoiceMap -Choices $userChoices $menuChoices = @($choiceMap.Choices + '─────────────' + 'Back') Show-InTUIStatusBar -Total $users.TotalCount -Showing $filteredUsers.Count -FilterText $SearchTerm $selection = Show-InTUIMenu -Title "[yellow]Select a user[/]" -Choices $menuChoices if ($selection -eq 'Back') { $exitList = $true } elseif ($selection -ne '─────────────') { $idx = $choiceMap.IndexMap[$selection] if ($null -ne $idx -and $idx -lt $filteredUsers.Count) { Show-InTUIUserDetail -UserId $filteredUsers[$idx].id } } } } function Show-InTUIUserDetail { <# .SYNOPSIS Displays detailed information about a specific user. #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$UserId ) $exitDetail = $false while (-not $exitDetail) { Clear-Host Show-InTUIHeader $user = Show-InTUILoading -Title "[yellow]Loading user details...[/]" -ScriptBlock { Invoke-InTUIGraphRequest -Uri "/users/$UserId`?`$select=id,displayName,userPrincipalName,mail,givenName,surname,jobTitle,department,officeLocation,mobilePhone,businessPhones,city,state,country,postalCode,accountEnabled,createdDateTime,lastSignInDateTime,assignedLicenses,assignedPlans" } if ($null -eq $user) { Show-InTUIError "Failed to load user details." Read-InTUIKey return } Show-InTUIBreadcrumb -Path @('Home', 'Users', $user.displayName) Add-InTUIHistoryEntry -ViewType 'User' -ViewId $UserId -DisplayName $user.displayName $enabled = if ($user.accountEnabled) { '[green]Enabled[/]' } else { '[red]Disabled[/]' } $propsContent = @" [bold white]$(ConvertTo-InTUISafeMarkup -Text $user.displayName)[/] $enabled [grey]UPN:[/] $($user.userPrincipalName) [grey]Email:[/] $($user.mail ?? 'N/A') [grey]First Name:[/] $($user.givenName ?? 'N/A') [grey]Last Name:[/] $($user.surname ?? 'N/A') [grey]Job Title:[/] $($user.jobTitle ?? 'N/A') [grey]Department:[/] $($user.department ?? 'N/A') [grey]Office:[/] $($user.officeLocation ?? 'N/A') [grey]Mobile Phone:[/] $($user.mobilePhone ?? 'N/A') [grey]Business Phone:[/] $(if ($user.businessPhones) { $user.businessPhones -join ', ' } else { 'N/A' }) [grey]City:[/] $($user.city ?? 'N/A') [grey]State:[/] $($user.state ?? 'N/A') [grey]Country:[/] $($user.country ?? 'N/A') [grey]Created:[/] $(Format-InTUIDate -DateString $user.createdDateTime) [grey]Licenses:[/] $(@($user.assignedLicenses).Count) assigned "@ Show-InTUIPanel -Title "[yellow]User Properties[/]" -Content $propsContent -BorderColor Yellow $actionChoices = @( 'View Managed Devices', 'View App Installations', 'View Group Memberships', 'View Licenses', "What's Applied?", '─────────────', 'Back to Users' ) $action = Show-InTUIMenu -Title "[yellow]User Actions[/]" -Choices $actionChoices Write-InTUILog -Message "User detail action" -Context @{ UserId = $UserId; UserName = $user.displayName; Action = $action } switch ($action) { 'View Managed Devices' { Show-InTUIUserDevices -UserId $UserId -UserName $user.displayName } 'View App Installations' { Show-InTUIUserApps -UserId $UserId -UserName $user.displayName } 'View Group Memberships' { Show-InTUIUserGroups -UserId $UserId -UserName $user.displayName } 'View Licenses' { Show-InTUIUserLicenses -UserId $UserId -UserName $user.displayName -Licenses $user.assignedLicenses } "What's Applied?" { Show-InTUIUserWhatsApplied -UserId $UserId -UserName $user.displayName } 'Back to Users' { $exitDetail = $true } default { continue } } } } function Show-InTUIUserDevices { <# .SYNOPSIS Shows devices registered/managed for a user. #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$UserId, [Parameter()] [string]$UserName ) Clear-Host Show-InTUIHeader Show-InTUIBreadcrumb -Path @('Home', 'Users', $UserName, 'Managed Devices') $devices = Show-InTUILoading -Title "[yellow]Loading user devices...[/]" -ScriptBlock { Invoke-InTUIGraphRequest -Uri "/users/$UserId/managedDevices?`$select=id,deviceName,operatingSystem,osVersion,complianceState,lastSyncDateTime,model,manufacturer" -Beta } if (-not $devices.value) { Show-InTUIWarning "No managed devices found for this user." Read-InTUIKey return } $rows = @() foreach ($device in $devices.value) { $compColor = Get-InTUIComplianceColor -State $device.complianceState $icon = Get-InTUIDeviceIcon -OperatingSystem $device.operatingSystem $rows += , @( "$icon $($device.deviceName)", "$($device.operatingSystem) $($device.osVersion)", "[$compColor]$($device.complianceState)[/]", "$($device.manufacturer) $($device.model)", (Format-InTUIDate -DateString $device.lastSyncDateTime) ) } Show-InTUITable -Title "Managed Devices for $UserName" -Columns @('Device', 'OS', 'Compliance', 'Model', 'Last Sync') -Rows $rows $deviceChoices = ($devices.value | ForEach-Object { $_.deviceName }) $deviceChoices += 'Back' $selection = Show-InTUIMenu -Title "[yellow]View device details[/]" -Choices $deviceChoices if ($selection -ne 'Back') { $selectedDevice = $devices.value | Where-Object { $_.deviceName -eq $selection } if ($selectedDevice) { Show-InTUIDeviceDetail -DeviceId $selectedDevice.id } } } function Show-InTUIUserApps { <# .SYNOPSIS Shows app installations for a user. #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$UserId, [Parameter()] [string]$UserName ) Clear-Host Show-InTUIHeader Show-InTUIBreadcrumb -Path @('Home', 'Users', $UserName, 'App Installations') $apps = Show-InTUILoading -Title "[yellow]Loading user app installations...[/]" -ScriptBlock { Invoke-InTUIGraphRequest -Uri "/users/$UserId/mobileAppIntentAndStates" -Beta } if (-not $apps.value) { Show-InTUIWarning "No app installation data available for this user." Read-InTUIKey return } foreach ($appState in $apps.value) { if ($appState.mobileAppList) { $rows = @() foreach ($app in $appState.mobileAppList) { $installColor = Get-InTUIInstallStateColor -State $app.installState $rows += , @( $app.displayName, "[$installColor]$($app.installState)[/]", ($app.displayVersion ?? 'N/A'), ($app.mobileAppIntent ?? 'N/A') ) } Show-InTUITable -Title "App Installations" -Columns @('App Name', 'Install State', 'Version', 'Intent') -Rows $rows } } Read-InTUIKey } function Show-InTUIUserGroups { <# .SYNOPSIS Shows group memberships for a user. #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$UserId, [Parameter()] [string]$UserName ) Clear-Host Show-InTUIHeader Show-InTUIBreadcrumb -Path @('Home', 'Users', $UserName, 'Group Memberships') $groups = Show-InTUILoading -Title "[yellow]Loading group memberships...[/]" -ScriptBlock { Invoke-InTUIGraphRequest -Uri "/users/$UserId/memberOf?`$select=id,displayName,description,groupTypes,mailEnabled,securityEnabled,membershipRule" -All } if (-not $groups -or @($groups).Count -eq 0) { Show-InTUIWarning "No group memberships found for this user." Read-InTUIKey return } # Filter to only groups (not roles, etc.) $groupsOnly = $groups | Where-Object { $_.'@odata.type' -eq '#microsoft.graph.group' } if ($groupsOnly.Count -eq 0) { Show-InTUIWarning "No group memberships found." Read-InTUIKey return } $rows = @() $groupChoices = @() foreach ($group in $groupsOnly) { $groupType = Get-InTUIGroupType -Group $group $rows += , @( $group.displayName, $groupType, ($group.description ?? 'N/A') ) $groupChoices += "[white]$(ConvertTo-InTUISafeMarkup -Text $group.displayName)[/] [grey]| $groupType[/]" } Render-InTUITable -Title "Group Memberships for $UserName" -Columns @('Group Name', 'Type', 'Description') -Rows $rows $choiceMap = Get-InTUIChoiceMap -Choices $groupChoices $menuChoices = @($choiceMap.Choices + '─────────────' + 'Back') $selection = Show-InTUIMenu -Title "[yellow]View group details[/]" -Choices $menuChoices if ($selection -ne 'Back' -and $selection -ne '─────────────') { $idx = $choiceMap.IndexMap[$selection] if ($null -ne $idx -and $idx -lt @($groupsOnly).Count) { Show-InTUIGroupDetail -GroupId @($groupsOnly)[$idx].id } } } function Show-InTUIUserLicenses { <# .SYNOPSIS Shows license assignments for a user. #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$UserId, [Parameter()] [string]$UserName, [Parameter()] [array]$Licenses ) Clear-Host Show-InTUIHeader Show-InTUIBreadcrumb -Path @('Home', 'Users', $UserName, 'Licenses') $licenseDetails = Show-InTUILoading -Title "[yellow]Loading license details...[/]" -ScriptBlock { Invoke-InTUIGraphRequest -Uri "/users/$UserId/licenseDetails" } if (-not $licenseDetails.value) { Show-InTUIWarning "No licenses assigned to this user." Read-InTUIKey return } $rows = @() foreach ($license in $licenseDetails.value) { $enabledPlans = @($license.servicePlans | Where-Object { $_.provisioningStatus -eq 'Success' }).Count $totalPlans = @($license.servicePlans).Count $rows += , @( $license.skuPartNumber, $license.skuId, "$enabledPlans / $totalPlans plans enabled" ) } Show-InTUITable -Title "Licenses for $UserName" -Columns @('License', 'SKU ID', 'Service Plans') -Rows $rows Read-InTUIKey } |