MyPSFunctions.Office365.ps1

<#
    ===========================================================================
     Created with: SAPIEN Technologies, Inc., PowerShell Studio 2021 v5.8.196
     Created on: 10/26/2023 6:52 PM
     Created by: John@MyPSFunctions.com
     Organization: MyPSFunctions
     Filename: MyPSFunctions.Office365.psm1
    -------------------------------------------------------------------------
     Module Name: MyPSFunctions.Office365
    ===========================================================================
#>


#region Modules
####################################################
###################### Modules ########################
####################################################
Function Install-MyPSFunctionsModules
{
    [CmdletBinding()]
    param
    (
        [Parameter(Position = 1)]
        [switch]$EXO,
        [Parameter(Position = 2)]
        [switch]$MSOnline,
        [Parameter(Position = 3)]
        [Switch]$AAD,
        [Parameter(Position = 4)]
        [switch]$Teams,
        [Parameter(Position = 5)]
        [Switch]$SPO,
        [Parameter(Position = 7)]
        [switch]$All
    )
    
    Try
    {
        Read-Host "Did you open powershell with admin rights - Press Enter to Continue or CTRL + C to Cancel"
        # Install MSOnline Module (Force & Update & Remove old version)
        If ($EXO)
        {
            Install-Module -Name PowerShellGet -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install PowershellGet Module"
            Install-Module -Name ExchangeOnlineManagement -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install (New) Exchange Online Module"
        }
        # Install MSOnline Module (Force & Update & Remove old version)
        If ($MSOnline) { Install-Module -Name MSOnline -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install MSOnline Module" }
        # Install Azure AD module (Force & Update & Remove old version)
        If ($AAD)
        {
            Install-Module -Name AzureADPreview -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install AzureAD Preview Module"
            Install-Module -Name Microsoft.Graph -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install Microsoft Graph Module"
            Install-Module -Name Microsoft.Graph.beta -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install Microsoft Graph Beta Module"
            
        }
        # Install Microsoft Teams Module (Force & Update & Remove old version)
        If ($Teams) { Install-Module -Name MicrosoftTeams -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install Teams Module" }
        # Install Sharepoint Module (Force & Update & Remove old version)
        if ($SPO)
        {
            Install-Module -Name Microsoft.Online.SharePoint.PowerShell -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install Sharepoint Module"
            Install-Module -Name SharePointPnPPowerShellOnline -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install SharePoint PnP PowerShell Online"
            Install-Module -Name PnP.PowerShell -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install PnP.PowerShellModule"
        }
        # install all the Modules
        if ($All)
        {
            # Install EXO Module (Force & Update & Remove old version)
            Install-Module -Name PowerShellGet -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install PowershellGet Module"
            Install-Module -Name ExchangeOnlineManagement -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install (New) Exchange Online Module"
            # Install MSOnline Module (Force & Update & Remove old version)
            Install-Module -Name MSOnline -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install MSOnline Module"
            # Install Azure AD module (Force & Update & Remove old version)
            Install-Module -Name AzureADPreview -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install AzureAD Preview Module"
            Install-Module -Name Microsoft.Graph -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install Microsoft Graph Module"
            Install-Module -Name Microsoft.Graph.beta -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install Microsoft Graph Beta Module"
            # Install Microsoft Teams Module (Force & Update & Remove old version)
            Install-Module -Name MicrosoftTeams -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install Teams Module"
            # Install Sharepoint Module (Force & Update & Remove old version)
            Install-Module -Name Microsoft.Online.SharePoint.PowerShell -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install Sharepoint Module"
            Install-Module -Name SharePointPnPPowerShellOnline -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install SharePoint PnP PowerShell Online"
            Install-Module -Name PnP.PowerShell -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install PnP.PowerShellModule"
            # Install Other Module
            Install-Module -Name AIPService -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install AIPService Module"
            Install-Module -Name Mailozaurr -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install Mailozaurr Module"
            Install-Module -Name Posh-SSH -SkipPublisherCheck -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install Posh-SSH Module"
            Install-Module -Name ORCA -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install ORCA Module"
            Install-Module -Name AzureRM -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install AzureRM Module"
            Install-Module -Name Az -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install Az Modules"
            Install-Module -Name Microsoft.PowerApps.Administration.PowerShell -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install Microsoft.PowerApps.Administration.PowerShell Module"
            Install-Module -Name Microsoft.PowerApps.PowerShell -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install Microsoft.PowerApps.PowerShell Module"
            Install-Module -Name PSTeams -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install PSTeams Module"
            Install-Module -Name PSBlackListChecker -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install PSBlackListChecker Module"
            Install-Module -Name PowerShellAI -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install PowerShellAI Module"
            Install-Module -Name MSIdentityTools -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install MS Identity Tools Module"
            Install-Module -Name ImportExcel -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install ImportExcel Module"
        }
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        Write-Host "Failed to run the following CMDLet: $CMDLet"
        Write-host "Failed with Error:$ErrorMessage"
    }
}

Function Update-MyPSFunctionsModules
{
    [CmdletBinding()]
    param
    (
        [Parameter(Position = 1)]
        [switch]$EXO,
        [Parameter(Position = 2)]
        [switch]$MSOnline,
        [Parameter(Position = 3)]
        [Switch]$AAD,
        [Parameter(Position = 4)]
        [switch]$Teams,
        [Parameter(Position = 5)]
        [Switch]$SPO,
        [Parameter(Position = 7)]
        [switch]$All
    )
    
    Try
    {
        Read-Host "Did you open powershell with admin rights - Press Enter to Continue or CTRL + C to Cancel"
        # Install MSOnline Module (Force & Update & Remove old version)
        If ($EXO)
        {
            Update-Module -Name PowerShellGet -Force -confirm:$False
            Update-Module -Name ExchangeOnlineManagement -Force -confirm:$False; Write-Host "Successfully Update (New) Exchange Online Module"
        }
        # Install MSOnline Module (Force & Update & Remove old version)
        If ($MSOnline) { Update-Module -Name MSOnline -Force -confirm:$False; Write-Host "Successfully Update MSOnline Module" }
        # Install Azure AD module (Force & Update & Remove old version)
        If ($AAD)
        {
            Update-Module -Name AzureADPreview -Force -confirm:$False; Write-Host "Successfully Update AzureAD Preview Module"
            Update-Module -Name Microsoft.Graph -Force -confirm:$False; Write-Host "Successfully Update Microsoft Graph Module"
            Update-Module -Name Microsoft.Graph.Beta -Force -confirm:$False; Write-Host "Successfully Update Microsoft Graph Beta Module"
        }
        # Install Microsoft Teams Module (Force & Update & Remove old version)
        If ($Teams) { Update-Module -Name MicrosoftTeams -Force -confirm:$False; Write-Host "Successfully Update Teams Module" }
        # Install Sharepoint Module (Force & Update & Remove old version)
        if ($SPO)
        {
            Update-Module -Name Microsoft.Online.SharePoint.PowerShell -Force -confirm:$False; Write-Host "Successfully Update Sharepoint Module"
            Update-Module -Name SharePointPnPPowerShellOnline -Force -Confirm:$False; Write-Host "Successfully Update SharePoint PnP PowerShell Online"
            Update-Module -Name PnP.PowerShell -Force -confirm:$False; Write-Host "Successfully Update PnP Module"
        }
        # install all the Modules
        if ($All)
        {
            # Install EXO Module (Force & Update & Remove old version)
            Update-Module -Name PowerShellGet -Force -confirm:$False
            Update-Module -Name ExchangeOnlineManagement -Force -confirm:$False; Write-Host "Successfully Update (New) Exchange Online Module"
            # Install MSOnline Module (Force & Update & Remove old version)
            Update-Module -Name MSOnline -Force -confirm:$False; Write-Host "Successfully Update MSOnline Module"
            # Install Azure AD module (Force & Update & Remove old version)
            Update-Module -Name AzureADPreview -Force -confirm:$False; Write-Host "Successfully Update AzureAD Preview Module"
            Update-Module -Name Microsoft.Graph -Force -confirm:$False; Write-Host "Successfully Update Microsoft Graph Module"
            Update-Module -Name Microsoft.Graph.beta -Force -confirm:$False; Write-Host "Successfully Update Microsoft Graph Beta Module"
            # Install Microsoft Teams Module (Force & Update & Remove old version)
            Update-Module -Name MicrosoftTeams -Force -confirm:$False; Write-Host "Successfully Update Teams Module"
            # Install Sharepoint Module (Force & Update & Remove old version)
            Update-Module -Name Microsoft.Online.SharePoint.PowerShell -Force -confirm:$False; Write-Host "Successfully Update Sharepoint Module"
            Update-Module -Name SharePointPnPPowerShellOnline -Force -confirm:$False; Write-Host "Successfully Update Sharepoint Module"
            Update-Module -Name PnP.PowerShell -Force -confirm:$False; Write-Host "Successfully Update PnP Module"
            # Install Other Module
            Update-Module -Name AIPService -Force -confirm:$False; Write-Host "Successfully Update AIPService Module"
            Update-Module -Name Mailozaurr -Force -confirm:$False; Write-Host "Successfully Update Mailozaurr Module"
            Update-Module -Name Posh-SSH -Force -confirm:$False; Write-Host "Successfully Update Posh-SSH Module"
            Update-Module -Name ORCA -Force -confirm:$False; Write-Host "Successfully Update ORCA Module"
            Update-Module -Name AzureRM -Force -confirm:$False; Write-Host "Successfully Update AzureRM Module"
            Update-Module -Name Az -Force -confirm:$False; Write-Host "Successfully Update Az Modules"
            Update-Module -Name Microsoft.PowerApps.Administration.PowerShell -Force -confirm:$False; Write-Host "Successfully Update Microsoft.PowerApps.Administration.PowerShell Module"
            Update-Module -Name Microsoft.PowerApps.PowerShell -Force -confirm:$False; Write-Host "Successfully Update Microsoft.PowerApps.PowerShell Module"
            Update-Module -Name PSTeams -Force -confirm:$False; Write-Host "Successfully Update PSTeams Module"
            Update-Module -Name PSBlackListChecker -Force -confirm:$False; Write-Host "Successfully Update PSBlackListChecker Module"
            Update-Module -Name PowerShellAI -Force -confirm:$False; Write-Host "Successfully Update PowerShellAI Module"
            Update-Module -Name MSIdentityTools -Force -confirm:$False; Write-Host "Successfully Update MS Identity Tools Module"
            Update-Module -Name ImportExcel -Force -confirm:$False; Write-Host "Successfully Update ImportExcel Module"
            
        }
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        Write-Host "Failed to run the following CMDLet: $CMDLet"
        Write-host "Failed with Error:$ErrorMessage"
    }
}

Function Validate-ExcelModule
{
    [CmdletBinding()]
    param ()
    $FoundModule = get-module -ListAvailable ImportExcel
    if ($FoundModule)
    {
        Write-host "Module was found"
    }
    Else
    {
        Write-host "Module ImportExcel was not found"
        Install-Module -Name ImportExcel -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Host "Successfully install ImportExcel Module"
    }
    
}
#endregion

#region Connect
####################################################
###################### Connect ########################
####################################################
Function Connect-MyMgGraph
{
    [CmdletBinding()]
    param ()
    
    Connect-MgGraph
    Get-MgContext | fl ContextScope, AuthType, Account, Scopes
    $MgGraphAccount = (Get-MgContext).Account
    # Update your Powershell windows with the following Title
    if ($Host.UI.RawUI.WindowTitle -notlike "Connected:*")
    {
        $Host.UI.RawUI.WindowTitle = "Connected: MgGraph ($MgGraphAccount)"
    }
    Else
    {
        
        $Tittle = $Host.UI.RawUI.WindowTitle
        $Host.UI.RawUI.WindowTitle = $Tittle + " & MgGraph ($MgGraphAccount) "
        
    }
}

Function Connect-AAD
{
    param
    (
        [Parameter(Position = 1)]
        [string]$AlternateID
    )
    If ($AlternateID)
    {
        $MyPSFunctionsO365Admin = $AlternateID
    }
    
    Write-Host -ForegroundColor Yellow "Please validate the Azure AD Preview Module is installed"
    # Connect to Azure AD
    Connect-AzureAD -AccountId $MyPSFunctionsO365Admin
    # Update your Powershell windows with the following Title
    if ($Host.UI.RawUI.WindowTitle -notlike "Connected:*")
    {
        $Host.UI.RawUI.WindowTitle = "Connected: EntraID ($MyPSFunctionsO365Admin)"
    }
    Else
    {

        $Tittle = $Host.UI.RawUI.WindowTitle
        $Host.UI.RawUI.WindowTitle = $Tittle + " & EntraID ($MyPSFunctionsO365Admin)"
        
    }
}

Function Connect-EXO
{
    param
    (
        [Parameter(Position = 1)]
        [string]$AlternateID
    )
    If ($AlternateID)
    {
        $MyPSFunctionsO365Admin = $AlternateID
    }
    
    Write-Host -ForegroundColor Yellow "Please validate the Exchange Online Module is installed"
    Write-Host "To install New Exchange Online Module use the following: https://aka.ms/exops-docs"
    #Load Exchange Online Module
    Connect-ExchangeOnline -UserPrincipalName $MyPSFunctionsO365Admin
    # Update your Powershell windows with the following Title
    if ($Host.UI.RawUI.WindowTitle -notlike "Connected:*")
    {
        $Host.UI.RawUI.WindowTitle = "Connected: Exchange Online ($MyPSFunctionsO365Admin)"
    }
    Else
    {
            $Tittle = $Host.UI.RawUI.WindowTitle
            $Host.UI.RawUI.WindowTitle = $Tittle + " & Exchange Online ($MyPSFunctionsO365Admin)"
        
    }
}

Function Connect-EXOLegacy
{
    param
    (
        [Parameter(Position = 1)]
        [string]$AlternateID
    )
    If ($AlternateID)
    {
        $MyPSFunctionsO365Admin = $AlternateID
    }
    
    Write-Host -ForegroundColor Yellow "Please validate the Exchange Online Module is installed"
    Write-Host "To install New Exchange Online Module use the following: https://aka.ms/exops-docs"
    #Load Exchange Online Module
    Connect-ExchangeOnline -UserPrincipalName $MyPSFunctionsO365Admin -UseRPSSession
    # Update your Powershell windows with the following Title
    if ($Host.UI.RawUI.WindowTitle -notlike "Connected:*")
    {
        $Host.UI.RawUI.WindowTitle = "Connected: Exchange Online ($MyPSFunctionsO365Admin)"
    }
    Else
    {
        $Tittle = $Host.UI.RawUI.WindowTitle
        $Host.UI.RawUI.WindowTitle = $Tittle + " & Exchange Online ($MyPSFunctionsO365Admin)"
        
    }
}

Function Connect-EXOCompliance
{
    param
    (
        [Parameter(Position = 1)]
        [string]$AlternateID
    )
    If ($AlternateID)
    {
        $MyPSFunctionsO365Admin = $AlternateID
    }
    
    Write-Host -ForegroundColor Yellow "Please validate the Exchange Online Module is installed"
    Write-Host "To install New Exchange Online Module use the following: https://aka.ms/exops-docs"
    #Load Exchange Online Module
    Connect-ExchangeOnline -UserPrincipalName $MyPSFunctionsO365Admin
    Connect-IPPSSession -UserPrincipalName $MyPSFunctionsO365Admin -UseRPSSession:$false
    # Update your Powershell windows with the following Title
    if ($Host.UI.RawUI.WindowTitle -notlike "Connected:*")
    {
        $Host.UI.RawUI.WindowTitle = "Connected: Exchange Online & Compliance Center ($MyPSFunctionsO365Admin)"
    }
    Else
    {
            $Tittle = $Host.UI.RawUI.WindowTitle
            $Host.UI.RawUI.WindowTitle = $Tittle + " & Exchange Online & Compliance Center ($MyPSFunctionsO365Admin)"
    }
}

Function Connect-SharepointOnline
{
    param
    (
        [Parameter(Mandatory = $false,
                   Position = 1)]
        [string]$AlternateID,
        [Parameter(Position = 2)]
        [string]$AlternateTenant
    )
    
    If ($AlternateID)
    {
        $MyPSFunctionsO365Admin = $AlternateID
        $MyPSFunctionsTenantName = $AlternateTenant
    }
    
    $AdminURL = "https://" + $MyPSFunctionsTenantName + "-admin.sharepoint.com"
    # Create a PS Session to Sharepoint Online
    $SharepointModule = Connect-SPOService -Url $AdminURL
    
    # Update your Powershell windows with the following Title
    if ($Host.UI.RawUI.WindowTitle -notlike "Connected:*")
    {
        $Host.UI.RawUI.WindowTitle = "Connected: Sharepoint Online ($MyPSFunctionsO365Admin)"
    }
    Else
    {
        $Tittle = $Host.UI.RawUI.WindowTitle
        $Host.UI.RawUI.WindowTitle = $Tittle + " & Sharepoint Online ($MyPSFunctionsO365Admin)"
    }
}

Function Connect-SharepointOnlineAll
{
    param
    (
        [Parameter(Mandatory = $false,
                   Position = 1)]
        [string]$AlternateID,
        [Parameter(Position = 2)]
        [string]$AlternateTenant
    )
    
    If ($AlternateID)
    {
        $MyPSFunctionsO365Admin = $AlternateID
        $MyPSFunctionsTenantName = $AlternateTenant
    }
    $AdminURL = "https://" + $MyPSFunctionsTenantName + "-admin.sharepoint.com"
    # Create a PS Session to Sharepoint Online
    $SharepointModule = Connect-SPOService -Url $AdminURL
    Connect-PnPOnline $AdminURL -Interactive # -UseWebLogin (with Powershell and graph API
    
    # Update your Powershell windows with the following Title
    if ($Host.UI.RawUI.WindowTitle -notlike "Connected:*")
    {
        $Host.UI.RawUI.WindowTitle = "Connected: Sharepoint Online ($MyPSFunctionsO365Admin)"
    }
    Else
    {
    $Tittle = $Host.UI.RawUI.WindowTitle
    $Host.UI.RawUI.WindowTitle = $Tittle + " & Sharepoint Online ($MyPSFunctionsO365Admin)"
        
    }
}

Function Connect-TeamsOnline
{
    # Create a Connect to Teams admin console using Teams Module
    $TeamsConnection = Connect-MicrosoftTeams
    $UserID = $TeamsConnection.account.id
    # Update your Powershell windows with the following Title
    if ($Host.UI.RawUI.WindowTitle -notlike "Connected:*")
    {
        $Host.UI.RawUI.WindowTitle = "Connected: Teams Online ($UserID)"
    }
    Else
    {
            $Tittle = $Host.UI.RawUI.WindowTitle
            $Host.UI.RawUI.WindowTitle = $Tittle + " & Teams Online ($UserID)"
    }
}
Function Connect-PowerPlatform
{
    param
    (
        [Parameter(Position = 1)]
        [string]$AlternateID
    )
    
    If ($AlternateID)
    {
        $MyPSFunctionsO365Admin = $AlternateID
    }
    # Create a Connect to Teams admin console using Teams Module
    Add-PowerAppsAccount -Username $MyPSFunctionsO365Admin
    # Update your Powershell windows with the following Title
    if ($Host.UI.RawUI.WindowTitle -notlike "Connected:*")
    {
        $Host.UI.RawUI.WindowTitle = "Connected: PowerPlatform $MyPSFunctionsO365Admin"
    }
    Else
    {
        $Tittle = $Host.UI.RawUI.WindowTitle
        $Host.UI.RawUI.WindowTitle = $Tittle + " & PowerPlatform $MyPSFunctionsO365Admin"
    }
}

Function Connect-ExchangeOnPremise
{
    param
    (
        [Parameter(Mandatory = $False,
                   Position = 1)]
        [string]$Admin,
        [Parameter(Mandatory = $False,
                   Position = 2)]
        [string]$ServerNameFQDN,
        [Parameter(Mandatory = $False,
                   Position = 3)]
        [string]$Prefix
    )
    
    If ($Admin)
    {
        $ExchangeAdmin = $Admin
        
    }
    Else
    {
        $ExchangeAdmin = $MyPSFunctionsOnPremiseAdmin
    }
    
    If ($ServerNameFQDN)
    {
        $ExchangeServerFQDN = $ServerNameFQDN
        
    }
    Else
    {
        $ExchangeServerFQDN = $MyPSFunctionsEXOHybridServerName
    }
    Write-host "The Script will connect to: $ExchangeServerFQDN"
    
    
    If ($Prefix)
    {
        $ConnectionUri = "http://" + $ExchangeServerFQDN + "/PowerShell/"
        $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $ConnectionUri -Credential $ExchangeAdmin
        Import-PSSession $Session -AllowClobber -Prefix $Prefix -DisableNameChecking

    }
    Else
    {
        $ConnectionUri = "http://" + $ExchangeServerFQDN + "/PowerShell/"
        $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $ConnectionUri -Credential $ExchangeAdmin
        Import-PSSession $Session -AllowClobber -DisableNameChecking

    }
    
    if ($Host.UI.RawUI.WindowTitle -notlike "Connected:*")
    {
        # Update your Powershell windows with the following Title
        $Host.UI.RawUI.WindowTitle = "Connected: Exchange OnPremise - $ExchangeServerFQDN ($ExchangeAdmin)"
    }
    Else
    {
        $Tittle = $Host.UI.RawUI.WindowTitle
        $Host.UI.RawUI.WindowTitle = $Tittle + " & Exchange OnPremise - $ExchangeServerFQDN ($ExchangeAdmin)"
        
    }
}

#endregion

#region Users
####################################################
###################### Users ########################
####################################################
Function Convert-ImmutableIDToGuid
{
    Param (
        [String]$ImmutableID
    )
    $GUID = [GUID][System.Convert]::FromBase64String($ImmutableID)
    Return $GUID
}

Function Convert-ObjectGUIDToImmutableID
{
    Param (
        [String]$GUID
    )
    $ImmutableID = [system.convert]::ToBase64String(([GUID]($GUID)).tobytearray())
    Return $ImmutableID
}

Function Check-MSOLUserMFAEnrolledDevices
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [String]$UPN
    )
    
    $User = Get-MSolUser -UserPrincipalName $UPN
    $User.StrongAuthenticationMethods | Ft MethodType, IsDefault
}

