DSCResources/MSFT_O365OrgSettings/MSFT_O365OrgSettings.psm1

function Get-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateSet('Yes')]
        [String]
        $IsSingleInstance,

        [Parameter()]
        [System.Boolean]
        $CortanaEnabled,

        [Parameter()]
        [System.Boolean]
        $AppsAndServicesIsOfficeStoreEnabled,

        [Parameter()]
        [System.Boolean]
        $AppsAndServicesIsAppAndServicesTrialEnabled,

        [Parameter()]
        [System.Boolean]
        $DynamicsCustomerVoiceIsRestrictedSurveyAccessEnabled,

        [Parameter()]
        [System.Boolean]
        $DynamicsCustomerVoiceIsRecordIdentityByDefaultEnabled,

        [Parameter()]
        [System.Boolean]
        $DynamicsCustomerVoiceIsInOrgFormsPhishingScanEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsExternalSendFormEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsExternalShareCollaborationEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsExternalShareResultEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsExternalShareTemplateEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsRecordIdentityByDefaultEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsBingImageSearchEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsInOrgFormsPhishingScanEnabled,

        [Parameter()]
        [System.Boolean]
        $M365WebEnableUsersToOpenFilesFrom3PStorage,

        [Parameter()]
        [System.Boolean]
        $PlannerAllowCalendarSharing,

        [Parameter()]
        [System.Boolean]
        $MicrosoftVivaBriefingEmail,

        [Parameter()]
        [System.Boolean]
        $ToDoIsPushNotificationEnabled,

        [Parameter()]
        [System.Boolean]
        $ToDoIsExternalJoinEnabled,

        [Parameter()]
        [System.Boolean]
        $ToDoIsExternalShareEnabled,

        [Parameter()]
        [System.Boolean]
        $VivaInsightsWebExperience,

        [Parameter()]
        [System.Boolean]
        $VivaInsightsDigestEmail,

        [Parameter()]
        [System.Boolean]
        $VivaInsightsOutlookAddInAndInlineSuggestions,

        [Parameter()]
        [System.Boolean]
        $VivaInsightsScheduleSendSuggestions,

        [Parameter()]
        [System.Boolean]
        $AdminCenterReportDisplayConcealedNames,

        [Parameter()]
        [System.String]
        [ValidateSet('current', 'monthlyEnterprise', 'semiAnnual')]
        $InstallationOptionsUpdateChannel,

        [Parameter()]
        [System.String[]]
        [ValidateSet('isVisioEnabled', 'isSkypeForBusinessEnabled', 'isProjectEnabled', 'isMicrosoft365AppsEnabled')]
        $InstallationOptionsAppsForWindows,

        [Parameter()]
        [System.String[]]
        [ValidateSet('isSkypeForBusinessEnabled', 'isMicrosoft365AppsEnabled')]
        $InstallationOptionsAppsForMac,

        [Parameter()]
        [ValidateSet('Present', 'Absent')]
        [System.String]
        $Ensure = 'Present',

        [Parameter()]
        [System.Management.Automation.PSCredential]
        $Credential,

        [Parameter()]
        [System.String]
        $ApplicationId,

        [Parameter()]
        [System.String]
        $TenantId,

        [Parameter()]
        [System.Management.Automation.PSCredential]
        $ApplicationSecret,

        [Parameter()]
        [System.String]
        $CertificateThumbprint,

        [Parameter()]
        [Switch]
        $ManagedIdentity,

        [Parameter()]
        [System.String[]]
        $AccessTokens
    )

    $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' `
        -InboundParameters $PSBoundParameters

    $ConnectionModeTasks = New-M365DSCConnection -Workload 'Tasks' `
        -InboundParameters $PSBoundParameters

    # Workaround for issue when if connected to S+C prior to calling cmdlet, an error about an invalid token is thrown.
    # If connected to S+C, then we need to re-initialize the connection to EXO.
    if ((Get-MSCloudLoginConnectionProfile -Workload SecurityComplianceCenter).Connected -and `
            (Get-MSCloudLoginConnectionProfile -Workload ExchangeOnline).Connected)
    {
        Reset-MSCloudLoginConnectionProfileContext
    }
    $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' `
        -InboundParameters $PSBoundParameters

    #Ensure the proper dependencies are installed in the current environment.
    Confirm-M365DSCDependencies

    #region Telemetry
    $ResourceName = $MyInvocation.MyCommand.ModuleName -replace 'MSFT_', ''
    $CommandName = $MyInvocation.MyCommand
    $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName `
        -CommandName $CommandName `
        -Parameters $PSBoundParameters
    Add-M365DSCTelemetryEvent -Data $data
    #endregion

    $nullReturn = @{
        IsSingleInstance = $IsSingleInstance
        Ensure           = 'Absent'
    }

    $results = @{
        IsSingleInstance      = 'Yes'
        Credential            = $Credential
        ApplicationId         = $ApplicationId
        TenantId              = $TenantId
        ApplicationSecret     = $ApplicationSecret
        CertificateThumbprint = $CertificateThumbprint
        Managedidentity       = $ManagedIdentity.IsPresent
        AccessTokens          = $AccessTokens
    }
    try
    {
        $OfficeOnlineId = 'c1f33bc0-bdb4-4248-ba9b-096807ddb43e'
        $M365WebEnableUsersToOpenFilesFrom3PStorageValue = Get-MgServicePrincipal -Filter "appId eq '$OfficeOnlineId'" -Property 'AccountEnabled' -ErrorAction SilentlyContinue
        if ($null -eq $M365WebEnableUsersToOpenFilesFrom3PStorageValue)
        {
            Write-Verbose -Message 'Registering the Office on the web Service Principal'
            New-MgServicePrincipal -AppId 'c1f33bc0-bdb4-4248-ba9b-096807ddb43e' -ErrorAction Stop | Out-Null
            $M365WebEnableUsersToOpenFilesFrom3PStorageValue = Get-MgServicePrincipal -Filter "appId eq '$OfficeOnlineId'" -Property 'AccountEnabled' -ErrorAction SilentlyContinue
        }

        if ($null -ne $M365WebEnableUsersToOpenFilesFrom3PStorageValue)
        {
            $results += @{
                M365WebEnableUsersToOpenFilesFrom3PStorage = $M365WebEnableUsersToOpenFilesFrom3PStorageValue.AccountEnabled
            }
        }

        # Planner iCal settings
        $PlannerSettings = Get-M365DSCO365OrgSettingsPlannerConfig
        if ($null -ne $PlannerSettings)
        {
            $results += @{
                PlannerAllowCalendarSharing = $PlannerSettings.allowCalendarSharing
            }
        }

        # Cortana settings
        $CortanaId = '0a0a29f9-0a25-49c7-94bf-c53c3f8fa69d'
        $CortanaEnabledValue = Get-MgServicePrincipal -Filter "appId eq '$CortanaId'" -Property 'AccountEnabled'
        if ($null -ne $CortanaEnabledValue)
        {
            $results += @{
                CortanaEnabled = $CortanaEnabledValue.AccountEnabled
            }
        }

        # DEPRECATED - Microsoft Viva Briefing Email
        <#
        $vivaBriefingEmailValue = $false
        try
        {
            $currentBriefingConfig = Get-DefaultTenantBriefingConfig -ErrorAction Stop -Verbose:$false
            if ($currentBriefingConfig.IsEnabledByDefault -eq 'opt-in')
            {
                $vivaBriefingEmailValue = $true
            }
        }
        catch
        {
            if ($_.Exception.Message -like "*Unexpected character encountered while parsing value*")
            {
                $vivaBriefingEmailValue = $true
            }
            elseif ($_.Exception.Message -like "*A task was canceled*")
            {
                $retries = 1
                $errorContent = $null
                while ($retries -le 5)
                {
                    try
                    {
                        Start-Sleep -Seconds 2
                        $currentBriefingConfig = Get-DefaultTenantBriefingConfig -ErrorAction Stop -Verbose:$false
                    }
                    catch
                    {
                        $errorContent = $_
                        $retries++
                    }
                }
                if ($null -eq $currentBriefingConfig)
                {
                    throw $errorContent
                }
                else
                {
                    if ($currentBriefingConfig.IsEnabledByDefault -eq 'opt-in')
                    {
                        $vivaBriefingEmailValue = $true
                    }
                }
            }
            else
            {
                throw $_
            }
        }
        $results += @{
            MicrosoftVivaBriefingEmail = $vivaBriefingEmailValue
        }#>


        # Viva Insights settings
        $currentVivaInsightsSettings = Get-DefaultTenantMyAnalyticsFeatureConfig -Verbose:$false
        if ($null -ne $currentVivaInsightsSettings)
        {
            $results += @{
                VivaInsightsDigestEmail                      = $currentVivaInsightsSettings.IsDigestEmailEnabled
                VivaInsightsOutlookAddInAndInlineSuggestions = $currentVivaInsightsSettings.IsAddInEnabled
                VivaInsightsScheduleSendSuggestions          = $currentVivaInsightsSettings.IsScheduleSendEnabled
                VivaInsightsWebExperience                    = $currentVivaInsightsSettings.IsDashboardEnabled
            }
        }

        $MRODeviceManagerService = 'ebe0c285-db95-403f-a1a3-a793bd6d7767'
        try
        {
            $servicePrincipal = Get-MgServicePrincipal -Filter "appid eq 'ebe0c285-db95-403f-a1a3-a793bd6d7767'"
            if ($null -eq $servicePrincipal)
            {
                Write-Verbose -Message 'Registering the MRO Device Manager Service Principal'
                New-MgServicePrincipal -AppId 'ebe0c285-db95-403f-a1a3-a793bd6d7767' -ErrorAction Stop | Out-Null
            }
        }
        catch
        {
            Write-Verbose -Message $_
        }

        # Reports Display Settings
        $AdminCenterReportDisplayConcealedNamesValue = Get-M365DSCOrgSettingsAdminCenterReport
        if ($null -ne $AdminCenterReportDisplayConcealedNamesValue)
        {
            $results += @{
                AdminCenterReportDisplayConcealedNames = $AdminCenterReportDisplayConcealedNamesValue.displayConcealedNames
            }
        }

        # Installation Options
        $installationOptions = Get-M365DSCOrgSettingsInstallationOptions -AuthenticationOption $ConnectionModeTasks
        if ($null -ne $installationOptions)
        {
            $appsForWindowsValue = @()
            foreach ($key in $installationOptions.appsForWindows.Keys)
            {
                if ($installationOptions.appsForWindows.$key)
                {
                    $appsForWindowsValue += $key
                }
            }
            $appsForMacValue = @()
            foreach ($key in $installationOptions.appsForMac.Keys)
            {
                if ($installationOptions.appsForMac.$key)
                {
                    $appsForMacValue += $key
                }
            }

            $results += @{
                InstallationOptionsUpdateChannel  = $installationOptions.updateChannel
                InstallationOptionsAppsForWindows = $appsForWindowsValue
                InstallationOptionsAppsForMac     = $appsForMacValue
            }
        }

        # Forms
        $FormsSettings = Get-M365DSCOrgSettingsForms
        if ($null -ne $FormsSettings)
        {
            $results += @{
                FormsIsExternalSendFormEnabled           = $FormsSettings.isExternalSendFormEnabled
                FormsIsExternalShareCollaborationEnabled = $FormsSettings.isExternalShareCollaborationEnabled
                FormsIsExternalShareResultEnabled        = $FormsSettings.isExternalShareResultEnabled
                FormsIsExternalShareTemplateEnabled      = $FormsSettings.isExternalShareTemplateEnabled
                FormsIsRecordIdentityByDefaultEnabled    = $FormsSettings.isRecordIdentityByDefaultEnabled
                FormsIsBingImageSearchEnabled            = $FormsSettings.isBingImageSearchEnabled
                FormsIsInOrgFormsPhishingScanEnabled     = $FormsSettings.isInOrgFormsPhishingScanEnabled
            }
        }

        # DynamicsCustomerVoice
        $DynamicCustomerVoiceSettings = Get-M365DSCOrgSettingsDynamicsCustomerVoice
        if ($null -ne $DynamicCustomerVoiceSettings)
        {
            $results += @{
                DynamicsCustomerVoiceIsRestrictedSurveyAccessEnabled  = $DynamicCustomerVoiceSettings.isRestrictedSurveyAccessEnabled
                DynamicsCustomerVoiceIsRecordIdentityByDefaultEnabled = $DynamicCustomerVoiceSettings.isRecordIdentityByDefaultEnabled
                DynamicsCustomerVoiceIsInOrgFormsPhishingScanEnabled  = $DynamicCustomerVoiceSettings.isInOrgFormsPhishingScanEnabled
            }
        }

        # Apps and Services
        $AppsAndServicesSettings = Get-M365DSCOrgSettingsAppsAndServices
        if ($null -ne $AppsAndServicesSettings)
        {
            $results += @{
                AppsAndServicesIsOfficeStoreEnabled         = $AppsAndServicesSettings.isOfficeStoreEnabled
                AppsAndServicesIsAppAndServicesTrialEnabled = $AppsAndServicesSettings.IsAppAndServicesTrialEnabled
            }
        }

        # To do
        $ToDoSettings = Get-M365DSCOrgSettingsToDo
        if ($null -ne $ToDoSettings)
        {
            $results += @{
                ToDoIsPushNotificationEnabled = $ToDoSettings.IsPushNotificationEnabled
                ToDoIsExternalJoinEnabled     = $ToDoSettings.IsExternalJoinEnabled
                ToDoIsExternalShareEnabled    = $ToDoSettings.IsExternalShareEnabled
            }
        }

        return $results
    }
    catch
    {
        New-M365DSCLogEntry -Message 'Error retrieving data:' `
            -Exception $_ `
            -Source $($MyInvocation.MyCommand.Source) `
            -TenantId $TenantId `
            -Credential $Credential

        return $nullReturn
    }
}

