Public/UserCallingSettings/Set-TeamsUserDelegate.ps1
# Module: Orbit.Teams # Function: VoiceConfig # Author: David Eberhardt # Updated: 20-OCT-2022 # Status: RC function Set-TeamsUserDelegate { <# .SYNOPSIS Sets CallingSettings (Delegates) for one or more Users .DESCRIPTION Adds or sets one or more Delegates for one or more Users and applies the specified settings for all Delegates listed. Wrapper for Set-CsUserCallingDelegate that allows adding delegates (which is normally performed by New-CsUserCallingDelegate) .PARAMETER UserPrincipalName Required. UserPrincipalName (UPN) of the User(s) to add a delegate for. Can be specified using the ObjectId or the SIP address. .PARAMETER Delegate Required. The Identity of one or more delegates to add. Can be specified using the ObjectId or the SIP address. Selected settings will be set for all Delegates .PARAMETER MakeCalls Optional. Specifies whether delegate is allowed to make calls on behalf of the specified user .PARAMETER ReceiveCalls Optional. Specifies whether delegate is allowed to receive calls on behalf of the specified user If the Delegate does not exist and will be added, this parameter will be set to TRUE by this command. .PARAMETER ManageSettings Optional. Specifies whether delegate is allowed to change the delegate and calling settings for the specified user. .PARAMETER PassThru Optional. Displays object after applying settings .PARAMETER Force Suppresses confirmation prompt unless -Confirm is used explicitly. Tries to enable users and delegates for Enterprise Voice if they are not yet enabled. .PARAMETER WriteErrorLog Optional. If Errors are encountered, writes log to C:\Temp .EXAMPLE Set-TeamsUserDelegate [-UserPrincipalName] John@domain.com -Delegate Jill@domain.com -MakeCalls $true -WriteErrorLog Adds Jill as a Delegate to John or updates the existing settings Redirection to the Group will be disabled if it is used as an UnansweredTarget or as an AlsoRing/ForwardingTarget If errors are encountered, will write an Error-Log to C:\Temp .EXAMPLE Set-TeamsUserDelegate [-UserPrincipalName] John@domain.com -Add Jill@domain.com -Remove Jeff@domain.com Adds Jill as a member of John's Call Group and removes Jeff .EXAMPLE "John@domain.com" | Set-TeamsUserDelegate -DelegateTargets Jill@domain.com,Jeff@domain.com -TargetInOrder Replaces all members of John's Call Group (if any) and only adds Jill & Jeff. Also activates Call Group targeting in Order. InOrder is only available for Call Groups with 5 or less members. .EXAMPLE "John@domain.com","Jill@domain.com","Jeff@domain.com" | Set-TeamsUserDelegate -DelegateTargets Jill@domain.com,Jeff@domain.com,John@domain.com Replaces all members of John's, Jill's & Jeff's Call Group (if any) and only adds John's, Jill's & Jeff's. Users cannot be added to their own call group, so they will be removed. John will have Jeff & Jill as members, Jill will have John & Jeff and Jeff will have John & Jill. This is useful for bigger teams that all should have the same Call Group settings .EXAMPLE Set-TeamsUserDelegate Jill@domain.com -NotificationSetting Banner Sets Calling Settings for Jill in ALL Call Groups Jill is a member in to Banner. This is not the same as the override .EXAMPLE Set-TeamsUserDelegate Jeff@domain.com -GroupNotificationOverride Banner Sets Calling Settings for Jeff to override all Call Group Notifications for Jeff with Banner This overrides settings made by other userss in their Call Group as Jeff does not want to be rang for Call Group Calls. .INPUTS System.String .OUTPUTS System.Void System.Object .NOTES Wrapper for Set-CsUserCallingDelegate with a twist. Also replaces New-CsUserCallingDelegate as it adds the delegate if it is not needed. Allows for adding multiple delegates with the same settings. Default value for ReceiveCalls is changed: If not provided, defaults to true for newly added Delegates. For existing Delegates, value is only changed if provided to retain consistency. Other parameters are unchanged. For CallingSettings invoking AlsoRing, IfUnanswered or Forwarding please call Set-TeamsUserCallingSettings. .COMPONENT VoiceConfiguration .FUNCTIONALITY Applies User Calling Settings for Call Groups .LINK https://github.com/DEberhardt/Orbit/tree/main/docs/Orbit.Teams/Set-TeamsUserDelegate.md .LINK https://github.com/DEberhardt/Orbit/tree/main/docs/about/about_VoiceConfiguration.md .LINK https://github.com/DEberhardt/Orbit/tree/main/docs/ #> [CmdletBinding( SupportsShouldProcess, PositionalBinding = $false )] [Alias('Set-TeamsUD')] [OutputType([PSCustomObject])] param( [Parameter(Mandatory, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)] [Alias('ObjectId', 'Identity', 'Delegator', 'SipUri')] [ValidateScript( { If ($script:OrbitRegexUPN.isMatch($_) -or $_ -match '^[0-9a-f]{8}-([0-9a-f]{4}\-){3}[0-9a-f]{12}$') { $True } else { throw [System.Management.Automation.ValidationMetadataException] 'Value must be a valid UPN or ObjectId' } })] [string[]]$UserPrincipalName, [Parameter(Mandatory, ValueFromPipelineByPropertyName, HelpMessage = 'The Identity of the delegate to add. Can be specified using the ObjectId or the SIP address.')] [Alias('Id')] [ValidateScript( { If ($script:OrbitRegexUPN.isMatch($_) -or $_ -match '^[0-9a-f]{8}-([0-9a-f]{4}\-){3}[0-9a-f]{12}$') { $True } else { throw [System.Management.Automation.ValidationMetadataException] 'Value must be a valid UPN or ObjectId' } })] [string[]]$Delegate, [Parameter(HelpMessage = 'Specifies whether delegate is allowed to make calls on behalf of the specified user.')] [boolean]$MakeCalls, [Parameter(HelpMessage = 'Specifies whether delegate is allowed to receive calls on behalf of the specified user.')] [boolean]$ReceiveCalls, [Parameter(HelpMessage = 'Specifies whether delegate is allowed to change the delegate and calling settings for the specified user.')] [boolean]$ManageSettings, [Parameter(HelpMessage = 'No output is written by default, Switch PassThru will return changed object')] [switch]$PassThru, [Parameter(HelpMessage = 'Tries to bring enable users for Enterprise Voice if they are not enabled.')] [switch]$Force, [Parameter(HelpMessage = 'Writes a Log File of Errors to C:\Temp')] [switch]$WriteErrorLog ) #param begin { Show-OrbitFunctionStatus -Level RC Write-Verbose -Message "[BEGIN ] $($MyInvocation.MyCommand)" # Asserting MicrosoftTeams Connection if ( -not (Assert-MicrosoftTeamsConnection) ) { throw 'Connection to Microsoft Teams not established. Please validate connection' } # Setting Preference Variables according to Upstream settings if (-not $PSBoundParameters['Verbose']) { $VerbosePreference = $PSCmdlet.SessionState.PSVariable.GetValue('VerbosePreference') } if (-not $PSBoundParameters['Confirm']) { $ConfirmPreference = $PSCmdlet.SessionState.PSVariable.GetValue('ConfirmPreference') } if (-not $PSBoundParameters['WhatIf']) { $WhatIfPreference = $PSCmdlet.SessionState.PSVariable.GetValue('WhatIfPreference') } $DebugPreference = if (-not $PSBoundParameters['Debug']) { $PSCmdlet.SessionState.PSVariable.GetValue('DebugPreference') } else { 'Continue' } $InformationPreference = if ( $PSBoundParameters['InformationAction']) { $PSCmdlet.SessionState.PSVariable.GetValue('InformationAction') } else { 'Continue' } } #begin process { Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand)" foreach ($User in $UserPrincipalName) { #region Querying Identity $UserCallingSettings = $null try { $UserCallingSettings = Get-CsUserCallingSettings -Identity $User -ErrorAction Stop } catch { if ( $_.Exception.Message.Contains('Could not resolve user') -or $_.Errordetails.Message.Contains('was not found') ) { $ErrorMessage = "User '$User' - User not found" Write-Verbose $ErrorMessage } else { $ErrorMessage = "User '$User' - Error: $($_.Errordetails.Message)" Write-Error -Message $ErrorMessage } if ( $WriteErrorLog.IsPresent ) { Write-OrbitErrorLog -ErrorLog $ErrorMessage -Artifact "$User" } continue } $CurrentDelegates = $null $CurrentDelegates = $UserCallingSettings.Delegates #endregion #region Processing Delegates foreach ( $Dele in $Delegate ) { #region Querying Delegate calling settings - if this fails - this indicates that the user is not enabled try { $DelegateUser = Get-CsOnlineUser -Identity $Dele -ErrorAction Stop #$DelegateCallingSettings = Get-CsUserCallingSettings -Identity $Dele -ErrorAction Stop # If delegate is not found in the current list of Delegates, it will be added as a new delegate with default settings (ReceiveCalls) $NewDelegate = ($DelegateUser.SipAddress -in $CurrentDelegates.Id) } catch { if ( $_.Exception.Message.Contains('Could not resolve user') -or $_.Errordetails.Message.Contains('was not found') ) { $ErrorMessage = "Delegate '$User' - User not found" Write-Verbose $ErrorMessage } else { $ErrorMessage = "Delegate '$User' - Error: $($_.Errordetails.Message)" Write-Error -Message $ErrorMessage } if ( $WriteErrorLog.IsPresent ) { Write-OrbitErrorLog -ErrorLog $ErrorMessage -Artifact "$User" } continue } #endregion #region Asserting Delegate state try { $Assertion = $null $Assertion = Assert-TeamsCallableEntity -Object $DelegateUser -RequireEV -InformationAction SilentlyContinue -WarningAction SilentlyContinue -ErrorAction Stop if ($Assertion) { # Preparing Splatting Object $CsUserCallingDelegate = $null $CsUserCallingDelegate = @{ Identity = $UserCallingSettings.SipUri Delegate = $DelegateUser.SipAddress ErrorAction = 'Stop' } } else { Write-Warning -Message "Delegate '$($DelegateUser.UserPrincipalName)' could not be enabled for EnterpriseVoice - Omitting Delegate" continue } } catch { Write-Warning -Message "Delegate '$($DelegateUser.UserPrincipalName)' - Assertion failed with Error: $($_.Exception.Message)" continue } #endregion #region SETTINGS if ( -not $PSBoundParameters['MakeCalls'] -and ` -not $PSBoundParameters['ReceiveCalls'] -and ` -not $PSBoundParameters['ManageSettings'] ) { Write-Error -Message "User '$User' - No Settings to be applied." break } else { if ( $NewDelegate ) { $CsUserCallingDelegate.MakeCalls = if ( $PSBoundParameters['MakeCalls'] ) { $CsUserCallingDelegate.MakeCalls = $MakeCalls } else { $false } $CsUserCallingDelegate.ReceiveCalls = if ( $PSBoundParameters['ReceiveCalls'] ) { $CsUserCallingDelegate.ReceiveCalls = $ReceiveCalls } else { $true } $CsUserCallingDelegate.MakeCalls = if ( $PSBoundParameters['ManageSettings'] ) { $CsUserCallingDelegate.ManageSettings = $ManageSettings } else { $false } } else { if ( $PSBoundParameters['MakeCalls'] ) { $CsUserCallingDelegate.MakeCalls = $MakeCalls } if ( $PSBoundParameters['ReceiveCalls'] ) { $CsUserCallingDelegate.ReceiveCalls = $ReceiveCalls } if ( $PSBoundParameters['ManageSettings'] ) { $CsUserCallingDelegate.ManageSettings = $ManageSettings } } } #endregion #region ACTION try { if ( $NewDelegate ) { # New Delegate will be added Write-Verbose -Message "User '$($CsUserCallingDelegate.Identity)'; Delegate '$($CsUserCallingDelegate.Delegate) - Delegate not present, adding delegate" -Verbose if ($Force -or $PSCmdlet.ShouldProcess("Calling New-CsUserCallingDelegate adding $($CsUserCallingDelegate.Delegate)")) { New-CsUserCallingDelegate @CsUserCallingDelegate -ErrorAction Stop } } else { # Re-apply/change Write-Verbose -Message "User '$($CsUserCallingDelegate.Identity)'; Delegate '$($CsUserCallingDelegate.Delegate) - Delegate already set, updating record" if ($Force -or $PSCmdlet.ShouldProcess("Calling Set-CsUserCallingDelegate adding $($CsUserCallingDelegate.Delegate)")) { Set-CsUserCallingDelegate @CsUserCallingDelegate -ErrorAction Stop } } } catch { #REST Errors behave differently. $_.Exception.Message only shows "Exception of type 'System.Exception' was thrown." $ExceptionMessage = $_.Errordetails.Message if ( $ExceptionMessage.Contains('Object not in correct state') ) { $ErrorMessage = "User '$($CsUserCallingDelegate.Identity)'; Delegate '$($CsUserCallingDelegate.Delegate) - Delegate not in the correct state: $ExceptionMessage " Write-Verbose $ErrorMessage } else { $ErrorMessage = "User '$($CsUserCallingDelegate.Identity)'; Delegate '$($CsUserCallingDelegate.Delegate) - Error applying settings: $ExceptionMessage " Write-Error -Message $ErrorMessage } if ( $WriteErrorLog.IsPresent ) { Write-OrbitErrorLog -ErrorLog $ErrorMessage -Artifact "$User" } continue } #endregion } #endregion # OUTPUT $OutputObject = $null if ( $PassThru ) { $OutputObject = Get-TeamsUserCallingSettings -UserPrincipalName $User -Show Delegates } Write-Output $OutputObject } } #process end { Write-Verbose -Message "[END ] $($MyInvocation.MyCommand)" } #end } #Set-TeamsUserDelegate |