Function Get-ResponseFailureInfo
{
    [cmdletbinding()]
    param
    (
        [Parameter(Mandatory = $true)]
        [object]$Exception
    )
    
    begin
    {
        $message = $null
    }
    process
    {
        if ($Exception.Response)
        {
            try
            {
                $stream = $Exception.Response.GetResponseStream()
                $reader = New-Object System.IO.StreamReader($stream)
                $message = $reader.ReadToEnd()
                
                if ($message)
                {
                    $message = $message | ConvertFrom-Json
                }
            }
            finally
            {
                if ($stream) { $stream.Dispose() }
            }
        }
        else
        {
            Write-Warning "Not found"
        }
    }
    end
    {
        $message.Response.error_code
    }
}

#endregion

#region Yammer
####################################################
###################### Yammer ########################
####################################################
Function Invoke-YammerRestRequest
{
<#
    .SYNOPSIS
        Execute an HTTP REST request to Yammer
    .DESCRIPTION
        Execute an HTTP REST request to Yammer
    .PARAMETER AccessToken
        Access token to execute the request
    .PARAMETER Uri
        Request URI
    .EXAMPLE
     
        Invoke-YammerRestRequest -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -Method Get -Uri "https://www.yammer.com/api/v1/users/by_email.json?email=john.doe@contoso.com"
#>

    [cmdletbinding()]
    param
    (
        [Parameter(Mandatory = $true)]
        [string]$AccessToken,
        [Parameter(Mandatory = $true)]
        [System.Uri]$Uri,
        [Parameter(Mandatory = $false)]
        [string]$Body,
        [Parameter(Mandatory = $true)]
        [ValidateSet("Default", "Delete", "Get", "Head", "Merge", "Options", "Patch", "Put", "Post")]
        [string]$Method
    )
    
    begin
    {
        $headers = @{ "Authorization" = "Bearer $AccessToken" }
    }
    process
    {
        $params = @{
            Uri        = $Uri
            Headers = $headers
            Method  = $Method
        }
        
        if ($Body)
        {
            $params["Body"] = $Body
            $params["Headers"] = $headers = @{ "Authorization" = "Bearer $AccessToken"; "content-type" = "application/json" }
        }
        
        Write-Verbose -Message "Executing URI: $($Uri.ToString())"
        
        try
        {
            $response = Invoke-WebRequest @params
        }
        catch
        {
            if ($errorCode = Get-ResponseFailureInfo -Exception $_.Exception)
            {
                Write-Error -Message "Exception Invoking REST Request: $errorCode"
            }
            else
            {
                Write-Error -Message "Exception Invoking REST Request: $($_.Exception)"
            }
        }
        
        if ($response -and $response.Content)
        {
            return ($response.Content | ConvertFrom-Json)
        }
        
        return $null
    }
    end
    {
    }
}

