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