From dc2659d05ca704ae7275adfe3d14f6dcd1023f30 Mon Sep 17 00:00:00 2001 From: Matti Tahvonen Date: Thu, 28 Feb 2008 10:14:50 +0000 Subject: [PATCH] Prototype of LoginBox component. svn changeset:3938/svn branch:trunk --- .../tests/tickets/Ticket1362Login.java | 272 ++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 src/com/itmill/toolkit/tests/tickets/Ticket1362Login.java diff --git a/src/com/itmill/toolkit/tests/tickets/Ticket1362Login.java b/src/com/itmill/toolkit/tests/tickets/Ticket1362Login.java new file mode 100644 index 0000000000..9b99019773 --- /dev/null +++ b/src/com/itmill/toolkit/tests/tickets/Ticket1362Login.java @@ -0,0 +1,272 @@ +package com.itmill.toolkit.tests.tickets; + +import java.io.ByteArrayInputStream; +import java.net.URL; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Map; + +import com.itmill.toolkit.Application; +import com.itmill.toolkit.terminal.ApplicationResource; +import com.itmill.toolkit.terminal.DownloadStream; +import com.itmill.toolkit.terminal.ParameterHandler; +import com.itmill.toolkit.terminal.URIHandler; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.CustomComponent; +import com.itmill.toolkit.ui.Embedded; +import com.itmill.toolkit.ui.ExpandLayout; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.Panel; +import com.itmill.toolkit.ui.Window; +import com.itmill.toolkit.ui.Button.ClickEvent; +import com.itmill.toolkit.ui.Window.Notification; + +/** + * Proof of concept how to create a decent login screen that works with browsers + * PW managers. (Browsers don't autofill generated login forms) + * + * TODO generalize js to work inside iframes (if toolkit is inside iframe) + * + * TODO extract login form to a external template. + * + * TODO theme + * + * TODO refine docs, make LoginBox a standard toolkit component + * + * TODO article + * + */ +public class Ticket1362Login extends Application { + + public class LoginBox extends CustomComponent { + + Embedded iframe = new Embedded(); + + ApplicationResource loginPage = new ApplicationResource() { + + private byte[] loginHTML = ("" + + "" + + "" + + "" + + "Iframe generated by LoginBox. PW managers can autofill form. Form handled by LoginBox " + + "that will fire LoginEvents. Will post into another iframe, from where the script " + + "will find toolkit client that will be force synced.
" + + "Username : " + + "Password : " + + "" + "
" + + "" + "" + + "").getBytes(); + + public Application getApplication() { + return LoginBox.this.getApplication(); + } + + public int getBufferSize() { + return loginHTML.length; + } + + public long getCacheTime() { + return 0; + } + + public String getFilename() { + return "login.html"; + } + + public DownloadStream getStream() { + return new DownloadStream(new ByteArrayInputStream(loginHTML), + getMIMEType(), getFilename()); + } + + public String getMIMEType() { + return "text/html"; + } + }; + + private ParameterHandler paramHandler = new ParameterHandler() { + + public void handleParameters(Map parameters) { + if (parameters.containsKey("username")) { + getWindow().addURIHandler(uriHandler); + + HashMap params = new HashMap(); + // expecting single params + for (Iterator it = parameters.keySet().iterator(); it + .hasNext();) { + String key = (String) it.next(); + String value = ((String[]) parameters.get(key))[0]; + params.put(key, value); + } + LoginEvent event = new LoginEvent(params); + for (Iterator iterator = listeners.iterator(); iterator + .hasNext();) { + LoginListener listener = (LoginListener) iterator + .next(); + listener.onLogin(event); + } + } + } + }; + + private URIHandler uriHandler = new URIHandler() { + public DownloadStream handleURI(URL context, String relativeUri) { + if (window != null) { + window.removeURIHandler(this); + } + return new DownloadStream( + new ByteArrayInputStream( + "Login form handeled." + .getBytes()), "text/html", + "loginSuccesfull.html"); + } + }; + + private LinkedList listeners = new LinkedList(); + + private Window window; + + LoginBox() { + iframe.setType(Embedded.TYPE_BROWSER); + iframe.setSizeFull(); + setCompositionRoot(iframe); + } + + public void attach() { + super.attach(); + getApplication().addResource(loginPage); + getWindow().addParameterHandler(paramHandler); + iframe.setSource(loginPage); + } + + public void detach() { + getApplication().removeResource(loginPage); + getWindow().removeParameterHandler(paramHandler); + // store window temporary to properly remove uri handler once + // response is handled. (May happen if login handler removes login + // box + window = getWindow(); + super.detach(); + } + + /** + * This event is sent when login form is submitted. + */ + public class LoginEvent { + + private Map params; + + private LoginEvent(Map params) { + this.params = params; + } + + /** + * Returns form value by field name. + * + * @param name + * @return value in given field + */ + public String getLoginParameter(String name) { + if (params.containsKey(name)) { + return (String) params.get(name); + } else { + return null; + } + } + } + + /** + * Adds LoginListener to handle login logic + * + * @param listener + */ + public void addLoginListener(LoginListener listener) { + listeners.add(listener); + } + + /** + * Removes LoginListener + * + * @param listener + */ + public void removeLoginListener(LoginListener listener) { + listeners.remove(listener); + } + + } + + /** + * Login listener is a class capable to listen LoginEvents sent from + * LoginBox + */ + public interface LoginListener { + /** + * This method is fired on each login form post. + * + * @param event + */ + public void onLogin(LoginBox.LoginEvent event); + } + + final static String GUEST = "guest"; + + LoginBox loginBox = new LoginBox(); + + Label currentUser = new Label(GUEST); + + private Panel mainPanel; + + private ExpandLayout el; + + public void init() { + + final Window mainWin = new Window( + "Test app with password manager savvy login functionality"); + + el = new ExpandLayout(); + + currentUser.setCaption("Currennt user"); + el.addComponent(currentUser); + + el.addComponent(loginBox); + el.expand(loginBox); + + mainWin.setLayout(el); + + setMainWindow(mainWin); + + mainPanel = new Panel("Test app"); + mainPanel.setSizeFull(); + mainPanel.addComponent(new Label("User is logged in")); + mainPanel.addComponent(new Button("Logout", new Button.ClickListener() { + + public void buttonClick(ClickEvent event) { + Ticket1362Login.this.close(); + } + })); + + loginBox.addLoginListener(new LoginListener() { + public void onLogin(LoginBox.LoginEvent event) { + String pw = event.getLoginParameter("password"); + String username = event.getLoginParameter("username"); + if (pw.equals("1234")) { + setUser(username); + currentUser.setValue(username); + currentUser.getWindow().showNotification( + "Logged in user: " + username); + getMainWindow().getLayout().replaceComponent(loginBox, + mainPanel); + el.expand(mainPanel); + } else { + getMainWindow().showNotification( + "Wrong password. Hint, try '1234' ", + Notification.TYPE_WARNING_MESSAGE); + } + } + }); + + } + +} \ No newline at end of file -- 2.39.5