/*
 * $Id: EditUserAction.java,v 1.56 2008/02/12 09:33:46 korowa Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: EditUserAction.java,v $
 * Revision 1.56  2008/02/12 09:33:46  korowa
 * Eine Möglichkeit für den Benutzer hinzugefügt die Emailsart auszuwählen(HTML oder Plaintext)
 *
 * Revision 1.55  2007/11/20 10:24:24  marbobo
 * + Falls der Benutzername geändert wird, wird jetzt ein neues Passswort generiert und per Mail zugeschickt
 *
 * Revision 1.54  2007/03/14 10:11:57  jw
 * Action forward for copy admin rights added.
 *
 * Revision 1.53  2006/10/04 03:15:01  marbobo
 * + Vollständige Unterstützung für Templates implementiert
 * + Alles von Virtoweb auf ProCoBa umgestellt
 *
 * Revision 1.52  2006/09/29 21:10:10  marbobo
 * + Sucheoptimiert
 *
 * Revision 1.51  2006/09/17 18:55:36  marbobo
 * + Bugfix bei der Behandlung der dyn. Attributen
 * + Umstellung der Initialisierung bei dyn. Attributen
 *
 * Revision 1.50  2006/09/14 11:31:02  lawern
 * synchronizeForm eingefügt.
 *
 * Revision 1.49  2006/08/31 12:15:38  korowa
 * Dynamische Attribute für Users eingefügt
 *
 * Revision 1.48  2006/05/18 22:50:01  marbobo
 * + Beim Menusprache-Wechsel werden jetzt auch alle 3 Frames aktualisiert
 *
 * Revision 1.47  2006/05/12 08:09:09  korowa
 * +showTree zum Userprofil hinzugefügt. Dieser parameter regelt die Anzeige des Explorerfensters beim VKC-Anmeldung. Lässt sich im Userprofil umschalten.
 *
 * Revision 1.46  2006/02/27 16:16:21  marbobo
 * + Systemsichten hinzugefügt
 * + SysLinks angepasst
 * + Benutzer können falls gewünscht Dokumentqueries anlegen
 *
 * Revision 1.45  2005/08/09 19:00:05  jonyp
 * support for change of publisher
 *
 * Revision 1.44  2005/02/20 16:56:22  marbobo
 * + Beim Speichern der Entities in die Datenbank wird sichergestellt
 *    dass Unicode-Zeichen in Kodierterform (als &#xxxxx;) gespeichert werden
 *
 * Revision 1.43  2005/02/14 14:01:46  bigmac
 * Applikationsweites CSS konfigurierbar gemacht + Refactorings
 *
 * Revision 1.42  2004/12/01 16:42:36  jonyp
 * added support for ldapusers
 *
 * Revision 1.41  2004/11/10 15:02:50  koppy
 * Projektweite Überarbeitung von Error-Logs, Stacktraces,..
 *
 * Revision 1.40  2004/11/09 20:15:39  marbobo
 * + kleine Änderung
 *
 * Revision 1.39  2004/10/07 12:58:32  marbobo
 * + Festlegen der Startkategorie
 *
 * Revision 1.38  2004/09/16 13:10:54  marbobo
 * + Auf VKCRequestProcessor umgestellt
 *
 * Revision 1.37  2004/08/30 20:06:35  marbobo
 * + Verbesserung des Redirectmechanismus
 *
 * Revision 1.36  2004/08/07 18:17:05  marbobo
 * + Bugfix für Zeitangaben und Refactorings
 *
 * Revision 1.35  2004/07/13 22:33:23  marbobo
 * + Sicherheitsüberprüfungen
 *
 * Revision 1.34  2004/06/22 22:34:39  marbobo
 * Quellcode maintenance
 *
 * Revision 1.33  2004/06/21 11:52:06  marbobo
 * + Benutzername nachträglich (falls möglich) editieren
 *
 * Revision 1.32  2004/06/15 20:20:20  marbobo
 * Refactoring
 *
 * Revision 1.31  2004/03/18 01:20:31  marbobo
 * EditUserAction und EditUserForm auf request-scope umgestellt
 *
 * Revision 1.30  2004/03/13 20:46:17  bigmac
 * Weitere Refactorings ...
 *
 * Revision 1.36  2003/08/17 23:48:22  marbobo
 * ertste Version
 *
 */
package vkc.administration.action;

