2009-11-07 22:49:58 +00:00
using System ;
using System.Diagnostics.CodeAnalysis ;
2010-04-16 13:33:45 -07:00
using Orchard.Localization ;
2009-11-07 22:49:58 +00:00
using System.Security.Principal ;
using System.Web.Mvc ;
using System.Web.Security ;
2010-01-06 04:49:55 +00:00
using Orchard.Logging ;
2010-04-05 22:36:30 -07:00
using Orchard.Mvc.Extensions ;
2009-11-12 03:46:14 +00:00
using Orchard.Security ;
2010-09-30 16:25:25 -07:00
using Orchard.Themes ;
2010-03-02 17:23:45 -08:00
using Orchard.Users.Services ;
2010-01-06 04:31:38 +00:00
using Orchard.Users.ViewModels ;
2010-08-31 12:57:15 -07:00
using Orchard.Settings ;
using JetBrains.Annotations ;
using Orchard.ContentManagement ;
using Orchard.Users.Models ;
2009-11-07 22:49:58 +00:00
2010-01-06 04:31:38 +00:00
namespace Orchard.Users.Controllers {
2010-09-30 16:37:32 -07:00
[HandleError, Themed]
2009-11-07 22:49:58 +00:00
public class AccountController : Controller {
2009-11-12 03:46:14 +00:00
private readonly IAuthenticationService _authenticationService ;
private readonly IMembershipService _membershipService ;
2010-03-02 17:23:45 -08:00
private readonly IUserService _userService ;
2009-11-07 22:49:58 +00:00
2010-01-06 04:49:55 +00:00
public AccountController (
IAuthenticationService authenticationService ,
2010-03-02 17:23:45 -08:00
IMembershipService membershipService ,
IUserService userService ) {
2009-11-12 03:46:14 +00:00
_authenticationService = authenticationService ;
_membershipService = membershipService ;
2010-03-02 17:23:45 -08:00
_userService = userService ;
2010-01-06 04:49:55 +00:00
Logger = NullLogger . Instance ;
2010-04-16 13:33:45 -07:00
T = NullLocalizer . Instance ;
2009-11-12 03:46:14 +00:00
}
2009-11-07 22:49:58 +00:00
2010-01-06 04:49:55 +00:00
public ILogger Logger { get ; set ; }
2010-04-16 13:33:45 -07:00
public Localizer T { get ; set ; }
2010-08-31 12:57:15 -07:00
protected virtual ISite CurrentSite { get ; [ UsedImplicitly ] private set ; }
2010-01-06 04:49:55 +00:00
2010-03-09 00:41:17 -08:00
public ActionResult AccessDenied ( ) {
var returnUrl = Request . QueryString [ "ReturnUrl" ] ;
2010-01-06 04:49:55 +00:00
var currentUser = _authenticationService . GetAuthenticatedUser ( ) ;
if ( currentUser = = null ) {
Logger . Information ( "Access denied to anonymous request on {0}" , returnUrl ) ;
2010-03-09 00:41:17 -08:00
return View ( "LogOn" , new LogOnViewModel { Title = "Access Denied" } ) ;
2010-01-06 04:49:55 +00:00
}
2010-01-06 04:31:38 +00:00
2010-03-09 00:41:17 -08:00
//TODO: (erikpo) Add a setting for whether or not to log access denieds since these can fill up a database pretty fast from bots on a high traffic site
2010-01-06 04:49:55 +00:00
Logger . Information ( "Access denied to user #{0} '{1}' on {2}" , currentUser . Id , currentUser . UserName , returnUrl ) ;
2010-03-09 00:41:17 -08:00
2010-09-01 15:51:41 -07:00
return View ( ) ;
2009-11-07 22:49:58 +00:00
}
2010-03-09 00:41:17 -08:00
public ActionResult LogOn ( ) {
if ( _authenticationService . GetAuthenticatedUser ( ) ! = null )
2010-03-03 10:21:59 -08:00
return Redirect ( "~/" ) ;
2010-03-09 00:41:17 -08:00
2010-10-14 14:51:41 -07:00
return View ( new LogOnViewModel { Title = "Log On" } ) ;
2010-01-06 04:31:38 +00:00
}
2010-04-05 22:36:30 -07:00
[HttpPost]
2009-11-07 22:49:58 +00:00
[ SuppressMessage ( "Microsoft.Design" , "CA1054:UriParametersShouldNotBeStrings" ,
Justification = "Needs to take same parameter type as Controller.Redirect()" ) ]
2010-05-14 22:30:16 -07:00
public ActionResult LogOn ( string userNameOrEmail , string password , bool rememberMe , string returnUrl ) {
2010-04-16 13:14:45 -07:00
var user = ValidateLogOn ( userNameOrEmail , password ) ;
2009-11-12 03:46:14 +00:00
if ( ! ModelState . IsValid ) {
2010-10-14 14:51:41 -07:00
return View ( new LogOnViewModel { Title = "Log On" } ) ;
2009-11-07 22:49:58 +00:00
}
2009-11-12 03:46:14 +00:00
_authenticationService . SignIn ( user , rememberMe ) ;
2010-05-14 22:30:16 -07:00
if ( string . IsNullOrEmpty ( returnUrl ) )
return new RedirectResult ( "~/" ) ;
return new RedirectResult ( returnUrl ) ;
2009-11-07 22:49:58 +00:00
}
2010-05-14 22:30:16 -07:00
public ActionResult LogOff ( string returnUrl ) {
2009-11-12 03:46:14 +00:00
_authenticationService . SignOut ( ) ;
2009-11-07 22:49:58 +00:00
2010-05-14 22:30:16 -07:00
if ( string . IsNullOrEmpty ( returnUrl ) )
return new RedirectResult ( "~/" ) ;
return new RedirectResult ( returnUrl ) ;
2009-11-07 22:49:58 +00:00
}
2009-11-12 03:46:14 +00:00
int MinPasswordLength {
get {
2009-11-14 06:24:54 +00:00
return _membershipService . GetSettings ( ) . MinRequiredPasswordLength ;
2009-11-12 03:46:14 +00:00
}
}
2009-11-07 22:49:58 +00:00
public ActionResult Register ( ) {
2010-08-31 12:57:15 -07:00
// ensure users can register
var registrationSettings = CurrentSite . As < RegistrationSettingsPart > ( ) ;
if ( ! registrationSettings . UsersCanRegister ) {
2010-10-14 11:30:58 -07:00
return HttpNotFound ( ) ;
2010-08-31 12:57:15 -07:00
}
2009-11-12 03:46:14 +00:00
ViewData [ "PasswordLength" ] = MinPasswordLength ;
2009-11-07 22:49:58 +00:00
2010-09-01 15:51:41 -07:00
return View ( ) ;
2009-11-07 22:49:58 +00:00
}
2010-01-21 21:13:35 +00:00
[HttpPost]
2009-11-07 22:49:58 +00:00
public ActionResult Register ( string userName , string email , string password , string confirmPassword ) {
2010-08-31 12:57:15 -07:00
// ensure users can register
var registrationSettings = CurrentSite . As < RegistrationSettingsPart > ( ) ;
if ( ! registrationSettings . UsersCanRegister ) {
2010-10-14 11:30:58 -07:00
return HttpNotFound ( ) ;
2010-08-31 12:57:15 -07:00
}
2009-11-12 03:46:14 +00:00
ViewData [ "PasswordLength" ] = MinPasswordLength ;
2009-11-07 22:49:58 +00:00
if ( ValidateRegistration ( userName , email , password , confirmPassword ) ) {
// Attempt to register the user
2010-09-01 14:39:28 -07:00
var user = _membershipService . CreateUser ( new CreateUserParams ( userName , password , email , null , null , false ) ) ;
2009-11-07 22:49:58 +00:00
2009-11-12 03:46:14 +00:00
if ( user ! = null ) {
2010-09-01 14:39:28 -07:00
if ( user . As < UserPart > ( ) . EmailStatus = = UserStatus . Pending ) {
string challengeToken = _membershipService . GetEncryptedChallengeToken ( user . As < UserPart > ( ) ) ;
_membershipService . SendChallengeEmail ( user . As < UserPart > ( ) , Url . AbsoluteAction ( ( ) = > Url . Action ( "ChallengeEmail" , "Account" , new { Area = "Orchard.Users" , token = challengeToken } ) ) ) ;
return RedirectToAction ( "ChallengeEmailSent" ) ;
}
2009-11-12 03:46:14 +00:00
_authenticationService . SignIn ( user , false /* createPersistentCookie */ ) ;
2010-01-06 04:31:38 +00:00
return Redirect ( "~/" ) ;
2009-11-07 22:49:58 +00:00
}
else {
2010-04-16 13:33:45 -07:00
ModelState . AddModelError ( "_FORM" , T ( ErrorCodeToString ( /*createStatus*/ MembershipCreateStatus . ProviderError ) ) ) ;
2009-11-07 22:49:58 +00:00
}
}
// If we got this far, something failed, redisplay form
2009-12-22 16:57:07 +00:00
return Register ( ) ;
2009-11-07 22:49:58 +00:00
}
[Authorize]
public ActionResult ChangePassword ( ) {
2009-11-12 03:46:14 +00:00
ViewData [ "PasswordLength" ] = MinPasswordLength ;
2009-11-07 22:49:58 +00:00
2010-09-01 15:51:41 -07:00
return View ( ) ;
2009-11-07 22:49:58 +00:00
}
[Authorize]
2010-01-21 21:13:35 +00:00
[HttpPost]
2009-11-07 22:49:58 +00:00
[ SuppressMessage ( "Microsoft.Design" , "CA1031:DoNotCatchGeneralExceptionTypes" ,
Justification = "Exceptions result in password not being changed." ) ]
public ActionResult ChangePassword ( string currentPassword , string newPassword , string confirmPassword ) {
2009-11-12 03:46:14 +00:00
ViewData [ "PasswordLength" ] = MinPasswordLength ;
2009-11-07 22:49:58 +00:00
if ( ! ValidateChangePassword ( currentPassword , newPassword , confirmPassword ) ) {
return View ( ) ;
}
try {
2009-11-19 05:17:02 +00:00
var validated = _membershipService . ValidateUser ( User . Identity . Name , currentPassword ) ;
2010-01-06 04:31:38 +00:00
2009-11-19 05:17:02 +00:00
if ( validated ! = null ) {
_membershipService . SetPassword ( validated , newPassword ) ;
2009-11-07 22:49:58 +00:00
return RedirectToAction ( "ChangePasswordSuccess" ) ;
}
else {
2010-04-16 13:14:45 -07:00
ModelState . AddModelError ( "_FORM" ,
2010-04-16 13:33:45 -07:00
T ( "The current password is incorrect or the new password is invalid." ) ) ;
2009-12-22 16:57:07 +00:00
return ChangePassword ( ) ;
2009-11-07 22:49:58 +00:00
}
}
catch {
2010-04-16 13:33:45 -07:00
ModelState . AddModelError ( "_FORM" , T ( "The current password is incorrect or the new password is invalid." ) ) ;
2009-12-22 16:57:07 +00:00
return ChangePassword ( ) ;
2009-11-07 22:49:58 +00:00
}
}
public ActionResult ChangePasswordSuccess ( ) {
2010-09-01 15:51:41 -07:00
return View ( ) ;
2009-11-07 22:49:58 +00:00
}
2010-09-01 14:39:28 -07:00
public ActionResult ChallengeEmailSent ( ) {
2010-09-02 21:29:10 -07:00
return View ( ) ;
2010-09-01 14:39:28 -07:00
}
2010-09-01 18:18:53 -07:00
public ActionResult ChallengeEmailSuccess ( ) {
2010-09-02 21:29:10 -07:00
return View ( ) ;
2010-09-01 18:18:53 -07:00
}
public ActionResult ChallengeEmailFail ( ) {
2010-09-02 21:29:10 -07:00
return View ( ) ;
2010-09-01 18:18:53 -07:00
}
2010-09-01 14:39:28 -07:00
public ActionResult ChallengeEmail ( string token ) {
var user = _membershipService . ValidateChallengeToken ( token ) ;
if ( user ! = null ) {
_authenticationService . SignIn ( user , false /* createPersistentCookie */ ) ;
2010-09-01 18:18:53 -07:00
return RedirectToAction ( "ChallengeEmailSuccess" ) ;
2010-09-01 14:39:28 -07:00
}
2010-09-01 18:18:53 -07:00
return RedirectToAction ( "ChallengeEmailFail" ) ;
2010-09-01 14:39:28 -07:00
}
2009-11-07 22:49:58 +00:00
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 ) ) {
2010-04-16 13:33:45 -07:00
ModelState . AddModelError ( "currentPassword" , T ( "You must specify a current password." ) ) ;
2009-11-07 22:49:58 +00:00
}
2009-11-12 03:46:14 +00:00
if ( newPassword = = null | | newPassword . Length < MinPasswordLength ) {
2010-04-16 13:33:45 -07:00
ModelState . AddModelError ( "newPassword" , T ( "You must specify a new password of {0} or more characters." , MinPasswordLength ) ) ;
2009-11-07 22:49:58 +00:00
}
if ( ! String . Equals ( newPassword , confirmPassword , StringComparison . Ordinal ) ) {
2010-04-16 13:33:45 -07:00
ModelState . AddModelError ( "_FORM" , T ( "The new password and confirmation password do not match." ) ) ;
2009-11-07 22:49:58 +00:00
}
return ModelState . IsValid ;
}
2010-04-16 13:14:45 -07:00
private IUser ValidateLogOn ( string userNameOrEmail , string password ) {
2010-05-13 16:31:40 -07:00
bool validate = true ;
2010-04-16 13:14:45 -07:00
if ( String . IsNullOrEmpty ( userNameOrEmail ) ) {
2010-04-16 13:33:45 -07:00
ModelState . AddModelError ( "userNameOrEmail" , T ( "You must specify a username or e-mail." ) ) ;
2010-05-13 16:31:40 -07:00
validate = false ;
2009-11-07 22:49:58 +00:00
}
if ( String . IsNullOrEmpty ( password ) ) {
2010-04-16 13:33:45 -07:00
ModelState . AddModelError ( "password" , T ( "You must specify a password." ) ) ;
2010-05-13 16:31:40 -07:00
validate = false ;
2009-11-07 22:49:58 +00:00
}
2010-05-13 16:31:40 -07:00
if ( ! validate )
return null ;
2010-04-16 13:14:45 -07:00
var user = _membershipService . ValidateUser ( userNameOrEmail , password ) ;
2009-11-12 03:46:14 +00:00
if ( user = = null ) {
2010-04-16 13:33:45 -07:00
ModelState . AddModelError ( "_FORM" , T ( "The username or e-mail or password provided is incorrect." ) ) ;
2009-11-07 22:49:58 +00:00
}
2009-11-12 03:46:14 +00:00
return user ;
2009-11-07 22:49:58 +00:00
}
private bool ValidateRegistration ( string userName , string email , string password , string confirmPassword ) {
2010-05-13 16:31:40 -07:00
bool validate = true ;
2009-11-07 22:49:58 +00:00
if ( String . IsNullOrEmpty ( userName ) ) {
2010-04-16 13:33:45 -07:00
ModelState . AddModelError ( "username" , T ( "You must specify a username." ) ) ;
2010-05-13 16:31:40 -07:00
validate = false ;
2009-11-07 22:49:58 +00:00
}
if ( String . IsNullOrEmpty ( email ) ) {
2010-04-16 13:33:45 -07:00
ModelState . AddModelError ( "email" , T ( "You must specify an email address." ) ) ;
2010-05-13 16:31:40 -07:00
validate = false ;
2009-11-07 22:49:58 +00:00
}
2010-05-13 16:31:40 -07:00
if ( ! validate )
return false ;
2010-03-02 17:23:45 -08:00
string userUnicityMessage = _userService . VerifyUserUnicity ( userName , email ) ;
if ( userUnicityMessage ! = null ) {
2010-04-16 13:33:45 -07:00
ModelState . AddModelError ( "userExists" , T ( userUnicityMessage ) ) ;
2010-03-02 17:23:45 -08:00
}
2009-11-12 03:46:14 +00:00
if ( password = = null | | password . Length < MinPasswordLength ) {
2010-04-16 13:33:45 -07:00
ModelState . AddModelError ( "password" , T ( "You must specify a password of {0} or more characters." , MinPasswordLength ) ) ;
2009-11-07 22:49:58 +00:00
}
if ( ! String . Equals ( password , confirmPassword , StringComparison . Ordinal ) ) {
2010-04-16 13:33:45 -07:00
ModelState . AddModelError ( "_FORM" , T ( "The new password and confirmation password do not match." ) ) ;
2009-11-07 22:49:58 +00:00
}
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
}
}