summaryrefslogtreecommitdiffstats
path: root/projecttemplates/MvcRelyingParty/Controllers/AccountController.cs
diff options
context:
space:
mode:
Diffstat (limited to 'projecttemplates/MvcRelyingParty/Controllers/AccountController.cs')
-rw-r--r--projecttemplates/MvcRelyingParty/Controllers/AccountController.cs292
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);
+ }
+ }
+}