/*
Copyright 2008-2013 Josh Drummond
This file is part of WebPasswordSafe.
WebPasswordSafe 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 2 of the License, or
(at your option) any later version.
WebPasswordSafe 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 WebPasswordSafe; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.webpasswordsafe.client.ui;
import java.util.List;
import net.webpasswordsafe.client.WebPasswordSafe;
import net.webpasswordsafe.client.i18n.TextMessages;
import net.webpasswordsafe.client.remote.UserService;
import net.webpasswordsafe.common.model.Group;
import net.webpasswordsafe.common.model.User;
import net.webpasswordsafe.common.model.UserAuthnPassword;
import net.webpasswordsafe.common.util.Constants;
import net.webpasswordsafe.common.util.Utils;
import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.Style.SortDir;
import com.extjs.gxt.ui.client.data.BaseModel;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.util.Format;
import com.extjs.gxt.ui.client.widget.Info;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.CheckBox;
import com.extjs.gxt.ui.client.widget.form.DualListField;
import com.extjs.gxt.ui.client.widget.form.ListField;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.extjs.gxt.ui.client.widget.layout.AbsoluteLayout;
import com.extjs.gxt.ui.client.widget.layout.AbsoluteData;
import com.extjs.gxt.ui.client.widget.form.LabelField;
/**
* @author Josh Drummond
*
*/
public class UserDialog extends Window
{
private final static TextMessages textMessages = GWT.create(TextMessages.class);
private User user;
private TextField<String> usernameTextBox;
private TextField<String> fullnameTextBox;
private TextField<String> emailTextBox;
private TextField<String> password1TextBox;
private TextField<String> password2TextBox;
private CheckBox enabledCheckBox;
private ListStore<GroupData> fromGroupStore;
private ListStore<GroupData> toGroupStore;
public UserDialog(User pUser)
{
this.user = pUser;
this.setHeading(textMessages.user());
this.setModal(true);
this.setLayout(new AbsoluteLayout());
this.setSize("455", "475");
this.setResizable(false);
LabelField lblfldUsername = new LabelField(textMessages.username_());
add(lblfldUsername, new AbsoluteData(6, 6));
usernameTextBox = new TextField<String>();
usernameTextBox.setReadOnly(user.getId() > 0);
add(usernameTextBox, new AbsoluteData(144, 6));
usernameTextBox.setSize("271px", "22px");
LabelField lblfldFullName = new LabelField(textMessages.fullname_());
add(lblfldFullName, new AbsoluteData(6, 34));
fullnameTextBox = new TextField<String>();
add(fullnameTextBox, new AbsoluteData(144, 34));
fullnameTextBox.setSize("271px", "22px");
LabelField lblfldEmail = new LabelField(textMessages.email_());
add(lblfldEmail, new AbsoluteData(6, 62));
emailTextBox = new TextField<String>();
add(emailTextBox, new AbsoluteData(144, 62));
emailTextBox.setSize("271px", "22px");
LabelField lblfldPassword = new LabelField(textMessages.password_());
add(lblfldPassword, new AbsoluteData(6, 90));
password1TextBox = new TextField<String>();
password1TextBox.setPassword(true);
add(password1TextBox, new AbsoluteData(144, 90));
password1TextBox.setSize("271px", "22px");
password2TextBox = new TextField<String>();
password2TextBox.setPassword(true);
add(password2TextBox, new AbsoluteData(144, 118));
password2TextBox.setSize("271px", "22px");
enabledCheckBox = new CheckBox();
enabledCheckBox.setBoxLabel(textMessages.enabled());
add(enabledCheckBox, new AbsoluteData(144, 146));
enabledCheckBox.setSize("76px", "22px");
LabelField lblfldGroups = new LabelField(textMessages.groups_());
add(lblfldGroups, new AbsoluteData(6, 170));
LabelField lblfldAvailable = new LabelField(textMessages.available());
add(lblfldAvailable, new AbsoluteData(6, 195));
LabelField lblfldMembers = new LabelField(textMessages.memberOf());
add(lblfldMembers, new AbsoluteData(233, 195));
DualListField<GroupData> membersListBox = new DualListField<GroupData>();
add(membersListBox, new AbsoluteData(6, 216));
membersListBox.setSize("424px", "183px");
ListField<GroupData> from = membersListBox.getFromList();
ListField<GroupData> to = membersListBox.getToList();
from.setSize(300, 100);
from.setDisplayField(Constants.NAME);
fromGroupStore = new ListStore<GroupData>();
fromGroupStore.sort(Constants.NAME, SortDir.ASC);
from.setStore(fromGroupStore);
to.setDisplayField(Constants.NAME);
to.setSize(300, 100);
toGroupStore = new ListStore<GroupData>();
toGroupStore.sort(Constants.NAME, SortDir.ASC);
to.setStore(toGroupStore);
Button saveButton = new Button(textMessages.save(), new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent ce) {
doSave();
}
});
Button cancelButton = new Button(textMessages.cancel(), new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent ce) {
doCancel();
}
});
setButtonAlign(HorizontalAlignment.CENTER);
addButton(saveButton);
addButton(cancelButton);
setFields();
}
@Override
public void show()
{
super.show();
if (user.getId() == 0)
{
setFocusWidget(usernameTextBox);
}
else
{
setFocusWidget(fullnameTextBox);
}
}
private void setFields()
{
usernameTextBox.setValue(user.getUsername());
fullnameTextBox.setValue(user.getFullname());
emailTextBox.setValue(user.getEmail());
enabledCheckBox.setValue(user.isActiveFlag());
for (Group group : user.getGroups())
{
if (!group.getName().equals(Constants.EVERYONE_GROUP_NAME))
{
toGroupStore.add(new GroupData(group));
}
}
loadAvailableGroups();
}
private boolean validateFields()
{
if (!(Utils.safeString(password2TextBox.getValue())).equals(Utils.safeString(password1TextBox.getValue())))
{
MessageBox.alert(textMessages.error(), textMessages.passwordsNotMatch(), null);
return false;
}
if (Utils.safeString(password1TextBox.getValue()).length() > UserAuthnPassword.LENGTH_PASSWORD)
{
MessageBox.alert(textMessages.error(), textMessages.tooLongPassword(), null);
return false;
}
if (Utils.safeString(usernameTextBox.getValue()).equals(""))
{
MessageBox.alert(textMessages.error(), textMessages.mustEnterUsername(), null);
return false;
}
if (Utils.safeString(usernameTextBox.getValue()).length() > User.LENGTH_USERNAME)
{
MessageBox.alert(textMessages.error(), textMessages.tooLongUsername(), null);
return false;
}
if (Utils.safeString(fullnameTextBox.getValue()).equals(""))
{
MessageBox.alert(textMessages.error(), textMessages.mustEnterFullName(), null);
return false;
}
if (Utils.safeString(fullnameTextBox.getValue()).length() > User.LENGTH_FULLNAME)
{
MessageBox.alert(textMessages.error(), textMessages.tooLongFullName(), null);
return false;
}
if (Utils.safeString(emailTextBox.getValue()).equals(""))
{
MessageBox.alert(textMessages.error(), textMessages.mustEnterEmail(), null);
return false;
}
if (Utils.safeString(emailTextBox.getValue()).length() > User.LENGTH_EMAIL)
{
MessageBox.alert(textMessages.error(), textMessages.tooLongEmail(), null);
return false;
}
if (!Utils.isValidEmail(Utils.safeString(emailTextBox.getValue())))
{
MessageBox.alert(textMessages.error(), textMessages.invalidEmail(), null);
return false;
}
return true;
}
private void doSave()
{
if (validateFields())
{
user.setUsername(Utils.safeString(usernameTextBox.getValue()));
user.setFullname(Utils.safeString(fullnameTextBox.getValue()));
user.setEmail(Utils.safeString(emailTextBox.getValue()));
user.setActiveFlag(enabledCheckBox.getValue());
user.updateAuthnPasswordValue(Utils.safeString(password1TextBox.getValue()));
user.removeGroups();
for (GroupData groupData : toGroupStore.getModels())
{
Group group = (Group)groupData.get(Constants.GROUP);
user.addGroup(group);
}
final AsyncCallback<Void> callback = new AsyncCallback<Void>()
{
@Override
public void onFailure(Throwable caught)
{
WebPasswordSafe.handleServerFailure(caught);
}
@Override
public void onSuccess(Void result)
{
Info.display(textMessages.status(), textMessages.userSaved());
hide();
}
};
if (user.getId() == 0)
{
final AsyncCallback<Boolean> callbackCheck = new AsyncCallback<Boolean>()
{
@Override
public void onFailure(Throwable caught)
{
WebPasswordSafe.handleServerFailure(caught);
}
@Override
public void onSuccess(Boolean result)
{
// true => username already taken, else go ahead and save
if (result)
{
MessageBox.alert(textMessages.error(), textMessages.usernameAlreadyExists(), null);
}
else
{
UserService.Util.getInstance().addUser(user, callback);
}
}
};
UserService.Util.getInstance().isUserTaken(user.getUsername(), callbackCheck);
}
else
{
UserService.Util.getInstance().updateUser(user, callback);
}
}
}
private void doCancel()
{
hide();
}
private void loadAvailableGroups()
{
AsyncCallback<List<Group>> callback = new AsyncCallback<List<Group>>()
{
@Override
public void onFailure(Throwable caught)
{
WebPasswordSafe.handleServerFailure(caught);
}
@Override
public void onSuccess(List<Group> result)
{
refreshAvailableGroups(result);
}
};
UserService.Util.getInstance().getGroups(false, callback);
}
private void refreshAvailableGroups(List<Group> groups)
{
for (Group group : groups)
{
if (!user.getGroups().contains(group))
{
fromGroupStore.add(new GroupData(group));
}
}
}
private class GroupData extends BaseModel
{
private static final long serialVersionUID = 1L;
public GroupData(Group group)
{
set(Constants.ID, group.getId());
set(Constants.NAME, Format.htmlEncode(group.getName()));
set(Constants.GROUP, group);
}
@Override
public String toString()
{
return get(Constants.NAME);
}
}
}