public/dialogs/Show-UiCredentialDialog.ps1
|
function Show-UiCredentialDialog { <# .SYNOPSIS Shows a credential dialog for Get-Credential scenarios. .DESCRIPTION Displays a themed credential dialog with username and password fields. Returns a PSCredential object. Uses actual PasswordBox for secure input. .PARAMETER Caption The caption/title of the dialog. .PARAMETER Message The message to display. .PARAMETER UserName Pre-filled username (optional). .PARAMETER TargetName The target resource name (shown in message if no message provided). .EXAMPLE Show-UiCredentialDialog -Caption "Credentials Required" -Message "Enter credentials for server" #> [CmdletBinding()] param( [string]$Caption, [string]$Message, [string]$UserName, [string]$TargetName ) Write-Debug "Caption='$Caption' UserName='$UserName' TargetName='$TargetName'" $dialogTitle = if ($Caption) { $Caption } else { "Credential Required" } # Create dialog window using shared helper with Key icon $keyIcon = [PsUi.ModuleContext]::GetIcon('Key') $dlg = New-DialogWindow -Title $dialogTitle -Width 420 -AppIdSuffix 'CredentialDialog' -OverlayGlyph $keyIcon -TitleIcon $keyIcon $window = $dlg.Window $contentPanel = $dlg.ContentPanel $colors = $dlg.Colors # Button panel at bottom $buttonPanel = [System.Windows.Controls.StackPanel]@{ Orientation = 'Horizontal' HorizontalAlignment = 'Right' Margin = [System.Windows.Thickness]::new(0, 12, 0, 0) } [System.Windows.Controls.DockPanel]::SetDock($buttonPanel, 'Bottom') [void]$contentPanel.Children.Add($buttonPanel) # Main content stack $mainStack = [System.Windows.Controls.StackPanel]::new() # Message text $displayMessage = if ($Message) { $Message } elseif ($TargetName) { "Enter credentials for: $TargetName" } else { "Enter your credentials" } $scrollViewer = [System.Windows.Controls.ScrollViewer]@{ VerticalScrollBarVisibility = 'Auto' HorizontalScrollBarVisibility = 'Disabled' Padding = [System.Windows.Thickness]::new(0, 0, 8, 0) MaxHeight = 300 } $msgText = [System.Windows.Controls.TextBlock]@{ Text = $displayMessage TextWrapping = 'Wrap' FontSize = 13 Foreground = ConvertTo-UiBrush $colors.ControlFg Margin = [System.Windows.Thickness]::new(0, 0, 0, 15) } $scrollViewer.Content = $msgText [void]$mainStack.Children.Add($scrollViewer) # Username field $userLabel = [System.Windows.Controls.TextBlock]@{ Text = "Username:" FontSize = 12 Foreground = ConvertTo-UiBrush $colors.ControlFg Margin = [System.Windows.Thickness]::new(0, 0, 0, 4) } [void]$mainStack.Children.Add($userLabel) $userTextBox = [System.Windows.Controls.TextBox]@{ Text = $UserName Height = 28 FontSize = 12 Padding = [System.Windows.Thickness]::new(2, 0, 2, 0) Margin = [System.Windows.Thickness]::new(0, 0, 0, 10) } Set-TextBoxStyle -TextBox $userTextBox [void]$mainStack.Children.Add($userTextBox) # Password field $passLabel = [System.Windows.Controls.TextBlock]@{ Text = "Password:" FontSize = 12 Foreground = ConvertTo-UiBrush $colors.ControlFg Margin = [System.Windows.Thickness]::new(0, 0, 0, 4) } [void]$mainStack.Children.Add($passLabel) $passwordBox = [System.Windows.Controls.PasswordBox]@{ Height = 28 FontSize = 12 Padding = [System.Windows.Thickness]::new(2, 0, 2, 0) Margin = [System.Windows.Thickness]::new(0) } Set-TextBoxStyle -PasswordBox $passwordBox [void]$mainStack.Children.Add($passwordBox) # Caps lock warning (Hidden, not Collapsed, to reserve space) $capsWarning = [System.Windows.Controls.StackPanel]@{ Orientation = 'Horizontal' Margin = [System.Windows.Thickness]::new(0, 6, 0, 0) Visibility = 'Hidden' } $capsIcon = [System.Windows.Controls.TextBlock]@{ Text = [PsUi.ModuleContext]::GetIcon('Alert') FontFamily = [System.Windows.Media.FontFamily]::new('Segoe MDL2 Assets') FontSize = 12 Foreground = ConvertTo-UiBrush $colors.Warning Margin = [System.Windows.Thickness]::new(0, 0, 6, 0) VerticalAlignment = 'Center' } $capsText = [System.Windows.Controls.TextBlock]@{ Text = 'Caps Lock is on' FontSize = 11 Foreground = ConvertTo-UiBrush $colors.Warning VerticalAlignment = 'Center' } [void]$capsWarning.Children.Add($capsIcon) [void]$capsWarning.Children.Add($capsText) [void]$mainStack.Children.Add($capsWarning) # Caps lock indicator update logic $updateCapsLock = { param($warningPanel) $isCapsOn = [System.Windows.Input.Keyboard]::IsKeyToggled([System.Windows.Input.Key]::CapsLock) $warningPanel.Visibility = if ($isCapsOn) { 'Visible' } else { 'Hidden' } } $capturedCapsWarning = $capsWarning $passwordBox.Add_GotFocus({ & $updateCapsLock $capturedCapsWarning }.GetNewClosure()) $passwordBox.Add_PreviewKeyDown({ & $updateCapsLock $capturedCapsWarning }.GetNewClosure()) $window.Add_ContentRendered({ & $updateCapsLock $capturedCapsWarning }.GetNewClosure()) [void]$contentPanel.Children.Add($mainStack) # OK button (accent) $okBtn = [System.Windows.Controls.Button]@{ Content = "OK" Width = 80 Height = 28 Margin = [System.Windows.Thickness]::new(4, 0, 0, 0) IsDefault = $true } Set-ButtonStyle -Button $okBtn -Accent $okBtn.Add_Click({ $window.Tag = 'OK'; $window.Close() }) [void]$buttonPanel.Children.Add($okBtn) # Cancel button $cancelBtn = [System.Windows.Controls.Button]@{ Content = "Cancel" Width = 80 Height = 28 Margin = [System.Windows.Thickness]::new(4, 0, 0, 0) IsCancel = $true } Set-ButtonStyle -Button $cancelBtn $cancelBtn.Add_Click({ $window.Tag = $null; $window.Close() }) [void]$buttonPanel.Children.Add($cancelBtn) # Focus username box (not password - causes async issues) Initialize-UiWindowLoaded -Window $window -FocusElement $userTextBox Set-UiDialogPosition -Dialog $window Write-Debug "Showing modal dialog" [void]$window.ShowDialog() if ($window.Tag -eq 'OK') { $username = $userTextBox.Text if ([string]::IsNullOrWhiteSpace($username)) { return $null } $securePassword = $passwordBox.SecurePassword try { $credential = [System.Management.Automation.PSCredential]::new($username, $securePassword) Write-Debug "Result: Credential for '$username'" return $credential } catch { Write-Debug "Result: <error creating credential>" return $null } } Write-Debug "Result: <cancelled>" return $null } |