3.5.0
This commit is contained in:
@@ -20,11 +20,13 @@ $global:documentationProviders = @()
|
||||
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'1.1.0'
|
||||
'1.2.0'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
{
|
||||
$script:alwaysUseMigTableForTranslation = $false
|
||||
|
||||
# Make sure we add the default Output types
|
||||
Add-OutputType
|
||||
|
||||
@@ -43,14 +45,20 @@ function Invoke-InitializeModule
|
||||
Schedule="ScheduledAction.List.schedule"
|
||||
MessageTemplate="ScheduledAction.Notification.messageTemplate"
|
||||
EmailCC="ScheduledAction.Notification.additionalRecipients"
|
||||
Filter="AssignmentFilters.assignmentFilterColumnHeader"
|
||||
Rule="ApplicabilityRules.GridLabel.Rule"
|
||||
ValueWithLabel="TableHeaders.value"
|
||||
Status="TableHeaders.status"
|
||||
CombinedValueWithLabel="TableHeaders.value"
|
||||
CombinedValue="TableHeaders.value"
|
||||
useDeviceLicensing="TableHeaders.licenseType"
|
||||
#filterMode="Filter mode" # Not in any string file yet
|
||||
Filter="AppResources.AppSettingsUx.assignmentFilterColumnHeader"
|
||||
filterMode="AppResources.AppSettingsUx.assignmentFilterTypeColumnHeader"
|
||||
deliveryOptimizationPriority="AppResources.AppSettingsUx.deliveryOptimizationPriorityHeader"
|
||||
startTimeColumnLabel="AppResources.AppSettingsUx.startTimeColumnLabel"
|
||||
installTimeSettings="AppResources.AppSettingsUx.deadlineTimeColumnLabel"
|
||||
restartSettings="AppResources.AppSettingsUx.restartGracePeriodHeader"
|
||||
notifications="AppResources.AppSettingsUx.assignmentToast"
|
||||
Settings="TableHeaders.settings"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +207,7 @@ function Get-ObjectDocumentation
|
||||
$status = $null
|
||||
$inputType = "Settings"
|
||||
|
||||
if(-not $script:scopeTags)
|
||||
if(-not $script:scopeTags -and $script:offlineDocumentation -ne $true)
|
||||
{
|
||||
$script:scopeTags = (Invoke-GraphRequest -Url "/deviceManagement/roleScopeTags").Value
|
||||
}
|
||||
@@ -209,7 +217,7 @@ function Get-ObjectDocumentation
|
||||
$script:currentObject = $obj
|
||||
|
||||
$script:languageStrings = $null
|
||||
|
||||
|
||||
$script:CurrentSubCategory = $null
|
||||
$script:objectBasicInfo = @()
|
||||
$script:objectSettingsData = @()
|
||||
@@ -587,19 +595,68 @@ function Add-BasicAdditionalValues
|
||||
|
||||
if($obj.createdDateTime)
|
||||
{
|
||||
$tmpDate = ([DateTime]::Parse($obj.createdDateTime))
|
||||
Add-BasicPropertyValue (Get-LanguageString "Inputs.createdDateTime") "$($tmpDate.ToLongDateString()) $($tmpDate.ToLongTimeString())"
|
||||
try
|
||||
{
|
||||
if($obj.createdDateTime -is [DateTime])
|
||||
{
|
||||
$tmpDate = $obj.createdDateTime
|
||||
}
|
||||
else
|
||||
{
|
||||
$tmpDate = ([DateTime]::Parse($obj.createdDateTime))
|
||||
}
|
||||
$tmpDateStr = "$($tmpDate.ToLongDateString()) $($tmpDate.ToLongTimeString())"
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Log "Failed to parse date from $($obj.createdDateTime) (Object type: $($obj.createdDateTime.GetType().Name))" 2
|
||||
$tmpDateStr = $obj.createdDateTime
|
||||
}
|
||||
Add-BasicPropertyValue (Get-LanguageString "Inputs.createdDateTime") $tmpDateStr
|
||||
}
|
||||
|
||||
if($obj.lastModifiedDateTime)
|
||||
{
|
||||
$tmpDate = ([DateTime]::Parse($obj.lastModifiedDateTime))
|
||||
Add-BasicPropertyValue (Get-LanguageString "TableHeaders.lastModified") "$($tmpDate.ToLongDateString()) $($tmpDate.ToLongTimeString())"
|
||||
try
|
||||
{
|
||||
if($obj.lastModifiedDateTime -is [DateTime])
|
||||
{
|
||||
$tmpDate = $obj.lastModifiedDateTime
|
||||
}
|
||||
else
|
||||
{
|
||||
$tmpDate = ([DateTime]::Parse($obj.lastModifiedDateTime))
|
||||
}
|
||||
$tmpDateStr = "$($tmpDate.ToLongDateString()) $($tmpDate.ToLongTimeString())"
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Log "Failed to parse date from $($obj.lastModifiedDateTime) (Object type: $($obj.lastModifiedDateTime.GetType().Name))" 2
|
||||
$tmpDateStr = $obj.lastModifiedDateTime
|
||||
}
|
||||
Add-BasicPropertyValue (Get-LanguageString "TableHeaders.lastModified") $tmpDateStr
|
||||
}
|
||||
elseif($obj.modifiedDateTime)
|
||||
{
|
||||
$tmpDate = ([DateTime]::Parse($obj.modifiedDateTime))
|
||||
Add-BasicPropertyValue (Get-LanguageString "TableHeaders.lastModified") "$($tmpDate.ToLongDateString()) $($tmpDate.ToLongTimeString())"
|
||||
try
|
||||
{
|
||||
if($obj.modifiedDateTime -is [DateTime])
|
||||
{
|
||||
$tmpDate = $obj.modifiedDateTime
|
||||
}
|
||||
else
|
||||
{
|
||||
$tmpDate = ([DateTime]::Parse($obj.modifiedDateTime))
|
||||
}
|
||||
$tmpDateStr = "$($tmpDate.ToLongDateString()) $($tmpDate.ToLongTimeString())"
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Log "Failed to parse date from $($obj.modifiedDateTime) (Object type: $($obj.modifiedDateTime.GetType().Name))" 2
|
||||
$tmpDateStr = $obj.modifiedDateTime
|
||||
}
|
||||
Add-BasicPropertyValue (Get-LanguageString "TableHeaders.lastModified") $tmpDateStr
|
||||
}
|
||||
|
||||
if($obj.version)
|
||||
@@ -1829,7 +1886,11 @@ function Invoke-TranslateSection
|
||||
$useParentProp = $true
|
||||
# Use $script:currentObject since $obj could be a property on the original object
|
||||
# Cert links are always specified on the main object
|
||||
$cert = Invoke-GraphRequest -URL $script:currentObject."$($prop.entityKey)@odata.navigationLink" -ODataMetadata "minimal" -NoError
|
||||
$cert = $null
|
||||
if($script:offlineDocumentation -ne $true)
|
||||
{
|
||||
$cert = Invoke-GraphRequest -URL $script:currentObject."$($prop.entityKey)@odata.navigationLink" -ODataMetadata "minimal" -NoError
|
||||
}
|
||||
if($cert)
|
||||
{
|
||||
if($cert.value -is [Object[]])
|
||||
@@ -1849,7 +1910,22 @@ function Invoke-TranslateSection
|
||||
}
|
||||
elseif($script:currentObject.'@ObjectFromFile' -eq $true)
|
||||
{
|
||||
$value = "##TBD - Linked Certificate"
|
||||
if($script:currentObject."#CustomRef_$($prop.entityKey)")
|
||||
{
|
||||
$idx = $script:currentObject."#CustomRef_$($prop.entityKey)".IndexOf("|:|")
|
||||
if($idx -gt -1)
|
||||
{
|
||||
$value = $script:currentObject."#CustomRef_$($prop.entityKey)".SubString(0,$idx)
|
||||
}
|
||||
else
|
||||
{
|
||||
$value = $script:currentObject."#CustomRef_$($prop.entityKey)"
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$value = "##TBD - Linked Certificate"
|
||||
}
|
||||
$rawValue = $value
|
||||
}
|
||||
}
|
||||
@@ -2242,6 +2318,17 @@ function Get-CustomChildObject
|
||||
return $obj
|
||||
}
|
||||
|
||||
function Invoke-InitDocumentation
|
||||
{
|
||||
foreach($docProvider in ($global:documentationProviders | Sort -Property Priority))
|
||||
{
|
||||
if($docProvider.InitializeDocumentation)
|
||||
{
|
||||
& $docProvider.InitializeDocumentation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Add-CustomProfileProperties
|
||||
{
|
||||
param($obj)
|
||||
@@ -2900,7 +2987,7 @@ function Invoke-TranslateAssignments
|
||||
|
||||
$groupInfo = $null
|
||||
|
||||
if($groupIds.Count -gt 0)
|
||||
if($groupIds.Count -gt 0 -and $script:offlineDocumentation -ne $true)
|
||||
{
|
||||
$ht = @{}
|
||||
$ht.Add("ids", @($groupIds | Unique))
|
||||
@@ -2913,26 +3000,40 @@ function Invoke-TranslateAssignments
|
||||
if(($null -eq $groupInfo -or ($groupInfo | measure).Count -eq 0) -and $obj."@ObjectFromFile" -eq $true -and $script:migTable)
|
||||
{
|
||||
### Get group info from mig table when documenting from file if there's no access to the environment
|
||||
$groupInfo = $script:migTable.Objects | Where Type -eq "Group"
|
||||
$groupInfo = $script:migTable.Objects | Where Type -eq "Group"
|
||||
}
|
||||
|
||||
if($filterIds.Count -gt 0)
|
||||
{
|
||||
$batchInfo = @{}
|
||||
$requests = @()
|
||||
#{"requests":[{"id":"<FilterID>","method":"GET","url":"deviceManagement/assignmentFilters/<FilterID>?$select=displayName"}]}
|
||||
foreach($filterId in $filterIds)
|
||||
{
|
||||
if($script:offlineDocumentation -eq $true)
|
||||
{
|
||||
$requests += [PSCustomObject]@{
|
||||
id = $filterIds
|
||||
method = "GET"
|
||||
"url" = "deviceManagement/assignmentFilters/$($filterId)?`$select=displayName"
|
||||
if($script:offlineObjects["AssignmentFilters"])
|
||||
{
|
||||
$filtersInfo = $script:offlineObjects["AssignmentFilters"] | Where { $_.Id -in $filterIds }
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Log "No assignment filters loaded for Offline documentation. Check export folder" 2
|
||||
}
|
||||
}
|
||||
$batchInfo = @{"requests"=$requests}
|
||||
$jsonBody = $batchInfo | ConvertTo-Json
|
||||
else
|
||||
{
|
||||
$batchInfo = @{}
|
||||
$requests = @()
|
||||
#{"requests":[{"id":"<FilterID>","method":"GET","url":"deviceManagement/assignmentFilters/<FilterID>?$select=displayName"}]}
|
||||
foreach($filterId in $filterIds)
|
||||
{
|
||||
$requests += [PSCustomObject]@{
|
||||
id = $filterId
|
||||
method = "GET"
|
||||
"url" = "deviceManagement/assignmentFilters/$($filterId)?`$select=displayName"
|
||||
}
|
||||
}
|
||||
$batchInfo = @{"requests"=$requests}
|
||||
$jsonBody = $batchInfo | ConvertTo-Json
|
||||
|
||||
$filtersInfo = Invoke-GraphRequest -Url "/`$batch" -Content $jsonBody -Method "Post"
|
||||
$filtersInfo = (Invoke-GraphRequest -Url "/`$batch" -Content $jsonBody -Method "Post").responses.body
|
||||
}
|
||||
}
|
||||
|
||||
foreach($assignment in $obj.assignments)
|
||||
@@ -2987,12 +3088,12 @@ function Invoke-TranslateAssignments
|
||||
$filterName = $noFilter
|
||||
$filterMode = $noFilter
|
||||
|
||||
if($assignment.target.deviceAndAppManagementAssignmentFilterId -and $filtersInfo.responses)
|
||||
if($assignment.target.deviceAndAppManagementAssignmentFilterId -and $filtersInfo)
|
||||
{
|
||||
$filtersObj = $filtersInfo.responses | Where Id -eq $assignment.target.deviceAndAppManagementAssignmentFilterId
|
||||
if($filtersObj.body.displayName)
|
||||
$filtersObj = $filtersInfo | Where Id -eq $assignment.target.deviceAndAppManagementAssignmentFilterId
|
||||
if($filtersObj.displayName)
|
||||
{
|
||||
$filterName = $filtersObj.body.displayName
|
||||
$filterName = $filtersObj.displayName
|
||||
}
|
||||
|
||||
if($assignment.target.deviceAndAppManagementAssignmentFilterType -eq "include")
|
||||
@@ -3037,6 +3138,66 @@ function Invoke-TranslateAssignments
|
||||
$value = Get-LanguageString "SettingDetails.licenseTypeUser"
|
||||
}
|
||||
}
|
||||
elseif($settingProp -eq "restartSettings" -and $null -eq $assignment.settings.$settingProp)
|
||||
{
|
||||
$value = Get-LanguageString "SettingDetails.disabledOption"
|
||||
}
|
||||
elseif($settingProp -eq "notifications")
|
||||
{
|
||||
$value = ?? (Get-LanguageString "AppResources.AssignmentToast.$($assignment.settings.$settingProp)") $assignment.settings.$settingProp
|
||||
}
|
||||
elseif($settingProp -eq "installTimeSettings")
|
||||
{
|
||||
$asap = Get-LanguageString "Assignment.SoftwareInstallationTime.defaultTime"
|
||||
$startValue = $asap
|
||||
$value = $asap
|
||||
|
||||
if($assignment.settings.installTimeSettings)
|
||||
{
|
||||
if($assignment.settings.installTimeSettings.startDateTime)
|
||||
{
|
||||
$instTime = Get-Date $assignment.settings.installTimeSettings.startDateTime
|
||||
|
||||
if($assignment.settings.installTimeSettings.useLocalTime -eq $false)
|
||||
{
|
||||
$hours = ($instTime.ToUniversalTime() - $instTime).Hours
|
||||
$instTime = $instTime.AddHours($hours)
|
||||
}
|
||||
$startValue = "$($instTime.ToShortDateString()) $($instTime.ToShortTimeString())"
|
||||
}
|
||||
|
||||
if($assignment.settings.installTimeSettings.deadlineDateTime)
|
||||
{
|
||||
$endTime = Get-Date $assignment.settings.installTimeSettings.deadlineDateTime
|
||||
|
||||
if($assignment.settings.installTimeSettings.useLocalTime -eq $false)
|
||||
{
|
||||
$hours = ($endTime.ToUniversalTime() - $endTime).Hours
|
||||
$endTime = $endTime.AddHours($hours)
|
||||
}
|
||||
$value = "$($instTime.ToShortDateString()) $($instTime.ToShortTimeString())"
|
||||
}
|
||||
}
|
||||
|
||||
$assignmentSettingProps.Add("startTimeColumnLabel", $startValue)
|
||||
}
|
||||
elseif($settingProp -eq "deliveryOptimizationPriority")
|
||||
{
|
||||
$tmpStr = Get-LanguageString "AppResources.DeliveryOptimizationPriority.displayText"
|
||||
if($assignment.settings.$settingProp -ne "foreground")
|
||||
{
|
||||
$tmpType = Get-LanguageString "AppResources.DeliveryOptimizationPriority.backgroundNormal"
|
||||
}
|
||||
else
|
||||
{
|
||||
$tmpType = Get-LanguageString "AppResources.DeliveryOptimizationPriority.foreground"
|
||||
}
|
||||
$value = $tmpStr -f $tmpType
|
||||
}
|
||||
elseif($assignment.settings.$settingProp -eq "notConfigured")
|
||||
{
|
||||
$value = Get-LanguageString "BooleanActions.notConfigured"
|
||||
}
|
||||
else
|
||||
{
|
||||
$value = $assignment.settings.$settingProp
|
||||
@@ -3389,6 +3550,9 @@ function Show-DocumentationForm
|
||||
|
||||
$txtDocumentationRawData.Text = ""
|
||||
|
||||
$script:offlineDocumentation = $false
|
||||
$script:offlineObjects = @{}
|
||||
|
||||
$loadExportedInfo = $true
|
||||
$script:migTable = $null
|
||||
$script:scopeTags = $null
|
||||
@@ -3421,6 +3585,8 @@ function Show-DocumentationForm
|
||||
|
||||
Get-CustomIgnoredCategories $obj
|
||||
|
||||
Invoke-InitDocumentation
|
||||
|
||||
if($global:grdDocumentObjects.Tag -eq "Objects")
|
||||
{
|
||||
$sourceList = @()
|
||||
@@ -3532,21 +3698,20 @@ function Show-DocumentationForm
|
||||
$script:migTable = ConvertFrom-Json (Get-Content $migFileName -Raw)
|
||||
}
|
||||
|
||||
$scopeTagObjectType = $global:currentViewObject.ViewItems | Where Id -eq "ScopeTags"
|
||||
|
||||
if($scopeTagObjectType)
|
||||
if($script:migTable.TenantId -and $script:migTable.TenantId -ne $global:organization.id)
|
||||
{
|
||||
$scopePath = [IO.Path]::Combine($diSource.FullName,$scopeTagObjectType.Id)
|
||||
if([IO.Directory]::Exists($scopePath) -eq $false)
|
||||
$script:offlineDocumentation = $true
|
||||
}
|
||||
|
||||
if($script:offlineDocumentation -eq $true)
|
||||
{
|
||||
Add-DocOfflineDependecies "ScopeTags" $diSource.FullName
|
||||
Add-DocOfflineDependecies "AssignmentFilters" $diSource.FullName
|
||||
Add-DocOfflineObjectTypeDependecies $diSource.FullName
|
||||
if($script:offlineObjects.ContainsKey("ScopeTags"))
|
||||
{
|
||||
Write-Log "Object path for Scope (Tags) ($($scopePath)) not found" 2
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
$scopeTagObjects = Get-GraphFileObjects $scopePath -ObjectType $scopeTagObjectType
|
||||
$script:scopeTags = @(($scopeTagObjects | Select Object))
|
||||
}
|
||||
$script:scopeTags = @($script:offlineObjects["ScopeTags"])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3723,7 +3888,7 @@ function Show-DocumentationForm
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($allObjectTypeObjects.Count -gt 0)
|
||||
@@ -3745,7 +3910,13 @@ function Show-DocumentationForm
|
||||
Write-Status "Run PostProcess for $($global:cbDocumentationType.SelectedItem.Name)"
|
||||
& $global:cbDocumentationType.SelectedItem.PostProcess
|
||||
}
|
||||
|
||||
|
||||
if($script:offlineDocumentation -eq $true)
|
||||
{
|
||||
# Clear the dependecy objects loaded for Offline documentation
|
||||
$global:LoadedDependencyObjects = $null
|
||||
}
|
||||
$script:offlineDocumentation = $false
|
||||
Write-Status ""
|
||||
}
|
||||
|
||||
@@ -3797,6 +3968,18 @@ function Show-DocumentationForm
|
||||
Show-ModalForm "Intune Documentation" $script:docForm -HideButtons
|
||||
}
|
||||
|
||||
function Get-DocOfflineObjects
|
||||
{
|
||||
param($objectName)
|
||||
|
||||
if($script:offlineDocumentation -eq $false) { return }
|
||||
|
||||
if($script:offlineObjects.ContainsKey($objectName))
|
||||
{
|
||||
$script:offlineObjects[$objectName]
|
||||
}
|
||||
}
|
||||
|
||||
function Set-OutputOptionsTabStatus
|
||||
{
|
||||
param($control)
|
||||
@@ -3828,6 +4011,42 @@ function Invoke-DocumentSelectedObjects
|
||||
Show-DocumentationForm -objects $script:selectedObjects -SelectedDocuments
|
||||
}
|
||||
|
||||
function Add-DocOfflineObjectTypeDependecies
|
||||
{
|
||||
param($fromFolder)
|
||||
|
||||
foreacH($viewItem in $global:currentViewObject.ViewItems)
|
||||
{
|
||||
foreach($dep in $viewItem.Dependencies)
|
||||
{
|
||||
Add-DocOfflineDependecies $dep $fromFolder
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Add-DocOfflineDependecies
|
||||
{
|
||||
param($objectTypeName, $fromFolder)
|
||||
|
||||
if($script:offlineObjects.ContainsKey($objectTypeName)) { return }
|
||||
|
||||
$tmpObjType = $global:currentViewObject.ViewItems | Where Id -eq $objectTypeName
|
||||
|
||||
if($tmpObjType)
|
||||
{
|
||||
$objPath = [IO.Path]::Combine($fromFolder,$tmpObjType.Id)
|
||||
if([IO.Directory]::Exists($objPath) -eq $false)
|
||||
{
|
||||
Write-Log "Object path for $($tmpObjType.Title) ($($objPath)) not found" 2
|
||||
}
|
||||
else
|
||||
{
|
||||
$tmpObjects = Get-GraphFileObjects $objPath -ObjectType $tmpObjType
|
||||
$script:offlineObjects.Add($tmpObjType.Id, @(($tmpObjects | Select Object).Object))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Add-DocumentationObjects
|
||||
{
|
||||
param($objects)
|
||||
|
||||
@@ -10,7 +10,7 @@ This module will also document some objects based on PowerShell functions
|
||||
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'1.1.0'
|
||||
'1.2.0'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
@@ -18,6 +18,7 @@ function Invoke-InitializeModule
|
||||
Add-DocumentationProvicer ([PSCustomObject]@{
|
||||
Name="Custom"
|
||||
Priority = 1000 # The priority of the Provider. Lower number has higher priority.
|
||||
InitializeDocumentation = { Initialize-CDDocumentation @args }
|
||||
DocumentObject = { Invoke-CDDocumentObject @args }
|
||||
GetCustomProfileValue = { Add-CDDocumentCustomProfileValue @args }
|
||||
GetCustomChildObject = { Get-CDDocumentCustomChildObjet @args }
|
||||
@@ -27,6 +28,12 @@ function Invoke-InitializeModule
|
||||
})
|
||||
}
|
||||
|
||||
function Initialize-CDDocumentation
|
||||
{
|
||||
$script:allTenantApps = $null
|
||||
$script:allTermsOfUse = $null
|
||||
}
|
||||
|
||||
function Invoke-CDDocumentObject
|
||||
{
|
||||
param($documentationObj)
|
||||
@@ -42,6 +49,13 @@ function Invoke-CDDocumentObject
|
||||
Properties = @("Name","Value","Category","SubCategory") #,"RawValue","Description"
|
||||
}
|
||||
}
|
||||
elseif($type -eq '#microsoft.graph.agreement')
|
||||
{
|
||||
Invoke-CDDocumentTermsOfUse $documentationObj
|
||||
return [PSCustomObject]@{
|
||||
Properties = @("Name","Value") #,"RawValue","Description"
|
||||
}
|
||||
}
|
||||
elseif($type -eq '#microsoft.graph.countryNamedLocation')
|
||||
{
|
||||
Invoke-CDDocumentCountryNamedLocation $documentationObj
|
||||
@@ -116,7 +130,7 @@ function Get-CDAllCloudApps
|
||||
{
|
||||
if(-not $script:allCloudApps)
|
||||
{
|
||||
$script:allCloudApps =(Invoke-GraphRequest -url "/servicePrincipals?`$select=displayName,appId&top=999" -ODataMetadata "minimal").value
|
||||
$script:allCloudApps = (Invoke-GraphRequest -url "/servicePrincipals?`$select=displayName,appId&top=999" -ODataMetadata "minimal").value
|
||||
}
|
||||
$script:allCloudApps
|
||||
}
|
||||
@@ -125,7 +139,11 @@ function Get-CDAllTenantApps
|
||||
{
|
||||
if(-not $script:allTenantApps)
|
||||
{
|
||||
$script:allTenantApps =(Invoke-GraphRequest -url "/deviceAppManagement/mobileApps?`$select=displayName,id&top=999" -ODataMetadata "minimal").value
|
||||
$script:allTenantApps = Get-DocOfflineObjects "Applications"
|
||||
if(-not $script:allTenantApps)
|
||||
{
|
||||
$script:allTenantApps =(Invoke-GraphRequest -url "/deviceAppManagement/mobileApps?`$select=displayName,id&top=999" -ODataMetadata "minimal").value
|
||||
}
|
||||
}
|
||||
$script:allTenantApps
|
||||
}
|
||||
@@ -750,13 +768,26 @@ function Add-CDDocumentCustomProfileProperty
|
||||
{
|
||||
if($obj.authenticationMethod -ne "derivedCredential")
|
||||
{
|
||||
$idCert = Invoke-GraphRequest -URL $obj."identityCertificateForClientAuthentication@odata.navigationLink" -ODataMetadata "minimal" -NoError
|
||||
if($obj."#CustomRef_identityCertificateForClientAuthentication" -and $obj.'@ObjectFromFile' -eq $true)
|
||||
{
|
||||
$idCert = $obj."#CustomRef_identityCertificateForClientAuthentication"
|
||||
$idx = $idCert.IndexOf("|:|")
|
||||
if($idx -gt -1)
|
||||
{
|
||||
$idCertType = $idCert.SubString($idx + 3)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$idCert = Invoke-GraphRequest -URL $obj."identityCertificateForClientAuthentication@odata.navigationLink" -ODataMetadata "minimal" -NoError
|
||||
$idCertType = $idCert.'@OData.Type'
|
||||
}
|
||||
|
||||
if($idCert.'@OData.Type' -like "*Pkcs*")
|
||||
if($idCertType -like "*Pkcs*")
|
||||
{
|
||||
$clientCertType = "PKCS certificate"
|
||||
}
|
||||
elseif($idCert.'@OData.Type' -like "*SCEP*")
|
||||
elseif($idCertType -like "*SCEP*")
|
||||
{
|
||||
$clientCertType = "SCEP certificate"
|
||||
}
|
||||
@@ -1102,6 +1133,7 @@ function Add-CDDocumentCustomProfileProperty
|
||||
$supersededApps = @()
|
||||
if($obj.dependentAppCount -gt 0 -or $obj.supersededAppCount -gt 0)
|
||||
{
|
||||
# ToDo: Add support for Offline documentation
|
||||
$relationships = (Invoke-GraphRequest -Url "/deviceAppManagement/mobileApps/$($obj.Id)/relationships?`$filter=targetType%20eq%20microsoft.graph.mobileAppRelationshipType%27child%27").value
|
||||
foreach($rel in $relationships)
|
||||
{
|
||||
@@ -1187,6 +1219,11 @@ function Add-CDDocumentCustomProfileProperty
|
||||
}
|
||||
|
||||
}
|
||||
elseif($obj.'@OData.Type' -eq "#microsoft.graph.windows10TeamGeneralConfiguration")
|
||||
{
|
||||
$obj | Add-Member Noteproperty -Name "syntheticAzureOperationalInsightsEnabled" -Value ($obj.azureOperationalInsightsBlockTelemetry -eq $false)
|
||||
$obj | Add-Member Noteproperty -Name "syntheticMaintenanceWindowEnabled" -Value ($obj.maintenanceWindowBlocked -eq $false)
|
||||
}
|
||||
|
||||
if(($obj.PSObject.Properties | where Name -eq "securityRequireSafetyNetAttestationBasicIntegrity") -and
|
||||
($obj.PSObject.Properties | where Name -eq "securityRequireSafetyNetAttestationCertifiedDevice"))
|
||||
@@ -1478,7 +1515,7 @@ function Invoke-CDDocumentCountryNamedLocation
|
||||
$countryList = @()
|
||||
foreach($country in $obj.countriesAndRegions)
|
||||
{
|
||||
$countryList += Get-LanguageString "Countries.$($country.ToLower())"
|
||||
$countryList += Get-LanguageString "AzureIAMCommon.CountryNames.countryName$($country.ToLower())"
|
||||
}
|
||||
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
@@ -1525,6 +1562,117 @@ function Invoke-CDDocumentIPNamedLocation
|
||||
})
|
||||
}
|
||||
|
||||
# Document Terms of Use
|
||||
function Invoke-CDDocumentTermsOfUse
|
||||
{
|
||||
param($documentationObj)
|
||||
|
||||
$obj = $documentationObj.Object
|
||||
$objectType = $documentationObj.ObjectType
|
||||
|
||||
$script:objectSeparator = ?? $global:cbDocumentationObjectSeparator.SelectedValue ([System.Environment]::NewLine)
|
||||
$script:propertySeparator = ?? $global:cbDocumentationPropertySeparator.SelectedValue ","
|
||||
|
||||
$offLabel = Get-LanguageString "SettingDetails.offOption"
|
||||
$onLabel = Get-LanguageString "SettingDetails.onOption"
|
||||
|
||||
###################################################
|
||||
# Basic info
|
||||
###################################################
|
||||
|
||||
Add-BasicPropertyValue (Get-LanguageString "SettingDetails.nameName") $obj.displayName
|
||||
Add-BasicPropertyValue (Get-LanguageString "TableHeaders.configurationType") (Get-LanguageString "AzureIAM.menuItemTermsOfUse")
|
||||
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "TermsOfUse.Wizard.agreementIsViewingBeforeAcceptanceRequiredLabel"
|
||||
Value = ?: $obj.isViewingBeforeAcceptanceRequired $onLabel $offLabel
|
||||
Category = $null
|
||||
SubCategory = $null
|
||||
EntityKey = "isViewingBeforeAcceptanceRequired"
|
||||
})
|
||||
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "TermsOfUse.Wizard.agreementIsPerDeviceAcceptanceRequiredLabel"
|
||||
Value = ?: $obj.isPerDeviceAcceptanceRequired $onLabel $offLabel
|
||||
Category = $null
|
||||
SubCategory = $null
|
||||
EntityKey = "isPerDeviceAcceptanceRequired"
|
||||
})
|
||||
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "TermsOfUse.Wizard.isAcceptanceExpirationEnabledLabel"
|
||||
Value = ?: $obj.termsExpiration $onLabel $offLabel
|
||||
Category = $null
|
||||
SubCategory = $null
|
||||
EntityKey = "isAcceptanceExpirationEnabledLabel"
|
||||
})
|
||||
|
||||
if($obj.termsExpiration.startDateTime)
|
||||
{
|
||||
try
|
||||
{
|
||||
if($obj.termsExpiration.startDateTime -is [DateTime])
|
||||
{
|
||||
$tmpDate = $obj.termsExpiration.startDateTime
|
||||
}
|
||||
else
|
||||
{
|
||||
$tmpDate = ([DateTime]::Parse($obj.termsExpiration.startDateTime))
|
||||
}
|
||||
$tmpDateStr = ($tmpDate).ToShortDateString()
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Log "Failed to parse date from string $($obj.termsExpiration.startDateTime)" 2
|
||||
$tmpDateStr = $obj.termsExpiration.startDateTime
|
||||
}
|
||||
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "TermsOfUse.Wizard.acceptanceExpirationStartDateTimeLabel"
|
||||
Value = $tmpDateStr
|
||||
Category = $null
|
||||
SubCategory = $null
|
||||
EntityKey = "startDateTime"
|
||||
})
|
||||
|
||||
if($obj.termsExpiration.frequency -eq "P365D")
|
||||
{
|
||||
$value = Get-LanguageString "TermsOfUse.AcceptanceExpirationFrequency.annually"
|
||||
}
|
||||
elseif($obj.termsExpiration.frequency -eq "P180D")
|
||||
{
|
||||
$value = Get-LanguageString "TermsOfUse.AcceptanceExpirationFrequency.biannually"
|
||||
}
|
||||
elseif($obj.termsExpiration.frequency -eq "P30D")
|
||||
{
|
||||
$value = Get-LanguageString "TermsOfUse.AcceptanceExpirationFrequency.monthly"
|
||||
}
|
||||
elseif($obj.termsExpiration.frequency -eq "P90D")
|
||||
{
|
||||
$value = Get-LanguageString "TermsOfUse.AcceptanceExpirationFrequency.quarterly"
|
||||
}
|
||||
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "TermsOfUse.Wizard.acceptanceExpirationFrequencyLabel"
|
||||
Value = $value
|
||||
Category = $null
|
||||
SubCategory = $null
|
||||
EntityKey = "frequency"
|
||||
})
|
||||
}
|
||||
if($null -ne $obj.userReacceptRequiredFrequency)
|
||||
{
|
||||
$days = Get-DurationValue $obj.userReacceptRequiredFrequency
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "TermsOfUse.Wizard.acceptanceDurationLabel"
|
||||
Value = $days
|
||||
Category = $null
|
||||
SubCategory = $null
|
||||
EntityKey = "userReacceptRequiredFrequency"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
# Document Conditional Access policy
|
||||
function Invoke-CDDocumentConditionalAccess
|
||||
{
|
||||
@@ -1540,7 +1688,9 @@ function Invoke-CDDocumentConditionalAccess
|
||||
# Basic info
|
||||
###################################################
|
||||
|
||||
Add-BasicDefaultValues $obj $objectType
|
||||
#Add-BasicDefaultValues $obj $objectType
|
||||
Add-BasicPropertyValue (Get-LanguageString "SettingDetails.nameName") $obj.displayName
|
||||
Add-BasicPropertyValue (Get-LanguageString "TableHeaders.configurationType") (Get-LanguageString "AzureIAM.conditionalAccessBladeTitle")
|
||||
|
||||
if($obj.state -eq "enabledForReportingButNotEnforced")
|
||||
{
|
||||
@@ -1590,6 +1740,7 @@ function Invoke-CDDocumentConditionalAccess
|
||||
|
||||
$body = $ht | ConvertTo-Json
|
||||
|
||||
# ToDo: Get from MigFile for Offline
|
||||
$idInfo = (Invoke-GraphRequest -Url "/directoryObjects/getByIds?`$select=displayName,id" -Content $body -Method "Post").Value
|
||||
}
|
||||
|
||||
@@ -1719,6 +1870,7 @@ function Invoke-CDDocumentConditionalAccess
|
||||
$idObj = $idInfo | Where Id -eq $id
|
||||
$tmpObjs += ?? $idObj.displayName $id
|
||||
}
|
||||
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = $category
|
||||
Value = $tmpObjs -join $script:objectSeparator
|
||||
@@ -1916,8 +2068,12 @@ function Invoke-CDDocumentConditionalAccess
|
||||
|
||||
if(-not $script:allNamedLocations -and ($obj.conditions.locations.includeLocations.Count -gt 0 -or $obj.conditions.locations.excludeLocations.Count))
|
||||
{
|
||||
# Might be better to get them one by one
|
||||
$script:allNamedLocations = (Invoke-GraphRequest -url "/identity/conditionalAccess/namedLocations?`$select=displayName,Id&top=999" -ODataMetadata "minimal").value
|
||||
$script:allNamedLocations = Get-DocOfflineObjects "NamedLocations"
|
||||
if(-not $script:allNamedLocations)
|
||||
{
|
||||
# Might be better to get them one by one
|
||||
$script:allNamedLocations = (Invoke-GraphRequest -url "/identity/conditionalAccess/namedLocations?`$select=displayName,Id&top=999" -ODataMetadata "minimal").value
|
||||
}
|
||||
if(-not $script:allNamedLocations) { $script:allNamedLocations = @()}
|
||||
elseif($script:allNamedLocations -isnot [Object[]]) { $script:allNamedLocations = @($script:allNamedLocations) }
|
||||
|
||||
@@ -1927,6 +2083,17 @@ function Invoke-CDDocumentConditionalAccess
|
||||
}
|
||||
}
|
||||
|
||||
if(-not $script:allTermsOfUse -and (($obj.grantControls.termsOfUse | measure).Count -gt 0))
|
||||
{
|
||||
$script:allTermsOfUse = Get-DocOfflineObjects "TermsOfUse"
|
||||
if(-not $script:allTermsOfUse)
|
||||
{
|
||||
$script:allTermsOfUse = (Invoke-GraphRequest -url "/identityGovernance/termsOfUse/agreements?`$select=displayName,Id&top=999" -ODataMetadata "minimal").value
|
||||
}
|
||||
if(-not $script:allTermsOfUse ) { $script:allTermsOfUse = @()}
|
||||
elseif($script:allTermsOfUse -isnot [Object[]]) { $script:allTermsOfUse = @($script:allTermsOfUse ) }
|
||||
}
|
||||
|
||||
if($obj.conditions.locations.includeLocations.Count -gt 0)
|
||||
{
|
||||
$tmpObjs = @()
|
||||
@@ -2056,82 +2223,103 @@ function Invoke-CDDocumentConditionalAccess
|
||||
EntityKey = "policyControl"
|
||||
})
|
||||
|
||||
if(($obj.grantControls.builtInControls | Where { $_ -eq "block"}))
|
||||
if($null -eq (($obj.grantControls.builtInControls | Where { $_ -eq "block"}) ))
|
||||
{
|
||||
if(($obj.grantControls.builtInControls | Where { $_ -eq "mfa"}))
|
||||
if(($obj.grantControls.builtInControls | measure).Count -gt 0)
|
||||
{
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "AzureIAM.policyControlMfaChallengeDisplayedName"
|
||||
Value = Get-LanguageString "Inputs.enabled"
|
||||
Category = $category
|
||||
SubCategory = ""
|
||||
EntityKey = "mfa"
|
||||
})
|
||||
if(($obj.grantControls.builtInControls | Where { $_ -eq "mfa"}))
|
||||
{
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "AzureIAM.policyControlMfaChallengeDisplayedName"
|
||||
Value = Get-LanguageString "Inputs.enabled"
|
||||
Category = $category
|
||||
SubCategory = ""
|
||||
EntityKey = "mfa"
|
||||
})
|
||||
}
|
||||
|
||||
if(($obj.grantControls.builtInControls | Where { $_ -eq "compliantDevice"}))
|
||||
{
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "AzureIAM.policyControlCompliantDeviceDisplayedName"
|
||||
Value = Get-LanguageString "Inputs.enabled"
|
||||
Category = $category
|
||||
SubCategory = ""
|
||||
EntityKey = "compliantDevice"
|
||||
})
|
||||
}
|
||||
|
||||
if(($obj.grantControls.builtInControls | Where { $_ -eq "domainJoinedDevice"}))
|
||||
{
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "AzureIAM.policyControlRequireDomainJoinedDisplayedName"
|
||||
Value = Get-LanguageString "Inputs.enabled"
|
||||
Category = $category
|
||||
SubCategory = ""
|
||||
EntityKey = "domainJoinedDevice"
|
||||
})
|
||||
}
|
||||
|
||||
if(($obj.grantControls.builtInControls | Where { $_ -eq "approvedApplication"}))
|
||||
{
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "AzureIAM.policyControlRequireMamDisplayedName"
|
||||
Value = Get-LanguageString "Inputs.enabled"
|
||||
Category = $category
|
||||
SubCategory = ""
|
||||
EntityKey = "approvedApplication"
|
||||
})
|
||||
}
|
||||
|
||||
if(($obj.grantControls.builtInControls | Where { $_ -eq "compliantApplication"}))
|
||||
{
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "AzureIAM.policyControlRequireCompliantAppDisplayedName"
|
||||
Value = Get-LanguageString "Inputs.enabled"
|
||||
Category = $category
|
||||
SubCategory = ""
|
||||
EntityKey = "compliantApplication"
|
||||
})
|
||||
}
|
||||
|
||||
if(($obj.grantControls.builtInControls | Where { $_ -eq "passwordChange"}))
|
||||
{
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "AzureIAM.policyControlRequiredPasswordChangeDisplayedName"
|
||||
Value = Get-LanguageString "Inputs.enabled"
|
||||
Category = $category
|
||||
SubCategory = ""
|
||||
EntityKey = "passwordChange"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if(($obj.grantControls.builtInControls | Where { $_ -eq "compliantDevice"}))
|
||||
if(($obj.grantControls.termsOfUse | measure).Count -gt 0)
|
||||
{
|
||||
$termsOfUse = @()
|
||||
foreach($tmpId in $obj.grantControls.termsOfUse)
|
||||
{
|
||||
$touObj = $script:allTermsOfUse | Where Id -eq $tmpId
|
||||
$termsOfUse += ?? $touObj.displayName $tmpId
|
||||
}
|
||||
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "AzureIAM.policyControlCompliantDeviceDisplayedName"
|
||||
Value = Get-LanguageString "Inputs.enabled"
|
||||
Name = Get-LanguageString "AzureIAM.menuItemTermsOfUse"
|
||||
Value = $termsOfUse -join $script:objectSeparator
|
||||
Category = $category
|
||||
SubCategory = ""
|
||||
EntityKey = "compliantDevice"
|
||||
})
|
||||
EntityKey = "termsOfUse"
|
||||
})
|
||||
}
|
||||
|
||||
if(($obj.grantControls.builtInControls | Where { $_ -eq "domainJoinedDevice"}))
|
||||
{
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "AzureIAM.policyControlRequireDomainJoinedDisplayedName"
|
||||
Value = Get-LanguageString "Inputs.enabled"
|
||||
Category = $category
|
||||
SubCategory = ""
|
||||
EntityKey = "domainJoinedDevice"
|
||||
})
|
||||
}
|
||||
|
||||
if(($obj.grantControls.builtInControls | Where { $_ -eq "approvedApplication"}))
|
||||
{
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "AzureIAM.policyControlRequireMamDisplayedName"
|
||||
Value = Get-LanguageString "Inputs.enabled"
|
||||
Category = $category
|
||||
SubCategory = ""
|
||||
EntityKey = "approvedApplication"
|
||||
})
|
||||
}
|
||||
|
||||
if(($obj.grantControls.builtInControls | Where { $_ -eq "compliantApplication"}))
|
||||
{
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "AzureIAM.policyControlRequireCompliantAppDisplayedName"
|
||||
Value = Get-LanguageString "Inputs.enabled"
|
||||
Category = $category
|
||||
SubCategory = ""
|
||||
EntityKey = "compliantApplication"
|
||||
})
|
||||
}
|
||||
|
||||
if(($obj.grantControls.builtInControls | Where { $_ -eq "passwordChange"}))
|
||||
{
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "AzureIAM.policyControlRequiredPasswordChangeDisplayedName"
|
||||
Value = Get-LanguageString "Inputs.enabled"
|
||||
Category = $category
|
||||
SubCategory = ""
|
||||
EntityKey = "passwordChange"
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = Get-LanguageString "AzureIAM.descriptionContentForControlsAndOr"
|
||||
Value = Get-LanguageString "AzureIAM.$((?: ($obj.grantControls.operator -eq "OR") "requireOneControlText" "requireAllControlsText"))"
|
||||
Category = $category
|
||||
SubCategory = ""
|
||||
EntityKey = "grantOperator"
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
###################################################
|
||||
# Session
|
||||
@@ -2644,12 +2832,11 @@ function Invoke-CDDocumentAssignmentFilter
|
||||
|
||||
$label = Get-LanguageString "ApplicabilityRules.GridLabel.rule"
|
||||
|
||||
# "Rules" is not in the translation file
|
||||
$category = "Rules"
|
||||
$category = Get-LanguageString "SettingDetails.rules"
|
||||
|
||||
Add-CustomSettingObject ([PSCustomObject]@{
|
||||
Name = $label
|
||||
Value = $obj.rule
|
||||
Value = $obj.rule
|
||||
EntityKey = "rule"
|
||||
Category = $category
|
||||
SubCategory = $null
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#https://docs.microsoft.com/en-us/office/vba/api/overview/word
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'1.1.0'
|
||||
'1.2.0'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
@@ -31,32 +31,7 @@ function Invoke-InitializeModule
|
||||
Process = { Invoke-WordProcessItem @args }
|
||||
PostProcess = { Invoke-WordPostProcessItems @args }
|
||||
ProcessAllObjects = { Invoke-WordProcessAllObjects @args }
|
||||
})
|
||||
|
||||
$script:columnHeaders = @{
|
||||
Name="Inputs.displayNameLabel"
|
||||
Value="TableHeaders.value"
|
||||
Description="TableHeaders.description"
|
||||
GroupMode="SettingDetails.modeTableHeader" #assignmentTypeSelectionLabel?
|
||||
Group="TableHeaders.assignedGroups"
|
||||
Groups="TableHeaders.groups"
|
||||
useDeviceContext="SettingDetails.installContextLabel"
|
||||
uninstallOnDeviceRemoval="SettingDetails.UninstallOnRemoval"
|
||||
isRemovable="SettingDetails.installAsRemovable"
|
||||
vpnConfigurationId="PolicyType.vpn"
|
||||
Action="SettingDetails.actionColumnName"
|
||||
Schedule="ScheduledAction.List.schedule"
|
||||
MessageTemplate="ScheduledAction.Notification.messageTemplate"
|
||||
EmailCC="ScheduledAction.Notification.additionalRecipients"
|
||||
Filter="AssignmentFilters.assignmentFilterColumnHeader"
|
||||
Rule="ApplicabilityRules.GridLabel.Rule"
|
||||
ValueWithLabel="TableHeaders.value"
|
||||
Status="TableHeaders.status"
|
||||
CombinedValueWithLabel="TableHeaders.value"
|
||||
CombinedValue="TableHeaders.value"
|
||||
useDeviceLicensing="TableHeaders.licenseType"
|
||||
#filterMode="Filter mode" # Not in any string file yet
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function Add-WordOptionsControl
|
||||
@@ -90,6 +65,11 @@ function Add-WordOptionsControl
|
||||
$global:txtWordTableHeaderStyle.Text = Get-Setting "Documentation" "WordTableHeaderStyle" ""
|
||||
$global:txtWordCategoryHeaderStyle.Text = Get-Setting "Documentation" "WordCategoryHeaderStyle" ""
|
||||
$global:txtWordSubCategoryHeaderStyle.Text = Get-Setting "Documentation" "WordSubCategoryHeaderStyle" ""
|
||||
$global:txtWordTableTextStyle.Text = Get-Setting "Documentation" "WordTableTextStyle" ""
|
||||
|
||||
$global:cbWordTableCaptionPosition.ItemsSource = ("[ { Name: `"Above`",Value: `"above`" }, { Name: `"Below`",Value: `"below`" }]" | ConvertFrom-Json)
|
||||
$global:cbWordTableCaptionPosition.SelectedValue = (Get-Setting "Documentation" "WordTableCaptionPosition" "below")
|
||||
|
||||
$global:txtWordContentControls.Text = Get-Setting "Documentation" "WordContentControls" "Year=;Address="
|
||||
$global:txtWordTitleProperty.Text = Get-Setting "Documentation" "WordTitleProperty" "Intune documentation"
|
||||
$global:txtWordSubjectProperty.Text = Get-Setting "Documentation" "WordSubjectProperty" "Intune documentation"
|
||||
@@ -152,6 +132,9 @@ function Invoke-WordPreProcessItems
|
||||
Save-Setting "Documentation" "WordTableHeaderStyle" $global:txtWordTableHeaderStyle.Text
|
||||
Save-Setting "Documentation" "WordCategoryHeaderStyle" $global:txtWordCategoryHeaderStyle.Text
|
||||
Save-Setting "Documentation" "WordSubCategoryHeaderStyle" $global:txtWordSubCategoryHeaderStyle.Text
|
||||
Save-Setting "Documentation" "WordTableTextStyle" $global:txtWordTableTextStyle.Text
|
||||
Save-Setting "Documentation" "WordTableCaptionPosition" $global:cbWordTableCaptionPosition.SelectedValue
|
||||
|
||||
Save-Setting "Documentation" "WordContentControls" $global:txtWordContentControls.Text
|
||||
Save-Setting "Documentation" "WordTitleProperty" $global:txtWordTitleProperty.Text
|
||||
Save-Setting "Documentation" "WordSubjectProperty" $global:txtWordSubjectProperty.Text
|
||||
@@ -470,7 +453,7 @@ function Set-WordContentControlText
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Log "No ContentControl found with name $controlName" 2
|
||||
#Write-Log "No ContentControl found with name $controlName" 2
|
||||
}
|
||||
}
|
||||
catch
|
||||
@@ -521,12 +504,12 @@ function Invoke-WordProcessItem
|
||||
|
||||
foreach($prop in $global:txtWordCustomProperties.Text.Split(","))
|
||||
{
|
||||
# This will add language support for custom columens (or replacing existing header)
|
||||
# This will add language support for custom columns (or replacing existing header)
|
||||
$propInfo = $prop.Split('=')
|
||||
if(($propInfo | measure).Count -gt 1)
|
||||
{
|
||||
$properties += $propInfo[0]
|
||||
Set-WordColumnHeaderLanguageId $propInfo[0] $propInfo[1]
|
||||
Set-DocColumnHeaderLanguageId $propInfo[0] $propInfo[1]
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -574,9 +557,12 @@ function Invoke-WordProcessItem
|
||||
if(($documentedObj.Assignments | measure).Count -gt 0)
|
||||
{
|
||||
$params = @{}
|
||||
$settingProps = $null
|
||||
if($documentedObj.Assignments[0].RawIntent)
|
||||
{
|
||||
$properties = @("GroupMode","Group","Filter","FilterMode")
|
||||
|
||||
$settingProps = @("Filter","FilterMode")
|
||||
|
||||
$settingsObj = $documentedObj.Assignments | Where { $_.Settings -ne $null } | Select -First 1
|
||||
|
||||
@@ -586,7 +572,7 @@ function Invoke-WordProcessItem
|
||||
{
|
||||
if($objProp -in $properties) { continue }
|
||||
if($objProp -in @("Category","RawIntent")) { continue }
|
||||
$properties += ("Settings." + $objProp)
|
||||
$settingProps += ("Settings." + $objProp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -609,7 +595,14 @@ function Invoke-WordProcessItem
|
||||
$params.Add("AddCategories", $true)
|
||||
}
|
||||
|
||||
# Creates a standard assignments table
|
||||
Add-DocTableItems $obj $objectType $documentedObj.Assignments $properties "TableHeaders.assignments" @params
|
||||
|
||||
if($null -ne $settingProps)
|
||||
{
|
||||
# Adds additional values to the assignments table for Apps assignments
|
||||
Set-DocTableSettingsItems $obj $objectType $documentedObj.Assignments $settingProps 3
|
||||
}
|
||||
}
|
||||
|
||||
if($global:chkWordAttatchJsonFile.IsChecked -eq $true)
|
||||
@@ -632,6 +625,44 @@ function Invoke-WordProcessItem
|
||||
}
|
||||
}
|
||||
|
||||
function Set-DocTableSettingsItems
|
||||
{
|
||||
param($obj, $objectType, $items, $properties, $firstColumn)
|
||||
|
||||
$secondColumn = $firstColumn + 1
|
||||
|
||||
$script:docTable.Cell(1, $firstColumn).Range.Text = (Invoke-WordTranslateColumnHeader "Settings")
|
||||
$script:docTable.Cell(1, $secondColumn).Range.Text = ""
|
||||
|
||||
$row = 2
|
||||
foreach($itemObj in $items)
|
||||
{
|
||||
$script:docTable.Cell($row, $firstColumn).Range.Text = ""
|
||||
$script:docTable.Cell($row, $secondColumn).Range.Text = ""
|
||||
$script:docTable.Cell($row, $firstColumn).Split($properties.Count,1)
|
||||
$script:docTable.Cell($row, $secondColumn).Split($properties.Count,1)
|
||||
|
||||
$cellRow = $row
|
||||
foreach($settingProp in $properties)
|
||||
{
|
||||
$script:docTable.Cell($cellRow, $firstColumn).Range.Text = (Invoke-WordTranslateColumnHeader ($settingProp.Split('.')[-1]))
|
||||
|
||||
$propArr = $settingProp.Split('.')
|
||||
$tmpObj = $itemObj
|
||||
$propName = $propArr[-1]
|
||||
for($x = 0; $x -lt ($propArr.Count - 1);$x++)
|
||||
{
|
||||
$tmpObj = $tmpObj."$($propArr[$x])"
|
||||
}
|
||||
|
||||
$script:docTable.Cell($cellRow, $secondColumn).Column.Cells($cellRow).Range.Text = "$($tmpObj.$propName)"
|
||||
|
||||
$cellRow++
|
||||
}
|
||||
$row = $row + $properties.Count
|
||||
}
|
||||
}
|
||||
|
||||
function Invoke-WordProcessAllObjects
|
||||
{
|
||||
param($allObjectTypeObjects)
|
||||
@@ -671,54 +702,32 @@ function Invoke-WordProcessAllObjects
|
||||
}
|
||||
}
|
||||
|
||||
function Invoke-WordTranslateColumnHeader
|
||||
{
|
||||
param($columnName)
|
||||
|
||||
$lngText = ""
|
||||
if($script:columnHeaders.ContainsKey($columnName))
|
||||
{
|
||||
$lngText = Get-LanguageString $script:columnHeaders[$columnName]
|
||||
}
|
||||
|
||||
(?? $lngText $columnName)
|
||||
}
|
||||
|
||||
function Invoke-WordCustomProcessItems
|
||||
{
|
||||
param($obj, $documentedObj)
|
||||
|
||||
}
|
||||
|
||||
function Set-WordColumnHeaderLanguageId
|
||||
{
|
||||
param($columnName, $lngId)
|
||||
|
||||
if(-not $script:columnHeaders -or -not $lngId) { return }
|
||||
|
||||
if($script:columnHeaders.ContainsKey($columnName))
|
||||
{
|
||||
$script:columnHeaders[$columnName] = $lngId
|
||||
}
|
||||
else
|
||||
{
|
||||
$script:columnHeaders.Add($columnName, $lngId)
|
||||
}
|
||||
}
|
||||
|
||||
function Add-DocTableItems
|
||||
{
|
||||
param($obj, $objectType, $items, $properties, $lngId, [switch]$AddCategories, [switch]$AddSubcategories, $captionOverride, [switch]$forceFullValue)
|
||||
|
||||
if(($items | measure).Count -eq 0)
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
$tblHeaderStyle = $global:txtWordTableHeaderStyle.Text
|
||||
$tblCategoryStyle = $global:txtWordCategoryHeaderStyle.Text
|
||||
$tblSubCategoryStyle = $global:txtWordSubCategoryHeaderStyle.Text
|
||||
$tblTextStyle = $global:txtWordTableTextStyle.Text
|
||||
$txtTableCaptionPosition = $global:cbWordTableCaptionPosition.SelectedValue
|
||||
|
||||
$range = $script:doc.application.selection.range
|
||||
|
||||
$script:docTable = $script:doc.Tables.Add($range, ($items.Count + 1), $properties.Count, [Microsoft.Office.Interop.Word.WdDefaultTableBehavior]::wdWord9TableBehavior, [Microsoft.Office.Interop.Word.WdAutoFitBehavior]::wdAutoFitWindow)
|
||||
$script:docTable.ApplyStyleHeadingRows = $true
|
||||
Set-DocObjectStyle $script:docTable $global:txtWordTableStyle.Text
|
||||
Set-DocObjectStyle $script:docTable $global:txtWordTableStyle.Text | Out-null
|
||||
|
||||
if($captionOverride)
|
||||
{
|
||||
@@ -736,7 +745,7 @@ function Add-DocTableItems
|
||||
$i = 1
|
||||
foreach($prop in $properties)
|
||||
{
|
||||
$script:docTable.Cell(1, $i).Range.Text = (Invoke-WordTranslateColumnHeader ($prop.Split(".")[-1]))
|
||||
$script:docTable.Cell(1, $i).Range.Text = (Invoke-DocTranslateColumnHeader ($prop.Split(".")[-1]))
|
||||
$i++
|
||||
}
|
||||
|
||||
@@ -816,6 +825,8 @@ function Add-DocTableItems
|
||||
}
|
||||
$i++
|
||||
}
|
||||
|
||||
Set-DocObjectStyle $script:docTable.Rows($row).Range $tblTextStyle
|
||||
|
||||
if($itemObj.Category -and $curCategory -ne $itemObj.Category -and $AddCategories -eq $true)
|
||||
{
|
||||
@@ -857,13 +868,22 @@ function Add-DocTableItems
|
||||
$row++
|
||||
}
|
||||
|
||||
# -2 = Table, 1 = Below
|
||||
$script:docTable.Application.Selection.InsertCaption(-2, ". $caption", $null, 1)
|
||||
# -2 = Table caption, 1 = Below / 0 = Above
|
||||
if($txtTableCaptionPosition -eq "above")
|
||||
{
|
||||
$capPos = 0
|
||||
}
|
||||
else
|
||||
{
|
||||
$capPos = 1
|
||||
}
|
||||
$script:docTable.Application.Selection.InsertCaption(-2, ". $caption", $null, $capPos)
|
||||
|
||||
Invoke-DocGoToEnd
|
||||
|
||||
# Add new row after the table
|
||||
#$script:doc.Application.Selection.InsertParagraphAfter()
|
||||
$script:doc.Application.Selection.TypeParagraph()
|
||||
#$script:doc.Application.Selection.TypeParagraph()
|
||||
}
|
||||
|
||||
function Add-DocTableScript
|
||||
|
||||
@@ -11,7 +11,7 @@ This module is for the Endpoint Manager/Intune View. It manages Export/Import/Co
|
||||
#>
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'3.4.0'
|
||||
'3.5.0'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
@@ -86,7 +86,7 @@ function Invoke-InitializeModule
|
||||
ID="IntuneGraphAPI"
|
||||
ViewPanel = $viewPanel
|
||||
AuthenticationID = "MSAL"
|
||||
ItemChanged = { Show-GraphObjects; Invoke-ModuleFunction "Invoke-GraphObjectsChanged"; Write-Status ""}
|
||||
ItemChanged = { Show-GraphObjects -ObjectTypeChanged; Invoke-ModuleFunction "Invoke-GraphObjectsChanged"; Write-Status ""}
|
||||
Deactivating = { Invoke-EMDeactivateView }
|
||||
Activating = { Invoke-EMActivatingView }
|
||||
Authentication = (Get-MSALAuthenticationObject)
|
||||
@@ -112,6 +112,7 @@ function Invoke-InitializeModule
|
||||
PostCopyCommand = { Start-PostCopyDeviceConfiguration @args }
|
||||
PostGetCommand = { Start-PostGetDeviceConfiguration @args }
|
||||
GroupId = "DeviceConfiguration"
|
||||
NavigationProperties=$true
|
||||
})
|
||||
|
||||
Add-ViewItem (New-Object PSObject -Property @{
|
||||
@@ -124,6 +125,8 @@ function Invoke-InitializeModule
|
||||
GroupId = "ConditionalAccess"
|
||||
ImportExtension = { Add-ConditionalAccessImportExtensions @args }
|
||||
PreImportCommand = { Start-PreImportConditionalAccess @args }
|
||||
PostExportCommand = { Start-PostExportConditionalAccess @args }
|
||||
ExpandAssignmentsList = $false
|
||||
})
|
||||
|
||||
if((Get-SettingValue "PreviewFeatures" $false) -eq $true)
|
||||
@@ -150,6 +153,7 @@ function Invoke-InitializeModule
|
||||
Permissons=@("Policy.ReadWrite.ConditionalAccess")
|
||||
ImportOrder = 50
|
||||
GroupId = "ConditionalAccess"
|
||||
ExpandAssignmentsList = $false
|
||||
})
|
||||
|
||||
Add-ViewItem (New-Object PSObject -Property @{
|
||||
@@ -226,6 +230,7 @@ function Invoke-InitializeModule
|
||||
SkipRemoveProperties = @('Id')
|
||||
GroupId = "Azure"
|
||||
SkipAddIDOnExport = $true
|
||||
ExpandAssignmentsList = $false
|
||||
})
|
||||
|
||||
Add-ViewItem (New-Object PSObject -Property @{
|
||||
@@ -340,6 +345,7 @@ function Invoke-InitializeModule
|
||||
PostExportCommand = { Start-PostExportTermsAndConditions @args }
|
||||
PreImportAssignmentsCommand = { Start-PreImportAssignmentsTermsAndConditions @args }
|
||||
GroupId = "TenantAdmin"
|
||||
ExpandAssignmentsList = $false
|
||||
})
|
||||
|
||||
Add-ViewItem (New-Object PSObject -Property @{
|
||||
@@ -359,6 +365,7 @@ function Invoke-InitializeModule
|
||||
Permissons=@("DeviceManagementApps.ReadWrite.All")
|
||||
Dependencies = @("Applications")
|
||||
GroupId = "AppProtection"
|
||||
ExpandAssignmentsList = $false
|
||||
})
|
||||
|
||||
# These are also included in the managedAppPolicies API
|
||||
@@ -377,6 +384,7 @@ function Invoke-InitializeModule
|
||||
Dependencies = @("Applications")
|
||||
Icon = "AppConfiguration"
|
||||
GroupId = "AppConfiguration"
|
||||
ExpandAssignmentsList = $false
|
||||
})
|
||||
|
||||
Add-ViewItem (New-Object PSObject -Property @{
|
||||
@@ -400,6 +408,7 @@ function Invoke-InitializeModule
|
||||
ViewID = "IntuneGraphAPI"
|
||||
PropertiesToRemove = @('uploadState','publishingState','isAssigned','dependentAppCount','supersedingAppCount','supersededAppCount','committedContentVersion','isFeatured','size','categories')
|
||||
QUERYLIST = "`$filter=(microsoft.graph.managedApp/appAvailability%20eq%20null%20or%20microsoft.graph.managedApp/appAvailability%20eq%20%27lineOfBusiness%27%20or%20isAssigned%20eq%20true)&`$orderby=displayName"
|
||||
QuerySearch=$true
|
||||
Permissons=@("DeviceManagementApps.ReadWrite.All")
|
||||
AssignmentsType="mobileAppAssignments"
|
||||
AssignmentProperties = @("@odata.type","target","settings","intent")
|
||||
@@ -437,10 +446,12 @@ function Invoke-InitializeModule
|
||||
PreImportAssignmentsCommand = { Start-PreImportAssignmentsPolicySets @args }
|
||||
PreImportCommand = { Start-PreImportPolicySets @args }
|
||||
PreUpdateCommand = { Start-PreUpdatePolicySets @args }
|
||||
PostListCommand = { Start-PostListPolicySets @args }
|
||||
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
|
||||
ImportOrder = 2000 # Policy Sets reference other objects so make sure it is imported last
|
||||
Dependencies = @("Applications","AppConfiguration","AppProtection","AutoPilot","EnrollmentRestrictions","EnrollmentStatusPage","DeviceConfiguration","AdministrativeTemplates","SettingsCatalog","CompliancePolicies")
|
||||
GroupId = "PolicySets"
|
||||
ExpandAssignmentsList = $false # expand is not allowed, IsAssigned is set in PostListCommand
|
||||
})
|
||||
|
||||
Add-ViewItem (New-Object PSObject -Property @{
|
||||
@@ -485,6 +496,8 @@ function Invoke-InitializeModule
|
||||
# Property that needs to be updated on the Compliance Policy
|
||||
# deviceManagement/managementConditionStatements/$obj.conditionStatementId
|
||||
|
||||
# Location objects support removed from Intune
|
||||
<#
|
||||
Add-ViewItem (New-Object PSObject -Property @{
|
||||
Title = "Locations"
|
||||
Id = "Locations"
|
||||
@@ -495,6 +508,7 @@ function Invoke-InitializeModule
|
||||
ImportOrder = 30
|
||||
GroupId = "CompliancePolicies"
|
||||
})
|
||||
#>
|
||||
|
||||
Add-ViewItem (New-Object PSObject -Property @{
|
||||
Title = "Settings Catalog"
|
||||
@@ -526,6 +540,8 @@ function Invoke-InitializeModule
|
||||
#expand=roleassignments
|
||||
PropertiesToRemoveForUpdate = @('isBuiltInRoleDefinition','isBuiltIn','roleAssignments') ### !!! ToDo: Add support for roleAssignments
|
||||
GroupId = "TenantAdmin"
|
||||
ExpandAssignments = $false
|
||||
ExpandAssignmentsList = $false
|
||||
})
|
||||
|
||||
Add-ViewItem (New-Object PSObject -Property @{
|
||||
@@ -539,6 +555,7 @@ function Invoke-InitializeModule
|
||||
ImportOrder = 10
|
||||
DocumentAll = $true
|
||||
GroupId = "TenantAdmin"
|
||||
ExpandAssignmentsList = $false # Adds the assignmnets property but always empty
|
||||
})
|
||||
|
||||
Add-ViewItem (New-Object PSObject -Property @{
|
||||
@@ -554,6 +571,7 @@ function Invoke-InitializeModule
|
||||
PostCopyCommand = { Start-PostCopyNotifications @args }
|
||||
PropertiesToRemoveForUpdate = @('defaultLocale','localizedNotificationMessages') ### !!! ToDo: Add support for localizedNotificationMessages
|
||||
GroupId = "CompliancePolicies"
|
||||
ExpandAssignmentsList = $false
|
||||
})
|
||||
|
||||
# This has some pre-reqs for working!
|
||||
@@ -593,6 +611,7 @@ function Invoke-InitializeModule
|
||||
ImportOrder = 15
|
||||
GroupId = "TenantAdmin"
|
||||
PropertiesToRemoveForUpdate = @('platform')
|
||||
ExpandAssignmentsList = $false
|
||||
})
|
||||
|
||||
Add-ViewItem (New-Object PSObject -Property @{
|
||||
@@ -749,19 +768,34 @@ function Set-EMViewPanel
|
||||
$btnRefresh.SetValue([System.Windows.Controls.Grid]::ColumnProperty,$grdTitle.ColumnDefinitions.Count - 1)
|
||||
$btnRefresh.Margin = "0,0,5,3"
|
||||
$btnRefresh.Cursor = "Hand"
|
||||
$btnRefresh.Name = "btnRefresh"
|
||||
$btnRefresh.Focusable = $false
|
||||
$grdTitle.Children.Add($btnRefresh) | Out-Null
|
||||
|
||||
$tooltip = [System.Windows.Controls.ToolTip]::new()
|
||||
$tooltip.Content = "Refresh"
|
||||
$tooltip.Content = "Refresh all objects"
|
||||
[System.Windows.Controls.ToolTipService]::SetToolTip($btnRefresh, $tooltip)
|
||||
|
||||
$panel.RegisterName($btnRefresh.Name, $btnRefresh)
|
||||
|
||||
$tooltip = [System.Windows.Controls.ToolTip]::new()
|
||||
$tooltip.Content = "Refresh objects"
|
||||
|
||||
[System.Windows.Controls.ToolTipService]::SetToolTip($btnRefresh, $tooltip)
|
||||
|
||||
$btnRefresh.Add_Click({
|
||||
# ToDo: Move this to view view object
|
||||
$txtFilterText = $null
|
||||
$txtFilter = $this.Parent.FindName("txtFilter")
|
||||
if($txtFilter) { $txtFilter.Text = "" }
|
||||
if($txtFilter) { $txtFilterText = $txtFilter.Text } #= "" }
|
||||
|
||||
Show-GraphObjects
|
||||
Show-GraphObjects $txtFilterText
|
||||
|
||||
if($txtFilterText -and $txtFilter)
|
||||
{
|
||||
$txtFilter.Text = $txtFilterText
|
||||
Invoke-FilterBoxChanged $txtFilter
|
||||
}
|
||||
|
||||
Write-Status ""
|
||||
})
|
||||
}
|
||||
@@ -782,11 +816,29 @@ function Set-EMViewPanel
|
||||
$graphObjects | ForEach-Object { $global:dgObjects.ItemsSource.AddNewItem($_) | Out-Null }
|
||||
$global:dgObjects.ItemsSource.CommitNew()
|
||||
Set-GraphPagesButtonStatus
|
||||
Invoke-FilterBoxChanged $global:txtFilter -ForceUpdate
|
||||
Invoke-FilterBoxChanged $global:txtFilter
|
||||
Write-Status ""
|
||||
})
|
||||
}
|
||||
|
||||
function Invoke-GraphObjectsChanged
|
||||
{
|
||||
$btnRefresh = $global:EMViewObject.ViewPanel.FindName("btnRefresh")
|
||||
|
||||
if($btnRefresh)
|
||||
{
|
||||
$tooltip = [System.Windows.Controls.ToolTipService]::GetToolTip($btnRefresh)
|
||||
if($global:lstMenuItems.SelectedItem.QuerySearch -eq $true)
|
||||
{
|
||||
$tooltip.Content = "Refresh objects based on filter. Note: Only filtered objects will be returned. Clear filter and press refresh to reload other objects"
|
||||
}
|
||||
else
|
||||
{
|
||||
$tooltip.Content = "Refresh all objects"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Invoke-EMSelectedItemsChanged
|
||||
{
|
||||
$hasSelectedItems = ($global:dgObjects.ItemsSource | Where IsSelected -eq $true) -or ($null -ne $global:dgObjects.SelectedItem)
|
||||
@@ -2132,6 +2184,16 @@ function Update-EMPolicySetAssignment
|
||||
Invoke-GraphRequest -Url $api -HttpMethod "POST" -Content $json
|
||||
}
|
||||
|
||||
function Start-PostListPolicySets
|
||||
{
|
||||
param($objList, $objectType)
|
||||
|
||||
foreach($obj in $objList)
|
||||
{
|
||||
$obj | Add-Member -MemberType NoteProperty -Name "IsAssigned" -Value ($obj.Object.status -ne "notAssigned")
|
||||
}
|
||||
$objList
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endregion Locations
|
||||
@@ -2710,6 +2772,43 @@ function Start-PreImportConditionalAccess
|
||||
$obj.state = $global:cbImportCAState.SelectedValue
|
||||
}
|
||||
}
|
||||
|
||||
function Start-PostExportConditionalAccess
|
||||
{
|
||||
param($obj, $objectType, $path)
|
||||
|
||||
$ids = @()
|
||||
foreach($id in ($obj.conditions.users.includeGroups + $obj.conditions.users.excludeGroups))
|
||||
{
|
||||
if($id -in $ids) { continue }
|
||||
elseif($id -eq "GuestsOrExternalUsers") { continue }
|
||||
elseif($id -eq "All") { continue }
|
||||
elseif($id -eq "None") { continue }
|
||||
|
||||
$ids += $id
|
||||
Add-GraphMigrationObject $id "/groups" "Group"
|
||||
}
|
||||
|
||||
foreach($id in ($obj.conditions.users.includeUsers +$obj.conditions.users.excludeUsers))
|
||||
{
|
||||
if($id -in $ids) { continue }
|
||||
elseif($id -eq "GuestsOrExternalUsers") { continue }
|
||||
elseif($id -eq "All") { continue }
|
||||
elseif($id -eq "None") { continue }
|
||||
|
||||
$ids += $id
|
||||
Add-GraphMigrationObject $id "/users" "User"
|
||||
}
|
||||
|
||||
<#
|
||||
$roleIds = @()
|
||||
foreach($id in ($obj.conditions.users.includeRoles + $obj.conditions.users.excludeRoles))
|
||||
{
|
||||
if($id -in $ids) { continue }
|
||||
$roleIds += $id
|
||||
}
|
||||
#>
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Terms of use
|
||||
|
||||
@@ -10,7 +10,7 @@ This module is for the Endpoint Info View. It shows read-only objects in Intune
|
||||
#>
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'3.1.4'
|
||||
'3.5.0'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
@@ -22,7 +22,7 @@ function Invoke-InitializeModule
|
||||
ID = "EMInfoGraphAPI"
|
||||
ViewPanel = $viewPanel
|
||||
AuthenticationID = "MSAL"
|
||||
ItemChanged = { Show-GraphObjects; Invoke-ModuleFunction "Invoke-GraphObjectsChanged"; Write-Status ""}
|
||||
ItemChanged = { Show-GraphObjects -ObjectTypeChanged; Invoke-ModuleFunction "Invoke-GraphObjectsChanged"; Write-Status ""}
|
||||
Activating = { Invoke-EMInfoActivatingView }
|
||||
Authentication = (Get-MSALAuthenticationObject)
|
||||
Authenticate = { Invoke-EMInfoAuthenticateToMSAL }
|
||||
@@ -40,7 +40,8 @@ function Invoke-InitializeModule
|
||||
API = "/deviceManagement/templates"
|
||||
ShowButtons = @("Export","View")
|
||||
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
|
||||
Icon="EndpointSecurity"
|
||||
Icon="EndpointSecurity"
|
||||
ExpandAssignmentsList = $false
|
||||
})
|
||||
|
||||
Add-ViewItem (New-Object PSObject -Property @{
|
||||
@@ -50,7 +51,8 @@ function Invoke-InitializeModule
|
||||
ViewProperties = @("bindStatus", "lastAppSyncDateTime", "ownerUserPrincipalName")
|
||||
API = "/deviceManagement/androidManagedStoreAccountEnterpriseSettings"
|
||||
ShowButtons = @("Export","View")
|
||||
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
|
||||
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
|
||||
ExpandAssignmentsList = $false
|
||||
})
|
||||
|
||||
Add-ViewItem (New-Object PSObject -Property @{
|
||||
@@ -61,6 +63,7 @@ function Invoke-InitializeModule
|
||||
ShowButtons = @("Export","View")
|
||||
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
|
||||
Icon = "AndroidCOWP"
|
||||
ExpandAssignmentsList = $false
|
||||
})
|
||||
|
||||
Add-ViewItem (New-Object PSObject -Property @{
|
||||
@@ -70,7 +73,8 @@ function Invoke-InitializeModule
|
||||
ViewProperties = @("appleId", "state", "appleId", "id")
|
||||
API = "/deviceAppManagement/vppTokens"
|
||||
ShowButtons = @("Export","View")
|
||||
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
|
||||
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
|
||||
ExpandAssignmentsList = $false
|
||||
})
|
||||
|
||||
Add-ViewItem (New-Object PSObject -Property @{
|
||||
@@ -80,9 +84,9 @@ function Invoke-InitializeModule
|
||||
ViewProperties = @("tokenName", "appleIdentifier", "tokenExpirationDateTime", "id")
|
||||
API = "/deviceManagement/depOnboardingSettings/?`$top=100"
|
||||
ShowButtons = @("Export","View")
|
||||
Permissons=@("DeviceManagementServiceConfig.ReadWrite.All")
|
||||
Permissons=@("DeviceManagementServiceConfig.ReadWrite.All")
|
||||
ExpandAssignmentsList = $false
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
function Invoke-EMInfoActivatingView
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@ This module manages Microsoft Grap fuctions like calling APIs, managing graph ob
|
||||
#>
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'3.4.0'
|
||||
'3.5.0'
|
||||
}
|
||||
|
||||
$global:MSGraphGlobalApps = @(
|
||||
@@ -61,6 +61,12 @@ function Invoke-InitializeModule
|
||||
Values = @()
|
||||
})
|
||||
|
||||
$global:appSettingSections += (New-Object PSObject -Property @{
|
||||
Title = "MS Graph General"
|
||||
Id = "GraphGeneral"
|
||||
Values = @()
|
||||
})
|
||||
|
||||
Add-SettingsObject (New-Object PSObject -Property @{
|
||||
Title = "Root folder"
|
||||
Key = "RootFolder"
|
||||
@@ -132,23 +138,6 @@ function Invoke-InitializeModule
|
||||
Description = "Default value for Import Scope (Tags) when importing objects"
|
||||
}) "ImportExport"
|
||||
|
||||
Add-SettingsObject (New-Object PSObject -Property @{
|
||||
Title = "Show Delete button"
|
||||
Key = "EMAllowDelete"
|
||||
Type = "Boolean"
|
||||
DefaultValue = $false
|
||||
Description = "Allow deleting individual objectes"
|
||||
}) "ImportExport"
|
||||
|
||||
Add-SettingsObject (New-Object PSObject -Property @{
|
||||
Title = "Show Bulk Delete "
|
||||
Key = "EMAllowBulkDelete"
|
||||
Type = "Boolean"
|
||||
DefaultValue = $false
|
||||
Description = "Allow using bulk delete to delete all objects of selected types"
|
||||
}) "ImportExport"
|
||||
|
||||
|
||||
Add-SettingsObject (New-Object PSObject -Property @{
|
||||
Title = "Allow update on import (Preview)"
|
||||
Key = "AllowUpdate"
|
||||
@@ -157,7 +146,6 @@ function Invoke-InitializeModule
|
||||
Description = "This will enable the option to update/replace an existing object during import"
|
||||
}) "ImportExport"
|
||||
|
||||
|
||||
Add-SettingsObject (New-Object PSObject -Property @{
|
||||
Title = "Add ID to export file"
|
||||
Key = "AddIDToExportFile"
|
||||
@@ -171,17 +159,17 @@ function Invoke-InitializeModule
|
||||
Key = "UseBatchAPI"
|
||||
Type = "Boolean"
|
||||
DefaultValue = $false
|
||||
Description = "This will use batch API to call up to extport 20 objects on each API call"
|
||||
Description = "This will use batch API to export up to 20 objects on each API call"
|
||||
}) "ImportExport"
|
||||
|
||||
Add-SettingsObject (New-Object PSObject -Property @{
|
||||
Title = "Refresh Objects after copy"
|
||||
Key = "RefreshObjectsAfterCopy"
|
||||
Title = "Resolve reference info"
|
||||
Key = "ResolveReferenceInfo"
|
||||
Type = "Boolean"
|
||||
DefaultValue = $true
|
||||
Description = "This will refresh all objects when after a copy. If this is disabled, the list must be refreshed manually to see the new objects. Default is true"
|
||||
Description = "This will export/import info for referenced/navigation properties eg certificates in VPN profiles etc."
|
||||
}) "ImportExport"
|
||||
|
||||
|
||||
Add-SettingsObject (New-Object PSObject -Property @{
|
||||
Title = "ApplicationId"
|
||||
Key = "GraphAzureAppId"
|
||||
@@ -202,6 +190,38 @@ function Invoke-InitializeModule
|
||||
Type = "String"
|
||||
Description = "Certificate for Azure App"
|
||||
}) "GraphSilent"
|
||||
|
||||
Add-SettingsObject (New-Object PSObject -Property @{
|
||||
Title = "Refresh Objects after copy"
|
||||
Key = "RefreshObjectsAfterCopy"
|
||||
Type = "Boolean"
|
||||
DefaultValue = $true
|
||||
Description = "This will refresh all objects when after a copy. If this is disabled, the list must be refreshed manually to see the new objects. Default is true"
|
||||
}) "GraphGeneral"
|
||||
|
||||
Add-SettingsObject (New-Object PSObject -Property @{
|
||||
Title = "Show Delete button"
|
||||
Key = "EMAllowDelete"
|
||||
Type = "Boolean"
|
||||
DefaultValue = $false
|
||||
Description = "Allow deleting individual objectes"
|
||||
}) "GraphGeneral"
|
||||
|
||||
Add-SettingsObject (New-Object PSObject -Property @{
|
||||
Title = "Show Bulk Delete "
|
||||
Key = "EMAllowBulkDelete"
|
||||
Type = "Boolean"
|
||||
DefaultValue = $false
|
||||
Description = "Allow using bulk delete to delete all objects of selected types"
|
||||
}) "GraphGeneral"
|
||||
|
||||
Add-SettingsObject (New-Object PSObject -Property @{
|
||||
Title = "Expand assignments"
|
||||
Key = "ExpandAssignments"
|
||||
Type = "Boolean"
|
||||
DefaultValue = $false
|
||||
Description = "Expand assignments when listing objects. This can be used in custom columns based on assignment info"
|
||||
}) "GraphGeneral"
|
||||
}
|
||||
|
||||
function Get-GraphAppInfo
|
||||
@@ -210,13 +230,8 @@ function Get-GraphAppInfo
|
||||
|
||||
if($global:hideUI -eq $true)
|
||||
{
|
||||
# Set app info from custom settings
|
||||
$appObj = New-Object PSObject -Property @{
|
||||
ClientId = Get-SettingValue "$($PreFix)CustomAppId"
|
||||
TenantId = $global:silentTenantId
|
||||
RedirectUri = Get-SettingValue "$($PreFix)CustomAppRedirect"
|
||||
Authority = Get-SettingValue "$($PreFix)CustomAuthority"
|
||||
}
|
||||
# Taken care of by authentication function
|
||||
return
|
||||
}
|
||||
|
||||
$graphAppId = Get-SettingValue $settingId
|
||||
@@ -288,8 +303,8 @@ function Invoke-GraphRequest
|
||||
|
||||
$ODataMetadata = "full", # full, minimal, none or skip
|
||||
|
||||
[ValidateSet("BETA","v1.0")]
|
||||
$GraphVersion = "BETA",
|
||||
[ValidateSet("beta","v1.0")]
|
||||
$GraphVersion = "beta",
|
||||
|
||||
[switch]
|
||||
$AllPages,
|
||||
@@ -452,7 +467,9 @@ function Get-GraphObjects
|
||||
[switch]
|
||||
$AllPages,
|
||||
[switch]
|
||||
$SingleObject)
|
||||
$SingleObject,
|
||||
[string]
|
||||
$filter)
|
||||
|
||||
$params = @{}
|
||||
if($objectType.ODataMetadata)
|
||||
@@ -486,7 +503,7 @@ function Get-GraphObjects
|
||||
if($SinglePage -eq $true)
|
||||
{
|
||||
#Use default page size or use below for a specific page size for testing
|
||||
#$params.Add("pageSize",100)
|
||||
#$params.Add("pageSize",10) #!!!
|
||||
}
|
||||
elseif($SingleObject -ne $true -and $SinglePage -ne $true)
|
||||
{
|
||||
@@ -498,14 +515,36 @@ function Get-GraphObjects
|
||||
$url = $script:nextGraphPage
|
||||
}
|
||||
|
||||
if($SingleObject -ne $true -and (Get-SettingValue "ExpandAssignments") -eq $true -and $objectType.ExpandAssignmentsList -ne $false)
|
||||
{
|
||||
# Expand assignments so they can be used in custom columns
|
||||
if(($url.IndexOf('expand',[System.StringComparison]::InvariantCultureIgnoreCase)) -eq -1)
|
||||
{
|
||||
$url += (?: (($url.IndexOf('?')) -eq -1) "?" "&")
|
||||
$url = "$($url)`$expand=assignments"
|
||||
}
|
||||
}
|
||||
|
||||
if($script:multipleGraphPages -eq $true -and $SingleObject -ne $true -and $filter -and $objectType.QuerySearch -eq $true)
|
||||
{
|
||||
# QuerySearch is only reqired when there are more pages to load
|
||||
if(($url.IndexOf('search',[System.StringComparison]::InvariantCultureIgnoreCase)) -eq -1)
|
||||
{
|
||||
$url += (?: (($url.IndexOf('?')) -eq -1) "?" "&")
|
||||
$url = "$($url)`$search=`"$($filter)`""
|
||||
}
|
||||
}
|
||||
|
||||
$graphObjects = Invoke-GraphRequest -Url $url @params
|
||||
if($SinglePage -eq $true -or $AllPages -eq $true)
|
||||
{
|
||||
$script:nextGraphPage = $graphObjects.'@odata.nextLink'
|
||||
}
|
||||
if($null -eq $script:multipleGraphPages)
|
||||
{
|
||||
$script:multipleGraphPages = $null -ne $script:nextGraphPage
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if($graphObjects -and ($graphObjects | GM -Name Value -MemberType NoteProperty))
|
||||
{
|
||||
$retObjects = $graphObjects.Value
|
||||
@@ -515,7 +554,7 @@ function Get-GraphObjects
|
||||
$retObjects = $graphObjects
|
||||
}
|
||||
|
||||
$graphObjects = Add-GraphObectProperties $retObjects $objectType $property $exclude $SortProperty
|
||||
$graphObjects = Add-GraphObjectProperties $retObjects $objectType $property $exclude $SortProperty
|
||||
|
||||
if($SingleObject -ne $true -and $objectType.PostListCommand)
|
||||
{
|
||||
@@ -525,7 +564,7 @@ function Get-GraphObjects
|
||||
$graphObjects
|
||||
}
|
||||
|
||||
function Add-GraphObectProperties
|
||||
function Add-GraphObjectProperties
|
||||
{
|
||||
param($graphObjects,
|
||||
$objectType,
|
||||
@@ -548,6 +587,8 @@ function Add-GraphObectProperties
|
||||
$retObjects = $graphObjects
|
||||
}
|
||||
|
||||
$getAssignmentInfo = ((Get-SettingValue "ExpandAssignments") -eq $true -and $objectType.ExpandAssignmentsList -ne $false)
|
||||
|
||||
foreach($graphObject in $retObjects)
|
||||
{
|
||||
$params = @{}
|
||||
@@ -559,7 +600,16 @@ function Add-GraphObectProperties
|
||||
$objTmp | Add-Member -NotePropertyName "Object" -NotePropertyValue $graphObject
|
||||
$objTmp | Add-Member -NotePropertyName "ObjectType" -NotePropertyValue $objectType
|
||||
$objects += $objTmp
|
||||
}
|
||||
}
|
||||
|
||||
if($null -ne $graphObject.isAssigned)
|
||||
{
|
||||
$objTmp | Add-Member -NotePropertyName "IsAssigned" -NotePropertyValue $graphObject.isAssigned
|
||||
}
|
||||
elseif($getAssignmentInfo)
|
||||
{
|
||||
$objTmp | Add-Member -NotePropertyName "IsAssigned" -NotePropertyValue (($graphObject.assignments | measure).Count -gt 0)
|
||||
}
|
||||
}
|
||||
|
||||
if($objects.Count -gt 0 -and $SortProperty -and ($objects[0] | GM -MemberType NoteProperty -Name $SortProperty))
|
||||
@@ -572,8 +622,15 @@ function Add-GraphObectProperties
|
||||
|
||||
function Show-GraphObjects
|
||||
{
|
||||
param($filter, [switch]$ObjectTypeChanged)
|
||||
|
||||
$global:curObjectType = $global:lstMenuItems.SelectedItem
|
||||
|
||||
if($ObjectTypeChanged -eq $true)
|
||||
{
|
||||
$script:multipleGraphPages = $null
|
||||
}
|
||||
|
||||
Clear-GraphObjects
|
||||
|
||||
if(-not $global:MSALToken)
|
||||
@@ -585,7 +642,17 @@ function Show-GraphObjects
|
||||
}
|
||||
elseif($global:curObjectType.'@AccessType' -eq "None")
|
||||
{
|
||||
$global:txtNotLoggedIn.Content = "You don't have the required permissons to access $($global:curObjectType.Title).`n`nRequired perimssons: $($global:curObjectType.Permissons)"
|
||||
$requiredPermissions = ($global:curObjectType.Permissons -join ",")
|
||||
$missingScopes = ?? $global:curObjectType.'@MissingScopes' $requiredPermissions
|
||||
if($requiredPermissions -ne $missingScopes)
|
||||
{
|
||||
$requiredPermissions = "`nRequired permissions: $requiredPermissions"
|
||||
}
|
||||
else
|
||||
{
|
||||
$requiredPermissions = ""
|
||||
}
|
||||
$global:txtNotLoggedIn.Content = "You don't have the required permissons to access $($global:curObjectType.Title).$($requiredPermissions)`n`Missing perimssons: $missingScopes`n`nRequest consent from the 'Request Consent' link in the user login info`nor`nDisable the 'Use Default Permissions' setting to trigger consent prompt.`nNote: Changing the 'Use Default Permissions' setting will require a restart of the app`nand a 'manual' login"
|
||||
$global:grdNotLoggedIn.Visibility = "Visible"
|
||||
$global:grdData.Visibility = "Collapsed"
|
||||
return
|
||||
@@ -593,7 +660,7 @@ function Show-GraphObjects
|
||||
$global:grdNotLoggedIn.Visibility = "Collapsed"
|
||||
$global:grdData.Visibility = "Visible"
|
||||
|
||||
# Always show Import is an item is selected
|
||||
# Always show Import if an item is selected
|
||||
$global:btnImport.IsEnabled = $global:lstMenuItems.SelectedItem -ne $null
|
||||
|
||||
if(-not $global:lstMenuItems.SelectedItem) { return }
|
||||
@@ -612,9 +679,9 @@ function Show-GraphObjects
|
||||
$global:grdTitle.Visibility = "Visible"
|
||||
}
|
||||
|
||||
$script:nextGraphPage = $null
|
||||
$script:nextGraphPage = $null
|
||||
|
||||
$graphObjects = @(Get-GraphObjects -property $global:curObjectType.ViewProperties -objectType $global:curObjectType -SinglePage)
|
||||
$graphObjects = @(Get-GraphObjects -property $global:curObjectType.ViewProperties -objectType $global:curObjectType -SinglePage -Filter $filter)
|
||||
|
||||
$dgObjects.AutoGenerateColumns = $false
|
||||
$dgObjects.Columns.Clear()
|
||||
@@ -857,7 +924,7 @@ function Start-GraphPreImport
|
||||
}
|
||||
|
||||
# Remove OData properties
|
||||
foreach($odataProp in ($obj.PSObject.Properties | Where { $_.Name -like "*@Odata*Link" -or $_.Name -like "*@odata.context" -or $_.Name -like "*@odata.id" -or ($_.Name -like "*@odata.type" -and $_.Name -ne "@odata.type")}))
|
||||
foreach($odataProp in ($obj.PSObject.Properties | Where { $_.Name -like "*@Odata*Link" -or $_.Name -like "*@odata.context" -or $_.Name -like "*@odata.id" -or ($_.Name -like "*@odata.type" -and $_.Name -ne "@odata.type")})) # -or $_.Name -like "#CustomRef*"
|
||||
{
|
||||
$removeProperties += $odataProp.Name
|
||||
}
|
||||
@@ -890,10 +957,11 @@ function Get-GraphMetaData
|
||||
{
|
||||
# Graph metadata does not support Content-Length in response so size can not be used to check if it is updated
|
||||
# There also no other version information in response headers. Use file date to update every week
|
||||
Write-Log "Load Graph MetaData file"
|
||||
$url = "https://graph.microsoft.com/beta/`$metadata"
|
||||
$fileFullPath = [Environment]::ExpandEnvironmentVariables("%LOCALAPPDATA%\CloudAPIPowerShellManagement\GraphMetaData.xml")
|
||||
$fi = [IO.FileInfo]$fileFullPath
|
||||
$maxAge = (Get-Date).AddDays(-7)
|
||||
$maxAge = (Get-Date).AddDays(-14)
|
||||
if($fi.Exists -and ($fi.LastWriteTime -gt $maxAge -or $fi.CreationTime -gt $maxAge))
|
||||
{
|
||||
try
|
||||
@@ -905,6 +973,7 @@ function Get-GraphMetaData
|
||||
|
||||
if(-not $global:metaDataXML)
|
||||
{
|
||||
Write-Log "Download Graph MetaData file"
|
||||
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions")
|
||||
$wc = New-Object System.Net.WebClient
|
||||
$wc.Encoding = [System.Text.Encoding]::UTF8
|
||||
@@ -1538,6 +1607,7 @@ function Show-GraphImportForm
|
||||
$filesToImport = & $global:curObjectType.PreFilesImportCommand $global:curObjectType $filesToImport
|
||||
}
|
||||
|
||||
$navigationPropObjects = @()
|
||||
foreach ($fileObj in $filesToImport)
|
||||
{
|
||||
if($allowUpdate -and $global:cbImportType.SelectedValue -ne "alwaysImport" -and (Reset-GraphObjet $fileObj $global:dgObjects.ItemsSource))
|
||||
@@ -1545,7 +1615,22 @@ function Show-GraphImportForm
|
||||
continue
|
||||
}
|
||||
|
||||
Import-GraphFile $fileObj
|
||||
$importedObj = Import-GraphFile $fileObj -PassThru
|
||||
if($importedObj -and $global:curObjectType.NavigationProperties -eq $true)
|
||||
{
|
||||
$navigationPropObjects += [PSCustomObject]@{
|
||||
File = $fileObj
|
||||
ImportedObject = $importedObj
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($navigationPropObjects)
|
||||
{
|
||||
foreach($navPropObj in $navigationPropObjects)
|
||||
{
|
||||
Set-GraphNavigationPropertiesFromFile $navPropObj
|
||||
}
|
||||
}
|
||||
Show-GraphObjects
|
||||
Show-ModalObject
|
||||
@@ -1554,8 +1639,9 @@ function Show-GraphImportForm
|
||||
|
||||
Add-XamlEvent $script:importForm "btnGetFiles" "add_click" {
|
||||
# Used when the user manually updates the path and the press Get Files
|
||||
$global:dgObjectsToImport.ItemsSource = @(Get-GraphFileObjects $global:txtImportPath.Text)
|
||||
if([IO.Directory]::Exists($global:txtImportPath.Text))
|
||||
$path = Expand-FileName $global:txtImportPath.Text
|
||||
$global:dgObjectsToImport.ItemsSource = @(Get-GraphFileObjects $path)
|
||||
if([IO.Directory]::Exists($path))
|
||||
{
|
||||
Save-Setting "" "LastUsedFullPath" $global:txtImportPath.Text
|
||||
Set-XamlProperty $script:importForm "lblMigrationTableInfo" "Content" (Get-MigrationTableInfo)
|
||||
@@ -1566,7 +1652,8 @@ function Show-GraphImportForm
|
||||
|
||||
if($global:txtImportPath.Text)
|
||||
{
|
||||
$global:dgObjectsToImport.ItemsSource = @(Get-GraphFileObjects $global:txtImportPath.Text)
|
||||
$path = Expand-FileName $global:txtImportPath.Text
|
||||
$global:dgObjectsToImport.ItemsSource = @(Get-GraphFileObjects $path)
|
||||
Set-XamlProperty $script:importForm "lblMigrationTableInfo" "Content" (Get-MigrationTableInfo)
|
||||
}
|
||||
|
||||
@@ -1750,7 +1837,8 @@ function Start-GraphObjectImport
|
||||
{
|
||||
$filesToImport = & $item.ObjectType.PreFilesImportCommand $item.ObjectType $filesToImport
|
||||
}
|
||||
|
||||
$navigationPropObjects = @()
|
||||
|
||||
foreach ($fileObj in @($filesToImport))
|
||||
{
|
||||
$objName = Get-GraphObjectName $fileObj.Object $item.ObjectType
|
||||
@@ -1766,10 +1854,25 @@ function Start-GraphObjectImport
|
||||
continue
|
||||
}
|
||||
|
||||
Import-GraphFile $fileObj
|
||||
$importedObj = Import-GraphFile $fileObj -PassThru
|
||||
if($importedObj -and $item.ObjectType.NavigationProperties -eq $true)
|
||||
{
|
||||
$navigationPropObjects += [PSCustomObject]@{
|
||||
File = $fileObj
|
||||
ImportedObject = $importedObj
|
||||
}
|
||||
}
|
||||
|
||||
$importedObjects++
|
||||
}
|
||||
Save-Setting "" "LastUsedFullPath" $folder
|
||||
if($navigationPropObjects)
|
||||
{
|
||||
foreach($navPropObj in $navigationPropObjects)
|
||||
{
|
||||
Set-GraphNavigationPropertiesFromFile $navPropObj
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2010,7 +2113,7 @@ function Get-GraphFileObjects
|
||||
|
||||
function Import-GraphFile
|
||||
{
|
||||
param($file, $objectType)
|
||||
param($file, $objectType, [switch]$PassThru)
|
||||
|
||||
if([IO.File]::Exists($file.FileInfo.FullName) -eq $false)
|
||||
{
|
||||
@@ -2050,7 +2153,12 @@ function Import-GraphFile
|
||||
if($newObj -and $objClone.Assignments -and $global:chkImportAssignments.IsChecked -eq $true)
|
||||
{
|
||||
Import-GraphObjectAssignment $newObj $file.ObjectType $objClone.Assignments $file.FileInfo.FullName | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
if($PassThru -eq $true -and $newObj)
|
||||
{
|
||||
$newObj
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -2347,7 +2455,8 @@ function Add-GraphMigrationInfo
|
||||
if($objType -eq "#microsoft.graph.groupAssignmentTarget" -or
|
||||
$objType -eq "#microsoft.graph.exclusionGroupAssignmentTarget")
|
||||
{
|
||||
Add-GroupMigrationObject $objInfo.groupid
|
||||
#Add-GroupMigrationObject $objInfo.groupid
|
||||
Add-GraphMigrationObject $objInfo.groupid "/groups" "Group"
|
||||
}
|
||||
elseif($objType -eq "#microsoft.graph.allLicensedUsersAssignmentTarget" -or
|
||||
$objType -eq "#microsoft.graph.allDevicesAssignmentTarget")
|
||||
@@ -2420,6 +2529,8 @@ function Add-GroupMigrationObject
|
||||
|
||||
if(-not $path) { return }
|
||||
|
||||
$path = Expand-FileName $path
|
||||
|
||||
# Check if group is already processed
|
||||
$groupObj = Get-GraphMigrationObject $groupId
|
||||
if(-not $groupObj)
|
||||
@@ -2434,7 +2545,7 @@ function Add-GroupMigrationObject
|
||||
if($global:AADObjectCache.ContainsKey($groupId) -eq $false) { $global:AADObjectCache.Add($groupId, $groupObj) }
|
||||
|
||||
# Add group to migration file
|
||||
if((Add-GraphMigrationObject $groupObj $path "Group"))
|
||||
if((Add-GraphMigrationObjectToFile $groupObj $path "Group"))
|
||||
{
|
||||
# Export group info to json file for possible import
|
||||
$grouspPath = Join-Path $path "Groups"
|
||||
@@ -2445,6 +2556,46 @@ function Add-GroupMigrationObject
|
||||
}
|
||||
}
|
||||
|
||||
function Add-GraphMigrationObject
|
||||
{
|
||||
param($objId, $grapAPI, $objTypeName)
|
||||
|
||||
if(-not $objId) { return }
|
||||
|
||||
$path = Get-GraphMigrationTableFile $global:txtExportPath.Text
|
||||
|
||||
if(-not $path) { return }
|
||||
|
||||
$path = Expand-FileName $path
|
||||
|
||||
# Check if object is already processed
|
||||
$graphObj = Get-GraphMigrationObject $objId
|
||||
if(-not $graphObj)
|
||||
{
|
||||
# Get object info
|
||||
$graphObj = Invoke-GraphRequest "$($grapAPI)/$objId" -ODataMetadata "none"
|
||||
}
|
||||
|
||||
if($graphObj)
|
||||
{
|
||||
# Add object to cache
|
||||
if($global:AADObjectCache.ContainsKey($objId) -eq $false) { $global:AADObjectCache.Add($objId, $ugraphObjserObj) }
|
||||
|
||||
# Add object to migration file
|
||||
if((Add-GraphMigrationObjectToFile $graphObj $path $objTypeName))
|
||||
{
|
||||
if($objTypeName -eq "Group")
|
||||
{
|
||||
# Export group info to json file for possible import
|
||||
$grouspPath = Join-Path $path "Groups"
|
||||
if(-not (Test-Path $grouspPath)) { mkdir -Path $grouspPath -Force -ErrorAction SilentlyContinue | Out-Null }
|
||||
$fileName = "$grouspPath\$((Remove-InvalidFileNameChars $graphObj.displayName)).json"
|
||||
ConvertTo-Json $graphObj -Depth 10 | Out-File $fileName -Force
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Get-GraphMigrationObject
|
||||
{
|
||||
param($objId)
|
||||
@@ -2458,7 +2609,7 @@ function Get-GraphMigrationObject
|
||||
}
|
||||
|
||||
# Adds an object to migration file if not added previously
|
||||
function Add-GraphMigrationObject
|
||||
function Add-GraphMigrationObjectToFile
|
||||
{
|
||||
param($obj, $path, $objType)
|
||||
|
||||
@@ -2517,6 +2668,7 @@ function Get-GraphMigrationTableForImport
|
||||
$global:GraphMigrationTable = $null
|
||||
# Migration table must be located in the root of the import path
|
||||
$path = $global:txtImportPath.Text
|
||||
$path = Expand-FileName $path
|
||||
|
||||
for($i = 0;$i -lt 2;$i++)
|
||||
{
|
||||
@@ -2659,7 +2811,7 @@ function Update-JsonForEnvironment
|
||||
#region Dependency Functions
|
||||
function Get-GraphDependencyDefaultObjects
|
||||
{
|
||||
Add-GraphDependencyObjects @("ScopeTags")
|
||||
Add-GraphDependencyObjects @("ScopeTags","AssignmentFilters")
|
||||
}
|
||||
|
||||
function Get-GraphDependencyObjects
|
||||
@@ -2771,6 +2923,8 @@ function Export-GraphObjects
|
||||
|
||||
$global:ExportRoot = (Get-XamlProperty $script:exportForm "txtExportPath" "Text")
|
||||
$folder = Get-GraphObjectFolder $objectType $global:ExportRoot (Get-XamlProperty $script:exportForm "chkAddObjectType" "IsChecked") (Get-XamlProperty $script:exportForm "chkAddCompanyName" "IsChecked")
|
||||
|
||||
$folder = Expand-FileName $folder
|
||||
|
||||
$objectsToExport = @()
|
||||
if($Selected -ne $true)
|
||||
@@ -2831,6 +2985,8 @@ function Export-GraphObject
|
||||
Write-Log "No object to export" 3
|
||||
return
|
||||
}
|
||||
|
||||
Add-GraphNavigationProperties $obj $objectType
|
||||
|
||||
try
|
||||
{
|
||||
@@ -2871,6 +3027,177 @@ function Export-GraphObject
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
Update the navigation references for an object
|
||||
#>
|
||||
function Set-GraphNavigationPropertiesFromFile
|
||||
{
|
||||
param($navPropObject)
|
||||
|
||||
if(-not $navPropObject.File -or -not $navPropObject.ImportedObject)
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
# Reload data from file. Some object properties was removed before import...
|
||||
$objFileInfo = (ConvertFrom-Json (Get-Content -LiteralPath $navPropObject.File.FileInfo.FullName -Raw))
|
||||
|
||||
if(-not ($objFileInfo.PSObject.Properties | Where { $_.Name -like "#CustomRef_*" })) { return }
|
||||
|
||||
Set-GraphNavigationProperties $navPropObject.ImportedObject $objFileInfo $navPropObject.File.ObjectType
|
||||
|
||||
}
|
||||
|
||||
function Set-GraphNavigationProperties
|
||||
{
|
||||
param($newObj, $oldObj, $objectType, [switch]$FromOldObject)
|
||||
|
||||
if($objectType.NavigationProperties -ne $true) { return }
|
||||
|
||||
if(-not $newObj -or -not $oldObj -or -not $objectType)
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
if((Get-SettingValue "ResolveReferenceInfo") -ne $true) { return }
|
||||
|
||||
$entityName = $oldObj.'@odata.type'.Split('.')[-1]
|
||||
|
||||
$nameProp = ?? $objectType.NameProperty "displayName"
|
||||
|
||||
$props = Get-GraphEntityTypeProperties $entityName
|
||||
|
||||
foreach($prop in ($props | Where LocalName -eq "NavigationProperty" ))
|
||||
{
|
||||
# Is this the correct way of filter out Assignments, summaries etc.?
|
||||
if($prop.ContainsTarget -eq $true) { continue }
|
||||
|
||||
if(-not ($oldObj."$($prop.Name)@odata.associationLink")) { continue }
|
||||
|
||||
$associationLink = $oldObj."$($prop.Name)@odata.associationLink" -replace $oldObj.Id,$newObj.Id
|
||||
$refBodyObjs = $null #@()
|
||||
$refObjName = $null
|
||||
$refObjId = $null
|
||||
|
||||
if($FromOldObject -eq $true)
|
||||
{
|
||||
$navProp = Invoke-GraphRequest -URL $oldObj."$($prop.Name)@odata.navigationLink" -ODataMetadata "minimal" -NoError
|
||||
|
||||
if(-not $navProp) { continue }
|
||||
|
||||
$refObjName = Get-GraphObjectName $navProp $navProp
|
||||
$refObjId = $navProp.Id
|
||||
|
||||
$refBodyObjs = ([PSCustomObject]@{
|
||||
"@odata.id" = ("https://$global:MSALGraphEnvironment/beta/$($objectType.API)('$($navProp.Id)')")
|
||||
})
|
||||
}
|
||||
else
|
||||
{
|
||||
if(-not ($oldObj."#CustomRef_$($prop.Name)")) { continue } # Not included in the export file
|
||||
|
||||
$idx = $oldObj."#CustomRef_$($prop.Name)".IndexOf("|:|")
|
||||
if($idx -gt -1)
|
||||
{
|
||||
$refObjName = $oldObj."#CustomRef_$($prop.Name)".SubString(0,$idx)
|
||||
}
|
||||
else
|
||||
{
|
||||
$refObjName = $oldObj."#CustomRef_$($prop.Name)"
|
||||
}
|
||||
|
||||
$refObjects = Invoke-GraphRequest -URL "$($objectType.API)?`$filter=$($nameProp) eq '$($refObjName)'" -NoError
|
||||
|
||||
$objectsFound = ($refObjects.value | measure).Count
|
||||
|
||||
if($objectsFound -eq 1)
|
||||
{
|
||||
# Are there any references that allows multiple ref objects?
|
||||
foreach($refObj in $refObjects.value)
|
||||
{
|
||||
$refBodyObjs = ([PSCustomObject]@{
|
||||
"@odata.id" = ("https://$global:MSALGraphEnvironment/beta/$($objectType.API)('$($refObj.Id)')")
|
||||
})
|
||||
$refObjId = $refObj.Id
|
||||
}
|
||||
}
|
||||
elseif($objectsFound -gt 1)
|
||||
{
|
||||
Write-Log "Multiple objects ($objectsFound) found with $nameProp $refObjName. Skipping reference." 2
|
||||
continue
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Log "No object found with $nameProp $refObjName" 2
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
Write-Log "Add $refObjName ($refObjId) to navigation property $($prop.Name)"
|
||||
|
||||
$body = $refBodyObjs | ConvertTo-Json -Depth 10
|
||||
Invoke-GraphRequest -URL $associationLink -HttpMethod "PUT" -Content $body | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
<#
|
||||
Add Navigation Property data to the object so it included in the exported json file
|
||||
#>
|
||||
function Add-GraphNavigationProperties
|
||||
{
|
||||
param($obj, $objType)
|
||||
|
||||
if($objectType.NavigationProperties -ne $true) { return }
|
||||
|
||||
if(-not $obj.'@odata.type') { return }
|
||||
|
||||
if((Get-SettingValue "ResolveReferenceInfo") -ne $true) { return }
|
||||
|
||||
$entityName = $obj.'@odata.type'.Split('.')[-1]
|
||||
|
||||
$props = Get-GraphEntityTypeProperties $entityName
|
||||
|
||||
foreach($prop in ($props | Where LocalName -eq "NavigationProperty" ))
|
||||
{
|
||||
# Is this the correct way of filter out Assignments, summaries etc.?
|
||||
if($prop.ContainsTarget -eq $true) { continue }
|
||||
|
||||
if(-not ($obj."$($prop.Name)@odata.navigationLink")) { continue }
|
||||
$navProp = Invoke-GraphRequest -URL $obj."$($prop.Name)@odata.navigationLink" -ODataMetadata "minimal" -NoError
|
||||
if($navProp)
|
||||
{
|
||||
$value = $null
|
||||
$refType = ""
|
||||
if($navProp.value -is [Object[]])
|
||||
{
|
||||
if($navProp.value.Count -gt 0 -and $navProp.value[0].'@odata.type') { $refType = $navProp.value[0].'@odata.type' }
|
||||
$refValues = @()
|
||||
$navProp.value | ForEach-Object { $refValues += (Get-GraphObjectName $_ $objType) }
|
||||
if($refValues.Count -gt 0)
|
||||
{
|
||||
if(($refValues -join "") -like "*,*")
|
||||
{
|
||||
Write-Log "One or mor referenced objects has the comma (,) character in the name. Cannot add navigation property $($prop.Name)" 3
|
||||
}
|
||||
$value = ($refValues -join ",")
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if($navProp.'@odata.type') { $refType = $navProp.'@odata.type' }
|
||||
$value = (Get-GraphObjectName $navProp $objType)
|
||||
}
|
||||
if($refType -and $value)
|
||||
{
|
||||
$value = ($value + "|:|" + $refType)
|
||||
}
|
||||
|
||||
$obj | Add-Member -NotePropertyName "#CustomRef_$($prop.Name)" -NotePropertyValue $value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Get-GraphBatchObjects
|
||||
{
|
||||
param($objects, $txtNameFilter)
|
||||
@@ -2932,7 +3259,7 @@ function Get-GraphBatchObjects
|
||||
if($objectType -and $batchResults.Count -gt 0)
|
||||
{
|
||||
$batchResultsTmp = $batchResults
|
||||
$batchResults = Add-GraphObectProperties $batchResultsTmp $objectType -property $objectType.ViewProperties
|
||||
$batchResults = Add-GraphObjectProperties $batchResultsTmp $objectType -property $objectType.ViewProperties
|
||||
|
||||
$curObj = 1
|
||||
foreach($obj in $batchResults)
|
||||
@@ -3120,6 +3447,8 @@ function Copy-GraphObject
|
||||
[System.Windows.MessageBox]::Show("No object selected`n`nSelect the $($global:curObjectType.Title) item you want to copy", "Error", "OK", "Error")
|
||||
return
|
||||
}
|
||||
$script:copyForm = Initialize-Window ($global:AppRootFolder + "\Xaml\CopyDialog.xaml")
|
||||
if(-not $script:copyForm) { return }
|
||||
|
||||
$newName = "$((Get-GraphObjectName $dgObjects.SelectedItem $global:curObjectType)) - Copy"
|
||||
if($global:curObjectType.CopyDefaultName)
|
||||
@@ -3127,10 +3456,44 @@ function Copy-GraphObject
|
||||
$newName = $global:curObjectType.CopyDefaultName
|
||||
$dgObjects.SelectedItem.PSObject.Properties | foreach { $newName = $newName -replace "%$($_.Name)%", $dgObjects.SelectedItem."$($_.Name)" }
|
||||
}
|
||||
$ret = Show-InputDialog "Copy $($global:curObjectType.Title)" "Select name for the new object" $newName
|
||||
|
||||
Set-XamlProperty $script:copyForm "txtObjectName" "Text" $newName
|
||||
$descriptionProperty = $global:dgObjects.SelectedItem.Object | gm | Where { $_.Name -eq "Description" }
|
||||
if($descriptionProperty)
|
||||
{
|
||||
Set-XamlProperty $script:copyForm "txtObjectDescription" "Text" $global:dgObjects.SelectedItem.Object.Description
|
||||
}
|
||||
else
|
||||
{
|
||||
Set-XamlProperty $script:copyForm "txtObjectDescription" "IsEnabled" $false
|
||||
}
|
||||
|
||||
$script:copyForm.Add_ContentRendered({
|
||||
$txtName = $script:copyForm.FindName("txtObjectName")
|
||||
if($txtName)
|
||||
{
|
||||
$txtName.SelectAll();
|
||||
}
|
||||
})
|
||||
|
||||
Add-XamlEvent $script:copyForm "btnOk" "Add_Click" -scriptBlock ([scriptblock]{
|
||||
$script:copyForm.DialogResult = $true;
|
||||
})
|
||||
|
||||
$script:copyForm.Owner = $global:window
|
||||
$script:copyForm.Icon = $global:Window.Icon
|
||||
$ret = $script:copyForm.ShowDialog()
|
||||
|
||||
if($ret)
|
||||
{
|
||||
$newName = Get-XamlProperty $script:copyForm "txtObjectName" "Text"
|
||||
if(-not $newName)
|
||||
{
|
||||
Write-Log "New name cannot be empty. Copy object skipped" 2
|
||||
Write-Status ""
|
||||
return
|
||||
}
|
||||
|
||||
# Export profile
|
||||
Write-Status "Export $((Get-GraphObjectName $dgObjects.SelectedItem $global:curObjectType))"
|
||||
|
||||
@@ -3138,7 +3501,7 @@ function Copy-GraphObject
|
||||
|
||||
if($global:curObjectType.PreCopyCommand)
|
||||
{
|
||||
if((& $global:curObjectType.PreCopyCommand $exportObj $global:curObjectType $ret))
|
||||
if((& $global:curObjectType.PreCopyCommand $exportObj $global:curObjectType $newName))
|
||||
{
|
||||
if((Get-SettingValue "RefreshObjectsAfterCopy") -eq $true)
|
||||
{
|
||||
@@ -3154,15 +3517,22 @@ function Copy-GraphObject
|
||||
if($obj)
|
||||
{
|
||||
# Import new profile
|
||||
Set-GraphObjectName $obj $global:curObjectType $ret
|
||||
Set-GraphObjectName $obj $global:curObjectType $newName
|
||||
if((Get-XamlProperty $script:copyForm "txtObjectDescription" "IsEnabled" $false) -eq $true)
|
||||
{
|
||||
$obj.Description = Get-XamlProperty $script:copyForm "txtObjectDescription" "Text"
|
||||
}
|
||||
|
||||
$newObj = Import-GraphObject $obj $global:curObjectType
|
||||
if($newObj)
|
||||
{
|
||||
Set-GraphNavigationProperties $newObj $exportObj $global:curObjectType -FromOldObject
|
||||
|
||||
if($global:curObjectType.PostCopyCommand)
|
||||
{
|
||||
& $global:curObjectType.PostCopyCommand $exportObj $newObj $global:curObjectType
|
||||
}
|
||||
|
||||
if((Get-SettingValue "RefreshObjectsAfterCopy") -eq $true)
|
||||
{
|
||||
Show-GraphObjects
|
||||
@@ -3236,7 +3606,7 @@ function Show-GraphObjectInfo
|
||||
$descriptionProperty = $global:dgObjects.SelectedItem.Object | gm | Where { $_.Name -eq "Description" }
|
||||
if($descriptionProperty)
|
||||
{
|
||||
Set-XamlProperty $script:detailsForm "txtObjectDescription" "Text" $descriptionProperty.Value
|
||||
Set-XamlProperty $script:detailsForm "txtObjectDescription" "Text" $global:dgObjects.SelectedItem.Object.Description
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3612,6 +3982,11 @@ function Get-GraphEntityTypeProperties
|
||||
{
|
||||
param($entityType, $xml)
|
||||
|
||||
Get-GraphMetaData
|
||||
|
||||
if(-not $xml) { $xml = $global:metaDataXML }
|
||||
if(-not $xml) { return }
|
||||
|
||||
$tmpEntity = $xml.SelectSingleNode("//*[name()='EntityType' and @Name='$entityType']")
|
||||
if(-not $tmpEntity) { return }
|
||||
|
||||
@@ -3631,7 +4006,7 @@ function Get-GraphEntityTypeProperties
|
||||
[array]::Reverse($entities)
|
||||
foreach($enitiy in $entities)
|
||||
{
|
||||
$properties += $enitiy.SelectNodes("*[name()='Property']")
|
||||
$properties += $enitiy.SelectNodes("*[name()='Property' or name()='NavigationProperty']")
|
||||
}
|
||||
|
||||
$properties
|
||||
|
||||
Reference in New Issue
Block a user