function Set-TargetResource
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateSet('Yes')]
        [String]
        $IsSingleInstance,

        [Parameter()]
        [System.Boolean]
        $CortanaEnabled,

        [Parameter()]
        [System.Boolean]
        $AppsAndServicesIsOfficeStoreEnabled,

        [Parameter()]
        [System.Boolean]
        $AppsAndServicesIsAppAndServicesTrialEnabled,

        [Parameter()]
        [System.Boolean]
        $DynamicsCustomerVoiceIsRestrictedSurveyAccessEnabled,

        [Parameter()]
        [System.Boolean]
        $DynamicsCustomerVoiceIsRecordIdentityByDefaultEnabled,

        [Parameter()]
        [System.Boolean]
        $DynamicsCustomerVoiceIsInOrgFormsPhishingScanEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsExternalSendFormEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsExternalShareCollaborationEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsExternalShareResultEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsExternalShareTemplateEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsRecordIdentityByDefaultEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsBingImageSearchEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsInOrgFormsPhishingScanEnabled,

        [Parameter()]
        [System.Boolean]
        $M365WebEnableUsersToOpenFilesFrom3PStorage,

        [Parameter()]
        [System.Boolean]
        $PlannerAllowCalendarSharing,

        [Parameter()]
        [System.Boolean]
        $MicrosoftVivaBriefingEmail,

        [Parameter()]
        [System.Boolean]
        $ToDoIsPushNotificationEnabled,

        [Parameter()]
        [System.Boolean]
        $ToDoIsExternalJoinEnabled,

        [Parameter()]
        [System.Boolean]
        $ToDoIsExternalShareEnabled,

        [Parameter()]
        [System.Boolean]
        $VivaInsightsWebExperience,

        [Parameter()]
        [System.Boolean]
        $VivaInsightsDigestEmail,

        [Parameter()]
        [System.Boolean]
        $VivaInsightsOutlookAddInAndInlineSuggestions,

        [Parameter()]
        [System.Boolean]
        $VivaInsightsScheduleSendSuggestions,

        [Parameter()]
        [System.Boolean]
        $AdminCenterReportDisplayConcealedNames,

        [Parameter()]
        [System.String]
        [ValidateSet('current', 'monthlyEnterprise', 'semiAnnual')]
        $InstallationOptionsUpdateChannel,

        [Parameter()]
        [System.String[]]
        [ValidateSet('isVisioEnabled', 'isSkypeForBusinessEnabled', 'isProjectEnabled', 'isMicrosoft365AppsEnabled')]
        $InstallationOptionsAppsForWindows,

        [Parameter()]
        [System.String[]]
        [ValidateSet('isSkypeForBusinessEnabled', 'isMicrosoft365AppsEnabled')]
        $InstallationOptionsAppsForMac,

        [Parameter()]
        [ValidateSet('Present', 'Absent')]
        [System.String]
        $Ensure = 'Present',

        [Parameter()]
        [System.Management.Automation.PSCredential]
        $Credential,

        [Parameter()]
        [System.String]
        $ApplicationId,

        [Parameter()]
        [System.String]
        $TenantId,

        [Parameter()]
        [System.Management.Automation.PSCredential]
        $ApplicationSecret,

        [Parameter()]
        [System.String]
        $CertificateThumbprint,

        [Parameter()]
        [Switch]
        $ManagedIdentity,

        [Parameter()]
        [System.String[]]
        $AccessTokens
    )

    if ($PSBoundParameters.ContainsKey('Ensure') -and $Ensure -eq 'Absent')
    {
        throw 'This resource is not able to remove the Org settings and therefore only accepts Ensure=Present.'
    }

    #Ensure the proper dependencies are installed in the current environment.
    Confirm-M365DSCDependencies

    #region Telemetry
    $ResourceName = $MyInvocation.MyCommand.ModuleName -replace 'MSFT_', ''
    $CommandName = $MyInvocation.MyCommand
    $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName `
        -CommandName $CommandName `
        -Parameters $PSBoundParameters
    Add-M365DSCTelemetryEvent -Data $data
    #endregion

    $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' `
        -InboundParameters $PSBoundParameters
    $currentValues = Get-TargetResource @PSBoundParameters

    if ($PSBoundParameters.ContainsKey('M365WebEnableUsersToOpenFilesFrom3PStorage') -and `
        ($M365WebEnableUsersToOpenFilesFrom3PStorage -ne $currentValues.M365WebEnableUsersToOpenFilesFrom3PStorage))
    {
        Write-Verbose -Message "Updating the Microsoft 365 On the Web setting to {$M365WebEnableUsersToOpenFilesFrom3PStorage}"
        $OfficeOnlineId = 'c1f33bc0-bdb4-4248-ba9b-096807ddb43e'
        $M365WebEnableUsersToOpenFilesFrom3PStorageValue = Get-MgServicePrincipal -Filter "appId eq '$OfficeOnlineId'" -Property 'AccountEnabled, Id'
        Update-MgServicePrincipal -ServicePrincipalId $($M365WebEnableUsersToOpenFilesFrom3PStorageValue.Id) `
            -AccountEnabled:$M365WebEnableUsersToOpenFilesFrom3PStorage
    }
    if ($PSBoundParameters.ContainsKey('PlannerAllowCalendarSharing') -and `
        ($PlannerAllowCalendarSharing -ne $currentValues.PlannerAllowCalendarSharing))
    {
        Write-Verbose -Message "Updating the Planner Allow Calendar Sharing setting to {$PlannerAllowCalendarSharing}"
        Set-M365DSCO365OrgSettingsPlannerConfig -AllowCalendarSharing $PlannerAllowCalendarSharing
    }

    if ($PSBoundParameters.ContainsKey('CortanaEnabled') -and `
        ($CortanaEnabled -ne $currentValues.CortanaEnabled))
    {
        $CortanaId = '0a0a29f9-0a25-49c7-94bf-c53c3f8fa69d'
        $CortanaEnabledValue = Get-MgServicePrincipal -Filter "appId eq '$CortanaId'" -Property 'AccountEnabled, Id'

        if ($null -ne $CortanaEnabledValue.Id)
        {
            Write-Verbose -Message "Updating the Cortana setting to {$CortanaEnabled}"
            Update-MgServicePrincipal -ServicePrincipalId $($CortanaEnabledValue.Id) `
                -AccountEnabled:$CortanaEnabled
        }
    }

    # Microsoft Viva Briefing Email
    if ($null -ne $MicrosoftVivaBriefingEmail)
    {
        Write-Verbose -Message 'DEPRECATED - The MicrosoftVivaBriefingEmail parameter is deprecated and will be ignored.'
    }
    #$briefingValue = 'opt-out'

    <# DEPRECATED
    if ($currentValues.MicrosoftVivaBriefingEmail -and $MicrosoftVivaBriefingEmail -ne $currentValues.MicrosoftVivaBriefingEmail)
    {
        Write-Verbose -Message "Updating Microsoft Viva Briefing Email settings."
        Set-DefaultTenantBriefingConfig -IsEnabledByDefault $briefingValue -Verbose:$false | Out-Null
    }#>


    # Viva Insights
    if ($PSBoundParameters.ContainsKey('VivaInsightsWebExperience') -and `
        ($currentValues.VivaInsightsWebExperience -ne $VivaInsightsWebExperience))
    {
        Write-Verbose -Message 'Updating Viva Insights settings for Web Experience'
        Set-DefaultTenantMyAnalyticsFeatureConfig -Feature 'Dashboard' -IsEnabled $VivaInsightsWebExperience -Verbose:$false | Out-Null
    }

    if ($PSBoundParameters.ContainsKey('VivaInsightsDigestEmail') -and `
        ($currentValues.VivaInsightsDigestEmail -ne $VivaInsightsDigestEmail))
    {
        Write-Verbose -Message 'Updating Viva Insights settings for Digest Email'
        Set-DefaultTenantMyAnalyticsFeatureConfig -Feature 'Digest-email' -IsEnabled $VivaInsightsDigestEmail -Verbose:$false | Out-Null
    }

    if ($PSBoundParameters.ContainsKey('VivaInsightsOutlookAddInAndInlineSuggestions') -and `
        ($currentValues.VivaInsightsOutlookAddInAndInlineSuggestions -ne $VivaInsightsOutlookAddInAndInlineSuggestions))
    {
        Write-Verbose -Message 'Updating Viva Insights settings for Addin and Inline Suggestions'
        Set-DefaultTenantMyAnalyticsFeatureConfig -Feature 'Add-In' -IsEnabled $VivaInsightsOutlookAddInAndInlineSuggestions -Verbose:$false | Out-Null
    }

    if ($PSBoundParameters.ContainsKey('VivaInsightsScheduleSendSuggestions') -and `
        ($currentValues.VivaInsightsScheduleSendSuggestions -ne $VivaInsightsScheduleSendSuggestions))
    {
        Write-Verbose -Message 'Updating Viva Insights settings for ScheduleSendSuggestions'
        Set-DefaultTenantMyAnalyticsFeatureConfig -Feature 'Scheduled-send' -IsEnabled $VivaInsightsScheduleSendSuggestions -Verbose:$false | Out-Null
    }

    # Reports Display Names
    $AdminCenterReportDisplayConcealedNamesEnabled = Get-M365DSCOrgSettingsAdminCenterReport
    if ($PSBoundParameters.ContainsKey('AdminCenterReportDisplayConcealedNames') -and `
        ($AdminCenterReportDisplayConcealedNames -ne $AdminCenterReportDisplayConcealedNamesEnabled.displayConcealedNames))
    {
        Write-Verbose -Message "Updating the Admin Center Report Display Concealed Names setting to {$AdminCenterReportDisplayConcealedNames}"
        Update-M365DSCOrgSettingsAdminCenterReport -DisplayConcealedNames $AdminCenterReportDisplayConcealedNames
    }

    # Apps Installation
    if (($PSBoundParameters.ContainsKey('InstallationOptionsAppsForWindows') -or `
                $PSBoundParameters.ContainsKey('InstallationOptionsAppsForMac')) -and `
        ($null -ne (Compare-Object -ReferenceObject $currentValues.InstallationOptionsAppsForWindows -DifferenceObject $InstallationOptionsAppsForWindows) -or `
                $null -ne (Compare-Object -ReferenceObject $currentValues.InstallationOptionsAppsForMac -DifferenceObject $InstallationOptionsAppsForMac)))
    {
        $ConnectionModeTasks = New-M365DSCConnection -Workload 'Tasks' `
            -InboundParameters $PSBoundParameters
        $InstallationOptions = Get-M365DSCOrgSettingsInstallationOptions -AuthenticationOption $ConnectionModeTasks
        $InstallationOptionsToUpdate = @{
            updateChannel  = ''
            appsForWindows = @{
                isMicrosoft365AppsEnabled = $false
                isProjectEnabled          = $false
                isSkypeForBusinessEnabled = $false
                isVisioEnabled            = $false
            }
            appsForMac     = @{
                isMicrosoft365AppsEnabled = $false
                isSkypeForBusinessEnabled = $false
            }
        }

        if ($PSBoundParameters.ContainsKey('InstallationOptionsUpdateChannel') -and `
            ($InstallationOptionsUpdateChannel -ne $InstallationOptions.updateChannel))
        {
            $InstallationOptionsToUpdate.updateChannel = $InstallationOptionsUpdateChannel
        }
        else
        {
            $InstallationOptionsToUpdate.Remove('updateChannel') | Out-Null
        }

        if ($PSBoundParameters.ContainsKey('InstallationOptionsAppsForWindows'))
        {
            foreach ($key in $InstallationOptionsAppsForWindows)
            {
                $InstallationOptionsToUpdate.appsForWindows.$key = $true
            }
        }
        else
        {
            $InstallationOptionsToUpdate.Remove('appsForWindows') | Out-Null
        }

        if ($PSBoundParameters.ContainsKey('InstallationOptionsAppsForMac'))
        {
            foreach ($key in $InstallationOptionsAppsForMac)
            {
                $InstallationOptionsToUpdate.appsForMac.$key = $true
            }
        }
        else
        {
            $InstallationOptionsToUpdate.Remove('appsForMac') | Out-Null
        }

        if ($InstallationOptionsToUpdate.Keys.Count -gt 0)
        {
            Write-Verbose -Message "Updating O365 Installation Options with $(Convert-M365DscHashtableToString -Hashtable $InstallationOptionsToUpdate)"
            Update-M365DSCOrgSettingsInstallationOptions -Options $InstallationOptionsToUpdate `
                -AuthenticationOption $ConnectionModeTasks
        }
    }

    # Forms
    $FormsParametersToUpdate = @{}
    if ($PSBoundParameters.ContainsKey('FormsIsExternalSendFormEnabled') -and `
        ($FormsIsExternalSendFormEnabled -ne $currentValues.FormsIsExternalSendFormEnabled))
    {
        $FormsParametersToUpdate.Add('isExternalSendFormEnabled', $FormsIsExternalSendFormEnabled)
    }
    if ($PSBoundParameters.ContainsKey('FormsIsExternalShareCollaborationEnabled') -and `
        ($FormsIsExternalShareCollaborationEnabled -ne $currentValues.FormsIsExternalShareCollaborationEnabled))
    {
        $FormsParametersToUpdate.Add('isExternalShareCollaborationEnabled', $FormsIsExternalShareCollaborationEnabled)
    }
    if ($PSBoundParameters.ContainsKey('FormsIsExternalShareResultEnabled') -and `
        ($FormsIsExternalShareResultEnabled -ne $currentValues.FormsIsExternalShareResultEnabled))
    {
        $FormsParametersToUpdate.Add('isExternalShareResultEnabled', $FormsIsExternalShareResultEnabled)
    }
    if ($PSBoundParameters.ContainsKey('FormsIsExternalShareTemplateEnabled') -and `
        ($FormsIsExternalShareTemplateEnabled -ne $currentValues.FormsIsExternalShareTemplateEnabled))
    {
        $FormsParametersToUpdate.Add('isExternalShareTemplateEnabled', $FormsIsExternalShareTemplateEnabled)
    }
    if ($PSBoundParameters.ContainsKey('FormsIsRecordIdentityByDefaultEnabled') -and `
        ($FormsIsRecordIdentityByDefaultEnabled -ne $currentValues.FormsIsRecordIdentityByDefaultEnabled))
    {
        $FormsParametersToUpdate.Add('isRecordIdentityByDefaultEnabled', $FormsIsRecordIdentityByDefaultEnabled)
    }
    if ($PSBoundParameters.ContainsKey('FormsIsBingImageSearchEnabled') -and `
        ($FormsIsBingImageSearchEnabled -ne $currentValues.FormsIsBingImageSearchEnabled))
    {
        $FormsParametersToUpdate.Add('isBingImageSearchEnabled', $FormsIsBingImageSearchEnabled)
    }
    if ($PSBoundParameters.ContainsKey('FormsIsInOrgFormsPhishingScanEnabled') -and `
        ($FormsIsInOrgFormsPhishingScanEnabled -ne $currentValues.FormsIsInOrgFormsPhishingScanEnabled))
    {
        $FormsParametersToUpdate.Add('isInOrgFormsPhishingScanEnabled', $FormsIsInOrgFormsPhishingScanEnabled)
    }
    if ($FormsParametersToUpdate.Keys.Count -gt 0)
    {
        Write-Verbose -Message "Updating the Microsoft Forms settings with values:$(Convert-M365DscHashtableToString -Hashtable $FormsParametersToUpdate)"
        Update-M365DSCOrgSettingsForms -Options $FormsParametersToUpdate
    }

    # Dynamics Customer Voice Settings
    $DynamicsCustomerVoiceParametersToUpdate = @{}
    if ($PSBoundParameters.ContainsKey('DynamicsCustomerVoiceIsRestrictedSurveyAccessEnabled') -and `
        ($DynamicsCustomerVoiceIsRestrictedSurveyAccessEnabled -ne $currentValues.DynamicsCustomerVoiceIsRestrictedSurveyAccessEnabled))
    {
        $DynamicsCustomerVoiceParametersToUpdate.Add('isRestrictedSurveyAccessEnabled', $DynamicsCustomerVoiceIsRestrictedSurveyAccessEnabled)
    }
    if ($PSBoundParameters.ContainsKey('DynamicsCustomerVoiceIsRecordIdentityByDefaultEnabled') -and `
        ($DynamicsCustomerVoiceIsRecordIdentityByDefaultEnabled -ne $currentValues.DynamicsCustomerVoiceIsRecordIdentityByDefaultEnabled))
    {
        $DynamicsCustomerVoiceParametersToUpdate.Add('isRecordIdentityByDefaultEnabled', $DynamicsCustomerVoiceIsRecordIdentityByDefaultEnabled)
    }
    if ($PSBoundParameters.ContainsKey('DynamicsCustomerVoiceIsInOrgFormsPhishingScanEnabled') -and `
        ($DynamicsCustomerVoiceIsInOrgFormsPhishingScanEnabled -ne $currentValues.DynamicsCustomerVoiceIsInOrgFormsPhishingScanEnabled))
    {
        $DynamicsCustomerVoiceParametersToUpdate.Add('isInOrgFormsPhishingScanEnabled', $DynamicsCustomerVoiceIsInOrgFormsPhishingScanEnabled)
    }
    if ($DynamicsCustomerVoiceParametersToUpdate.Keys.Count -gt 0)
    {
        Write-Verbose -Message "Updating the Dynamics 365 Customer Voice settings with values:$(Convert-M365DscHashtableToString -Hashtable $DynamicsCustomerVoiceParametersToUpdate)"
        Update-M365DSCOrgSettingsDynamicsCustomerVoice -Options $DynamicsCustomerVoiceParametersToUpdate
    }

    # Apps And Services
    $AppsAndServicesParametersToUpdate = @{}
    if ($PSBoundParameters.ContainsKey('AppsAndServicesIsOfficeStoreEnabled') -and `
        ($AppsAndServicesIsOfficeStoreEnabled -ne $currentValues.AppsAndServicesIsOfficeStoreEnabled))
    {
        $AppsAndServicesParametersToUpdate.Add('isOfficeStoreEnabled', $AppsAndServicesIsOfficeStoreEnabled)
    }
    if ($PSBoundParameters.ContainsKey('AppsAndServicesIsAppAndServicesTrialEnabled') -and `
        ($AppsAndServicesIsAppAndServicesTrialEnabled -ne $currentValues.AppsAndServicesIsAppAndServicesTrialEnabled))
    {
        $AppsAndServicesParametersToUpdate.Add('isAppAndServicesTrialEnabled', $AppsAndServicesIsAppAndServicesTrialEnabled)
    }
    if ($AppsAndServicesParametersToUpdate.Keys.Count -gt 0)
    {
        Write-Verbose -Message "Updating the Apps & Settings settings with values:$(Convert-M365DscHashtableToString -Hashtable $AppsAndServicesParametersToUpdate)"
        Update-M365DSCOrgSettingsAppsAndServices -Options $AppsAndServicesParametersToUpdate
    }

    # To Do
    $ToDoParametersToUpdate = @{}
    if ($PSBoundParameters.ContainsKey('ToDoIsPushNotificationEnabled') -and `
        ($ToDoIsPushNotificationEnabled -ne $currentValues.ToDoIsPushNotificationEnabled))
    {
        $ToDoParametersToUpdate.Add('isPushNotificationEnabled', $ToDoIsPushNotificationEnabled)
    }
    if ($PSBoundParameters.ContainsKey('ToDoIsExternalJoinEnabled') -and `
        ($ToDoIsExternalJoinEnabled -ne $currentValues.ToDoIsExternalJoinEnabled))
    {
        $ToDoParametersToUpdate.Add('isExternalJoinEnabled', $ToDoIsExternalJoinEnabled)
    }
    if ($PSBoundParameters.ContainsKey('ToDoIsExternalShareEnabled') -and `
        ($ToDoIsExternalShareEnabled -ne $currentValues.ToDoIsExternalShareEnabled))
    {
        $ToDoParametersToUpdate.Add('isExternalShareEnabled', $ToDoIsExternalShareEnabled)
    }
    if ($ToDoParametersToUpdate.Keys.Count -gt 0)
    {
        Write-Verbose -Message "Updating the To Do settings with values:$(Convert-M365DscHashtableToString -Hashtable $ToDoParametersToUpdate)"
        Update-M365DSCOrgSettingsToDo -Options $ToDoParametersToUpdate
    }
}

function Test-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateSet('Yes')]
        [String]
        $IsSingleInstance,

        [Parameter()]
        [System.Boolean]
        $CortanaEnabled,

        [Parameter()]
        [System.Boolean]
        $AppsAndServicesIsOfficeStoreEnabled,

        [Parameter()]
        [System.Boolean]
        $AppsAndServicesIsAppAndServicesTrialEnabled,

        [Parameter()]
        [System.Boolean]
        $DynamicsCustomerVoiceIsRestrictedSurveyAccessEnabled,

        [Parameter()]
        [System.Boolean]
        $DynamicsCustomerVoiceIsRecordIdentityByDefaultEnabled,

        [Parameter()]
        [System.Boolean]
        $DynamicsCustomerVoiceIsInOrgFormsPhishingScanEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsExternalSendFormEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsExternalShareCollaborationEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsExternalShareResultEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsExternalShareTemplateEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsRecordIdentityByDefaultEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsBingImageSearchEnabled,

        [Parameter()]
        [System.Boolean]
        $FormsIsInOrgFormsPhishingScanEnabled,

        [Parameter()]
        [System.Boolean]
        $M365WebEnableUsersToOpenFilesFrom3PStorage,

        [Parameter()]
        [System.Boolean]
        $PlannerAllowCalendarSharing,

        [Parameter()]
        [System.Boolean]
        $MicrosoftVivaBriefingEmail,

        [Parameter()]
        [System.Boolean]
        $ToDoIsPushNotificationEnabled,

        [Parameter()]
        [System.Boolean]
        $ToDoIsExternalJoinEnabled,

        [Parameter()]
        [System.Boolean]
        $ToDoIsExternalShareEnabled,

        [Parameter()]
        [System.Boolean]
        $VivaInsightsWebExperience,

        [Parameter()]
        [System.Boolean]
        $VivaInsightsDigestEmail,

        [Parameter()]
        [System.Boolean]
        $VivaInsightsOutlookAddInAndInlineSuggestions,

        [Parameter()]
        [System.Boolean]
        $VivaInsightsScheduleSendSuggestions,

        [Parameter()]
        [System.Boolean]
        $AdminCenterReportDisplayConcealedNames,

        [Parameter()]
        [System.String]
        [ValidateSet('current', 'monthlyEnterprise', 'semiAnnual')]
        $InstallationOptionsUpdateChannel,

        [Parameter()]
        [System.String[]]
        [ValidateSet('isVisioEnabled', 'isSkypeForBusinessEnabled', 'isProjectEnabled', 'isMicrosoft365AppsEnabled')]
        $InstallationOptionsAppsForWindows,

        [Parameter()]
        [System.String[]]
        [ValidateSet('isSkypeForBusinessEnabled', 'isMicrosoft365AppsEnabled')]
        $InstallationOptionsAppsForMac,

        [Parameter()]
        [ValidateSet('Present', 'Absent')]
        [System.String]
        $Ensure = 'Present',

        [Parameter()]
        [System.Management.Automation.PSCredential]
        $Credential,

        [Parameter()]
        [System.String]
        $ApplicationId,

        [Parameter()]
        [System.String]
        $TenantId,

        [Parameter()]
        [System.Management.Automation.PSCredential]
        $ApplicationSecret,

        [Parameter()]
        [System.String]
        $CertificateThumbprint,

        [Parameter()]
        [Switch]
        $ManagedIdentity,

        [Parameter()]
        [System.String[]]
        $AccessTokens
    )
    #Ensure the proper dependencies are installed in the current environment.
    Confirm-M365DSCDependencies

    #region Telemetry
    $ResourceName = $MyInvocation.MyCommand.ModuleName -replace 'MSFT_', ''
    $CommandName = $MyInvocation.MyCommand
    $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName `
        -CommandName $CommandName `
        -Parameters $PSBoundParameters
    Add-M365DSCTelemetryEvent -Data $data
    #endregion

    Write-Verbose -Message 'Testing configuration for Org Settings.'

    $CurrentValues = Get-TargetResource @PSBoundParameters
    $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone()
    $ValuesToCheck.Remove('MicrosoftVivaBriefingEmail') | Out-Null

    Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)"
    Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)"

    $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues `
        -Source $($MyInvocation.MyCommand.Source) `
        -DesiredValues $PSBoundParameters `
        -ValuesToCheck $ValuesToCheck.Keys

    Write-Verbose -Message "Test-TargetResource returned $TestResult"

    return $TestResult
}

function Export-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.String])]
    param
    (
        [Parameter()]
        [System.Management.Automation.PSCredential]
        $Credential,

        [Parameter()]
        [System.String]
        $ApplicationId,

        [Parameter()]
        [System.String]
        $TenantId,

        [Parameter()]
        [System.Management.Automation.PSCredential]
        $ApplicationSecret,

        [Parameter()]
        [System.String]
        $CertificateThumbprint,

        [Parameter()]
        [Switch]
        $ManagedIdentity,

        [Parameter()]
        [System.String[]]
        $AccessTokens
    )
    $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' `
        -InboundParameters $PSBoundParameters

    #Ensure the proper dependencies are installed in the current environment.
    Confirm-M365DSCDependencies

    #region Telemetry
    $ResourceName = $MyInvocation.MyCommand.ModuleName -replace 'MSFT_', ''
    $CommandName = $MyInvocation.MyCommand
    $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName `
        -CommandName $CommandName `
        -Parameters $PSBoundParameters
    Add-M365DSCTelemetryEvent -Data $data
    #endregion

    try
    {
        if ($null -ne $Global:M365DSCExportResourceInstancesCount)
        {
            $Global:M365DSCExportResourceInstancesCount++
        }

        $Params = @{
            IsSingleInstance      = 'Yes'
            Credential            = $Credential
            ApplicationId         = $ApplicationId
            TenantId              = $TenantId
            ApplicationSecret     = $ApplicationSecret
            CertificateThumbprint = $CertificateThumbprint
            Managedidentity       = $ManagedIdentity.IsPresent
            AccessTokens          = $AccessTokens
        }

        $Results = Get-TargetResource @Params

        $dscContent = ''
        $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode `
            -Results $Results
        $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName `
            -ConnectionMode $ConnectionMode `
            -ModulePath $PSScriptRoot `
            -Results $Results `
            -Credential $Credential
        $dscContent += $currentDSCBlock

        Save-M365DSCPartialExport -Content $currentDSCBlock `
            -FileName $Global:PartialExportFileName
        Write-Host $Global:M365DSCEmojiGreenCheckMark

        return $dscContent
    }
    catch
    {
        Write-Host $Global:M365DSCEmojiRedX

        New-M365DSCLogEntry -Message 'Error during Export:' `
            -Exception $_ `
            -Source $($MyInvocation.MyCommand.Source) `
            -TenantId $TenantId `
            -Credential $Credential

        return ''
    }
}

