/*
* Rapid Beans Framework: DialogLogin.java
*
* Copyright (C) 2009 Martin Bluemel
*
* Creation Date: 11/08/2007
*
* This program 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 3 of the License, or (at your option) any later version.
* 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 Lesser General Public License for more details.
* You should have received a copies of the GNU Lesser General Public License and the
* GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
package org.rapidbeans.presentation;
import java.util.logging.Logger;
import org.rapidbeans.core.basic.RapidBean;
import org.rapidbeans.core.common.RapidBeansLocale;
import org.rapidbeans.core.exception.RapidBeansRuntimeException;
import org.rapidbeans.presentation.config.ApplicationGuiType;
import org.rapidbeans.presentation.settings.SettingsAll;
import org.rapidbeans.presentation.settings.SettingsAuthn;
import org.rapidbeans.presentation.settings.SettingsCred;
import org.rapidbeans.presentation.swing.DialogLoginSwing;
import org.rapidbeans.security.CryptoHelper;
import org.rapidbeans.security.LoginDialogResult;
import org.rapidbeans.security.User;
/**
* The super class that abstracts from gui implementation.
*
* @author Martin Bluemel
*/
public abstract class DialogLogin {
private static final Logger log = Logger.getLogger(DialogLogin.class.getName());
/**
* the dialog's title
*/
private String title;
/**
* @return the title
*/
protected String getTitle() {
return title;
}
/**
* @param title
* the title to set
*/
protected void setTitle(String title) {
this.title = title;
}
/**
* the user logged in.
*/
private RapidBean user = null;
/**
* the gui type independent login method.
*
* @param maxtries
* maximal count of tries
*
* @return the authenticated user.
*/
public static RapidBean login(final int maxtries) {
return login(maxtries, createDialog());
}
/**
* the gui type independent login method.
*
* @param maxtries
* maximal count of tries
*
* @return the authenticated user.
*/
protected static RapidBean login(final int maxtries, final DialogLogin dialog) {
final Application client = ApplicationManager.getApplication();
final SettingsAll settings = client.getSettings();
SettingsAuthn settingsAuthn = null;
if (settings != null) {
settingsAuthn = settings.getAuthn();
}
LoginDialogResult result = null;
for (int tryno = maxtries; tryno > 0; tryno--) {
result = dialog.tryLogin(tryno);
if (result == LoginDialogResult.ok || result == LoginDialogResult.cancelled
|| (result == LoginDialogResult.nopwd && dialog.user.getPropValue("pwd") == null)) {
break;
}
}
dialog.dispose();
if (result == LoginDialogResult.ok
|| (result == LoginDialogResult.nopwd && dialog.user.getPropValue("pwd") == null)) {
if (settings != null) {
if (settingsAuthn == null) {
settingsAuthn = new SettingsAuthn();
settings.setAuthn(settingsAuthn);
}
if (dialog.getSavecred()) {
SettingsCred cred = settingsAuthn.getCred();
if (cred == null) {
cred = new SettingsCred();
}
cred.setLogname(getTostoreLogname(dialog));
final String pwd = getTostorePwd(dialog);
cred.setPwd(pwd);
if (dialog.getEncryptcred()) {
cred.setEncrypted(true);
} else {
cred.setEncrypted(false);
}
settingsAuthn.setCred(cred);
} else {
settingsAuthn.setCred(null);
}
client.getSettingsDoc().save();
}
return dialog.user;
} else {
return null;
}
}
private static String getStoredLogname(final SettingsAuthn settingsAuthn) {
String logname = settingsAuthn.getCred().getLogname();
if (settingsAuthn.getCred().getEncrypted() && logname.length() > 3) {
logname = CryptoHelper.decrypt(logname);
}
return logname;
}
private static String getStoredPwd(final SettingsAuthn settingsAuthn) {
String pwd = settingsAuthn.getCred().getPwd();
if (settingsAuthn.getCred().getEncrypted() && pwd.length() > 3) {
pwd = CryptoHelper.decrypt(pwd);
}
return pwd;
}
private static String getTostoreLogname(final DialogLogin dialog) {
String logname = dialog.getLoginname();
if (dialog.getEncryptcred()) {
logname = CryptoHelper.encrypt(logname);
}
return logname;
}
private static String getTostorePwd(final DialogLogin dialog) {
String pwd = dialog.getPwd();
if (dialog.getEncryptcred() && pwd.length() > 3) {
pwd = CryptoHelper.encrypt(pwd);
}
return pwd;
}
/**
* factory method to create the login dialog appropriate for the GUI toolkit
* chosen.
*
* @return the login dialog created
*/
private static DialogLogin createDialog() {
DialogLogin dialog = null;
final Application client = ApplicationManager.getApplication();
final ApplicationGuiType guitype = client.getConfiguration().getGuitype();
boolean savecred = false;
boolean encryptcred = false;
final SettingsAll settings = client.getSettings();
SettingsAuthn settingsAuthn = null;
if (settings != null) {
settingsAuthn = settings.getAuthn();
}
if (settingsAuthn != null) {
if (settingsAuthn.getCred() != null) {
savecred = true;
}
final SettingsCred credsettings = settingsAuthn.getCred();
if (credsettings != null) {
if (credsettings.getPropValue("encrypted") == null) {
credsettings.setEncrypted(false);
encryptcred = true;
} else if (credsettings.getEncrypted()) {
encryptcred = true;
}
}
}
switch (guitype) {
case swing:
dialog = new DialogLoginSwing(savecred, encryptcred);
break;
default:
throw new RapidBeansRuntimeException("gui type \"" + guitype.name() + "\" not supported");
}
if (settingsAuthn != null && settingsAuthn.getCred() != null) {
dialog.setLoginname(getStoredLogname(settingsAuthn));
dialog.setPwd(getStoredPwd(settingsAuthn));
}
return dialog;
}
/**
* business logic of a single login try.
*
* @param tryno
* the number of the concrete login try counted backwards
*
* @return the result of the login dialog
*/
private LoginDialogResult tryLogin(final int tryno) {
final Application client = ApplicationManager.getApplication();
boolean ok = showLogin();
LoginDialogResult result = null;
if (!ok) {
result = LoginDialogResult.cancelled;
}
final String loginnameGiven = getLoginname();
if (result == null && (loginnameGiven == null || loginnameGiven.equals(""))) {
result = LoginDialogResult.nouser;
}
if (result == null) {
if (client.getAuthnDoc() == null) {
throw new RapidBeansRuntimeException("No authentication document specified");
}
this.user = client.getAuthnDoc().findBean("org.rapidbeans.security.User", loginnameGiven);
}
if (result == null && this.user == null) {
result = LoginDialogResult.unkownuser;
}
final String pwdGiven = getPwd();
String pwdHashed = null;
if ((result == null) && (pwdGiven != null && (!(pwdGiven.equals(""))))) {
if (client.getConfiguration() == null) {
log.warning("client.getConfiguration()");
} else {
if (client.getConfiguration().getAuthorization() == null) {
log.warning("client.getConfiguration().getAuthorization() == null");
} else {
final String pwdHashAlg = client.getConfiguration().getAuthorization().getPwdhashalgorithm();
if (pwdHashAlg != null) {
pwdHashed = User.hashPwd(pwdGiven, pwdHashAlg);
} else {
pwdHashed = pwdGiven;
}
}
}
}
if (result == null && (pwdHashed == null || pwdHashed.equals("")) && user.getPropValue("pwd") != null) {
result = LoginDialogResult.nopwd;
}
if (result == null) {
result = LoginDialogResult.wrongpwd;
if (user.getPropValue("pwd") == null) {
if (pwdHashed == null || pwdHashed.equals("")) {
result = LoginDialogResult.ok;
}
} else if (user.getPropValue("pwd").equals(pwdHashed)) {
result = LoginDialogResult.ok;
}
}
if (result != LoginDialogResult.nopwd || user.getPropValue("pwd") != null) {
this.evalResult(result, tryno);
}
return result;
}
/**
* Evaluate the login dialog result and show an appropriate massage.
*
* @param result
* the result of the login dialog
* @param tryno
* the number of the concrete login try
*
* @return the result
*/
private void evalResult(final LoginDialogResult result, final int tryno) {
final Application client = ApplicationManager.getApplication();
final RapidBeansLocale locale = client.getCurrentLocale();
switch (result) {
case ok:
break;
case cancelled:
client.messageInfo(locale.getStringMessage("login.cancelled"), this.getTitle());
break;
default:
if (tryno > 2) {
client.messageError(locale.getStringMessage("login.failed", Integer.toString(tryno - 1)),
this.getTitle());
} else if (tryno == 2) {
client.messageError(locale.getStringMessage("login.failed.uno"), this.getTitle());
} else {
client.messageError(locale.getStringMessage("login.failed.shut"), this.getTitle());
}
break;
}
}
/**
* this GUI toolkit specific method pops up a login dialog.
*
* @return if the dialog has been finished with OK (true) or Cancel (false),
* Closing the dialog is interpreted as Cancel.
*/
protected abstract boolean showLogin();
/**
* @return the login name entered
*/
protected abstract String getLoginname();
/**
* @param l
* the login name
*/
protected abstract void setLoginname(final String l);
/**
* Accesses the pwd entered and erases the pwd input field.
*
* @return the pwd entered
*/
protected abstract String getPwd();
/**
* @param p
* the pwd
*/
protected abstract void setPwd(final String p);
/**
* @return if saving the credentials is desired or not.
*/
protected abstract boolean getSavecred();
/**
* @return if encrypting the credentials is desired or not.
*/
protected abstract boolean getEncryptcred();
/**
* Dispose the dialog widget.
*/
protected abstract void dispose();
}