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 NuxeoGroup getGroup(String groupName, DocumentModel context) { 124 NuxeoGroup grp = super.getGroup(groupName, context); 125 if (activateComputedGroup() && (grp == null || getService().allowGroupOverride())) { 126 NuxeoGroup computed = getService().getComputedGroup(groupName); 127 if (computed != null) { 128 grp = computed; 129 } 130 } 131 return grp; 132 } 133 134 @Override 135 public List<String> getGroupIds() { 136 List<String> ids = super.getGroupIds(); 137 if (activateComputedGroup()) { 138 List<String> vGroups = getService().computeGroupIds(); 139 for (String vGroup : vGroups) { 140 if (!ids.contains(vGroup)) { 141 ids.add(vGroup); 142 } 143 } 144 } 145 return ids; 146 } 147 148 @Override 149 public DocumentModel getGroupModel(String groupName) { 150 DocumentModel grpDoc = super.getGroupModel(groupName); 151 if (activateComputedGroup() && grpDoc == null) { 152 return getComputedGroupAsDocumentModel(groupName); 153 } 154 return grpDoc; 155 } 156 157 @Override 158 public DocumentModelList searchGroups(Map<String, Serializable> filter, Set<String> fulltext) 159 { 160 return searchGroups(filter, fulltext, null); 161 } 162 163 @Override 164 public DocumentModelList searchGroups(Map<String, Serializable> filter, Set<String> fulltext, DocumentModel context) 165 { 166 167 boolean searchInVirtualGroups = activateComputedGroup(); 168 if (Boolean.FALSE.equals(filter.get(VIRTUAL_GROUP_MARKER))) { 169 searchInVirtualGroups = false; 170 } 171 172 removeVirtualFilters(filter); 173 DocumentModelList groups = super.searchGroups(filter, fulltext, context); 174 175 if (searchInVirtualGroups) { 176 for (String vGroupName : getService().searchComputedGroups(filter, fulltext)) { 177 DocumentModel vGroup = getComputedGroupAsDocumentModel(vGroupName); 178 if (vGroup != null) { 179 if (!groups.contains(vGroup)) { 180 groups.add(vGroup); 181 } 182 } 183 } 184 } 185 return groups; 186 } 187 188 protected DocumentModel getComputedGroupAsDocumentModel(String grpName) { 189 NuxeoGroup grp = getService().getComputedGroup(grpName); 190 if (grp == null) { 191 return null; 192 } 193 194 String schemaName = getGroupSchemaName(); 195 String id = getGroupIdField(); 196 DocumentModel groupDoc = BaseSession.createEntryModel(null, schemaName, grpName, null); 197 198 groupDoc.setProperty(schemaName, getGroupMembersField(), grp.getMemberUsers()); 199 groupDoc.setProperty(schemaName, id, grp.getName()); 200 groupDoc.setProperty(schemaName, getGroupIdField(), grp.getName()); 201 202 final ScopedMap contextData = groupDoc.getContextData(); 203 contextData.putScopedValue("virtual", Boolean.TRUE); 204 205 return groupDoc; 206 } 207 208}