Public/UserManagement/VoiceConfig/Set-TeamsUserEmergencyConfiguration.ps1
# Module: TeamsFunctions # Function: VoiceConfig # Author: David Eberhardt # Updated: 24-MAY-2021 # Status: RC function Set-TeamsUserEmergencyConfiguration { <# .SYNOPSIS Changes settings for a Common Area Phone .DESCRIPTION Applies settings relevant to a Common Area Phone. This includes DisplayName, UsageLocation, License, IP Phone Policy, Calling Policy and Call Park Policy can be applied. .PARAMETER UserPrincipalName Required for Parameterset UserPrincipalName. UserPrincipalName of a CsOnlineUser Object to be provisioned. .PARAMETER Object Required for Parameterset Object. CsOnlineUser Object passed to the function to reduce query time. .PARAMETER TeamsEmergencyCallingPolicy Optional. Adds a Teams Emergency Calling Policy to the User .PARAMETER TeamsEmergencyCallRoutingPolicy Optional. Adds a Teams Emergency Call Routing Policy to the User .PARAMETER TeamsEmergencyAddress Optional. Adds an Emergency Address to the User .PARAMETER PassThru Optional. Displays the Object after execution. .PARAMETER WriteErrorLog If Errors are encountered, writes log to C:\Temp .EXAMPLE Set-TeamsUserEmergencyConfiguration -UserPrincipalName User@Domain.com -TeamsEmergencyCallingPolicy US Changes the Object User@Domain.com. Applies the Emergency Calling Policy US to the User. .EXAMPLE Set-TeamsUserEmergencyConfiguration -UserPrincipalName User@Domain.com -TeamsEmergencyCallRoutingPolicy USMAIN Changes the Object User@Domain.com. Applies the Emergency Call Routing Policy USMAIN to the User. .EXAMPLE Set-TeamsUserEmergencyConfiguration -UserPrincipalName User@Domain.com -TeamsEmergencyAddress "US Main office" Changes the Object User@Domain.com. Applies the Location with the Description "US Main office" to the User. .EXAMPLE Set-TeamsUserEmergencyConfiguration -UserPrincipalName "User@Domain.com" -TeamsEmergencyCallingPolicy US -TeamsEmergencyCallRoutingPolicy USMAIN -TeamsEmergencyAddress "US Main office" -PassThru Applies Emergency Calling Policy, Emergency Call Routing Policy and Emergency Address (Location) to the User Displays the Common Area Phone Object afterwards .EXAMPLE Set-TeamsUserEmergencyConfiguration -UserPrincipalName "User@Domain.com" -TeamsEmergencyCallingPolicy US -WriteErrorLog Applies Emergency Calling Policy to the User If Errors are encountered, they are written to C:\Temp as well as on screen .INPUTS System.String .OUTPUTS System.Void - Default Behaviour System.Object - With Switch PassThru System.File - With Switch WriteErrorLog .NOTES Execution requires Teams Communication Admin Role (or higher) in Azure AD This CmdLet deliberately does not apply a Phone Number to the Object. To do so, please run Set-TeamsPhoneNumber or Set-TeamsUserVoiceConfig for a full Voice Configuration apply a Calling Plan or Online Voice Routing Policy a Phone Number and optionally a Tenant Dial Plan. This Script only covers relevant user-specific elements for Emergency calling configuration themselves. .COMPONENT UserManagement .FUNCTIONALITY Changes a Users Emergency Calling Configuration in Teams .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/Set-TeamsUserEmergencyConfiguration.md .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/about_VoiceConfiguration.md .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/about_UserManagement.md .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/ #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium', DefaultParameterSetName = 'UserPrincipalName')] [Alias('Set-TeamsEMS')] [OutputType([System.Void])] param ( #TEST Whether both Object and Identity work - replicate for Set-TeamsCAP [Parameter(Mandatory, Position = 0, ParameterSetName = 'Object', ValueFromPipeline)] [Object[]]$Object, [Parameter(Mandatory, Position = 0, ParameterSetName = 'UserPrincipalName', ValueFromPipeline, ValueFromPipelineByPropertyName, HelpMessage = 'UPN of the Object to query.')] [ValidateScript( { If ($_ -match '@') { $True } else { throw [System.Management.Automation.ValidationMetadataException] 'Value must be a valid UPN' } })] [Alias('ObjectId', 'Identity')] [string[]]$UserPrincipalName, [Parameter(ValueFromPipelineByPropertyName, HelpMessage = 'Teams Emergency Calling Policy')] [AllowNull()] [AllowEmptyString()] [ValidateScript( { if ($null -eq $_ -or $_ -eq '' -or $_ -in $(&$global:TfAcSbEmergencyCallingPolicy)) { return $true } else { throw [System.Management.Automation.ValidationMetadataException] 'Value must be a valid Policy in the Tenant. Use Intellisense for options' } })] [ArgumentCompleter({ &$global:TfAcSbEmergencyCallingPolicy })] [string]$TeamsEmergencyCallingPolicy, [Parameter(ValueFromPipelineByPropertyName, HelpMessage = 'Teams Emergency CallRouting Policy')] [AllowNull()] [AllowEmptyString()] [ValidateScript( { if ($null -eq $_ -or $_ -eq '' -or $_ -in $(&$global:TfAcSbEmergencyCallRoutingPolicy)) { return $true } else { throw [System.Management.Automation.ValidationMetadataException] 'Value must be a valid Policy in the Tenant. Use Intellisense for options' } })] [ArgumentCompleter({ &$global:TfAcSbEmergencyCallRoutingPolicy })] [string]$TeamsEmergencyCallRoutingPolicy, [Parameter(ValueFromPipelineByPropertyName, HelpMessage = 'Teams Emergency Address - Location')] [string]$TeamsEmergencyAddress, [Parameter(HelpMessage = 'No output is written by default, Switch PassThru will return changed object')] [switch]$PassThru, [Parameter(HelpMessage = 'Writes a Log File to C:\Temp')] [switch]$WriteErrorLog ) #param begin { Show-FunctionStatus -Level RC Write-Verbose -Message "[BEGIN ] $($MyInvocation.MyCommand)" # 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' } # Worker function to apply settings once accounts have been ascertained function SetTeamsUserEMSConfig { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Low')] param ( [Parameter(Mandatory, ValueFromPipelineByPropertyName, HelpMessage = 'CsOnlineUser Object')] [Object[]]$UserObject, [Parameter(HelpMessage = 'Teams Emergency Calling Policy')] [string]$WFTeamsEmergencyCallingPolicy, [Parameter(HelpMessage = 'Teams Emergency CallRouting Policy')] [string]$WFTeamsEmergencyCallRoutingPolicy, [Parameter(HelpMessage = 'Teams Emergency Address - Location')] [string]$WFTeamsEmergencyAddress, [Parameter(HelpMessage = 'No output is written by default, Switch PassThru will return changed object')] [switch]$PassThru ) begin { Write-Verbose -Message "[BEGIN ] $($MyInvocation.MyCommand)" # 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' } #Initialising Counters $private:StepsID0, $private:StepsID1 = Get-WriteBetterProgressSteps -Code $($MyInvocation.MyCommand.Definition) -MaxId 1 $private:ActivityID0 = $($MyInvocation.MyCommand.Name) [int] $private:CountID0 = [int] $private:CountID1 = 1 } #begin process { Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand)" $StatusID0 = 'Applying Users Emergency Calling and Call Routing Confugration' #region ACTION #region Teams Emergency Calling Policy $ActivityID0 = 'Teams Emergency Calling Policy' $CurrentOperationID0 = "Processing $ActivityID0" Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 if ($PSBoundParameters.ContainsKey('WFTeamsEmergencyCallingPolicy')) { try { Grant-CsTeamsEmergencyCallingPolicy -Identity $UserObject.Identity -PolicyName $WFTeamsEmergencyCallingPolicy -ErrorAction Stop } catch { $ErrorLog = $_.Exception.Message Write-Error -Message $ErrorLog if ( $WriteErrorLog.IsPresent ) { Write-TFErrorLog -ErrorLog $ErrorLog -Artifact $UserObject.UserPrincipalName } } } elseif ( $UserObject.TeamsEmergencyCallingPolicy ) { Write-Verbose -Message "Object '$($UserObject.UserPrincipalName)' - $ActivityID0 '$($UserObject.TeamsEmergencyCallingPolicy)' present" } else { Write-Verbose -Message "Object '$($UserObject.UserPrincipalName)' - $ActivityID0 not assigned - Dynamic configuration may be present (undetermined)" } #endregion #region Teams Emergency Call Routing Policy $ActivityID0 = 'Teams Emergency Call Routing Policy' $CurrentOperationID0 = "Processing $ActivityID0" Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 if ($PSBoundParameters.ContainsKey('WFTeamsEmergencyCallRoutingPolicy')) { try { Grant-CsTeamsEmergencyCallRoutingPolicy -Identity $UserObject.Identity -PolicyName $WFTeamsEmergencyCallRoutingPolicy -ErrorAction Stop } catch { $ErrorLog = $_.Exception.Message Write-Error -Message $ErrorLog if ( $WriteErrorLog.IsPresent ) { Write-TFErrorLog -ErrorLog $ErrorLog -Artifact $UserObject.UserPrincipalName } } } elseif ( $UserObject.TeamsEmergencyCallRoutingPolicy ) { Write-Verbose -Message "Object '$($UserObject.UserPrincipalName)' - $ActivityID0 '$($UserObject.TeamsEmergencyCallRoutingPolicy)' present" } else { Write-Verbose -Message "Object '$($UserObject.UserPrincipalName)' - $ActivityID0 not assigned - Dynamic configuration may be present (undetermined)" } #endregion #region Teams Emergency Address $ActivityID0 = 'Teams Emergency Address' $CurrentOperationID0 = "Processing $ActivityID0" Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 if ($PSBoundParameters.ContainsKey('WFTeamsEmergencyAddress')) { # This calls the TeamsFunctions Cmdlet try { Grant-TeamsEmergencyAddress -Identity $UserObject.Identity -PolicyName $WFTeamsEmergencyAddress -ErrorAction Stop } catch { $ErrorLog = $_.Exception.Message Write-Error -Message $ErrorLog if ( $WriteErrorLog.IsPresent ) { Write-TFErrorLog -ErrorLog $ErrorLog -Artifact $UserObject.UserPrincipalName } } } else { Write-Verbose -Message "Object '$($UserObject.UserPrincipalName)' - $ActivityID0 not queried. To gain feedback, please run Get-TeamsUserVoiceConfig with DiagnosticLevel 1 or higher" } #endregion #endregion #region OUTPUT $CurrentOperationID0 = 'Validation & Output' Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 $TeamsUVCObject = $null if ( $PassThru ) { $TeamsUVCObject = Get-TeamsUserVoiceConfig -UserPrincipalName "$($UserObject.UserPrincipalName)" -DiagnosticLevel 1 -WarningAction SilentlyContinue } Write-Progress -Id 0 -Activity $ActivityID0 -Completed Write-Output $TeamsUVCObject | Select-Object UserPrincipalName, Identity, InterpretedUserType, TeamsEmergencyCallingPolicy, TeamsEmergencyCallRoutingPolicy, TeamsEmergencyAddress #endregion } #process end { Write-Verbose -Message "[END ] $($MyInvocation.MyCommand)" } #end } #endregion #Preparing Splatting Parameter $parameters = $null $Parameters += @{ 'ErrorAction' = 'STOP' } #TODO Check whether this can be passed with $Args (removing the UPN or Object respectively!) if ( $PSBoundParameters.ContainsKey('TeamsEmergencyCallingPolicy') ) { $Parameters += @{ 'WFTeamsEmergencyCallingPolicy' = $TeamsEmergencyCallingPolicy } } if ( $PSBoundParameters.ContainsKey('TeamsEmergencyCallRoutingPolicy') ) { $Parameters += @{ 'WFTeamsEmergencyCallRoutingPolicy' = $TeamsEmergencyCallRoutingPolicy } } if ( $PSBoundParameters.ContainsKey('TeamsEmergencyAddress') ) { $Parameters += @{ 'WFTeamsEmergencyAddress' = $TeamsEmergencyAddress } } if ( $PassThru.IsPresent ) { $Parameters += @{ 'PassThru' = $PassThru } } } #begin process { Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand)" try { switch ($PSCmdlet.ParameterSetName) { 'UserprincipalName' { foreach ($User in $UserPrincipalName) { Write-Verbose -Message "[PROCESS] Processing provided UserPrincipalName '$User'" try { $CsUser = Get-CsOnlineUser -Identity "$User" -WarningAction SilentlyContinue -ErrorAction Stop } catch { $ErrorLog = "'$User' not found" Write-Error -Message $ErrorLog -Category ObjectNotFound if ( $WriteErrorLog.IsPresent ) { Write-TFErrorLog -ErrorLog $ErrorLog -Artifact $User } continue } if ($Force -or $PSCmdlet.ShouldProcess("$($CsUser.UserPrincipalName)", 'Set Emergency Configuration')) { SetTeamsUserEMSConfig -UserObject $CsUser @Parameters } } } 'Object' { foreach ($O in $Object) { Write-Verbose -Message "[PROCESS] Processing provided CsOnlineUser Object for '$($O.UserPrincipalName)'" if ($Force -or $PSCmdlet.ShouldProcess("$($CsUser.UserPrincipalName)", 'Set Emergency Configuration')) { SetTeamsUserEMSConfig -UserObject $O @Parameters } } } } } catch { Write-Error -Message $($_.Exception.Message) -ErrorAction $ErrorActionPreference } } #process end { Write-Verbose -Message "[END ] $($MyInvocation.MyCommand)" } #end } #Set-TeamsUserEmergencyConfiguration |