import java.security.MessageDigest;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.struts.Globals;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import vkc.administration.form.EditUserForm;
import vkc.db.entities.VKCDocument;
import vkc.db.entities.VKCDynUserAttribute;
import vkc.db.entities.VKCLanguage;
import vkc.db.entities.VKCUser;
import vkc.db.serializer.VKCDocumentSerializer;
import vkc.db.serializer.VKCProxyUserSerializer;
import vkc.db.serializer.VKCSysParameterSerializer;
import vkc.db.serializer.VKCUserSerializer;
import vkc.exception.DBException;
import vkc.misc.MailUtils;
import vkc.misc.TemplateParser;
import vkc.misc.VKCLogManager;
import vkc.util.DateUtils;
import vkc.util.ServletUtils;
import vkc.util.StringUtils;
import vkc.util.VKCCoder;
import vkc.util.VKCStringUtils;
import vkc.view.WebShare;
import vkc.view.bean.ResourceInfo;
import vkc.view.bean.UserDynAttr;
import vkc.view.bean.UserInfo;


/**
 * Action-Klasse zum Editieren eines Benutzer-Objektes
 *
 * @author marbobo
 * @version $Revision: 1.56 $
 */
public final class EditUserAction extends Action {
	private ActionForward DEFAULT_FORWARD = new ActionForward("/templates/${template.name}/administration/editUser.jsp");
	private ActionForward DEFAULT_FORWARD_ANCHORGROUP = new ActionForward("/templates/${template.name}/administration/editUser.jsp?anchor=groups");
	private ActionForward DEFAULT_FORWARD_ANCHORPROXY = new ActionForward("/templates/${template.name}/administration/editUser.jsp?anchor=proxys");
	private ActionForward DEFAULT_FORWARD_ANCHORDYNAATTRIBUTES = new ActionForward("/templates/${template.name}/administration/editUser.jsp?anchor=dynaattributes");
	private ActionForward INFO_FORWARD = new ActionForward("/templates/${template.name}/common/InfoPage.jsp");

	//~ Methods ----------------------------------------------------------------

	/**
	 * Hier werden die entsprechenden Aktionen eingeleitet (Benutzerdaten
	 * speichern, Benutzer Passwort ändern, usw...)
	 */
	public ActionForward execute(ActionMapping mapping, 
	        					 ActionForm f, 
	        					 HttpServletRequest request, 
	        					 HttpServletResponse response)
		throws Exception {
		EditUserForm form = (EditUserForm) f;
		VKCUser user = form.getUser();
		
		if (!user.hasAdminPrivileges() 
		    && !user.isDedicatedUsersAdmin() 
		    && form.getEditUser() == null 
		    && !user.getUserId().equals(form.getEditUser().getCreatorId())) {
            request.setAttribute(WebShare.INFO_KEY, "vkc.info.access_denied");
            
            return INFO_FORWARD;
        }

		
        // following code is only needed, when external users ar to be handled
		// not a fine code, but it works...
		// if edited user is not external, get infos from form, because they are fully displayable
		// otherwise these contents are not transferred via http (form-element is readonly), 
		// so keep them like the original one... jp of 30.11.2004
		boolean useLdap = Integer.parseInt(WebShare.getSysParameterValue("LDAP", "EnableLdapSupport", "0")) != 0 ? true : false;
		
		if (useLdap) {
		    synchronizeForm(form, request);	
		    VKCUser editUser = form.getEditUser();
		
		    if (editUser.isExternalUser()) {
		        form.setUsername(editUser.getUser());
		        form.setAccountValid(editUser.getAccountValid());
		        form.setFirstname(editUser.getFirstname());
		        form.setLastname(editUser.getLastname());
		        form.setEmail(editUser.getEmail());
		    }
		}
		
		//Aktionen bestimmen
		if (request.getParameter("action.back") != null) {
			return new ActionForward(form.getRedirectPath());
		} else if (request.getParameter("action.change.password") != null) {
			return new ActionForward(form.getChangeUserPasswordPath(), true);
		} else if (request.getParameter("action.change.publisher") != null) {
			return new ActionForward(form.getChangeCreatorPublishershipPath(), true);
        } else if (request.getParameter("action.copy.adminrights") != null) {
            return new ActionForward(form.getCopyAdminRightsPath(), true);
		} else if (request.getParameter("action.save.profile") != null) {
			return handleSaveProfileAction(form, request);
		} else if (request.getParameter("action.proxy.remove.select.changed") != null) {
			return handleChangeSelectedProxyUserAction(form, request);
		} else if (request.getParameter("action.add.groupsToUser") != null) {
			return handleAddGroupsToUserAction(form, request);
		} else if (request.getParameter("action.remove.groupsFromUser") != null) {
			return handleRemoveGroupsFromUserAction(form, request);
		} else if (request.getParameter("action.add.proxyUserToUser") != null) {
			return handleAddProxyUsersToUserAction(form, request);
		} else if (request.getParameter("action.remove.proxyUserFromUser") != null) {
			return handleRemoveProxyUsersFromUserAction(form, request);
		} else if (request.getParameter("action.add.dynaattribute") != null) {
			return handleAddUserDynAttribute(form, request);
		}else if (request.getParameter("action.delete.dynaattribute.x") != null) {
            return handleDeleteDynAttributeAction(form, request);
		}else if (request.getParameter("action.unlock.profile") != null) {
            return unlockProfile(form, request);
        } else {
			return handleInitializeAction(form, request);
		} 
	}

