/****************************************************************************** * Product: Posterita Ajax UI * * Copyright (C) 2007 Posterita Ltd. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * For the text or an alternative of this public license, you may reach us * * Posterita Ltd., 3, Draper Avenue, Quatre Bornes, Mauritius * * or via info@posterita.org or http://www.posterita.org/ * * * * Contributors: * * - Heng Sin Low * * * * Sponsors: * * - Idalica Corporation * *****************************************************************************/ package org.adempiere.webui.panel; import java.text.MessageFormat; import java.util.Locale; import java.util.Properties; import java.util.ResourceBundle; import java.util.logging.Level; import org.adempiere.webui.LayoutUtils; import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.component.Combobox; import org.adempiere.webui.component.ConfirmPanel; import org.adempiere.webui.component.Label; import org.adempiere.webui.component.Textbox; import org.adempiere.webui.component.Window; import org.adempiere.webui.event.TokenEvent; import org.adempiere.webui.exception.ApplicationException; import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.theme.ITheme; import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.util.BrowserToken; import org.adempiere.webui.util.UserPreference; import org.adempiere.webui.window.LoginWindow; import org.compiere.Adempiere; import org.compiere.model.MSession; import org.compiere.model.MSystem; import org.compiere.model.MUser; import org.compiere.util.CLogger; import org.compiere.util.DB; import org.compiere.util.Env; import org.compiere.util.KeyNamePair; import org.compiere.util.Language; import org.compiere.util.Login; import org.compiere.util.Msg; import org.zkoss.lang.Strings; import org.zkoss.util.Locales; import org.zkoss.zhtml.Div; import org.zkoss.zhtml.Table; import org.zkoss.zhtml.Td; import org.zkoss.zhtml.Tr; import org.zkoss.zk.au.out.AuFocus; import org.zkoss.zk.au.out.AuScript; import org.zkoss.zk.fn.ZkFns; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.Session; import org.zkoss.zk.ui.WrongValueException; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; import org.zkoss.zk.ui.util.Clients; import org.zkoss.zul.Checkbox; import org.zkoss.zul.Comboitem; import org.zkoss.zul.Image; /** * * @author <a href="mailto:agramdass@gmail.com">Ashley G Ramdass</a> * @date Feb 25, 2007 * @version $Revision: 0.10 $ * @author <a href="mailto:sendy.yagambrum@posterita.org">Sendy Yagambrum</a> * @date July 18, 2007 */ public class LoginPanel extends Window implements EventListener { /** * */ private static final long serialVersionUID = 3992171368813030624L; private static final String RESOURCE = "org.compiere.apps.ALoginRes"; private ResourceBundle res = ResourceBundle.getBundle(RESOURCE); private static CLogger logger = CLogger.getCLogger(LoginPanel.class); private Properties ctx; private Label lblUserId; private Label lblPassword; private Label lblLanguage; private Textbox txtUserId; private Textbox txtPassword; private Combobox lstLanguage; private LoginWindow wndLogin; private Checkbox chkRememberMe; public LoginPanel(Properties ctx, LoginWindow loginWindow) { this.ctx = ctx; this.wndLogin = loginWindow; initComponents(); init(); this.setId("loginPanel"); AuFocus auf = new AuFocus(txtUserId); Clients.response(auf); BrowserToken.load(this.getUuid()); } private void init() { Div div = new Div(); div.setSclass(ITheme.LOGIN_BOX_HEADER_CLASS); Label label = new Label("Login"); label.setSclass(ITheme.LOGIN_BOX_HEADER_TXT_CLASS); div.appendChild(label); this.appendChild(div); Table table = new Table(); table.setId("grdLogin"); table.setDynamicProperty("cellpadding", "0"); table.setDynamicProperty("cellspacing", "5"); table.setSclass(ITheme.LOGIN_BOX_BODY_CLASS); this.appendChild(table); Tr tr = new Tr(); table.appendChild(tr); Td td = new Td(); td.setSclass(ITheme.LOGIN_BOX_HEADER_LOGO_CLASS); tr.appendChild(td); td.setDynamicProperty("colspan", "2"); Image image = new Image(); image.setSrc(ThemeManager.getLargeLogo()); td.appendChild(image); tr = new Tr(); tr.setId("rowUser"); table.appendChild(tr); td = new Td(); tr.appendChild(td); td.setSclass(ITheme.LOGIN_LABEL_CLASS); td.appendChild(lblUserId); td = new Td(); td.setSclass(ITheme.LOGIN_FIELD_CLASS); tr.appendChild(td); td.appendChild(txtUserId); tr = new Tr(); tr.setId("rowPassword"); table.appendChild(tr); td = new Td(); tr.appendChild(td); td.setSclass(ITheme.LOGIN_LABEL_CLASS); td.appendChild(lblPassword); td = new Td(); td.setSclass(ITheme.LOGIN_FIELD_CLASS); tr.appendChild(td); td.appendChild(txtPassword); tr = new Tr(); tr.setId("rowLanguage"); table.appendChild(tr); td = new Td(); tr.appendChild(td); td.setSclass(ITheme.LOGIN_LABEL_CLASS); td.appendChild(lblLanguage); td = new Td(); td.setSclass(ITheme.LOGIN_FIELD_CLASS); tr.appendChild(td); td.appendChild(lstLanguage); if (MSystem.isZKRememberUserAllowed()) { tr = new Tr(); tr.setId("rowRememberMe"); table.appendChild(tr); td = new Td(); tr.appendChild(td); td.setSclass(ITheme.LOGIN_LABEL_CLASS); td.appendChild(new Label("")); td = new Td(); td.setSclass(ITheme.LOGIN_FIELD_CLASS); tr.appendChild(td); td.appendChild(chkRememberMe); } div = new Div(); div.setSclass(ITheme.LOGIN_BOX_FOOTER_CLASS); ConfirmPanel pnlButtons = new ConfirmPanel(false); pnlButtons.addActionListener(this); LayoutUtils.addSclass(ITheme.LOGIN_BOX_FOOTER_PANEL_CLASS, pnlButtons); pnlButtons.setWidth(null); pnlButtons.getButton(ConfirmPanel.A_OK).setSclass(ITheme.LOGIN_BUTTON_CLASS); div.appendChild(pnlButtons); this.appendChild(div); this.addEventListener(TokenEvent.ON_USER_TOKEN, new EventListener() { @Override public void onEvent(Event event) throws Exception { String[] data = (String[]) event.getData(); try { int AD_Session_ID = Integer.parseInt(data[0]); MSession session = new MSession(Env.getCtx(), AD_Session_ID, null); if (session.get_ID() == AD_Session_ID) { int AD_User_ID = session.getCreatedBy(); MUser user = MUser.get(Env.getCtx(), AD_User_ID); if (user != null && user.get_ID() == AD_User_ID) { String token = data[1]; if (BrowserToken.validateToken(session, user, token)) { if (MSystem.isZKRememberUserAllowed()) { txtUserId.setValue(user.getName()); onUserIdChange(); chkRememberMe.setChecked(true); } if (MSystem.isZKRememberPasswordAllowed()) { txtPassword.setValue(token); txtPassword.setAttribute("user.token.hash", token); txtPassword.setAttribute("user.token.sid", AD_Session_ID); } } } } } catch (Exception e) { //safe to ignore logger.log(Level.INFO, e.getLocalizedMessage(), e); } } }); } private void initComponents() { lblUserId = new Label(); lblUserId.setId("lblUserId"); lblUserId.setValue("User ID"); lblPassword = new Label(); lblPassword.setId("lblPassword"); lblPassword.setValue("Password"); lblLanguage = new Label(); lblLanguage.setId("lblLanguage"); lblLanguage.setValue("Language"); txtUserId = new Textbox(); txtUserId.setId("txtUserId"); txtUserId.setCols(25); txtUserId.setMaxlength(40); txtUserId.setWidth("220px"); txtUserId.addEventListener(Events.ON_CHANGE, this); // Elaine 2009/02/06 txtPassword = new Textbox(); txtPassword.setId("txtPassword"); txtPassword.setType("password"); txtPassword.setCols(25); // txtPassword.setMaxlength(40); txtPassword.setWidth("220px"); lstLanguage = new Combobox(); lstLanguage.setAutocomplete(true); lstLanguage.setAutodrop(true); lstLanguage.setId("lstLanguage"); lstLanguage.addEventListener(Events.ON_SELECT, this); lstLanguage.setWidth("220px"); // Update Language List lstLanguage.getItems().clear(); String[] availableLanguages = Language.getNames(); for (String langName : availableLanguages) { Language language = Language.getLanguage(langName); lstLanguage.appendItem(langName, language.getAD_Language()); } chkRememberMe = new Checkbox(Msg.getMsg(Language.getBaseAD_Language(), "RememberMe")); //set base language String baseLanguage = Language.getBaseLanguage().getName(); for(int i = 0; i < lstLanguage.getItemCount(); i++) { Comboitem li = lstLanguage.getItemAtIndex(i); if(li.getLabel().equals(baseLanguage)) { lstLanguage.setSelectedIndex(i); languageChanged(li.getLabel()); break; } } } public void onEvent(Event event) { Component eventComp = event.getTarget(); if (event.getTarget().getId().equals(ConfirmPanel.A_OK)) { validateLogin(); } if (event.getName().equals(Events.ON_SELECT)) { if(eventComp.getId().equals(lstLanguage.getId())) { String langName = (String) lstLanguage.getSelectedItem().getLabel(); languageChanged(langName); } } // Elaine 2009/02/06 - initial language if (event.getName().equals(Events.ON_CHANGE)) { if(eventComp.getId().equals(txtUserId.getId())) { onUserIdChange(); } } // } private void onUserIdChange() { String userId = txtUserId.getValue(); if(userId != null && userId.length() > 0) { int AD_User_ID = DB.getSQLValue(null, "SELECT AD_User_ID FROM AD_User WHERE Name = ?", userId); if(AD_User_ID > 0) { // Elaine 2009/02/06 Load preference from AD_Preference UserPreference userPreference = SessionManager.getSessionApplication().loadUserPreference(AD_User_ID); String initDefault = userPreference.getProperty(UserPreference.P_LANGUAGE); for(int i = 0; i < lstLanguage.getItemCount(); i++) { Comboitem li = lstLanguage.getItemAtIndex(i); if(li.getLabel().equals(initDefault)) { lstLanguage.setSelectedIndex(i); languageChanged(li.getLabel()); // Elaine 2009/04/17 language changed break; } } } } } private void languageChanged(String langName) { Language language = findLanguage(langName); // Locales Locale loc = language.getLocale(); Locale.setDefault(loc); res = ResourceBundle.getBundle(RESOURCE, loc); lblUserId.setValue(res.getString("User")); lblPassword.setValue(res.getString("Password")); lblLanguage.setValue(res.getString("Language")); chkRememberMe.setLabel(Msg.getMsg(language, "RememberMe")); } private Language findLanguage(String langName) { Language tmp = Language.getLanguage(langName); Language language = new Language(tmp.getName(), tmp.getAD_Language(), tmp.getLocale(), tmp.isDecimalPoint(), tmp.getDateFormat().toPattern(), tmp.getMediaSize()); Env.verifyLanguage(ctx, language); Env.setContext(ctx, Env.LANGUAGE, language.getAD_Language()); Env.setContext(ctx, AEnv.LOCALE, language.getLocale().toString()); return language; } /** * validates user name and password when logging in * **/ public void validateLogin() { Login login = new Login(ctx); String userId = txtUserId.getValue(); String userPassword = txtPassword.getValue(); //check is token String token = (String) txtPassword.getAttribute("user.token.hash"); if (token != null && token.equals(userPassword)) { userPassword = ""; int AD_Session_ID = (Integer)txtPassword.getAttribute("user.token.sid"); MSession session = new MSession(Env.getCtx(), AD_Session_ID, null); if (session.get_ID() == AD_Session_ID) { MUser user = MUser.get(Env.getCtx(), session.getCreatedBy()); if (BrowserToken.validateToken(session, user, token)) { userPassword = user.getPassword(); } } } KeyNamePair rolesKNPairs[] = login.getRoles(userId, userPassword); if(rolesKNPairs == null || rolesKNPairs.length == 0) throw new WrongValueException("User Id or Password invalid!!!"); else { String langName = null; if ( lstLanguage.getSelectedItem() != null ) langName = (String) lstLanguage.getSelectedItem().getLabel(); else langName = Language.getBaseLanguage().getName(); Language language = findLanguage(langName); wndLogin.loginOk(userId, userPassword); Env.setContext(ctx, UserPreference.LANGUAGE_NAME, language.getName()); // Elaine 2009/02/06 Locales.setThreadLocal(language.getLocale()); Clients.response("zkLocaleJavaScript", new AuScript(null, ZkFns.outLocaleJavaScript())); String timeoutText = getUpdateTimeoutTextScript(); if (!Strings.isEmpty(timeoutText)) Clients.response("zkLocaleJavaScript2", new AuScript(null, timeoutText)); } // This temporary validation code is added to check the reported bug // [ adempiere-ZK Web Client-2832968 ] User context lost? // https://sourceforge.net/tracker/?func=detail&atid=955896&aid=2832968&group_id=176962 // it's harmless, if there is no bug then this must never fail Session currSess = Executions.getCurrent().getDesktop().getSession(); currSess.setAttribute("Check_AD_User_ID", Env.getAD_User_ID(ctx)); // End of temporary code for [ adempiere-ZK Web Client-2832968 ] User context lost? Env.setContext(ctx, BrowserToken.REMEMBER_ME, chkRememberMe.isChecked()); /* Check DB version */ String version = DB.getSQLValueString(null, "SELECT Version FROM AD_System"); // Identical DB version if (! Adempiere.DB_VERSION.equals(version)) { String AD_Message = "DatabaseVersionError"; // Code assumes Database version {0}, but Database has Version {1}. String msg = Msg.getMsg(ctx, AD_Message); // complete message msg = MessageFormat.format(msg, new Object[] {Adempiere.DB_VERSION, version}); throw new ApplicationException(msg); } } private String getUpdateTimeoutTextScript() { String msg = Msg.getMsg(Env.getCtx(), "SessionTimeoutText"); if (msg == null || msg.equals("SessionTimeoutText")) { return null; } msg = Strings.escape(msg, "\""); String s = "adempiere.store.set(\"zkTimeoutText\", \"" + msg + "\")"; return s; } }