/*
* Copyright (C) 2014 Jan Pokorsky
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cz.cas.lib.proarc.webapp.client.widget;
import com.google.gwt.core.client.GWT;
import com.smartgwt.client.i18n.SmartGwtMessages;
import com.smartgwt.client.rpc.LoginRequiredCallback;
import com.smartgwt.client.rpc.RPCCallback;
import com.smartgwt.client.rpc.RPCManager;
import com.smartgwt.client.rpc.RPCRequest;
import com.smartgwt.client.rpc.RPCResponse;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.ReadOnlyDisplayAppearance;
import com.smartgwt.client.types.TitleOrientation;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.IButton;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.events.SubmitValuesEvent;
import com.smartgwt.client.widgets.form.events.SubmitValuesHandler;
import com.smartgwt.client.widgets.form.fields.PasswordItem;
import com.smartgwt.client.widgets.form.fields.StaticTextItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.layout.HStack;
import com.smartgwt.client.widgets.layout.VLayout;
import cz.cas.lib.proarc.webapp.client.ClientMessages;
import cz.cas.lib.proarc.webapp.client.ClientUtils;
import cz.cas.lib.proarc.webapp.client.ds.RestConfig;
import java.util.HashMap;
import java.util.Map;
/**
* The login window to get user credentials and authenticate the user.
* It registers own relogin callback to {@link RPCManager}.
*
* @author Jan Pokorsky
*/
public final class LoginWindow {
private static LoginWindow INSTANCE;
private static final String USERNAME = "j_username";
private static final String PASSWORD = "j_password";
private static final String PRODUCER_CODE = "j_code";
private static final String ERROR = "error";
private final DynamicForm form;
private final ClientMessages i18n;
private final SmartGwtMessages i18nSgwt;
private Window window;
public static LoginWindow login() {
if (INSTANCE == null) {
INSTANCE = new LoginWindow();
}
return INSTANCE;
}
private LoginWindow() {
i18n = GWT.create(ClientMessages.class);
i18nSgwt = ClientUtils.createSmartGwtMessages();
form = createForm();
reloginCallback();
}
private void showWindow(Object loginType) {
if (window == null) {
window = createWindow(form);
form.focusInItem(USERNAME);
} else if (window.isVisible()) {
// ignore subsequent requests after the session timeout detection
return ;
}
window.show();
form.clearErrors(true);
form.focus();
if (form.getValueAsString(USERNAME) != null) {
// relogin
form.getField(USERNAME).setCanEdit(false);
form.getField(USERNAME).setCanFocus(false);
form.getField(PRODUCER_CODE).setCanEdit(false);
form.getField(PRODUCER_CODE).setCanFocus(false);
form.clearValue(PASSWORD);
form.focusInItem(PASSWORD);
}
if ("desa".equals(loginType)) {
form.getField(PRODUCER_CODE).setVisible(true);
} else {
form.getField(PRODUCER_CODE).clearValue();
form.getField(PRODUCER_CODE).setVisible(false);
}
}
private Window createWindow(DynamicForm form) {
VLayout container = new VLayout();
container.setMembers(form, createButtons());
container.setMargin(15);
Window window = new Window();
window.setAutoCenter(true);
window.setAutoSize(true);
window.setIsModal(true);
window.addItem(container);
window.setTitle(i18nSgwt.dialog_LoginTitle());
window.setShowCloseButton(false);
window.setShowMinimizeButton(false);
window.setKeepInParentRect(true);
window.setShowModalMask(true);
window.setCanDragReposition(false);
return window;
}
private DynamicForm createForm() {
DynamicForm f = new DynamicForm();
f.setWidth(400);
f.setBrowserSpellCheck(false);
f.setNumCols(1);
f.setTitleOrientation(TitleOrientation.TOP);
f.setSaveOnEnter(true);
TextItem user = new TextItem(USERNAME, i18nSgwt.dialog_UserNameTitle());
user.setRequired(true);
user.setWidth("*");
user.setReadOnlyDisplay(ReadOnlyDisplayAppearance.STATIC);
PasswordItem passwd = new PasswordItem(PASSWORD, i18nSgwt.dialog_PasswordTitle());
passwd.setRequired(true);
passwd.setWidth("*");
TextItem producerCode = new TextItem(PRODUCER_CODE, i18n.LoginWindow_ProducerCode());
producerCode.setWidth("*");
producerCode.setReadOnlyDisplay(ReadOnlyDisplayAppearance.STATIC);
StaticTextItem error = new StaticTextItem(ERROR);
error.setShowTitle(false);
error.setShowErrorText(true);
f.setItems(user, producerCode, passwd, error);
f.addSubmitValuesHandler(new SubmitValuesHandler() {
@Override
public void onSubmitValues(SubmitValuesEvent event) {
submitCredentials();
}
});
return f;
}
private void finish() {
window.hide();
}
private Canvas createButtons() {
IButton btnSubmit = new IButton(i18nSgwt.dialog_LoginButtonTitle(), new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
submitCredentials();
}
});
HStack btnLayout = new HStack(5);
btnLayout.setAutoHeight();
btnLayout.setLayoutTopMargin(20);
btnLayout.setLayoutAlign(Alignment.CENTER);
btnLayout.setMembers(btnSubmit);
return btnLayout;
}
private Map<?,?> getCredentials() {
Map<?,?> values = form.getValues();
values.remove(ERROR);
if (values.get(PRODUCER_CODE) == null) {
values.remove(PRODUCER_CODE);
}
return values;
}
private void showErrors() {
i18nSgwt.dialog_LoginErrorMessage();
HashMap<String, String> errors = new HashMap<String, String>();
errors.put(ERROR, i18nSgwt.dialog_LoginErrorMessage());
form.setErrors(errors, true);
}
private void submitCredentials() {
RPCRequest request = new RPCRequest();
request.setContainsCredentials(true);
request.setActionURL(RestConfig.URL_LOGIN_SERVLET);
request.setUseSimpleHttp(true);
request.setShowPrompt(false);
request.setParams(getCredentials());
RPCManager.sendRequest(request, new RPCCallback() {
@Override
public void execute(RPCResponse response, Object rawData, RPCRequest request) {
if (response.getHttpResponseCode() == 200) {
finish();
RPCManager.resendTransaction();
} else {
showErrors();
}
}
});
}
/**
* Registers relogin callback.
*
* @see <a href="http://www.smartclient.com/smartgwt/javadoc/com/smartgwt/client/docs/Relogin.html">SmartGWT Relogin</a>
*/
private void reloginCallback() {
RPCManager.setLoginRequiredCallback(new LoginRequiredCallback() {
@Override
public void loginRequired(int transactionNum,
com.smartgwt.client.rpc.RPCRequest rpcRequest,
RPCResponse rpcResponse) {
Map httpHeaders = rpcResponse.getHttpHeaders();
Object loginType = httpHeaders.get("ProArc-Authenticate");
showWindow(loginType);
}
});
}
}