NN.MSGraph.psm1

#Region './Public/Get-MgAccessToken.ps1' 0
function Get-MgAccessToken {
    param (
        $accessTokenPath = "$env:USERPROFILE\.creds\MSGraph\msgraphAccessToken.xml"
    )

    #Conditions to refresh access token
    if (Test-Path $accessTokenPath) {
        [datetime]$accessTokenExpiryDate = (Import-Clixml $accessTokenPath | ConvertFrom-SecureString -AsPlainText | ConvertFrom-Json).expiry_date

        #Refresh access token if there's less than 5 minutes till token expiry
        if (($accessTokenExpiryDate.AddMinutes(-5)) -lt (Get-Date)) {
            #Request new access token
            New-MgAccessToken
        }
    } else {
        #Request new access token
        New-MgAccessToken
    }

    #Import the access token
    (Import-Clixml $accessTokenPath | ConvertFrom-SecureString -AsPlainText | ConvertFrom-Json).access_token
}
#EndRegion './Public/Get-MgAccessToken.ps1' 23
#Region './Public/Get-MgApiUser.ps1' 0
function Get-MgApiUser {
    param (
        [Parameter(Mandatory)]$identifier
    )
    
    $splat = @{
        "Method" = "GET"
        "Uri" = "https://graph.microsoft.com/v1.0/users/$identifier"
        "Headers" = @{
            "Authorization" = "Bearer $(Get-MgAccessToken)"
        }
    }
    Invoke-RestMethod @splat
}
#EndRegion './Public/Get-MgApiUser.ps1' 15
#Region './Public/Get-MgAuthenticationMetod.ps1' 0
function Get-MgAuthenticationMethod {
    param (
        [Parameter(Mandatory)][string]$UPN
    )
    
    $splat = @{
        "Method" = "GET"
        "Uri" = "https://graph.microsoft.com/beta/users/$UPN/authentication/phoneMethods"
        "Headers" = @{
            "Authorization" = "Bearer $(Get-GraphAccessToken)"
        }
    }
    Invoke-RestMethod @splat
}
#EndRegion './Public/Get-MgAuthenticationMetod.ps1' 15
#Region './Public/Get-MgDirectReportsList.ps1' 0
function Get-MgDirectReportsList {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)][string]$identifier
    )

    process {
        $splat = @{
            "Method" = "GET"
            "Uri" = "https://graph.microsoft.com/v1.0/users/$identifier/directReports"
            "Headers" = @{
                "Authorization" = "Bearer $(Get-MgAccessToken)"
            }
        }
        $Result = Invoke-RestMethod @splat
        $Result.value
    }
}
#EndRegion './Public/Get-MgDirectReportsList.ps1' 19
#Region './Public/Get-MgManager.ps1' 0
function Get-MgManager {
    param (
        [Parameter(Mandatory)][string]$identifier
    )
    $splat = @{
        "Method" = "GET"
        "Uri" = "https://graph.microsoft.com/v1.0/users/$identifier/manager"
        "Headers" = @{
            "Authorization" = "Bearer $(Get-MgAccessToken)"
        }
    }
    Invoke-RestMethod @splat
}
#EndRegion './Public/Get-MgManager.ps1' 14
#Region './Public/Get-MgSecret.ps1' 0
function Get-MgSecret {
    param (
        $secretPath = "$env:USERPROFILE\.creds\MSGraph\msgraphSecret.xml"
    )


    #Check if secret file exists
    if (Test-Path $secretPath) {
        [datetime]$dateTomorrow = (Get-Date).AddDays(1)
        $secretExpiryDate = (Import-Clixml $secretPath | ConvertFrom-SecureString -AsPlainText | ConvertFrom-Json).endDateTime

        #Refresh secret if there's less than 1 day till secret expiry
        if ($dateTomorrow -gt $secretExpiryDate) {
            New-MgSecret
        }
    } else {
        #Refresh secret if the secret file doesn't exist
        New-MgSecret
    }

    #Import the secret key
    (Import-Clixml $secretPath | ConvertFrom-SecureString -AsPlainText | ConvertFrom-Json).secretText
}
#EndRegion './Public/Get-MgSecret.ps1' 24
#Region './Public/Get-MgSharepointColumns.ps1' 0
function Get-MgSharepointColumns {
    [CmdletBinding(DefaultParameterSetName="List columns")]
    param (
        [Parameter(Mandatory)][string]$SiteId,
        [Parameter(Mandatory)][string]$ListId, 
        [Parameter(Mandatory,ParameterSetName="Get column by id")][string]$ColumnId,
        [Parameter(ParameterSetName="List columns")][switch]$ListColumns
    )

    process {
        $Uri = "https://graph.microsoft.com/v1.0/sites/$SiteId/lists/$ListId"

        switch ($PsCmdlet.ParameterSetName) {
            "Get column by id" {
                $Uri = "$Uri/columns/$ColumnId"
            }
            "List columns" {
                $Uri = "$Uri/columns"
            }
        }

        $Splat = @{
            "Method" = "GET"
            "Uri" = $Uri
            "Headers" = @{
                "Authorization" = "Bearer $(Get-MgAccessToken)"
            }
        }
        $result = Invoke-RestMethod @Splat

        switch ($PsCmdlet.ParameterSetName) {
            "Get column by id" {
                $Result
            }
            "List columns" {
                $Result.value
            }
        }
    }
}
#EndRegion './Public/Get-MgSharepointColumns.ps1' 41
#Region './Public/Get-MgShift.ps1' 0
function Get-MgShift {
    param (
        #Id of the Team to get shifts from
        [Parameter(Mandatory)]$teamId,
        #Id of the user that the request is sent on the behalf of
        [Parameter(Mandatory)]$actAsUID,
        [Parameter(Mandatory)]$shiftId
    )

    $splat = @{
        "Method" = "GET"
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule/shifts/$shiftId"
        "Headers" = @{
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "MS-APP-ACTS-AS" = $actAsUID
        }
    }
    Invoke-RestMethod @splat
}
#EndRegion './Public/Get-MgShift.ps1' 20
#Region './Public/Get-MgShiftList.ps1' 0
function Get-MgShiftList {
    [CmdletBinding(DefaultParameterSetName="List shifts")]
    param (
        #Id of the Team to get shifts from
        [Parameter(Mandatory)]$teamId,
        #Id of the user that the request is sent on the behalf of
        [Parameter(Mandatory)]$actAsUID,
        #Timespan to fetch shifts from
        [Parameter(ParameterSetName="Get shifts within timeframe",Mandatory)][datetime]$dateFrom,
        [Parameter(ParameterSetName="Get shifts within timeframe")][datetime]$dateTo,
        [Parameter(ParameterSetName="List shifts")][switch]$ListShifts
    )
    
    $splat = $ExportObjects = $null

    switch ($PsCmdlet.ParameterSetName) {
        "Get shifts within timeframe" {
            if (!$dateTo) {
                $dateTo = $dateFrom.AddDays(1)
            }
            
            #Convert to "ISO 8601" date format, which is supported in json queries
            $convertedDateFrom = [Xml.XmlConvert]::ToString($dateFrom,[Xml.XmlDateTimeSerializationMode]::Utc)
            $convertedDateTo = [Xml.XmlConvert]::ToString($dateTo,[Xml.XmlDateTimeSerializationMode]::Utc)

            $splat += @{
                "Body" = @{
                    '$filter' = @"
sharedShift/startDateTime ge $convertedDateFrom and sharedShift/endDateTime le $convertedDateTo
"@

                }
            }
        }
    }

    $splat += @{
        "Method" = "GET"
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule/shifts"
        "Headers" = @{
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "MS-APP-ACTS-AS" = $actAsUID
        }
    }
    $result = Invoke-RestMethod @splat
    $ExportObjects += $result.value

    while ($result.'@odata.nextLink') {
        $splat.Uri = $result.'@odata.nextLink'
        $result = Invoke-RestMethod @splat
        $ExportObjects += $result.value
    }
    
    Write-Output $ExportObjects
}
#EndRegion './Public/Get-MgShiftList.ps1' 55
#Region './Public/Get-MgShiftSchedule.ps1' 0
function Get-MgShiftSchedule {
    param (
        #Id of the Team to get shifts from
        [Parameter(Mandatory)][string]$teamId,
        #Id of the user that the request is sent on the behalf of
        [Parameter(Mandatory)][string]$actAsUID
    )

    $Splat = @{
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule"
        "Method" = "GET"
        "Headers" = @{
            "Accept" = "application/json"
            "Content-Type" = "application/json"
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "MS-APP-ACTS-AS" = $actAsUID
        }
    }
    Invoke-RestMethod @Splat
}
#EndRegion './Public/Get-MgShiftSchedule.ps1' 21
#Region './Public/Get-MgShiftSchedulingGroup.ps1' 0
function Get-MgShiftSchedulingGroup {
    param (
        #Id of the Team to get shifts from
        [string][Parameter(Mandatory)]$teamId,
        #Id of the user that the request is sent on the behalf of
        [string][Parameter(Mandatory)]$actAsUID,
        [string][Parameter(Mandatory)]$schedulingGroupId
    )

    $splat = @{
        "Method" = "GET"
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule/schedulingGroups/$schedulingGroupId"
        "Headers" = @{
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "MS-APP-ACTS-AS" = $actAsUID
        }
    }
    Invoke-RestMethod @splat
}
#EndRegion './Public/Get-MgShiftSchedulingGroup.ps1' 20
#Region './Public/Get-MgShiftSchedulingGroupList.ps1' 0
function Get-MgShiftSchedulingGroupList {
    param (
        #Id of the Team to get shifts from
        [Parameter(Mandatory)]$teamId,
        #Id of the user that the request is sent on the behalf of
        [Parameter(Mandatory)]$actAsUID
    )

    $splat = @{
        "Method" = "GET"
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule/schedulingGroups"
        "Headers" = @{
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "MS-APP-ACTS-AS" = $actAsUID
        }
    }
    $result = Invoke-RestMethod @splat
    $result.value
}
#EndRegion './Public/Get-MgShiftSchedulingGroupList.ps1' 20
#Region './Public/Get-MgShiftTimeOff.ps1' 0
function Get-MgShiftTimeOff {
    param (
        #Id of the Team to get shifts from
        [Parameter(Mandatory)]$teamId,
        #Id of the user that the request is sent on the behalf of
        [Parameter(Mandatory)]$actAsUID,
        [Parameter(Mandatory)]$timeOffId
    )

    $splat = @{
        "Method" = "GET"
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule/timesOff/$timeOffId"
        "Headers" = @{
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "MS-APP-ACTS-AS" = $actAsUID
        }
    }
    Invoke-RestMethod @splat   
}
#EndRegion './Public/Get-MgShiftTimeOff.ps1' 20
#Region './Public/Get-MgShiftTimeOffList.ps1' 0
function Get-MgShiftTimeOffList {
    [CmdletBinding(DefaultParameterSetName="List timeOffObjects")]
    param (
        #Id of the Team to get timeOffObjects from
        [Parameter(Mandatory)]$teamId,
        #Id of the user that the request is sent on the behalf of
        [Parameter(Mandatory)]$actAsUID,
        #Timespan to fetch timeOffObjects from
        [Parameter(ParameterSetName="Get timeOffObjects within timeframe",Mandatory)][datetime]$dateFrom,
        [Parameter(ParameterSetName="Get timeOffObjects within timeframe")][datetime]$dateTo,
        [Parameter(ParameterSetName="List timeOffObjects")][switch]$ListTimeOffObjects
    )

    $splat = $ExportObjects = $null

    switch ($PsCmdlet.ParameterSetName) {
        "Get timeOffObjects within timeframe" {
            if (!$dateTo) {
                $dateTo = $dateFrom.AddDays(1)
            }
            
            #Convert to "ISO 8601" date format, which is supported in json queries
            $convertedDateFrom = [Xml.XmlConvert]::ToString($dateFrom,[Xml.XmlDateTimeSerializationMode]::Utc)
            $convertedDateTo = [Xml.XmlConvert]::ToString($dateTo,[Xml.XmlDateTimeSerializationMode]::Utc)

            $splat += @{
                "Body" = @{
                    '$filter' = @"
sharedTimeOff/startDateTime ge $convertedDateFrom and sharedTimeOff/endDateTime le $convertedDateTo
"@

                }
            }
        }
    }

    $splat += @{
        "Method" = "GET"
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule/timesOff"
        "Headers" = @{
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "MS-APP-ACTS-AS" = $actAsUID
        }
    }
    $result = Invoke-RestMethod @splat
    $ExportObjects += $result.value

    while ($result.'@odata.nextLink') {
        $splat.Uri = $result.'@odata.nextLink'
        $result = Invoke-RestMethod @splat
        $ExportObjects += $result.value
    }
    
    Write-Output $ExportObjects
}
#EndRegion './Public/Get-MgShiftTimeOffList.ps1' 55
#Region './Public/Get-MgShiftTimeOffReasonList.ps1' 0
function Get-MgShiftTimeOffReasonList {
    param (
        #Id of the Team to get shifts from
        [Parameter(Mandatory)]$teamId,
        #Id of the user that the request is sent on the behalf of
        [Parameter(Mandatory)]$actAsUID
    )

    $splat = @{
        "Method" = "GET"
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule/timeOffReasons"
        "Headers" = @{
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "MS-APP-ACTS-AS" = $actAsUID
        }
    }
    $result = Invoke-RestMethod @splat
    $result.value
}
#EndRegion './Public/Get-MgShiftTimeOffReasonList.ps1' 20
#Region './Public/Invoke-MgShiftScheduleShare.ps1' 0
function Invoke-MgShiftScheduleShare {
    param (
        #Id of the Team to get shifts from
        [Parameter(Mandatory)][string]$teamId,
        #Id of the user that the request is sent on the behalf of
        [Parameter(Mandatory)][string]$actAsUID,
        [Parameter(Mandatory)][bool]$notifyTeam,
        [Parameter(Mandatory)][datetime]$startDateTime,
        [Parameter(Mandatory)][datetime]$endDateTime
    )

    $ParameterExclusion = @("teamId","actAsUID")
    $Body = $null
    $PSBoundParameters.Keys.ForEach({
        [string]$Key = $_
        $Value = $PSBoundParameters.$key
    
        if ($ParameterExclusion -contains $Key) {
            return
        }
    
        $Body += @{
            $Key = $Value
        }
    })

    $Splat = @{
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule/share"
        "Method" = "POST"
        "Headers" = @{
            "Accept" = "application/json"
            "Content-Type" = "application/json"
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "MS-APP-ACTS-AS" = $actAsUID
        }
        "Body" = ($Body | ConvertTo-Json)
    }
    Invoke-RestMethod @Splat
}
#EndRegion './Public/Invoke-MgShiftScheduleShare.ps1' 40
#Region './Public/New-MgAccessToken.ps1' 0
function New-MgAccessToken {
    param (
        #Azure tenantID
        $tenantIdPath = "$env:USERPROFILE\.creds\MSGraph\msgraphTenantId.xml",
        #AppID of the Azure app
        $appIdPath = "$env:USERPROFILE\.creds\MSGraph\msgraphAppId.xml",
        $accessTokenPath = "$env:USERPROFILE\.creds\MSGraph\msgraphAccessToken.xml"
    )
    
    #Create folder to store credentials
    $accessTokenDir = $accessTokenPath.Substring(0, $accessTokenPath.lastIndexOf('\'))
    if (!(Test-Path $accessTokenDir)) {
        $null = New-Item -ItemType Directory $accessTokenDir
    }

    #Get tenantId
    if (Test-Path $tenantIdPath) {
        $tenantId = Import-Clixml $tenantIdPath | ConvertFrom-SecureString -AsPlainText
    } else {
        #Create tenantId file
        $tenantId = Read-Host "Enter MSGraph tenantId"
        $tenantId | ConvertTo-SecureString -AsPlainText | Export-Clixml $tenantIdPath
    }

    #Get appId
    if (Test-Path $appIdPath) {
        $appId = Import-Clixml $appIdPath | ConvertFrom-SecureString -AsPlainText
    } else {
        #Create appId file
        $appId = Read-Host "Enter MSGraph appId"
        $appId | ConvertTo-SecureString -AsPlainText | Export-Clixml $appIdPath
    }

    $splat = @{
        "Method" = "POST"
        "Uri" = "https://login.microsoftonline.com/$tenantId/oauth2/token"
        "Body" = @{
            "resource" = "https://graph.microsoft.com"
            "client_id"     = $appId
            "client_secret" = Get-MgSecret
            "grant_type"    = "client_credentials"
            "scope"         = "openid"
        }
    }
    $result = Invoke-RestMethod @splat

    #Adds access token and expiry date to access token file
    [PSCustomObject]@{
        access_token = $result.access_token
        expiry_date = (Get-Date).AddSeconds($result.expires_in)
    } | ConvertTo-Json | ConvertTo-SecureString -AsPlainText | Export-Clixml -Path $accessTokenPath -Force
}
#EndRegion './Public/New-MgAccessToken.ps1' 53
#Region './Public/New-MgSecret.ps1' 0
function New-MgSecret {
    param (
        [Parameter(Mandatory)][string]$customKeyIdentifier,
        #ObjectId of the Azure application
        $objectIdPath = "$env:USERPROFILE\.creds\MSGraph\msgraphObjectId.xml",
        $secretPath = "$env:USERPROFILE\.creds\MSGraph\msgraphSecret.xml"
    )

    #Create folder to store credentials
    $secretDir = $secretPath.Substring(0, $secretPath.lastIndexOf('\'))
    if (!(Test-Path $secretDir)) {
        $null = New-Item -ItemType Directory $secretDir
    }

    #Create objectId file
    if (Test-Path $objectIdPath) {
        $objectId = Import-Clixml $objectIdPath | ConvertFrom-SecureString -AsPlainText
    } else {
        $objectId = Read-Host "Enter MSGraph objectId"
        $objectId | ConvertTo-SecureString -AsPlainText | Export-Clixml $objectIdPath
    }

    #Install required modules
    $RequiredModulesNameArray = @("Az.Accounts","Az.Resources")
    $RequiredModulesNameArray.ForEach({
        if (Get-InstalledModule $_ -ErrorAction SilentlyContinue) {
            Import-Module $_ -Force
        } else {
            Install-Module $_ -Force -Repository PSGallery
        }
    })

    
    $customKeyIdentifierBytes = [System.Text.Encoding]::UTF8.GetBytes($customKeyIdentifier)
    $customKeyIdentifierB64 = [System.Convert]::ToBase64String($customKeyIdentifierBytes)

    #Connect to the Azure account
    $null = Connect-AzAccount
    #Create a new secret
    $result = New-AzADAppCredential -ObjectId $objectId -CustomKeyIdentifier $customKeyIdentifierB64
    #Export secret to the secret file
    $result | ConvertTo-SecureString -AsPlainText | Export-Clixml $secretPath -Force
    #Output the eol date of the secret
    Write-Output "MSGraph secret expires $($result.endDateTime.ToString("dd/MM/yyyy hh:mm"))"
}
#EndRegion './Public/New-MgSecret.ps1' 46
#Region './Public/New-MgSharepointListItem.ps1' 0
function New-MgSharepointListItem {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)][string]$SiteId,
        [Parameter(Mandatory)][string]$ListId,
        [Parameter(Mandatory)][hashtable]$RequestBody
    )

    process {
        $splat = @{
            "Method" = "POST"
            "Uri" = "https://graph.microsoft.com/v1.0/sites/$SiteId/lists/$ListId/items"
            "Headers" = @{
                "Authorization" = "Bearer $(Get-MgAccessToken)"
                "Content-type" = "application/json"
            }
            "Body" = @{
                "fields" = $RequestBody
            } | ConvertTo-Json
        }
        Invoke-RestMethod @splat
    }
}
#EndRegion './Public/New-MgSharepointListItem.ps1' 24
#Region './Public/New-MgShift.ps1' 0
function New-MgShift {
    param (
        [Parameter(Mandatory)][string]$userId,
        [Parameter(Mandatory)][datetime]$startDateTime,
        [Parameter(Mandatory)][datetime]$endDateTime,
        [Parameter(Mandatory)][string]$displayName,
        [Parameter(Mandatory)][string]$theme,
        [Parameter(Mandatory)][string]$schedulingGroupId,
        #Id of the Team to get shifts from
        [Parameter(Mandatory)][string]$teamId,
        #Id of the user that the request is sent on the behalf of
        [Parameter(Mandatory)][string]$actAsUID,
        [Parameter(Mandatory)][ValidateSet("sharedShift","draftShift")][string]$shiftType,
        [string]$notes
    )

    #Convert to "ISO 8601" date format and UTC timezone, which is supported in json queries
    $convertedStartDateTime = [Xml.XmlConvert]::ToString($startDateTime,[Xml.XmlDateTimeSerializationMode]::Utc)
    $convertedEndDateTime = [Xml.XmlConvert]::ToString($endDateTime,[Xml.XmlDateTimeSerializationMode]::Utc)

    $Body = @{
        "userId" = $userId
        "schedulingGroupId" = $schedulingGroupId
        "$shiftType" = @{
            "@odata.type" = "microsoft.graph.shiftItem"
            "displayName" = $displayName
            "startDateTime" = $convertedStartDateTime
            "endDateTime" = $convertedEndDateTime
            "notes" = $notes
            "theme" = $theme
        }
    }

    $splat = @{
        "Method" = "POST"
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule/shifts"
        "Headers" = @{
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "Content-type" = "application/json"
            "MS-APP-ACTS-AS" = $actAsUID
        }
        "Body" = [System.Text.Encoding]::UTF8.GetBytes(($Body | ConvertTo-Json))
    }
    Invoke-RestMethod @splat
}
#EndRegion './Public/New-MgShift.ps1' 46
#Region './Public/New-MgShiftSchedule.ps1' 0
function New-MgShiftSchedule {
    param (
        #Id of the Team to get shifts from
        [Parameter(Mandatory)][string]$teamId,
        #Id of the user that the request is sent on the behalf of
        [Parameter(Mandatory)][string]$actAsUID,
        [Parameter(Mandatory)][bool]$enabled,
        [Parameter(Mandatory)][string]$timeZone,
        [bool]$offerShiftRequestsEnabled,
        [bool]$openShiftsEnabled,
        [bool]$swapShiftsRequestsEnabled,
        [bool]$timeClockEnabled,
        [bool]$timeOffRequestsEnabled
    )

    $ParameterExclusion = @()
    $Body = $null
    $PSBoundParameters.Keys.ForEach({
        [string]$Key = $_
        $Value = $PSBoundParameters.$key
    
        if ($ParameterExclusion -contains $Key) {
            return
        }
    
        $Body += @{
            $Key = $Value
        }
    })

    $Splat = @{
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule"
        "Method" = "PUT"
        "Headers" = @{
            "Accept" = "application/json"
            "Content-Type" = "application/json"
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "MS-APP-ACTS-AS" = $actAsUID
        }
        "Body" = $Body | ConvertTo-Json -Depth 99
    }

    Write-Warning @"
Are you sure you want to perform destructive action that replaces the shift schedule on the team
`"$teamId`"
"@

    $confirmation = Read-Host "Press [y] to confirm"
    if ($confirmation -ne 'y') {
        Write-Host "Destructive action successfully cancelled"
        return
    }

    Invoke-RestMethod @Splat
}
#EndRegion './Public/New-MgShiftSchedule.ps1' 55
#Region './Public/New-MgShiftSchedulingGroup.ps1' 0
function New-MgShiftSchedulingGroup {
    param (
        #Id of the Team to get shifts from
        [Parameter(Mandatory)][string]$teamId,
        #Id of the user that the request is sent on the behalf of
        [Parameter(Mandatory)][string]$actAsUID,
        [Parameter(Mandatory)][string]$displayName,
        [array]$userIds
    )

    $ParameterExclusion = @()
    $Body = $null
    $PSBoundParameters.Keys.ForEach({
        [string]$Key = $_
        $Value = $PSBoundParameters.$key
    
        if ($ParameterExclusion -contains $Key) {
            return
        }
    
        $Body += @{
            $Key = $Value
        }
    })

    $Splat = @{
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule/schedulingGroups"
        "Method" = "POST"
        "Headers" = @{
            "Accept" = "application/json"
            "Content-Type" = "application/json"
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "MS-APP-ACTS-AS" = $actAsUID
        }
        "Body" = [System.Text.Encoding]::UTF8.GetBytes(($Body | ConvertTo-Json -Depth 99))
    }
    Invoke-RestMethod @Splat
}
#EndRegion './Public/New-MgShiftSchedulingGroup.ps1' 39
#Region './Public/New-MgShiftTimeOff.ps1' 0
function New-MgShiftTimeOff {
    param (
        [Parameter(Mandatory)][string]$userId,
        [Parameter(Mandatory)][datetime]$startDateTime,
        [Parameter(Mandatory)][datetime]$endDateTime,
        [Parameter(Mandatory)][string]$timeOffReasonId,
        #Id of the Team to get shifts from
        [Parameter(Mandatory)][string]$teamId,
        #Id of the user that the request is sent on the behalf of
        [Parameter(Mandatory)][string]$actAsUID,
        [Parameter(Mandatory)][string]$theme,
        [Parameter(Mandatory)][ValidateSet("draftTimeOff","sharedTimeOff")][string]$timeOffType,
        [string]$notes
    )

    #Convert to "ISO 8601" date format, which is supported in json queries
    $convertedStartDateTime = [Xml.XmlConvert]::ToString($startDateTime,[Xml.XmlDateTimeSerializationMode]::Utc)
    $convertedEndDateTime = [Xml.XmlConvert]::ToString($endDateTime,[Xml.XmlDateTimeSerializationMode]::Utc)

    $Body = @{
        "userId" = $userId
        "$timeOffType" = @{
            "@odata.type" = "microsoft.graph.timeOffItem"
            "timeOffReasonId" = $timeOffReasonId
            "startDateTime" = $convertedStartDateTime
            "endDateTime" = $convertedEndDateTime
            "theme" = $theme
            "notes" = $notes
        }
    }
    
    $splat = @{
        "Method" = "POST"
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule/timesOff"
        "Headers" = @{
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "Content-type" = "application/json"
            "MS-APP-ACTS-AS" = $actAsUID
        }
        "Body" = [System.Text.Encoding]::UTF8.GetBytes(($Body | ConvertTo-Json))
    }
    Invoke-RestMethod @splat
}
#EndRegion './Public/New-MgShiftTimeOff.ps1' 44
#Region './Public/New-MgShiftTimeOffReason.ps1' 0
function New-MgShiftTimeOffReason {
    param (
        #Id of the Team to get shifts from
        [Parameter(Mandatory)][string]$teamId,
        #Id of the user that the request is sent on the behalf of
        [Parameter(Mandatory)][string]$actAsUID,
        [Parameter(Mandatory)][string]$displayName,
        [Parameter(Mandatory)][ValidateSet(
            "none",
            "car",
            "calendar",
            "running",
            "plane",
            "firstAid",
            "doctor",
            "notWorking",
            "clock",
            "juryDuty",
            "globe",
            "cup",
            "phone",
            "weather",
            "umbrella",
            "piggyBank",
            "dog",
            "cake",
            "trafficCone",
            "pin",
            "sunny"
        )][string]$iconType
    )

    $ParameterExclusion = @()
    $Body = $null
    $PSBoundParameters.Keys.ForEach({
        [string]$Key = $_
        $Value = $PSBoundParameters.$key
    
        if ($ParameterExclusion -contains $Key) {
            return
        }
    
        $Body += @{
            $Key = $Value
        }
    })

    $Splat = @{
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule/timeOffReasons"
        "Method" = "POST"
        "Headers" = @{
            "Accept" = "application/json"
            "Content-Type" = "application/json"
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "MS-APP-ACTS-AS" = $actAsUID
        }
        "Body" = [System.Text.Encoding]::UTF8.GetBytes(($Body | ConvertTo-Json -Depth 99))
    }
    Invoke-RestMethod @Splat
}
#EndRegion './Public/New-MgShiftTimeOffReason.ps1' 61
#Region './Public/Remove-MgShift.ps1' 0
function Remove-MgShift {
    param (
        [Parameter(Mandatory)][string]$shiftId,
        #Id of the Team to get shifts from
        [Parameter(Mandatory)][string]$teamId,
        #Id of the user that the request is sent on the behalf of
        [Parameter(Mandatory)][string]$actAsUID
    )

    $splat = @{
        "Method" = "DELETE"
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule/shifts/$shiftId"
        "Headers" = @{
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "Content-type" = "application/json"
            "MS-APP-ACTS-AS" = $actAsUID
        }
    }
    Invoke-RestMethod @splat
}
#EndRegion './Public/Remove-MgShift.ps1' 21
#Region './Public/Remove-MgShiftSchedulingGroup.ps1' 0
function Remove-MgShiftSchedulingGroup {
    param (
        [Parameter(Mandatory)][string]$schedulingGroupId,
        #Id of the Team to get shifts from
        [Parameter(Mandatory)][string]$teamId,
        #Id of the user that the request is sent on the behalf of
        [Parameter(Mandatory)][string]$actAsUID
    )

    $splat = @{
        "Method" = "DELETE"
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule/schedulingGroups/$schedulingGroupId"
        "Headers" = @{
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "Content-type" = "application/json"
            "MS-APP-ACTS-AS" = $actAsUID
        }
    }
    Invoke-RestMethod @splat
}
#EndRegion './Public/Remove-MgShiftSchedulingGroup.ps1' 21
#Region './Public/Remove-MgShiftTimeOff.ps1' 0
function Remove-MgShiftTimeOff {
    param (
        [Parameter(Mandatory)][string]$timeOffId,
        #Id of the Team to get shifts from
        [Parameter(Mandatory)][string]$teamId,
        #Id of the user that the request is sent on the behalf of
        [Parameter(Mandatory)][string]$actAsUID
    )

    $splat = @{
        "Method" = "DELETE"
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule/timesOff/$timeOffId"
        "Headers" = @{
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "Content-type" = "application/json"
            "MS-APP-ACTS-AS" = $actAsUID
        }
    }
    Invoke-RestMethod @splat
}
#EndRegion './Public/Remove-MgShiftTimeOff.ps1' 21
#Region './Public/Remove-MgShiftTimeOffReason.ps1' 0
function Remove-MgShiftTimeOffReason {
    param (
        [Parameter(Mandatory)][string]$timeOffReasonId,
        #Id of the Team to get shifts from
        [Parameter(Mandatory)][string]$teamId,
        #Id of the user that the request is sent on the behalf of
        [Parameter(Mandatory)][string]$actAsUID
    )

    $splat = @{
        "Method" = "DELETE"
        "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule/timeOffReasons/$timeOffReasonId"
        "Headers" = @{
            "Authorization" = "Bearer $(Get-MgAccessToken)"
            "Content-type" = "application/json"
            "MS-APP-ACTS-AS" = $actAsUID
        }
    }
    Invoke-RestMethod @splat
}
#EndRegion './Public/Remove-MgShiftTimeOffReason.ps1' 21
#Region './Public/Send-MgMail.ps1' 0
function Send-MgMail {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)][string]$Identifier,
        [string]$Subject,
        [Parameter(Mandatory,ParameterSetName="Send txt mail")][string]$Content,
        [Parameter(Mandatory,ParameterSetName="Send html mail")][string]$HtmlContent,
        [Parameter(Mandatory)][array]$ToRecipients,
        [array]$CcRecipients,
        [bool]$SaveToSentItems = $true
    )

    begin {
        $ToRecipientsArr = New-Object -TypeName System.Collections.ArrayList
        $CcRecipientsArr = New-Object -TypeName System.Collections.ArrayList
    }

    process {
        #Convert toRecipients
        $ToRecipients.ForEach({
            $null = $ToRecipientsArr.Add(
                @{
                    "emailAddress" = @{
                        "address" = "$_"
                    }
                }
            )
        })
        #Convert ccRecipients
        $CcRecipients.ForEach({
            $null = $CcRecipientsArr.Add(
                @{
                    "emailAddress" = @{
                        "address" = "$_"
                    }
                }
            )
        })

        switch ($PsCmdlet.ParameterSetName) {
            "Send txt mail" {
                $MsgBody = @{
                    "contentType" = "Text"
                    "content" = $Content
                }
            }
            "Send html mail" {
                $MsgBody = @{
                    "contentType" = "HTML"
                    "content" = $HtmlContent
                }
            }
        }

        $Body = @{
            "message" = @{
                "subject" = $Subject
                "body" = $MsgBody
                "toRecipients" = $ToRecipientsArr
                "ccRecipients" = $CcRecipientsArr
            }
            "saveToSentItems" = $SaveToSentItems
        } | ConvertTo-Json -Depth 10

        $Splat = @{
            "Method" = "POST"
            "Uri" = "https://graph.microsoft.com/v1.0/users/$Identifier/sendMail"
            "Headers" = @{
                "Authorization" = "Bearer $(Get-MgAccessToken)"
                "Content-type" = "application/json"
            }
            "Body" = [System.Text.Encoding]::UTF8.GetBytes($Body)
        }
        Invoke-RestMethod @Splat
    }
}
#EndRegion './Public/Send-MgMail.ps1' 77