/* * Copyright (C) 2005 Alfresco, Inc. * * Licensed under the Alfresco Network License. You may obtain a * copy of the License at * * http://www.alfrescosoftware.com/legal/ * * Please view the license relevant to your network subscription. * * BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING, * READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"), * YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE * ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO * THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE * AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE * TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE" * BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY * HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE * SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE * TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU * CHECK THE "I UNDERSTAND AND ACCEPT" BOX. */ package org.alfresco.web.bean; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import javax.faces.application.FacesMessage; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.event.ActionEvent; import javax.faces.model.DataModel; import javax.faces.model.ListDataModel; import javax.faces.model.SelectItem; import javax.faces.validator.ValidatorException; import javax.transaction.UserTransaction; import org.alfresco.model.ContentModel; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.AuthorityType; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.web.app.Application; import org.alfresco.web.app.context.IContextListener; import org.alfresco.web.app.context.UIContextService; import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.ui.common.SortableSelectItem; import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.component.IBreadcrumbHandler; import org.alfresco.web.ui.common.component.UIActionLink; import org.alfresco.web.ui.common.component.UIBreadcrumb; import org.alfresco.web.ui.common.component.UIGenericPicker; import org.alfresco.web.ui.common.component.UIModeList; import org.alfresco.web.ui.common.component.data.UIRichList; import org.apache.log4j.Logger; /** * Backing Bean for the Groups Management pages. * * @author Kevin Roast */ public class GroupsBean implements IContextListener { private static final String FILTER_CHILDREN = "children"; private static final String FILTER_ALL = "all"; private static final String DEFAULT_OUTCOME = "finish"; private static final String MSG_GROUPS = "root_groups"; private static Logger logger = Logger.getLogger(GroupsBean.class); /** The NodeService to be used by the bean */ private NodeService nodeService; /** The AuthorityService to be used by the bean */ private AuthorityService authService; /** personService bean reference */ private PersonService personService; /** Component references */ private UIRichList groupsRichList; private UIRichList usersRichList; /** datamodel for table of users added to group */ private DataModel usersDataModel = null; /** Currently visible Group Authority */ private String group = null; private String groupName = null; /** Action group authority */ private String actionGroup = null; private String actionGroupName = null; private int actionGroupItems = 0; /** selected users to be added to a group */ private List usersForGroup = null; /** Dialog properties */ private String name = null; /** RichList view mode */ private String viewMode = "icons"; /** List filter mode */ private String filterMode = FILTER_CHILDREN; /** Groups path breadcrumb location */ private List location = null; // ------------------------------------------------------------------------------ // Construction /** * Default Constructor */ public GroupsBean() { UIContextService.getInstance(FacesContext.getCurrentInstance()).registerBean(this); } // ------------------------------------------------------------------------------ // Bean property getters and setters /** * @param nodeService The NodeService to set. */ public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; } /** * @param authService The AuthorityService to set. */ public void setAuthorityService(AuthorityService authService) { this.authService = authService; } /** * @param permissionService The PermissionService to set. */ public void setPersonService(PersonService personService) { this.personService = personService; } /** * @return Returns the groups RichList to set. */ public UIRichList getGroupsRichList() { return this.groupsRichList; } /** * @param list The RichList to set. */ public void setGroupsRichList(UIRichList list) { this.groupsRichList = list; } /** * @return Returns the users RichList. */ public UIRichList getUsersRichList() { return this.usersRichList; } /** * @param usersRichList The RichList to set. */ public void setUsersRichList(UIRichList usersRichList) { this.usersRichList = usersRichList; } /** * @return Returns the usersDataModel. */ public DataModel getUsersDataModel() { if (this.usersDataModel == null) { this.usersDataModel = new ListDataModel(); } this.usersDataModel.setWrappedData(this.usersForGroup); return this.usersDataModel; } /** * @param usersDataModel The usersDataModel to set. */ public void setUsersDataModel(DataModel usersDataModel) { this.usersDataModel = usersDataModel; } /** * @return Returns the name. */ public String getName() { return this.name; } /** * @param name The name to set. */ public void setName(String name) { this.name = name; } /** * @return Returns the viewMode. */ public String getViewMode() { return this.viewMode; } /** * @param viewMode The viewMode to set. */ public void setViewMode(String viewMode) { this.viewMode = viewMode; } /** * @return Returns the filterMode. */ public String getFilterMode() { return this.filterMode; } /** * @param filterMode The filterMode to set. */ public void setFilterMode(String filterMode) { this.filterMode = filterMode; // clear datalist cache ready to change results based on filter setting contextUpdated(); } /** * @return Returns the Group being used for the current action screen. */ public String getActionGroup() { return this.actionGroup; } /** * @param actionSpace Set the Group to be used for the current action screen. */ public void setActionGroup(String group) { this.actionGroup = group; if (group != null) { // calculate action group metadata setActionGroupName(this.authService.getShortName(group)); int count = this.authService.getContainedAuthorities(AuthorityType.GROUP, group, false).size(); count += this.authService.getContainedAuthorities(AuthorityType.USER, group, false).size(); setActionGroupItems(count); } else { setActionGroupName(null); setActionGroupItems(0); } // clear value used by Create Group form this.name = null; // clear list for Add Users to Group screen this.usersForGroup = new ArrayList(); } /** * @return Returns the actionGroupName. */ public String getActionGroupName() { return this.actionGroupName; } /** * @param actionGroupName The actionGroupName to set. */ public void setActionGroupName(String actionGroupName) { this.actionGroupName = actionGroupName; } /** * @return Returns the action Group Items count. */ public int getActionGroupItems() { return this.actionGroupItems; } /** * @param actionGroupItems The action Group Items count to set. */ public void setActionGroupItems(int actionGroupItems) { this.actionGroupItems = actionGroupItems; } /** * @return The currently displayed group or null if at the root. */ public String getCurrentGroup() { return this.group; } /** * Set the current Group Authority. *

* Setting this value causes the UI to update and display the specified node as current. * * @param group The current group authority. */ public void setCurrentGroup(String group, String groupName) { if (logger.isDebugEnabled()) logger.debug("Setting current group: " + group); // set the current Group Authority for our UI context operations this.group = group; this.groupName = groupName; // inform that the UI needs updating after this change contextUpdated(); } /** * @return Returns the groupName. */ public String getGroupName() { return this.groupName; } /** * @param groupName The groupName to set. */ public void setGroupName(String groupName) { this.groupName = groupName; } /** * @return Breadcrumb location list */ public List getLocation() { if (this.location == null) { List loc = new ArrayList(8); loc.add(new GroupBreadcrumbHandler(null, Application.getMessage(FacesContext.getCurrentInstance(), MSG_GROUPS))); this.location = loc; } return this.location; } /** * @param location Breadcrumb location list */ public void setLocation(List location) { this.location = location; } /** * @return The list of group objects to display. Returns the list of root groups or the * list of sub-groups for the current group if set. */ public List getGroups() { List groups; UserTransaction tx = null; try { FacesContext context = FacesContext.getCurrentInstance(); tx = Repository.getUserTransaction(context); tx.begin(); Set authorities; boolean immediate = (this.filterMode.equals(FILTER_CHILDREN)); if (this.group == null) { // root groups if (immediate == true) { authorities = this.authService.getAllRootAuthorities(AuthorityType.GROUP); } else { authorities = this.authService.getAllAuthorities(AuthorityType.GROUP); } } else { // sub-group of an existing group authorities = this.authService.getContainedAuthorities(AuthorityType.GROUP, group, immediate); } groups = new ArrayList(authorities.size()); for (String authority : authorities) { Map authMap = new HashMap(3, 1.0f); String name = this.authService.getShortName(authority); authMap.put("name", name); authMap.put("id", authority); groups.add(authMap); } // commit the transaction tx.commit(); } catch (Throwable err) { Utils.addErrorMessage(MessageFormat.format(Application.getMessage( FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err); groups = Collections.emptyList(); try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} } return groups; } /** * @return The list of user objects to display. Returns the list of user for the current group. */ public List getUsers() { List users; UserTransaction tx = null; try { FacesContext context = FacesContext.getCurrentInstance(); tx = Repository.getUserTransaction(context); tx.begin(); Set authorities; if (this.group == null) { authorities = Collections.emptySet(); } else { // users of an existing group boolean immediate = (this.filterMode.equals(FILTER_CHILDREN)); authorities = this.authService.getContainedAuthorities(AuthorityType.USER, group, immediate); } users = new ArrayList(authorities.size()); for (String authority : authorities) { Map authMap = new HashMap(3, 1.0f); String userName = this.authService.getShortName(authority); authMap.put("userName", userName); authMap.put("id", authority); // get Person details for this Authority NodeRef ref = this.personService.getPerson(authority); String firstName = (String)this.nodeService.getProperty(ref, ContentModel.PROP_FIRSTNAME); String lastName = (String)this.nodeService.getProperty(ref, ContentModel.PROP_LASTNAME); // build a sensible label for display StringBuilder label = new StringBuilder(48); label.append(firstName) .append(' ') .append(lastName); authMap.put("name", label.toString()); users.add(authMap); } // commit the transaction tx.commit(); } catch (Throwable err) { Utils.addErrorMessage(MessageFormat.format(Application.getMessage( FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err); users = Collections.emptyList(); try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} } return users; } /** * Validate password field data is acceptable */ public void validateGroupName(FacesContext context, UIComponent component, Object value) throws ValidatorException { String name = (String)value; if (name.indexOf('\'') != -1 || name.indexOf('"') != -1 || name.indexOf('\\') != -1) { String err = MessageFormat.format(Application.getMessage(context, "groups_err_group_name"), new Object[]{"', \", \\"}); throw new ValidatorException(new FacesMessage(err)); } } /** * Query callback method executed by the Generic Picker component. * This method is part of the contract to the Generic Picker, it is up to the backing bean * to execute whatever query is appropriate and return the results. * * @param filterIndex Index of the filter drop-down selection * @param contains Text from the contains textbox * * @return An array of SelectItem objects containing the results to display in the picker. */ public SelectItem[] pickerCallback(int filterIndex, String contains) { FacesContext context = FacesContext.getCurrentInstance(); SelectItem[] items; UserTransaction tx = null; try { tx = Repository.getUserTransaction(context); tx.begin(); // build xpath to match available User/Person objects ServiceRegistry services = Repository.getServiceRegistry(context); NodeRef peopleRef = personService.getPeopleContainer(); String xpath = "*[like(@" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + "firstName, '%" + contains + "%', false)" + " or " + "like(@" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + "lastName, '%" + contains + "%', false)]"; List nodes = services.getSearchService().selectNodes( peopleRef, xpath, null, services.getNamespaceService(), false); items = new SelectItem[nodes.size()]; for (int index=0; index params = link.getParameterMap(); String group = params.get("id"); if (group != null && group.length() != 0) { if (logger.isDebugEnabled()) logger.debug("Setup for action, setting current Group to: " + group); // prepare a node for the action context setActionGroup(group); // clear datalist cache ready from return from action dialog contextUpdated(); } } /** * Clear the Group action context - e.g. ready for a Create Root Group operation */ public void clearGroupAction(ActionEvent event) { setActionGroup(null); // clear datalist cache ready from return from action dialog contextUpdated(); } /** * Action called when a Group folder is clicked. * Navigate into the Group and show child Groups and child Users. */ public void clickGroup(ActionEvent event) { UIActionLink link = (UIActionLink)event.getComponent(); Map params = link.getParameterMap(); String group = params.get("id"); if (group != null && group.length() != 0) { // refresh UI based on node selection updateUILocation(group); } } /** * Action handler called on Create Group finish button click. */ public String finishCreate() { String outcome = DEFAULT_OUTCOME; UserTransaction tx = null; try { FacesContext context = FacesContext.getCurrentInstance(); tx = Repository.getUserTransaction(context); tx.begin(); // create new Group using Authentication Service this.authService.createAuthority(AuthorityType.GROUP, getActionGroup(), this.name); // commit the transaction tx.commit(); } catch (Throwable err) { // rollback the transaction try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} Utils.addErrorMessage(MessageFormat.format(Application.getMessage( FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err); outcome = null; } return outcome; } /** * Action handler called on Delete Group finish button click. */ public String finishDelete() { String outcome = DEFAULT_OUTCOME; UserTransaction tx = null; try { FacesContext context = FacesContext.getCurrentInstance(); tx = Repository.getUserTransaction(context); tx.begin(); // delete group using the Authentication Service this.authService.deleteAuthority(getActionGroup()); // commit the transaction tx.commit(); // remove this node from the breadcrumb if required List location = getLocation(); GroupBreadcrumbHandler handler = (GroupBreadcrumbHandler)location.get(location.size() - 1); // see if the current breadcrumb location is our Group if ( getActionGroup().equals(handler.Group) ) { location.remove(location.size() - 1); // now work out which Group to set the list to refresh against if (location.size() != 0) { handler = (GroupBreadcrumbHandler)location.get(location.size() - 1); this.setCurrentGroup(handler.Group, handler.Label); } } // clear action context setActionGroup(null); } catch (Throwable err) { // rollback the transaction try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} Utils.addErrorMessage(MessageFormat.format(Application.getMessage( FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err); outcome = null; } return outcome; } /** * Remove specified user from the current group */ public void removeUser(ActionEvent event) { UIActionLink link = (UIActionLink)event.getComponent(); Map params = link.getParameterMap(); String authority = params.get("id"); if (authority != null && authority.length() != 0) { try { this.authService.removeAuthority(this.group, authority); // refresh UI after change contextUpdated(); } catch (Throwable err) { Utils.addErrorMessage(MessageFormat.format(Application.getMessage( FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err); } } } /** * Action handler called when Finish button clicked on Add User to Group page */ public String finishAddUser() { String outcome = DEFAULT_OUTCOME; UserTransaction tx = null; try { FacesContext context = FacesContext.getCurrentInstance(); tx = Repository.getUserTransaction(context); tx.begin(); // add each selected user to the current group in turn for (UserAuthorityDetails wrapper : this.usersForGroup) { this.authService.addAuthority(getActionGroup(), wrapper.authority); } // commit the transaction tx.commit(); } catch (Throwable err) { // rollback the transaction try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} Utils.addErrorMessage(MessageFormat.format(Application.getMessage( FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err); outcome = null; } return outcome; } /** * Add the selected User to the list for adding to a Group */ public void addSelectedUsers(ActionEvent event) { UIGenericPicker picker = (UIGenericPicker)event.getComponent().findComponent("picker"); String[] results = picker.getSelectedResults(); if (results != null) { for (int i=0; i