	private ActionForward unlockProfile(EditUserForm form, HttpServletRequest request) throws Exception {
	    form.synchronizeForm(request);
        VKCUserSerializer.setUserPwdMismatchCount(form.getEditUser().getUserId(), new Integer(0));

        return DEFAULT_FORWARD;
    }

    private ActionForward handleAddUserDynAttribute(EditUserForm form, HttpServletRequest request) {
	    form.synchronizeForm(request);
        form.getDynaAttributes().add(new UserDynAttr("", "", UserDynAttr.AUTORIZATION_NO));
        
        return DEFAULT_FORWARD_ANCHORDYNAATTRIBUTES;
	}

	/**
	 * Diese Methode speichert alle Benutzerdaten permanent in die  Datenbank
	 * ab
	 */
	private ActionForward handleSaveProfileAction(EditUserForm form, HttpServletRequest request) throws Exception {
		//Benutzerspezifische Variablen setzen oder initialisieren
		boolean languageChanged = false;
		VKCUser editUser = form.getEditUser();
		UserInfo oldUserInfo = VKCUserSerializer.retrieveUserInfo(form.getUserId());
		String oldFullName = oldUserInfo.getFullName();
		String oldUsername = oldUserInfo.getUsername();

		editUser.setUser(VKCStringUtils.filterUnicodeChars(form.getUsername()));
		editUser.setTitle(VKCStringUtils.filterUnicodeChars(form.getTitle()));
		editUser.setFirstname(VKCStringUtils.filterUnicodeChars(form.getFirstname()));
		editUser.setLastname(VKCStringUtils.filterUnicodeChars(form.getLastname()));
		editUser.setEmail(form.getEmail());
		editUser.setCompany(VKCStringUtils.filterUnicodeChars(form.getCompany()));
		editUser.setDepartment(VKCStringUtils.filterUnicodeChars(form.getDepartment()));
		editUser.setStreet(VKCStringUtils.filterUnicodeChars(form.getStreet()));
		editUser.setZip(form.getZip());
		editUser.setCity(VKCStringUtils.filterUnicodeChars(form.getCity()));
		editUser.setFax(form.getFax());
		editUser.setPhone(form.getPhone());
		editUser.setMobile(form.getMobile());
		editUser.setContactURL(form.getContactURL());
		editUser.setHomepageURL(form.getHomepageURL());
		editUser.setAccountValid(form.isAccountValid());
		editUser.setShowEmail(form.isShowEmail());
		editUser.setShowTree(form.getShowTree());
		editUser.setAllowManageSystemViewType(form.isAllowManageSystemViewType());
		editUser.setSystemViewTypeId(form.getSelectedSystemViewTypeId());
		editUser.setHomeCategoryId(Integer.valueOf(form.getSelectedCategoryId()));
        editUser.setEnableHtmlNotification(form.isEnableHtmlNotification());        

		if (editUser.getAccountValid()) {
			String from = form.getValidFrom();
			String until = form.getValidUntil();

			if (!StringUtils.isEmpty(from)) {
				Date d = DateUtils.parseDate(from);
				editUser.setValidFrom(new Timestamp(d.getTime()));
			} else {
			    editUser.setValidFrom(null);
			}

			if (!StringUtils.isEmpty(until)) {
				Date d = DateUtils.parseDate(until);
				Calendar c = Calendar.getInstance();
				c.setTime(d);
				c.set(Calendar.HOUR_OF_DAY, 23);
				c.set(Calendar.MINUTE, 59);
				c.set(Calendar.SECOND, 59);
				editUser.setValidUntil(new Timestamp(c.getTimeInMillis()));
			} else {
			    editUser.setValidUntil(null);
			}
		} else {
			editUser.setValidFrom(null);
			editUser.setValidUntil(null);
		}

		if (form.getUser().hasAdminPrivileges()) {
			editUser.setAdminPrivileges(form.isAdminPrivileges());
			editUser.setManageOwnGroups(form.isManageOwnGroups());
			editUser.setManageOwnProxies(form.isManageOwnProxies());
			editUser.setManageOwnUsers(form.isManageOwnUsers());
			
			if (editUser.getManageOwnUsers()) {
				editUser.setManageOwnUsersSystemViews(form.isManageOwnUsersSystemViews());
			} else {
				editUser.setManageOwnUsersSystemViews(false);
			}

			editUser.setManageVirtualDocumentQueries(form.isManageVirtualDocumentQueries());

			// session timeout einstellen
			editUser.setSessionTimeout(form.getSelectedSessionTimeout());        	
        
			// quota
			if ("null".equals(form.getSelectedQuota())) {
				editUser.setQuota(null);
			} else {
				editUser.setQuota(new Integer(form.getSelectedQuota()));	
			}
		}

		if (!editUser.getLanguageId().equals(form.getSelectedLanguageId())) {
			languageChanged = true;
		}
		
		for (int i = 0; i < form.getLanguageLabels().size(); i++) {
			VKCLanguage lang = (VKCLanguage)form.getLanguageLabels().get(i);
			
			if (lang.getLanguageId().equals(form.getSelectedLanguageId())) {
				editUser.setLanguageId(lang.getLanguageId());
				editUser.setLanguage(lang);
				break;
			}
		}

		// Dynamische Attribute speichern
		List dynaAttributes = new ArrayList();
	        
        for (int i = 0; i < form.getDynaAttributes().size(); i++) {
            UserDynAttr bean = (UserDynAttr)form.getDynaAttributes().get(i);
            VKCDynUserAttribute dynaAttr = new VKCDynUserAttribute();
            dynaAttr.setName(VKCStringUtils.filterUnicodeChars(bean.getName()));
            dynaAttr.setValue(VKCStringUtils.filterUnicodeChars(bean.getValue()));
            dynaAttr.setAutorization(new Integer(bean.getAutorization()));
            dynaAttr.setUserId(editUser.getUserId());
            dynaAttributes.add(dynaAttr);
        }			

        editUser.setDynaAttributes(dynaAttributes);

		//Benutzergruppen ermitteln und setzen
		editUser.setGroups(form.getGroups());

		//Speichern des Benutzerobjektes einleiten
		try {
			//Benutzerobjekt in die Datenbank abspeicher
			editUser.setLastChangerId(form.getUser().getUserId());
			editUser.setLastChanged(new Timestamp(System.currentTimeMillis()));
            VKCUserSerializer.saveUser(editUser);

			if (form.getUser().hasAdminPrivileges()) {
				// Speichern der ProxyUsers
				VKCProxyUserSerializer.saveProxyUsers(form.getProxyUsers(), editUser.getUserId());
			}

			//Falls Vor- oder Nachname des Benutzer sich ändert werden alle Benutzerdokumente
			//im Suchindex aktualisiert
			if (!editUser.getFullName().equals(oldFullName)) {
				List userDocuments = new ArrayList(VKCDocumentSerializer.getDocuments(editUser));

				for (int i = 0; i < userDocuments.size(); i++) {
					VKCDocument document = (VKCDocument) userDocuments.get(i);
                    VKCDocumentSerializer.saveDocument(document, true, false);
				}
			}

            //Falls Username des Benutzer sich ändert wird der Passwort geändert
            if (!editUser.getUser().equals(oldUsername)) {
                String username = editUser.getUser();
                //zufälliges MD5-Passwort erzeugen
                String password = RandomStringUtils.randomAlphanumeric(8);
                byte[] md5Bytes = (username + password).getBytes("ISO-8859-1");

                MessageDigest digest = MessageDigest.getInstance("MD5");
                digest.reset();
                digest.update(md5Bytes);
                byte[] fingerPrint = digest.digest();
                fingerPrint = VKCCoder.base64Encode(fingerPrint);
                String md5Password = new String(fingerPrint, "ISO-8859-1");
                editUser.setPassword(md5Password);
                editUser.setPasswordChanged(false);
                editUser.setPasswordChangedTs(new Timestamp(System.currentTimeMillis()));
                editUser.setLastChanged(new Timestamp(System.currentTimeMillis()));
                editUser.setLastChangerId(form.getUser().getUserId());
                
                try {
                    // die Zugangsdaten zuschicken
                    String senderAddr  = VKCSysParameterSerializer.retrieveValue("MAIL", "AdminEmail", "");
                    String smtpServer  = VKCSysParameterSerializer.retrieveValue("MAIL", "MailServer", "");
                    String smtpUsername  = VKCSysParameterSerializer.retrieveValue("MAIL", "MailUsername", "");
                    String smtpPassword  = VKCSysParameterSerializer.retrieveValue("MAIL", "MailPassword", "");
                    String vkc_rootURL = WebShare.getRootURL() + WebShare.getContextPath();
                    String subject     = WebShare.resources.getMessage(editUser.getLanguage().getLocale(), "vkc.changepassword");
                    String recepient   = VKCStringUtils.decodeXmlEntities(editUser.getEmail());

                    TemplateParser asciiTemplate = TemplateParser.getTemplateParser();
                    TemplateParser htmlTemplate = TemplateParser.getTemplateParser();

                    HashMap context = new HashMap();
                    context.put("adminEmail", senderAddr);
                    context.put("homepage", vkc_rootURL);
                    context.put("username", VKCStringUtils.filterUnicodeChars(editUser.getUser()));
                    context.put("fullname", VKCStringUtils.filterUnicodeChars(editUser.getFirstname() + " " + editUser.getLastname()));
                    context.put("password", password);
                    context.put("resources", new ResourceInfo(WebShare.resources, editUser.getLanguage().getLocale()));
                    context.put("vkcstringutils", new VKCStringUtils());
                    context.put("template", editUser.getTemplate().getName());
                    
                    asciiTemplate.setContextData(context);
                    htmlTemplate.setContextData(context);
                    String asciiPath = "templates/${template.name}/velocitytemplates/mail/changepassword_notification.plain";
                    String htmlPath = "templates/${template.name}/velocitytemplates/mail/changepassword_notification.html";
                    
                    String asciiText = asciiTemplate.createString(ServletUtils.replacePathVars(asciiPath, editUser));
                    String htmlText = htmlTemplate.createString(ServletUtils.replacePathVars(htmlPath, editUser));
                    
                    MailUtils m = new MailUtils(editUser);
                    if(editUser.isEnableHtmlNotification())m.sendSMTPMailWithVKCLogo(senderAddr, recepient, subject, asciiText, htmlText, null, null, smtpServer, smtpUsername, smtpPassword);
                    else m.sendSMTPMail(senderAddr, recepient, subject, asciiText, null, null, null, smtpServer, smtpUsername, smtpPassword);
                } catch (Exception e) {
                    ActionErrors errors = new ActionErrors();
                    errors.add("mailmessage.failure", new ActionError("vkc.administration.newuser.mailfailure"));
                    request.setAttribute(Globals.ERROR_KEY, errors);
                    VKCLogManager.errorLog(this, "1", " - email sending failes: " + e.getMessage(), e);
                }

                VKCUserSerializer.saveUser(editUser);
            }

			//eingeloggter Benutzer ist der editierte Benutzer -> Daten abgleichen
			if (editUser.getUserId().equals(form.getUser().getUserId())) {
				if (languageChanged) {
					form.setLanguageChanged(true);
				}
				
				request.getSession().setAttribute(WebShare.USER_KEY, editUser);
				request.getSession().setAttribute(WebShare.LOCALE_KEY, editUser.getLanguage().getLocale());
			}

			return handleInitializeAction(form, request);
		} catch (DBException e) {
			VKCLogManager.errorLog(this, "", e.getMessage(), e);

			return INFO_FORWARD;
		}
	}

