Skip to content

Commit bf03e8b

Browse files
authored
Merge pull request #349 from KelvinTegelaar/dev
[pull] dev from KelvinTegelaar:dev
2 parents e5f7287 + 34e75e4 commit bf03e8b

File tree

5 files changed

+145
-4
lines changed

5 files changed

+145
-4
lines changed

Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,36 @@ function Add-CIPPScheduledTask {
9999
$excludedTenants = if ($task.excludedTenants.value) {
100100
$task.excludedTenants.value -join ','
101101
}
102+
103+
# Handle tenant filter - support both single tenant and tenant groups
104+
$tenantFilter = $task.TenantFilter.value ? $task.TenantFilter.value : $task.TenantFilter
105+
$originalTenantFilter = $task.TenantFilter
106+
107+
# If tenant filter is a complex object (from form), extract the value
108+
if ($tenantFilter -is [PSCustomObject] -and $tenantFilter.value) {
109+
$originalTenantFilter = $tenantFilter
110+
$tenantFilter = $tenantFilter.value
111+
}
112+
113+
# If tenant filter is a string but still seems to be JSON, try to parse it
114+
if ($tenantFilter -is [string] -and $tenantFilter.StartsWith('{')) {
115+
try {
116+
$parsedTenantFilter = $tenantFilter | ConvertFrom-Json
117+
if ($parsedTenantFilter.value) {
118+
$originalTenantFilter = $parsedTenantFilter
119+
$tenantFilter = $parsedTenantFilter.value
120+
}
121+
} catch {
122+
# If parsing fails, use the string as is
123+
Write-Warning "Could not parse tenant filter JSON: $tenantFilter"
124+
}
125+
}
126+
102127
$entity = @{
103128
PartitionKey = [string]'ScheduledTask'
104129
TaskState = [string]'Planned'
105130
RowKey = [string]$RowKey
106-
Tenant = $task.TenantFilter.value ? "$($task.TenantFilter.value)" : "$($task.TenantFilter)"
131+
Tenant = [string]$tenantFilter
107132
excludedTenants = [string]$excludedTenants
108133
Name = [string]$task.Name
109134
Command = [string]$task.Command.value
@@ -115,6 +140,21 @@ function Add-CIPPScheduledTask {
115140
Hidden = [bool]$Hidden
116141
Results = 'Planned'
117142
}
143+
144+
# Store the original tenant filter for group expansion during execution
145+
if ($originalTenantFilter -is [PSCustomObject] -and $originalTenantFilter.type -eq 'Group') {
146+
$entity['TenantGroup'] = [string]($originalTenantFilter | ConvertTo-Json -Compress)
147+
} elseif ($originalTenantFilter -is [string] -and $originalTenantFilter.StartsWith('{')) {
148+
# Check if it's a serialized group object
149+
try {
150+
$parsedOriginal = $originalTenantFilter | ConvertFrom-Json
151+
if ($parsedOriginal.type -eq 'Group') {
152+
$entity['TenantGroup'] = [string]$originalTenantFilter
153+
}
154+
} catch {
155+
# Not a JSON object, ignore
156+
}
157+
}
118158
if ($SyncType) {
119159
$entity.SyncType = $SyncType
120160
}

Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ function Push-ExecScheduledCommand {
1010
$Table = Get-CippTable -tablename 'ScheduledTasks'
1111
$task = $Item.TaskInfo
1212
$commandParameters = $Item.Parameters | ConvertTo-Json -Depth 10 | ConvertFrom-Json -AsHashtable
13+
14+
# Handle tenant resolution - support both direct tenant and group-expanded tenants
1315
$Tenant = $Item.Parameters.TenantFilter ?? $Item.TaskInfo.Tenant
16+
17+
# For tenant group tasks, the tenant will be the expanded tenant from the orchestrator
18+
# We don't need to expand groups here as that's handled in the orchestrator
1419
$TenantInfo = Get-Tenants -TenantFilter $Tenant
1520

1621
$null = Update-AzDataTableEntity -Force @Table -Entity @{
@@ -81,14 +86,14 @@ function Push-ExecScheduledCommand {
8186
}
8287
}
8388

84-
if ($StoredResults.Length -gt 64000 -or $task.Tenant -eq 'AllTenants') {
89+
if ($StoredResults.Length -gt 64000 -or $task.Tenant -eq 'AllTenants' -or $task.TenantGroup) {
8590
$TaskResultsTable = Get-CippTable -tablename 'ScheduledTaskResults'
8691
$TaskResults = @{
8792
PartitionKey = $task.RowKey
8893
RowKey = $Tenant
8994
Results = [string](ConvertTo-Json -Compress -Depth 20 $results)
9095
}
91-
$null = Add-AzDataTableEntity @TaskResultsTable -Entity $TaskResults -Force
96+
$null = Add-CIPPAzDataTableEntity @TaskResultsTable -Entity $TaskResults -Force
9297
$StoredResults = @{ Results = 'Completed, details are available in the More Info pane' } | ConvertTo-Json -Compress
9398
}
9499
} catch {

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItemDetails.ps1

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function Invoke-ListScheduledItemDetails {
2828

2929
# Retrieve the task information
3030
$TaskTable = Get-CIPPTable -TableName 'ScheduledTasks'
31-
$Task = Get-CIPPAzDataTableEntity @TaskTable -Filter "RowKey eq '$RowKey' and PartitionKey eq 'ScheduledTask'" | Select-Object Name, TaskState, Command, Parameters, Recurrence, ExecutedTime, ScheduledTime, PostExecution, Tenant, Hidden, Results, Timestamp
31+
$Task = Get-CIPPAzDataTableEntity @TaskTable -Filter "RowKey eq '$RowKey' and PartitionKey eq 'ScheduledTask'" | Select-Object Name, TaskState, Command, Parameters, Recurrence, ExecutedTime, ScheduledTime, PostExecution, Tenant, TenantGroup, Hidden, Results, Timestamp
3232

3333
if (-not $Task) {
3434
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
@@ -57,6 +57,35 @@ function Invoke-ListScheduledItemDetails {
5757
$Task.ScheduledTime = [DateTimeOffset]::FromUnixTimeSeconds($Task.ScheduledTime).UtcDateTime
5858
} catch {}
5959

60+
# Handle tenant group display information (similar to Invoke-ListScheduledItems)
61+
if ($Task.TenantGroup) {
62+
try {
63+
$TenantGroupObject = $Task.TenantGroup | ConvertFrom-Json -ErrorAction SilentlyContinue
64+
if ($TenantGroupObject) {
65+
# Create a tenant group object for the frontend formatting
66+
$TenantGroupForDisplay = [PSCustomObject]@{
67+
label = $TenantGroupObject.label
68+
value = $TenantGroupObject.value
69+
type = 'Group'
70+
}
71+
$Task | Add-Member -NotePropertyName TenantGroupInfo -NotePropertyValue $TenantGroupForDisplay -Force
72+
# Update the tenant to show the group object for proper formatting
73+
$Task.Tenant = $TenantGroupForDisplay
74+
}
75+
} catch {
76+
Write-Warning "Failed to parse tenant group information for task $($Task.RowKey): $($_.Exception.Message)"
77+
# Fall back to keeping original tenant value
78+
}
79+
} else {
80+
# For regular tenants, create a tenant object for consistent formatting
81+
$TenantForDisplay = [PSCustomObject]@{
82+
label = $Task.Tenant
83+
value = $Task.Tenant
84+
type = 'Tenant'
85+
}
86+
$Task.Tenant = $TenantForDisplay
87+
}
88+
6089
# Get the results if available
6190
$ResultsTable = Get-CIPPTable -TableName 'ScheduledTaskResults'
6291
$ResultsFilter = "PartitionKey eq '$RowKey'"

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItems.ps1

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,30 @@ function Invoke-ListScheduledItems {
7575
try {
7676
$Task.ScheduledTime = [DateTimeOffset]::FromUnixTimeSeconds($Task.ScheduledTime).UtcDateTime
7777
} catch {}
78+
79+
# Handle tenant group display information
80+
if ($Task.TenantGroup) {
81+
try {
82+
$TenantGroupObject = $Task.TenantGroup | ConvertFrom-Json -ErrorAction SilentlyContinue
83+
if ($TenantGroupObject) {
84+
# Create a tenant group object for the frontend formatting
85+
$TenantGroupForDisplay = [PSCustomObject]@{
86+
label = $TenantGroupObject.label
87+
value = $TenantGroupObject.value
88+
type = 'Group'
89+
}
90+
$Task | Add-Member -NotePropertyName TenantGroupInfo -NotePropertyValue $TenantGroupForDisplay -Force
91+
# Update the tenant to show the group object for proper formatting
92+
$Task.Tenant = @($TenantGroupForDisplay)
93+
}
94+
} catch {
95+
Write-Warning "Failed to parse tenant group information for task $($Task.RowKey): $($_.Exception.Message)"
96+
# Fall back to keeping original tenant value
97+
}
98+
} else {
99+
$Task.Tenant = @($Task.Tenant)
100+
}
101+
78102
$Task
79103
}
80104

Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-UserTasksOrchestrator.ps1

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,50 @@ function Start-UserTasksOrchestrator {
5050
}
5151
}
5252
$Batch.AddRange($AllTenantCommands)
53+
} elseif ($task.TenantGroup) {
54+
# Handle tenant groups - expand group to individual tenants
55+
try {
56+
$TenantGroupObject = $task.TenantGroup | ConvertFrom-Json
57+
Write-Host "Expanding tenant group: $($TenantGroupObject.label) with ID: $($TenantGroupObject.value)"
58+
59+
# Create a tenant filter object for expansion
60+
$TenantFilterForExpansion = @([PSCustomObject]@{
61+
type = 'Group'
62+
value = $TenantGroupObject.value
63+
label = $TenantGroupObject.label
64+
})
65+
66+
# Expand the tenant group to individual tenants
67+
$ExpandedTenants = Expand-CIPPTenantGroups -TenantFilter $TenantFilterForExpansion
68+
69+
$ExcludedTenants = $task.excludedTenants -split ','
70+
Write-Host "Excluded Tenants from this task: $ExcludedTenants"
71+
72+
$GroupTenantCommands = foreach ($ExpandedTenant in $ExpandedTenants | Where-Object { $_.value -notin $ExcludedTenants }) {
73+
$NewParams = $task.Parameters.Clone()
74+
if ((Get-Command $task.Command).Parameters.TenantFilter) {
75+
$NewParams.TenantFilter = $ExpandedTenant.value
76+
}
77+
[pscustomobject]@{
78+
Command = $task.Command
79+
Parameters = $NewParams
80+
TaskInfo = $task
81+
FunctionName = 'ExecScheduledCommand'
82+
}
83+
}
84+
$Batch.AddRange($GroupTenantCommands)
85+
} catch {
86+
Write-Host "Error expanding tenant group: $($_.Exception.Message)"
87+
Write-LogMessage -API 'Scheduler_UserTasks' -tenant $tenant -message "Failed to expand tenant group for task $($task.Name): $($_.Exception.Message)" -sev Error
88+
89+
# Fall back to treating as single tenant
90+
if ((Get-Command $task.Command).Parameters.TenantFilter) {
91+
$ScheduledCommand.Parameters['TenantFilter'] = $task.Tenant
92+
}
93+
$Batch.Add($ScheduledCommand)
94+
}
5395
} else {
96+
# Handle single tenant
5497
if ((Get-Command $task.Command).Parameters.TenantFilter) {
5598
$ScheduledCommand.Parameters['TenantFilter'] = $task.Tenant
5699
}

0 commit comments

Comments
 (0)