Function Get-YammerUser
{
<#
    .SYNOPSIS
        Gets a user's information from the Yammer network
    .DESCRIPTION
        Gets a user's information from the Yammer network
    .PARAMETER AccessToken
        Access token to execute the request
    .PARAMETER EmailAddress
        Email address of the user to get from the Yammer network
    .PARAMETER UserId
        Yammer User Id of the user to get from the Yammer network
    .EXAMPLE
     
        Get-YammerUser -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -EmailAddress "john.doe@contoso.com"
    .EXAMPLE
     
        Get-YammerUser -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -UserId "1665835523"
    .EXAMPLE
     
        Get-YammerUser -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -CurrentUser
#>

    [cmdletbinding()]
    param
    (
        [Parameter(Mandatory = $true, ParameterSetName = "EmailAddress")]
        [Parameter(Mandatory = $true, ParameterSetName = "UserId")]
        [Parameter(Mandatory = $true, ParameterSetName = "CurrentUser")]
        [string]$AccessToken,
        [Parameter(Mandatory = $true, ParameterSetName = "CurrentUser")]
        [switch]$CurrentUser,
        [Parameter(Mandatory = $true, ParameterSetName = "EmailAddress")]
        [string]$EmailAddress,
        [Parameter(Mandatory = $true, ParameterSetName = "UserId")]
        [string]$UserId
    )
    
    begin
    {
    }
    process
    {
        switch ($PSCmdlet.ParameterSetName)
        {
            "CurrentUser"
            {
                Invoke-YammerRestRequest -AccessToken $AccessToken -Method Get -Uri "https://www.yammer.com/api/v1/users/current.json"
            }
            "EmailAddress"
            {
                Invoke-YammerRestRequest -AccessToken $AccessToken -Method Get -Uri "https://www.yammer.com/api/v1/users/by_email.json?email=$EmailAddress"
            }
            "UserId"
            {
                Invoke-YammerRestRequest -AccessToken $AccessToken -Method Get -Uri "https://www.yammer.com/api/v1/users/$UserId.json"
            }
        }
    }
    end
    {
    }
}

