001/*
002 * (C) Copyright 2010 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 * Contributors:
016 *     Nuxeo - initial API and implementation
017 */
018
019package org.nuxeo.ecm.webapp.security;
020
021import static org.jboss.seam.ScopeType.CONVERSATION;
022import static org.jboss.seam.annotations.Install.FRAMEWORK;
023import static org.nuxeo.ecm.platform.ui.web.api.WebActions.CURRENT_TAB_CHANGED_EVENT;
024import static org.nuxeo.ecm.platform.ui.web.api.WebActions.CURRENT_TAB_SELECTED_EVENT;
025
026import java.io.Serializable;
027
028import javax.faces.application.FacesMessage;
029import javax.faces.component.EditableValueHolder;
030import javax.faces.component.UIComponent;
031import javax.faces.context.FacesContext;
032
033import org.apache.commons.lang3.StringUtils;
034import org.apache.commons.logging.Log;
035import org.apache.commons.logging.LogFactory;
036import org.jboss.seam.annotations.Install;
037import org.jboss.seam.annotations.Name;
038import org.jboss.seam.annotations.Observer;
039import org.jboss.seam.annotations.Scope;
040import org.jboss.seam.core.Events;
041import org.jboss.seam.international.StatusMessage;
042import org.nuxeo.ecm.core.api.DocumentModel;
043import org.nuxeo.ecm.core.api.NuxeoPrincipal;
044import org.nuxeo.ecm.directory.BaseSession;
045import org.nuxeo.ecm.platform.ui.web.util.ComponentUtils;
046import org.nuxeo.ecm.platform.usermanager.exceptions.GroupAlreadyExistsException;
047
048/**
049 * /** Handles users management related web actions.
050 *
051 * @author <a href="mailto:troger@nuxeo.com">Thomas Roger</a>
052 * @since 5.4.2
053 */
054@Name("groupManagementActions")
055@Scope(CONVERSATION)
056@Install(precedence = FRAMEWORK)
057public class GroupManagementActions extends AbstractUserGroupManagement implements Serializable {
058
059    private static final long serialVersionUID = 1L;
060
061    private static final Log log = LogFactory.getLog(GroupManagementActions.class);
062
063    public static final String GROUPS_TAB = USER_CENTER_CATEGORY + ":" + USERS_GROUPS_HOME + ":" + "GroupsHome";
064
065    public static final String GROUPS_LISTING_CHANGED = "groupsListingChanged";
066
067    protected Boolean canEditGroups;
068
069    protected DocumentModel selectedGroup;
070
071    protected DocumentModel newGroup;
072
073    protected boolean createAnotherGroup = false;
074
075    @Override
076    protected String computeListingMode() {
077        return userManager.getGroupListingMode();
078    }
079
080    public DocumentModel getSelectedGroup() {
081        shouldResetStateOnTabChange = true;
082        return selectedGroup;
083    }
084
085    /**
086     * @since 6.0
087     */
088    public String getSelectedGroupName() {
089        return selectedGroup.getId();
090    }
091
092    /**
093     * @since 6.0
094     */
095    public void setSelectedGroupName(String groupName) {
096        setSelectedGroup(groupName);
097    }
098
099    /**
100     * @since 6.0
101     */
102    public void setShowGroup(String showGroup) {
103        showUserOrGroup = Boolean.valueOf(showGroup);
104    }
105
106    public void setSelectedGroup(String groupName) {
107        selectedGroup = refreshGroup(groupName);
108    }
109
110    // refresh to get references
111    protected DocumentModel refreshGroup(String groupName) {
112        return userManager.getGroupModel(groupName);
113    }
114
115    public DocumentModel getNewGroup() {
116        if (newGroup == null) {
117            newGroup = userManager.getBareGroupModel();
118        }
119        return newGroup;
120    }
121
122    public void clearSearch() {
123        searchString = null;
124        fireSeamEvent(GROUPS_LISTING_CHANGED);
125    }
126
127    public void createGroup() {
128        try {
129            selectedGroup = userManager.createGroup(newGroup);
130            newGroup = null;
131            facesMessages.add(StatusMessage.Severity.INFO,
132                    resourcesAccessor.getMessages().get("info.groupManager.groupCreated"));
133            if (createAnotherGroup ) {
134                showCreateForm = true;
135            } else {
136                showCreateForm = false;
137                showUserOrGroup = true;
138                detailsMode = null;
139            }
140            fireSeamEvent(GROUPS_LISTING_CHANGED);
141        } catch (GroupAlreadyExistsException e) {
142            String message = resourcesAccessor.getMessages().get("error.groupManager.groupAlreadyExists");
143            facesMessages.addToControl("groupName", StatusMessage.Severity.ERROR, message);
144        }
145    }
146
147    public void updateGroup() {
148        userManager.updateGroup(selectedGroup);
149        detailsMode = DETAILS_VIEW_MODE;
150        fireSeamEvent(GROUPS_LISTING_CHANGED);
151    }
152
153    public void deleteGroup() {
154        userManager.deleteGroup(selectedGroup);
155        selectedGroup = null;
156        showUserOrGroup = false;
157        fireSeamEvent(GROUPS_LISTING_CHANGED);
158    }
159
160    public boolean getAllowCreateGroup() {
161        return getCanEditGroups();
162    }
163
164    protected boolean getCanEditGroups() {
165        if (canEditGroups == null) {
166            canEditGroups = false;
167            if (!userManager.areGroupsReadOnly() && currentUser instanceof NuxeoPrincipal) {
168                if (webActions.checkFilter(USERS_GROUPS_MANAGEMENT_ACCESS_FILTER)) {
169                    canEditGroups = true;
170                }
171            }
172        }
173        return canEditGroups;
174    }
175
176    public boolean getAllowDeleteGroup() {
177        if (getAllAdminGroups().contains(selectedGroup.getId())) {
178            return currentUser.isAdministrator();
179        }
180
181        return getCanEditGroups() && !BaseSession.isReadOnlyEntry(selectedGroup);
182    }
183
184    public boolean getAllowEditGroup() {
185        // Changing administrator group is only given to administrators (not
186        // powerusers)
187        // NXP-10584
188        if (getAllAdminGroups().contains(selectedGroup.getId())) {
189            return currentUser.isAdministrator();
190        }
191
192        return getCanEditGroups() && !BaseSession.isReadOnlyEntry(selectedGroup);
193    }
194
195    public void validateGroupName(FacesContext context, UIComponent component, Object value) {
196        if (!(value instanceof String) || !StringUtils.containsOnly((String) value, VALID_CHARS)) {
197            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, ComponentUtils.translate(context,
198                    "label.groupManager.wrongGroupName"), null);
199            ((EditableValueHolder) component).setValid(false);
200            context.addMessage(component.getClientId(context), message);
201            // also add global message
202            context.addMessage(null, message);
203        }
204    }
205
206    public String viewGroup() {
207        if (selectedGroup != null) {
208            return viewGroup(selectedGroup.getId());
209        } else {
210            return null;
211        }
212    }
213
214    public String viewGroup(String groupName) {
215        webActions.setCurrentTabIds(MAIN_TAB_HOME + "," + GROUPS_TAB);
216        setSelectedGroup(groupName);
217        showUserOrGroup = true;
218        // do not reset the state before actually viewing the group
219        shouldResetStateOnTabChange = false;
220        return VIEW_HOME;
221    }
222
223    protected void fireSeamEvent(String eventName) {
224        Events evtManager = Events.instance();
225        evtManager.raiseEvent(eventName);
226    }
227
228    @Observer(value = { GROUPS_LISTING_CHANGED })
229    public void onUsersListingChanged() {
230        contentViewActions.refreshOnSeamEvent(GROUPS_LISTING_CHANGED);
231        contentViewActions.resetPageProviderOnSeamEvent(GROUPS_LISTING_CHANGED);
232    }
233
234    @Observer(value = { CURRENT_TAB_CHANGED_EVENT + "_" + MAIN_TABS_CATEGORY,
235            CURRENT_TAB_CHANGED_EVENT + "_" + NUXEO_ADMIN_CATEGORY,
236            CURRENT_TAB_CHANGED_EVENT + "_" + USER_CENTER_CATEGORY,
237            CURRENT_TAB_CHANGED_EVENT + "_" + USERS_GROUPS_MANAGER_SUB_TAB,
238            CURRENT_TAB_CHANGED_EVENT + "_" + USERS_GROUPS_HOME_SUB_TAB,
239            CURRENT_TAB_SELECTED_EVENT + "_" + MAIN_TABS_CATEGORY,
240            CURRENT_TAB_SELECTED_EVENT + "_" + NUXEO_ADMIN_CATEGORY,
241            CURRENT_TAB_SELECTED_EVENT + "_" + USER_CENTER_CATEGORY,
242            CURRENT_TAB_SELECTED_EVENT + "_" + USERS_GROUPS_MANAGER_SUB_TAB,
243            CURRENT_TAB_SELECTED_EVENT + "_" + USERS_GROUPS_HOME_SUB_TAB }, create = false)
244    public void resetState() {
245        if (shouldResetStateOnTabChange) {
246            newGroup = null;
247            showUserOrGroup = false;
248            showCreateForm = false;
249            detailsMode = DETAILS_VIEW_MODE;
250        }
251    }
252
253    public boolean isCreateAnotherGroup() {
254        return createAnotherGroup;
255    }
256
257    public void setCreateAnotherGroup(boolean createAnotherGroup) {
258        this.createAnotherGroup = createAnotherGroup;
259    }
260
261}