NN.MSGraph.psm1
#Region './Private/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 './Private/Get-MgAccessToken.ps1' 23 #Region './Private/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 './Private/Get-MgSecret.ps1' 24 #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-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 { 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/shifts" "Headers" = @{ "Authorization" = "Bearer $(Get-MgAccessToken)" "MS-APP-ACTS-AS" = $actAsUID } "Body" = @{ '$filter' = "sharedShift/startDateTime ge $convertedDateFrom and sharedShift/endDateTime le $convertedDateTo" } } Invoke-RestMethod @splat } #EndRegion './Public/Get-MgShiftList.ps1' 29 #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)]$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 $requiredModules = @("Az.Accounts","Az.Resources") $requiredModules.ForEach({ if (Get-InstalledModule $_) { Import-Module $_ -Force } else { Install-Module $_ -Force } }) #Connect to the Azure account $null = Connect-AzAccount #Create a new secret $result = New-AzADAppCredential -ObjectId $objectId -CustomKeyIdentifier $CustomKeyIdentifier #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' 42 #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-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 } } } $Splat = @{ "Method" = "POST" "Uri" = "https://graph.microsoft.com/v1.0/users/$Identifier/sendMail" "Headers" = @{ "Authorization" = "Bearer $(Get-MgAccessToken)" "Content-type" = "application/json" } "Body" = @{ "message" = @{ "subject" = $Subject "body" = $MsgBody "toRecipients" = $ToRecipientsArr "ccRecipients" = $CcRecipientsArr } "saveToSentItems" = $SaveToSentItems } | ConvertTo-Json -Depth 10 } Invoke-RestMethod @Splat } } #EndRegion './Public/Send-MgMail.ps1' 75 |