Function Get-YammerImpersonatedUser
{
<#
    .SYNOPSIS
        Gets the impersonated user information for a user from the Yammer network
    .DESCRIPTION
        Gets the impersonated user information for a user from the Yammer network
    .PARAMETER AccessToken
        Access token to execute the request
    .PARAMETER ClientId
        The app's consumer key which is available in the app that you registered.
    .PARAMETER UserId
        The UserId of the user on behalf of whom you are generating the access token.
    .PARAMETER EmailAddress
        The EmailAddress of the user on behalf of whom you are generating the access token.
    .EXAMPLE
     
        Get-YammerImpersonatedUser -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -ClientId "aHYXwaaaY9AXGR3Bd6NR3A" -UserId "1665835523"
    .EXAMPLE
     
        Get-YammerImpersonatedUser -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -ClientId "aHYXwaaaY9AXGR3Bd6NR3A" -EmailAddress "john.doe@contoso.com"
#>

    [cmdletbinding()]
    param
    (
        [Parameter(Mandatory = $true, ParameterSetName = "EmailAddress")]
        [Parameter(Mandatory = $true, ParameterSetName = "UserId")]
        [string]$AccessToken,
        [Parameter(Mandatory = $true, ParameterSetName = "EmailAddress")]
        [Parameter(Mandatory = $true, ParameterSetName = "UserId")]
        [string]$ClientId,
        [Parameter(Mandatory = $true, ParameterSetName = "UserId")]
        [int]$UserId,
        [Parameter(Mandatory = $true, ParameterSetName = "EmailAddress")]
        [string]$EmailAddress
    )
    
    begin
    {
        if ($PSCmdlet.ParameterSetName -eq "EmailAddress")
        {
            $UserId = Get-YammerUser -AccessToken $AccessToken -EmailAddress $EmailAddress | SELECT -ExpandProperty Id
        }
    }
    process
    {
        if ($UserId)
        {
            Invoke-YammerRestRequest -AccessToken $AccessToken -Method Get -Uri "https://www.yammer.com/api/v1/oauth/tokens.json?consumer_key=$ClientId&user_id=$UserId"
        }
    }
    end
    {
    }
}

Function New-YammerGroup
{
<#
    .SYNOPSIS
        Creates a new Yammer group. The group admin will be the user associated with the provided AccessToken
    .DESCRIPTION
        Creates a new Yammer group. The group admin will be the user associated with the provided AccessToken
    .PARAMETER AccessToken
        Access token to execute the request
    .PARAMETER GroupName
        Name of the new Yammer group
    .PARAMETER IsPrivate
        Switch to specifiy if the new Yammer group should be private. Default the group will be public
    .EXAMPLE
     
        New-YammerGroup -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -GroupName "Example Group"
    .EXAMPLE
     
        New-YammerGroup -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -GroupName "Example Group" -IsPrivate
#>

    [cmdletbinding()]
    param
    (
        [Parameter(Mandatory = $true)]
        [string]$GroupName,
        [Parameter(Mandatory = $true)]
        [string]$AccessToken,
        [Parameter(Mandatory = $false)]
        [switch]$IsPrivate
    )
    
    begin
    {
        $url = "https://www.yammer.com/api/v1/groups.json?name=$GroupName"
        
        if ($IsPrivate)
        {
            $url = "https://www.yammer.com/api/v1/groups.json?name=$GroupName&private=true"
        }
    }
    process
    {
        $yammerGroup = Get-YammerGroup -GroupName $GroupName -AccessToken $AccessToken
        
        if (-not $yammerGroup)
        {
            if ($group = Invoke-YammerRestRequest -AccessToken $AccessToken -Method Post -Uri $url)
            {
                $group
            }
        }
        else
        {
            Write-Error "A Yammer group with the name '$GroupName' already exists."
        }
    }
    end
    {
    }
}

