diff --git a/.github/workflows/SyncReadmeCommandReference.yml b/.github/workflows/SyncReadmeCommandReference.yml index 3b9c3f1..ddd02d4 100644 --- a/.github/workflows/SyncReadmeCommandReference.yml +++ b/.github/workflows/SyncReadmeCommandReference.yml @@ -3,14 +3,13 @@ name: Sync README Command Reference on: pull_request: types: [opened, synchronize, reopened] - branches: [ "main" ] + branches: [ "develop", "main" ] permissions: contents: read jobs: sync-readme: - if: github.event.pull_request.head.ref == 'develop' runs-on: ubuntu-latest steps: @@ -20,10 +19,11 @@ jobs: ref: ${{ github.head_ref }} fetch-depth: 0 - # develop requires PRs for all changes, so this can't auto-commit/push a fix directly to - # develop (that used to work before branch protection was added, and now fails every time - # there's real drift to fix). Instead this just fails the check with instructions, the same - # way Invoke-ScriptAnalyzer already gates PSScriptAnalyzer.yml. + # Runs on every PR into develop (and into main, as a final check on promotion), so drift + # gets caught before it lands anywhere - develop requires PRs for all changes, so this + # can't auto-commit/push a fix directly to it (that used to work before branch protection + # was added). Instead this fails the check with instructions, the same way + # Invoke-ScriptAnalyzer already gates PSScriptAnalyzer.yml. - name: Check README command reference is up to date shell: pwsh run: ./tools/Update-ReadmeCommandReference.ps1 -Check diff --git a/PiHoleShell/Public/Authentication/Get-PiHoleCurrentAuthSession.ps1 b/PiHoleShell/Public/Authentication/Get-PiHoleCurrentAuthSession.ps1 index fdce234..9d1c146 100644 --- a/PiHoleShell/Public/Authentication/Get-PiHoleCurrentAuthSession.ps1 +++ b/PiHoleShell/Public/Authentication/Get-PiHoleCurrentAuthSession.ps1 @@ -29,48 +29,42 @@ Get-PiHoleCurrentAuthSession -PiHoleServer "http://pihole.domain.com:8080" -Pass [bool]$RawOutput = $false ) - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/auth/sessions" - Method = "Get" - SkipCertificateCheck = $IgnoreSsl - ContentType = "application/json" - } + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/auth/sessions" + Method = "Get" + SkipCertificateCheck = $IgnoreSsl + ContentType = "application/json" + } - try { $Response = Invoke-RestMethod @Params if ($RawOutput) { Write-Output $Response } - else { - if ($Response.Sessions) { - $ObjectFinal = @() - foreach ($Item in $Response.Sessions) { - $Object = [PSCustomObject]@{ - Id = $Item.id - CurrentSession = $Item.current_session - Valid = $Item.valid - TlsLogin = $Item.tls.login - TlsMixed = $Item.tls.mixed - LoginAt = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.login_at).LocalTime - LastActive = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.last_active).LocalTime - ValidUntil = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.valid_until).LocalTime - RemoteAddress = $Item.remote_addr - UserAgent = $Item.user_agent - App = $Item.app - } - - $ObjectFinal += $Object - $Object = $null + $ObjectFinal = foreach ($Item in $Response.sessions) { + [PSCustomObject]@{ + Id = $Item.id + CurrentSession = $Item.current_session + Valid = $Item.valid + TlsLogin = $Item.tls.login + TlsMixed = $Item.tls.mixed + LoginAt = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.login_at).LocalTime + LastActive = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.last_active).LocalTime + ValidUntil = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.valid_until).LocalTime + RemoteAddress = $Item.remote_addr + UserAgent = $Item.user_agent + XForwardedFor = $Item.x_forwarded_for + App = $Item.app + Cli = $Item.cli } } - Write-Output $ObjectFinal | Where-Object { $_.CurrentSession -match "False" } + Write-Output $ObjectFinal } - $ObjectFinal = @() } catch { @@ -79,7 +73,7 @@ Get-PiHoleCurrentAuthSession -PiHoleServer "http://pihole.domain.com:8080" -Pass finally { if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl } } -} \ No newline at end of file +} diff --git a/PiHoleShell/Public/FTLInformation/Get-PiHoleInfoHost.ps1 b/PiHoleShell/Public/FTLInformation/Get-PiHoleInfoHost.ps1 index 6ea7d84..c573354 100644 --- a/PiHoleShell/Public/FTLInformation/Get-PiHoleInfoHost.ps1 +++ b/PiHoleShell/Public/FTLInformation/Get-PiHoleInfoHost.ps1 @@ -1,11 +1,27 @@ function Get-PiHoleInfoHost { <# .SYNOPSIS -Get info about various host parameters -This API hook returns a collection of host infos. +Get information about the host system +.DESCRIPTION +Request host system information: kernel/OS details (uname), the hardware model, and DMI +(motherboard/BIOS) details where available. + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Set to $true to skip SSL certificate validation + +.PARAMETER RawOutput +This will dump the response instead of the formatted object + +.EXAMPLE +Get-PiHoleInfoHost -PiHoleServer "http://pihole.domain.com:8080" -Password "your-app-password" #> - #Work In Progress [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/info/host')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( @@ -32,29 +48,30 @@ This API hook returns a collection of host infos. if ($RawOutput) { Write-Output $Response } - else { - $ObjectFinal = @() - foreach ($Item in $Response.host) { - $Object = $null - $Object = [PSCustomObject]@{ - DomainName = $Item.uname.domainname - Machine = $Item.uname.machine - NodeName = $Item.uname.nodename - Release = $Item.uname.release - SysName = $Item.uname.sysname - Version = $Item.uname.version - - } - $ObjectFinal += $Object - Write-Output $ObjectFinal + $Object = [PSCustomObject]@{ + DomainName = $Response.host.uname.domainname + Machine = $Response.host.uname.machine + NodeName = $Response.host.uname.nodename + Release = $Response.host.uname.release + SysName = $Response.host.uname.sysname + Version = $Response.host.uname.version + Model = $Response.host.model + BiosVendor = $Response.host.dmi.bios.vendor + BoardName = $Response.host.dmi.board.name + BoardVendor = $Response.host.dmi.board.vendor + BoardVersion = $Response.host.dmi.board.version + ProductName = $Response.host.dmi.product.name + ProductFamily = $Response.host.dmi.product.family + ProductVersion = $Response.host.dmi.product.version + SysVendor = $Response.host.dmi.sys.vendor } + Write-Output $Object } } catch { Write-Error -Message $_.Exception.Message - break } finally { @@ -62,4 +79,4 @@ This API hook returns a collection of host infos. Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl } } -} \ No newline at end of file +} diff --git a/PiHoleShell/Public/Metrics/Get-PiHoleStatsSummary.ps1 b/PiHoleShell/Public/Metrics/Get-PiHoleStatsSummary.ps1 index 18c1fbb..9712c83 100644 --- a/PiHoleShell/Public/Metrics/Get-PiHoleStatsSummary.ps1 +++ b/PiHoleShell/Public/Metrics/Get-PiHoleStatsSummary.ps1 @@ -10,8 +10,8 @@ The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "h .PARAMETER Password The API Password you generated from your PiHole server - -This will dump the response instead of the formatted object +.PARAMETER IgnoreSsl +Set to $true to skip SSL certificate validation .PARAMETER RawOutput This will dump the response instead of the formatted object @@ -50,6 +50,10 @@ Get-PiHoleStatsSummary -PiHoleServer "http://pihole.domain.com:8080" -Password " Total = $Response.queries.total Blocked = $Response.queries.blocked PercentBlocked = $Response.queries.percent_blocked + UniqueDomains = $Response.queries.unique_domains + Forwarded = $Response.queries.forwarded + Cached = $Response.queries.cached + Frequency = $Response.queries.frequency Types = [PSCustomObject]@{ A = $Response.queries.types.A AAAA = $Response.queries.types.AAAA @@ -105,15 +109,21 @@ Get-PiHoleStatsSummary -PiHoleServer "http://pihole.domain.com:8080" -Password " None = $Response.queries.replies.NONE Blob = $Response.queries.replies.BLOB } + Clients = [PSCustomObject]@{ + Active = $Response.clients.active + Total = $Response.clients.total + } + Gravity = [PSCustomObject]@{ + DomainsBeingBlocked = $Response.gravity.domains_being_blocked + LastUpdate = $Response.gravity.last_update + } } - $ObjectFinal += $Object - Write-Output $ObjectFinal + Write-Output $Object } } catch { Write-Error -Message $_.Exception.Message - break } finally { @@ -121,4 +131,4 @@ Get-PiHoleStatsSummary -PiHoleServer "http://pihole.domain.com:8080" -Password " Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl } } -} \ No newline at end of file +} diff --git a/PiHoleShell/Public/Padd/Get-PiHolePadd.ps1 b/PiHoleShell/Public/Padd/Get-PiHolePadd.ps1 index 662266f..c2b1a82 100644 --- a/PiHoleShell/Public/Padd/Get-PiHolePadd.ps1 +++ b/PiHoleShell/Public/Padd/Get-PiHolePadd.ps1 @@ -51,8 +51,6 @@ Get-PiHolePadd -PiHoleServer "http://pihole.domain.com:8080" -Password "your-app } else { - $ObjectFinal = @() - $Object = $null $IFaceV4RxBytes = [PSCustomObject]@{ Value = $Response.iface.v4.rx_bytes.value Unit = $Response.iface.v4.rx_bytes.unit @@ -83,6 +81,7 @@ Get-PiHolePadd -PiHoleServer "http://pihole.domain.com:8080" -Password "your-app Total = $Response.queries.total Blocked = $Response.queries.blocked PercentBlocked = $Response.queries.percent_blocked + QueryFrequency = $Response.queries.query_frequency } $Sensors = [PSCustomObject]@{ CpuTemp = $Response.sensors.cpu_temp @@ -121,22 +120,18 @@ Get-PiHolePadd -PiHoleServer "http://pihole.domain.com:8080" -Password "your-app Queries = $Queries RecentBlocked = $Response.recent_blocked Sensors = $Sensors - System = $Response.system + System = ConvertTo-PiHolePascalCaseObject -InputObject $Response.system TopBlocked = $Response.top_blocked TopClient = $Response.top_client TopDomain = $Response.top_domain - Version = $Response.version + Version = ConvertTo-PiHolePascalCaseObject -InputObject $Response.version } - if ($Object) { - $ObjectFinal += $Object - } - Write-Output $ObjectFinal + Write-Output $Object } } catch { Write-Error -Message $_.Exception.Message - break } finally { diff --git a/README.md b/README.md index d14d073..31ddd4f 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ Functions marked 🚧 are still under active development — signatures and outp | Function | Description | |---|---| | `Get-PiHoleConfig` | Get current configuration of Pi-hole | -| `Get-PiHoleInfoHost` 🚧 | Get info about various host parameters This API hook returns a collection of host infos. | +| `Get-PiHoleInfoHost` | Get information about the host system | | `Get-PiHoleInfoMessage` | Get Pi-hole diagnosis messages Request Pi-hole diagnosis messages | | `Get-PiHolePadd` | Get summarized data for PADD | diff --git a/tests/Get-PiHoleInfoHost.Integration.Tests.ps1 b/tests/Get-PiHoleInfoHost.Integration.Tests.ps1 index 0aa7b03..3ca7e8a 100644 --- a/tests/Get-PiHoleInfoHost.Integration.Tests.ps1 +++ b/tests/Get-PiHoleInfoHost.Integration.Tests.ps1 @@ -25,6 +25,7 @@ Describe 'Get-PiHoleInfoHost (Integration)' -Tag 'Integration' { $result | Should -Not -BeNullOrEmpty $result.NodeName | Should -Not -BeNullOrEmpty + $result.Model | Should -Not -BeNullOrEmpty } It 'returns the raw API response when RawOutput is set' -Skip:(-not $script:ConfigAvailable) { diff --git a/tests/Get-PiHoleStatsSummary.Integration.Tests.ps1 b/tests/Get-PiHoleStatsSummary.Integration.Tests.ps1 index 00aa057..dbd0004 100644 --- a/tests/Get-PiHoleStatsSummary.Integration.Tests.ps1 +++ b/tests/Get-PiHoleStatsSummary.Integration.Tests.ps1 @@ -31,6 +31,8 @@ Describe 'Get-PiHoleStatsSummary (Integration)' -Tag 'Integration' { $result.Types | Should -Not -BeNullOrEmpty $result.Status | Should -Not -BeNullOrEmpty $result.Replies | Should -Not -BeNullOrEmpty + $result.Clients | Should -Not -BeNullOrEmpty + $result.Gravity | Should -Not -BeNullOrEmpty } It 'returns the raw API response when RawOutput is set' -Skip:(-not $script:ConfigAvailable) {