using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Security.Principal; using System.Web; using System.Web.Mvc; using System.Web.Security; using System.Web.UI; using NHibernate; using NHibernate.Linq; using Sleis.Models; using Sleis.Infrastructure; using log4net; using Sleis.Utility; using Sleis.ViewModels; using Sleis.Models.ErrorHandling; namespace Sleis.Controllers { public class AccountController : BaseController { public string PasswordresetConfirmationMessage { get; set; } public string EnterNewPasswordMessage { get; set; } public string InvalidCredentialMessage { get; set; } public string InvalidUserProfileMessage { get; set; } public override void Init() { base.Init(); ArgumentValidationUtility.ThrowOnEmpty(PasswordresetConfirmationMessage, "PasswordresetConfirmationMessage"); ArgumentValidationUtility.ThrowOnEmpty(InvalidCredentialMessage, "InvalidCredentialMessage"); } public ActionResult Login() { return View(new SimpleAuthModel()); } public ActionResult Forgot(string EmailAddress = "") { return View(); } public ActionResult Reset() { return View(); } [HttpPost] public ActionResult Reset(ResetPasswordModel model, string id) { ActionResult resultView = null; if (ModelState.IsValid && !String.IsNullOrEmpty(id)) { try { int readId = EncryptionUtility.DecryptTokenFromUrl(id); //Change UserModel user = UserService.ChangePassword(readId, model.Password1); //Audit AppEventModel audit = new AppEventModel(EventType.Audit, user.Email, "Password Reset", Request.UserHostAddress); //Save audit UserService.Audit(audit); TempData[Constants.GlobalMessageKey] = new SimpleMessage(EnterNewPasswordMessage); //Redirect resultView = RedirectToAction("Login", "Account"); } catch (SleisPasswordException err) { TempData[Constants.GlobalMessageKey] = new SimpleMessage(err.Message, true); return View(); } } else { resultView = View(); } return resultView; } [HttpGet] public ActionResult Verify(string id) { ActionResult resultView = null; if (!String.IsNullOrEmpty(id)) { try { int readId = EncryptionUtility.DecryptTokenFromUrl(id); //Change th status back to pending UserService.ResetUserStatus(readId); //TODO: Log and audit resultView = RedirectToAction("Reset", "Account", new { @id = id }); } catch (Exception err) { TempData[Constants.GlobalMessageKey] = new SimpleMessage(Properties.Get(Constants.InvalidResetPasswordToken), true); return RedirectToAction("Login"); } } else { throw new ApplicationException("Invalid token"); } return resultView; } [HttpPost] public ActionResult Forgot(SimpleEmailModel email) { if (ModelState.IsValid) { UserService.Audit(new AppEventModel(EventType.Auth, email.EmailAddress, "Forgot Password Process Initiated", Request.UserHostAddress)); try { UserModel usr = UserService.GetUser(email.EmailAddress, 0); if (usr == null || usr.Id <= 0) throw new ArgumentNullException("Invalid user"); //Require user to answer security question if(usr.ContactSecAnswers!=null && usr.ContactSecAnswers.Count>0) return RedirectToAction("VerifySecurity", new{id=UserService.GetUser(email.EmailAddress, 0).Id}); return CompletePasswordReset(usr); } catch (Exception ex) { Log.Error("Forgot credentials:", ex); Log.ErrorFormat("Email: {0}", email); TempData[Constants.GlobalMessageKey] = new SimpleMessage(InvalidUserProfileMessage, true); } } return RedirectToAction("Forgot", new { EmailAddress = email.EmailAddress }); } [HttpGet] public ActionResult VerifySecurity(int id) { var user = UserService.GetUser(id); if (user.Status == SleisUserStatusType.Locked) throw new AccountLockedException(); List questions = user.ContactSecAnswers; VerifySecurityViewModel model = new VerifySecurityViewModel() { Question = questions[new Random().Next(0, questions.Count - 1)].Question, UserId = user.Id }; return View(model); } [HttpPost] public ActionResult VerifySecurity(VerifySecurityViewModel model) { try { var user = UserService.GetUser(model.UserId); if (UserService.ValidateUserSecurityQuestionAnswer(user, model.Question, model.Answer)) { return CompletePasswordReset(user); } TempData[Constants.GlobalMessageKey] = new SimpleMessage("Invalid challenge question answer. Please try again.", true); } catch (AccountLockedException ex) { throw ex; //pass it on to global error handler. } catch (Exception err) { TempData[Constants.GlobalMessageKey] = new SimpleMessage(err.Message, true); } return RedirectToAction("VerifySecurity", new { id = model.UserId }); } [HttpPost] public ActionResult Login(SimpleAuthModel auth, string returnUrl) { ActionResult resultView = View(); if (ModelState.IsValid) { UserService.Audit(new AppEventModel(EventType.Auth, auth.EmailAddress, "Login Attempt", Request.UserHostAddress)); try { UserModel user = UserService.AuthUser(auth); ArgumentValidationUtility.ThrowOnNull(user, InvalidCredentialMessage); FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, //version user.FullName, // user name DateTime.Now, //creation DateTime.Now.AddDays(1), //24 valid false, //Persistent user.Id.ToString()); // Id, wil come from string encTicket = FormsAuthentication.Encrypt(authTicket); Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket)); HttpContext.Session.Add(UserModel.SESSION_USER_KEY, new UserView() { User = user }); if (user.Type == SleisUserTypeType.Agency) { resultView = RedirectToAction("Home", "Agency"); } else if (user.Type == SleisUserTypeType.Facility) { resultView = RedirectToAction("List", "Facility"); } else { resultView = Redirect(returnUrl); } } catch (AccountLockedException ex) { throw ex; //pass it along } catch (Exception ex) { Log.Error("Auth", ex); TempData[Constants.GlobalMessageKey] = new SimpleMessage(InvalidCredentialMessage, true); AppEventModel audit = new AppEventModel(EventType.Audit, auth.EmailAddress, InvalidCredentialMessage, Request.UserHostAddress); UserService.Audit(audit); //Save Audit }//try }//valid return resultView; } public ActionResult Logout() { FormsAuthentication.SignOut(); Session.Clear(); //TempData[Constants.GlobalMessageKey] = new SimpleMessage("User successfully logged out."); return RedirectToAction("Home", "Public"); } [Authorize] public ActionResult ChangePassword() { return View(); } private ActionResult CompletePasswordReset(UserModel user) { UserService.Forgot(user.Email, String.Format("{0}/Account/Verify/", BaseUri)); TempData[Constants.GlobalMessageKey] = new SimpleMessage(PasswordresetConfirmationMessage); return RedirectToAction("Home", "Public"); } } }