/* * * * Copyright (c) 2016. David Sowerby * * * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * * the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * * specific language governing permissions and limitations under the License. * */ package uk.q3c.krail.core.view; import com.google.inject.Inject; import com.google.inject.Provider; import com.vaadin.event.ShortcutAction; import com.vaadin.ui.*; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.themes.ChameleonTheme; import com.vaadin.ui.themes.ValoTheme; import net.engio.mbassy.bus.common.PubSubSupport; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.authc.*; import org.apache.shiro.subject.Subject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import uk.q3c.krail.core.eventbus.BusMessage; import uk.q3c.krail.core.eventbus.SessionBusProvider; import uk.q3c.krail.core.i18n.*; import uk.q3c.krail.core.shiro.LoginExceptionHandler; import uk.q3c.krail.core.shiro.SubjectProvider; import uk.q3c.krail.core.user.status.UserStatusBusMessage; import uk.q3c.krail.core.view.component.LoginFormException; import uk.q3c.krail.core.view.component.ViewChangeBusMessage; import uk.q3c.util.ID; import java.util.Optional; public class DefaultLoginView extends Grid3x3ViewBase implements LoginView, ClickListener { private static Logger log = LoggerFactory.getLogger(DefaultLoginView.class); private final LoginExceptionHandler loginExceptionHandler; private final Provider<Subject> subjectProvider; private final Translate translate; private final PubSubSupport<BusMessage> eventBus; @Caption(caption = LabelKey.Log_In, description = DescriptionKey.Please_log_in) private Panel centrePanel; @Value(LabelKey.Authentication) private Label label; @Caption(caption = LabelKey.Password, description = DescriptionKey.Enter_Your_Password) private PasswordField passwordBox; private Label statusMsgLabel; @Caption(caption = LabelKey.Submit, description = DescriptionKey.Submit_Your_Login_Details) private Button submitButton; @Caption(caption = LabelKey.User_Name, description = DescriptionKey.Enter_your_user_name) private TextField usernameBox; @Inject protected DefaultLoginView(LoginExceptionHandler loginExceptionHandler, SubjectProvider subjectProvider, Translate translate, SessionBusProvider eventBusProvider) { super(translate); this.loginExceptionHandler = loginExceptionHandler; this.subjectProvider = subjectProvider; this.translate = translate; this.eventBus = eventBusProvider.get(); nameKey = LabelKey.Log_In; descriptionKey = DescriptionKey.Log_In; } @Override public void doBuild(ViewChangeBusMessage event) { super.doBuild(event); centrePanel = new Panel(); centrePanel.addStyleName(ChameleonTheme.PANEL_BUBBLE); centrePanel.setSizeUndefined(); VerticalLayout vl = new VerticalLayout(); centrePanel.setContent(vl); vl.setSpacing(true); vl.setSizeUndefined(); label = new Label(); usernameBox = new TextField(); passwordBox = new PasswordField(); Label demoInfoLabel = new Label("for this demo, enter any user name, and a password of 'password'"); Label demoInfoLabel2 = new Label("In a real application your Shiro Realm implementation defines how to authenticate"); submitButton = new Button(); submitButton.addClickListener(this); statusMsgLabel = new Label("Please enter your username and password"); vl.addComponent(label); vl.addComponent(demoInfoLabel); vl.addComponent(demoInfoLabel2); vl.addComponent(usernameBox); vl.addComponent(passwordBox); vl.addComponent(submitButton); vl.addComponent(statusMsgLabel); setMiddleCentre(centrePanel); } @Override protected void setIds() { super.setIds(); submitButton.setId(ID.getId(Optional.empty(), this, submitButton)); submitButton.setClickShortcut(ShortcutAction.KeyCode.ENTER); submitButton.addStyleName(ValoTheme.BUTTON_PRIMARY); usernameBox.setId(ID.getId(Optional.of("username"), this, usernameBox)); passwordBox.setId(ID.getId(Optional.of("password"), this, passwordBox)); statusMsgLabel.setId(ID.getId(Optional.of("status"), this, statusMsgLabel)); label.setId(ID.getId(Optional.of("label"), this, label)); } @Override public void buttonClick(ClickEvent event) { String username = usernameBox.getValue(); String password = passwordBox.getValue(); if (StringUtils.isEmpty(username)) { throw new LoginFormException(LabelKey.Username_Cannot_be_Empty); } if (StringUtils.isEmpty(password)) { throw new LoginFormException(LabelKey.Password_Cannot_be_Empty); } UsernamePasswordToken token = new UsernamePasswordToken(username, password); try { subjectProvider.get() .login(token); log.debug("Publishing UserStatusBusMessage from: '{}'", this.getClass() .getSimpleName()); eventBus.publish(new UserStatusBusMessage(this, true)); } catch (UnknownAccountException uae) { loginExceptionHandler.unknownAccount(this, token); } catch (IncorrectCredentialsException ice) { loginExceptionHandler.incorrectCredentials(this, token); } catch (ExpiredCredentialsException ece) { loginExceptionHandler.expiredCredentials(this, token); } catch (LockedAccountException lae) { loginExceptionHandler.accountLocked(this, token); } catch (ExcessiveAttemptsException excess) { loginExceptionHandler.excessiveAttempts(this, token); } catch (DisabledAccountException dae) { loginExceptionHandler.disabledAccount(this, token); } catch (ConcurrentAccessException cae) { loginExceptionHandler.concurrentAccess(this, token); } catch (AuthenticationException ae) { loginExceptionHandler.authentication(this, token); } // unexpected condition - error? // an exception would be raised if login failed } @Override public void setUsername(String username) { usernameBox.setValue(username); } @Override public void setPassword(String password) { passwordBox.setValue(password); } @Override public Button getSubmitButton() { return submitButton; } @Override public String getStatusMessage() { return statusMsgLabel.getValue(); } @Override public void setStatusMessage(I18NKey messageKey) { setStatusMessage(translate.from(messageKey)); } @Override public void setStatusMessage(String msg) { statusMsgLabel.setValue(msg); } public TextField getUsernameBox() { return usernameBox; } public PasswordField getPasswordBox() { return passwordBox; } }