modules/Devolutions.CIEM.PSU/Pages/New-CIEMConfigPage.ps1
|
function New-CIEMConfigPage { <# .SYNOPSIS Creates the CIEM Configuration page. .PARAMETER Navigation Array of UDListItem components for sidebar navigation. #> [CmdletBinding()] param( [Parameter(Mandatory)] [object[]]$Navigation ) $ErrorActionPreference = 'Stop' New-UDPage -Name 'Configuration' -Url '/ciem/config' -Content { New-UDTypography -Text 'Configuration' -Variant 'h4' -Style @{ marginBottom = '20px'; marginTop = '10px' } New-UDTypography -Text 'Configure scheduled discovery and outbound notifications' -Variant 'subtitle1' -Style @{ marginBottom = '30px'; color = '#666' } New-UDElement -Tag 'div' -Id 'scheduledDiscoveryWrapper' -Content { New-UDCard -Title 'Scheduled Discovery' -Content { $scheduleRows = @(Devolutions.CIEM\Get-CIEMAzureDiscoverySchedule) $schedule = $scheduleRows | Select-Object -First 1 $selectedScope = if ($schedule) { [string]$schedule.Scope } else { 'All' } $selectedCadence = if (-not $schedule -or $schedule.Cron -eq '0 2 * * *') { 'daily' } elseif ($schedule.Cron -eq '0 2 * * 1') { 'weekly' } else { throw "Unsupported scheduled discovery cron '$($schedule.Cron)'." } $scheduleEnabled = if ($schedule) { [bool]$schedule.Enabled } else { $false } New-UDGrid -Container -Spacing 2 -Content { New-UDGrid -Item -ExtraSmallSize 12 -MediumSize 4 -Content { New-UDSelect -Id 'azureDiscoveryScheduleCadence' -Label 'Cadence' -DefaultValue $selectedCadence -FullWidth -Option { New-UDSelectOption -Name 'Daily' -Value 'daily' New-UDSelectOption -Name 'Weekly' -Value 'weekly' } } New-UDGrid -Item -ExtraSmallSize 12 -MediumSize 4 -Content { New-UDSelect -Id 'azureDiscoveryScheduleScope' -Label 'Scope' -DefaultValue $selectedScope -FullWidth -Option { New-UDSelectOption -Name 'All' -Value 'All' New-UDSelectOption -Name 'ARM' -Value 'ARM' New-UDSelectOption -Name 'Entra' -Value 'Entra' } } New-UDGrid -Item -ExtraSmallSize 12 -MediumSize 2 -Content { New-UDSwitch -Id 'azureDiscoveryScheduleEnabled' -Label 'Enabled' -Checked $scheduleEnabled } New-UDGrid -Item -ExtraSmallSize 12 -MediumSize 2 -Content { New-UDButton -Id 'saveAzureDiscoveryScheduleBtn' -Text 'Save' -Variant 'contained' -Color 'primary' -ShowLoading -OnClick { try { $cadence = [string](Get-UDElement -Id 'azureDiscoveryScheduleCadence').value $scope = [string](Get-UDElement -Id 'azureDiscoveryScheduleScope').value $enabled = [bool](Get-UDElement -Id 'azureDiscoveryScheduleEnabled').checked $cron = switch ($cadence) { 'daily' { '0 2 * * *' } 'weekly' { '0 2 * * 1' } default { throw "Unsupported scheduled discovery cadence '$cadence'." } } Devolutions.CIEM\Set-CIEMAzureDiscoverySchedule -Scope $scope -Cron $cron -Enabled $enabled | Out-Null Sync-UDElement -Id 'azureDiscoveryScheduleStatus' Show-UDToast -Message 'Scheduled discovery saved.' -Duration 5000 -BackgroundColor '#4caf50' } catch { Devolutions.CIEM\Write-CIEMLog -Message "Save scheduled discovery failed: $($_.Exception.Message)" -Severity ERROR -Component 'PSU-ConfigPage' Show-UDToast -Message "Scheduled discovery save failed: $($_.Exception.Message)" -Duration 10000 -BackgroundColor '#f44336' } } } } New-UDDynamic -Id 'azureDiscoveryScheduleStatus' -Content { $currentSchedule = @(Devolutions.CIEM\Get-CIEMAzureDiscoverySchedule) | Select-Object -First 1 if ($currentSchedule) { $state = if ($currentSchedule.Enabled) { 'Enabled' } else { 'Disabled' } $lastStatus = if ($currentSchedule.LastStatus) { $currentSchedule.LastStatus } else { 'No scheduled run recorded' } New-UDTypography -Text "$state - $($currentSchedule.Scope) - $($currentSchedule.Cron) - $lastStatus" -Variant 'caption' -Style @{ color = '#666' } } else { New-UDTypography -Text 'Disabled - no schedule configured' -Variant 'caption' -Style @{ color = '#666' } } } } } New-UDCard -Title 'Notification Channels' -Content { New-UDElement -Tag 'div' -Id 'availableNotificationChannelTypes' -Attributes @{ style = @{ marginBottom = '18px' } } -Content { New-UDTypography -Text 'Available Channel Types' -Variant 'subtitle2' -Style @{ marginBottom = '8px'; color = '#555' } New-UDStack -Direction 'row' -Spacing 1 -Content { New-UDButton -Id 'addEmailNotificationChannelBtn' -Text 'Add Email Channel' -Variant 'outlined' -Color 'primary' -OnClick { $notificationChannel = @(Devolutions.CIEM\Get-CIEMNotificationChannel -Id 'email-default') | Select-Object -First 1 Set-UDElement -Id 'notificationChannelEditorPane' -Content { New-UDElement -Tag 'div' -Attributes @{ style = @{ border = '1px solid #d7dde5'; borderRadius = '6px'; padding = '16px'; marginBottom = '18px'; backgroundColor = '#fafbfc' } } -Content { New-UDTypography -Text 'Email Channel' -Variant 'h6' -Style @{ marginBottom = '12px' } New-UDGrid -Container -Spacing 2 -Content { New-UDGrid -Item -ExtraSmallSize 12 -MediumSize 6 -Content { New-UDTextbox -Id 'notificationFromAddress' -Label 'From Address' -Value $notificationChannel.FromAddress -FullWidth -Placeholder 'ciem@example.com' } New-UDGrid -Item -ExtraSmallSize 12 -MediumSize 6 -Content { New-UDTextbox -Id 'notificationToRecipients' -Label 'To Recipients' -Value (@($notificationChannel.ToRecipients) -join ', ') -FullWidth -Placeholder 'security@example.com, it@example.com' } } New-UDStack -Direction 'row' -Spacing 2 -Content { New-UDButton -Id 'saveNotificationsBtn' -Text 'Save' -Variant 'contained' -Color 'primary' -ShowLoading -OnClick { try { $parseRecipients = { param([string]$RecipientText) if ([string]::IsNullOrWhiteSpace($RecipientText)) { return } foreach ($recipient in ($RecipientText -split ',')) { $trimmedRecipient = $recipient.Trim() if (-not [string]::IsNullOrWhiteSpace($trimmedRecipient)) { $trimmedRecipient } } } $toRecipients = [string[]]@(& $parseRecipients ([string](Get-UDElement -Id 'notificationToRecipients').value)) Devolutions.CIEM\Set-CIEMNotificationChannel ` -Enabled $true ` -FromAddress ([string](Get-UDElement -Id 'notificationFromAddress').value) ` -ToRecipients $toRecipients | Out-Null Set-UDElement -Id 'notificationChannelEditorPane' -Content {} Sync-UDElement -Id 'notificationChannelsTableRegion' Show-UDToast -Message 'Notifications saved.' -Duration 5000 -BackgroundColor '#4caf50' } catch { Devolutions.CIEM\Write-CIEMLog -Message "Save notifications failed: $($_.Exception.Message)" -Severity ERROR -Component 'PSU-ConfigPage' Show-UDToast -Message "Notification save failed: $($_.Exception.Message)" -Duration 10000 -BackgroundColor '#f44336' } } New-UDButton -Id 'cancelNotificationChannelEditBtn' -Text 'Cancel' -Variant 'outlined' -OnClick { Set-UDElement -Id 'notificationChannelEditorPane' -Content {} } } } } } } } New-UDElement -Tag 'div' -Id 'notificationChannelEditorPane' New-UDDynamic -Id 'notificationChannelsTableRegion' -Content { $channels = @(Devolutions.CIEM\Get-CIEMNotificationChannel) $channelRows = @(foreach ($channel in $channels) { [PSCustomObject]@{ Id = [string]$channel.Id Name = [string]$channel.Name Type = [string]$channel.Type Enabled = [bool]$channel.Enabled Status = if ($channel.Enabled) { 'Enabled' } else { 'Disabled' } From = [string]$channel.FromAddress Recipients = (@($channel.ToRecipients) -join ', ') CcRecipients = (@($channel.CcRecipients) -join ', ') BccRecipients = (@($channel.BccRecipients) -join ', ') UpdatedAt = [string]$channel.UpdatedAt } }) New-UDTable -Id 'notificationChannelsTable' -Data $channelRows -Columns @( New-UDTableColumn -Property 'Name' -Title 'Channel' New-UDTableColumn -Property 'Type' -Title 'Type' New-UDTableColumn -Property 'Status' -Title 'Status' New-UDTableColumn -Property 'From' -Title 'From' New-UDTableColumn -Property 'Recipients' -Title 'Recipients' New-UDTableColumn -Property 'Actions' -Title 'Actions' -Render { New-UDButton -Id "editNotificationChannel_$($EventData.Id)" -Text 'Edit' -Variant 'outlined' -OnClick { $notificationChannel = @(Devolutions.CIEM\Get-CIEMNotificationChannel -Id $EventData.Id) | Select-Object -First 1 Show-UDModal -Header { New-UDTypography -Text 'Notification Channel Details' -Variant 'h6' } -Content { New-UDGrid -Container -Spacing 2 -Content { New-UDGrid -Item -ExtraSmallSize 12 -MediumSize 3 -Content { New-UDSwitch -Id 'notificationChannelEnabled' -Label 'Enabled' -Checked ([bool]$notificationChannel.Enabled) } New-UDGrid -Item -ExtraSmallSize 12 -MediumSize 9 -Content { New-UDTextbox -Id 'notificationFromAddress' -Label 'From Address' -Value $notificationChannel.FromAddress -FullWidth -Placeholder 'ciem@example.com' } New-UDGrid -Item -ExtraSmallSize 12 -Content { New-UDTextbox -Id 'notificationToRecipients' -Label 'To Recipients' -Value (@($notificationChannel.ToRecipients) -join ', ') -FullWidth -Placeholder 'security@example.com, it@example.com' } New-UDGrid -Item -ExtraSmallSize 12 -MediumSize 6 -Content { New-UDTextbox -Id 'notificationCcRecipients' -Label 'Cc Recipients' -Value (@($notificationChannel.CcRecipients) -join ', ') -FullWidth -Placeholder 'manager@example.com' } New-UDGrid -Item -ExtraSmallSize 12 -MediumSize 6 -Content { New-UDTextbox -Id 'notificationBccRecipients' -Label 'Bcc Recipients' -Value (@($notificationChannel.BccRecipients) -join ', ') -FullWidth -Placeholder 'audit@example.com' } } } -Footer { New-UDStack -Direction 'row' -Spacing 2 -Content { New-UDButton -Id 'saveNotificationsBtn' -Text 'Save' -Variant 'contained' -Color 'primary' -ShowLoading -OnClick { try { $parseRecipients = { param([string]$RecipientText) if ([string]::IsNullOrWhiteSpace($RecipientText)) { return } foreach ($recipient in ($RecipientText -split ',')) { $trimmedRecipient = $recipient.Trim() if (-not [string]::IsNullOrWhiteSpace($trimmedRecipient)) { $trimmedRecipient } } } $toRecipients = [string[]]@(& $parseRecipients ([string](Get-UDElement -Id 'notificationToRecipients').value)) $ccRecipients = [string[]]@(& $parseRecipients ([string](Get-UDElement -Id 'notificationCcRecipients').value)) $bccRecipients = [string[]]@(& $parseRecipients ([string](Get-UDElement -Id 'notificationBccRecipients').value)) Devolutions.CIEM\Set-CIEMNotificationChannel ` -Enabled ([bool](Get-UDElement -Id 'notificationChannelEnabled').checked) ` -FromAddress ([string](Get-UDElement -Id 'notificationFromAddress').value) ` -ToRecipients $toRecipients ` -CcRecipients $ccRecipients ` -BccRecipients $bccRecipients | Out-Null Hide-UDModal Sync-UDElement -Id 'notificationChannelsTableRegion' Show-UDToast -Message 'Notifications saved.' -Duration 5000 -BackgroundColor '#4caf50' } catch { Devolutions.CIEM\Write-CIEMLog -Message "Save notifications failed: $($_.Exception.Message)" -Severity ERROR -Component 'PSU-ConfigPage' Show-UDToast -Message "Notification save failed: $($_.Exception.Message)" -Duration 10000 -BackgroundColor '#f44336' } } New-UDButton -Id 'cancelNotificationChannelEditBtn' -Text 'Cancel' -Variant 'outlined' -OnClick { Hide-UDModal } } } -FullWidth -MaxWidth 'md' -Persistent } } ) -Dense -OnRowExpand { New-UDStack -Spacing 1 -Content { New-UDTypography -Text "Status: $($EventData.Status)" -Variant 'caption' New-UDTypography -Text "Cc: $($EventData.CcRecipients)" -Variant 'caption' New-UDTypography -Text "Bcc: $($EventData.BccRecipients)" -Variant 'caption' New-UDTypography -Text "Updated: $($EventData.UpdatedAt)" -Variant 'caption' } } } } -Style @{ marginTop = '24px' } } -Navigation $Navigation -NavigationLayout permanent } |