Function Get-YammerGroup
{
<#
    .SYNOPSIS
        Get the group info from the Yammer network.
    .DESCRIPTION
        Get the group info from the Yammer network.
    .PARAMETER AccessToken
        Access token to execute the request
    .PARAMETER GroupId
        Id of the Yammer group to retrieve from the Yammer network
    .PARAMETER GroupName
        Name of the Yammer group to retrieve from the Yammer network
    .EXAMPLE
     
        Get-YammerGroup -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw"
    .EXAMPLE
     
        Get-YammerGroup -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -GroupName "Example Group"
    .EXAMPLE
     
        Get-YammerGroup -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -GroupId "14582024"
#>

    [cmdletbinding()]
    param
    (
        [Parameter(Mandatory = $true, ParameterSetName = "AllGroups")]
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$AccessToken,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$GroupName,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [string]$GroupId
    )
    
    begin
    {
        $page = 1
    }
    process
    {
        switch ($PSCmdlet.ParameterSetName)
        {
            "AllGroups"
            {
                do
                {
                    if ($groups = Invoke-YammerRestRequest -Method Get -AccessToken $AccessToken -Uri "https://www.yammer.com/api/v1/groups.json?page=$page")
                    {
                        $groups
                    }
                    
                    $page++
                }
                while ($groups.Count -gt 0)
            }
            "GroupName"
            {
                do
                {
                    if ($group = (Invoke-YammerRestRequest -Method Get -AccessToken $AccessToken -Uri "https://www.yammer.com/api/v1/groups.json?page=$page") | ? { $_.Name -eq $GroupName })
                    {
                        return $group
                    }
                    
                    $page++
                }
                while ($groups.Count -gt 0)
            }
            "GroupId"
            {
                Invoke-YammerRestRequest -Method Get -AccessToken $AccessToken -Uri "https://www.yammer.com/api/v1/groups/$GroupId.json"
            }
        }
    }
    end
    {
    }
}

Function Get-YammerGroupMembership
{
<#
    .SYNOPSIS
        Get the members of a Yammer group
    .DESCRIPTION
        Get the members of a Yammer group
    .PARAMETER AccessToken
        Access token to execute the request
    .PARAMETER GroupId
        Id of the Yammer group to retrieve from the Yammer network
    .PARAMETER GroupName
        Name of the Yammer group to retrieve from the Yammer network
    .EXAMPLE
     
        Get-YammerGroupMembership -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -GroupName "Example Group"
    .EXAMPLE
     
        Get-YammerGroupMembership -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -GroupId "14582024"
#>

    [cmdletbinding()]
    param
    (
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$AccessToken,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$GroupName,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [string]$GroupId
    )
    
    begin
    {
        $page = 1
    }
    process
    {
        if ($PSCmdlet.ParameterSetName -eq "GroupName")
        {
            $GroupId = Get-YammerGroup -AccessToken $AccessToken -GroupName $GroupName | SELECT -ExpandProperty Id
        }
        
        do
        {
            if ($membership = (Invoke-YammerRestRequest -Method Get -AccessToken $AccessToken -Uri "https://www.yammer.com/api/v1/groups/$GroupId/members.json?page=$page"))
            {
                return $membership.Users
            }
            
            $page++
        }
        while ($membership.Count -gt 0)
    }
    end
    {
    }
}

Function Add-YammerGroupMember
{
<#
    .SYNOPSIS
        Adds a user to a Yammer group
    .DESCRIPTION
        Adds a user to a Yammer group
    .PARAMETER AccessToken
        Access token to execute the request
    .PARAMETER GroupId
        Id of the Yammer group
    .PARAMETER GroupName
        Name of the Yammer group
    .PARAMETER EmailAddress
        Email address of the user to add to the group
    .EXAMPLE
     
        Get-YammerGroup -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -GroupName "Example Group" -EmailAddress "john.doe@contoso.com"
    .EXAMPLE
     
        Get-YammerGroup -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -GroupId 15094523 -EmailAddress "john.doe@contoso.com"
#>

    [cmdletbinding()]
    param
    (
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$AccessToken,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$GroupName,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [String]$GroupId,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$EmailAddress
    )
    
    begin
    {
        $uri = "https://www.yammer.com/api/v1/groups/{groupId}/make_admin?user_id={userId}"
    }
    process
    {
        if ($PSCmdlet.ParameterSetName -eq "GroupName")
        {
            $GroupId = Get-YammerGroup -AccessToken $AccessToken -GroupName $GroupName | SELECT -ExpandProperty Id
        }
        
        $json = (@{ group_id = $GroupId; email = $EmailAddress } | ConvertTo-Json)
        $json
        
        Invoke-YammerRestRequest -Method Post -AccessToken $AccessToken -Uri "https://www.yammer.com/api/v1/group_memberships.json" -Body $json
    }
    end
    {
    }
}

Function Remove-YammerGroupMember
{
<#
    .SYNOPSIS
        Removes a user from a Yammer group. Requires the caller to be a verified Yammer admin because this requires impersonation.
    .DESCRIPTION
        Removes a user from a Yammer group
    .PARAMETER AccessToken
        Access token to execute the request
    .PARAMETER GroupId
        Id of the Yammer group
    .PARAMETER GroupName
        Name of the Yammer group
    .PARAMETER ClientId
        The app's consumer key which is available in the app that you registered.
    .PARAMETER EmailAddress
        Email address of the user to remove
    .EXAMPLE
     
        Remove-YammerGroupMember -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -GroupName "Example Group" -ClientId "aHYXwaaaY9AXGR3Bd6NR3A" -EmailAddress "john.doe@contoso.com"
    .EXAMPLE
     
        Remove-YammerGroupMember -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -GroupId 15094523 -ClientId "aHYXwaaaY9AXGR3Bd6NR3A" -EmailAddress "john.doe@contoso.com"
#>

    [cmdletbinding()]
    param
    (
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$AccessToken,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$GroupName,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [string]$GroupId,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$ClientId,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$EmailAddress
    )
    
    begin
    {
    }
    process
    {
        if ($PSCmdlet.ParameterSetName -eq "GroupName")
        {
            $GroupId = Get-YammerGroup -AccessToken $AccessToken -GroupName $GroupName | SELECT -ExpandProperty Id
        }
        
        $impersonatedUser = Get-YammerImpersonatedUser -AccessToken $AccessToken -ClientId $ClientId -EmailAddress $EmailAddress
        
        if ($impersonatedUser -and $impersonatedUser.token)
        {
            Invoke-YammerRestRequest -Method Delete -AccessToken $impersonatedUser.token -Uri "https://www.yammer.com/api/v1/group_memberships.json?group_id=$GroupId"
        }
        else
        {
            Write-Error "Failed to generate an impersonation token for user $EmailAddress"
        }
    }
    end
    {
    }
}

Function Get-YammerGroupAdmin
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [String]$AccessToken,
        [Parameter(Position = 2)]
        [String]$GroupID
    )
    
    $Members = Get-YammerGroupMembership -AccessToken $AccessToken -GroupId $GroupID
    $Admins = $Members | where { $_.is_group_admin -eq $True } | select Email
    #$Admins | ft Full_name, Email, Job_Title
    $AdminsEmail = $Admins.Email -join ";"
    Return $AdminsEmail
}