	private ActionForward handleInitializeAction(EditUserForm form, HttpServletRequest request) {
		synchronizeForm(form, request);

		return DEFAULT_FORWARD;
	}
	
	private ActionForward handleChangeSelectedProxyUserAction(EditUserForm form, HttpServletRequest request) {
		Integer id = form.getCurrentProxyUserId();
		form.setDynaValue("proxyDescription_" + id.toString(), form.getProxyDescription());
		form.setDynaValue("proxyValidFrom_" + id.toString(), form.getProxyValidFrom());
		form.setDynaValue("proxyValidUntil_" + id.toString(), form.getProxyValidUntil());
		form.setCurrentProxyUserId(form.getSelectedRemoveProxyUserIds()[0]);
		form.setProxyDescription((String)form.getDynaValue("proxyDescription_" + form.getCurrentProxyUserId().toString()));
		form.setProxyValidFrom((String)form.getDynaValue("proxyValidFrom_" + form.getCurrentProxyUserId().toString()));
		form.setProxyValidUntil((String)form.getDynaValue("proxyValidUntil_" + form.getCurrentProxyUserId().toString()));
		synchronizeForm(form, request);

		return DEFAULT_FORWARD_ANCHORPROXY;
	}

	private ActionForward handleAddGroupsToUserAction(EditUserForm form, HttpServletRequest request) throws Exception {
		Integer[] addIds = form.getSelectedAddGroupIds();
		List addGroupIds = new ArrayList(Arrays.asList(form.getAddGroupIds()));
	
		for (int i = 0; i < addIds.length; i++) {
			if (!addGroupIds.contains(addIds[i])) {
				addGroupIds.add(addIds[i]);
			}
		}
	
		form.setAddGroupIds((Integer[])addGroupIds.toArray(new Integer[0]));
	
		synchronizeForm(form, request);

		return DEFAULT_FORWARD_ANCHORGROUP;
	}

