ref #9498 using PasswordResetService for Password Recover tab
authorAndreas Kohlbecker <a.kohlbecker@bgbm.org>
Thu, 11 Nov 2021 10:22:43 +0000 (11:22 +0100)
committerAndreas Kohlbecker <a.kohlbecker@bgbm.org>
Thu, 11 Nov 2021 10:22:43 +0000 (11:22 +0100)
src/main/java/eu/etaxonomy/cdm/vaadin/component/LoginDialog.java
src/main/java/eu/etaxonomy/cdm/vaadin/design/LoginDialogDesign.java
src/main/java/eu/etaxonomy/cdm/vaadin/view/LoginPresenter.java
src/main/java/eu/etaxonomy/cdm/vaadin/view/LoginViewBean.java
src/main/resources/eu/etaxonomy/cdm/vaadin/design/LoginDialogDesign.html

index 53e5983ce14885e2dae4e68c50900b049bbfe959..3d0708ecffae5fa845f91ad5eda5b42fd6489d62 100644 (file)
@@ -27,9 +27,9 @@ public class LoginDialog extends LoginDialogDesign {
 
     public LoginDialog() {
         addSelectedTabChangeListener(e -> focusFirstElement(e.getTabSheet()));
-        getMessageLabel().setVisible(false);
-        getTab(1).setEnabled(false);
-        getTab(2).setEnabled(false);
+        getLoginMessageLabel().setVisible(false);
+//        getTab(1).setEnabled(false);
+//        getTab(2).setEnabled(false);
         focusFirstElement(this);
     }
 
@@ -122,11 +122,15 @@ public class LoginDialog extends LoginDialogDesign {
      * @return the sendOnetimeLogin
      */
     public Button getSendOnetimeLogin() {
-        return sendOnetimeLogin;
+        return sendRecoveryEmail;
     }
 
-    public Label getMessageLabel() {
-        return message;
+    public Label getLoginMessageLabel() {
+        return messageLogin;
+    }
+
+    public Label getMessageSendRecoveryEmailLabel() {
+        return messageRecoveryEmail;
     }
 
 
index 90112e5b8d1b49f5c0dc20d6697f0d7bdb107fc4..4d7efc21f0d002e0a06e94e8a4a4d6a02d080fe5 100644 (file)
@@ -9,11 +9,11 @@ import com.vaadin.ui.TabSheet;
 import com.vaadin.ui.TextField;
 import com.vaadin.ui.declarative.Design;
 
-/** 
+/**
  * !! DO NOT EDIT THIS FILE !!
- * 
+ *
  * This class is generated by Vaadin Designer and will be overwritten.
- * 
+ *
  * Please make a subclass with logic and additional interfaces as needed,
  * e.g class LoginView extends LoginDesign implements View { }
  */
@@ -23,7 +23,7 @@ import com.vaadin.ui.declarative.Design;
 public class LoginDialogDesign extends TabSheet {
     protected TextField userName;
     protected PasswordField password;
-    protected Label message;
+    protected Label messageLogin;
     protected Button loginButton;
     protected Button cancelLoginButton;
     protected TextField userNameSuggestion;
@@ -31,7 +31,8 @@ public class LoginDialogDesign extends TabSheet {
     protected Button registerButton;
     protected Button cancelRegistrationButton;
     protected TextField userNameOrEmail;
-    protected Button sendOnetimeLogin;
+    protected Button sendRecoveryEmail;
+    protected Label messageRecoveryEmail;
 
     public LoginDialogDesign() {
         Design.read(this);
index 4a892dc51b5be7ddf9c35f255afc2e4b83038334..498f29f17531b478c22955f84d31943448f560ee 100644 (file)
@@ -8,25 +8,37 @@
 */
 package eu.etaxonomy.cdm.vaadin.view;
 
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
+import org.springframework.util.concurrent.ListenableFuture;
 import org.vaadin.spring.events.Event;
 import org.vaadin.spring.events.EventBus;
-import org.vaadin.spring.events.EventBus.ViewEventBus;
 import org.vaadin.spring.events.EventBusListener;
+import org.vaadin.spring.events.annotation.EventBusListenerMethod;
 
 import com.vaadin.spring.annotation.SpringComponent;
 import com.vaadin.spring.annotation.ViewScope;
+import com.vaadin.ui.themes.ValoTheme;
 
+import eu.etaxonomy.cdm.api.application.ICdmRepository;
 import eu.etaxonomy.cdm.vaadin.event.AuthenticationAttemptEvent;
 import eu.etaxonomy.cdm.vaadin.event.AuthenticationSuccessEvent;
+import eu.etaxonomy.cdm.vaadin.event.PasswordRevoveryEvent;
+import eu.etaxonomy.cdm.vaadin.util.VaadinServletUtilities;
 import eu.etaxonomy.vaadin.mvp.AbstractPresenter;
 import eu.etaxonomy.vaadin.ui.navigation.NavigationEvent;
 import eu.etaxonomy.vaadin.ui.navigation.NavigationManager;
@@ -63,13 +75,14 @@ public class LoginPresenter extends AbstractPresenter<LoginView> implements Even
 
     protected EventBus.UIEventBus uiEventBus;
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected void eventViewBusSubscription(ViewEventBus viewEventBus) {
-        // not listening to view scope events
-    }
+    @Autowired
+    @Qualifier("cdmRepository")
+    private ICdmRepository repo;
+
+//    @Override
+//    protected void eventViewBusSubscription(ViewEventBus viewEventBus) {
+//        viewEventBus.subscribe(this);
+//    }
 
     @Autowired
     protected void setUIEventBus(EventBus.UIEventBus uiEventBus){
@@ -100,11 +113,6 @@ public class LoginPresenter extends AbstractPresenter<LoginView> implements Even
         return false;
     }
 
-
-
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public void handleViewEntered() {
 
@@ -137,5 +145,51 @@ public class LoginPresenter extends AbstractPresenter<LoginView> implements Even
         }
     }
 
+    @EventBusListenerMethod
+    public void onPasswordRevoveryEvent(PasswordRevoveryEvent event) throws MalformedURLException, ExecutionException {
+        String userNameOrEmail = getView().getLoginDialog().getUserNameOrEmail().getValue();
+        URL servletBaseUrl = VaadinServletUtilities.getServletBaseUrl();
+        logger.debug("PasswordRevoveryEvent for " + servletBaseUrl + ", userNameOrEmail:" + userNameOrEmail);
+        // Implementation note: UI modifications allied in the below callback methods will not affect the UI
+        // immediately, therefore we use a CountDownLatch
+        CountDownLatch finshedSignal = new CountDownLatch(1);
+        List<Throwable> asyncException = new ArrayList<>(1);
+        ListenableFuture<Boolean> futureResult = repo.getPasswordResetService().emailResetToken(userNameOrEmail, servletBaseUrl.toString());
+        futureResult.addCallback(
+                    successFuture -> {
+                        finshedSignal.countDown();
+                    },
+                    exception -> {
+                        // possible MailException
+                        asyncException.add(exception);
+                        finshedSignal.countDown();
+                    }
+                );
+        boolean asyncTimeout = false;
+        Boolean result = false;
+        try {
+            finshedSignal.await(2, TimeUnit.SECONDS);
+            result = futureResult.get();
+        } catch (InterruptedException e) {
+            asyncTimeout = true;
+        }
+        if(!asyncException.isEmpty()) {
+            getView().getLoginDialog().getMessageSendRecoveryEmailLabel()
+            .setValue("Sending an password reset email to you has failed. Please try again later or contect the support in case this error persists.");
+            getView().getLoginDialog().getMessageSendRecoveryEmailLabel().setStyleName(ValoTheme.LABEL_FAILURE);
+        } else {
+            if(!asyncTimeout && result) {
+                getView().getLoginDialog().getMessageSendRecoveryEmailLabel().setValue("An email with a password reset link has been sent to you.");
+                getView().getLoginDialog().getMessageSendRecoveryEmailLabel().setStyleName(ValoTheme.LABEL_SUCCESS);
+                getView().getLoginDialog().getSendOnetimeLogin().setEnabled(false);
+                getView().getLoginDialog().getUserNameOrEmail().setEnabled(false);
+                getView().getLoginDialog().getUserNameOrEmail().setReadOnly(true);
+
+            } else {
+                getView().getLoginDialog().getMessageSendRecoveryEmailLabel().setValue("A timeout has occured, please try again.");
+                getView().getLoginDialog().getMessageSendRecoveryEmailLabel().setStyleName(ValoTheme.LABEL_FAILURE);
+            }
+        }
+    }
 
 }
index 50b84e662d1c5560555bd5f5ed7d8d0609e87232..c63373eb4c2577983395f572ef2470a965176eba 100644 (file)
@@ -10,6 +10,7 @@ package eu.etaxonomy.cdm.vaadin.view;
 
 import org.vaadin.spring.events.EventScope;
 
+import com.vaadin.data.validator.StringLengthValidator;
 import com.vaadin.event.ShortcutAction.KeyCode;
 import com.vaadin.navigator.View;
 import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
@@ -56,15 +57,23 @@ public class LoginViewBean  extends AbstractView<LoginPresenter> implements Logi
         loginDialog.getLoginButton().addClickListener(e -> handleLoginClick(e));
         loginDialog.getLoginButton().setClickShortcut(KeyCode.ENTER);
         loginDialog.getRegisterButton().addClickListener(e -> getViewEventBus().publish(EventScope.UI, this, new RegisterNewUserEvent(e)));
-        loginDialog.getSendOnetimeLogin().addClickListener(e -> getViewEventBus().publish(EventScope.UI, this, new PasswordRevoveryEvent(e)));
+        loginDialog.getSendOnetimeLogin().addClickListener(e -> {
+            getViewEventBus().publish(this, new PasswordRevoveryEvent(e));
+        });
         // NOTE: null viewName will be replaced by the default view name in NavigationManagerBean
         loginDialog.getCancelLoginButton().addClickListener(e -> getViewEventBus().publish(EventScope.UI, this, new NavigationEvent(null)));
+
         loginDialog.getCancelRegistrationButton().addClickListener(e -> getViewEventBus().publish(EventScope.UI, this, new NavigationEvent(null)));
+
+        StringLengthValidator nameOrEmailValidator = new StringLengthValidator("Please enter your username or email address.");
+        loginDialog.getUserNameOrEmail().addValidator(nameOrEmailValidator);
+        loginDialog.getUserNameOrEmail().addTextChangeListener(e -> {
+            String text = e.getText();
+            logger.debug("text: " + text);
+            loginDialog.getSendOnetimeLogin().setEnabled(text != null && text.length() > 1);
+        });
     }
 
-    /**
-     * @param e
-     */
     private void handleLoginClick(ClickEvent e) {
         getViewEventBus().publish(EventScope.UI, this, new AuthenticationAttemptEvent(e, loginDialog.getUserName().getValue()));
     }
@@ -74,9 +83,6 @@ public class LoginViewBean  extends AbstractView<LoginPresenter> implements Logi
         return loginDialog;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     // TODO pull up to AbstractView and let AbstractView implement View?
     public void enter(ViewChangeEvent event) {
@@ -85,16 +91,15 @@ public class LoginViewBean  extends AbstractView<LoginPresenter> implements Logi
 
     @Override
     public void showErrorMessage(String text){
-        loginDialog.getMessageLabel().setVisible(true);
-        loginDialog.getMessageLabel().setStyleName(ValoTheme.BUTTON_TINY + " " +  ValoTheme.LABEL_FAILURE);
-        loginDialog.getMessageLabel().setValue(text);
+        loginDialog.getLoginMessageLabel().setVisible(true);
+        loginDialog.getLoginMessageLabel().setStyleName(ValoTheme.BUTTON_TINY + " " +  ValoTheme.LABEL_FAILURE);
+        loginDialog.getLoginMessageLabel().setValue(text);
     }
 
-
     @Override
     public void clearMessage(){
-        loginDialog.getMessageLabel().setVisible(false);
-        loginDialog.getMessageLabel().setStyleName("");
-        loginDialog.getMessageLabel().setValue("");
+        loginDialog.getLoginMessageLabel().setVisible(false);
+        loginDialog.getLoginMessageLabel().setStyleName("");
+        loginDialog.getLoginMessageLabel().setValue("");
     }
 }
index 7c4bbe95b42ff99552d798250ba5460ffc787c5f..9885879454cd469ec562a863566fe3c715e64f5d 100644 (file)
@@ -14,7 +14,7 @@
      </vaadin-label>
      <vaadin-text-field caption="Username" _id="userName"></vaadin-text-field>
      <vaadin-password-field caption="Password" _id="password"></vaadin-password-field>
-     <vaadin-label style-name="tiny" width="190px" _id="message"></vaadin-label>
+     <vaadin-label style-name="tiny" width="190px" _id="messageLogin"></vaadin-label>
      <vaadin-label style-name="tiny" width="190px">
        Lost your password? Please use the 
       <b>Password Recovery</b> tab. 
        Please enter your username or email adress. 
      </vaadin-label>
      <vaadin-text-field caption="Username / email address" _id="userNameOrEmail"></vaadin-text-field>
-     <vaadin-button enabled="false" style-name="primary" plain-text _id="sendOnetimeLogin">
-       E-mail new password 
+     <vaadin-button enabled="false" style-name="primary" plain-text _id="sendRecoveryEmail">
+       Send recovery email
      </vaadin-button>
-     <vaadin-label style-name="tiny" width="190px">
+     <vaadin-label style-name="tiny" width="190px" _id="messageRecoveryEmail">
        After clicking the above button you will receive an E-mail with further instructions. 
      </vaadin-label>
     </vaadin-form-layout>