2021-05-28 14:45:14 +08:00
using System ;
2019-05-14 21:03:13 +08:00
using System.Collections.Generic ;
using System.Diagnostics.CodeAnalysis ;
2022-01-14 17:32:07 +08:00
using System.Linq ;
2019-03-10 05:58:20 +08:00
using System.Text.RegularExpressions ;
2019-05-14 21:03:13 +08:00
using System.Web.Mvc ;
using System.Web.Security ;
2019-03-10 05:58:20 +08:00
using Orchard.ContentManagement ;
2015-12-14 05:21:02 +08:00
using Orchard.Localization ;
using Orchard.Logging ;
using Orchard.Mvc ;
using Orchard.Mvc.Extensions ;
using Orchard.Security ;
2019-05-14 21:03:13 +08:00
using Orchard.Services ;
2015-12-14 05:21:02 +08:00
using Orchard.Themes ;
using Orchard.UI.Notify ;
using Orchard.Users.Events ;
2016-07-29 03:59:13 +08:00
using Orchard.Users.Models ;
using Orchard.Users.Services ;
2015-12-14 05:21:02 +08:00
using Orchard.Utility.Extensions ;
namespace Orchard.Users.Controllers {
[HandleError, Themed]
public class AccountController : Controller {
private readonly IAuthenticationService _authenticationService ;
private readonly IMembershipService _membershipService ;
private readonly IUserService _userService ;
private readonly IOrchardServices _orchardServices ;
private readonly IUserEventHandler _userEventHandler ;
2016-07-29 03:59:13 +08:00
private readonly IClock _clock ;
2022-01-14 16:36:26 +08:00
private readonly IAccountValidationService _accountValidationService ;
2015-12-14 05:21:02 +08:00
public AccountController (
2016-07-29 03:59:13 +08:00
IAuthenticationService authenticationService ,
2015-12-14 05:21:02 +08:00
IMembershipService membershipService ,
2016-07-29 03:59:13 +08:00
IUserService userService ,
2015-12-14 05:21:02 +08:00
IOrchardServices orchardServices ,
2016-07-29 03:59:13 +08:00
IUserEventHandler userEventHandler ,
2022-01-14 16:36:26 +08:00
IClock clock ,
IAccountValidationService accountValidationService ) {
2016-07-29 03:59:13 +08:00
2015-12-14 05:21:02 +08:00
_authenticationService = authenticationService ;
_membershipService = membershipService ;
_userService = userService ;
_orchardServices = orchardServices ;
_userEventHandler = userEventHandler ;
2016-07-29 03:59:13 +08:00
_clock = clock ;
2022-01-14 16:36:26 +08:00
_accountValidationService = accountValidationService ;
2016-07-29 03:59:13 +08:00
2015-12-14 05:21:02 +08:00
Logger = NullLogger . Instance ;
T = NullLocalizer . Instance ;
}
public ILogger Logger { get ; set ; }
public Localizer T { get ; set ; }
[AlwaysAccessible]
public ActionResult AccessDenied ( ) {
var returnUrl = Request . QueryString [ "ReturnUrl" ] ;
var currentUser = _authenticationService . GetAuthenticatedUser ( ) ;
if ( currentUser = = null ) {
Logger . Information ( "Access denied to anonymous request on {0}" , returnUrl ) ;
var shape = _orchardServices . New . LogOn ( ) . Title ( T ( "Access Denied" ) . Text ) ;
2016-07-29 03:59:13 +08:00
return new ShapeResult ( this , shape ) ;
2015-12-14 05:21:02 +08:00
}
Logger . Information ( "Access denied to user #{0} '{1}' on {2}" , currentUser . Id , currentUser . UserName , returnUrl ) ;
_userEventHandler . AccessDenied ( currentUser ) ;
return View ( ) ;
}
[AlwaysAccessible]
public ActionResult LogOn ( string returnUrl ) {
if ( _authenticationService . GetAuthenticatedUser ( ) ! = null )
return this . RedirectLocal ( returnUrl ) ;
var shape = _orchardServices . New . LogOn ( ) . Title ( T ( "Log On" ) . Text ) ;
2016-07-29 03:59:13 +08:00
return new ShapeResult ( this , shape ) ;
2015-12-14 05:21:02 +08:00
}
[HttpPost]
[AlwaysAccessible]
[ValidateInput(false)]
[ SuppressMessage ( "Microsoft.Design" , "CA1054:UriParametersShouldNotBeStrings" ,
Justification = "Needs to take same parameter type as Controller.Redirect()" ) ]
public ActionResult LogOn ( string userNameOrEmail , string password , string returnUrl , bool rememberMe = false ) {
_userEventHandler . LoggingIn ( userNameOrEmail , password ) ;
var user = ValidateLogOn ( userNameOrEmail , password ) ;
if ( ! ModelState . IsValid ) {
var shape = _orchardServices . New . LogOn ( ) . Title ( T ( "Log On" ) . Text ) ;
2016-07-29 03:59:13 +08:00
return new ShapeResult ( this , shape ) ;
}
var membershipSettings = _membershipService . GetSettings ( ) ;
if ( user ! = null & &
membershipSettings . EnableCustomPasswordPolicy & &
membershipSettings . EnablePasswordExpiration & &
_membershipService . PasswordIsExpired ( user , membershipSettings . PasswordExpirationTimeInDays ) ) {
return RedirectToAction ( "ChangeExpiredPassword" , new { username = user . UserName } ) ;
2015-12-14 05:21:02 +08:00
}
2022-01-14 17:32:07 +08:00
if ( user ! = null & & user . As < UserPart > ( ) . ForcePasswordChange ) {
return RedirectToAction ( "ChangeExpiredPassword" , new { username = user . UserName } ) ;
}
2015-12-14 05:21:02 +08:00
_authenticationService . SignIn ( user , rememberMe ) ;
_userEventHandler . LoggedIn ( user ) ;
return this . RedirectLocal ( returnUrl ) ;
}
public ActionResult LogOff ( string returnUrl ) {
_authenticationService . SignOut ( ) ;
2015-12-14 06:46:19 +08:00
var loggedUser = _authenticationService . GetAuthenticatedUser ( ) ;
if ( loggedUser ! = null ) {
_userEventHandler . LoggedOut ( loggedUser ) ;
}
2015-12-14 05:21:02 +08:00
return this . RedirectLocal ( returnUrl ) ;
}
[AlwaysAccessible]
public ActionResult Register ( ) {
// ensure users can register
2016-07-29 03:59:13 +08:00
var membershipSettings = _membershipService . GetSettings ( ) ;
if ( ! membershipSettings . UsersCanRegister ) {
2015-12-14 05:21:02 +08:00
return HttpNotFound ( ) ;
}
2016-07-29 03:59:13 +08:00
ViewData [ "PasswordLength" ] = membershipSettings . GetMinimumPasswordLength ( ) ;
2019-12-20 04:25:45 +08:00
ViewData [ "LowercaseRequirement" ] = membershipSettings . GetPasswordLowercaseRequirement ( ) ;
ViewData [ "UppercaseRequirement" ] = membershipSettings . GetPasswordUppercaseRequirement ( ) ;
ViewData [ "SpecialCharacterRequirement" ] = membershipSettings . GetPasswordSpecialRequirement ( ) ;
ViewData [ "NumberRequirement" ] = membershipSettings . GetPasswordNumberRequirement ( ) ;
2015-12-14 05:21:02 +08:00
var shape = _orchardServices . New . Register ( ) ;
2016-07-29 03:59:13 +08:00
return new ShapeResult ( this , shape ) ;
2015-12-14 05:21:02 +08:00
}
[HttpPost]
[AlwaysAccessible]
[ValidateInput(false)]
public ActionResult Register ( string userName , string email , string password , string confirmPassword , string returnUrl = null ) {
// ensure users can register
2016-07-29 03:59:13 +08:00
var membershipSettings = _membershipService . GetSettings ( ) ;
if ( ! membershipSettings . UsersCanRegister ) {
2015-12-14 05:21:02 +08:00
return HttpNotFound ( ) ;
}
2016-07-29 03:59:13 +08:00
ViewData [ "PasswordLength" ] = membershipSettings . GetMinimumPasswordLength ( ) ;
2019-12-20 04:25:45 +08:00
ViewData [ "LowercaseRequirement" ] = membershipSettings . GetPasswordLowercaseRequirement ( ) ;
ViewData [ "UppercaseRequirement" ] = membershipSettings . GetPasswordUppercaseRequirement ( ) ;
ViewData [ "SpecialCharacterRequirement" ] = membershipSettings . GetPasswordSpecialRequirement ( ) ;
ViewData [ "NumberRequirement" ] = membershipSettings . GetPasswordNumberRequirement ( ) ;
2015-12-14 05:21:02 +08:00
if ( ValidateRegistration ( userName , email , password , confirmPassword ) ) {
// Attempt to register the user
// No need to report this to IUserEventHandler because _membershipService does that for us
2022-01-14 17:32:07 +08:00
var user = _membershipService . CreateUser ( new CreateUserParams ( userName , password , email , null , null , false , false ) ) ;
2015-12-14 05:21:02 +08:00
if ( user ! = null ) {
2016-07-29 03:59:13 +08:00
if ( user . As < UserPart > ( ) . EmailStatus = = UserStatus . Pending ) {
2015-12-14 05:21:02 +08:00
var siteUrl = _orchardServices . WorkContext . CurrentSite . BaseUrl ;
2016-07-29 03:59:13 +08:00
if ( String . IsNullOrWhiteSpace ( siteUrl ) ) {
2015-12-14 05:21:02 +08:00
siteUrl = HttpContext . Request . ToRootUrlString ( ) ;
}
2016-07-29 03:59:13 +08:00
_userService . SendChallengeEmail ( user . As < UserPart > ( ) , nonce = > Url . MakeAbsolute ( Url . Action ( "ChallengeEmail" , "Account" , new { Area = "Orchard.Users" , nonce = nonce } ) , siteUrl ) ) ;
2015-12-14 05:21:02 +08:00
_userEventHandler . SentChallengeEmail ( user ) ;
2015-12-14 06:46:19 +08:00
return RedirectToAction ( "ChallengeEmailSent" , new { ReturnUrl = returnUrl } ) ;
2015-12-14 05:21:02 +08:00
}
if ( user . As < UserPart > ( ) . RegistrationStatus = = UserStatus . Pending ) {
2015-12-14 06:46:19 +08:00
return RedirectToAction ( "RegistrationPending" , new { ReturnUrl = returnUrl } ) ;
2015-12-14 05:21:02 +08:00
}
2015-12-14 06:46:19 +08:00
_userEventHandler . LoggingIn ( userName , password ) ;
2015-12-14 05:21:02 +08:00
_authenticationService . SignIn ( user , false /* createPersistentCookie */ ) ;
2015-12-14 06:46:19 +08:00
_userEventHandler . LoggedIn ( user ) ;
2015-12-14 05:21:02 +08:00
return this . RedirectLocal ( returnUrl ) ;
}
2016-07-29 03:59:13 +08:00
2015-12-14 05:21:02 +08:00
ModelState . AddModelError ( "_FORM" , T ( ErrorCodeToString ( /*createStatus*/ MembershipCreateStatus . ProviderError ) ) ) ;
}
// If we got this far, something failed, redisplay form
var shape = _orchardServices . New . Register ( ) ;
2016-07-29 03:59:13 +08:00
return new ShapeResult ( this , shape ) ;
2015-12-14 05:21:02 +08:00
}
[AlwaysAccessible]
public ActionResult RequestLostPassword ( ) {
// ensure users can request lost password
2016-07-29 03:59:13 +08:00
var membershipSettings = _membershipService . GetSettings ( ) ;
if ( ! membershipSettings . EnableLostPassword ) {
2015-12-14 05:21:02 +08:00
return HttpNotFound ( ) ;
}
return View ( ) ;
}
[HttpPost]
[AlwaysAccessible]
public ActionResult RequestLostPassword ( string username ) {
// ensure users can request lost password
2016-07-29 03:59:13 +08:00
var membershipSettings = _membershipService . GetSettings ( ) ;
if ( ! membershipSettings . EnableLostPassword ) {
2015-12-14 05:21:02 +08:00
return HttpNotFound ( ) ;
}
2019-05-14 21:03:13 +08:00
if ( string . IsNullOrWhiteSpace ( username ) ) {
2015-12-14 05:21:02 +08:00
ModelState . AddModelError ( "username" , T ( "You must specify a username or e-mail." ) ) ;
return View ( ) ;
}
var siteUrl = _orchardServices . WorkContext . CurrentSite . BaseUrl ;
2019-05-14 21:03:13 +08:00
if ( string . IsNullOrWhiteSpace ( siteUrl ) ) {
2015-12-14 05:21:02 +08:00
siteUrl = HttpContext . Request . ToRootUrlString ( ) ;
}
2019-08-25 23:17:20 +08:00
_userService . SendLostPasswordEmail ( username , nonce = >
Url . MakeAbsolute ( Url . Action ( "LostPassword" , "Account" , new { Area = "Orchard.Users" , nonce } ) , siteUrl ) ) ;
2015-12-14 05:21:02 +08:00
2019-08-25 23:17:20 +08:00
_orchardServices . Notifier . Information ( T ( "If your username or email is correct, we will send you an email with a link to reset your password." ) ) ;
2016-07-29 03:59:13 +08:00
2015-12-14 05:21:02 +08:00
return RedirectToAction ( "LogOn" ) ;
}
2022-01-14 17:32:07 +08:00
[AlwaysAccessible]
public ActionResult RequestChallengeEmail ( string email = null ) {
// ensure users can request lost password
var membershipSettings = _membershipService . GetSettings ( ) ;
if ( ! membershipSettings . UsersMustValidateEmail ) {
return HttpNotFound ( ) ;
}
return View ( model : email ) ;
}
[HttpPost, ActionName("RequestChallengeEmail")]
[AlwaysAccessible]
public ActionResult RequestChallengeEmailPOST ( string username ) {
// ensure users can request lost password
var membershipSettings = _membershipService . GetSettings ( ) ;
if ( ! membershipSettings . UsersMustValidateEmail ) {
return HttpNotFound ( ) ;
}
if ( string . IsNullOrWhiteSpace ( username ) ) {
ModelState . AddModelError ( "username" , T ( "You must specify a username or e-mail." ) ) ;
return View ( ) ;
}
// Get the user
var user = _userService . GetUserByNameOrEmail ( username ) ;
if ( user ! = null & & user . EmailStatus = = UserStatus . Pending ) {
var siteUrl = _orchardServices . WorkContext . CurrentSite . BaseUrl ;
if ( string . IsNullOrWhiteSpace ( siteUrl ) ) {
siteUrl = HttpContext . Request . ToRootUrlString ( ) ;
}
_userService . SendChallengeEmail ( user . As < UserPart > ( ) , nonce = > Url . MakeAbsolute ( Url . Action ( "ChallengeEmail" , "Account" , new { Area = "Orchard.Users" , nonce = nonce } ) , siteUrl ) ) ;
_userEventHandler . SentChallengeEmail ( user ) ;
}
return RedirectToAction ( "ChallengeEmailSent" ) ;
}
2015-12-14 05:21:02 +08:00
[Authorize]
[AlwaysAccessible]
public ActionResult ChangePassword ( ) {
2016-07-29 03:59:13 +08:00
var membershipSettings = _membershipService . GetSettings ( ) ;
ViewData [ "PasswordLength" ] = membershipSettings . GetMinimumPasswordLength ( ) ;
2019-12-20 04:25:45 +08:00
ViewData [ "LowercaseRequirement" ] = membershipSettings . GetPasswordLowercaseRequirement ( ) ;
ViewData [ "UppercaseRequirement" ] = membershipSettings . GetPasswordUppercaseRequirement ( ) ;
ViewData [ "SpecialCharacterRequirement" ] = membershipSettings . GetPasswordSpecialRequirement ( ) ;
ViewData [ "NumberRequirement" ] = membershipSettings . GetPasswordNumberRequirement ( ) ;
2015-12-14 05:21:02 +08:00
2018-02-06 01:29:26 +08:00
ViewData [ "InvalidateOnPasswordChange" ] = _orchardServices . WorkContext
2019-05-14 21:03:13 +08:00
. CurrentSite . As < SecuritySettingsPart > ( )
. ShouldInvalidateAuthOnPasswordChanged ;
2018-02-06 01:29:26 +08:00
2015-12-14 05:21:02 +08:00
return View ( ) ;
}
[Authorize]
[HttpPost]
[AlwaysAccessible]
[ValidateInput(false)]
[ SuppressMessage ( "Microsoft.Design" , "CA1031:DoNotCatchGeneralExceptionTypes" ,
Justification = "Exceptions result in password not being changed." ) ]
public ActionResult ChangePassword ( string currentPassword , string newPassword , string confirmPassword ) {
2016-07-29 03:59:13 +08:00
var membershipSettings = _membershipService . GetSettings ( ) ;
2018-02-06 01:29:26 +08:00
ViewData [ "PasswordLength" ] = membershipSettings . GetMinimumPasswordLength ( ) ;
2019-12-20 04:25:45 +08:00
ViewData [ "LowercaseRequirement" ] = membershipSettings . GetPasswordLowercaseRequirement ( ) ;
ViewData [ "UppercaseRequirement" ] = membershipSettings . GetPasswordUppercaseRequirement ( ) ;
ViewData [ "SpecialCharacterRequirement" ] = membershipSettings . GetPasswordSpecialRequirement ( ) ;
ViewData [ "NumberRequirement" ] = membershipSettings . GetPasswordNumberRequirement ( ) ;
2021-05-28 14:45:14 +08:00
var shouldSignout = _orchardServices . WorkContext
2019-05-14 21:03:13 +08:00
. CurrentSite . As < SecuritySettingsPart > ( )
. ShouldInvalidateAuthOnPasswordChanged ;
2021-05-28 14:45:14 +08:00
ViewData [ "InvalidateOnPasswordChange" ] = shouldSignout ;
2015-12-14 05:21:02 +08:00
2022-01-14 17:32:07 +08:00
if ( ! ValidateChangePassword ( currentPassword , newPassword , confirmPassword , _orchardServices . WorkContext . CurrentUser ) ) {
2015-12-14 05:21:02 +08:00
return View ( ) ;
}
2016-07-29 03:59:13 +08:00
if ( PasswordChangeIsSuccess ( currentPassword , newPassword , _orchardServices . WorkContext . CurrentUser . UserName ) ) {
2021-05-28 14:45:14 +08:00
if ( shouldSignout ) {
_authenticationService . SignOut ( ) ;
var loggedUser = _authenticationService . GetAuthenticatedUser ( ) ;
if ( loggedUser ! = null ) {
_userEventHandler . LoggedOut ( loggedUser ) ;
}
}
2016-07-29 03:59:13 +08:00
return RedirectToAction ( "ChangePasswordSuccess" ) ;
2022-01-14 16:36:26 +08:00
} else {
2016-07-29 03:59:13 +08:00
return ChangePassword ( ) ;
}
}
[AlwaysAccessible]
public ActionResult ChangeExpiredPassword ( string username ) {
2022-10-07 16:09:36 +08:00
if ( string . IsNullOrWhiteSpace ( username ) ) {
return RedirectToAction ( "LogOn" ) ;
2022-09-30 15:00:00 +08:00
}
2022-10-07 16:09:36 +08:00
var userPart = _membershipService . GetUser ( username ) ? . As < UserPart > ( ) ;
if ( userPart = = null ) {
// user not valid / doesn't exist
return RedirectToAction ( "LogOn" ) ;
}
var membershipSettings = _membershipService . GetSettings ( ) ;
// if the password hasn't actually expired for the user, redirect to logon
var passwordIsActuallyExpired = membershipSettings . EnableCustomPasswordPolicy
& & membershipSettings . EnablePasswordExpiration
& & _membershipService . PasswordIsExpired ( userPart , membershipSettings . PasswordExpirationTimeInDays ) ;
if ( ! passwordIsActuallyExpired & & ! userPart . ForcePasswordChange ) {
2016-07-29 03:59:13 +08:00
return RedirectToAction ( "LogOn" ) ;
}
var viewModel = _orchardServices . New . ViewModel (
Username : username ,
2019-12-20 04:25:45 +08:00
PasswordLength : membershipSettings . GetMinimumPasswordLength ( ) ,
LowercaseRequirement : membershipSettings . GetPasswordLowercaseRequirement ( ) ,
UppercaseRequirement : membershipSettings . GetPasswordUppercaseRequirement ( ) ,
SpecialCharacterRequirement : membershipSettings . GetPasswordSpecialRequirement ( ) ,
NumberRequirement : membershipSettings . GetPasswordNumberRequirement ( ) ) ;
2016-07-29 03:59:13 +08:00
return View ( viewModel ) ;
}
[HttpPost, AlwaysAccessible, ValidateInput(false)]
public ActionResult ChangeExpiredPassword ( string currentPassword , string newPassword , string confirmPassword , string username ) {
var membershipSettings = _membershipService . GetSettings ( ) ;
var viewModel = _orchardServices . New . ViewModel (
Username : username ,
2019-12-20 04:25:45 +08:00
PasswordLength : membershipSettings . GetMinimumPasswordLength ( ) ,
LowercaseRequirement : membershipSettings . GetPasswordLowercaseRequirement ( ) ,
UppercaseRequirement : membershipSettings . GetPasswordUppercaseRequirement ( ) ,
SpecialCharacterRequirement : membershipSettings . GetPasswordSpecialRequirement ( ) ,
NumberRequirement : membershipSettings . GetPasswordNumberRequirement ( ) ) ;
2016-07-29 03:59:13 +08:00
2022-01-14 17:32:07 +08:00
if ( ! ValidateChangePassword ( currentPassword , newPassword , confirmPassword , _membershipService . GetUser ( username ) ) ) {
2016-07-29 03:59:13 +08:00
return View ( viewModel ) ;
}
if ( PasswordChangeIsSuccess ( currentPassword , newPassword , username ) ) {
2022-01-14 17:32:07 +08:00
2016-07-29 03:59:13 +08:00
return RedirectToAction ( "ChangePasswordSuccess" ) ;
2022-01-14 16:36:26 +08:00
} else {
2016-07-29 03:59:13 +08:00
return View ( viewModel ) ;
}
}
private bool PasswordChangeIsSuccess ( string currentPassword , string newPassword , string username ) {
2015-12-14 05:21:02 +08:00
try {
2019-05-14 21:03:13 +08:00
var validated = _membershipService . ValidateUser ( username , currentPassword , out List < LocalizedString > validationErrors ) ;
2015-12-14 05:21:02 +08:00
2016-07-29 03:59:13 +08:00
if ( validated ! = null ) {
2022-01-14 17:32:07 +08:00
_userEventHandler . ChangingPassword ( validated , newPassword ) ;
2015-12-14 05:21:02 +08:00
_membershipService . SetPassword ( validated , newPassword ) ;
2019-08-25 21:15:59 +08:00
_userEventHandler . ChangedPassword ( validated , newPassword ) ;
2019-05-14 21:03:13 +08:00
// if security settings tell to invalidate on password change fire the LoggedOut event
2022-01-14 17:32:07 +08:00
if ( _orchardServices . WorkContext
. CurrentSite . As < SecuritySettingsPart > ( )
. ShouldInvalidateAuthOnPasswordChanged ) {
2018-02-06 01:29:26 +08:00
_userEventHandler . LoggedOut ( validated ) ;
}
2016-07-29 03:59:13 +08:00
return true ;
2015-12-14 05:21:02 +08:00
}
2016-07-29 03:59:13 +08:00
2022-01-14 16:36:26 +08:00
} catch {
2015-12-14 05:21:02 +08:00
ModelState . AddModelError ( "_FORM" , T ( "The current password is incorrect or the new password is invalid." ) ) ;
2016-07-29 03:59:13 +08:00
return false ;
}
2022-01-14 17:32:07 +08:00
// unknown error
ModelState . AddModelError ( "_FORM" , T ( "The current password is incorrect or the new password is invalid." ) ) ;
2019-05-14 21:03:13 +08:00
return false ;
2015-12-14 05:21:02 +08:00
}
[AlwaysAccessible]
public ActionResult LostPassword ( string nonce ) {
2019-03-10 05:58:20 +08:00
if ( _userService . ValidateLostPassword ( nonce ) = = null ) {
2015-12-14 05:21:02 +08:00
return RedirectToAction ( "LogOn" ) ;
}
2016-07-29 03:59:13 +08:00
var membershipSettings = _membershipService . GetSettings ( ) ;
ViewData [ "PasswordLength" ] = membershipSettings . GetMinimumPasswordLength ( ) ;
2019-12-20 04:25:45 +08:00
ViewData [ "LowercaseRequirement" ] = membershipSettings . GetPasswordLowercaseRequirement ( ) ;
ViewData [ "UppercaseRequirement" ] = membershipSettings . GetPasswordUppercaseRequirement ( ) ;
ViewData [ "SpecialCharacterRequirement" ] = membershipSettings . GetPasswordSpecialRequirement ( ) ;
ViewData [ "NumberRequirement" ] = membershipSettings . GetPasswordNumberRequirement ( ) ;
2015-12-14 05:21:02 +08:00
return View ( ) ;
}
[HttpPost]
[AlwaysAccessible]
[ValidateInput(false)]
public ActionResult LostPassword ( string nonce , string newPassword , string confirmPassword ) {
IUser user ;
2019-03-10 05:58:20 +08:00
if ( ( user = _userService . ValidateLostPassword ( nonce ) ) = = null ) {
2015-12-14 05:21:02 +08:00
return Redirect ( "~/" ) ;
}
2016-07-29 03:59:13 +08:00
var membershipSettings = _membershipService . GetSettings ( ) ;
ViewData [ "PasswordLength" ] = membershipSettings . GetMinimumPasswordLength ( ) ;
2019-12-20 04:25:45 +08:00
ViewData [ "LowercaseRequirement" ] = membershipSettings . GetPasswordLowercaseRequirement ( ) ;
ViewData [ "UppercaseRequirement" ] = membershipSettings . GetPasswordUppercaseRequirement ( ) ;
ViewData [ "SpecialCharacterRequirement" ] = membershipSettings . GetPasswordSpecialRequirement ( ) ;
ViewData [ "NumberRequirement" ] = membershipSettings . GetPasswordNumberRequirement ( ) ;
2015-12-14 05:21:02 +08:00
2022-01-14 17:32:07 +08:00
if ( ! ValidatePassword ( newPassword , confirmPassword , user ) ) {
2015-12-14 05:21:02 +08:00
return View ( ) ;
}
2022-01-14 17:32:07 +08:00
_userEventHandler . ChangingPassword ( user , newPassword ) ;
2015-12-14 05:21:02 +08:00
_membershipService . SetPassword ( user , newPassword ) ;
2019-08-25 21:15:59 +08:00
_userEventHandler . ChangedPassword ( user , newPassword ) ;
2015-12-14 05:21:02 +08:00
return RedirectToAction ( "ChangePasswordSuccess" ) ;
}
[AlwaysAccessible]
public ActionResult ChangePasswordSuccess ( ) {
2018-02-06 01:29:26 +08:00
ViewData [ "InvalidateOnPasswordChange" ] = _orchardServices . WorkContext
2019-05-14 21:03:13 +08:00
. CurrentSite . As < SecuritySettingsPart > ( )
. ShouldInvalidateAuthOnPasswordChanged ;
2015-12-14 05:21:02 +08:00
return View ( ) ;
}
2019-03-10 06:07:12 +08:00
[AlwaysAccessible]
2015-12-14 05:21:02 +08:00
public ActionResult RegistrationPending ( ) {
return View ( ) ;
}
2019-03-10 06:07:12 +08:00
[AlwaysAccessible]
2015-12-14 05:21:02 +08:00
public ActionResult ChallengeEmailSent ( ) {
return View ( ) ;
}
2019-03-10 06:07:12 +08:00
[AlwaysAccessible]
2015-12-14 05:21:02 +08:00
public ActionResult ChallengeEmailSuccess ( ) {
return View ( ) ;
}
2019-03-10 06:07:12 +08:00
[AlwaysAccessible]
2015-12-14 05:21:02 +08:00
public ActionResult ChallengeEmailFail ( ) {
return View ( ) ;
}
2019-03-10 06:07:12 +08:00
[AlwaysAccessible]
2015-12-14 05:21:02 +08:00
public ActionResult ChallengeEmail ( string nonce ) {
var user = _userService . ValidateChallenge ( nonce ) ;
2019-03-10 05:58:20 +08:00
if ( user ! = null ) {
2015-12-14 05:21:02 +08:00
_userEventHandler . ConfirmedEmail ( user ) ;
return RedirectToAction ( "ChallengeEmailSuccess" ) ;
}
return RedirectToAction ( "ChallengeEmailFail" ) ;
}
#region Validation Methods
2022-01-14 17:32:07 +08:00
private bool ValidateChangePassword ( string currentPassword , string newPassword , string confirmPassword , IUser user ) {
2019-05-14 21:03:13 +08:00
if ( string . IsNullOrEmpty ( currentPassword ) ) {
2015-12-14 05:21:02 +08:00
ModelState . AddModelError ( "currentPassword" , T ( "You must specify a current password." ) ) ;
}
2016-07-29 03:59:13 +08:00
2019-05-14 21:03:13 +08:00
if ( string . Equals ( currentPassword , newPassword , StringComparison . Ordinal ) ) {
2016-07-29 03:59:13 +08:00
ModelState . AddModelError ( "newPassword" , T ( "The new password must be different from the current password." ) ) ;
2015-12-14 05:21:02 +08:00
}
2022-01-14 16:36:26 +08:00
if ( ! ModelState . IsValid ) {
return false ;
2015-12-14 05:21:02 +08:00
}
2022-01-14 17:32:07 +08:00
return ValidatePassword ( newPassword , confirmPassword , user ) ;
2015-12-14 05:21:02 +08:00
}
private IUser ValidateLogOn ( string userNameOrEmail , string password ) {
bool validate = true ;
2019-05-14 21:03:13 +08:00
if ( string . IsNullOrEmpty ( userNameOrEmail ) ) {
2015-12-14 05:21:02 +08:00
ModelState . AddModelError ( "userNameOrEmail" , T ( "You must specify a username or e-mail." ) ) ;
validate = false ;
}
2022-01-14 16:36:26 +08:00
// Here we don't do the "full" validation of the password, because policies may have
// changed since its creation and that should not prevent a user from logging in.
2019-05-14 21:03:13 +08:00
if ( string . IsNullOrEmpty ( password ) ) {
2015-12-14 05:21:02 +08:00
ModelState . AddModelError ( "password" , T ( "You must specify a password." ) ) ;
validate = false ;
}
if ( ! validate )
return null ;
2019-05-14 21:03:13 +08:00
var validationResult = _membershipService . ValidateUser ( userNameOrEmail , password , out List < LocalizedString > validationErrors ) ;
2017-09-15 03:26:55 +08:00
if ( validationResult = = null ) {
2015-12-14 05:21:02 +08:00
_userEventHandler . LogInFailed ( userNameOrEmail , password ) ;
}
2017-09-15 03:26:55 +08:00
foreach ( var error in validationErrors ) {
ModelState . AddModelError ( "_FORM" , error ) ;
}
return validationResult ;
2015-12-14 05:21:02 +08:00
}
private bool ValidateRegistration ( string userName , string email , string password , string confirmPassword ) {
2022-01-14 16:36:26 +08:00
var context = new AccountValidationContext {
UserName = userName ,
Email = email ,
Password = password
} ;
_accountValidationService . ValidateUserName ( context ) ;
_accountValidationService . ValidateEmail ( context ) ;
// Don't do the other validations if we already know we failed
if ( ! context . ValidationSuccessful ) {
foreach ( var error in context . ValidationErrors ) {
ModelState . AddModelError ( error . Key , error . Value ) ;
2022-01-14 17:32:07 +08:00
}
2015-12-14 05:21:02 +08:00
return false ;
2022-01-14 16:36:26 +08:00
}
2015-12-14 05:21:02 +08:00
if ( ! _userService . VerifyUserUnicity ( userName , email ) ) {
2022-01-14 17:32:07 +08:00
// Not a new registration, but perhaps we already have that user and they
// haven't validated their email address. This doesn't care whether there
// were other issues with the registration attempt that caused its validation
// to fail: if the user exists and still has to confirm their email, we show
// a link to the action from which the challenge email is sent again.
var membershipSettings = _membershipService . GetSettings ( ) ;
if ( membershipSettings . UsersMustValidateEmail ) {
var user = _userService . GetUserByNameOrEmail ( email ) ;
if ( user = = null ) {
user = _userService . GetUserByNameOrEmail ( userName ) ;
}
if ( user ! = null & & user . EmailStatus = = UserStatus . Pending ) {
// We can't have links in the "text" of a ModelState Error. We are using a notifier
// to provide the user with an option to ask for a new challenge email.
_orchardServices . Notifier . Warning (
T ( "User with that username and/or email already exists. Follow <a href=\"{0}\">this link</a> if you want to receive a new email to validate your address." ,
Url . Action ( actionName : "RequestChallengeEmail" , routeValues : new { email = email } ) ) ) ;
// In creating the link above we use the email that was written in the form
// rather than the actual user's email address to prevent exploiting this
// for information discovery.
}
}
// We should add the error to the ModelState anyway.
2022-01-14 16:36:26 +08:00
context . ValidationErrors . Add ( "userExists" , T ( "User with that username and/or email already exists." ) ) ;
2015-12-14 05:21:02 +08:00
}
2016-07-29 03:59:13 +08:00
2022-01-14 16:36:26 +08:00
_accountValidationService . ValidatePassword ( context ) ;
2016-07-29 03:59:13 +08:00
2019-05-14 21:03:13 +08:00
if ( ! string . Equals ( password , confirmPassword , StringComparison . Ordinal ) ) {
2022-01-14 16:36:26 +08:00
context . ValidationErrors . Add ( "_FORM" , T ( "The new password and confirmation password do not match." ) ) ;
}
if ( ! context . ValidationSuccessful ) {
foreach ( var error in context . ValidationErrors ) {
ModelState . AddModelError ( error . Key , error . Value ) ;
}
2015-12-14 05:21:02 +08:00
}
2022-01-14 16:36:26 +08:00
2015-12-14 05:21:02 +08:00
return ModelState . IsValid ;
}
2022-01-14 17:32:07 +08:00
private bool ValidatePassword ( string password , IUser user ) {
2022-01-14 16:36:26 +08:00
var context = new AccountValidationContext {
2022-01-14 17:32:07 +08:00
Password = password ,
User = user
2022-01-14 16:36:26 +08:00
} ;
var result = _accountValidationService . ValidatePassword ( context ) ;
if ( ! result ) {
foreach ( var error in context . ValidationErrors ) {
2016-07-29 03:59:13 +08:00
ModelState . AddModelError ( error . Key , error . Value ) ;
}
}
2022-01-14 16:36:26 +08:00
return result ;
}
2022-01-14 17:32:07 +08:00
private bool ValidatePassword ( string password , string confirmPassword , IUser user ) {
2022-01-14 16:36:26 +08:00
if ( ! string . Equals ( password , confirmPassword , StringComparison . Ordinal ) ) {
ModelState . AddModelError ( "_FORM" , T ( "The new password and confirmation password do not match." ) ) ;
return false ;
}
2022-01-14 17:32:07 +08:00
return ValidatePassword ( password , user ) ;
2016-07-29 03:59:13 +08:00
}
2015-12-14 05:21:02 +08:00
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
}
2009-11-08 06:49:58 +08:00
}