	private ActionForward handleRemoveGroupsFromUserAction(EditUserForm form, HttpServletRequest request) throws Exception {
		Integer[] removeIds = form.getSelectedRemoveGroupIds();
		List addGroupIds = new ArrayList(Arrays.asList(form.getAddGroupIds()));

		for (int i = 0; i < removeIds.length; i++) {
			if (addGroupIds.contains(removeIds[i])) {
				addGroupIds.remove(removeIds[i]);
			}
		}

		form.setAddGroupIds((Integer[])addGroupIds.toArray(new Integer[0]));

		synchronizeForm(form, request);

		return DEFAULT_FORWARD_ANCHORGROUP;
	}

	private ActionForward handleAddProxyUsersToUserAction(EditUserForm form, HttpServletRequest request) throws Exception {
		Integer[] addIds = form.getSelectedAddProxyUserIds();
		List addProxyUserIds = new ArrayList(Arrays.asList(form.getAddProxyUserIds()));
	
		for (int i = 0; i < addIds.length; i++) {
			if (!addProxyUserIds.contains(addIds[i])) {
				addProxyUserIds.add(addIds[i]);
			}
		}
	
		form.setAddProxyUserIds((Integer[])addProxyUserIds.toArray(new Integer[0]));
	
		synchronizeForm(form, request);

		return DEFAULT_FORWARD_ANCHORPROXY;
	}

	private ActionForward handleRemoveProxyUsersFromUserAction(EditUserForm form, HttpServletRequest request) throws Exception {
		Integer[] removeIds = form.getSelectedRemoveProxyUserIds();
		List addProxyUserIds = new ArrayList(Arrays.asList(form.getAddProxyUserIds()));
		
		for (int i = 0; i < removeIds.length; i++) {
			if (addProxyUserIds.contains(removeIds[i])) {
				addProxyUserIds.remove(removeIds[i]);
			}
		}
		
		form.setAddProxyUserIds((Integer[])addProxyUserIds.toArray(new Integer[0]));
		
		synchronizeForm(form, request);

		return DEFAULT_FORWARD_ANCHORPROXY;
	}

	private ActionForward handleDeleteDynAttributeAction(EditUserForm form, HttpServletRequest request) {
		form.synchronizeForm(request);

		int index = form.getSelectedIndex().intValue();

        if (index >= 0 && index < form.getDynaAttributes().size()) {
            form.getDynaAttributes().remove(index);            
        }

		return DEFAULT_FORWARD_ANCHORDYNAATTRIBUTES;
    }

	private void synchronizeForm(EditUserForm form, HttpServletRequest request) {
		form.synchronizeForm(request);
	}
}