Public/Get-InforcerGroup.ps1
|
function Get-InforcerGroup { <# .SYNOPSIS Retrieves groups from an Inforcer tenant. .DESCRIPTION Gets a list of groups or a single group from the Inforcer API. When called without -Group, returns all groups (GroupSummary objects) with optional filtering and auto-pagination. When called with -Group, resolves the group by GUID or display name and returns the full group detail (Group object) including members. Use -Search for server-side prefix filtering (fast, sent to API). Use -Filter for client-side wildcard filtering (supports contains, e.g. *comp*). .PARAMETER TenantId The Inforcer tenant ID. Accepts numeric ID, GUID, or tenant name. Supports pipeline input. .PARAMETER Group The group to retrieve full details for. Accepts a GUID or a display name. When a GUID is provided, fetches the group directly. When a display name is provided, searches for the group and returns the detail including members. .PARAMETER Search Server-side search filter (sent to API). The API performs prefix matching on display name. For contains/substring matching, use -Filter instead. .PARAMETER Filter Client-side wildcard filter applied to display name after fetching all groups. Supports PowerShell wildcards: *comp* matches "All Company", empl* matches "All Employees". Fetches all groups from the API, then filters locally. Slower than -Search for large tenants but supports contains matching that the API does not. .PARAMETER MaxResults Maximum number of groups to return. 0 (default) means no limit. Only available when -Group is not specified. .PARAMETER OutputType Output type: 'PowerShellObject' (default) or 'JsonObject'. .EXAMPLE Get-InforcerGroup -TenantId 139 Lists all groups in tenant 139. .EXAMPLE Get-InforcerGroup -TenantId 139 -Search "Finance" Server-side search for groups starting with "Finance". .EXAMPLE Get-InforcerGroup -TenantId 139 -Filter "*comp*" Client-side filter for groups containing "comp" in the display name (e.g. "All Company"). .EXAMPLE Get-InforcerGroup -TenantId 139 -Group "Tailspin Toys" Resolves the group by display name and returns full detail including members. .EXAMPLE Get-InforcerGroup -TenantId 139 -Group "f44f2f5c-3160-420b-900d-5ecbede954fc" Gets full detail for a specific group by GUID including members. .EXAMPLE Get-InforcerTenant -TenantId 139 | Get-InforcerGroup Lists all groups in the piped tenant. .EXAMPLE Get-InforcerGroup -TenantId 139 -OutputType JsonObject Returns all groups as a JSON string. .EXAMPLE Get-InforcerGroup -TenantId 139 -Group "Finance" -OutputType JsonObject Returns full group detail as a JSON string. .OUTPUTS PSObject or String (when -OutputType JsonObject) .LINK https://github.com/royklo/InforcerCommunity/blob/main/docs/CMDLET-REFERENCE.md#get-inforcergroup .LINK Connect-Inforcer #> [CmdletBinding(DefaultParameterSetName = 'List')] [OutputType([PSObject], [string])] param( [Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName = 'List')] [Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName = 'ById')] [Alias('ClientTenantId')] [object]$TenantId, [Parameter(Mandatory, ParameterSetName = 'ById')] [Alias('GroupId')] [string]$Group, [Parameter(ParameterSetName = 'List')] [string]$Search, [Parameter(ParameterSetName = 'List')] [string]$Filter, [Parameter(ParameterSetName = 'List')] [int]$MaxResults = 0, [Parameter(ParameterSetName = 'List')] [Parameter(ParameterSetName = 'ById')] [ValidateSet('PowerShellObject', 'JsonObject')] [string]$OutputType = 'PowerShellObject' ) process { if (-not (Test-InforcerSession)) { Write-Error -Message "Not connected to Inforcer. Use Connect-Inforcer first." -ErrorId 'NotConnected' -Category ConnectionError return } try { $resolvedTenantId = Resolve-InforcerTenantId -TenantId $TenantId } catch { Write-Error -Message $_.Exception.Message -ErrorId 'InvalidTenantId' -Category InvalidArgument return } if ($PSCmdlet.ParameterSetName -eq 'ById') { # --- ById: resolve group (GUID or name) and get detail --- try { $resolvedGroupId = Resolve-InforcerGroupId -GroupId $Group -TenantId $resolvedTenantId } catch { Write-Error -Message $_.Exception.Message -ErrorId 'InvalidGroupId' -Category InvalidArgument return } $endpoint = "/beta/tenants/$resolvedTenantId/groups/$resolvedGroupId" $err = $null $response = Invoke-InforcerApiRequest -Endpoint $endpoint -Method GET -OutputType PowerShellObject -PreserveStructure -ErrorVariable err -ErrorAction SilentlyContinue if ($null -eq $response) { if ($err -and $err[0].FullyQualifiedErrorId -like 'ApiRequestFailed_404*') { Write-Error -Message "Group '$Group' not found in tenant '$resolvedTenantId'." -ErrorId 'GroupNotFound' -Category ObjectNotFound } elseif ($err) { Write-Error -ErrorRecord $err[0] } else { Write-Error -Message "Group '$Group' not found in tenant '$resolvedTenantId'." -ErrorId 'GroupNotFound' -Category ObjectNotFound } return } if ($OutputType -eq 'JsonObject') { return $response | ConvertTo-Json -Depth 100 } $null = Add-InforcerPropertyAliases -InputObject $response -ObjectType Group $response.PSObject.TypeNames.Insert(0, 'InforcerCommunity.Group') return $response } # --- List: paginated group list --- $jsonBuffer = $null if ($OutputType -eq 'JsonObject') { $jsonBuffer = [System.Collections.ArrayList]::new() } $continuationToken = $null $pageCount = 0 $itemCount = 0 do { $pageCount++ $endpoint = "/beta/tenants/$resolvedTenantId/groups" $queryParams = @() if ($Search) { $queryParams += "search=$([System.Uri]::EscapeDataString($Search))" } if ($continuationToken) { $queryParams += "continuationToken=$([System.Uri]::EscapeDataString($continuationToken))" } if ($queryParams.Count -gt 0) { $endpoint += '?' + ($queryParams -join '&') } Write-Verbose "Fetching page $pageCount..." $response = Invoke-InforcerApiRequest -Endpoint $endpoint -Method GET -OutputType PowerShellObject -PreserveFullResponse if ($null -eq $response) { break } # continuationToken is at the response root level (sibling of .data), not inside .data $items = if ($null -ne $response.PSObject.Properties['data']) { $response.data } else { $null } $newToken = if ($null -ne $response.PSObject.Properties['continuationToken']) { $response.continuationToken } else { $null } # Guard against infinite loop: if API returns the same token, stop if ($newToken -and $newToken -eq $continuationToken) { Write-Verbose "API returned duplicate continuationToken. Stopping pagination." break } $continuationToken = $newToken if ($null -ne $items) { $itemArray = @($items) Write-Verbose "Page $pageCount returned $($itemArray.Count) items." foreach ($item in $itemArray) { if ($null -eq $item) { continue } if ($MaxResults -gt 0 -and $itemCount -ge $MaxResults) { $continuationToken = $null break } # Client-side wildcard filter on displayName if ($Filter) { $displayName = $null $dnProp = $item.PSObject.Properties['displayName'] if ($dnProp) { $displayName = $dnProp.Value } if (-not $displayName -or $displayName -notlike $Filter) { continue } } $itemCount++ if ($OutputType -eq 'JsonObject') { [void]$jsonBuffer.Add($item) } else { $null = Add-InforcerPropertyAliases -InputObject $item -ObjectType GroupSummary $item.PSObject.TypeNames.Insert(0, 'InforcerCommunity.GroupSummary') $item } } } } while ($continuationToken) if ($OutputType -eq 'JsonObject') { return $jsonBuffer | ConvertTo-Json -Depth 100 } } } |