Public/Functions/VoiceConfig/Assert-TeamsUserVoiceConfig.ps1
# Module: TeamsFunctions # Function: VoiceConfig # Author: David Eberhardt # Updated: 15-MAY-2021 # Status: Live #TODO Evaluate whether to integrate Find-TeamsUVC (Phone Number unique!) as a test function Assert-TeamsUserVoiceConfig { <# .SYNOPSIS Tests the validity of the Voice Configuration for one or more Users .DESCRIPTION Validates Object Type, enablement for Enterprise Voice, and optionally also the Tenant Dial Plan For Calling Plans, validates Calling Plan License and presence of Telephone Number For Direct Routing, validates Online Voice Routing Policy and OnPremLineUri For Skype Hybrid PSTN, validate Voice Routing Policy and OnPremLineUri Configuration is always done on the assumption that a full configuration is desired. Any partial configuration is fed back on screen. .PARAMETER UserPrincipalName Required. UserPrincipalName of the User to be tested .PARAMETER IncludeTenantDialPlan Optional. By default, only the core requirements for Voice Routing are verified. This extends the requirements to also include the Tenant Dial Plan. .PARAMETER ExtensionState Optional. For DirectRouting, enforces the presence (or absence) of an Extension. Default: NotMeasured No effect for Microsoft Calling Plans .EXAMPLE Assert-TeamsUserVoiceConfig -UserPrincipalName John@domain.com If incorrect/missing, writes information output about every tested parameter Returns output of Get-TeamsUserVoiceConfig for all Objects that have an incorrectly configured Voice Configuration .EXAMPLE Assert-TeamsUserVoiceConfig -UserPrincipalName John@domain.com -IncludeTenantDialPlan If incorrect/missing, writes information output about every tested parameter including the Tenant Dial Plan Returns output of Get-TeamsUserVoiceConfig for all Objects that have an incorrectly configured Voice Configuration .EXAMPLE Assert-TeamsUserVoiceConfig -UserPrincipalName John@domain.com -ExtensionState MustBePopulated If incorrect/missing, writes information output about every tested parameter including the Extension. With MustBePopulated an Extension is expected. If no Extension is present, it is flagged as misconfigured Returns output of Get-TeamsUserVoiceConfig for all Objects that have an incorrectly configured Voice Configuration .INPUTS System.String .OUTPUTS System.Void - If called directly and no errors are found - Information Text only System.Object - If called directly and errors are found (Get-TeamsUserVoiceConfig) Boolean - If called by other CmdLets .NOTES Verbose output is available, though all required information is fed back directly to the User. If no objections are found, nothing is returned. Piping the Output to Export-Csv can give the best result for investigation into misconfigured users. .COMPONENT VoiceConfiguration .FUNCTIONALITY Finding Users with a incorrectly set up Voice Configuration .LINK https://github.com/DEberhardt/TeamsFunctions/tree/master/docs/ .LINK https://docs.microsoft.com/en-us/microsoftteams/direct-routing-migrating .LINK about_VoiceConfiguration .LINK Assert-TeamsUserVoiceConfig .LINK Find-TeamsUserVoiceConfig .LINK Get-TeamsTenantVoiceConfig .LINK Get-TeamsUserVoiceConfig .LINK New-TeamsUserVoiceConfig .LINK Set-TeamsUserVoiceConfig .LINK Remove-TeamsUserVoiceConfig .LINK Test-TeamsUserVoiceConfig #> [CmdletBinding()] [Alias('Assert-TeamsUVC')] #[OutputType([Boolean])] param ( [Parameter(Mandatory, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName, HelpMessage = 'Username(s)')] [Alias('ObjectId', 'Identity')] [string[]]$UserPrincipalName, [Parameter(HelpMessage = 'Extends requirements to include Tenant Dial Plan assignment')] [switch]$IncludeTenantDialPlan, [Parameter(HelpMessage = 'Extends requirements to validate the status of the Extension')] [ValidateSet('MustBePopulated','MustNotBePopulated','NotMeasured')] [string]$ExtensionState = 'NotMeasured' ) begin { Show-FunctionStatus -Level Live $Stack = Get-PSCallStack $Called = ($stack.length -ge 3) Write-Verbose -Message "[BEGIN ] $($MyInvocation.MyCommand)" Write-Verbose -Message "Need help? Online: $global:TeamsFunctionsHelpURLBase$($MyInvocation.MyCommand)`.md" # Asserting AzureAD Connection if (-not (Assert-AzureADConnection)) { break } # Asserting MicrosoftTeams Connection if (-not (Assert-MicrosoftTeamsConnection)) { break } # Setting Preference Variables according to Upstream settings if (-not $PSBoundParameters.ContainsKey('Verbose')) { $VerbosePreference = $PSCmdlet.SessionState.PSVariable.GetValue('VerbosePreference') } if (-not $PSBoundParameters.ContainsKey('Confirm')) { $ConfirmPreference = $PSCmdlet.SessionState.PSVariable.GetValue('ConfirmPreference') } if (-not $PSBoundParameters.ContainsKey('WhatIf')) { $WhatIfPreference = $PSCmdlet.SessionState.PSVariable.GetValue('WhatIfPreference') } if (-not $PSBoundParameters.ContainsKey('Debug')) { $DebugPreference = $PSCmdlet.SessionState.PSVariable.GetValue('DebugPreference') } else { $DebugPreference = 'Continue' } if ( $PSBoundParameters.ContainsKey('InformationAction')) { $InformationPreference = $PSCmdlet.SessionState.PSVariable.GetValue('InformationAction') } else { $InformationPreference = 'Continue' } } #begin process { Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand)" foreach ($Id in $UserPrincipalName) { Write-Verbose -Message "[PROCESS] Processing '$Id'" try { $CsOnlineUser = Get-CsOnlineUser -Identity "$Id" -WarningAction SilentlyContinue -ErrorAction STOP $User = $CsOnlineUser.UserPrincipalName } catch { Write-Error -Message "User '$Id' not found" continue } if ($CsOnlineUser.InterpretedUserType -notlike '*User*') { Write-Information "User '$User' not a User" continue } else { # Testing Full Configuration Write-Verbose -Message "User '$User' - User Voice Configuration (Full)" $TestFull = Test-TeamsUserVoiceConfig -UserPrincipalName "$User" -IncludeTenantDialPlan:$IncludeTenantDialPlan -ExtensionState:$ExtensionState if ($PSBoundParameters.ContainsKey('Debug') -or $DebugPreference -eq 'Continue') { "Function: $($MyInvocation.MyCommand.Name): TestFull:", ($TestFull | Format-Table -AutoSize | Out-String).Trim() | Write-Debug } if ($TestFull) { if ($Called) { Write-Output $TestFull } else { Write-Information "User '$User' is correctly configured" continue } } else { # Testing Partial Configuration Write-Verbose -Message "User '$User' - User Voice Configuration (Partial)" $TestPart = Test-TeamsUserVoiceConfig -UserPrincipalName "$User" -Partial -IncludeTenantDialPlan:$IncludeTenantDialPlan -ExtensionState:$ExtensionState -WarningAction SilentlyContinue if ($PSBoundParameters.ContainsKey('Debug') -or $DebugPreference -eq 'Continue') { "Function: $($MyInvocation.MyCommand.Name): TestPart:", ($TestPart | Format-Table -AutoSize | Out-String).Trim() | Write-Debug } if ($TestPart) { if ($Called) { Write-Output $TestPart } else { Write-Warning "User '$User' is only partially configured!" Get-TeamsUserVoiceConfig -UserPrincipalName "$User" -SkipLicenseCheck -DiagnosticLevel 1 -WarningAction SilentlyContinue } } } } } #foreach Identity } #process end { Write-Verbose -Message "[END ] $($MyInvocation.MyCommand)" } #end } #Assert-TeamsUserVoiceConfig |