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