context: using System;
  using System.Collections.Generic;
  using System.Configuration;
  using System.IO;
  using System.Linq;
  using System.Net.Configuration;
  using System.Web.Mvc;
  using System.Web.Security;
  using Web.Mailers;
  using Web.Mailers.Models;
  using SecurityGuard.Core;
  using SecurityGuard.Interfaces;
  using SecurityGuard.Services;
  using SecurityGuard.ViewModels;
  using viewModels = Web.Areas.SecurityGuard.ViewModels;
  
  namespace Web.Controllers
  {
      /// <summary>
      /// This class handles all the normal logon, logoff, 
      /// register, change password, and forgot password operations
      /// that occur in the public part of your web application.
      /// </summary>
      public class SGAccountController : BaseController
      {
                  
          #region ctors
  
          private IMembershipService membershipService;
          private IAuthenticationService authenticationService;
          private IFormsAuthenticationService formsAuthenticationService;
          private IPasswordResetMailer _mailer = new PasswordResetMailer();
  
          public SGAccountController()
          {
              this.membershipService = new MembershipService(Membership.Provider);
              this.authenticationService = new AuthenticationService(membershipService, new FormsAuthenticationService());
              this.formsAuthenticationService = new FormsAuthenticationService();
          }
  
          #endregion
  
          #region Public Properties
  
          public IPasswordResetMailer Mailer
          {
              get { return _mailer; }
              set { _mailer = value; }
          }
  
          #endregion
  
          public virtual ActionResult Index()
          {
              return View();
          }
  
          #region LogOn Methods
  
          [HttpGet]
          public virtual ActionResult Login()
          {
              var viewModel = new LogOnViewModel()
              {
                  EnablePasswordReset = membershipService.EnablePasswordReset
              };
              return ContextDependentView(viewModel);
          }
  
          [HttpPost]
          [ValidateAntiForgeryToken]
          public virtual ActionResult Login(LogOnViewModel model, string returnUrl)
          {
              if (ModelState.IsValid)
              {
                  if (authenticationService.LogOn(model.UserName, model.Password, model.RememberMe))
                  {
                      if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                          && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                      {
                          return Redirect(returnUrl);
                      }
                      else
                      {
                          return RedirectToAction("Index", "Home");
                      }
                  }
                  else
                  {
                      MembershipUser user = membershipService.GetUser(model.UserName);
                      if (user == null)
                      {
                          ModelState.AddModelError("", "This account does not exist. Please try again.");
                      }
                      else
                      {
                          if (!user.IsApproved)
                          {
                              ModelState.AddModelError("", "Your account has not been approved yet.");
                          }
                          else if (user.IsLockedOut)
                          {
                              ModelState.AddModelError("", "Your account is currently locked.");
                          }
                          else
                          {
                              ModelState.AddModelError("", "The user name or password provided is incorrect.");
                          }
                      }
                  }
              }
  
              // If we got this far, something failed, redisplay form
              return RedirectToAction("Login");
          }
  
          [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
          [ValidateAntiForgeryToken()]
          public virtual ActionResult LogOff()
          {
              authenticationService.LogOff();
  
              return RedirectToAction("Index", "Home");
          } 
          #endregion
  
          #region Register Methods
  
          public virtual ActionResult Register()
          {
              var model = new viewModels.RegisterViewModel()
              {
                  RequireSecretQuestionAndAnswer = membershipService.RequiresQuestionAndAnswer
              };
              return ContextDependentView(model);
          }
  
          [HttpPost]
          [ValidateAntiForgeryToken()]
          public virtual ActionResult Register(viewModels.RegisterViewModel model)
          {
              if (ModelState.IsValid)
              {
                  // Attempt to register the user
                  MembershipCreateStatus createStatus;
                  membershipService.CreateUser(model.UserName, model.Password, model.Email, model.SecretQuestion, model.SecretAnswer, true, out createStatus);
  
                  if (createStatus == MembershipCreateStatus.Success)
                  {
                      formsAuthenticationService.SetAuthCookie(model.UserName, false /* createPersistentCookie */);
                      return RedirectToAction("Index", "Home");
                  }
                  else
                  {
                      ModelState.AddModelError("", ErrorCodeToString(createStatus));
                  }
              }
  
              return RedirectToAction("Register");
          }
  
  
          #endregion
  
          #region ChangePassword Methods
          
          /// <summary>
          /// This allows the logged on user to change his password.
          /// </summary>
          /// <returns></returns>
          [Authorize]
          public virtual ActionResult ChangePassword()
          {
              var viewModel = new ChangePasswordViewModel();
  
              return View(viewModel);
          }
  
          [Authorize]
          [HttpPost]
          [ValidateAntiForgeryToken()]
          public virtual ActionResult ChangePassword(ChangePasswordViewModel model)
          {
              if (ModelState.IsValid)
              {
  
                  // ChangePassword will throw an exception rather
                  // than return false in certain failure scenarios.
                  bool changePasswordSucceeded;
                  try
                  {
                      MembershipUser currentUser = Membership.GetUser(User.Identity.Name, true /* userIsOnline */);
                      changePasswordSucceeded = currentUser.ChangePassword(model.OldPassword, model.NewPassword);
                  }
                  catch (Exception)
                  {
                      changePasswordSucceeded = false;
                  }
  
                  if (changePasswordSucceeded)
                  {
                      return RedirectToAction("ChangePasswordSuccess");
                  }
                  else
                  {
                      ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
                  }
              }
  
              // If we got this far, something failed, redisplay form
              return RedirectToAction("ChangePassword");
          }
  
          //
          // GET: /Account/ChangePasswordSuccess
  
          public virtual ActionResult ChangePasswordSuccess()
          {
              return View();
          }
  
  
          #endregion
  
          #region Forgot Password Methods
  
          /// <summary>
          /// This allows the non-logged on user to have his password
          /// reset and emailed to him.
          /// </summary>
          /// <returns></returns>
          public ActionResult ForgotPassword()
          {
              var viewModel = new ForgotPasswordViewModel()
              {
                  RequireSecretQuestionAndAnswer = membershipService.RequiresQuestionAndAnswer
              };
              return View(viewModel);
          }
  
          /// <summary>
          /// This is the GET action to collect the answer and then continue.
          /// This is only hit if the web.config/system.web/membership provider is
          /// set with the attribute requiresQuestionAndAnswer="true".
          /// </summary>
          /// <param name="model">ForgotPasswordViewModel</param>
          /// <returns></returns>
          public virtual ActionResult EnterSecretAnswer(ForgotPasswordViewModel model)
          {
              return View(model);
          }
  
          /// <summary>
          /// Reset the password for the user and email it to him.
          /// </summary>
          /// <param name="email"></param>
          /// <returns></returns>
          [HttpPost]
          [ValidateAntiForgeryToken()]
          public virtual ActionResult ForgotPassword(ForgotPasswordViewModel model)
          {
              string userName = membershipService.GetUserNameByEmail(model.Email);
              // Get the userName by the email address
              if (string.IsNullOrEmpty(userName))
              {
                  ModelState.AddModelError("Email", "Email address does not exist. Please check your spelling and try again.");
                  return RedirectToAction("ForgotPassword");
              }
  
  
gt:             MembershipUser user = membershipService.GetUser(userName);