function Get-M365DSCO365OrgSettingsPlannerConfig
{
    [CmdletBinding()]
    param()
    $VerbosePreference = 'SilentlyContinue'

    try
    {
        $Uri = (Get-MSCloudLoginConnectionProfile -Workload Tasks).HostUrl + '/taskAPI/tenantAdminSettings/Settings'
        [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
        $results = Invoke-RestMethod -ContentType 'application/json;odata.metadata=full' `
            -Headers @{'Accept' = 'application/json'; 'Authorization' = (Get-MSCloudLoginConnectionProfile -Workload Tasks).AccessToken; 'Accept-Charset' = 'UTF-8'; 'OData-Version' = '4.0;NetFx'; 'OData-MaxVersion' = '4.0;NetFx' } `
            -Method GET `
            $Uri -ErrorAction Stop
        return $results
    }
    catch
    {
        if ($_.Exception.Message -eq 'The request was aborted: Could not create SSL/TLS secure channel.')
        {
            Write-Warning -Message 'Could not create SSL/TLS secure channel. Skipping the Planner settings.'
        }
        else
        {
            Write-Verbose -Message 'Not able to retrieve Office 365 Planner Settings. Please ensure correct permissions have been granted.'
            New-M365DSCLogEntry -Message 'Error updating Office 365 Planner Settings' `
                -Exception $_ `
                -Source $($MyInvocation.MyCommand.Source) `
                -TenantId $TenantId `
                -Credential $Credential
        }

        return $null
    }
}

function Set-M365DSCO365OrgSettingsPlannerConfig
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [System.Boolean]
        $AllowCalendarSharing
    )
    $VerbosePreference = 'SilentlyContinue'

    $flags = @{
        allowCalendarSharing = $AllowCalendarSharing
    }

    $requestBody = $flags | ConvertTo-Json
    $Uri = (Get-MSCloudLoginConnectionProfile -Workload Tasks).HostUrl + '/taskAPI/tenantAdminSettings/Settings'
    $results = Invoke-RestMethod -ContentType 'application/json;odata.metadata=full' `
        -Headers @{'Accept' = 'application/json'; 'Authorization' = (Get-MSCloudLoginConnectionProfile -Workload Tasks).AccessToken; 'Accept-Charset' = 'UTF-8'; 'OData-Version' = '4.0;NetFx'; 'OData-MaxVersion' = '4.0;NetFx' } `
        -Method PATCH `
        -Body $requestBody `
        $Uri
}

function Get-M365DSCOrgSettingsInstallationOptions
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param(
        [Parameter(Mandatory = $true)]
        [System.String]
        $AuthenticationOption
    )
    $VerbosePreference = 'SilentlyContinue'

    try
    {
        $url = (Get-MSCloudLoginConnectionProfile -Workload MicrosoftGraph).ResourceUrl + 'beta/admin/microsoft365Apps/installationOptions'
        $results = Invoke-MgGraphRequest -Method GET -Uri $url
        return $results
    }
    catch
    {
        Write-Verbose -Message 'Not able to retrieve Office 365 Apps Installation Options. Please ensure correct permissions have been granted.'
        return $null
    }
}

function Update-M365DSCOrgSettingsInstallationOptions
{
    [CmdletBinding()]
    [OutputType([Void])]
    param(
        [Parameter(Mandatory = $true)]
        [System.Collections.Hashtable]
        $Options,

        [Parameter(Mandatory = $true)]
        [System.String]
        $AuthenticationOption
    )
    $VerbosePreference = 'SilentlyContinue'

    try
    {
        $url = (Get-MSCloudLoginConnectionProfile -Workload MicrosoftGraph).ResourceUrl + 'beta/admin/microsoft365Apps/installationOptions'
        Invoke-MgGraphRequest -Method PATCH -Uri $url -Body $Options | Out-Null
    }
    catch
    {
        if ($_.Exception.ToString().Contains('Forbidden (Forbidden)'))
        {
            if ($AuthenticationOption -eq 'Credentials')
            {
                $errorMessage = "You don't have the proper permissions to update the Office 365 Apps Installation Options." `
                    + ' When using Credentials to authenticate, you need to grant permissions to the Microsoft Graph PowerShell SDK by running' `
                    + ' Connect-MgGraph -Scopes OrgSettings-Microsoft365Install.ReadWrite.All'
                Write-Error -Message $errorMessage
            }
        }
    }
}

function Get-M365DSCOrgSettingsForms
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param()
    $VerbosePreference = 'SilentlyContinue'

    try
    {
        $url = (Get-MSCloudLoginConnectionProfile -Workload MicrosoftGraph).ResourceUrl + 'beta/admin/forms/settings'
        $results = Invoke-MgGraphRequest -Method GET -Uri $url -ErrorAction Stop
        return $results
    }
    catch
    {
        Write-Verbose -Message 'Not able to retrieve O365OrgSettings Forms Settings. Please ensure correct permissions have been granted.'
        return $null
    }
}

function Update-M365DSCOrgSettingsForms
{
    [CmdletBinding()]
    [OutputType([Void])]
    param(
        [Parameter(Mandatory = $true)]
        [System.Collections.Hashtable]
        $Options
    )
    $VerbosePreference = 'SilentlyContinue'

    try
    {
        Write-Verbose -Message 'Updating Forms Settings'
        $url = (Get-MSCloudLoginConnectionProfile -Workload MicrosoftGraph).ResourceUrl + 'beta/admin/forms/settings'
        Invoke-MgGraphRequest -Method PATCH -Uri $url -Body $Options | Out-Null
    }
    catch
    {
        New-M365DSCLogEntry -Message 'Error updating O365OrgSettings Forms Settings' `
            -Exception $_ `
            -Source $($MyInvocation.MyCommand.Source) `
            -TenantId $TenantId `
            -Credential $Credential
    }
}

function Get-M365DSCOrgSettingsDynamicsCustomerVoice
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param()
    $VerbosePreference = 'SilentlyContinue'

    try
    {
        $url = (Get-MSCloudLoginConnectionProfile -Workload MicrosoftGraph).ResourceUrl + 'beta/admin/dynamics/customerVoice'
        $results = Invoke-MgGraphRequest -Method GET -Uri $url -ErrorAction Stop
        return $results
    }
    catch
    {
        Write-Verbose -Message 'Not able to retrieve O365OrgSettings Dynamics Customer Voice Settings. Please ensure correct permissions have been granted.'
        return $null
    }
}

function Update-M365DSCOrgSettingsDynamicsCustomerVoice
{
    [CmdletBinding()]
    [OutputType([Void])]
    param(
        [Parameter(Mandatory = $true)]
        [System.Collections.Hashtable]
        $Options
    )
    $VerbosePreference = 'SilentlyContinue'

    try
    {
        $url = (Get-MSCloudLoginConnectionProfile -Workload MicrosoftGraph).ResourceUrl + 'beta/admin/dynamics/customerVoice'
        Invoke-MgGraphRequest -Method PATCH -Uri $url -Body $Options | Out-Null
    }
    catch
    {
        New-M365DSCLogEntry -Message 'Error updating O365OrgSettings Dynamics Customer Voice Settings' `
            -Exception $_ `
            -Source $($MyInvocation.MyCommand.Source) `
            -TenantId $TenantId `
            -Credential $Credential
    }
}

function Get-M365DSCOrgSettingsAppsAndServices
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param()
    $VerbosePreference = 'SilentlyContinue'

    try
    {
        $url = (Get-MSCloudLoginConnectionProfile -Workload MicrosoftGraph).ResourceUrl + 'beta/admin/appsAndServices/settings'
        $results = Invoke-MgGraphRequest -Method GET -Uri $url -ErrorAction Stop
        return $results
    }
    catch
    {
        Write-Verbose -Message 'Not able to retrieve O365OrgSettings Apps and Services Settings. Please ensure correct permissions have been granted.'
        return $null
    }
}

function Update-M365DSCOrgSettingsAppsAndServices
{
    [CmdletBinding()]
    [OutputType([Void])]
    param(
        [Parameter(Mandatory = $true)]
        [System.Collections.Hashtable]
        $Options
    )
    $VerbosePreference = 'SilentlyContinue'

    try
    {
        $url = (Get-MSCloudLoginConnectionProfile -Workload MicrosoftGraph).ResourceUrl + 'beta/admin/appsAndServices/settings'
        Invoke-MgGraphRequest -Method PATCH -Uri $url -Body $Options | Out-Null
    }
    catch
    {
        New-M365DSCLogEntry -Message 'Error updating O365OrgSettings Apps and Services Settings' `
            -Exception $_ `
            -Source $($MyInvocation.MyCommand.Source) `
            -TenantId $TenantId `
            -Credential $Credential
    }
}
function Get-M365DSCOrgSettingsToDo
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param()
    $VerbosePreference = 'SilentlyContinue'

    try
    {
        $url = (Get-MSCloudLoginConnectionProfile -Workload MicrosoftGraph).ResourceUrl + 'beta/admin/todo/settings'
        $results = Invoke-MgGraphRequest -Method GET -Uri $url -ErrorAction Stop
        return $results
    }
    catch
    {
        Write-Verbose -Message 'Not able to retrieve ToDo settings. Please ensure correct permissions have been granted.'
        return $null
    }
}

function Update-M365DSCOrgSettingsToDo
{
    [CmdletBinding()]
    [OutputType([Void])]
    param(
        [Parameter(Mandatory = $true)]
        [System.Collections.Hashtable]
        $Options
    )
    $VerbosePreference = 'SilentlyContinue'

    try
    {
        $url = (Get-MSCloudLoginConnectionProfile -Workload MicrosoftGraph).ResourceUrl + 'beta/admin/todo/settings'
        Invoke-MgGraphRequest -Method PATCH -Uri $url -Body $Options | Out-Null
    }
    catch
    {
        Write-Verbose -Message "Error: $($_.Exception.Message)"
        New-M365DSCLogEntry -Message 'Error updating O365OrgSettings To Do Settings' `
            -Exception $_ `
            -Source $($MyInvocation.MyCommand.Source) `
            -TenantId $TenantId `
            -Credential $Credential
    }
}

function Get-M365DSCOrgSettingsAdminCenterReport
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param()
    $VerbosePreference = 'SilentlyContinue'

    try
    {
        $url = (Get-MSCloudLoginConnectionProfile -Workload MicrosoftGraph).ResourceUrl + 'beta/admin/reportSettings'
        $results = Invoke-MgGraphRequest -Method GET -Uri $url -ErrorAction Stop
        return $results
    }
    catch
    {
        Write-Verbose -Message 'Not able to retrieve Office 365 Report Settings. Please ensure correct permissions have been granted.'
        return $null
    }
}

function Update-M365DSCOrgSettingsAdminCenterReport
{
    [CmdletBinding()]
    [OutputType([Void])]
    param(
        [Parameter(Mandatory = $true)]
        [System.Boolean]
        $DisplayConcealedNames
    )
    $VerbosePreference = 'SilentlyContinue'
    $url = (Get-MSCloudLoginConnectionProfile -Workload MicrosoftGraph).ResourceUrl + 'beta/admin/reportSettings'
    $body = @{
        '@odata.context'      = (Get-MSCloudLoginConnectionProfile -Workload MicrosoftGraph).ResourceUrl + 'beta/$metadata#admin/reportSettings/$entity'
        displayConcealedNames = $DisplayConcealedNames
    }
    Invoke-MgGraphRequest -Method PATCH -Uri $url -Body $body | Out-Null
}

Export-ModuleMember -Function *-TargetResource