1010using System . Windows ;
1111using System . Windows . Controls ;
1212using Microsoft . Data . SqlClient ;
13+ using PerformanceMonitorDashboard . Helpers ;
1314using PerformanceMonitorDashboard . Models ;
1415using PerformanceMonitorDashboard . Services ;
1516
@@ -51,11 +52,18 @@ public AddServerDialog(ServerConnection existingServer)
5152 } ;
5253 TrustServerCertificateCheckBox . IsChecked = existingServer . TrustServerCertificate ;
5354
54- if ( existingServer . UseWindowsAuth )
55+ if ( existingServer . AuthenticationType == AuthenticationTypes . EntraMFA )
5556 {
56- WindowsAuthRadio . IsChecked = true ;
57+ EntraMfaAuthRadio . IsChecked = true ;
58+
59+ var credentialService = new CredentialService ( ) ;
60+ var cred = credentialService . GetCredential ( existingServer . Id ) ;
61+ if ( cred . HasValue && ! string . IsNullOrEmpty ( cred . Value . Username ) )
62+ {
63+ EntraMfaUsernameBox . Text = cred . Value . Username ;
64+ }
5765 }
58- else
66+ else if ( existingServer . AuthenticationType == AuthenticationTypes . SqlServer )
5967 {
6068 SqlAuthRadio . IsChecked = true ;
6169
@@ -67,13 +75,23 @@ public AddServerDialog(ServerConnection existingServer)
6775 PasswordBox . Password = cred . Value . Password ;
6876 }
6977 }
78+ else
79+ {
80+ WindowsAuthRadio . IsChecked = true ;
81+ }
7082 }
7183
7284 private void AuthType_Changed ( object sender , RoutedEventArgs e )
7385 {
74- if ( SqlAuthPanel != null )
86+ if ( SqlAuthPanel != null && EntraMfaPanel != null )
7587 {
76- SqlAuthPanel . IsEnabled = SqlAuthRadio . IsChecked == true ;
88+ SqlAuthPanel . Visibility = SqlAuthRadio . IsChecked == true
89+ ? System . Windows . Visibility . Visible
90+ : System . Windows . Visibility . Collapsed ;
91+
92+ EntraMfaPanel . Visibility = EntraMfaAuthRadio . IsChecked == true
93+ ? System . Windows . Visibility . Visible
94+ : System . Windows . Visibility . Collapsed ;
7795 }
7896 }
7997
@@ -106,15 +124,27 @@ private SqlConnectionStringBuilder BuildConnectionBuilder()
106124 ApplicationName = "PerformanceMonitorDashboard" ,
107125 ConnectTimeout = 10 ,
108126 TrustServerCertificate = TrustServerCertificateCheckBox . IsChecked == true ,
109- Encrypt = ParseEncryptOption ( GetSelectedEncryptMode ( ) ) ,
110- IntegratedSecurity = WindowsAuthRadio . IsChecked == true
127+ Encrypt = ParseEncryptOption ( GetSelectedEncryptMode ( ) )
111128 } ;
112129
113- if ( WindowsAuthRadio . IsChecked != true )
130+ if ( WindowsAuthRadio . IsChecked == true )
131+ {
132+ builder . IntegratedSecurity = true ;
133+ }
134+ else if ( SqlAuthRadio . IsChecked == true )
114135 {
136+ builder . IntegratedSecurity = false ;
115137 builder . UserID = UsernameTextBox . Text . Trim ( ) ;
116138 builder . Password = PasswordBox . Password ;
117139 }
140+ else if ( EntraMfaAuthRadio . IsChecked == true )
141+ {
142+ builder . IntegratedSecurity = false ;
143+ builder . Authentication = SqlAuthenticationMethod . ActiveDirectoryInteractive ;
144+ var mfaUsername = EntraMfaUsernameBox . Text . Trim ( ) ;
145+ if ( ! string . IsNullOrEmpty ( mfaUsername ) )
146+ builder . UserID = mfaUsername ;
147+ }
118148
119149 return builder ;
120150 }
@@ -146,15 +176,19 @@ private bool ValidateInputs()
146176 return true ;
147177 }
148178
149- private async System . Threading . Tasks . Task < ( bool Connected , string ? ErrorMessage , string ? ServerVersion ) > RunConnectionTestAsync ( Button triggerButton )
179+ private async System . Threading . Tasks . Task < ( bool Connected , string ? ErrorMessage , bool MfaCancelled , string ? ServerVersion ) > RunConnectionTestAsync ( Button triggerButton )
150180 {
151181 triggerButton . IsEnabled = false ;
152182 SaveButton . IsEnabled = false ;
153- StatusText . Text = "Testing connection..." ;
183+
184+ StatusText . Text = EntraMfaAuthRadio . IsChecked == true
185+ ? "Testing connection — please complete authentication in the popup window..."
186+ : "Testing connection..." ;
154187 StatusText . Visibility = System . Windows . Visibility . Visible ;
155188
156189 bool connected = false ;
157190 string ? errorMessage = null ;
191+ bool mfaCancelled = false ;
158192 string ? serverVersion = null ;
159193 try
160194 {
@@ -169,6 +203,8 @@ private bool ValidateInputs()
169203 {
170204 connected = false ;
171205 errorMessage = ex . Message ;
206+ if ( EntraMfaAuthRadio . IsChecked == true && MfaAuthenticationHelper . IsMfaCancelledException ( ex ) )
207+ mfaCancelled = true ;
172208 }
173209 finally
174210 {
@@ -178,14 +214,14 @@ private bool ValidateInputs()
178214 StatusText . Visibility = System . Windows . Visibility . Collapsed ;
179215 }
180216
181- return ( connected , errorMessage , serverVersion ) ;
217+ return ( connected , errorMessage , mfaCancelled , serverVersion ) ;
182218 }
183219
184220 private async void TestConnection_Click ( object sender , RoutedEventArgs e )
185221 {
186222 if ( ! ValidateInputs ( ) ) return ;
187223
188- var ( connected , errorMessage , serverVersion ) = await RunConnectionTestAsync ( TestConnectionButton ) ;
224+ var ( connected , errorMessage , mfaCancelled , serverVersion ) = await RunConnectionTestAsync ( TestConnectionButton ) ;
189225
190226 if ( connected )
191227 {
@@ -199,12 +235,26 @@ private async void TestConnection_Click(object sender, RoutedEventArgs e)
199235 MessageBoxImage . Information
200236 ) ;
201237 }
238+ else if ( mfaCancelled )
239+ {
240+ MessageBox . Show (
241+ "Authentication was cancelled. Click Test to try again." ,
242+ "Authentication Cancelled" ,
243+ MessageBoxButton . OK ,
244+ MessageBoxImage . Warning
245+ ) ;
246+ }
202247 else
203248 {
204249 var detail = errorMessage != null ? $ "\n \n Error: { errorMessage } " : string . Empty ;
205250 MessageBox . Show (
206- $ "Could not connect to { ServerNameTextBox . Text } .{ detail } ",
207- "Connection Failed" ,
251+ $ "Could not connect to { ServerNameTextBox . Text } .{ detail } \n \n Please check:\n " +
252+ "• Server name/address is correct\n " +
253+ "• Server is accessible from this machine\n " +
254+ "• Firewall allows SQL Server connections\n " +
255+ "• SQL Server service is running\n " +
256+ "• You have the 'PerformanceMonitor' database and access to it" ,
257+ "Connection Test Failed" ,
208258 MessageBoxButton . OK ,
209259 MessageBoxImage . Error
210260 ) ;
@@ -215,10 +265,21 @@ private async void Save_Click(object sender, RoutedEventArgs e)
215265 {
216266 if ( ! ValidateInputs ( ) ) return ;
217267
218- var ( connected , errorMessage , _) = await RunConnectionTestAsync ( SaveButton ) ;
268+ var ( connected , errorMessage , mfaCancelled , _) = await RunConnectionTestAsync ( SaveButton ) ;
219269
220270 if ( ! connected )
221271 {
272+ if ( mfaCancelled )
273+ {
274+ MessageBox . Show (
275+ "Authentication was cancelled. Click Save to try again, or Cancel to abort." ,
276+ "Authentication Cancelled" ,
277+ MessageBoxButton . OK ,
278+ MessageBoxImage . Warning
279+ ) ;
280+ return ;
281+ }
282+
222283 var detail = errorMessage != null ? $ "\n \n Error: { errorMessage } " : string . Empty ;
223284 var result = MessageBox . Show (
224285 $ "Could not connect to { ServerNameTextBox . Text } .{ detail } \n \n " +
@@ -232,6 +293,27 @@ private async void Save_Click(object sender, RoutedEventArgs e)
232293 return ;
233294 }
234295
296+ // Determine authentication type and credentials
297+ string authenticationType ;
298+ if ( WindowsAuthRadio . IsChecked == true )
299+ {
300+ authenticationType = AuthenticationTypes . Windows ;
301+ Username = null ;
302+ Password = null ;
303+ }
304+ else if ( EntraMfaAuthRadio . IsChecked == true )
305+ {
306+ authenticationType = AuthenticationTypes . EntraMFA ;
307+ Username = EntraMfaUsernameBox . Text . Trim ( ) ;
308+ Password = null ;
309+ }
310+ else
311+ {
312+ authenticationType = AuthenticationTypes . SqlServer ;
313+ Username = UsernameTextBox . Text . Trim ( ) ;
314+ Password = PasswordBox . Password ;
315+ }
316+
235317 // Use server name as display name if not provided
236318 var displayName = string . IsNullOrWhiteSpace ( DisplayNameTextBox . Text )
237319 ? ServerNameTextBox . Text . Trim ( )
@@ -241,7 +323,7 @@ private async void Save_Click(object sender, RoutedEventArgs e)
241323 {
242324 ServerConnection . DisplayName = displayName ;
243325 ServerConnection . ServerName = ServerNameTextBox . Text . Trim ( ) ;
244- ServerConnection . UseWindowsAuth = WindowsAuthRadio . IsChecked == true ;
326+ ServerConnection . AuthenticationType = authenticationType ;
245327 ServerConnection . Description = DescriptionTextBox . Text . Trim ( ) ;
246328 ServerConnection . IsFavorite = IsFavoriteCheckBox . IsChecked == true ;
247329 ServerConnection . EncryptMode = GetSelectedEncryptMode ( ) ;
@@ -253,7 +335,7 @@ private async void Save_Click(object sender, RoutedEventArgs e)
253335 {
254336 DisplayName = displayName ,
255337 ServerName = ServerNameTextBox . Text . Trim ( ) ,
256- UseWindowsAuth = WindowsAuthRadio . IsChecked == true ,
338+ AuthenticationType = authenticationType ,
257339 Description = DescriptionTextBox . Text . Trim ( ) ,
258340 IsFavorite = IsFavoriteCheckBox . IsChecked == true ,
259341 CreatedDate = DateTime . Now ,
@@ -263,12 +345,6 @@ private async void Save_Click(object sender, RoutedEventArgs e)
263345 } ;
264346 }
265347
266- if ( SqlAuthRadio . IsChecked == true )
267- {
268- Username = UsernameTextBox . Text . Trim ( ) ;
269- Password = PasswordBox . Password ;
270- }
271-
272348 DialogResult = true ;
273349 Close ( ) ;
274350 }
0 commit comments