using System; using System.Web.Mvc; using System.Web.Security; using MileageTraker.Web.DAL; using MileageTraker.Web.Email; using MileageTraker.Web.Utility; using MileageTraker.Web.ViewModels.Account; namespace MileageTraker.Web.Controllers { [Authorize] public class AccountController : ControllerBase { [AllowAnonymous] public ActionResult Login(string returnUrl, string username) { ViewBag.ReturnUrl = returnUrl; return View(new LoginViewModel{Username = username}); } [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public ActionResult Login(LoginViewModel model, string returnUrl) { if (ModelState.IsValid) { try { var success = Membership.ValidateUser(model.Username, model.Password); if (success) { FormsAuthentication.SetAuthCookie(model.Username, model.RememberMe); TempData["StatusMessage"] = "Logged in as " + model.Username; return RedirectToLocal(returnUrl); } ModelState.AddModelError("", "The user name or password provided is incorrect."); } catch (UserAccountDisabledException) { ModelState.AddModelError("", "Account is disabled for " + model.Username + "."); } catch (UserLockedOutException) { ModelState.AddModelError("", "Too many failed password attempts for " + model.Username + ". Account is locked. " + @"Use 'Forgot Password' or contact " + "administrator to unlock." ); } } // If we got this far, something failed, redisplay form return View(model); } [HttpPost] [ValidateAntiForgeryToken] public ActionResult LogOff() { TempData["StatusMessage"] = User.Identity.Name + " logged off"; FormsAuthentication.SignOut(); return RedirectToAction("Index", "CreateLog"); } public ActionResult Manage(ManageMessageId? message) { ViewBag.StatusMessage = message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed." : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set." : null; ViewBag.ReturnUrl = Url.Action("Manage"); return View(); } [HttpPost] [ValidateAntiForgeryToken] public ActionResult Manage(ChangePasswordViewModel model) { ViewBag.ReturnUrl = Url.Action("Manage"); if (ModelState.IsValid) { // ChangePassword will throw an exception rather than return false in certain failure scenarios. bool changePasswordSucceeded; try { var currentUser = Membership.GetUser(User.Identity.Name, true); changePasswordSucceeded = currentUser.ChangePassword(model.OldPassword, model.NewPassword); } catch (Exception) { changePasswordSucceeded = false; } if (changePasswordSucceeded) { TempData["StatusMessage"] = "Your password has been changed."; return RedirectToAction("Manage"); } ModelState.AddModelError("", "The current password is incorrect or the new password is invalid."); } // If we got this far, something failed, redisplay form return View(model); } private ActionResult RedirectToLocal(string returnUrl) { if (Url.IsLocalUrl(returnUrl)) { return Redirect(returnUrl); } return RedirectToAction("Index", "Log"); } public enum ManageMessageId { ChangePasswordSuccess, SetPasswordSuccess, } #region Reset Password /// /// View the Reset Password form /// [AllowAnonymous] [AcceptVerbs(HttpVerbs.Get)] public ViewResult ResetPassword(string username) { return View(new ResetPasswordViewModel{Username = username}); } /// /// Begins the Reset Password process /// [AllowAnonymous] [AcceptVerbs(HttpVerbs.Post)] [ValidateAntiForgeryToken] public ActionResult ResetPassword(ResetPasswordViewModel viewModel) { var user = DataService.FindUserByUsername(viewModel.Username); if (user != null && Request.Url != null) { var passwordResetToken = Algorithms.GenerateToken(); var url = Request.Url.Scheme + @"://" + Request.Url.Authority + Url.Action("NewPassword", "Account", new NewPasswordViewModel { UserId = user.UserId, PasswordResetToken = passwordResetToken }); user.PasswordResetToken = passwordResetToken; DataService.UpdateUser(user); var email = new EmailNotificationService(); email.NotifyResetPassword(user,url); } TempData["StatusMessage"] = "Please check your email - we have sent a request for you to reset the password."; // even when if not successful, let the user think they're getting a cookie return RedirectToAction("Login"); } /// /// Action users are sent to when they reset their password. /// [AllowAnonymous] [AcceptVerbs(HttpVerbs.Get)] public ActionResult NewPassword(Guid userId, string passwordResetToken) { var user = DataService.GetUser(userId); if (user != null && user.PasswordResetToken == passwordResetToken) { var newPasswordViewModel = new NewPasswordViewModel { UserId = user.UserId, Username = user.Username, PasswordResetToken = passwordResetToken }; return View(newPasswordViewModel); } return HttpNotFound(); } /// /// Set a new password. /// /// The view model. [AllowAnonymous] [AcceptVerbs(HttpVerbs.Post)] [ValidateAntiForgeryToken] public ActionResult NewPassword(NewPasswordViewModel viewModel) { if (ModelState.IsValid) { var user = DataService.GetUser(viewModel.UserId); if (user != null && user.PasswordResetToken == viewModel.PasswordResetToken) { DataService.UpdateUserPassword(viewModel.UserId, viewModel.NewPassword); TempData["StatusMessage"] = "Password set for " + viewModel.Username; return RedirectToAction("Login", new {username = viewModel.Username}); } } // If we got this far, something failed, redisplay form return View(viewModel); } #endregion } }