Function Get-YammerGroupAdminAll
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [String]$Token
    )
    $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    $Location = $Null
    $Location = (Get-Location).Path
    $RootFolder = $Location + "\YammerGroups_" + $DateFull + "\"
    Create-folder $RootFolder
    $Table = $Null
    $Table = @()
    
    #Initiate the Hash Table
    [Int]$i = 1
    $YammerGroups = Get-YammerGroup -AccessToken $Token
    $Count = ($YammerGroups | Measure).count
    ForEach ($YammerGroup in $YammerGroups)
    {
        $YammerGroupID = $Null
        $YammerGroupID = $YammerGroup.ID
        $YammerGroupfull_name = $Null
        $YammerGroupfull_name = $YammerGroup.full_name
        $YammerGroupName = $Null
        $YammerGroupName = $YammerGroup.name
        $YammerGroupPrivacy = $Null
        $YammerGroupPrivacy = $YammerGroup.privacy
        $YammerGroupurl = $Null
        $YammerGroupurl = $YammerGroup.url
        $YammerGroupweb_url = $Null
        $YammerGroupweb_url = $YammerGroup.web_url
        $YammerGroupstate = $Null
        $YammerGroupstate = $YammerGroup.state
        Write-Log -Level Warning -message "The script is analyzing $YammerGroupfull_name ($YammerGroupID) ….. --- $i/$Count"
        $Admins = $Null
        $Admins = Get-YammerGroupAdmin -AccessToken $Token -GroupId $YammerGroupID
        
        $Table += New-object PSobject -Property ([Ordered] @{
                YammerGroupID         = $YammerGroupID;
                YammerGroupFull_Name = $YammerGroupfull_name;
                YammerGroupName         = $YammerGroupName;
                YammerGroupPrivacy   = $YammerGroupPrivacy;
                YammerGroupurl         = $YammerGroupurl;
                YammerGroupweb_url   = $YammerGroupweb_url;
                YammerGroupstate     = $YammerGroupstate;
                Admins                 = $Admins;
            })
        
        
        $i++
    }
    $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    $ReportFilexlsx = ".\Report_AdminsYammerGroups_" + $DateFull + ".xlsx"
    $Table | Export-Excel $ReportFilexlsx -TableName "YammerGroups" -Title "YammerGroups" -TitleBold -WorksheetName "YammerGroups" -TableStyle Medium9 -AutoSize -AutoFilter
    Write-log INFO -Message "Generate the following Report: $ReportFilexlsx"
    
}

Function Add-YammerGroupAdmin
{
<#
    .SYNOPSIS
        Set's a user as a Yammer group administrator. Must be a verified admin to execute this function.
    .DESCRIPTION
        Set's a user as a Yammer group administrator. Must be a verified admin to execute this function.
    .PARAMETER AccessToken
        Access token to execute the request
    .PARAMETER GroupId
        Id of the Yammer group to retrieve from the Yammer network
    .PARAMETER GroupName
        Name of the Yammer group to retrieve from the Yammer network
    .PARAMETER EmailAddress
        Email address of the user to grant admin rights
    .EXAMPLE
     
        Add-YammerGroupAdmin -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -GroupName "Example Group" -EmailAddress "john.doe@contoso.com"
    .EXAMPLE
     
        Add-YammerGroupAdmin -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -GroupId "14582024" -EmailAddress "john.doe@contoso.com"
#>

    [cmdletbinding()]
    param
    (
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$AccessToken,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$GroupName,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [string]$GroupId,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$EmailAddress
    )
    
    begin
    {
        $uri = "https://www.yammer.com/api/v1/groups/{groupId}/make_admin?user_id={userId}"
    }
    process
    {
        if ($PSCmdlet.ParameterSetName -eq "GroupName")
        {
            $GroupId = Get-YammerGroup -AccessToken $AccessToken -GroupName $GroupName | SELECT -ExpandProperty Id
        }
        
        $UserId = Get-YammerUser -AccessToken $AccessToken -EmailAddress $EmailAddress | SELECT -ExpandProperty id
        
        Invoke-YammerRestRequest -Method Post -AccessToken $AccessToken -Uri "https://www.yammer.com/api/v1/groups/$GroupId/make_admin?user_id=$UserId"
    }
    end
    {
    }
}

Function Remove-YammerGroupAdmin
{
<#
<#
    .SYNOPSIS
        Removes a user as a Yammer group administrator. Must be a verified admin to execute this function.
    .DESCRIPTION
        Set's a user as a Yammer group administrator. Must be a verified admin to execute this function.
    .PARAMETER AccessToken
        Access token to execute the request
    .PARAMETER GroupId
        Id of the Yammer group to retrieve from the Yammer network
    .PARAMETER GroupName
        Name of the Yammer group to retrieve from the Yammer network
    .PARAMETER EmailAddress
        Email address of the user to revoke admin rights
    .EXAMPLE
     
        Remove-YammerGroupAdmin -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -GroupName "Example Group" -EmailAddress "john.doe@contoso.com"
    .EXAMPLE
     
        Remove-YammerGroupAdmin -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -GroupId "14582024" -EmailAddress "john.doe@contoso.com"
#>

    [cmdletbinding()]
    param
    (
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$AccessToken,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$GroupName,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [string]$GroupId,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$EmailAddress
    )
    
    begin
    {
    }
    process
    {
        if ($PSCmdlet.ParameterSetName -eq "GroupName")
        {
            $GroupId = Get-YammerGroup -AccessToken $AccessToken -GroupName $GroupName | SELECT -ExpandProperty Id
        }
        
        $UserId = Get-YammerUser -AccessToken $AccessToken -EmailAddress $EmailAddress | SELECT -ExpandProperty id
        
        Invoke-YammerRestRequest -Method Post -AccessToken $AccessToken -Uri "https://www.yammer.com/api/v1/groups/$GroupId/revoke_admin?user_id=$UserId"
    }
    end
    {
    }
}

Function Remove-YammerGroup
{
<#
    .SYNOPSIS
        Removes a Yammer group.
    .DESCRIPTION
        Removes a Yammer group.
    .PARAMETER AccessToken
        Access token to execute the request
    .PARAMETER GroupId
        Id of the Yammer group to retrieve from the Yammer network
    .PARAMETER GroupName
        Name of the Yammer group to retrieve from the Yammer network
    .EXAMPLE
     
        Remove-YammerGroup -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -GroupName "Example Group"
    .EXAMPLE
     
        Remove-YammerGroup -AccessToken "3066245-B1iZJ5bSp02QL7un4uxQw" -GroupId "14582024"
#>

    [cmdletbinding()]
    param
    (
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$AccessToken,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupName")]
        [string]$GroupName,
        [Parameter(Mandatory = $true, ParameterSetName = "GroupId")]
        [string]$GroupId
    )
    
    begin
    {
    }
    process
    {
        if ($PSCmdlet.ParameterSetName -eq "GroupName")
        {
            $group = Get-YammerGroup -AccessToken $AccessToken -GroupName $GroupName
        }
        else
        {
            $group = Get-YammerGroup -AccessToken $AccessToken -GroupId $GroupId
        }
        
        if ($group -and $group.state -eq "active")
        {
            Invoke-YammerRestRequest -Method Delete -AccessToken $AccessToken -Uri "https://www.yammer.com/api/v1/groups/$GroupId.json"
        }
        else
        {
            Write-Warning "The group $($group.full_name) was not found or has already been deleted."
        }
    }
    end
    {
    }
}

