| 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 | }
|
|---|