/*
* JBoss, Home of Professional Open Source.
* Copyright 2006, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.bpm.console.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.RunAsyncCallback;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.http.client.*;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.*;
import com.mvc4g.client.Controller;
import com.mvc4g.client.ViewInterface;
import org.gwt.mosaic.ui.client.Caption;
import org.gwt.mosaic.ui.client.MessageBox;
import org.gwt.mosaic.ui.client.WindowPanel;
import org.gwt.mosaic.ui.client.layout.BoxLayout;
import org.gwt.mosaic.ui.client.layout.BoxLayoutData;
import org.gwt.mosaic.ui.client.layout.MosaicPanel;
import org.jboss.bpm.console.client.util.ConsoleLog;
import org.jboss.errai.bus.client.ErraiBus;
import org.jboss.errai.bus.client.api.base.MessageBuilder;
import org.jboss.errai.bus.client.protocols.SecurityParts;
import org.jboss.errai.bus.client.security.SecurityService;
import org.jboss.errai.workspaces.client.framework.Registry;
import java.util.List;
/**
* @author Heiko.Braun <heiko.braun@jboss.com>
*/
public class LoginView implements ViewInterface
{
public final static String NAME = "loginView";
private ConsoleConfig config;
private Authentication auth;
private WindowPanel window = null;
private TextBox usernameInput;
private PasswordTextBox passwordInput;
public final static String[] KNOWN_ROLES = {"administrator", "manager", "user"};
private HTML messagePanel = new HTML("Authentication required");
public LoginView()
{
this.config = Registry.get(ApplicationContext.class).getConfig();
}
public void setController(Controller controller)
{
}
public void display()
{
// force session invalidation, required to catch browser reload
Authentication.logout(config);
// start new session
requestSessionID();
}
private void requestSessionID()
{
RequestBuilder rb = new RequestBuilder(
RequestBuilder.GET,
config.getConsoleServerUrl()+"/rs/identity/sid"
);
try
{
rb.sendRequest(null, new RequestCallback()
{
public void onResponseReceived(Request request, Response response)
{
ConsoleLog.debug("SID: "+ response.getText());
ConsoleLog.debug("Cookies: "+ Cookies.getCookieNames());
final String sid = response.getText();
auth = new Authentication(
config,
sid,
URLBuilder.getInstance().getUserInRoleURL(KNOWN_ROLES)
);
auth.setCallback(
new Authentication.AuthCallback()
{
public void onLoginSuccess(Request request, Response response)
{
// clear the form
usernameInput.setText("");
passwordInput.setText("");
// display main console
window.hide();
// assemble main layout
DeferredCommand.addCommand(
new Command()
{
public void execute()
{
// move the loading div to foreground
DOM.getElementById("splash").getStyle().setProperty("zIndex", "1000");
DOM.getElementById("ui_loading").getStyle().setProperty("visibility", "visible");
// launch workspace
GWT.runAsync(
new RunAsyncCallback()
{
public void onFailure(Throwable throwable)
{
GWT.log("Code splitting failed", throwable);
MessageBox.error("Code splitting failed", throwable.getMessage());
}
public void onSuccess()
{
List<String> roles = auth.getRolesAssigned();
StringBuilder roleString = new StringBuilder();
int index = 1;
for(String s : roles)
{
roleString.append(s);
if(index<roles.size())
roleString.append(",");
index++;
}
// populate authentication context
// this will trigger the AuthenticaionModule
// and finally initialize the workspace UI
Registry.get(SecurityService.class).setDeferredNotification(false);
MessageBuilder.createMessage()
.toSubject("AuthorizationListener")
.signalling()
.with(SecurityParts.Name, auth.getUsername())
.with(SecurityParts.Roles, roleString.toString())
.noErrorHandling()
.sendNowWith(ErraiBus.get()
);
Timer t = new Timer() {
public void run()
{
// hide the loading div
DeferredCommand.addCommand(
new Command()
{
public void execute()
{
DOM.getElementById("ui_loading").getStyle().setProperty("visibility", "hidden");
DOM.getElementById("splash").getStyle().setProperty("visibility", "hidden");
}
});
}
};
t.schedule(2000);
}
}
);
}
});
window = null;
}
public void onLoginFailed(Request request, Throwable t)
{
usernameInput.setText("");
passwordInput.setText("");
messagePanel.setHTML("<div style='color:#CC0000;'>Authentication failed. Please try again:</div>");
}
}
);
Registry.set(Authentication.class, auth);
createLayoutWindowPanel();
window.pack();
window.center();
// focus
usernameInput.setFocus(true);
}
public void onError(Request request, Throwable t)
{
ConsoleLog.error("Failed to initiate session", t);
}
});
}
catch (RequestException e)
{
ConsoleLog.error("Request error", e);
}
}
/**
* The 'layout' window panel.
*/
private void createLayoutWindowPanel() {
window = new WindowPanel(config.getProfileName(), false);
Widget closeBtn = window.getHeader().getWidget(0, Caption.CaptionRegion.RIGHT);
closeBtn.setVisible(false);
window.setAnimationEnabled(false);
MosaicPanel panel = new MosaicPanel();
panel.addStyleName("bpm-login");
createLayoutContent(panel);
window.setWidget(panel);
}
/**
* Create content for layout.
*/
private void createLayoutContent(MosaicPanel layoutPanel) {
layoutPanel.setLayout(new BoxLayout(BoxLayout.Orientation.VERTICAL));
layoutPanel.setPadding(10);
Widget form = createForm();
final Button submit = new Button("Login");
submit.addClickHandler(new ClickHandler()
{
public void onClick(ClickEvent clickEvent)
{
engageLogin();
}
});
HTML html = new HTML("Version: " + Version.VERSION);
html.setStyleName("bpm-login-info");
MosaicPanel btnPanel = new MosaicPanel(new BoxLayout());
btnPanel.add(html, new BoxLayoutData(BoxLayoutData.FillStyle.HORIZONTAL));
btnPanel.add(submit);
layoutPanel.add(messagePanel, new BoxLayoutData(BoxLayoutData.FillStyle.HORIZONTAL));
layoutPanel.add(form, new BoxLayoutData(BoxLayoutData.FillStyle.BOTH));
layoutPanel.add(btnPanel, new BoxLayoutData(BoxLayoutData.FillStyle.HORIZONTAL));
}
private Widget createForm()
{
MosaicPanel panel = new MosaicPanel(new BoxLayout(BoxLayout.Orientation.VERTICAL));
panel.setPadding(0);
MosaicPanel box1 = new MosaicPanel(new BoxLayout());
box1.setPadding(0);
MosaicPanel box2 = new MosaicPanel(new BoxLayout());
box2.setPadding(0);
usernameInput = new TextBox();
passwordInput = new PasswordTextBox();
BoxLayoutData bld1 = new BoxLayoutData(BoxLayoutData.FillStyle.HORIZONTAL);
bld1.setPreferredWidth("70px");
box1.add( new Label("Username:"), bld1);
box1.add(usernameInput);
box2.add(new Label("Password:"), bld1);
box2.add(passwordInput);
passwordInput.addKeyboardListener(
new KeyboardListener()
{
public void onKeyDown(Widget widget, char c, int i)
{
}
public void onKeyPress(Widget widget, char c, int i)
{
}
public void onKeyUp(Widget widget, char c, int i)
{
if(c == KeyboardListener.KEY_ENTER)
{
engageLogin();
}
}
}
);
panel.add(box1);
panel.add(box2);
return panel;
}
// -----------------------------------
private void engageLogin()
{
requestProtectedResource();
}
/**
* The j_security_check URL is a kind of temporary resource that only exists
* if tomcat decided that the login page should be shown.
*/
private void requestProtectedResource()
{
RequestBuilder rb = new RequestBuilder(
RequestBuilder.GET,
config.getConsoleServerUrl()+"/rs/identity/secure/sid"
);
try
{
rb.sendRequest(null, new RequestCallback()
{
public void onResponseReceived(Request request, Response response)
{
ConsoleLog.debug("requestProtectedResource() HTTP "+response.getStatusCode());
auth.login( getUsername(), getPassword() );
}
public void onError(Request request, Throwable t)
{
ConsoleLog.error("Failed to request protected resource", t);
}
});
}
catch (RequestException e)
{
ConsoleLog.error("Request error", e);
}
}
private String getUsername()
{
return usernameInput.getText();
}
private String getPassword()
{
return passwordInput.getText();
}
}