Function Remove-YammerGroupsUsingCSV
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [string]$Token,
        [Parameter(Mandatory = $true,
                   Position = 2)]
        [String]$CSVFile
    )
    Read-host "Please validate the Private mode is enabled in order to delete Private Groups"
    Read-Host "Expected CSV Column: ID,Name"
    $YammerGroups = Import-Csv $CSVFile
    $Count = ($YammerGroups | Measure).count
    [Int]$i = 1
    $Table = $Null
    $Table = @()
    Foreach ($YammerGroup in $YammerGroups)
    {
        $YammerGroupID = $Null
        $YammerGroupID = $YammerGroup.ID
        $YammerGroupName = $Null
        $YammerGroupName = $YammerGroup.Name
        Try
        {
            $YammerGroupBefore = $Null
            $YammerGroupBefore = Get-YammerGroup -AccessToken $Token -GroupId $YammerGroupID
            $YammerGroupNameBefore = $Null
            $YammerGroupNameBefore = $YammerGroupBefore.full_name
            Write-Host "The script will try to remove the Yammer Group : $YammerGroupName ($YammerGroupID) --- $i/$Count"
            Remove-YammerGroup -AccessToken $Token -GroupId $YammerGroupID
            Write-Host "The script removed the Yammer Group : $YammerGroupName ($YammerGroupID)"
            $Status = "Success"
        }
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $CMDLet = $Error[0].InvocationInfo.Line
            $FailedItem = $Error[0].Exception.ItemName
            Write-Host "The script failed to remove the Yammer Group : $YammerGroupName ($YammerGroupID)"
            $Status = "Failed"
        }
        $YammerGroupAfter = $Null
        $YammerGroupAfter = Get-YammerGroup -AccessToken $Token -GroupId $YammerGroupID
        
        $YammerGroupBeforeState = $Null
        $YammerGroupAfterState = $Null
        $YammerGroupBeforeState = $YammerGroupBefore.State
        $YammerGroupAfterState = $YammerGroupAfter.State
        
        $Table += New-object PSobject -Property ([Ordered] @{
                Source_GroupName = $YammerGroupName;
                Found_GroupName  = $YammerGroupNameBefore;
                YammerGroupID    = $YammerGroupID;
                StateBefore         = $YammerGroupBeforeState;
                StateAfter         = $YammerGroupAfterState;
                Status             = $Status;
            })
        
        $i++
    }
    $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    $ReportFilexlsx = ".\Report_YammerGroup_CleanUp_" + $DateFull + ".xlsx"
    $Table | Export-Excel $ReportFilexlsx -TableName "YammerGroupCleanUp" -Title "YammerGroupCleanUp" -TitleBold -WorksheetName "YammerGroupCleanUp" -TableStyle Medium9 -AutoSize -AutoFilter
    Write-log INFO -Message "Generate the following Report: $ReportFilexlsx"
}

Function Backup-YammerAllGroups
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [String]$Token
    )
    $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    $Location = $Null
    $Location = (Get-Location).Path
    $RootFolder = $Location + "\YammerGroupBackup_" + $DateFull + "\"
    Create-folder $RootFolder
    #Initiate the Hash Table
    [Int]$i = 1
    $YammerGroups = Get-YammerGroup -AccessToken $Token
    $Count = ($YammerGroups | Measure).count
    ForEach ($YammerGroup in $YammerGroups)
    {
        $YammerGroupID = $Null
        $YammerGroupID = $YammerGroup.ID
        $YammerGroupfull_name = $Null
        $YammerGroupfull_name = $YammerGroup.full_name
        $YammerGroupName = $Null
        $YammerGroupName = $YammerGroup.name
        Write-Log -Level Warning -message "The script is analyzing $YammerGroupfull_name ($YammerGroupID) ….. --- $i/$Count"
        
        $YammerGroupData = $Null
        $YammerGroupData = Get-YammerGroup -AccessToken $Token -GroupId $YammerGroupID
        # Export Group Info
        $YammerGroupXMLFile = $Null
        $YammerGroupXMLFile = $RootFolder + $YammerGroupName + "_YammerGroup_Info_" + $DateFull + ".xml"
        $YammerGroupData | Export-Clixml $YammerGroupXMLFile
        Write-Log -Level Info -message "The script generated a report for $YammerGroupfull_name ($YammerGroupID): $YammerGroupXMLFile "
        #Export Member of groups
        $YammerGroupMemberData = Get-YammerGroupMembership -AccessToken $Token -GroupId $YammerGroupID
        $YammerGroupMembersXMLFile = $Null
        $YammerGroupMembersXMLFile = $RootFolder + $YammerGroupName + "_YammerGroup_Members_" + $DateFull + ".xml"
        $YammerGroupMemberData | Export-Clixml $YammerGroupMembersXMLFile
        Write-Log -Level Info -message "The script generated a report for $YammerGroupfull_name ($YammerGroupID): $YammerGroupMembersXMLFile "
        $i++
    }
    
}

Function Add-YammerUsersToGroupUsingCSV
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 2)]
        [String]$GroupID,
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [String]$Token,
        [Parameter(Mandatory = $true,
                   Position = 3)]
        [String]$CSVFile
    )
    
    Read-Host "Expected CSV Column: EmailAddress"
    $YammerGroup = Get-YammerGroup -AccessToken $Token -GroupID $GroupID
    $YammeGroupName = $Null
    $YammeGroupName = $YammerGroup.Full_Name
    #Initiate the Hash Table
    [Int]$i = 1
    $Table = $Null
    $Table = @()
    $YammerUsers = Import-Csv $CSVFile
    $Count = ($YammerUsers | Measure).count
    
    ForEach ($YammerUser in $YammerUsers)
    {
        $EmailAddress = $Null
        $EmailAddress = $YammerUser.EmailAddress
        Write-Log -Level Warning -message "The script is adding $EmailAddress to $YammeGroupName ($GroupID) --- $i/$Count"
        Add-YammerGroupMember -AccessToken $Token -GroupID $GroupID -EmailAddress $EmailAddress
        $i++
    }
}

Function Generate-YammerGroupReport
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [string]$Token,
        [Parameter(Mandatory = $true,
                   Position = 2)]
        [String]$CSVFile
    )
    Read-Host "Expected CSV Column: 'Group Display Name', 'Owner Principal Name','Group Type','Office 365 Connected','Member Count'"
    $YammerGroups = Import-Csv $CSVFile
    $YammerGroupData = $Null
    $AllYammerGroups = Get-YammerGroup -AccessToken $Token
    #Initiate the Hash Table
    [Int]$i = 1
    $Table = $Null
    $Table = @()
    $Count = ($YammerGroups | Measure).count
    
    ForEach ($YammerGroup in $YammerGroups)
    {
        $Name = $Null
        $Name = $YammerGroup.'Group Display Name'
        $Owner = $Null
        $Owner = $YammerGroup.'Owner Principal Name'
        $Type = $Null
        $Type = $YammerGroup.'Group Type'
        $Connected = $Null
        $Connected = $YammerGroup.'Office 365 Connected'
        $MemberCount = $Null
        $MemberCount = $YammerGroup.'Member Count'
        
        Write-Log -Level Warning -message "The script is analyzing $Name ….. --- $i/$Count"
        
        $GroupID = $Null
        $GroupID = ($AllYammerGroups | where { $_.full_name -eq $Name }).id
        $Table += New-object PSobject -Property ([Ordered] @{
                Name        = $Name;
                GroupID        = $GroupID;
                Owner        = $Owner;
                Type        = $Type;
                Connected   = $Connected;
                MemberCount = $MemberCount;
            })
        
        $i++
    }
    
    $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    $ReportFilexlsx = ".\Report_YammerGroups_" + $DateFull + ".xlsx"
    $Table | Export-Excel $ReportFilexlsx -TableName "YammerGroups" -Title "YammerGroups" -TitleBold -WorksheetName "YammerGroups" -TableStyle Medium9 -AutoSize -AutoFilter
    Write-log INFO -Message "Generate the following Report: $ReportFilexlsx"
    
}

#endregion

