Skip to content

Commit 8271f4c

Browse files
authored
Merge pull request #654 from KelvinTegelaar/dev
[pull] dev from KelvinTegelaar:dev
2 parents 602a288 + 3338a42 commit 8271f4c

File tree

6 files changed

+412
-18
lines changed

6 files changed

+412
-18
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
function Invoke-AddTestReport {
2+
<#
3+
.FUNCTIONALITY
4+
Entrypoint
5+
.ROLE
6+
CIPP.Dashboard.Read
7+
#>
8+
[CmdletBinding()]
9+
param($Request, $TriggerMetadata)
10+
11+
$APIName = $TriggerMetadata.FunctionName
12+
Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API $APIName -message 'Accessed this API' -Sev 'Debug'
13+
14+
try {
15+
$Body = $Request.Body
16+
17+
# Validate required fields
18+
if ([string]::IsNullOrEmpty($Body.name)) {
19+
throw 'Report name is required'
20+
}
21+
22+
# Generate a unique ID
23+
$ReportId = New-Guid
24+
$IdentityTests = $Body.IdentityTests ? ($Body.IdentityTests.value | ConvertTo-Json) : '[]'
25+
$DevicesTests = $Body.DevicesTests ? ($Body.DevicesTests.value | ConvertTo-Json) : '[]'
26+
27+
# Create report object
28+
$Report = [PSCustomObject]@{
29+
PartitionKey = 'Report'
30+
RowKey = [string]$ReportId
31+
name = [string]$Body.name
32+
description = [string]$Body.description
33+
version = '1.0'
34+
IdentityTests = [string]$IdentityTests
35+
DevicesTests = [string]$DevicesTests
36+
CreatedAt = [string](Get-Date).ToString('o')
37+
}
38+
39+
# Save to table
40+
$Table = Get-CippTable -tablename 'CippReportTemplates'
41+
Add-CIPPAzDataTableEntity -Entity $Report @Table
42+
$Body = [PSCustomObject]@{
43+
Results = 'Successfully created custom report'
44+
ReportId = $ReportId
45+
}
46+
$StatusCode = [HttpStatusCode]::OK
47+
} catch {
48+
$ErrorMessage = Get-CippException -Exception $_
49+
Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API $APIName -message "Failed to create report: $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage
50+
$Body = [PSCustomObject]@{
51+
Results = "Failed to create report: $($ErrorMessage.NormalizedError)"
52+
}
53+
$StatusCode = [HttpStatusCode]::BadRequest
54+
}
55+
56+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
57+
StatusCode = $StatusCode
58+
Body = ConvertTo-Json -InputObject $Body -Depth 10
59+
})
60+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
function Invoke-DeleteTestReport {
2+
<#
3+
.FUNCTIONALITY
4+
Entrypoint
5+
.ROLE
6+
CIPP.Dashboard.Read
7+
#>
8+
[CmdletBinding()]
9+
param($Request, $TriggerMetadata)
10+
11+
$APIName = $TriggerMetadata.FunctionName
12+
Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API $APIName -message 'Accessed this API' -Sev 'Debug'
13+
14+
try {
15+
$ReportId = $Request.Body.ReportId
16+
$Table = Get-CippTable -tablename 'CippReportTemplates'
17+
$ExistingReport = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq '$ReportId'"
18+
Remove-AzDataTableEntity @Table -Entity $ExistingReport
19+
20+
$Body = [PSCustomObject]@{
21+
Results = 'Successfully deleted custom report'
22+
}
23+
$StatusCode = [HttpStatusCode]::OK
24+
} catch {
25+
$ErrorMessage = Get-CippException -Exception $_
26+
Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API $APIName -message "Failed to delete report: $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage
27+
$Body = [PSCustomObject]@{
28+
Results = "Failed to delete report: $($ErrorMessage.NormalizedError)"
29+
}
30+
$StatusCode = [HttpStatusCode]::BadRequest
31+
}
32+
33+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
34+
StatusCode = $StatusCode
35+
Body = ConvertTo-Json -InputObject $Body -Depth 10
36+
})
37+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
function Invoke-ListAvailableTests {
2+
<#
3+
.FUNCTIONALITY
4+
Entrypoint
5+
.ROLE
6+
CIPP.Dashboard.Read
7+
#>
8+
[CmdletBinding()]
9+
param($Request, $TriggerMetadata)
10+
11+
$APIName = $TriggerMetadata.FunctionName
12+
Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API $APIName -message 'Accessed this API' -Sev 'Debug'
13+
14+
try {
15+
# Get all test folders
16+
$TestFolders = Get-ChildItem 'Modules\CIPPCore\Public\Tests' -Directory
17+
18+
# Build identity tests array
19+
$IdentityTests = foreach ($TestFolder in $TestFolders) {
20+
$IdentityTestFiles = Get-ChildItem "$($TestFolder.FullName)\Identity\*.ps1" -ErrorAction SilentlyContinue
21+
foreach ($TestFile in $IdentityTestFiles) {
22+
# Extract test ID from filename (e.g., Invoke-CippTestZTNA21772.ps1 -> ZTNA21772)
23+
if ($TestFile.BaseName -match 'Invoke-CippTest(.+)$') {
24+
$TestId = $Matches[1]
25+
26+
# Try to get test metadata from the file
27+
$TestContent = Get-Content $TestFile.FullName -Raw
28+
$TestName = $TestId
29+
30+
# Try to extract Synopsis from comment-based help
31+
if ($TestContent -match '\.SYNOPSIS\s+(.+?)(?=\s+\.|\s+#>|\s+\[)') {
32+
$TestName = $Matches[1].Trim()
33+
}
34+
35+
[PSCustomObject]@{
36+
id = $TestId
37+
name = $TestName
38+
category = 'Identity'
39+
testFolder = $TestFolder.Name
40+
}
41+
}
42+
}
43+
}
44+
45+
# Build device tests array
46+
$DevicesTests = foreach ($TestFolder in $TestFolders) {
47+
$DeviceTestFiles = Get-ChildItem "$($TestFolder.FullName)\Devices\*.ps1" -ErrorAction SilentlyContinue
48+
foreach ($TestFile in $DeviceTestFiles) {
49+
if ($TestFile.BaseName -match 'Invoke-CippTest(.+)$') {
50+
$TestId = $Matches[1]
51+
52+
$TestContent = Get-Content $TestFile.FullName -Raw
53+
$TestName = $TestId
54+
55+
if ($TestContent -match '\.SYNOPSIS\s+(.+?)(?=\s+\.|\s+#>|\s+\[)') {
56+
$TestName = $Matches[1].Trim()
57+
}
58+
59+
[PSCustomObject]@{
60+
id = $TestId
61+
name = $TestName
62+
category = 'Devices'
63+
testFolder = $TestFolder.Name
64+
}
65+
}
66+
}
67+
}
68+
69+
$Body = [PSCustomObject]@{
70+
IdentityTests = $IdentityTests
71+
DevicesTests = $DevicesTests
72+
}
73+
$StatusCode = [HttpStatusCode]::OK
74+
} catch {
75+
$ErrorMessage = Get-CippException -Exception $_
76+
Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API $APIName -message "Failed to list available tests: $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage
77+
$Body = [PSCustomObject]@{
78+
Results = "Failed to list available tests: $($ErrorMessage.NormalizedError)"
79+
}
80+
$StatusCode = [HttpStatusCode]::BadRequest
81+
}
82+
83+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
84+
StatusCode = $StatusCode
85+
Body = ConvertTo-Json -InputObject $Body -Depth 10
86+
})
87+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
function Invoke-ListTestReports {
2+
<#
3+
.SYNOPSIS
4+
Lists all available test reports from JSON files and database
5+
6+
.FUNCTIONALITY
7+
Entrypoint
8+
9+
.ROLE
10+
Tenant.Reports.Read
11+
#>
12+
[CmdletBinding()]
13+
param($Request, $TriggerMetadata)
14+
15+
$APIName = $TriggerMetadata.FunctionName
16+
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
17+
18+
try {
19+
# Get reports from JSON files in test folders
20+
$FileReports = Get-ChildItem 'Modules\CIPPCore\Public\Tests\*\report.json' -ErrorAction SilentlyContinue | ForEach-Object {
21+
try {
22+
$ReportContent = Get-Content $_.FullName -Raw | ConvertFrom-Json
23+
$FolderName = $_.Directory.Name
24+
[PSCustomObject]@{
25+
id = $FolderName.ToLower()
26+
name = $ReportContent.name ?? $FolderName
27+
description = $ReportContent.description ?? ''
28+
version = $ReportContent.version ?? '1.0'
29+
source = 'file'
30+
type = $FolderName
31+
}
32+
} catch {
33+
Write-LogMessage -API $APIName -message "Error reading report.json from $($_.Directory.Name): $($_.Exception.Message)" -sev Warning
34+
}
35+
}
36+
37+
# Get custom reports from CippReportTemplates table
38+
$ReportTable = Get-CippTable -tablename 'CippReportTemplates'
39+
$Filter = "PartitionKey eq 'Report'"
40+
$CustomReports = Get-CIPPAzDataTableEntity @ReportTable -Filter $Filter
41+
42+
$DatabaseReports = foreach ($Report in $CustomReports) {
43+
[PSCustomObject]@{
44+
id = $Report.RowKey
45+
name = $Report.Name ?? 'Custom Report'
46+
description = $Report.Description ?? ''
47+
version = $Report.Version ?? '1.0'
48+
source = 'database'
49+
type = 'custom'
50+
}
51+
}
52+
53+
$Reports = @($FileReports) + @($DatabaseReports)
54+
55+
$StatusCode = [HttpStatusCode]::OK
56+
$Body = @($Reports)
57+
58+
} catch {
59+
$ErrorMessage = Get-CippException -Exception $_
60+
Write-LogMessage -API $APIName -message "Error retrieving test reports: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage
61+
$StatusCode = [HttpStatusCode]::BadRequest
62+
$Body = @{ Error = $ErrorMessage.NormalizedError }
63+
}
64+
65+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
66+
StatusCode = $StatusCode
67+
Body = ConvertTo-Json -InputObject $Body -Depth 10 -Compress
68+
})
69+
}

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Invoke-ListTests.ps1

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,31 +27,62 @@ function Invoke-ListTests {
2727

2828
$IdentityTotal = 0
2929
$DevicesTotal = 0
30+
$IdentityTests = @()
31+
$DevicesTests = @()
3032

3133
if ($ReportId) {
32-
$ReportTable = Get-CippTable -tablename 'CippReportTemplates'
33-
$Filter = "PartitionKey eq 'ReportingTemplate' and RowKey eq '{0}'" -f $ReportId
34-
$ReportTemplate = Get-CIPPAzDataTableEntity @ReportTable -Filter $Filter
35-
36-
if ($ReportTemplate) {
37-
$IdentityTests = @()
38-
$DeviceTests = @()
39-
40-
if ($ReportTemplate.identityTests) {
41-
$IdentityTests = $ReportTemplate.identityTests | ConvertFrom-Json
42-
$IdentityTotal = @($IdentityTests).Count
34+
$ReportJsonFiles = Get-ChildItem 'Modules\CIPPCore\Public\Tests\*\report.json' -ErrorAction SilentlyContinue
35+
$ReportFound = $false
36+
37+
$MatchingReport = $ReportJsonFiles | Where-Object { $_.Directory.Name.ToLower() -eq $ReportId.ToLower() } | Select-Object -First 1
38+
39+
if ($MatchingReport) {
40+
try {
41+
$ReportContent = Get-Content $MatchingReport.FullName -Raw | ConvertFrom-Json
42+
if ($ReportContent.IdentityTests) {
43+
$IdentityTests = $ReportContent.IdentityTests
44+
$IdentityTotal = @($IdentityTests).Count
45+
}
46+
if ($ReportContent.DevicesTests) {
47+
$DevicesTests = $ReportContent.DevicesTests
48+
$DevicesTotal = @($DevicesTests).Count
49+
}
50+
$ReportFound = $true
51+
} catch {
52+
Write-LogMessage -API $APIName -tenant $TenantFilter -message "Error reading report.json: $($_.Exception.Message)" -sev Warning
4353
}
54+
}
4455

45-
if ($ReportTemplate.deviceTests) {
46-
$DeviceTests = $ReportTemplate.deviceTests | ConvertFrom-Json
47-
$DevicesTotal = @($DeviceTests).Count
56+
# Fall back to database if not found in JSON files
57+
if (-not $ReportFound) {
58+
$ReportTable = Get-CippTable -tablename 'CippReportTemplates'
59+
$Filter = "PartitionKey eq 'Report' and RowKey eq '{0}'" -f $ReportId
60+
$ReportTemplate = Get-CIPPAzDataTableEntity @ReportTable -Filter $Filter
61+
62+
if ($ReportTemplate) {
63+
if ($ReportTemplate.identityTests) {
64+
$IdentityTests = $ReportTemplate.identityTests | ConvertFrom-Json
65+
$IdentityTotal = @($IdentityTests).Count
66+
}
67+
68+
if ($ReportTemplate.DevicesTests) {
69+
$DevicesTests = $ReportTemplate.DevicesTests | ConvertFrom-Json
70+
$DevicesTotal = @($DevicesTests).Count
71+
}
72+
$ReportFound = $true
73+
} else {
74+
Write-LogMessage -API $APIName -tenant $TenantFilter -message "Report template '$ReportId' not found" -sev Warning
4875
}
76+
}
4977

50-
$AllReportTests = $IdentityTests + $DeviceTests
51-
$FilteredTests = $TestResultsData.TestResults | Where-Object { $AllReportTests -contains $_.RowKey }
78+
# Filter tests if report was found
79+
if ($ReportFound) {
80+
$AllReportTests = $IdentityTests + $DevicesTests
81+
# Use HashSet for O(1) lookup performance
82+
$TestLookup = [System.Collections.Generic.HashSet[string]]::new([string[]]$AllReportTests)
83+
$FilteredTests = $TestResultsData.TestResults | Where-Object { $TestLookup.Contains($_.RowKey) }
5284
$TestResultsData.TestResults = @($FilteredTests)
5385
} else {
54-
Write-LogMessage -API $APIName -tenant $TenantFilter -message "Report template '$ReportId' not found" -sev Warning
5586
$TestResultsData.TestResults = @()
5687
}
5788
} else {

0 commit comments

Comments
 (0)