1 | using System;
|
---|
2 | using System.Collections.Generic;
|
---|
3 | using System.Text;
|
---|
4 | using IndianHealthService.BMXNet.WinForm.Configuration;
|
---|
5 | using IndianHealthService.BMXNet.Net;
|
---|
6 | using System.Security.Principal;
|
---|
7 | using IndianHealthService.BMXNet.Forms;
|
---|
8 | using IndianHealthService.BMXNet.WinForm.Forms;
|
---|
9 | using System.Windows.Forms;
|
---|
10 | using IndianHealthService.BMXNet.WinForm.Model;
|
---|
11 |
|
---|
12 | namespace IndianHealthService.BMXNet.WinForm
|
---|
13 | {
|
---|
14 | /// <summary>
|
---|
15 | /// This class models the workflow of the LoginProcess. It correographs UI and non-UI
|
---|
16 | /// login methods, login cancelling, management dialogs, and provides hooks (events) to
|
---|
17 | /// customize the login workflow.
|
---|
18 | /// </summary>
|
---|
19 | /// <example>
|
---|
20 | /// See the SDK for other examples.
|
---|
21 | /// <code>
|
---|
22 | /// this.Framework = WinFramework.CreateWithNetworkBroker(true);
|
---|
23 | /// this.Framework.LoadSettings(LocalPersistentStore.CreateIn(Environment.SpecialFolder.LocalApplicationData, EntryAssemblyInfo.AssemblyCompany + "/" + EntryAssemblyInfo.AssemblyProduct, false), "settings");
|
---|
24 | /// this.Framework.LoadConnectionSpecs(LocalPersistentStore.CreateIn(Environment.SpecialFolder.LocalApplicationData, EntryAssemblyInfo.AssemblyCompany + "/" + EntryAssemblyInfo.AssemblyProduct, false), "connectiosn");
|
---|
25 | /// LoginProcess login = this.Framework.CreateLoginProcess();
|
---|
26 | ///
|
---|
27 | /// //Attempt a non-UI WindowsAuth if and only if there is a default connection with WindowsAuth
|
---|
28 | /// //Of course, an application can set its own policy of when to AttemptWindowsAuthLogin()
|
---|
29 | ///
|
---|
30 | /// if (login.HasDefaultConnectionWithUseWindowsAuth)
|
---|
31 | /// {
|
---|
32 | /// login.AttemptWindowsAuthLogin();
|
---|
33 | /// }
|
---|
34 | ///
|
---|
35 | /// //If not attempted yet, i.e. skipped the AttemptWindowsAuthLogin(), or was unsuccessul, try and UI login
|
---|
36 | /// if (!login.WasLoginAttempted || !login.WasSuccessful)
|
---|
37 | /// {
|
---|
38 | /// login.AttemptUserInputLogin(IndianHealthService.BMXNet.Util.EntryAssemblyInfo.AssemblyTitle+" Login", 3,!this.Framework.BootStrapSettings.Get("lockedit",false), this);
|
---|
39 | /// }
|
---|
40 | ///
|
---|
41 | /// //If the login process was unable to login after the max tries (or fow other configuration reasons), exit the application
|
---|
42 | /// if (!login.WasSuccessful)
|
---|
43 | /// {
|
---|
44 | /// this.Close();
|
---|
45 | /// return;
|
---|
46 | /// }
|
---|
47 | ///
|
---|
48 | /// // Making sure that the user's division is set. Can use AttemptUserInputSetDivision() or the application can devise another solution
|
---|
49 | /// if ((this.Framework.User.Division == null) && !this.Framework.AttemptUserInputSetDivision("Set Initial Division", this))
|
---|
50 | /// {
|
---|
51 | /// this.Close();
|
---|
52 | /// return;
|
---|
53 | /// }
|
---|
54 | ///
|
---|
55 | /// // Logged in with valid user and division
|
---|
56 | /// this.RemoteSession = this.Framework.PrimaryRemoteSession;
|
---|
57 | /// </code></example>
|
---|
58 | public class LoginProcess
|
---|
59 | {
|
---|
60 | /// <summary>
|
---|
61 | /// Triggered before every login attempt. See <see cref="AttemptingLoginEventArgs"/> for details .
|
---|
62 | /// </summary>
|
---|
63 | public event EventHandler<AttemptingLoginEventArgs> AttemptingLogin;
|
---|
64 |
|
---|
65 | /// <summary>
|
---|
66 | /// Triggered after every login attempt. See <see cref="LoginAttemptedEventArgs"/> for details .
|
---|
67 | /// </summary>
|
---|
68 | public event EventHandler<LoginAttemptedEventArgs> LoginAttempted;
|
---|
69 |
|
---|
70 | private bool _cancel = false;
|
---|
71 |
|
---|
72 | /// <summary>
|
---|
73 | /// During a LoginAttempted the LoginProcess can be Cancelled by setting Cancel to True.
|
---|
74 | /// </summary>
|
---|
75 | public bool Cancel
|
---|
76 | {
|
---|
77 | get { return _cancel; }
|
---|
78 | set { _cancel = value; }
|
---|
79 | }
|
---|
80 |
|
---|
81 | private bool _IsSwitchServerModeEnabled = false;
|
---|
82 |
|
---|
83 | /// <summary>
|
---|
84 | /// If set to True, the Connection combo box on the Login screen with be dropped down when the
|
---|
85 | /// dialog is displayed. This is useful for applications that have an option to change Connections.
|
---|
86 | /// The default is False.
|
---|
87 | /// </summary>
|
---|
88 | public bool IsSwitchServerModeEnabled
|
---|
89 | {
|
---|
90 | get { return _IsSwitchServerModeEnabled; }
|
---|
91 | set { _IsSwitchServerModeEnabled = value; }
|
---|
92 | }
|
---|
93 |
|
---|
94 | private bool _autoSetDivisionToLastLookup = true;
|
---|
95 |
|
---|
96 | /// <summary>
|
---|
97 | /// If set to True, RPMS is checked and if there was a previously set division for the user it will be used, otherwise
|
---|
98 | /// MustResolveDivision will be set to True and the division will need to be set for the user.
|
---|
99 | /// The default is True
|
---|
100 | /// </summary>
|
---|
101 | public bool AutoSetDivisionToLastLookup
|
---|
102 | {
|
---|
103 | get { return _autoSetDivisionToLastLookup; }
|
---|
104 | set { _autoSetDivisionToLastLookup = value; }
|
---|
105 | }
|
---|
106 |
|
---|
107 | private bool _mustResolveDivision = false;
|
---|
108 |
|
---|
109 | /// <summary>
|
---|
110 | /// If the division for the user has not been determine after the LoginProcess, MustResolveDivision will be set to True.
|
---|
111 | /// The default if False.
|
---|
112 | /// </summary>
|
---|
113 | public bool MustResolveDivision
|
---|
114 | {
|
---|
115 | get { return _mustResolveDivision; }
|
---|
116 | set { _mustResolveDivision = value; }
|
---|
117 | }
|
---|
118 |
|
---|
119 | private int _loginAttempts = 0;
|
---|
120 |
|
---|
121 | /// <summary>
|
---|
122 | /// The number of login attempts so far. This value can be modified during the AttemptingLogin and LoginAttempted events.
|
---|
123 | /// </summary>
|
---|
124 | public int LoginAttempts
|
---|
125 | {
|
---|
126 | get { return _loginAttempts; }
|
---|
127 | set { _loginAttempts = value; }
|
---|
128 | }
|
---|
129 |
|
---|
130 | private int _maxAttempts = 3;
|
---|
131 |
|
---|
132 | /// <summary>
|
---|
133 | /// The number of login attempts before cancelling the LoginProcess. The default value is 3. This value can be modified during the AttemptingLogin and LoginAttempted events.
|
---|
134 | /// </summary>
|
---|
135 | public int MaxAttempts
|
---|
136 | {
|
---|
137 | get { return _maxAttempts; }
|
---|
138 | set { _maxAttempts = value; }
|
---|
139 | }
|
---|
140 |
|
---|
141 | private bool _wasLoginAttempted = false;
|
---|
142 |
|
---|
143 | /// <summary>
|
---|
144 | /// True if a login was attempted. False if the user is presented with a LoginDialog and "Cancel" is selected.
|
---|
145 | /// The value is changed during every login attempt cycle.
|
---|
146 | /// </summary>
|
---|
147 | public bool WasLoginAttempted
|
---|
148 | {
|
---|
149 | get { return _wasLoginAttempted; }
|
---|
150 | set { _wasLoginAttempted = value; }
|
---|
151 | }
|
---|
152 |
|
---|
153 | private bool _wasSuccessful = false;
|
---|
154 |
|
---|
155 | /// <summary>
|
---|
156 | /// True if the most recent login attempt was successful.
|
---|
157 | /// </summary>
|
---|
158 | public bool WasSuccessful
|
---|
159 | {
|
---|
160 | get { return _wasSuccessful; }
|
---|
161 | set { _wasSuccessful = value; }
|
---|
162 | }
|
---|
163 | private String _failureMessage = null;
|
---|
164 |
|
---|
165 | /// <summary>
|
---|
166 | /// A reasonable message to display to the user if the last login attempt failed.
|
---|
167 | /// </summary>
|
---|
168 | public String FailureMessage
|
---|
169 | {
|
---|
170 | get { return _failureMessage; }
|
---|
171 | set { _failureMessage = value; }
|
---|
172 | }
|
---|
173 |
|
---|
174 | private Exception _failureException = null;
|
---|
175 |
|
---|
176 | /// <summary>
|
---|
177 | /// If an exception occured during the last login attempt, FailureException will be set to it.
|
---|
178 | /// </summary>
|
---|
179 | public Exception FailureException
|
---|
180 | {
|
---|
181 | get { return _failureException; }
|
---|
182 | set { _failureException = value; }
|
---|
183 | }
|
---|
184 |
|
---|
185 | private RpmsConnectionSpec _connectionSpec = null;
|
---|
186 |
|
---|
187 | /// <summary>
|
---|
188 | /// The active ConnectionSpec being used to login. With care, the property can be changed or the instance can be modified during the AttemptingLogin and LoginAttempted events
|
---|
189 | /// with care.
|
---|
190 | /// </summary>
|
---|
191 | public RpmsConnectionSpec ConnectionSpec
|
---|
192 | {
|
---|
193 | get { return _connectionSpec; }
|
---|
194 | set { _connectionSpec = value; }
|
---|
195 | }
|
---|
196 |
|
---|
197 | internal LoginProcess(WinFramework aFramework)
|
---|
198 | {
|
---|
199 | this.Framework = aFramework;
|
---|
200 | }
|
---|
201 |
|
---|
202 | internal RpmsConnectionSettings Settings
|
---|
203 | {
|
---|
204 | get { return this.Framework.ConnectionSettings; }
|
---|
205 | }
|
---|
206 |
|
---|
207 | private WinFramework _framework = null;
|
---|
208 |
|
---|
209 | internal protected WinFramework Framework
|
---|
210 | {
|
---|
211 | get { return _framework; }
|
---|
212 | set { _framework = value; }
|
---|
213 | }
|
---|
214 |
|
---|
215 | /// <summary>
|
---|
216 | /// Answer True if there is a default managed connection that uses WindowsAuthenication
|
---|
217 | /// </summary>
|
---|
218 | public bool HasDefaultConnectionWithUseWindowsAuth
|
---|
219 | {
|
---|
220 | get
|
---|
221 | {
|
---|
222 | RpmsConnectionSpec spec = this.Settings.DefaultConnectionSpec;
|
---|
223 |
|
---|
224 | return spec == null ? false : spec.UseWindowsAuthentication;
|
---|
225 | }
|
---|
226 |
|
---|
227 |
|
---|
228 | }
|
---|
229 |
|
---|
230 |
|
---|
231 | /// <summary>
|
---|
232 | /// Attempt a WindowsAuthentication Login and answer true if it was successful.
|
---|
233 | /// </summary>
|
---|
234 | /// <returns>True if login was successful</returns>
|
---|
235 | public bool AttemptWindowsAuthLogin(RpmsConnectionSpec aConnectionSpec)
|
---|
236 | {
|
---|
237 | RpmsConnectionSpec spec = aConnectionSpec;
|
---|
238 | if (spec == null)
|
---|
239 | {
|
---|
240 | return this.Failed("A default connection spec must be set for automatic Windows Authenication");
|
---|
241 | }
|
---|
242 |
|
---|
243 | if (spec.UseWindowsAuthentication)
|
---|
244 | {
|
---|
245 | return this.PrimitiveAttemptWindowsAuthLogin(spec);
|
---|
246 | }
|
---|
247 | else
|
---|
248 | {
|
---|
249 | return this.Failed("Connection spec must be set for automatic Windows Authenication for auto-login");
|
---|
250 | }
|
---|
251 | }
|
---|
252 |
|
---|
253 | /// <summary>
|
---|
254 | /// Using the current default connection spec, attempt a WindowsAuthentication Login and answer true if it was successful.
|
---|
255 | /// </summary>
|
---|
256 | /// <remarks>
|
---|
257 | /// Most common approach when using the DefaultConnection feature the RpmsConnection spec class.
|
---|
258 | /// </remarks>
|
---|
259 | /// <returns>True if login was successful</returns>
|
---|
260 | public bool AttemptWindowsAuthLogin()
|
---|
261 | {
|
---|
262 | return this.AttemptWindowsAuthLogin(this.Settings.DefaultConnectionSpec);
|
---|
263 | }
|
---|
264 |
|
---|
265 | private bool Failed(string aMessage)
|
---|
266 | {
|
---|
267 | this.WasLoginAttempted = true;
|
---|
268 | this.WasSuccessful = false;
|
---|
269 | this.FailureMessage = aMessage;
|
---|
270 |
|
---|
271 | return this.WasSuccessful;
|
---|
272 | }
|
---|
273 |
|
---|
274 | /// <summary>
|
---|
275 | /// Attempt an interactive UI login. There are several useful arguments to control the process and appearance of the this process.
|
---|
276 | /// </summary>
|
---|
277 | /// <param name="aDialogTitle">The title of the login. Customize to be something like "MyApplication Login"</param>
|
---|
278 | /// <param name="maxAttempts">The number of attempts before cancelling</param>
|
---|
279 | /// <param name="enableConnectionManagement">If false, the user will not be able to change the connections. This is useful for lockdown situations</param>
|
---|
280 | /// <param name="aUiOwnerForPositioningDialog">Provide your main application as the window owner so the LoginDialog box is correctly managed.</param>
|
---|
281 | /// <returns>True if login was successful</returns>
|
---|
282 | public bool AttemptUserInputLogin(string aDialogTitle, int maxAttempts, bool enableConnectionManagement,IWin32Window aUiOwnerForPositioningDialog)
|
---|
283 | {
|
---|
284 | this.MaxAttempts = maxAttempts;
|
---|
285 | RpmsLoginView view = (RpmsLoginView)new RpmsLoginDialog();
|
---|
286 |
|
---|
287 | view.Title = aDialogTitle;
|
---|
288 |
|
---|
289 | RpmsLoginPresenter presenter = new RpmsLoginPresenter();
|
---|
290 | presenter.EnableConnectionManagement = enableConnectionManagement;
|
---|
291 | presenter.View = view;
|
---|
292 | presenter.Model = this;
|
---|
293 | presenter.UiOwner = aUiOwnerForPositioningDialog;
|
---|
294 |
|
---|
295 | presenter.Open();
|
---|
296 |
|
---|
297 |
|
---|
298 | return this.WasSuccessful;
|
---|
299 | }
|
---|
300 |
|
---|
301 | /// <summary>
|
---|
302 | /// If the application is managing the actual login, send Succeeded() to indicate success.
|
---|
303 | /// </summary>
|
---|
304 | /// <remarks>
|
---|
305 | /// Do not set WasSuccessful to true.
|
---|
306 | /// </remarks>
|
---|
307 | /// <returns>True if successful</returns>
|
---|
308 | public bool Succeeded()
|
---|
309 | {
|
---|
310 | this.WasLoginAttempted = true;
|
---|
311 | this.WasSuccessful = true;
|
---|
312 | this.FailureMessage = "";
|
---|
313 | this.Framework.Login = this;
|
---|
314 |
|
---|
315 | return this.WasSuccessful;
|
---|
316 | }
|
---|
317 |
|
---|
318 |
|
---|
319 |
|
---|
320 | internal bool PrimitiveAttemptWindowsAuthLogin(RpmsConnectionSpec aSpec)
|
---|
321 | {
|
---|
322 | BMXNetBroker broker = this.Framework.SocketBroker;
|
---|
323 | this.ConnectionSpec = aSpec;
|
---|
324 |
|
---|
325 | if (this.AttemptingLogin != null)
|
---|
326 | {
|
---|
327 | AttemptingLoginEventArgs args = new AttemptingLoginEventArgs();
|
---|
328 | args.Process = this;
|
---|
329 | this.AttemptingLogin(this, args);
|
---|
330 | if (args.Handled)
|
---|
331 | {
|
---|
332 | return this.WasSuccessful;
|
---|
333 | }
|
---|
334 |
|
---|
335 | if (args.Cancel)
|
---|
336 | {
|
---|
337 | this.Cancel = true;
|
---|
338 | return false;
|
---|
339 | }
|
---|
340 | }
|
---|
341 |
|
---|
342 | try
|
---|
343 | {
|
---|
344 | if (broker.Open(aSpec.Server, aSpec.Port, aSpec.NameSpace, WindowsIdentity.GetCurrent(),aSpec.SendTimeout,aSpec.ReceiveTimeout))
|
---|
345 | {
|
---|
346 | this.Succeeded();
|
---|
347 | this.ResolveDivision(broker);
|
---|
348 | return this.WasSuccessful;
|
---|
349 | }
|
---|
350 | else
|
---|
351 | {
|
---|
352 | return this.Failed("Unable to authenicate. Use may need to login");
|
---|
353 | }
|
---|
354 | }
|
---|
355 | catch (BMXNetException problem)
|
---|
356 | {
|
---|
357 | this.FailureException = problem;
|
---|
358 | return this.Failed(problem.Message);
|
---|
359 | }
|
---|
360 | catch (Exception anException)
|
---|
361 | {
|
---|
362 | this.FailureException = anException;
|
---|
363 | return this.Failed("Critical issue: " + anException.Message);
|
---|
364 | }
|
---|
365 | }
|
---|
366 |
|
---|
367 |
|
---|
368 | public VerifyCodeUpdateResult AttemptVerifyCodeChange(WinFramework bmxFramework, RpmsConnectionSpec bmxConnectionSpec, string strAccessCode)
|
---|
369 | {
|
---|
370 |
|
---|
371 | // Open the verify code upate dialog
|
---|
372 | VerifyCodeUpdateDialog vcd = new VerifyCodeUpdateDialog(bmxFramework, bmxConnectionSpec, strAccessCode);
|
---|
373 | DialogResult dr = new DialogResult();
|
---|
374 | VerifyCodeUpdateResult vr = new VerifyCodeUpdateResult();
|
---|
375 |
|
---|
376 | while (vr.DialogResult != DialogResult.Cancel && !(vr.WasVerifyCodeUpdatedSuccessfully ))
|
---|
377 | {
|
---|
378 | vr = vcd.ShowVerifyChangeDialog(null);
|
---|
379 | }
|
---|
380 |
|
---|
381 | return vr;
|
---|
382 |
|
---|
383 | }
|
---|
384 |
|
---|
385 | /// <summary>
|
---|
386 | /// Attempt a headless non-interactive UI login. This would be useful for an ASP.NET or NT-service type application
|
---|
387 | /// </summary>
|
---|
388 | /// <param name="aSpec">The RpmsConnectionSpec to use during the login process</param>
|
---|
389 | /// <param name="anAccessCode">The clear text access code</param>
|
---|
390 | /// <param name="aVerifyCode">The clear text verify code</param>
|
---|
391 | /// <returns>True if the login was successful</returns>
|
---|
392 | public bool AttemptAccessVerifyLogin(RpmsConnectionSpec aSpec, String anAccessCode, String aVerifyCode)
|
---|
393 | {
|
---|
394 | BMXNetBroker broker = this.Framework.SocketBroker;
|
---|
395 |
|
---|
396 | this.ConnectionSpec = aSpec;
|
---|
397 |
|
---|
398 |
|
---|
399 | if (this.AttemptingLogin != null)
|
---|
400 | {
|
---|
401 | AttemptingLoginEventArgs args = new AttemptingLoginEventArgs();
|
---|
402 | args.Process = this;
|
---|
403 | this.AttemptingLogin(this, args);
|
---|
404 | if (args.Handled)
|
---|
405 | {
|
---|
406 | return this.WasSuccessful;
|
---|
407 | }
|
---|
408 |
|
---|
409 | if (args.Cancel)
|
---|
410 | {
|
---|
411 | this.Cancel = true;
|
---|
412 | return false;
|
---|
413 | }
|
---|
414 | }
|
---|
415 |
|
---|
416 |
|
---|
417 | try
|
---|
418 | {
|
---|
419 | this.LoginAttempts++;
|
---|
420 |
|
---|
421 | if (broker.Open(aSpec.Server, aSpec.Port, aSpec.NameSpace, anAccessCode, aVerifyCode,aSpec.SendTimeout,aSpec.ReceiveTimeout))
|
---|
422 | {
|
---|
423 | this.Succeeded();
|
---|
424 | if (aSpec.UseWindowsAuthentication)
|
---|
425 | {
|
---|
426 | String result = broker.RegisterWindowsIdentityForWindowsAuthenication(WindowsIdentity.GetCurrent());
|
---|
427 | }
|
---|
428 | this.ResolveDivision(broker);
|
---|
429 |
|
---|
430 | return this.WasSuccessful;
|
---|
431 | }
|
---|
432 | else
|
---|
433 | {
|
---|
434 | return this.Failed("Unable to authenicate. Use may need to login");
|
---|
435 | }
|
---|
436 | }
|
---|
437 |
|
---|
438 | catch (BMXNetException problem)
|
---|
439 | {
|
---|
440 | this.FailureException = problem;
|
---|
441 |
|
---|
442 | if ( problem.Message.Contains("VERIFY CODE MUST be changed before continued use."))
|
---|
443 | {
|
---|
444 | string message = "Your Verify Code has expired. Do you want to submit a new Verify Code now? Click Yes to continue, Click No to exit the sign in process.";
|
---|
445 | string caption = "Verify Code Expired";
|
---|
446 | MessageBoxButtons buttons = MessageBoxButtons.YesNo;
|
---|
447 |
|
---|
448 | DialogResult result;
|
---|
449 |
|
---|
450 | // Displays the MessageBox.
|
---|
451 |
|
---|
452 | result = MessageBox.Show(message, caption, buttons);
|
---|
453 |
|
---|
454 | if (result == System.Windows.Forms.DialogResult.Yes)
|
---|
455 | {
|
---|
456 | // Open the verify code upate dialog
|
---|
457 | VerifyCodeUpdateDialog vcd =new VerifyCodeUpdateDialog(this.Framework,this.ConnectionSpec,anAccessCode);
|
---|
458 | DialogResult dr = new DialogResult();
|
---|
459 |
|
---|
460 | while ( (dr != DialogResult.Cancel) && (!vcd.IsUpdateSuccessful))
|
---|
461 | {
|
---|
462 | dr = vcd.ShowDialog();
|
---|
463 | }
|
---|
464 |
|
---|
465 |
|
---|
466 | if (dr == DialogResult.OK)
|
---|
467 | {
|
---|
468 | bool bLogin = AttemptAccessVerifyLogin(this.ConnectionSpec,vcd.AccessCode, vcd.NewVerifyCode);
|
---|
469 | return bLogin;
|
---|
470 | }
|
---|
471 | else
|
---|
472 | {
|
---|
473 | this.FailureMessage = "VERIFY CODE MUST be changed before continued use.";
|
---|
474 | return this.WasSuccessful;
|
---|
475 | }
|
---|
476 | }
|
---|
477 | else
|
---|
478 | {
|
---|
479 | return this.Failed(problem.Message);
|
---|
480 | }
|
---|
481 | }
|
---|
482 | else
|
---|
483 | {
|
---|
484 | return this.Failed(problem.Message);
|
---|
485 | }
|
---|
486 |
|
---|
487 | }
|
---|
488 | catch (Exception anException)
|
---|
489 | {
|
---|
490 | this.FailureException = anException;
|
---|
491 | return this.Failed("Critical issue: " + anException.Message);
|
---|
492 | }
|
---|
493 | }
|
---|
494 |
|
---|
495 | private void TriggerAttemptingLogin()
|
---|
496 | {
|
---|
497 | throw new NotImplementedException();
|
---|
498 | }
|
---|
499 |
|
---|
500 | private void ResolveDivision(BMXNetBroker aBroker)
|
---|
501 | {
|
---|
502 | List<SelectableDivision> divisions = this.Framework.Divisions(aBroker.Duz);
|
---|
503 | if (divisions.Count == 1)
|
---|
504 | {
|
---|
505 | this.Framework.SetDivision(divisions[0]);
|
---|
506 | }
|
---|
507 | else
|
---|
508 | {
|
---|
509 | if (this.AutoSetDivisionToLastLookup)
|
---|
510 | {
|
---|
511 | WinDivision last = null;
|
---|
512 | foreach (WinDivision each in divisions)
|
---|
513 | {
|
---|
514 | if (each.MostRecentLookup)
|
---|
515 | {
|
---|
516 | last = each;
|
---|
517 | break;
|
---|
518 | }
|
---|
519 | }
|
---|
520 | if (last == null)
|
---|
521 | {
|
---|
522 | this.MustResolveDivision = true;
|
---|
523 | }
|
---|
524 | else
|
---|
525 | {
|
---|
526 | this.Framework.SetDivision(last);
|
---|
527 | }
|
---|
528 | }
|
---|
529 | else
|
---|
530 | {
|
---|
531 | this.MustResolveDivision = true;
|
---|
532 | }
|
---|
533 | }
|
---|
534 | }
|
---|
535 |
|
---|
536 | /// <summary>
|
---|
537 | /// Will trigger the LoginAttempted event
|
---|
538 | /// </summary>
|
---|
539 | /// <returns>Answer true if the LoginProcess has been Canceled or handled</returns>
|
---|
540 | public bool HandleLoginAttemptedFailed()
|
---|
541 | {
|
---|
542 | if (this.LoginAttempted != null)
|
---|
543 | {
|
---|
544 | LoginAttemptedEventArgs args = new LoginAttemptedEventArgs();
|
---|
545 | args.Process = this;
|
---|
546 | args.Handled = false;
|
---|
547 | args.WasSuccessful = this.WasLoginAttempted;
|
---|
548 | this.LoginAttempted(this, args);
|
---|
549 | if (args.Cancel)
|
---|
550 | {
|
---|
551 | this.Cancel = true;
|
---|
552 | }
|
---|
553 | return args.Handled || this.Cancel;
|
---|
554 |
|
---|
555 | }
|
---|
556 | else
|
---|
557 | {
|
---|
558 | return false;
|
---|
559 | }
|
---|
560 | }
|
---|
561 | }
|
---|
562 | }
|
---|