Private/NestedFunctions/Get-JCObject.ps1
Function Get-JCObject { [CmdletBinding(DefaultParameterSetName = 'Default')] Param() DynamicParam { $JCTypes = Get-JCType # Build parameter array $RuntimeParameterDictionary = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary New-DynamicParameter -Name:('Type') -Type:([System.String]) -Mandatory -Position:(0) -ValueFromPipelineByPropertyName -ValidateNotNullOrEmpty -ValidateSet:($JCTypes.TypeName.TypeNameSingular) -RuntimeParameterDictionary:($RuntimeParameterDictionary) | Out-Null New-DynamicParameter -Name:('Id') -Type([System.String[]]) -Mandatory -Position(1) -ValueFromPipelineByPropertyName -ValidateNotNullOrEmpty -ParameterSets(@('ById')) -Alias:(($JCTypes.ById) | Where-Object {$_ -ne 'Id'} | Select-Object -Unique) -RuntimeParameterDictionary:($RuntimeParameterDictionary) | Out-Null New-DynamicParameter -Name:('Name') -Type([System.String[]]) -Mandatory -Position(1) -ValueFromPipelineByPropertyName -ValidateNotNullOrEmpty -ParameterSets:(@('ByName')) -Alias:(($JCTypes.ByName) | Where-Object {$_ -ne 'Name'} | Select-Object -Unique) -RuntimeParameterDictionary:($RuntimeParameterDictionary) | Out-Null New-DynamicParameter -Name:('SearchBy') -Type:([System.String]) -Mandatory -Position:(1) -ValueFromPipelineByPropertyName -ValidateNotNullOrEmpty -ParameterSets:('ByValue') -ValidateSet:(@('ById', 'ByName')) -RuntimeParameterDictionary:($RuntimeParameterDictionary) | Out-Null New-DynamicParameter -Name:('SearchByValue') -Type:([System.String[]]) -Mandatory -Position:(2) -ValueFromPipelineByPropertyName -ValidateNotNullOrEmpty -ParameterSets:('ByValue') -HelpMessage:('Specify the item which you want to search for. Supports wildcard searches using: *') -RuntimeParameterDictionary:($RuntimeParameterDictionary) | Out-Null New-DynamicParameter -Name:('Fields') -Type:([System.Array]) -Position:(3) -ValueFromPipelineByPropertyName -ValidateNotNullOrEmpty -HelpMessage:('An array of the fields/properties/columns you want to return from the search.') -RuntimeParameterDictionary:($RuntimeParameterDictionary) | Out-Null New-DynamicParameter -Name:('Limit') -Type:([System.Int32]) -Position:(4) -ValueFromPipelineByPropertyName -ValidateRange:(1, [int]::MaxValue) -RuntimeParameterDictionary:($RuntimeParameterDictionary) | Out-Null New-DynamicParameter -Name:('Skip') -Type:([System.Int32]) -Position:(5) -ValueFromPipelineByPropertyName -ValidateRange:(1, [int]::MaxValue) -RuntimeParameterDictionary:($RuntimeParameterDictionary) | Out-Null New-DynamicParameter -Name:('ReturnHashTable') -Type:([switch]) -Position:(6) -ValueFromPipelineByPropertyName -RuntimeParameterDictionary:($RuntimeParameterDictionary) -DefaultValue:($false) | Out-Null New-DynamicParameter -Name:('ReturnCount') -Type:([switch]) -Position:(7) -ValueFromPipelineByPropertyName -RuntimeParameterDictionary:($RuntimeParameterDictionary) -DefaultValue:($false) | Out-Null Return $RuntimeParameterDictionary } Begin { # Debug message for parameter call Invoke-Command -ScriptBlock:($ScriptBlock_DefaultDebugMessageBegin) -ArgumentList:($MyInvocation, $PsBoundParameters, $PSCmdlet) -NoNewScope $Results = @() } Process { # For DynamicParam with a default value set that value and then convert the DynamicParam inputs into new variables for the script to use Invoke-Command -ScriptBlock:($ScriptBlock_DefaultDynamicParamProcess) -ArgumentList:($PsBoundParameters, $PSCmdlet, $RuntimeParameterDictionary) -NoNewScope Try { # Identify the command type to run to get the object for the specified item $JCTypeItem = $JCTypes | Where-Object { $Type -in $_.TypeName.TypeNameSingular } If ($JCTypeItem) { $TypeName = $JCTypeItem.TypeName $TypeNameSingular = $TypeName.TypeNameSingular $TypeNamePlural = $TypeName.TypeNamePlural $Targets = $JCTypeItem.Targets $TargetSingular = $Targets.TargetSingular $TargetPlural = $Targets.TargetPlural $Url = $JCTypeItem.Url $Method = $JCTypeItem.Method $ById = $JCTypeItem.ById $ByName = $JCTypeItem.ByName $Paginate = $JCTypeItem.Paginate $SupportRegexFilter = $JCTypeItem.SupportRegexFilter $Limit = $JCTypeItem.Limit $UrlObject = @() # If searching ByValue add filters to query string and body. # Hacky logic to get g_suite and office_365 directories If ($PSCmdlet.ParameterSetName -eq 'Default' -or $TypeNameSingular -in ('g_suite', 'office_365')) { $UrlObject += [PSCustomObject]@{ 'Url' = $Url; 'Body' = $null; 'SearchByValue' = $null; } } Else { If ($PSCmdlet.ParameterSetName -eq 'ById') { $SearchBy = 'ById' $SearchByValue = $Id $PropertyIdentifier = $JCTypeItem.ById } ElseIf ($PSCmdlet.ParameterSetName -eq 'ByName') { $SearchBy = 'ByName' $SearchByValue = $Name $PropertyIdentifier = $JCTypeItem.ByName } ElseIf ($PSCmdlet.ParameterSetName -eq 'ByValue') { $SearchBy = $SearchBy $SearchByValue = $SearchByValue $PropertyIdentifier = Switch ($SearchBy) { 'ById' { $JCTypeItem.ById }; 'ByName' { $JCTypeItem.ByName }; } } ForEach ($SearchByValueItem In $SearchByValue) { $QueryStrings = @() $BodyParts = @() # Populate Url placeholders. Assumption is that if an endpoint requires an Id to be passed in the Url that it does not require a filter because its looking for an exact match already. If ($Url -match '({)(.*?)(})') { Write-Verbose ('Populating ' + $Matches[0] + ' with ' + $SearchByValueItem) $UrlOut = $Url.Replace($Matches[0], $SearchByValueItem) } Else { Switch ($SearchBy) { 'ById' { $UrlOut = $Url + '/' + $SearchByValueItem } 'ByName' { $UrlOut = $Url # Add filters for exact match and wildcards If ($SearchByValueItem -match '\*') { If ($SupportRegexFilter) { $BodyParts += ('"filter":[{"' + $PropertyIdentifier + '":{"$regex": "(?i)(' + $SearchByValueItem.Replace('*', ')(.*?)(') + ')"}}]').Replace('()', '') } Else { Write-Error ('The endpoint ' + $UrlOut + ' does not support wildcards in the $SearchByValueItem. Please remove "*" from "' + $SearchByValueItem + '".') } } Else { $QueryStrings += 'filter=' + $PropertyIdentifier + ':eq:' + $SearchByValueItem $BodyParts += '"filter":[{"' + $PropertyIdentifier + '":"' + $SearchByValueItem + '"}]' } } Default {Write-Error ('Unknown $SearchBy value: ' + $SearchBy)} } } # Build query string and body $JoinedQueryStrings = $QueryStrings -join '&' $JoinedBodyParts = $BodyParts -join ',' # Build final body and url If ($JoinedBodyParts) { $Body = '{' + $JoinedBodyParts + '}' } If ($JoinedQueryStrings) { $UrlOut = $UrlOut + '?' + $JoinedQueryStrings } $UrlObject += [PSCustomObject]@{ 'Url' = $UrlOut; 'Body' = $Body; 'SearchByValueItem' = $SearchByValueItem; } } } ForEach ($UrlItem In $UrlObject) { $Url = $UrlItem.Url $Body = $UrlItem.Body $SearchByValueItem = $UrlItem.SearchByValueItem ## Escape Url???? # $Url = ([uri]::EscapeDataString($Url) # Build function parameters $FunctionParameters = [ordered]@{ } If ($Url) { $FunctionParameters.Add('Url', $Url) } If ($Method) { $FunctionParameters.Add('Method', $Method) } If ($Body) { $FunctionParameters.Add('Body', $Body) } If ($Limit) { $FunctionParameters.Add('Limit', $Limit) } If ($Skip) { $FunctionParameters.Add('Skip', $Skip) } If ($ReturnHashTable) { $Values = $Fields $Key = If ($PropertyIdentifier) { $PropertyIdentifier } Else { $ById } If ($Key) { $FunctionParameters.Add('Key', $Key) } If ($Values) { $FunctionParameters.Add('Values', $Values) } } Else { If ($Fields) { $FunctionParameters.Add('Fields', $Fields) } $FunctionParameters.Add('Paginate', $Paginate) If ($ReturnCount -eq $true) { $FunctionParameters.Add('ReturnCount', $ReturnCount) } } # Hacky logic for organization If ($TypeNameSingular -eq 'organization') { $Organization = Invoke-JCApi @FunctionParameters $FunctionParameters['Url'] = $Url + '/' + $Organization.$ById } # Run command $Result = Switch ($ReturnHashTable) { $true { Get-JCHash @FunctionParameters } Default { Invoke-JCApi @FunctionParameters } } # Hacky logic to get g_suite and office_365directories If ($TypeNameSingular -in ('g_suite', 'office_365')) { If ($ReturnCount -eq $true) { $Directory = $Result.results | Where-Object { $_.Type -eq $TypeNameSingular } $Result.totalCount = ($Directory | Measure-Object).Count $Result.results = $Directory } Else { $Result = $Result | Where-Object { $_.Type -eq $TypeNameSingular } } } If ($Result -and $Result.PSObject.Properties.name -notcontains 'NoContent') { If ($SearchBy -and ($Result | Measure-Object).Count -gt 1) { Write-Warning -Message:('Found "' + [string]($Result | Measure-Object).Count + '" "' + $TypeNamePlural + '" with the "' + $SearchBy.Replace('By', '').ToLower() + '" of "' + $SearchByValueItem + '"') } # If ($PSCmdlet.ParameterSetName -eq 'Default' -and $TypeNameSingular -notin ('g_suite', 'office_365') -and $Url -notlike '*/api/v2/directories*' -and $Url -notlike '*/groups*' -and $Url -notlike '*/api/organizations*' -and $Url -notlike '*/api/search*') # { # $Results = $Result | ForEach-Object { Get-JCObject -Type:($TypeNameSingular) -Id:($_.($ById))} # } # Else # { # List values to add to results $HiddenProperties = @('ById', 'ByName', 'TypeName', 'TypeNameSingular', 'TypeNamePlural', 'Targets', 'TargetSingular', 'TargetPlural') # Append meta info to each result record Get-Variable -Name:($HiddenProperties) | ForEach-Object { $Variable = $_ $Result | ForEach-Object { Add-Member -InputObject:($_) -MemberType:('NoteProperty') -Name:($Variable.Name) -Value:($Variable.Value) } } # Set the meta info to be hidden by default $Results += Hide-ObjectProperty -Object:($Result) -HiddenProperties:($HiddenProperties) } Else { If ($SearchByValueItem) { Write-Warning ('A "' + $TypeNameSingular + '" called "' + $SearchByValueItem + '" does not exist. Note the search is case sensitive.') } Else { Write-Warning ('The search value is blank or no "' + $TypeNamePlural + '" have been setup in your org. SearchValue:"' + $SearchByValueItem + '"') } } # } } } Else { Write-Error ('$Type of "' + $Type + '" not found. $Type must be:' + ($JCTypes.TypeName.TypeNameSingular -join ',')) } } Catch { Invoke-Command -ScriptBlock:($ScriptBlock_TryCatchError) -ArgumentList:($_, $true) -NoNewScope } } End { Return $Results } } |