mirror of
https://github.com/Micke-K/IntuneManagement.git
synced 2026-09-28 19:05:38 +02:00
IntuneManagement 4.0.0-beta1
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
# Shared plumbing behind the policy-picker dialogs in both UI backends.
|
||||
#
|
||||
# The picker used to work off a full-tenant sweep: every Add Pair click ran
|
||||
# Get-GraphPolicies once per policy group, which took minutes on a real tenant.
|
||||
# Instead the user now picks a scope (one policy group or one policy type) and
|
||||
# types a name; the search goes to Graph as a server-side prefix filter and
|
||||
# comes back with just the matches.
|
||||
#
|
||||
# Lives in Internal/ rather than UI/ so WPF and Avalonia agree on the scope
|
||||
# list and the search call, and so the UI stays a thin caller (R9/R10).
|
||||
|
||||
# Minimum characters before a search is sent. Below this the prefix matches
|
||||
# most of the tenant, which is the slow full sweep this exists to avoid. Users
|
||||
# who really want everything in the scope click "Load all in scope" instead.
|
||||
$script:PolicySearchMinLength = 2
|
||||
|
||||
function Get-PolicySearchMinLength
|
||||
{
|
||||
return $script:PolicySearchMinLength
|
||||
}
|
||||
|
||||
# The scope list for the picker's "Search in" dropdown: every policy group,
|
||||
# each followed by its own policy types. Groups are listed first so picking
|
||||
# "everything in Configuration" is one click; the indented type rows narrow it
|
||||
# to a single API.
|
||||
#
|
||||
# Key is what the UI binds SelectedValue to - Id alone is not unique because a
|
||||
# group and a type can carry the same Id (e.g. Applications).
|
||||
function Get-PolicySearchScopes
|
||||
{
|
||||
param(
|
||||
# Marks the scope for this policy type as the default selection. The
|
||||
# compare flows pass the source policy's type, which is the scope the
|
||||
# user wants almost every time.
|
||||
[string]$DefaultPolicyTypeId
|
||||
)
|
||||
|
||||
$scopes = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
|
||||
foreach($group in @($script:IntuneGroups | Where-Object { $_.Title } | Sort-Object Title))
|
||||
{
|
||||
[void]$scopes.Add([PSCustomObject]@{
|
||||
Key = "Group|$($group.Id)"
|
||||
Id = $group.Id
|
||||
Kind = "Group"
|
||||
Title = "$($group.Title) (all types)"
|
||||
GroupId = $group.Id
|
||||
IsDefault = $false
|
||||
})
|
||||
|
||||
foreach($type in @($group.PolicyTypes | Where-Object { $_.Title -and $_.API } | Sort-Object Title))
|
||||
{
|
||||
[void]$scopes.Add([PSCustomObject]@{
|
||||
Key = "Type|$($type.Id)"
|
||||
Id = $type.Id
|
||||
Kind = "Type"
|
||||
# Leading spaces indent the type under its group row. ASCII
|
||||
# only - see the string-literal gate in Static.Tests.ps1.
|
||||
Title = " $($type.Title)"
|
||||
GroupId = $group.Id
|
||||
IsDefault = ($DefaultPolicyTypeId -and $type.Id -eq $DefaultPolicyTypeId)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return $scopes.ToArray()
|
||||
}
|
||||
|
||||
# The tenants the picker can search, one entry per live token - same source and
|
||||
# labelling as the Copy dialog's destination-tenant combo (Get-TokenInfo, which
|
||||
# is provider-agnostic, so MSAL / OAuth / MgGraph tokens all appear). Returns an
|
||||
# empty array when only one tenant is signed in; callers hide the combo then.
|
||||
#
|
||||
# Searching another tenant works because Get-GraphPolicies stamps each policy
|
||||
# with the TokenId it came from, and GetFullObject / Invoke-PolicyHydrate resolve
|
||||
# against that stamp - so a policy picked from tenant B still hydrates and
|
||||
# compares against tenant B.
|
||||
function Get-PolicySearchTenants
|
||||
{
|
||||
$tokens = @(Get-TokenInfo)
|
||||
if($tokens.Count -le 1) { return @() }
|
||||
|
||||
$tenants = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
foreach($token in $tokens)
|
||||
{
|
||||
if(-not $token) { continue }
|
||||
|
||||
$title = Get-StringOrDefault $token.TenantName $token.TenantID
|
||||
if([String]::IsNullOrWhiteSpace($title)) { $title = "Tenant $($token.Id)" }
|
||||
if($token.IsDefault -eq $true) { $title = "$title (Current)" }
|
||||
|
||||
[void]$tenants.Add([PSCustomObject]@{
|
||||
Key = "Token|$($token.Id)"
|
||||
TokenId = [int]$token.Id
|
||||
TenantId = $token.TenantID
|
||||
Title = $title
|
||||
IsDefault = ($token.IsDefault -eq $true)
|
||||
})
|
||||
}
|
||||
|
||||
return $tenants.ToArray()
|
||||
}
|
||||
|
||||
# Key of the tenant to preselect: the current one, else the first.
|
||||
function Get-PolicySearchDefaultTenantKey
|
||||
{
|
||||
param($Tenants)
|
||||
|
||||
$all = @($Tenants)
|
||||
if($all.Count -eq 0) { return $null }
|
||||
|
||||
$current = $all | Where-Object { $_.IsDefault } | Select-Object -First 1
|
||||
if($current) { return $current.Key }
|
||||
|
||||
return $all[0].Key
|
||||
}
|
||||
|
||||
# Default scope key for a policy type id: the type's own row when it is in the
|
||||
# list, otherwise its group, otherwise the first scope. Returns $null when
|
||||
# there are no scopes at all.
|
||||
function Get-PolicySearchDefaultScopeKey
|
||||
{
|
||||
param(
|
||||
$Scopes,
|
||||
[string]$PolicyTypeId
|
||||
)
|
||||
|
||||
$all = @($Scopes)
|
||||
if($all.Count -eq 0) { return $null }
|
||||
|
||||
if($PolicyTypeId)
|
||||
{
|
||||
$typeScope = $all | Where-Object { $_.Kind -eq "Type" -and $_.Id -eq $PolicyTypeId } | Select-Object -First 1
|
||||
if($typeScope) { return $typeScope.Key }
|
||||
}
|
||||
|
||||
return $all[0].Key
|
||||
}
|
||||
|
||||
# Run one scoped search. $Scope is an entry from Get-PolicySearchScopes; an
|
||||
# empty $SearchText returns everything in the scope (the "Load all in scope"
|
||||
# path). Types whose endpoint rejects a server-side filter are handled inside
|
||||
# Get-GraphPolicies, which always re-checks names client-side.
|
||||
function Search-IntunePolicies
|
||||
{
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
$Scope,
|
||||
[string]$SearchText,
|
||||
# Ids to drop from the result - used to keep a policy from being
|
||||
# compared against itself.
|
||||
[string[]]$ExcludeIds,
|
||||
[Int]$TokenId = (Get-DefaultTokenId)
|
||||
)
|
||||
|
||||
if(-not $Scope) { return @() }
|
||||
|
||||
$params = @{ TokenId = $TokenId }
|
||||
if($Scope.Kind -eq "Group") { $params.Add("PolicyGroup", $Scope.Id) }
|
||||
else { $params.Add("PolicyType", $Scope.Id) }
|
||||
if($SearchText) { $params.Add("NameFilter", $SearchText) }
|
||||
|
||||
$found = @()
|
||||
try {
|
||||
$found = @(Get-GraphPolicies @params)
|
||||
}
|
||||
catch {
|
||||
Write-LogError "Search-IntunePolicies failed for scope $($Scope.Key)" $_.Exception
|
||||
return @()
|
||||
}
|
||||
|
||||
if($ExcludeIds -and $ExcludeIds.Count -gt 0) {
|
||||
$found = @($found | Where-Object { $ExcludeIds -notcontains $_.Id })
|
||||
}
|
||||
|
||||
return $found
|
||||
}
|
||||
Reference in New Issue
Block a user