diff options
Diffstat (limited to 'projecttemplates/MvcRelyingParty/Controllers/AccountController.cs')
-rw-r--r-- | projecttemplates/MvcRelyingParty/Controllers/AccountController.cs | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/projecttemplates/MvcRelyingParty/Controllers/AccountController.cs b/projecttemplates/MvcRelyingParty/Controllers/AccountController.cs new file mode 100644 index 0000000..bcce1dc --- /dev/null +++ b/projecttemplates/MvcRelyingParty/Controllers/AccountController.cs @@ -0,0 +1,292 @@ +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; + +namespace MvcRelyingParty.Controllers { + + [HandleError] + public class AccountController : Controller { + + // This constructor is used by the MVC framework to instantiate the controller using + // the default forms authentication and membership providers. + + public AccountController() + : this(null, null) { + } + + // This constructor is not used by the MVC framework but is instead provided for ease + // of unit testing this type. See the comments at the end of this file for more + // information. + public AccountController(IFormsAuthentication formsAuth, IMembershipService service) { + FormsAuth = formsAuth ?? new FormsAuthenticationService(); + MembershipService = service ?? new AccountMembershipService(); + } + + public IFormsAuthentication FormsAuth { + get; + private set; + } + + public IMembershipService MembershipService { + get; + private set; + } + + public ActionResult LogOn() { + + return View(); + } + + [AcceptVerbs(HttpVerbs.Post)] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", + Justification = "Needs to take same parameter type as Controller.Redirect()")] + public ActionResult LogOn(string userName, string password, bool rememberMe, string returnUrl) { + + if (!ValidateLogOn(userName, password)) { + return View(); + } + + FormsAuth.SignIn(userName, rememberMe); + if (!String.IsNullOrEmpty(returnUrl)) { + return Redirect(returnUrl); + } else { + return RedirectToAction("Index", "Home"); + } + } + + public ActionResult LogOff() { + + FormsAuth.SignOut(); + + return RedirectToAction("Index", "Home"); + } + + public ActionResult Register() { + + ViewData["PasswordLength"] = MembershipService.MinPasswordLength; + + return View(); + } + + [AcceptVerbs(HttpVerbs.Post)] + public ActionResult Register(string userName, string email, string password, string confirmPassword) { + + ViewData["PasswordLength"] = MembershipService.MinPasswordLength; + + if (ValidateRegistration(userName, email, password, confirmPassword)) { + // Attempt to register the user + MembershipCreateStatus createStatus = MembershipService.CreateUser(userName, password, email); + + if (createStatus == MembershipCreateStatus.Success) { + FormsAuth.SignIn(userName, false /* createPersistentCookie */); + return RedirectToAction("Index", "Home"); + } else { + ModelState.AddModelError("_FORM", ErrorCodeToString(createStatus)); + } + } + + // If we got this far, something failed, redisplay form + return View(); + } + + [Authorize] + public ActionResult ChangePassword() { + + ViewData["PasswordLength"] = MembershipService.MinPasswordLength; + + return View(); + } + + [Authorize] + [AcceptVerbs(HttpVerbs.Post)] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", + Justification = "Exceptions result in password not being changed.")] + public ActionResult ChangePassword(string currentPassword, string newPassword, string confirmPassword) { + + ViewData["PasswordLength"] = MembershipService.MinPasswordLength; + + if (!ValidateChangePassword(currentPassword, newPassword, confirmPassword)) { + return View(); + } + + try { + if (MembershipService.ChangePassword(User.Identity.Name, currentPassword, newPassword)) { + return RedirectToAction("ChangePasswordSuccess"); + } else { + ModelState.AddModelError("_FORM", "The current password is incorrect or the new password is invalid."); + return View(); + } + } catch { + ModelState.AddModelError("_FORM", "The current password is incorrect or the new password is invalid."); + return View(); + } + } + + public ActionResult ChangePasswordSuccess() { + + return View(); + } + + protected override void OnActionExecuting(ActionExecutingContext filterContext) { + if (filterContext.HttpContext.User.Identity is WindowsIdentity) { + throw new InvalidOperationException("Windows authentication is not supported."); + } + } + + #region Validation Methods + + private bool ValidateChangePassword(string currentPassword, string newPassword, string confirmPassword) { + if (String.IsNullOrEmpty(currentPassword)) { + ModelState.AddModelError("currentPassword", "You must specify a current password."); + } + if (newPassword == null || newPassword.Length < MembershipService.MinPasswordLength) { + ModelState.AddModelError("newPassword", + String.Format(CultureInfo.CurrentCulture, + "You must specify a new password of {0} or more characters.", + MembershipService.MinPasswordLength)); + } + + if (!String.Equals(newPassword, confirmPassword, StringComparison.Ordinal)) { + ModelState.AddModelError("_FORM", "The new password and confirmation password do not match."); + } + + return ModelState.IsValid; + } + + private bool ValidateLogOn(string userName, string password) { + if (String.IsNullOrEmpty(userName)) { + ModelState.AddModelError("username", "You must specify a username."); + } + if (String.IsNullOrEmpty(password)) { + ModelState.AddModelError("password", "You must specify a password."); + } + if (!MembershipService.ValidateUser(userName, password)) { + ModelState.AddModelError("_FORM", "The username or password provided is incorrect."); + } + + return ModelState.IsValid; + } + + private bool ValidateRegistration(string userName, string email, string password, string confirmPassword) { + if (String.IsNullOrEmpty(userName)) { + ModelState.AddModelError("username", "You must specify a username."); + } + if (String.IsNullOrEmpty(email)) { + ModelState.AddModelError("email", "You must specify an email address."); + } + if (password == null || password.Length < MembershipService.MinPasswordLength) { + ModelState.AddModelError("password", + String.Format(CultureInfo.CurrentCulture, + "You must specify a password of {0} or more characters.", + MembershipService.MinPasswordLength)); + } + if (!String.Equals(password, confirmPassword, StringComparison.Ordinal)) { + ModelState.AddModelError("_FORM", "The new password and confirmation password do not match."); + } + return ModelState.IsValid; + } + + private static string ErrorCodeToString(MembershipCreateStatus createStatus) { + // See http://msdn.microsoft.com/en-us/library/system.web.security.membershipcreatestatus.aspx for + // a full list of status codes. + switch (createStatus) { + case MembershipCreateStatus.DuplicateUserName: + return "Username already exists. Please enter a different user name."; + + case MembershipCreateStatus.DuplicateEmail: + return "A username for that e-mail address already exists. Please enter a different e-mail address."; + + case MembershipCreateStatus.InvalidPassword: + return "The password provided is invalid. Please enter a valid password value."; + + case MembershipCreateStatus.InvalidEmail: + return "The e-mail address provided is invalid. Please check the value and try again."; + + case MembershipCreateStatus.InvalidAnswer: + return "The password retrieval answer provided is invalid. Please check the value and try again."; + + case MembershipCreateStatus.InvalidQuestion: + return "The password retrieval question provided is invalid. Please check the value and try again."; + + case MembershipCreateStatus.InvalidUserName: + return "The user name provided is invalid. Please check the value and try again."; + + case MembershipCreateStatus.ProviderError: + return "The authentication provider returned an error. Please verify your entry and try again. If the problem persists, please contact your system administrator."; + + case MembershipCreateStatus.UserRejected: + return "The user creation request has been canceled. Please verify your entry and try again. If the problem persists, please contact your system administrator."; + + default: + return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator."; + } + } + #endregion + } + + // The FormsAuthentication type is sealed and contains static members, so it is difficult to + // unit test code that calls its members. The interface and helper class below demonstrate + // how to create an abstract wrapper around such a type in order to make the AccountController + // code unit testable. + + public interface IFormsAuthentication { + void SignIn(string userName, bool createPersistentCookie); + void SignOut(); + } + + public class FormsAuthenticationService : IFormsAuthentication { + public void SignIn(string userName, bool createPersistentCookie) { + FormsAuthentication.SetAuthCookie(userName, createPersistentCookie); + } + public void SignOut() { + FormsAuthentication.SignOut(); + } + } + + public interface IMembershipService { + int MinPasswordLength { get; } + + bool ValidateUser(string userName, string password); + MembershipCreateStatus CreateUser(string userName, string password, string email); + bool ChangePassword(string userName, string oldPassword, string newPassword); + } + + public class AccountMembershipService : IMembershipService { + private MembershipProvider _provider; + + public AccountMembershipService() + : this(null) { + } + + public AccountMembershipService(MembershipProvider provider) { + _provider = provider ?? Membership.Provider; + } + + public int MinPasswordLength { + get { + return _provider.MinRequiredPasswordLength; + } + } + + public bool ValidateUser(string userName, string password) { + return _provider.ValidateUser(userName, password); + } + + public MembershipCreateStatus CreateUser(string userName, string password, string email) { + MembershipCreateStatus status; + _provider.CreateUser(userName, password, email, null, null, true, null, out status); + return status; + } + + public bool ChangePassword(string userName, string oldPassword, string newPassword) { + MembershipUser currentUser = _provider.GetUser(userName, true /* userIsOnline */); + return currentUser.ChangePassword(oldPassword, newPassword); + } + } +} |