Change Password History
HI,
I am trying to implement password change history. So when a user changes his password, I will check against a list and not allow if the password is present in the list.
I used the EventHub to subscribe to the UserUpdating event in the Global.asax using the Bootstrapper.
EventHub.Subscribe<UserUpdating>(UserUpdating_Action);
Next in the event handler:
private void UserUpdating_Action(UserUpdating @event)
if (@event.PasswordChanged)
// Check list and throw validataion error
...
...
throw new ValidationException("Error");
This throws a standard ASP.NET error on the page. I would prefer it to display into the error message box on the page and stop the password from changing to the new one.
How would this be accomplished? Effectively how to stop the event from completing in an event handler?
thanks
Hi
In order to validate the input and show an error message, you should create a custom UserChangePasswordWidget.
Here is the widget template, added a custom validator, so we can show the error message:
<%@ Control Language="C#" %>
<%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI" Assembly="Telerik.Sitefinity" %>
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.ContentUI" Assembly="Telerik.Sitefinity" %>
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.PublicControls.BrowseAndEdit" %>
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.Fields" Assembly="Telerik.Sitefinity" %>
<%@ Register TagPrefix="sfvalidation" Namespace="Telerik.Sitefinity.Web.UI.Validation.Definitions" Assembly="Telerik.Sitefinity" %>
<
asp:PlaceHolder
ID
=
"changePasswordRegion"
runat
=
"server"
>
<
fieldset
class
=
"sfprofileChangePasswordFormWrp"
>
<
sf:SitefinityLabel
runat
=
"server"
id
=
"errorLabel"
Visible
=
"false"
WrapperTagName
=
"div"
HideIfNoText
=
"false"
CssClass
=
"sfprofileFailureMsg"
/>
<
sf:SitefinityLabel
runat
=
"server"
id
=
"successLabel"
Visible
=
"false"
WrapperTagName
=
"div"
HideIfNoText
=
"false"
CssClass
=
"sfprofileSuccessMsg"
/>
<
ol
class
=
"sfprofileFieldsList"
>
<
sf:TextField
ID
=
"newPassword"
runat
=
"server"
DisplayMode
=
"Write"
IsPasswordMode
=
"true"
Title="<%$ Resources:Labels, NewPasswordText %>" CssClass="sfprofileField" WrapperTag="li">
<
ValidatorDefinition
MessageCssClass
=
"sfError"
Required
=
"true"
/>
</
sf:TextField
>
<
sf:TextField
ID
=
"confirmNewPassword"
runat
=
"server"
DisplayMode
=
"Write"
IsPasswordMode
=
"true"
Title="<%$ Resources:Labels, ConfirmNewPasswordText %>" CssClass="sfprofileField" WrapperTag="li">
<
ValidatorDefinition
MessageCssClass
=
"sfError"
>
<
ComparingValidatorDefinitions
>
<
sfvalidation:ComparingValidatorDefinition
ControlToCompare
=
"newPassword"
Operator
=
"Equal"
ValidationViolationMessage="<%$ Resources:ErrorMessages, CreateUserWizardDefaultConfirmPasswordCompareErrorMessage %>"/>
</
ComparingValidatorDefinitions
>
</
ValidatorDefinition
>
</
sf:TextField
>
<
asp:CustomValidator
id
=
"CustomValidator1"
runat
=
"server"
ControlToValidate
=
"newPassword"
CssClass
=
"sfError"
ErrorMessage
=
"Password already used. Enter new password."
>
</
asp:CustomValidator
>
</
ol
>
<
div
class
=
"sfprofileLnkWrp"
>
<
asp:LinkButton
runat
=
"server"
ID
=
"saveChanges"
Text="<%$ Resources:Labels, Submit %>" CssClass="sfprofileSaveLnk" />
</
div
>
</
fieldset
>
</
asp:PlaceHolder
>
<
asp:PlaceHolder
ID
=
"passwordChangedRegion"
runat
=
"server"
Visible
=
"false"
>
<
p
>
<
asp:Literal
runat
=
"server"
Text="<%$ Resources:Labels, PasswordSuccessfullyChanged %>"></
asp:Literal
>
</
p
>
<
sf:SitefinityHyperLink
ID
=
"continueToWebsite"
runat
=
"server"
Text="<%$ Resources:Labels, ContinueToWebsite %>" NavigateUrl="~/"></
sf:SitefinityHyperLink
>
</
asp:PlaceHolder
>
public
class
UserChangePasswordWidgetCustom : UserChangePasswordWidget
public
override
string
LayoutTemplatePath
get
return
UserChangePasswordWidgetCustom.layoutTemplatePathCustom;
protected
virtual
CustomValidator CustomValidator1
get
return
this
.Container.GetControl<CustomValidator>(
"CustomValidator1"
,
true
);
protected
override
void
InitializeControls(Telerik.Sitefinity.Web.UI.GenericContainer container, Telerik.Sitefinity.Web.UI.ContentUI.Contracts.IContentViewDefinition definition)
this
.CustomValidator1.ServerValidate += NewPasswordValidate;
this
.SaveChangesButton.Click += SaveChangesButton_Click;
base
.InitializeControls(container, definition);
void
SaveChangesButton_Click(
object
sender, EventArgs e)
this
.NewPasswordOriginalValue =
this
.NewPasswordTextField.Value;
if
(
this
.NewPasswordOriginalValue !=
null
&& !
string
.IsNullOrWhiteSpace(
this
.NewPasswordOriginalValue.ToString()))
if
(!ValidatePassword(
this
.NewPasswordOriginalValue.ToString()))
this
.NewPasswordTextField.Value =
string
.Empty;
this
.NewPasswordTextField.ShowMessageOnError =
false
;
protected
void
NewPasswordValidate(
object
source, ServerValidateEventArgs args)
args.IsValid = ValidatePassword(args.Value.ToString());
private
bool
ValidatePassword(
string
password)
// Check list
return
false
;
protected
override
bool
OnBubbleEvent(
object
source, EventArgs args)
this
.NewPasswordTextField.Value =
this
.NewPasswordOriginalValue;
return
base
.OnBubbleEvent(source, args);
internal
static
readonly
string
layoutTemplatePathCustom =
"~/UserChangePasswordWidgetCustom/UserChangePasswordWidgetCustom.ascx"
;
public
object
NewPasswordOriginalValue
get
;
set
;
Thanks Nikola,
I was hoping not to create a whole new widget to perform what has already been done. But I guess that will do. Of course now the next thing is to disable the standard backend change password page so the user would be forced to use this new one, but that's another story.
For that matter, the ability to return a bool from any event handler raised by EventHub that will interrupt the main processing would be most useful not just to this particular scenario.
Hi
Unfortunately, the EventHub provides only subscribe/unsubscribe functionality. The event cannot be canceled from the -ing events. Furthermore, you will not be able to show an adequate error message from the event handling.
Regards,
Nikola Zagorchev
Telerik