package edu.harvard.iq.dataverse.passwordreset; import edu.harvard.iq.dataverse.DataverseServiceBean; import edu.harvard.iq.dataverse.DataverseSession; import edu.harvard.iq.dataverse.ValidateEmail; import edu.harvard.iq.dataverse.actionlogging.ActionLogRecord; import edu.harvard.iq.dataverse.actionlogging.ActionLogServiceBean; import edu.harvard.iq.dataverse.authorization.AuthenticationServiceBean; import edu.harvard.iq.dataverse.authorization.providers.builtin.BuiltinAuthenticationProvider; import edu.harvard.iq.dataverse.authorization.providers.builtin.BuiltinUser; import edu.harvard.iq.dataverse.authorization.providers.builtin.BuiltinUserServiceBean; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; import java.util.logging.Level; import java.util.logging.Logger; import javax.ejb.EJB; import javax.faces.application.FacesMessage; import javax.faces.context.FacesContext; import javax.faces.view.ViewScoped; import javax.inject.Inject; import javax.inject.Named; import org.hibernate.validator.constraints.NotBlank; @ViewScoped @Named("PasswordResetPage") public class PasswordResetPage implements java.io.Serializable { private static final Logger logger = Logger.getLogger(PasswordResetPage.class.getCanonicalName()); @EJB PasswordResetServiceBean passwordResetService; @EJB BuiltinUserServiceBean dataverseUserService; @EJB DataverseServiceBean dataverseService; @EJB AuthenticationServiceBean authSvc; @Inject DataverseSession session; @EJB ActionLogServiceBean actionLogSvc; /** * The unique string used to look up a user and continue the password reset * process. */ String token; /** * The user looked up by the token who will be setting a new password. */ BuiltinUser user; /** * The email address that is entered to initiate the password reset process. */ @NotBlank(message = "Please enter a valid email address.") @ValidateEmail(message = "Password reset page default email message.") String emailAddress; /** * The link that is emailed to the user to reset the password that contains * a token. */ String passwordResetUrl; /** * The new password the user enters. */ String newPassword; PasswordResetData passwordResetData; public void init() { if (token != null) { PasswordResetExecResponse passwordResetExecResponse = passwordResetService.processToken(token); passwordResetData = passwordResetExecResponse.getPasswordResetData(); if (passwordResetData != null) { user = passwordResetData.getBuiltinUser(); } else { FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Password Reset Link", "Your password reset link is not valid.")); } } } public String sendPasswordResetLink() { actionLogSvc.log( new ActionLogRecord(ActionLogRecord.ActionType.BuiltinUser, "passwordResetRequest") .setInfo("Email Address: " + emailAddress) ); try { PasswordResetInitResponse passwordResetInitResponse = passwordResetService.requestReset(emailAddress); PasswordResetData passwordResetData = passwordResetInitResponse.getPasswordResetData(); if (passwordResetData != null) { BuiltinUser foundUser = passwordResetData.getBuiltinUser(); passwordResetUrl = passwordResetInitResponse.getResetUrl(); actionLogSvc.log( new ActionLogRecord(ActionLogRecord.ActionType.BuiltinUser, "passwordResetSent") .setInfo("Email Address: " + emailAddress) ); } else { /** * @todo remove "single" when it's no longer necessary. See * https://github.com/IQSS/dataverse/issues/844 and * https://github.com/IQSS/dataverse/issues/1141 */ logger.log(Level.INFO, "Couldn''t find single account using {0}", emailAddress); } FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Password Reset Initiated", "")); } catch (PasswordResetException ex) { /** * @todo do we really need a special exception for this?? */ logger.log(Level.WARNING, "Error While resetting password: " + ex.getMessage(), ex); } return ""; } public String resetPassword() { PasswordChangeAttemptResponse response = passwordResetService.attemptPasswordReset(user, newPassword, this.token); if (response.isChanged()) { FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, response.getMessageSummary(), response.getMessageDetail())); String builtinAuthProviderId = BuiltinAuthenticationProvider.PROVIDER_ID; AuthenticatedUser au = authSvc.lookupUser(builtinAuthProviderId, user.getUserName()); session.setUser(au); return "/dataverse.xhtml?alias=" + dataverseService.findRootDataverse().getAlias() + "faces-redirect=true"; } else { FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, response.getMessageSummary(), response.getMessageDetail())); return null; } } public boolean isAccountUpgrade() { return passwordResetData.getReason() == PasswordResetData.Reason.UPGRADE_REQUIRED; } public String getToken() { return token; } public void setToken(String token) { this.token = token; } public BuiltinUser getUser() { return user; } public String getEmailAddress() { return emailAddress; } public void setEmailAddress(String emailAddress) { this.emailAddress = emailAddress; } public String getPasswordResetUrl() { return passwordResetUrl; } public void setNewPassword(String newPassword) { this.newPassword = newPassword; } public String getNewPassword() { return newPassword; } public PasswordResetData getPasswordResetData() { return passwordResetData; } public void setPasswordResetData(PasswordResetData passwordResetData) { this.passwordResetData = passwordResetData; } }