3.1.2
Support for deleting profiles/policies
This commit is contained in:
@@ -11,7 +11,7 @@ Objects can be compared based on Properties or Documentatation info.
|
||||
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'1.0.0'
|
||||
'1.0.1'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
|
||||
@@ -20,7 +20,7 @@ $global:documentationProviders = @()
|
||||
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'1.0.0'
|
||||
'1.0.1'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
@@ -411,6 +411,10 @@ function Get-ObjectTypeString
|
||||
{
|
||||
return (Get-LanguageString "SecurityTemplate.conditionalAccess")
|
||||
}
|
||||
elseif($objTypeId -eq "EndpointAnalytics")
|
||||
{
|
||||
return (Get-LanguageString "SettingDetails.healthMonScopeBootPerf")
|
||||
}
|
||||
elseif($objTypeId -eq "EndpointSecurity")
|
||||
{
|
||||
return (Get-LanguageString "PolicyType.EndpointSecurityTemplate.default")
|
||||
|
||||
@@ -10,7 +10,7 @@ This module is for the Endpoint Manager/Intune View. It manages Export/Import/Co
|
||||
#>
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'3.1.0'
|
||||
'3.1.2'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
@@ -20,7 +20,7 @@ function Invoke-InitializeModule
|
||||
Title = "Endpoint Manager/Intune"
|
||||
Id = "EndpointManager"
|
||||
Values = @()
|
||||
Priority = 10
|
||||
Priority = 10
|
||||
})
|
||||
|
||||
Add-SettingsObject (New-Object PSObject -Property @{
|
||||
@@ -72,6 +72,22 @@ function Invoke-InitializeModule
|
||||
SubPath = "EndpointManager"
|
||||
}) "EndpointManager"
|
||||
|
||||
Add-SettingsObject (New-Object PSObject -Property @{
|
||||
Title = "Show Delete button"
|
||||
Key = "EMAllowDelete"
|
||||
Type = "Boolean"
|
||||
DefaultValue = $false
|
||||
Description = "Allow deleting individual objectes"
|
||||
}) "EndpointManager"
|
||||
|
||||
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"
|
||||
}) "EndpointManager"
|
||||
|
||||
$viewPanel = Get-XamlObject ($global:AppRootFolder + "\Xaml\EndpointManagerPanel.xaml") -AddVariables
|
||||
|
||||
Set-EMViewPanel $viewPanel
|
||||
@@ -89,6 +105,8 @@ function Invoke-InitializeModule
|
||||
Authenticate = { Invoke-EMAuthenticateToMSAL }
|
||||
AppInfo = (Get-GraphAppInfo "EMAzureApp" "d1ddf0e4-d672-4dae-b554-9d5bdfd93547")
|
||||
SaveSettings = { Invoke-EMSaveSettings }
|
||||
|
||||
Permissions = @()
|
||||
})
|
||||
|
||||
Add-ViewObject $global:EMViewObject
|
||||
@@ -166,6 +184,7 @@ function Invoke-InitializeModule
|
||||
PostImportCommand = { Start-PostImportIntuneBranding @args }
|
||||
PostGetCommand = { Start-PostGetIntuneBranding @args }
|
||||
PostExportCommand = { Start-PostExportIntuneBranding @args }
|
||||
PreDeleteCommand = { Start-PreDeleteIntuneBranding @args }
|
||||
Permissons=@("DeviceManagementApps.ReadWrite.All")
|
||||
Icon = "Branding"
|
||||
SkipRemoveProperties = @('Id') # Id is removed by PreImport. Required for default profile
|
||||
@@ -202,6 +221,7 @@ function Invoke-InitializeModule
|
||||
ViewID = "IntuneGraphAPI"
|
||||
PreImportCommand = { Start-PreImportESP @args }
|
||||
PostExportCommand = { Start-PostExportESP @args }
|
||||
PreDeleteCommand = { Start-PreDeleteEnrollmentRestrictions @args } # Note: Uses same PreDelete as restrictions
|
||||
QUERYLIST = "`$filter=endsWith(id,'Windows10EnrollmentCompletionPageConfiguration')"
|
||||
Permissons=@("DeviceManagementServiceConfig.ReadWrite.All")
|
||||
SkipRemoveProperties = @('Id')
|
||||
@@ -217,6 +237,7 @@ function Invoke-InitializeModule
|
||||
QUERYLIST = "`$filter=not endsWith(id,'Windows10EnrollmentCompletionPageConfiguration')"
|
||||
PostExportCommand = { Start-PostExportEnrollmentRestrictions @args }
|
||||
PreImportCommand = { Start-PreImportEnrollmentRestrictions @args }
|
||||
PreDeleteCommand = { Start-PreDeleteEnrollmentRestrictions @args }
|
||||
Permissons=@("DeviceManagementServiceConfig.ReadWrite.All")
|
||||
SkipRemoveProperties = @('Id')
|
||||
AssignmentsType = "enrollmentConfigurationAssignments"
|
||||
@@ -522,13 +543,26 @@ function Invoke-InitializeModule
|
||||
ImportOrder = 15
|
||||
GroupId = "TenantAdmin"
|
||||
})
|
||||
|
||||
Add-ViewItem (New-Object PSObject -Property @{
|
||||
Title = "Health Scripts"
|
||||
Id = "DeviceHealthScripts"
|
||||
ViewID = "IntuneGraphAPI"
|
||||
QUERYLIST = "`$filter=isGlobalScript%20eq%20false" # Looks like filters are not working for deviceHealthScripts
|
||||
API = "/deviceManagement/deviceHealthScripts"
|
||||
PreDeleteCommand = { Start-PreDeleteDeviceHealthScripts @args }
|
||||
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
|
||||
GroupId = "EndpointAnalytics"
|
||||
Icon = "Report"
|
||||
AssignmentsType = "deviceHealthScriptAssignments"
|
||||
})
|
||||
}
|
||||
|
||||
function Invoke-EMAuthenticateToMSAL
|
||||
{
|
||||
$global:EMViewObject.AppInfo = Get-GraphAppInfo "EMAzureApp" "d1ddf0e4-d672-4dae-b554-9d5bdfd93547"
|
||||
Set-MSALCurrentApp $global:EMViewObject.AppInfo
|
||||
& $global:msalAuthenticator.Login -Account (?? $global:MSALToken.Account.UserName (Get-Setting "" "LastLoggedOnUser"))
|
||||
& $global:msalAuthenticator.Login -Account (?? $global:MSALToken.Account.UserName (Get-Setting "" "LastLoggedOnUser")) -Permissions $global:EMViewObject.Permissions
|
||||
}
|
||||
|
||||
function Invoke-EMDeactivateView
|
||||
@@ -566,16 +600,38 @@ function Invoke-EMSaveSettings
|
||||
Connect-MSALUser -Account $global:MSALToken.Account.Username
|
||||
Write-Status ""
|
||||
}
|
||||
|
||||
# Hide/Show Delete button
|
||||
$allowDelete = Get-SettingValue "EMAllowDelete"
|
||||
$global:btnDelete.Visibility = (?: ($allowDelete -eq $true) "Visible" "Collapsed")
|
||||
|
||||
# Hide/Show Delete on Bulk menu
|
||||
$allowBulkDelete = Get-SettingValue "EMAllowBulkDelete"
|
||||
$mnuBulk = $mnuMain.Items | Where Name -eq "EMBulk"
|
||||
|
||||
if($mnuBulk)
|
||||
{
|
||||
$mnuBulkDelete = $mnuBulk.Items | Where Name -eq "mnuBulkDelete"
|
||||
if($mnuBulkDelete)
|
||||
{
|
||||
$mnuBulkDelete.Visibility = (?: ($allowBulkDelete -eq $true) "Visible" "Collapsed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Set-EMViewPanel
|
||||
{
|
||||
param($panel)
|
||||
|
||||
# ToDo: Create View specific pannel and move this to graph
|
||||
Add-XamlEvent $panel "btnView" "Add_Click" -scriptBlock ([scriptblock]{
|
||||
Show-GraphObjectInfo
|
||||
})
|
||||
|
||||
Add-XamlEvent $panel "btnDelete" "Add_Click" -scriptBlock ([scriptblock]{
|
||||
Remove-GraphObjects
|
||||
})
|
||||
|
||||
Add-XamlEvent $panel "btnCopy" "Add_Click" -scriptBlock ([scriptblock]{
|
||||
Copy-GraphObject
|
||||
})
|
||||
@@ -603,11 +659,14 @@ function Set-EMViewPanel
|
||||
})
|
||||
|
||||
Invoke-FiterBoxChanged ($panel.FindName("txtFilter"))
|
||||
|
||||
|
||||
$allowDelete = Get-SettingValue "EMAllowDelete"
|
||||
Set-XamlProperty $panel "btnDelete" "Visibility" (?: ($allowDelete -eq $true) "Visible" "Collapsed")
|
||||
|
||||
$global:dgObjects.add_selectionChanged({
|
||||
Set-XamlProperty $this.Parent "btnView" "IsEnabled" (?: ($global:dgObjects.SelectedItem -eq $null) $false $true)
|
||||
Set-XamlProperty $this.Parent "btnCopy" "IsEnabled" (?: ($global:dgObjects.SelectedItem -eq $null) $false $true)
|
||||
Set-XamlProperty $this.Parent "btnDelete" "IsEnabled" (?: ($global:dgObjects.SelectedItem -eq $null -and $global:curObjectType.AllowDelete -ne $false) $false $true)
|
||||
})
|
||||
|
||||
# ToDo: Move this to the view object
|
||||
@@ -922,6 +981,15 @@ function Start-PostExportIntuneBranding
|
||||
}
|
||||
}
|
||||
|
||||
function Start-PreDeleteIntuneBranding
|
||||
{
|
||||
param($obj, $objectType)
|
||||
|
||||
if($obj.isDefaultProfile -eq $true)
|
||||
{
|
||||
@{ "Delete" = $false }
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1613,6 +1681,16 @@ function Start-PreImportEnrollmentRestrictions
|
||||
Remove-Property $obj "Id"
|
||||
}
|
||||
}
|
||||
|
||||
function Start-PreDeleteEnrollmentRestrictions
|
||||
{
|
||||
param($obj, $objectType)
|
||||
|
||||
if($obj.Priority -eq 0)
|
||||
{
|
||||
@{ "Delete" = $false }
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ScopeTags
|
||||
@@ -1633,6 +1711,20 @@ function Start-PreImportAssignmentsAutoPilot
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Health Scripts
|
||||
|
||||
function Start-PreDeleteDeviceHealthScripts
|
||||
{
|
||||
param($obj, $objectType)
|
||||
|
||||
if($obj.IsGlobal -eq $true)
|
||||
{
|
||||
@{ "Delete" = $false }
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Generic functions
|
||||
|
||||
function Save-EMDefaultPolicy
|
||||
|
||||
@@ -10,7 +10,7 @@ This module is for the Endpoint Info View. It shows read-only objects in Intune
|
||||
#>
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'3.1.0'
|
||||
'3.1.1'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
@@ -27,6 +27,7 @@ function Invoke-InitializeModule
|
||||
Authenticate = { Invoke-EMInfoAuthenticateToMSAL }
|
||||
AppInfo = (Get-GraphAppInfo "EM" "d1ddf0e4-d672-4dae-b554-9d5bdfd93547")
|
||||
SaveSettings = { Invoke-EMSaveSettings }
|
||||
Permissions = @()
|
||||
})
|
||||
|
||||
Add-ViewObject $global:EMInfoViewObject
|
||||
@@ -80,7 +81,7 @@ function Invoke-InitializeModule
|
||||
ShowButtons = @("View")
|
||||
Permissons=@("DeviceManagementServiceConfig.ReadWrite.All")
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
function Invoke-EMInfoActivatingView
|
||||
@@ -99,6 +100,6 @@ function Invoke-EMInfoAuthenticateToMSAL
|
||||
$usr = (?? $global:MSALToken.Account.UserName (Get-Setting "" "LastLoggedOnUser"))
|
||||
if($usr)
|
||||
{
|
||||
& $global:msalAuthenticator.Login -Account $usr
|
||||
& $global:msalAuthenticator.Login -Account $usr -Permissions $global:EMInfoViewObject.Permissions
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ This module manages Authentication for the application with MSAL. It is also res
|
||||
#>
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'3.0.0'
|
||||
'3.0.1'
|
||||
}
|
||||
|
||||
$global:msalAuthenticator = $null
|
||||
@@ -59,6 +59,14 @@ function Invoke-InitializeModule
|
||||
Description = "Default permissions of the selected app will be used when logging on. Some objects might not be accessable"
|
||||
}) "MSAL"
|
||||
|
||||
Add-SettingsObject (New-Object PSObject -Property @{
|
||||
Title = "Add Azure Role Read permissions"
|
||||
Key = "AzureADRoleRead"
|
||||
Type = "Boolean"
|
||||
DefaultValue = $false
|
||||
Description = "Request Azure AD Role read permission when getting the token. This can be use to resolve the SIDs to Azure Roles for the wids property on the Access Token. Note: This might trigger a consent prompt"
|
||||
}) "MSAL"
|
||||
|
||||
Add-MSALPrereq
|
||||
|
||||
#$script:MSALDLLMissing = $true #!!!!
|
||||
@@ -75,6 +83,7 @@ function Get-MSALAuthenticationObject
|
||||
Logout = { Disconnect-MSALUser }
|
||||
ProfilePicture = { Get-MSALProfileEllipse @args }
|
||||
ShowErrors = { Show-MSALError }
|
||||
Permissions = @("openid","profile","email","User.ReadWrite.All","Group.ReadWrite.All") #"RoleManagement.Read.Directory"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,7 +520,9 @@ function Connect-MSALUser
|
||||
[switch]
|
||||
$Interactive,
|
||||
|
||||
$Account
|
||||
$Account,
|
||||
|
||||
$Permissions = @() # Addidional permissions required by the current view object
|
||||
)
|
||||
|
||||
# No login during first time the app is started
|
||||
@@ -559,8 +570,29 @@ function Connect-MSALUser
|
||||
}
|
||||
else
|
||||
{
|
||||
$Scopes = [string[]]$global:PermissionScope
|
||||
#$Scopes = [string[]]$global:PermissionScope
|
||||
$reqScopes = [string[]]$global:msalAuthenticator.Permissions
|
||||
$useDefaultPermissions = $false
|
||||
|
||||
$resolveRoles = ((Get-SettingValue "AzureADRoleRead" $false) -eq $true)
|
||||
|
||||
if($resolveRoles -and $global:msalAuthenticator.Permissions -notcontains "RoleManagement.Read.Directory")
|
||||
{
|
||||
# Adds the required permission for reading AAD directory roles
|
||||
$reqScopes += "RoleManagement.Read.Directory"
|
||||
}
|
||||
|
||||
if($Permissions.Count -gt 0)
|
||||
{
|
||||
$script:curViewPermissions = $Permissions
|
||||
}
|
||||
$reqScopes += $script:curViewPermissions
|
||||
|
||||
foreach($tmpScope in $script:curViewPermissions)
|
||||
{
|
||||
if($reqScopes -notcontains $tmpScope) { $reqScopes += $tmpScope }
|
||||
}
|
||||
$Scopes = [String[]]$reqScopes
|
||||
}
|
||||
|
||||
$global:MSALApp = Get-MSALApp $global:appObj
|
||||
@@ -645,14 +677,14 @@ function Connect-MSALUser
|
||||
#AADSTS65001
|
||||
if($script:authenticationFailure.Classification -eq "ConsentRequired")
|
||||
{
|
||||
$Scopes = [string[]]$global:PermissionScope
|
||||
$Scopes = [string[]]$reqScopes
|
||||
}
|
||||
else
|
||||
{
|
||||
if($useDefaultPermissions -eq $false -and $authResult -and ($global:PermissionScope | measure).Count -gt 0 -and $global:promptConsentRequested -notcontains $authResult.TenantId)
|
||||
if($useDefaultPermissions -eq $false -and $authResult -and ($reqScopes | measure).Count -gt 0 -and $global:promptConsentRequested -notcontains $authResult.TenantId)
|
||||
{
|
||||
$missingScopes = @()
|
||||
foreach($scope in $global:PermissionScope)
|
||||
foreach($scope in $reqScopes)
|
||||
{
|
||||
$tmpScope = $scope.Split('/')[-1]
|
||||
if($tmpScope -eq ".default") { continue }
|
||||
@@ -1270,7 +1302,7 @@ function Get-MSALProfileEllipse
|
||||
|
||||
$dg = [System.Windows.Controls.DataGrid]::new()
|
||||
$dg.ItemsSource = ($tokenArr | Select Name, Value)
|
||||
Show-ModalForm "Token info" $dg
|
||||
Show-ModalForm "Token info" $dg
|
||||
}
|
||||
|
||||
Add-XamlEvent $tmpObj "lnkAccessTokenInfo" "add_Click" {
|
||||
|
||||
@@ -10,7 +10,7 @@ This module manages Microsoft Grap fuctions like calling APIs, managing graph ob
|
||||
#>
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'3.1.0'
|
||||
'3.1.1'
|
||||
}
|
||||
|
||||
$global:MSGraphGlobalApps = @(
|
||||
@@ -697,19 +697,28 @@ function Show-GraphBulkExportForm
|
||||
|
||||
Add-GraphExportExtensions $script:exportForm 0
|
||||
|
||||
$script:lstObjectsToExport = $script:exportForm.FindName("lstObjectsToExport")
|
||||
if($script:lstObjectsToExport)
|
||||
{
|
||||
$script:lstObjectsToExport.ItemsSource = $script:exportObjects
|
||||
$column = Get-GridCheckboxColumn "Selected"
|
||||
$global:dgObjectsToExport.Columns.Add($column)
|
||||
|
||||
Add-XamlEvent $script:exportForm "chkCheckAll" "add_click" ({
|
||||
foreach($item in $script:exportObjects)
|
||||
{
|
||||
$column.Header.IsChecked = $true # All items are checked by default
|
||||
$column.Header.add_Click({
|
||||
foreach($item in $global:dgObjectsToExport.ItemsSource)
|
||||
{
|
||||
$item.Selected = $this.IsChecked
|
||||
}
|
||||
$script:lstObjectsToExport.Items.Refresh()
|
||||
})
|
||||
}
|
||||
$global:dgObjectsToExport.Items.Refresh()
|
||||
}
|
||||
)
|
||||
|
||||
# Add Object type column
|
||||
$binding = [System.Windows.Data.Binding]::new("Title")
|
||||
$column = [System.Windows.Controls.DataGridTextColumn]::new()
|
||||
$column.Header = "Object type"
|
||||
$column.IsReadOnly = $true
|
||||
$column.Binding = $binding
|
||||
$global:dgObjectsToExport.Columns.Add($column)
|
||||
|
||||
$global:dgObjectsToExport.ItemsSource = $script:exportObjects
|
||||
|
||||
Add-XamlEvent $script:exportForm "btnClose" "add_click" ({
|
||||
$script:exportForm = $null
|
||||
@@ -739,11 +748,11 @@ function Show-GraphBulkExportForm
|
||||
{
|
||||
$folder = Get-GraphObjectFolder $item.ObjectType (Get-XamlProperty $script:exportForm "txtExportPath" "Text") (Get-XamlProperty $script:exportForm "chkAddObjectType" "IsChecked") (Get-XamlProperty $script:exportForm "chkAddCompanyName" "IsChecked")
|
||||
|
||||
$objects = @(Get-GraphObjects -Url $url -property $objectType.ViewProperties -objectType $objectType)
|
||||
$objects = @(Get-GraphObjects -Url $url -property $item.ObjectType.ViewProperties -objectType $item.ObjectType)
|
||||
foreach($obj in $objects)
|
||||
{
|
||||
Write-Status "Export $($item.Title): $((Get-GraphObjectName $obj))" -Force
|
||||
Export-GraphObject $obj.Object $item.ObjectType $folder
|
||||
Write-Status "Export $($item.Title): $((Get-GraphObjectName $obj.Object $obj.ObjectType))" -Force
|
||||
Export-GraphObject $obj.Object $item.ObjectType $folder
|
||||
}
|
||||
Save-Setting "" "LastUsedFullPath" $folder
|
||||
}
|
||||
@@ -876,19 +885,36 @@ function Show-GraphBulkImportForm
|
||||
|
||||
Add-GraphImportExtensions $script:importForm 0
|
||||
|
||||
$script:lstObjectsToImport = $script:importForm.FindName("lstObjectsToImport")
|
||||
if($script:lstObjectsToImport)
|
||||
{
|
||||
$script:lstObjectsToImport.ItemsSource = $script:importObjects
|
||||
$column = Get-GridCheckboxColumn "Selected"
|
||||
$global:dgObjectsToImport.Columns.Add($column)
|
||||
|
||||
Add-XamlEvent $script:importForm "chkCheckAll" "add_click" ({
|
||||
foreach($item in $script:importObjects)
|
||||
{
|
||||
$column.Header.IsChecked = $true # All items are checked by default
|
||||
$column.Header.add_Click({
|
||||
foreach($item in $global:dgObjectsToImport.ItemsSource)
|
||||
{
|
||||
$item.Selected = $this.IsChecked
|
||||
}
|
||||
$script:lstObjectsToImport.Items.Refresh()
|
||||
})
|
||||
}
|
||||
$global:dgObjectsToImport.Items.Refresh()
|
||||
}
|
||||
)
|
||||
|
||||
# Add Object type column
|
||||
$binding = [System.Windows.Data.Binding]::new("Title")
|
||||
$column = [System.Windows.Controls.DataGridTextColumn]::new()
|
||||
$column.Header = "Object type"
|
||||
$column.IsReadOnly = $true
|
||||
$column.Binding = $binding
|
||||
$global:dgObjectsToImport.Columns.Add($column)
|
||||
|
||||
# Add Order column
|
||||
$binding = [System.Windows.Data.Binding]::new("ObjectType.ImportOrder")
|
||||
$column = [System.Windows.Controls.DataGridTextColumn]::new()
|
||||
$column.Header = "Import order"
|
||||
$column.IsReadOnly = $true
|
||||
$column.Binding = $binding
|
||||
$global:dgObjectsToImport.Columns.Add($column)
|
||||
|
||||
$global:dgObjectsToImport.ItemsSource = $script:importObjects
|
||||
|
||||
Add-XamlEvent $script:importForm "btnClose" "add_click" ({
|
||||
$script:importForm = $null
|
||||
@@ -934,6 +960,11 @@ function Show-GraphBulkImportForm
|
||||
{
|
||||
[System.Windows.MessageBox]::Show("No objects were imported. Verify folder and exported files", "Error", "OK", "Error")
|
||||
}
|
||||
else
|
||||
{
|
||||
Show-GraphObjects
|
||||
Write-Status ""
|
||||
}
|
||||
})
|
||||
|
||||
if((Get-XamlProperty $script:importForm "txtImportPath" "Text"))
|
||||
@@ -994,6 +1025,113 @@ function Add-GraphImportExtensions
|
||||
}
|
||||
}
|
||||
|
||||
function Show-GraphBulkDeleteForm
|
||||
{
|
||||
$script:deleteForm = Get-XamlObject ($global:AppRootFolder + "\Xaml\BulkDeleteForm.xaml") -AddVariables
|
||||
if(-not $script:deleteForm) { return }
|
||||
|
||||
$script:deleteObjects = @()
|
||||
foreach($objType in $global:lstMenuItems.ItemsSource)
|
||||
{
|
||||
if(-not $objType.Title) { continue }
|
||||
|
||||
if($objType.ShowButtons -is [Object[]] -and $objType.ShowButtons -notcontains "Delete") { continue }
|
||||
|
||||
$script:deleteObjects += New-Object PSObject -Property @{
|
||||
Title = $objType.Title
|
||||
Selected = $false
|
||||
ObjectType = $objType
|
||||
}
|
||||
}
|
||||
|
||||
$column = Get-GridCheckboxColumn "Selected"
|
||||
$global:dgBulkDeleteObjects.Columns.Add($column)
|
||||
|
||||
$column.Header.IsChecked = $false # All items are NOT checked by default
|
||||
$column.Header.add_Click({
|
||||
foreach($item in $global:dgBulkDeleteObjects.ItemsSource)
|
||||
{
|
||||
$item.Selected = $this.IsChecked
|
||||
}
|
||||
$global:dgBulkDeleteObjects.Items.Refresh()
|
||||
}
|
||||
)
|
||||
|
||||
# Add title column
|
||||
$binding = [System.Windows.Data.Binding]::new("Title")
|
||||
$column = [System.Windows.Controls.DataGridTextColumn]::new()
|
||||
$column.Header = "Title"
|
||||
$column.IsReadOnly = $true
|
||||
$column.Binding = $binding
|
||||
$global:dgBulkDeleteObjects.Columns.Add($column)
|
||||
|
||||
$ocList = [System.Collections.ObjectModel.ObservableCollection[object]]::new(@($script:deleteObjects))
|
||||
$global:dgBulkDeleteObjects.ItemsSource = [System.Windows.Data.CollectionViewSource]::GetDefaultView($ocList)
|
||||
|
||||
Add-XamlEvent $script:deleteForm "btnClose" "add_click" ({
|
||||
$script:deleteForm = $null
|
||||
Show-ModalObject
|
||||
})
|
||||
|
||||
Add-XamlEvent $script:deleteForm "btnDelete" "add_click" ({
|
||||
|
||||
$selCount = (($global:dgBulkDeleteObjects.ItemsSource | Where Selected -eq $true) | measure).Count
|
||||
|
||||
if($selCount -eq 0)
|
||||
{
|
||||
[System.Windows.MessageBox]::Show("No object types selected`n`nSelect types you want to delete", "Error", "OK", "Error")
|
||||
return
|
||||
}
|
||||
|
||||
if(([System.Windows.MessageBox]::Show("Are you sure you want to delete all objects of the selected type(s)?`n`n$selCount type(s) selected", "Delete Objects?", "YesNo", "Warning")) -ne "Yes")
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
Write-Status "Delete objects" -Block
|
||||
Write-Log "****************************************************************"
|
||||
Write-Log "Start bulk delete"
|
||||
Write-Log "****************************************************************"
|
||||
|
||||
foreach($item in ($global:dgBulkDeleteObjects.ItemsSource | Where Selected -eq $true))
|
||||
{
|
||||
Write-Log "----------------------------------------------------------------"
|
||||
Write-Log "Delete $($item.ObjectType.Title) objects"
|
||||
Write-Log "----------------------------------------------------------------"
|
||||
|
||||
$url = $item.ObjectType.API
|
||||
if($item.ObjectType.QUERYLIST)
|
||||
{
|
||||
$url = "$($url.Trim())?$($item.ObjectType.QUERYLIST.Trim())"
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Write-Status "Get $($item.Title) objects" -Force
|
||||
$objects = @(Get-GraphObjects -Url $url -property $item.ObjectType.ViewProperties -objectType $item.ObjectType)
|
||||
foreach($obj in $objects)
|
||||
{
|
||||
Write-Status "Delete $($item.Title): $((Get-GraphObjectName $obj.Object $obj.ObjectType))" -Force
|
||||
Remove-GraphObject $obj.Object $obj.ObjectType $folder
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-LogError "Failed when deleting $($item.Title) objects" $_.Exception
|
||||
}
|
||||
}
|
||||
|
||||
Write-Log "****************************************************************"
|
||||
Write-Log "Bulk delete finished"
|
||||
Write-Log "****************************************************************"
|
||||
Show-GraphObjects
|
||||
Write-Status ""
|
||||
})
|
||||
|
||||
|
||||
Show-ModalForm "Bulk Delete" $script:deleteForm -HideButtons
|
||||
}
|
||||
|
||||
function Get-GraphFileObjects
|
||||
{
|
||||
param($path, $Exclude = @("*_settings.json","*_assignments.json"), $SelectedStatus = $true, $ObjectType = $global:curObjectType)
|
||||
@@ -1788,6 +1926,82 @@ function Import-GraphObject
|
||||
$newObj
|
||||
}
|
||||
|
||||
function Remove-GraphObjects
|
||||
{
|
||||
$objectsToDelete = @()
|
||||
if(($global:dgObjects.ItemsSource | Where IsSelected -eq $true).Count -gt 0)
|
||||
{
|
||||
# Delete checked items
|
||||
$objectsToDelete += ($global:dgObjects.ItemsSource | Where IsSelected -eq $true)
|
||||
}
|
||||
elseif($global:dgObjects.SelectedItem)
|
||||
{
|
||||
# Delete the selected item
|
||||
$objectsToDelete += $global:dgObjects.SelectedItem
|
||||
}
|
||||
|
||||
if($objectsToDelete.Count -eq 0)
|
||||
{
|
||||
[System.Windows.MessageBox]::Show("No object selected`n`nSelect items you want to delete", "Error", "OK", "Error")
|
||||
return
|
||||
}
|
||||
|
||||
if(([System.Windows.MessageBox]::Show("Are you sure you want to delete $($objectsToDelete.Count) $($global:curObjectType.Title) object(s)?", "Delete Objects?", "YesNo", "Warning")) -ne "Yes")
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
foreach($tmpObj in $objectsToDelete)
|
||||
{
|
||||
Remove-GraphObject $tmpObj.Object $tmpObj.ObjectType
|
||||
}
|
||||
|
||||
Show-GraphObjects
|
||||
Write-Status ""
|
||||
}
|
||||
|
||||
function Remove-GraphObject
|
||||
{
|
||||
param($objToRemove, $objectType)
|
||||
|
||||
$strAPI = $null
|
||||
if($objectType.PreDeleteCommand)
|
||||
{
|
||||
$ret = & $objectType.PreDeleteCommand $objToRemove $objectType
|
||||
if($ret -is [HashTable])
|
||||
{
|
||||
if($ret.ContainsKey("Delete") -and $ret["Delete"] -eq $false)
|
||||
{
|
||||
# Delete handled manually or aborted
|
||||
return $false
|
||||
}
|
||||
|
||||
if($ret.ContainsKey("API"))
|
||||
{
|
||||
$strAPI = $ret["API"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($strAPI)
|
||||
{
|
||||
$api = $strAPI
|
||||
}
|
||||
elseif($objectType.DELETEAPI)
|
||||
{
|
||||
$api = $objectType.DELETEAPI
|
||||
}
|
||||
else
|
||||
{
|
||||
$api = $objectType.API
|
||||
}
|
||||
|
||||
Write-Status "Delete $((Get-GraphObjectName $objToRemove $objectType))"
|
||||
$strAPI = ($api + "/$($objToRemove.Id)")
|
||||
Write-Log "Delete $($objectType.Title) object $((Get-GraphObjectName $objToRemove $objectType))"
|
||||
Invoke-GraphRequest -Url $strAPI -HttpMethod "DELETE" -ODataMetadata "none"
|
||||
}
|
||||
|
||||
function Copy-GraphObject
|
||||
{
|
||||
if(-not $dgObjects.SelectedItem)
|
||||
@@ -1940,14 +2154,25 @@ function Add-GraphBulkMenu
|
||||
$menuItem = [System.Windows.Controls.MenuItem]::new()
|
||||
$menuItem.Header = "_Bulk"
|
||||
$menuItem.Name = "EMBulk"
|
||||
|
||||
$subItem = [System.Windows.Controls.MenuItem]::new()
|
||||
$subItem.Header = "_Export"
|
||||
$subItem.Add_Click({Show-GraphBulkExportForm})
|
||||
$menuItem.AddChild($subItem) | Out-Null
|
||||
|
||||
$subItem = [System.Windows.Controls.MenuItem]::new()
|
||||
$subItem.Header = "_Import"
|
||||
$subItem.Add_Click({Show-GraphBulkImportForm})
|
||||
$menuItem.AddChild($subItem) | Out-Null
|
||||
|
||||
$subItem = [System.Windows.Controls.MenuItem]::new()
|
||||
$subItem.Header = "_Delete"
|
||||
$subItem.Name = "mnuBulkDelete"
|
||||
$allowBulkDelete = Get-SettingValue "EMAllowBulkDelete"
|
||||
# Add it hidden even if not enabled, the save settings will enable it
|
||||
$subItem.Visibility = (?: ($allowBulkDelete -eq $true) "Visible" "Collapsed")
|
||||
$subItem.Add_Click({Show-GraphBulkDeleteForm})
|
||||
$menuItem.AddChild($subItem) | Out-Null
|
||||
|
||||
$mnuMain.Items.Insert(1,$menuItem) | Out-Null
|
||||
}
|
||||
Reference in New Issue
Block a user