#region MCAS
####################################################
###################### MCAS ########################
####################################################
Function Import-MCAS_IPAddress_fromCSV
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [string]$CSVFile
    )
    
    Read-Host "Expected CSV Column: Organization,Product,IPAddress,Mask"
    $IP_Sites = Import-Csv $CSVFile
    $Count = ($IP_Sites | Measure).count
    [Int]$i = 1
    $Table = $Null
    $Table = @()
    Foreach ($IP_Site in $IP_Sites)
    {
        $Name = $Null
        $Product = $Null
        $Product = $IP_Site.Product
        $Organization = $Null
        $Organization = $IP_Site.Organization
        $IP = $Null
        $IP = $IP_Site.IPAddress
        $Mask = $Null
        $Mask = $IP_Site.Mask
        $Name = $Organization + " - " + $Product + " - " + $IP
        $Subnet = $Null
        $Subnet = $IP + $Mask
        Try
        {
            Write-Log -Level Warning -message "The script will update $Name with Subnet: $Subnet ….. --- $i/$Count"
            New-MCASSubnetCollection -Name $Name -Category Corporate -Subnets $Subnet -Tags $Organization -Organization $Organization -Quiet
            $Status = "Success"
            Read-Host "Pause before next"
        }
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $CMDLet = $Error[0].InvocationInfo.Line
            $FailedItem = $Error[0].Exception.ItemName
            Write-Log -Level Error -Message "Failed to add $Name with Subnet: $Subnet "
            Write-Log -Level Error -Message "Failed to run the following CMDLet: $CMDLet"
            Write-Log -Level Error -Message "Failed with Error:$ErrorMessage"
            $Status = "Failed"
        }
        $Table += New-object PSobject -Property ([Ordered] @{
                Organization = $Organization;
                Name         = $Name;
                IPAddress    = $IP;
                Subnet         = $Subnet;
                Status         = $Status;
            })
        $i++
    }
    $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    $ReportFilexlsx = ".\Report_MCAS_Import_IPAddresses_" + $DateFull + ".xlsx"
    $Table | Export-Excel $ReportFilexlsx -TableName "MCASIP" -Title "MCAS IPAddresses" -TitleBold -WorksheetName "MCASIP" -TableStyle Medium9 -AutoSize -AutoFilter
    Write-log INFO -Message "Generate the following Report: $ReportFilexlsx"
}

#endregion

#region Planner
####################################################
###################### Planner ########################
####################################################
Function Connect-Planner
{
<#
.Synopsis
(Private to module) Attempts to obtain a token from AAD.
.Description
This function attempts to obtain a token from Azure Active Directory.
.example
$authorizationContext = Connect-AAD
#>

    
    $authUrl = "https://login.microsoftonline.com/common" # Prod environment
    $resource = "https://tasks.office.com" # Prod environment
    $clientId = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
    
    $redirectUri = "urn:ietf:wg:oauth:2.0:oob"
    $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Always"
    
    $authentiationContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authUrl, $False
    
    $authenticationResult = $authentiationContext.AcquireTokenAsync($resource, $clientId, $redirectUri, $platformParameters).Result
    return $authenticationResult
}

Function Set-PlannerConfiguration
{
<#
.Synopsis
Configures tenant level settings for Microsoft Planner.
.Description
This cmdlet allows tenant administrators to change policies regarding availability of certain features in Microsoft Planner. The changes to settings take effect immediately. This cmdlet specifies the administrator preference on whether the feature should be available. The features can still be disabled due to Microsoft Planner behavior, at the discretion of Microsoft.
.Parameter Uri
The URL of the Tenant-Level Settings API for the Planner instance to control.
.Parameter AccessToken
A valid access token of a user with tenant-level administrator privileges.
.Parameter AllowCalendarSharing
If set to $false, disables creating iCalendar links from Microsoft Planner, and disables previously created iCalendar links. If set to $true, enables creating iCalendar links from Microsoft Planner and re-enables any previously created iCalendar links.
.Parameter AllowTenantMoveWithDataLoss
If set to $true, allows the tenant to be moved to another Planner environment or region. This move will result in the tenant's existing Planner data being lost.
.Parameter AllowRosterCreation
If set to $true, allows the users of the tenant to create rosters as the container for a plan to facilitate ad-hoc collaboration. This setting does not restrict the use of existing roster contained plans.
.example
 
Set-PlannerConfiguration -AllowCalendarSharing $true
 
.example
 
Set-PlannerConfiguration -AllowTenantMoveWithDataLoss $true
 
.example
 
Set-PlannerConfiguration -AllowRosterCreation $false
#>

    param (
        [ValidateNotNull()]
        [System.String]$Uri = "https://tasks.office.com/taskAPI/tenantAdminSettings/Settings",
        [ValidateNotNullOrEmpty()]
        [Parameter(Mandatory = $false)]
        [System.String]$AccessToken,
        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [System.Boolean]$AllowCalendarSharing,
        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [System.Boolean]$AllowTenantMoveWithDataLoss,
        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [System.Boolean]$AllowRosterCreation
    )
    
    if (!($PSBoundParameters.ContainsKey("AccessToken")))
    {
        $authorizationContext = Connect-Planner
        $AccessToken = $authorizationContext.AccessTokenType.ToString() + ' ' + $authorizationContext.AccessToken
    }
    
    $flags = @{ }
    
    if ($PSBoundParameters.ContainsKey("AllowCalendarSharing"))
    {
        $flags.Add("allowCalendarSharing", $AllowCalendarSharing);
    }
    
    if ($PSBoundParameters.ContainsKey("AllowTenantMoveWithDataLoss"))
    {
        $flags.Add("allowTenantMoveWithDataLoss", $AllowTenantMoveWithDataLoss);
    }
    
    if ($PSBoundParameters.ContainsKey("AllowRosterCreation"))
    {
        $flags.Add("allowRosterCreation", $AllowRosterCreation);
    }
    
    $propertyCount = $flags | Select-Object -ExpandProperty Count
    
    if ($propertyCount -eq 0)
    {
        Throw "No properties were set."
    }
    
    $requestBody = $flags | ConvertTo-Json
    
    Invoke-RestMethod -ContentType "application/json;odata.metadata=full" -Headers @{ "Accept" = "application/json"; "Authorization" = $AccessToken; "Accept-Charset" = "UTF-8"; "OData-Version" = "4.0;NetFx"; "OData-MaxVersion" = "4.0;NetFx" } -Method PATCH -Body $requestBody $Uri
}

Function Get-PlannerConfiguration
{
<#
.Synopsis
Retrieves tenant level settings for Microsoft Planner.
.Description
This cmdlet allows users and tenant administrators to retrieve policy preferences set by the tenant administrator regarding availability of certain features in Microsoft Planner. While a feature may be permitted by a tenant administrator's preference, features can still be disabled due to Microsoft Planner behavior, at the discretion of Microsoft.
.Parameter Uri
The URL of the Tenant-Level Settings API for the Planner instance to retrieve.
.Parameter AccessToken
A valid access token of a user with tenant-level administrator privileges.
 
.example
 
Get-PlannerConfiguration
#>

    param (
        [ValidateNotNull()]
        [System.String]$Uri = "https://tasks.office.com/taskAPI/tenantAdminSettings/Settings",
        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [System.String]$AccessToken
    )
    
    if (!($PSBoundParameters.ContainsKey("AccessToken")))
    {
        $authorizationContext = Connect-Planner
        $accessToken = $authorizationContext.AccessTokenType.ToString() + ' ' + $authorizationContext.AccessToken
    }
    
    $response = Invoke-RestMethod -ContentType "application/json;odata.metadata=full" -Headers @{ "Accept" = "application/json"; "Authorization" = $AccessToken; "Accept-Charset" = "UTF-8"; "OData-Version" = "4.0;NetFx"; "OData-MaxVersion" = "4.0;NetFx" } -Method GET $Uri
    $result = New-Object PSObject -Property @{
        "AllowCalendarSharing" = $response.allowCalendarSharing
        "AllowTenantMoveWithDataLoss" = $response.allowTenantMoveWithDataLoss
        "AllowRosterCreation"  = $response.allowRosterCreation
    }
    
    return $result
}

#endregion

#region Audit

#endregion