/*
* eXist Open Source Native XML Database
* Copyright (C) 2001-2012 The eXist Project
* http://exist-db.org
*
* 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 2
* 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 copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* $Id$
*/
package org.exist.client.security;
import java.util.*;
import javax.swing.JOptionPane;
import org.exist.client.DialogCompleteWithResponse;
import org.exist.client.DialogWithResponse;
import org.exist.security.AXSchemaType;
import org.exist.security.Account;
import org.exist.security.EXistSchemaType;
import org.exist.security.PermissionDeniedException;
import org.exist.xmldb.EXistUserManagementService;
import org.exist.xmldb.UserManagementService;
import org.xmldb.api.base.XMLDBException;
/**
*
* @author Adam Retter <adam.retter@googlemail.com>
*/
public class EditUserDialog extends UserDialog implements DialogWithResponse<String> {
private static final long serialVersionUID = 9097018734007436201L;
private final static String HIDDEN_PASSWORD_CONST = "password";
private final Account account;
private final List<DialogCompleteWithResponse<String>> dialogCompleteWithResponseCallbacks = new ArrayList<DialogCompleteWithResponse<String>>();
public EditUserDialog(final UserManagementService userManagementService, final Account account) {
super(userManagementService);
this.account = account;
setFormPropertiesFromAccount();
}
private void setFormPropertiesFromAccount() {
setTitle("Edit User: " + getAccount().getName());
btnCreate.setText("Save");
txtUsername.setText(getAccount().getName());
txtUsername.setEnabled(false);
txtFullName.setText(getAccount().getMetadataValue(AXSchemaType.FULLNAME));
txtDescription.setText(getAccount().getMetadataValue(EXistSchemaType.DESCRIPTION));
txtPassword.setText(HIDDEN_PASSWORD_CONST);
txtPasswordConfirm.setText(HIDDEN_PASSWORD_CONST);
cbDisabled.setSelected(!getAccount().isEnabled());
spnUmask.setValue(UmaskSpinnerModel.intToOctalUmask(getAccount().getUserMask()));
cbPersonalGroup.setVisible(false);
boolean first = true;
for(final String group : getAccount().getGroups()) {
getMemberOfGroupsListModel().add(group);
getAvailableGroupsListModel().removeElement(group);
if(first) {
setPrimaryGroup(group);
getMemberOfGroupsListCellRenderer().setCellOfInterest(getPrimaryGroup());
first = false;
}
}
}
@Override
protected void createUser() {
if(getMemberOfGroupsListModel().getSize() == 0) {
JOptionPane.showMessageDialog(this, "A user must be a member of at least one user group", "Edit User Error", JOptionPane.ERROR_MESSAGE);
return;
}
//dont create a user, update instead!
updateUser();
//return updated password
//only fire if password changed
if(isPasswordChanged()) {
for(final DialogCompleteWithResponse<String> callback : getDialogCompleteWithResponseCallbacks()) {
callback.complete(txtPassword.getText());
}
}
}
private void updateUser() {
try {
final Optional<String> newPassword = setAccountFromFormProperties();
/**
* We update the account in three stages:
*
* 1) General account properties
* 2) Group memebrship
* 3) Optionally set changed password.
*
* The password is always changed last if needed,
* as it means the admin client must reconnect
* if we are changing the logged in users password.
*
* The reconnection is performed by the registered
* DialogCompleteWithResponse handler
*/
//1) Update general account properties
getUserManagementService().updateAccount(getAccount());
//2) Update group membership (has to be modified separately from (1))
modifyAccountGroupMembership();
//3) Finally, optionally change the password
if(newPassword.isPresent()) {
final Account acct = getUserManagementService().getAccount(getAccount().getName());
acct.setPassword(newPassword.get());
getUserManagementService().updateAccount(acct);
}
} catch(final PermissionDeniedException pde) {
JOptionPane.showMessageDialog(this, "Could not update user '" + txtUsername.getText() + "': " + pde.getMessage(), "Edit User Error", JOptionPane.ERROR_MESSAGE);
} catch(final XMLDBException xmldbe) {
JOptionPane.showMessageDialog(this, "Could not update user '" + txtUsername.getText() + "': " + xmldbe.getMessage(), "Edit User Error", JOptionPane.ERROR_MESSAGE);
}
}
private boolean isPasswordChanged() {
final String password = new String(txtPassword.getPassword());
return !password.equals(HIDDEN_PASSWORD_CONST);
}
private void modifyAccountGroupMembership() throws XMLDBException {
//get the current groups of the user
final Set<String> currentGroups = new HashSet<String>(Arrays.asList(getAccount().getGroups()));
//get the new groups of the user to be set
final Set<String> memberOfGroups = new HashSet<String>();
for(int i = 0; i < getMemberOfGroupsListModel().getSize(); i++) {
memberOfGroups.add((String)getMemberOfGroupsListModel().getElementAt(i));
}
//groups to remove
for(final String currentGroup : currentGroups) {
if(!memberOfGroups.contains(currentGroup)) {
getUserManagementService().removeGroupMember(currentGroup, getAccount().getName());
}
}
//groups to add
for(final String memberOfGroup : memberOfGroups) {
if(!currentGroups.contains(memberOfGroup)) {
getUserManagementService().addAccountToGroup(getAccount().getName(), memberOfGroup);
}
}
//set the primary group
((EXistUserManagementService)getUserManagementService()).setUserPrimaryGroup(getAccount().getName(), getPrimaryGroup());
}
/**
* Updates the account with all of the fields from the form
* except the password.
*
* If the password on the form has been changed then it is returned
* as the result of this function
*/
private Optional<String> setAccountFromFormProperties() throws PermissionDeniedException {
getAccount().setMetadataValue(AXSchemaType.FULLNAME, txtFullName.getText());
getAccount().setMetadataValue(EXistSchemaType.DESCRIPTION, txtDescription.getText());
getAccount().setEnabled(!cbDisabled.isSelected());
getAccount().setUserMask(UmaskSpinnerModel.octalUmaskToInt((String)spnUmask.getValue()));
if(isPasswordChanged()) {
final String password = new String(txtPassword.getPassword());
return Optional.of(password);
} else {
return Optional.empty();
}
}
protected Account getAccount() {
return account;
}
private List<DialogCompleteWithResponse<String>> getDialogCompleteWithResponseCallbacks() {
return dialogCompleteWithResponseCallbacks;
}
@Override
public void addDialogCompleteWithResponseCallback(final DialogCompleteWithResponse<String> dialogCompleteWithResponseCallback) {
getDialogCompleteWithResponseCallbacks().add(dialogCompleteWithResponseCallback);
}
}