Public/Pages.ps1
function Set-PodeWebLoginPage { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string] $Authentication, [Parameter()] [hashtable[]] $Content, [Parameter()] [Alias('Icon')] [string] $Logo, [Parameter()] [Alias('IconUrl')] [string] $LogoUrl, [Parameter()] [string] $Copyright, [Parameter()] [string] $UsernameProperty, [Parameter()] [string] $GroupProperty, [Parameter()] [string] $AvatarProperty, [Parameter()] [string] $ThemeProperty, [Parameter()] [string] $BackgroundImage, [Parameter()] [string] $SignInMessage, [switch] $PassThru ) # check content if (!(Test-PodeWebContent -Content $Content -ComponentType Layout, Element)) { throw 'The Login page can only contain layouts and/or elements' } # if no content, add default if (Test-PodeIsEmpty -Value $Content) { $Content = @( New-PodeWebTextbox -Type Text -Name 'username' -Id 'username' -Placeholder 'Username' -Required -AutoFocus -DynamicLabel New-PodeWebTextbox -Type Password -Name 'password' -Id 'password' -Placeholder 'Password' -Required -DynamicLabel ) } # set auth to be used on other pages Set-PodeWebState -Name 'auth' -Value $Authentication Set-PodeWebState -Name 'auth-props' -Value @{ Username = $UsernameProperty Group = $GroupProperty Avatar = $AvatarProperty Theme = $ThemeProperty Logout = $true } # set a default logo/url if ([string]::IsNullOrWhiteSpace($Logo)) { $Logo = '/pode.web/images/icon.png' } $Logo = (Add-PodeWebAppPath -Url $Logo) if ([string]::IsNullOrWhiteSpace($LogoUrl)) { $LogoUrl = '/' } $LogoUrl = (Add-PodeWebAppPath -Url $LogoUrl) # background image $BackgroundImage = (Add-PodeWebAppPath -Url $BackgroundImage) # set default failure/success urls $auth = Get-PodeAuth -Name $Authentication $auth.Failure.Url = (Add-PodeWebAppPath -Url '/login') $auth.Success.Url = (Add-PodeWebAppPath -Url '/') # is this auto-redirect oauth2? $isOAuth2 = ($auth.Scheme.Scheme -ieq 'oauth2') $grantType = 'authorization_code' if ($isOAuth2 -and !(Test-PodeIsEmpty $auth.Scheme.InnerScheme)) { $grantType = 'password' } # route path $routePath = '/login' # setup page meta $pageMeta = @{ ComponentType = 'Page' ObjectType = 'Page' Path = $routePath Name = 'Login' Content = $Content SignInMessage = (Protect-PodeWebValue -Value $SignInMessage -Default 'Please sign in' -Encode) IsSystem = $true } # add page meta to state $pages = Get-PodeWebState -Name 'pages' $pages[$routePath] = $pageMeta # get the endpoints to bind $endpointNames = Get-PodeWebState -Name 'endpoint-name' # add the login route Add-PodeRoute -Method Get -Path '/login' -Authentication $Authentication -ArgumentList @{ Path = $routePath } -EndpointName $endpointNames -Login -ScriptBlock { param($Data) $global:PageData = (Get-PodeWebState -Name 'pages')[$Data.Path] Write-PodeWebViewResponse -Path 'login' -Data @{ Page = $global:PageData Content = $global:PageData.Content Theme = Get-PodeWebTheme Logo = $using:Logo LogoUrl = $using:LogoUrl Background = @{ Image = $using:BackgroundImage } SignInMessage = $global:PageData.SignInMessage Copyright = $using:Copyright Auth = @{ Name = $using:Authentication IsOAuth2 = $using:isOAuth2 GrantType = $using:grantType } } $global:PageData = $null } Add-PodeRoute -Method Post -Path '/login' -Authentication $Authentication -EndpointName $endpointNames -Login # add the logout route Add-PodeRoute -Method Post -Path '/logout' -Authentication $Authentication -EndpointName $endpointNames -Logout # add an authenticated home route Remove-PodeWebRoute -Method Get -Path '/' -EndpointName $endpointNames Add-PodeRoute -Method Get -Path '/' -Authentication $Authentication -EndpointName $endpointNames -ScriptBlock { $page = Get-PodeWebFirstPublicPage if ($null -ne $page) { Move-PodeResponseUrl -Url (Get-PodeWebPagePath -Page $page) } $authData = Get-PodeWebAuthData $username = Get-PodeWebAuthUsername -AuthData $authData $groups = Get-PodeWebAuthGroups -AuthData $authData $avatar = Get-PodeWebAuthAvatarUrl -AuthData $authData $theme = Get-PodeWebTheme $navigation = Get-PodeWebNavDefault Write-PodeWebViewResponse -Path 'index' -Data @{ Page = @{ Name = 'Home' Title = 'Home' DisplayName = 'Home' Path = '/' IsSystem = $true } Theme = $theme Navigation = $navigation Auth = @{ Enabled = $true Logout = (Get-PodeWebState -Name 'auth-props').Logout Authenticated = $authData.IsAuthenticated Username = $username Groups = $groups Avatar = $avatar } } } if ($PassThru) { return $pageMeta } } function Set-PodeWebHomePage { [CmdletBinding()] param( [Parameter()] [hashtable[]] $Layouts, [Parameter()] [string] $DisplayName, [Parameter()] [string] $Title, [Parameter()] [hashtable[]] $Navigation, [Parameter()] [Alias('NoAuth')] [switch] $NoAuthentication, [switch] $NoTitle, [switch] $PassThru ) # ensure layouts are correct if (!(Test-PodeWebContent -Content $Layouts -ComponentType Layout)) { throw 'The Home Page can only contain layouts' } # set page title if ([string]::IsNullOrWhiteSpace($DisplayName)) { $DisplayName = 'Home' } if ([string]::IsNullOrWhiteSpace($Title)) { $Title = $DisplayName } # route path $routePath = '/' # setup page meta $pageMeta = @{ ComponentType = 'Page' ObjectType = 'Page' Path = $routePath Name = 'Home' Title = [System.Net.WebUtility]::HtmlEncode($Title) DisplayName = [System.Net.WebUtility]::HtmlEncode($DisplayName) NoTitle = $NoTitle.IsPresent Navigation = $Navigation Layouts = $Layouts IsSystem = $true } # add page meta to state $pages = Get-PodeWebState -Name 'pages' $pages[$routePath] = $pageMeta # does the page need auth? $auth = $null if (!$NoAuthentication) { $auth = (Get-PodeWebState -Name 'auth') } # get the endpoints to bind $endpointNames = Get-PodeWebState -Name 'endpoint-name' # remove route Remove-PodeWebRoute -Method Get -Path $routePath -EndpointName $endpointNames # re-add route Add-PodeRoute -Method Get -Path $routePath -Authentication $auth -ArgumentList @{ Path = $routePath } -EndpointName $endpointNames -ScriptBlock { param($Data) $global:PageData = (Get-PodeWebState -Name 'pages')[$Data.Path] # we either render the home page, or move to the first page if home page is blank $comps = $global:PageData.Layouts if (($null -eq $comps) -or ($comps.Length -eq 0)) { $page = Get-PodeWebFirstPublicPage if ($null -ne $page) { Move-PodeResponseUrl -Url (Get-PodeWebPagePath -Page $page) } } $authData = Get-PodeWebAuthData $username = Get-PodeWebAuthUsername -AuthData $authData $groups = Get-PodeWebAuthGroups -AuthData $authData $avatar = Get-PodeWebAuthAvatarUrl -AuthData $authData $theme = Get-PodeWebTheme $navigation = Get-PodeWebNavDefault -Items $global:PageData.Navigation Write-PodeWebViewResponse -Path 'index' -Data @{ Page = $global:PageData Theme = $theme Navigation = $navigation Layouts = $comps Auth = @{ Enabled = ![string]::IsNullOrWhiteSpace((Get-PodeWebState -Name 'auth')) Logout = (Get-PodeWebState -Name 'auth-props').Logout Authenticated = $authData.IsAuthenticated Username = $username Groups = $groups Avatar = $avatar } } $global:PageData = $null } if ($PassThru) { return $pageMeta } } function Add-PodeWebPage { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string] $Name, [Parameter()] [string] $DisplayName, [Parameter()] [string] $Title, [Parameter()] [string] $Group, [Parameter()] [ValidateNotNullOrEmpty()] [string] $Icon = 'file', [Parameter()] [hashtable[]] $Layouts, [Parameter()] [scriptblock] $ScriptBlock, [Parameter()] [object[]] $ArgumentList, [Parameter()] [string[]] $AccessGroups = @(), [Parameter()] [string[]] $AccessUsers = @(), [Parameter()] [string[]] $EndpointName, [Parameter()] [hashtable[]] $Navigation, [Parameter()] [scriptblock] $HelpScriptBlock, [Parameter()] [Alias('NoAuth')] [switch] $NoAuthentication, [switch] $NoTitle, [switch] $NoBackArrow, [switch] $NoBreadcrumb, [switch] $NewTab, [switch] $Hide, [switch] $NoSidebar, [switch] $PassThru ) # ensure layouts are correct if (!(Test-PodeWebContent -Content $Layouts -ComponentType Layout)) { throw 'A Page can only contain layouts' } # test if page/page-link exists if (Test-PodeWebPage -Name $Name -Group $Group -NoGroup) { throw "Web page/link already exists: $($Name) [Group: $($Group)]" } # set page title if ([string]::IsNullOrWhiteSpace($DisplayName)) { $DisplayName = $Name } if ([string]::IsNullOrWhiteSpace($Title)) { $Title = $DisplayName } # build the route path $routePath = (Get-PodeWebPagePath -Name $Name -Group $Group -NoAppPath) # setup page meta $pageMeta = @{ ComponentType = 'Page' ObjectType = 'Page' Path = $routePath Name = $Name Title = [System.Net.WebUtility]::HtmlEncode($Title) DisplayName = [System.Net.WebUtility]::HtmlEncode($DisplayName) NoTitle = $NoTitle.IsPresent NoBackArrow = $NoBackArrow.IsPresent NoBreadcrumb = $NoBreadcrumb.IsPresent NewTab = $NewTab.IsPresent IsDynamic = $false ShowHelp = ($null -ne $HelpScriptBlock) Icon = $Icon Group = $Group Url = (Get-PodeWebPagePath -Name $Name -Group $Group) Hide = $Hide.IsPresent NoSidebar = $NoSidebar.IsPresent Navigation = $Navigation ScriptBlock = $ScriptBlock HelpScriptBlock = $HelpScriptBlock Layouts = $Layouts NoAuthentication = $NoAuthentication.IsPresent Access = @{ Groups = @($AccessGroups) Users = @($AccessUsers) } } # add page meta to state $pages = Get-PodeWebState -Name 'pages' $pages[$routePath] = $pageMeta # does the page need auth? $auth = $null if (!$NoAuthentication) { $auth = (Get-PodeWebState -Name 'auth') } # get the endpoints to bind if (Test-PodeIsEmpty $EndpointName) { $EndpointName = Get-PodeWebState -Name 'endpoint-name' } # add the page route Add-PodeRoute -Method Get -Path $routePath -Authentication $auth -ArgumentList @{ Data = $ArgumentList; Path = $routePath } -EndpointName $EndpointName -ScriptBlock { param($Data) $global:PageData = (Get-PodeWebState -Name 'pages')[$Data.Path] if (!$global:PageData.NoBackArrow) { $global:PageData.ShowBack = (($null -ne $WebEvent.Query) -and ($WebEvent.Query.Count -gt 0)) if ($global:PageData.ShowBack -and ($WebEvent.Query.Count -eq 1) -and ($WebEvent.Query.ContainsKey(''))) { $global:PageData.ShowBack = $false } } else { $global:PageData.ShowBack = $false } # get auth details of a user $authData = Get-PodeWebAuthData $username = Get-PodeWebAuthUsername -AuthData $authData $groups = Get-PodeWebAuthGroups -AuthData $authData $avatar = Get-PodeWebAuthAvatarUrl -AuthData $authData $theme = Get-PodeWebTheme $navigation = Get-PodeWebNavDefault -Items $global:PageData.Navigation $authMeta = @{ Enabled = ![string]::IsNullOrWhiteSpace((Get-PodeWebState -Name 'auth')) Logout = (Get-PodeWebState -Name 'auth-props').Logout Authenticated = $authData.IsAuthenticated Username = $username Groups = $groups Avatar = $avatar } # check access - 403 if denied if (!(Test-PodeWebPageAccess -PageAccess $global:PageData.Access -Auth $authMeta)) { Set-PodeResponseStatus -Code 403 } else { # if we have a scriptblock, invoke that to get dynamic components $layouts = $null if ($null -ne $global:PageData.ScriptBlock) { $layouts = Invoke-PodeScriptBlock -ScriptBlock $global:PageData.ScriptBlock -Arguments $Data.Data -Splat -Return } if (($null -eq $layouts) -or ($layouts.Length -eq 0)) { $layouts = $global:PageData.Layouts } $breadcrumb = $null $filteredLayouts = @() foreach ($item in $layouts) { if ($item.ObjectType -ieq 'breadcrumb') { if ($null -ne $breadcrumb) { throw "Cannot set two brecrumb trails on one page" } $breadcrumb = $item } else { $filteredLayouts += $item } } Write-PodeWebViewResponse -Path 'index' -Data @{ Page = $global:PageData Title = $global:PageData.Title DisplayName = $global:PageData.DisplayName Theme = $theme Navigation = $navigation Breadcrumb = $breadcrumb Layouts = $filteredLayouts Auth = $authMeta } } $global:PageData = $null } # add the page help route $helpPath = "$($routePath)/help" if (($null -ne $HelpScriptBlock) -and !(Test-PodeWebRoute -Path $helpPath)) { Add-PodeRoute -Method Post -Path $helpPath -Authentication $auth -ArgumentList @{ Data = $ArgumentList; Path = $routePath } -EndpointName $EndpointName -ScriptBlock { param($Data) $global:PageData = (Get-PodeWebState -Name 'pages')[$Data.Path] # get auth details of a user $authData = Get-PodeWebAuthData $username = Get-PodeWebAuthUsername -AuthData $authData $groups = Get-PodeWebAuthGroups -AuthData $authData $authMeta = @{ Enabled = ![string]::IsNullOrWhiteSpace((Get-PodeWebState -Name 'auth')) Authenticated = $authData.IsAuthenticated Username = $username Groups = $groups } # check access - 403 if denied if (!(Test-PodeWebPageAccess -PageAccess $global:PageData.Access -Auth $authMeta)) { Set-PodeResponseStatus -Code 403 } else { $result = Invoke-PodeScriptBlock -ScriptBlock $global:PageData.HelpScriptBlock -Arguments $Data.Data -Splat -Return if ($null -eq $result) { $result = @() } if (!$WebEvent.Response.Headers.ContainsKey('Content-Disposition')) { Write-PodeJsonResponse -Value $result } } $global:PageData = $null } } if ($PassThru) { return $pageMeta } } function Add-PodeWebPageLink { [CmdletBinding(DefaultParameterSetName='ScriptBlock')] param( [Parameter(Mandatory=$true)] [string] $Name, [Parameter()] [string] $DisplayName, [Parameter()] [string] $Group, [Parameter()] [ValidateNotNullOrEmpty()] [string] $Icon = 'file', [Parameter(Mandatory=$true, ParameterSetName='ScriptBlock')] [scriptblock] $ScriptBlock, [Parameter(ParameterSetName='ScriptBlock')] [object[]] $ArgumentList, [Parameter(Mandatory=$true, ParameterSetName='Url')] [string] $Url, [Parameter()] [string[]] $AccessGroups = @(), [Parameter()] [string[]] $AccessUsers = @(), [Parameter(ParameterSetName='ScriptBlock')] [string[]] $EndpointName, [Parameter(ParameterSetName='ScriptBlock')] [Alias('NoAuth')] [switch] $NoAuthentication, [Parameter(ParameterSetName='Url')] [switch] $NewTab, [switch] $Hide ) # test if page/page-link exists if (Test-PodeWebPage -Name $Name -Group $Group -NoGroup) { throw "Web page/link already exists: $($Name) [Group: $($Group)]" } # set page title if ([string]::IsNullOrWhiteSpace($DisplayName)) { $DisplayName = $Name } # setup page meta $pageMeta = @{ ComponentType = 'Page' ObjectType = 'Link' Name = $Name DisplayName = [System.Net.WebUtility]::HtmlEncode($DisplayName) NewTab = $NewTab.IsPresent Icon = $Icon Group = $Group Url = (Add-PodeWebAppPath -Url $Url) Hide = $Hide.IsPresent IsDynamic = ($null -ne $ScriptBlock) ScriptBlock = $ScriptBlock Access = @{ Groups = @($AccessGroups) Users = @($AccessUsers) } NoEvents = $true } # build the route path $routePath = (Get-PodeWebPagePath -Name $Name -Group $Group -NoAppPath) # add page meta to state $pages = Get-PodeWebState -Name 'pages' $pages[$routePath] = $pageMeta # add page link if (($null -ne $ScriptBlock) -and !(Test-PodeWebRoute -Path $routePath)) { $auth = $null if (!$NoAuthentication) { $auth = (Get-PodeWebState -Name 'auth') } if (Test-PodeIsEmpty $EndpointName) { $EndpointName = Get-PodeWebState -Name 'endpoint-name' } Add-PodeRoute -Method Post -Path $routePath -Authentication $auth -ArgumentList @{ Data = $ArgumentList; Path = $routePath } -EndpointName $EndpointName -ScriptBlock { param($Data) $pageData = (Get-PodeWebState -Name 'pages')[$Data.Path] $result = Invoke-PodeScriptBlock -ScriptBlock $pageData.ScriptBlock -Arguments $Data.Data -Splat -Return if ($null -eq $result) { $result = @() } if (!$WebEvent.Response.Headers.ContainsKey('Content-Disposition')) { Write-PodeJsonResponse -Value $result } } } } function ConvertTo-PodeWebPage { [CmdletBinding()] param( [Parameter(ValueFromPipeline=$true)] [string[]] $Commands, [Parameter()] [string] $Module, [switch] $GroupVerbs, [Parameter()] [Alias('NoAuth')] [switch] $NoAuthentication ) # if a module was supplied, import it - then validate the commands if (![string]::IsNullOrWhiteSpace($Module)) { Import-PodeModule -Name $Module Export-PodeModule -Name $Module Write-Verbose "Getting exported commands from module" $ModuleCommands = (Get-Module -Name $Module | Sort-Object -Descending | Select-Object -First 1).ExportedCommands.Keys # if commands were supplied validate them - otherwise use all exported ones if (Test-PodeIsEmpty $Commands) { Write-Verbose "Using all commands in $($Module) for converting to Pages" $Commands = $ModuleCommands } else { Write-Verbose "Validating supplied commands against module's exported commands" foreach ($cmd in $Commands) { if ($ModuleCommands -inotcontains $cmd) { throw "Module $($Module) does not contain function $($cmd) to convert to a Page" } } } } # if there are no commands, fail if (Test-PodeIsEmpty $Commands) { throw 'No commands supplied to convert to Pages' } $sysParams = @( 'Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'InformationAction', 'ErrorVariable', 'WarningVariable', 'InformationVariable', 'OutVariable', 'OutBuffer', 'PipelineVariable' ) # create the pages for each of the commands foreach ($cmd in $Commands) { Write-Verbose "Building page for $($cmd)" $cmdInfo = (Get-Command -Name $cmd -ErrorAction Stop) $sets = $cmdInfo.ParameterSets if (($null -eq $sets) -or ($sets.Length -eq 0)) { continue } # for cmdlets this will be null $ast = $cmdInfo.ScriptBlock.Ast $paramDefs = $null if ($null -ne $ast) { $paramDefs = $ast.FindAll({ $args[0] -is [System.Management.Automation.Language.ParameterAst] }, $true) | Where-Object { $_.Parent.Parent.Parent.Name -ieq $cmd } } $tabs = New-PodeWebTabs -Tabs @(foreach ($set in $sets) { $elements = @(foreach ($param in $set.Parameters) { if ($sysParams -icontains $param.Name) { continue } $type = $param.ParameterType.Name $default = $null if ($null -ne $paramDefs) { $default = ($paramDefs | Where-Object { $_.DefaultValue -and $_.Name.Extent.Text -ieq "`$$($param.Name)" }).DefaultValue.Value } if ($type -iin @('boolean', 'switchparameter')) { New-PodeWebCheckbox -Name $param.Name -AsSwitch } else { switch ($type) { 'pscredential' { New-PodeWebCredential -Name $param.Name } default { $multiple = $param.ParameterType.Name.EndsWith('[]') if ($param.Attributes.TypeId.Name -icontains 'ValidateSetAttribute') { $values = ($param.Attributes | Where-Object { $_.TypeId.Name -ieq 'ValidateSetAttribute' }).ValidValues New-PodeWebSelect -Name $param.Name -Options $values -SelectedValue $default -Multiple:$multiple } elseif ($param.ParameterType.BaseType.Name -ieq 'enum') { $values = [enum]::GetValues($param.ParameterType) New-PodeWebSelect -Name $param.Name -Options $values -SelectedValue $default -Multiple:$multiple } else { New-PodeWebTextbox -Name $param.Name -Value $default } } } } }) $elements += (New-PodeWebHidden -Name '_Function_Name_' -Value $cmd) $name = $set.Name if ([string]::IsNullOrWhiteSpace($name) -or ($set.Name -iin @('__AllParameterSets'))) { $name = 'Default' } $formId = "form_param_$($cmd)_$($name)" $form = New-PodeWebForm -Name Parameters -Id $formId -Content $elements -AsCard -NoAuthentication:$NoAuthentication -ScriptBlock { $cmd = $WebEvent.Data['_Function_Name_'] $WebEvent.Data.Remove('_Function_Name_') $_args = @{} foreach ($key in $WebEvent.Data.Keys) { if ($key -imatch '(?<name>.+)_(Username|Password)$') { $name = $Matches['name'] $uKey = "$($name)_Username" $pKey = "$($name)_Password" if (![string]::IsNullOrWhiteSpace($WebEvent.Data[$uKey]) -and ![string]::IsNullOrWhiteSpace($WebEvent.Data[$pKey])) { $creds = (New-Object System.Management.Automation.PSCredential -ArgumentList $WebEvent.Data[$uKey], (ConvertTo-SecureString -AsPlainText $WebEvent.Data[$pKey] -Force)) $_args[$name] = $creds } } else { if ($WebEvent.Data[$key] -iin @('true', 'false')) { $_args[$key] = ($WebEvent.Data[$key] -ieq 'true') } else { if ($WebEvent.Data[$key].Contains(',')) { $_args[$key] = ($WebEvent.Data[$key] -isplit ',' | ForEach-Object { $_.Trim() }) } else { $_args[$key] = $WebEvent.Data[$key] } } } } try { (. $cmd @_args) | Out-PodeWebTextbox -Multiline -Preformat } catch { $_.Exception | Out-PodeWebTextbox -Multiline -Preformat } } New-PodeWebTab -Name $name -Layouts $form }) $group = [string]::Empty if ($GroupVerbs) { $group = $cmdInfo.Verb if ([string]::IsNullOrWhiteSpace($group)) { $group = '_' } } Add-PodeWebPage -Name $cmd -Icon Settings -Layouts $tabs -Group $group -NoAuthentication:$NoAuthentication } } function Use-PodeWebPages { [CmdletBinding()] param( [Parameter()] [string] $Path ) # use default ./pages, or custom path if ([string]::IsNullOrWhiteSpace($Path)) { $Path = Join-Path (Get-PodeServerPath) 'pages' } elseif ($Path.StartsWith('.')) { $Path = Join-Path (Get-PodeServerPath) $Path } # fail if path not found if (!(Test-Path -Path $Path)) { throw "Path to load pages not found: $($Path)" } # get .ps1 files and load them Get-ChildItem -Path $Path -Filter *.ps1 -Force -Recurse | ForEach-Object { Use-PodeScript -Path $_.FullName } } function Get-PodeWebPage { [CmdletBinding()] param( [Parameter()] [string] $Name, [Parameter()] [string] $Group, [Parameter()] [switch] $NoGroup ) # get all pages $pages = Get-PodeWebState -Name 'pages' if (($null -eq $pages) -or ($pages.Count -eq 0)) { return $null } $pages = $pages.Values # filter by group if ($NoGroup -and [string]::IsNullOrWhiteSpace($Group)) { $pages = @(foreach ($page in $pages) { if ([string]::IsNullOrWhiteSpace($page.Group)) { $page } }) } elseif (![string]::IsNullOrWhiteSpace($Group)) { $pages = @(foreach ($page in $pages) { if ($page.Group -ieq $Group) { $page } }) } # filter by page name if (![string]::IsNullOrWhiteSpace($Name)) { $pages = @(foreach ($page in $pages) { if ($page.Name -ieq $Name) { $page } }) } # return filtered pages return $pages } function Test-PodeWebPage { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string] $Name, [Parameter()] [string] $Group, [Parameter()] [switch] $NoGroup ) # get pages $pages = Get-PodeWebPage -Name $Name -Group $Group -NoGroup:$NoGroup # are there any pages? if ($null -eq $pages) { return $false } return (@($pages) | Measure-Object).Count -gt 0 } |