001/*
002 * (C) Copyright 2006-2007 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 *
016 * Contributors:
017 *     Thierry Delprat
018 *
019 */
020
021package org.nuxeo.ecm.platform.computedgroups;
022
023import java.io.Serializable;
024import java.util.ArrayList;
025import java.util.List;
026import java.util.Map;
027import java.util.Set;
028
029import org.nuxeo.ecm.core.api.DocumentModel;
030import org.nuxeo.ecm.core.api.DocumentModelList;
031import org.nuxeo.ecm.core.api.NuxeoGroup;
032import org.nuxeo.ecm.core.api.NuxeoPrincipal;
033import org.nuxeo.ecm.directory.BaseSession;
034import org.nuxeo.ecm.platform.usermanager.NuxeoPrincipalImpl;
035import org.nuxeo.ecm.platform.usermanager.UserManager;
036import org.nuxeo.ecm.platform.usermanager.UserManagerImpl;
037import org.nuxeo.runtime.api.Framework;
038
039/**
040 * {@link UserManager} implementation that is aware of {@link ComputedGroup}.
041 *
042 * @author Thierry Delprat
043 */
044public class UserManagerWithComputedGroups extends UserManagerImpl {
045
046    private static final long serialVersionUID = 1L;
047
048    protected static ComputedGroupsService cgs;
049
050    protected static Boolean useComputedGroup;
051
052    public static final String VIRTUAL_GROUP_MARKER = "__virtualGroup";
053
054    protected ComputedGroupsService getService() {
055        if (cgs == null) {
056            cgs = Framework.getLocalService(ComputedGroupsService.class);
057        }
058        return cgs;
059    }
060
061    protected boolean activateComputedGroup() {
062        // NXP-8133: recompute during tests, need to find a cleaner fix
063        if (useComputedGroup == null || Framework.isTestModeSet()) {
064            useComputedGroup = getService().activateComputedGroups();
065        }
066        return useComputedGroup;
067    }
068
069    @Override
070    protected NuxeoPrincipal makePrincipal(DocumentModel userEntry, boolean anonymous, List<String> groups)
071            {
072
073        NuxeoPrincipal principal = super.makePrincipal(userEntry, anonymous, groups);
074        if (activateComputedGroup() && principal instanceof NuxeoPrincipalImpl) {
075            NuxeoPrincipalImpl nuxPrincipal = (NuxeoPrincipalImpl) principal;
076
077            List<String> vGroups = getService().computeGroupsForUser(nuxPrincipal);
078
079            if (vGroups == null) {
080                vGroups = new ArrayList<String>();
081            }
082
083            List<String> origVGroups = nuxPrincipal.getVirtualGroups();
084            if (origVGroups == null) {
085                origVGroups = new ArrayList<String>();
086            }
087
088            // MERGE!
089            origVGroups.addAll(vGroups);
090
091            nuxPrincipal.setVirtualGroups(origVGroups);
092
093            // This a hack to work around the problem of running tests
094            if (!Framework.isTestModeSet()) {
095                nuxPrincipal.updateAllGroups();
096            } else {
097                List<String> allGroups = nuxPrincipal.getGroups();
098                for (String vGroup : vGroups) {
099                    if (!allGroups.contains(vGroup)) {
100                        allGroups.add(vGroup);
101                    }
102                }
103                nuxPrincipal.setGroups(allGroups);
104            }
105        }
106        return principal;
107    }
108
109    @Override
110    public NuxeoGroup getGroup(String groupName) {
111        NuxeoGroup grp = super.getGroup(groupName);
112        if (activateComputedGroup() && (grp == null || getService().allowGroupOverride())) {
113            NuxeoGroup computed = getService().getComputedGroup(groupName);
114            if (computed != null) {
115                grp = computed;
116            }
117        }
118        return grp;
119    }
120
121    @Override
122    public NuxeoGroup getGroup(String groupName, DocumentModel context) {
123        NuxeoGroup grp = super.getGroup(groupName, context);
124        if (activateComputedGroup() && (grp == null || getService().allowGroupOverride())) {
125            NuxeoGroup computed = getService().getComputedGroup(groupName);
126            if (computed != null) {
127                grp = computed;
128            }
129        }
130        return grp;
131    }
132
133    @Override
134    public List<String> getGroupIds() {
135        List<String> ids = super.getGroupIds();
136        if (activateComputedGroup()) {
137            List<String> vGroups = getService().computeGroupIds();
138            for (String vGroup : vGroups) {
139                if (!ids.contains(vGroup)) {
140                    ids.add(vGroup);
141                }
142            }
143        }
144        return ids;
145    }
146
147    @Override
148    public DocumentModel getGroupModel(String groupName) {
149        DocumentModel grpDoc = super.getGroupModel(groupName);
150        if (activateComputedGroup() && grpDoc == null) {
151            return getComputedGroupAsDocumentModel(groupName);
152        }
153        return grpDoc;
154    }
155
156    @Override
157    public DocumentModelList searchGroups(Map<String, Serializable> filter, Set<String> fulltext)
158            {
159        return searchGroups(filter, fulltext, null);
160    }
161
162    @Override
163    public DocumentModelList searchGroups(Map<String, Serializable> filter, Set<String> fulltext, DocumentModel context)
164            {
165
166        boolean searchInVirtualGroups = activateComputedGroup();
167        if (Boolean.FALSE.equals(filter.get(VIRTUAL_GROUP_MARKER))) {
168            searchInVirtualGroups = false;
169        }
170
171        removeVirtualFilters(filter);
172        DocumentModelList groups = super.searchGroups(filter, fulltext, context);
173
174        if (searchInVirtualGroups) {
175            for (String vGroupName : getService().searchComputedGroups(filter, fulltext)) {
176                DocumentModel vGroup = getComputedGroupAsDocumentModel(vGroupName);
177                if (vGroup != null) {
178                    if (!groups.contains(vGroup)) {
179                        groups.add(vGroup);
180                    }
181                }
182            }
183        }
184        return groups;
185    }
186
187    protected DocumentModel getComputedGroupAsDocumentModel(String grpName) {
188        NuxeoGroup grp = getService().getComputedGroup(grpName);
189        if (grp == null) {
190            return null;
191        }
192
193        String schemaName = getGroupSchemaName();
194        String id = getGroupIdField();
195        DocumentModel groupDoc = BaseSession.createEntryModel(null, schemaName, grpName, null);
196
197        groupDoc.setProperty(schemaName, getGroupMembersField(), grp.getMemberUsers());
198        groupDoc.setProperty(schemaName, id, grp.getName());
199        groupDoc.setProperty(schemaName, getGroupIdField(), grp.getName());
200
201        groupDoc.putContextData("virtual", Boolean.TRUE);
202
203        return groupDoc;
204    }
205
206}