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 ) 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' 53 #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 } } Invoke-RestMethod @splat } #EndRegion './Public/Get-MgShiftSchedulingGroupList.ps1' 19 #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 { 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(Mandatory)][datetime]$dateFrom, [datetime]$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 = @{ "Method" = "GET" "Uri" = "https://graph.microsoft.com/v1.0/teams/$teamId/schedule/timesOff" "Headers" = @{ "Authorization" = "Bearer $(Get-MgAccessToken)" "MS-APP-ACTS-AS" = $actAsUID } "Body" = @{ '$filter' = "sharedTimeOff/startDateTime ge $convertedDateFrom and sharedTimeOff/endDateTime le $convertedDateTo" } } Invoke-RestMethod @splat } #EndRegion './Public/Get-MgShiftTimeOffList.ps1' 29 #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/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)]$userId, [Parameter(Mandatory)]$startDateTime, [Parameter(Mandatory)]$endDateTime, [Parameter(Mandatory)]$shiftType, [Parameter(Mandatory)]$theme, [Parameter(Mandatory)]$schedulingGroupId, #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, [string]$notes ) #Convert from current TZ to UTC $strCurrentTZ = (Get-CimInstance win32_timezone).StandardName $TZ = [System.TimeZoneInfo]::FindSystemTimeZoneById($strCurrentTZ) $shiftStartDateTime = [System.TimeZoneInfo]::ConvertTimeToUtc($startDateTime, $TZ) $shiftEndDateTime = [System.TimeZoneInfo]::ConvertTimeToUtc($endDateTime, $TZ) #Convert to "ISO 8601" date format, which is supported in json queries $convertedStartDateTime = [Xml.XmlConvert]::ToString($shiftStartDateTime,[Xml.XmlDateTimeSerializationMode]::Utc) $convertedEndDateTime = [Xml.XmlConvert]::ToString($shiftEndDateTime,[Xml.XmlDateTimeSerializationMode]::Utc) $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" = @{ "userId" = $userId "schedulingGroupId" = $schedulingGroupId "sharedShift" = @{ "@odata.type" = "microsoft.graph.shiftItem" "displayName" = $shiftType "notes" = $notes "startDateTime" = $convertedStartDateTime "endDateTime" = $convertedEndDateTime "theme" = $theme } } | ConvertTo-Json } Invoke-RestMethod @splat } #EndRegion './Public/New-MgShift.ps1' 49 #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-MgShiftTimeOff.ps1' 0 function New-MgShiftTimeOff { param ( [Parameter(Mandatory)]$userId, [Parameter(Mandatory)]$startDateTime, [Parameter(Mandatory)]$endDateTime, [Parameter(Mandatory)]$timeOffReasonId, #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, [string]$notes, $theme = "gray" ) #Convert from current TZ to UTC $strCurrentTZ = (Get-CimInstance win32_timezone).StandardName $TZ = [System.TimeZoneInfo]::FindSystemTimeZoneById($strCurrentTZ) $shiftStartDateTime = [System.TimeZoneInfo]::ConvertTimeToUtc($startDateTime, $TZ) $shiftEndDateTime = [System.TimeZoneInfo]::ConvertTimeToUtc($endDateTime, $TZ) #Convert to "ISO 8601" date format, which is supported in json queries $convertedStartDateTime = [Xml.XmlConvert]::ToString($shiftStartDateTime,[Xml.XmlDateTimeSerializationMode]::Utc) $convertedEndDateTime = [Xml.XmlConvert]::ToString($shiftEndDateTime,[Xml.XmlDateTimeSerializationMode]::Utc) $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" = @{ "userId" = $userId "sharedTimeOff" = @{ "@odata.type" = "microsoft.graph.timeOffItem" "timeOffReasonId" = $timeOffReasonId "notes" = $notes "startDateTime" = $convertedStartDateTime "endDateTime" = $convertedEndDateTime "theme" = $theme } } | ConvertTo-Json } Invoke-RestMethod @splat } #EndRegion './Public/New-MgShiftTimeOff.ps1' 47 #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 |