using System; using System.Web.Mvc; using System.Web.Security; using MileageTraker.Web.Attributes; using MileageTraker.Web.DAL; using MileageTraker.Web.Email; using MileageTraker.Web.ViewModels.Account; namespace MileageTraker.Web.Controllers { [Authorize] public class AccountController : ControllerBase { [AllowAnonymous] [ActionLog] public ActionResult Login(string returnUrl, string username) { if (User.Identity.IsAuthenticated) { return RedirectToAction("Index", "CreateLog"); } ViewBag.ReturnUrl = returnUrl; return View(new LoginViewModel{Username = username}); } [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] [ActionLog] 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); SetStatusMessage("Logged in as " + model.Username); return RedirectToLocal(returnUrl); } ModelState.AddModelError("", "The user name or password provided is incorrect."); } catch (UserAccountDisabledException) { var errorMessage = "Account is disabled for " + model.Username + "."; log4net.LogManager.GetLogger("AccountController.Login").InfoFormat(errorMessage); ModelState.AddModelError("", errorMessage); } catch (UserLockedOutException) { var errorMessage = "Too many failed password attempts for " + model.Username + ". Account is locked. " + @"Use 'Forgot Password' or contact " + "administrator to unlock."; log4net.LogManager.GetLogger("AccountController.Login").InfoFormat(errorMessage); ModelState.AddModelError("", errorMessage); } catch (UninitializedAccountException) { var errorMessage = "Account for " + model.Username + " has not been initialized. " + @"Please check your email for initialization instructions."; log4net.LogManager.GetLogger("AccountController.Login").InfoFormat(errorMessage); ModelState.AddModelError("", errorMessage); } } // If we got this far, something failed, redisplay form return View(model); } [HttpPost] [ValidateAntiForgeryToken] public ActionResult LogOff() { SetStatusMessage(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"); var user = DataService.FindUserByUsername(User.Identity.Name); var viewModel = new ChangePasswordViewModel(user); return View(viewModel); } [HttpPost] [ValidateAntiForgeryToken] [ActionLog] public ActionResult Manage(ChangePasswordViewModel model) { ViewBag.ReturnUrl = Url.Action("Manage"); var membershipUser = Membership.GetUser(User.Identity.Name, true); //var user = DataService.FindUserByUsername(User.Identity.Name); //model.SetProperties(user); if (ModelState.IsValid) { // ChangePassword will throw an exception rather than return false in certain failure scenarios. bool changePasswordSucceeded; try { changePasswordSucceeded = membershipUser.ChangePassword(model.OldPassword, model.NewPassword); } catch (Exception) { changePasswordSucceeded = false; } if (changePasswordSucceeded) { SetStatusMessage("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] [HttpGet] public ViewResult ResetPassword(string username) { return View(new ResetPasswordViewModel{Username = username}); } /// /// Begins the Reset Password process /// [AllowAnonymous] [HttpPost] [ValidateAntiForgeryToken] [ActionLog] public ActionResult ResetPassword(ResetPasswordViewModel viewModel) { var user = DataService.FindUserByUsername(viewModel.Username); if (user != null && user.IsApproved && Request.Url != null) { var email = new EmailNotificationService(); var resetPasswordUrl = ResetPassword(user); email.SendResetPassword(user, resetPasswordUrl); SetStatusMessage("Please check your email - we have sent a request for you to reset the password."); } else if (user == null) { SetStatusMessage("Could not find username " + viewModel.Username + ".", StatusType.Error); return RedirectToAction("ResetPassword"); } else if (!user.IsApproved) { SetStatusMessage("Account is disabled for " + viewModel.Username + ".", StatusType.Error); } // 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] [HttpGet] public ActionResult NewPassword(Guid userId, string passwordResetToken) { var user = DataService.GetUser(userId); if (user != null && user.IsApproved && 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] [HttpPost] [ValidateAntiForgeryToken] [ActionLog] public ActionResult NewPassword(NewPasswordViewModel viewModel) { if (ModelState.IsValid) { var user = DataService.GetUser(viewModel.UserId); if (user != null && user.IsApproved && user.PasswordResetToken == viewModel.PasswordResetToken) { DataService.UpdateUserPassword(viewModel.UserId, viewModel.NewPassword); var success = Membership.ValidateUser(user.Username, viewModel.NewPassword); if (success) { FormsAuthentication.SetAuthCookie(viewModel.Username, false); SetStatusMessage("Password set for " + viewModel.Username + ", logged in"); return RedirectToAction("Index", "CreateLog"); } } } // If we got this far, something failed, redisplay form return View(viewModel); } #endregion } }