From 74647435c2593c34ce6b2edbbade3792bc4e171f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 24 Nov 2025 21:52:26 +0100 Subject: [PATCH 1/5] Feat: Add support for assigning apps to custom groups --- .../Applications/Invoke-ExecAssignApp.ps1 | 96 +++++++++--- .../Public/Set-CIPPAssignedApplication.ps1 | 140 ++++++++++++------ 2 files changed, 172 insertions(+), 64 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAssignApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAssignApp.ps1 index ff2c14b38dcd..aad1697954db 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAssignApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAssignApp.ps1 @@ -1,4 +1,4 @@ -Function Invoke-ExecAssignApp { +function Invoke-ExecAssignApp { <# .FUNCTIONALITY Entrypoint @@ -16,37 +16,91 @@ Function Invoke-ExecAssignApp { $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter $appFilter = $Request.Query.ID ?? $Request.Body.ID $AssignTo = $Request.Query.AssignTo ?? $Request.Body.AssignTo - $AssignBody = switch ($AssignTo) { + $Intent = $Request.Query.Intent ?? $Request.Body.Intent + $AppType = $Request.Query.AppType ?? $Request.Body.AppType + $GroupNamesRaw = $Request.Query.GroupNames ?? $Request.Body.GroupNames + $GroupIdsRaw = $Request.Query.GroupIds ?? $Request.Body.GroupIds + $AssignmentMode = $Request.Query.AssignmentMode ?? $Request.Body.AssignmentMode - 'AllUsers' { - @' -{"mobileAppAssignments":[{"@odata.type":"#microsoft.graph.mobileAppAssignment","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"},"intent":"Required","settings":null}]} -'@ + $Intent = if ([string]::IsNullOrWhiteSpace($Intent)) { 'Required' } else { $Intent } + + if ([string]::IsNullOrWhiteSpace($AssignmentMode)) { + $AssignmentMode = 'replace' + } else { + $AssignmentMode = $AssignmentMode.ToLower() + if ($AssignmentMode -notin @('replace', 'append')) { + throw "Unsupported AssignmentMode value '$AssignmentMode'. Valid options are 'replace' or 'append'." } + } + + function Get-StandardizedAssignmentList { + param($InputObject) - 'AllDevices' { - @' -{"mobileAppAssignments":[{"@odata.type":"#microsoft.graph.mobileAppAssignment","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"},"intent":"Required","settings":null}]} -'@ + if ($null -eq $InputObject -or ($InputObject -is [string] -and [string]::IsNullOrWhiteSpace($InputObject))) { + return @() + } + if ($InputObject -is [string]) { + return ($InputObject -split ',') | ForEach-Object { $_.Trim() } | Where-Object { $_ } + } + if ($InputObject -is [System.Collections.IEnumerable]) { + return @($InputObject | Where-Object { $_ }) } + return @($InputObject) + } + + $GroupNames = Get-StandardizedAssignmentList -InputObject $GroupNamesRaw + $GroupIds = Get-StandardizedAssignmentList -InputObject $GroupIdsRaw + + if (-not $AssignTo -and $GroupIds.Count -eq 0 -and $GroupNames.Count -eq 0) { + throw 'No assignment target provided. Supply AssignTo, GroupNames, or GroupIds.' + } - 'Both' { - @' -{"mobileAppAssignments":[{"@odata.type":"#microsoft.graph.mobileAppAssignment","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"},"intent":"Required","settings":null},{"@odata.type":"#microsoft.graph.mobileAppAssignment","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"},"intent":"Required","settings":null}]} -'@ + # Try to get the application type if not provided. Mostly just useful for ppl using the API that dont know the application type. + if (-not $AppType) { + try { + $AppMetadata = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/$appFilter?`$select=id,@odata.type" -tenantid $TenantFilter + $odataType = $AppMetadata.'@odata.type' + if ($odataType) { + $AppType = ($odataType -replace '#microsoft.graph.', '') -replace 'App$' + } + } catch { + Write-Warning "Unable to resolve application type for $appFilter. Continuing without assignment settings." } + } + + $targetLabel = if ($AssignTo) { + $AssignTo + } elseif ($GroupNames.Count -gt 0) { + ($GroupNames -join ', ') + } elseif ($GroupIds.Count -gt 0) { + "GroupIds: $($GroupIds -join ',')" + } else { + 'CustomGroupAssignment' + } + + $setParams = @{ + ApplicationId = $appFilter + TenantFilter = $TenantFilter + Intent = $Intent + APIName = $APIName + Headers = $Headers + GroupName = ($AssignTo ? $AssignTo : $targetLabel) + AssignmentMode = $AssignmentMode + } + if ($AppType) { + $setParams.AppType = $AppType } + + if ($GroupIds.Count -gt 0) { + $setParams.GroupIds = $GroupIds + } + try { - $null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/$appFilter/assign" -tenantid $TenantFilter -body $AssignBody - $Result = "Successfully assigned app $($appFilter) to $($AssignTo)" - Write-LogMessage -headers $Headers -API $APIName -tenant $($TenantFilter) -message $Result -Sev Info + $Result = Set-CIPPAssignedApplication @setParams $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed to assign app $($appFilter) to $($AssignTo). Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage + $Result = $_.Exception.Message $StatusCode = [HttpStatusCode]::InternalServerError } diff --git a/Modules/CIPPCore/Public/Set-CIPPAssignedApplication.ps1 b/Modules/CIPPCore/Public/Set-CIPPAssignedApplication.ps1 index 272c0d21aff8..3c90a8af786a 100644 --- a/Modules/CIPPCore/Public/Set-CIPPAssignedApplication.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPAssignedApplication.ps1 @@ -6,11 +6,36 @@ function Set-CIPPAssignedApplication { $AppType, $ApplicationId, $TenantFilter, + $GroupIds, + $AssignmentMode = 'replace', $APIName = 'Assign Application', $Headers ) Write-Host "GroupName: $GroupName Intent: $Intent AppType: $AppType ApplicationId: $ApplicationId TenantFilter: $TenantFilter APIName: $APIName" try { + $assignmentSettings = $null + if ($AppType) { + $assignmentSettings = @{ + '@odata.type' = "#microsoft.graph.$($AppType)AppAssignmentSettings" + } + + switch ($AppType) { + 'Win32Lob' { + $assignmentSettings.notifications = 'hideAll' + } + 'WinGet' { + $assignmentSettings.notifications = 'hideAll' + } + 'macOsVpp' { + $assignmentSettings.useDeviceLicensing = $true + } + default { + # No additional settings + } + } + } + + # Build the assignment object $MobileAppAssignment = switch ($GroupName) { 'AllUsers' { @(@{ @@ -19,12 +44,7 @@ function Set-CIPPAssignedApplication { '@odata.type' = '#microsoft.graph.allLicensedUsersAssignmentTarget' } intent = $Intent - settings = @{ - '@odata.type' = "#microsoft.graph.$($appType)AppAssignmentSettings" - notifications = 'hideAll' - installTimeSettings = $null - restartSettings = $null - } + settings = $assignmentSettings }) break } @@ -35,12 +55,7 @@ function Set-CIPPAssignedApplication { '@odata.type' = '#microsoft.graph.allDevicesAssignmentTarget' } intent = $Intent - settings = @{ - '@odata.type' = "#microsoft.graph.$($appType)AppAssignmentSettings" - notifications = 'hideAll' - installTimeSettings = $null - restartSettings = $null - } + settings = $assignmentSettings }) break } @@ -52,12 +67,7 @@ function Set-CIPPAssignedApplication { '@odata.type' = '#microsoft.graph.allLicensedUsersAssignmentTarget' } intent = $Intent - settings = @{ - '@odata.type' = "#microsoft.graph.$($appType)AppAssignmentSettings" - notifications = 'hideAll' - installTimeSettings = $null - restartSettings = $null - } + settings = $assignmentSettings }, @{ '@odata.type' = '#microsoft.graph.mobileAppAssignment' @@ -65,27 +75,33 @@ function Set-CIPPAssignedApplication { '@odata.type' = '#microsoft.graph.allDevicesAssignmentTarget' } intent = $Intent - settings = @{ - '@odata.type' = "#microsoft.graph.$($appType)AppAssignmentSettings" - notifications = 'hideAll' - installTimeSettings = $null - restartSettings = $null - } + settings = $assignmentSettings } ) } default { - $GroupNames = $GroupName.Split(',') - $GroupIds = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/groups' -tenantid $TenantFilter | ForEach-Object { - $Group = $_ - foreach ($SingleName in $GroupNames) { - if ($_.displayname -like $SingleName) { - $group.id + $resolvedGroupIds = @() + if ($PSBoundParameters.ContainsKey('GroupIds') -and $GroupIds) { + $resolvedGroupIds = $GroupIds + } else { + $GroupNames = $GroupName.Split(',') + $resolvedGroupIds = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/groups' -tenantid $TenantFilter | ForEach-Object { + $Group = $_ + foreach ($SingleName in $GroupNames) { + if ($_.displayName -like $SingleName) { + $group.id + } } } + Write-Information "found $($resolvedGroupIds) groups" + } + + # We ain't found nothing so we panic + if (-not $resolvedGroupIds) { + throw 'No matching groups resolved for assignment request.' } - Write-Information "found $($GroupIds) groups" - foreach ($Group in $GroupIds) { + + foreach ($Group in $resolvedGroupIds) { @{ '@odata.type' = '#microsoft.graph.mobileAppAssignment' target = @{ @@ -93,30 +109,68 @@ function Set-CIPPAssignedApplication { groupId = $Group } intent = $Intent - settings = @{ - '@odata.type' = "#microsoft.graph.$($appType)AppAssignmentSettings" - notifications = 'hideAll' - installTimeSettings = $null - restartSettings = $null - } + settings = $assignmentSettings } } } } + + # If we're appending, we need to get existing assignments + if ($AssignmentMode -eq 'append') { + try { + $ExistingAssignments = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/$($ApplicationId)/assignments" -tenantid $TenantFilter + } catch { + Write-Warning "Unable to retrieve existing assignments for $ApplicationId. Proceeding with new assignments only. Error: $($_.Exception.Message)" + $ExistingAssignments = @() + } + } + + # Deduplicate current assignments so the new ones override existing ones + if ($ExistingAssignments) { + $ExistingAssignments = $ExistingAssignments | ForEach-Object { + if ($_.target.groupId -notin $MobileAppAssignment.target.groupId) { + $_ + } + } + } + + $FinalAssignments = [System.Collections.Generic.List[object]]::new() + if ($AssignmentMode -eq 'append' -and $ExistingAssignments) { + $ExistingAssignments | ForEach-Object { + $FinalAssignments.Add(@{ + '@odata.type' = '#microsoft.graph.mobileAppAssignment' + target = $_.target + intent = $_.intent + settings = $_.settings + }) + } + + $MobileAppAssignment | ForEach-Object { + $FinalAssignments.Add(@{ + '@odata.type' = '#microsoft.graph.mobileAppAssignment' + target = $_.target + intent = $_.intent + settings = $_.settings + }) + } + } else { + $FinalAssignments = $MobileAppAssignment + } + $DefaultAssignmentObject = [PSCustomObject]@{ mobileAppAssignments = @( - $MobileAppAssignment + $FinalAssignments ) } if ($PSCmdlet.ShouldProcess($GroupName, "Assigning Application $ApplicationId")) { Start-Sleep -Seconds 1 $null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/$($ApplicationId)/assign" -tenantid $TenantFilter -type POST -body ($DefaultAssignmentObject | ConvertTo-Json -Compress -Depth 10) - Write-LogMessage -headers $Headers -API $APIName -message "Assigned Application to $($GroupName)" -Sev 'Info' -tenant $TenantFilter + Write-LogMessage -headers $Headers -API $APIName -message "Assigned Application $ApplicationId to $($GroupName)" -Sev 'Info' -tenant $TenantFilter } - return "Assigned Application to $($GroupName)" + return "Assigned Application $ApplicationId to $($GroupName)" } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -message "Could not assign application to $GroupName. Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - return "Could not assign application to $GroupName. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message "Could not assign application $ApplicationId to $GroupName. Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + throw "Could not assign application $ApplicationId to $GroupName. Error: $($ErrorMessage.NormalizedError)" } } From e33b6f34d592d510e878269bf936a219f2033af7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Tue, 25 Nov 2025 00:28:39 +0100 Subject: [PATCH 2/5] Fix: Update assignment mode handling and improve existing assignment deduplication logic --- .../Applications/Invoke-ExecAssignApp.ps1 | 4 ++-- .../Public/Set-CIPPAssignedApplication.ps1 | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAssignApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAssignApp.ps1 index aad1697954db..6733e150366f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAssignApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAssignApp.ps1 @@ -20,7 +20,7 @@ function Invoke-ExecAssignApp { $AppType = $Request.Query.AppType ?? $Request.Body.AppType $GroupNamesRaw = $Request.Query.GroupNames ?? $Request.Body.GroupNames $GroupIdsRaw = $Request.Query.GroupIds ?? $Request.Body.GroupIds - $AssignmentMode = $Request.Query.AssignmentMode ?? $Request.Body.AssignmentMode + $AssignmentMode = $Request.Body.assignmentMode $Intent = if ([string]::IsNullOrWhiteSpace($Intent)) { 'Required' } else { $Intent } @@ -58,7 +58,7 @@ function Invoke-ExecAssignApp { # Try to get the application type if not provided. Mostly just useful for ppl using the API that dont know the application type. if (-not $AppType) { try { - $AppMetadata = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/$appFilter?`$select=id,@odata.type" -tenantid $TenantFilter + $AppMetadata = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/$appFilter" -tenantid $TenantFilter $odataType = $AppMetadata.'@odata.type' if ($odataType) { $AppType = ($odataType -replace '#microsoft.graph.', '') -replace 'App$' diff --git a/Modules/CIPPCore/Public/Set-CIPPAssignedApplication.ps1 b/Modules/CIPPCore/Public/Set-CIPPAssignedApplication.ps1 index 3c90a8af786a..862ca7e91d5c 100644 --- a/Modules/CIPPCore/Public/Set-CIPPAssignedApplication.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPAssignedApplication.ps1 @@ -128,8 +128,18 @@ function Set-CIPPAssignedApplication { # Deduplicate current assignments so the new ones override existing ones if ($ExistingAssignments) { $ExistingAssignments = $ExistingAssignments | ForEach-Object { - if ($_.target.groupId -notin $MobileAppAssignment.target.groupId) { - $_ + $ExistingAssignment = $_ + switch ($ExistingAssignment.target.'@odata.type') { + '#microsoft.graph.groupAssignmentTarget' { + if ($ExistingAssignment.target.groupId -notin $MobileAppAssignment.target.groupId) { + $ExistingAssignment + } + } + default { + if ($ExistingAssignment.target.'@odata.type' -notin $MobileAppAssignment.target.'@odata.type') { + $ExistingAssignment + } + } } } } @@ -164,6 +174,7 @@ function Set-CIPPAssignedApplication { } if ($PSCmdlet.ShouldProcess($GroupName, "Assigning Application $ApplicationId")) { Start-Sleep -Seconds 1 + # Write-Information (ConvertTo-Json $DefaultAssignmentObject -Depth 10) $null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/$($ApplicationId)/assign" -tenantid $TenantFilter -type POST -body ($DefaultAssignmentObject | ConvertTo-Json -Compress -Depth 10) Write-LogMessage -headers $Headers -API $APIName -message "Assigned Application $ApplicationId to $($GroupName)" -Sev 'Info' -tenant $TenantFilter } From af75f3df5d766ead099752b6971f2bba6d742be3 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 25 Nov 2025 12:02:03 -0500 Subject: [PATCH 3/5] fix standard reruns --- .../Activity Triggers/Standards/Push-CIPPStandard.ps1 | 4 ++-- Modules/CIPPCore/Public/Test-CIPPRerun.ps1 | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Standards/Push-CIPPStandard.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Standards/Push-CIPPStandard.ps1 index b48f9f42b954..758fac1e6add 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Standards/Push-CIPPStandard.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Standards/Push-CIPPStandard.ps1 @@ -14,9 +14,9 @@ function Push-CIPPStandard { Write-Information "We'll be running $FunctionName" if ($Standard -in @('IntuneTemplate', 'ConditionalAccessTemplate')) { - $API = "$Standard_$($Item.templateId)_$($Item.Settings.TemplateList.value)" + $API = "$($Standard)_$($Item.templateId)_$($Item.Settings.TemplateList.value)" } else { - $API = "$Standard_$($Item.templateId)" + $API = "$($Standard)_$($Item.templateId)" } $Rerun = Test-CIPPRerun -Type Standard -Tenant $Tenant -API $API diff --git a/Modules/CIPPCore/Public/Test-CIPPRerun.ps1 b/Modules/CIPPCore/Public/Test-CIPPRerun.ps1 index 021678392573..a329eb0a3d6a 100644 --- a/Modules/CIPPCore/Public/Test-CIPPRerun.ps1 +++ b/Modules/CIPPCore/Public/Test-CIPPRerun.ps1 @@ -19,10 +19,11 @@ function Test-CIPPRerun { $EstimatedNextRun = $CurrentUnixTime + $EstimatedDifference try { - $RerunData = Get-CIPPAzDataTableEntity @RerunTable -filter "PartitionKey eq '$($TenantFilter)' and RowKey eq '$($Type)_$($API)'" + $RerunData = Get-CIPPAzDataTableEntity @RerunTable -filter "PartitionKey eq '$($TenantFilter)'" | Where-Object { $_.RowKey -match "^$($Type)_$($API)" } if ($ClearAll.IsPresent) { $AllRerunData = Get-CIPPAzDataTableEntity @RerunTable if ($AllRerunData) { + Write-Information "Clearing all rerun cache entries for $($Type)_$($API)" Remove-AzDataTableEntity @RerunTable -Entity $AllRerunData -Force } return $false From 6ea35ff9cf14a018899f3ab85dc5f67e3e7f5d4c Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 25 Nov 2025 13:13:04 -0500 Subject: [PATCH 4/5] Add TemplateId support to standards compare functions Updated Invoke-ListStandardsCompare and Set-CIPPStandardsCompareField to handle TemplateId filtering and storage. Standards can now be filtered by TemplateId in queries and TemplateId is included in stored entities for improved traceability. --- .../Standards/Invoke-ListStandardsCompare.ps1 | 35 ++++++------------- .../Public/Set-CIPPStandardsCompareField.ps1 | 2 ++ 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListStandardsCompare.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListStandardsCompare.ps1 index fdcb1f71aaa0..d2aaddf9a694 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListStandardsCompare.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListStandardsCompare.ps1 @@ -11,35 +11,19 @@ function Invoke-ListStandardsCompare { $Table = Get-CIPPTable -TableName 'CippStandardsReports' $TenantFilter = $Request.Query.tenantFilter + $TemplateFilter = $Request.Query.templateId + + $Filters = [system.collections.generic.list[string]]::new() if ($TenantFilter) { - $Table.Filter = "PartitionKey eq '{0}'" -f $TenantFilter + $Filters.Add("PartitionKey eq '{0}'" -f $TenantFilter) + } + if ($TemplateFilter) { + $Filters.Add("TemplateId eq '{0}'" -f $TemplateFilter) } + $Filter = $Filters -join ' and ' $Tenants = Get-Tenants -IncludeErrors - $Standards = Get-CIPPAzDataTableEntity @Table | Where-Object { $_.PartitionKey -in $Tenants.defaultDomainName } - - #in the results we have objects starting with "standards." All these have to be converted from JSON. Do not do this is its a boolean - <#$Results | ForEach-Object { - $Object = $_ - $Object.PSObject.Properties | ForEach-Object { - if ($_.Name -like 'standards_*') { - if ($_.Value -is [System.Boolean]) { - $_.Value = [bool]$_.Value - } elseif ($_.Value -like '*{*') { - $_.Value = ConvertFrom-Json -InputObject $_.Value -ErrorAction SilentlyContinue - } else { - $_.Value = [string]$_.Value - } - - $Key = $_.Name.replace('standards_', 'standards.') - $Key = $Key.replace('IntuneTemplate_', 'IntuneTemplate.') - $Key = $Key -replace '__', '-' - - $object | Add-Member -MemberType NoteProperty -Name $Key -Value $_.Value -Force - $object.PSObject.Properties.Remove($_.Name) - } - } - }#> + $Standards = Get-CIPPAzDataTableEntity @Table -Filter $Filter | Where-Object { $_.PartitionKey -in $Tenants.defaultDomainName } $TenantStandards = @{} $Results = [System.Collections.Generic.List[object]]::new() @@ -75,6 +59,7 @@ function Invoke-ListStandardsCompare { $TenantStandards[$Tenant][$FieldName] = @{ Value = $FieldValue LastRefresh = $Standard.TimeStamp.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') + TemplateId = $Standard.TemplateId } } diff --git a/Modules/CIPPCore/Public/Set-CIPPStandardsCompareField.ps1 b/Modules/CIPPCore/Public/Set-CIPPStandardsCompareField.ps1 index 96c23dbc9fc6..67c71db59ec2 100644 --- a/Modules/CIPPCore/Public/Set-CIPPStandardsCompareField.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPStandardsCompareField.ps1 @@ -23,12 +23,14 @@ function Set-CIPPStandardsCompareField { try { if ($Existing) { $Existing.Value = $FieldValue + $Existing | Add-Member -NotePropertyName TemplateId -NotePropertyValue $script:StandardInfo.StandardTemplateId -Force Add-CIPPAzDataTableEntity @Table -Entity $Existing -Force } else { $Result = [PSCustomObject]@{ PartitionKey = [string]$TenantName.defaultDomainName RowKey = [string]$FieldName Value = $FieldValue + TemplateId = $script:StandardInfo.StandardTemplateId } Add-CIPPAzDataTableEntity @Table -Entity $Result -Force } From 56cc68ed368af1b65c8b15fd95fe23d7c3749d8e Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 25 Nov 2025 22:22:39 +0100 Subject: [PATCH 5/5] version up --- host.json | 2 +- version_latest.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/host.json b/host.json index 2cf91f7b1f33..d3491c33973c 100644 --- a/host.json +++ b/host.json @@ -16,7 +16,7 @@ "distributedTracingEnabled": false, "version": "None" }, - "defaultVersion": "8.7.1", + "defaultVersion": "8.7.2", "versionMatchStrategy": "Strict", "versionFailureStrategy": "Fail" } diff --git a/version_latest.txt b/version_latest.txt index d139a75408e9..dba07fcdeb4b 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -8.7.1 +8.7.2