001/* 002 * (C) Copyright 2006-2011 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 * bstefanescu 018 */ 019package org.nuxeo.ecm.automation.features; 020 021import java.util.HashSet; 022import java.util.Set; 023 024import org.apache.commons.lang.StringUtils; 025import org.nuxeo.ecm.core.api.DocumentModel; 026import org.nuxeo.ecm.core.api.NuxeoGroup; 027import org.nuxeo.ecm.core.api.NuxeoPrincipal; 028import org.nuxeo.ecm.core.api.security.ACE; 029import org.nuxeo.ecm.core.api.security.ACL; 030import org.nuxeo.ecm.core.api.security.ACP; 031import org.nuxeo.ecm.core.api.security.PermissionProvider; 032import org.nuxeo.ecm.core.api.security.SecurityConstants; 033import org.nuxeo.ecm.platform.usermanager.UserManager; 034 035/** 036 * Provides helper methods to find extract permissions/principals info from documents. 037 * 038 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 039 * @author Anahide Tchertchian 040 */ 041public class PrincipalHelper { 042 043 protected UserManager userManager; 044 045 protected PermissionProvider permissionProvider; 046 047 public PrincipalHelper(UserManager userManager, PermissionProvider permissionProvider) { 048 this.userManager = userManager; 049 this.permissionProvider = permissionProvider; 050 } 051 052 @SuppressWarnings("unchecked") 053 public Set<String> getEmailsForPermission(DocumentModel input, String permission, boolean ignoreGroups) 054 { 055 return (Set<String>) collectObjectsMatchingPermission(input, permission, ignoreGroups, true, 056 new EmailCollector(userManager.getUserSchemaName(), userManager.getUserEmailField())); 057 } 058 059 /** 060 * Resolves the list of identifiers for users and groups who have the given permission on given document. 061 * 062 * @param input document model to resolve users and groups on. 063 * @param permission the permission to check 064 * @param ignoreGroups if true, will ignore groups in resolution of ids 065 * @param resolveGroups if true, will resolve user members, iterating in the hierarchy of groups 066 * @param prefixIds if true, will prefix identifiers with {@link NuxeoPrincipal#PREFIX} and 067 * {@link NuxeoGroup#PREFIX} 068 */ 069 @SuppressWarnings("unchecked") 070 public Set<String> getUserAndGroupIdsForPermission(DocumentModel input, String permission, boolean ignoreGroups, 071 boolean resolveGroups, boolean prefixIds) { 072 return (Set<String>) collectObjectsMatchingPermission(input, permission, ignoreGroups, resolveGroups, 073 new IdCollector(prefixIds)); 074 } 075 076 @SuppressWarnings("unchecked") 077 public Set<NuxeoPrincipal> getPrincipalsForPermission(DocumentModel input, String permission, boolean ignoreGroups, 078 boolean resolveGroups) { 079 return (Set<NuxeoPrincipal>) collectObjectsMatchingPermission(input, permission, ignoreGroups, resolveGroups, 080 new PrincipalCollector()); 081 } 082 083 public Set<String> getEmailsFromGroup(String groupId, boolean resolveGroups) { 084 EmailCollector collector = new EmailCollector(userManager.getUserSchemaName(), userManager.getUserEmailField()); 085 collectObjectsFromGroup(groupId, resolveGroups, collector); 086 return collector.getResult(); 087 } 088 089 public Set<NuxeoPrincipal> getPrincipalsFromGroup(String groupId, boolean resolveGroups) { 090 PrincipalCollector collector = new PrincipalCollector(); 091 collectObjectsFromGroup(groupId, resolveGroups, collector); 092 return collector.getResult(); 093 } 094 095 public Set<String> getUserNamesFromGroup(String groupId, boolean resolveGroups, boolean prefixIds) 096 { 097 IdCollector collector = new IdCollector(prefixIds); 098 collectObjectsFromGroup(groupId, resolveGroups, collector); 099 return collector.getResult(); 100 } 101 102 public void collectObjectsFromGroup(String groupId, boolean resolveGroups, Collector<?> collector) 103 { 104 NuxeoGroup group = userManager.getGroup(groupId); 105 if (group == null) { 106 userManager.getPrincipal(groupId); 107 } else { 108 for (String u : group.getMemberUsers()) { 109 NuxeoPrincipal principal = userManager.getPrincipal(u); 110 if (principal != null) { 111 collector.collect(principal); 112 } 113 } 114 if (resolveGroups) { 115 for (String g : group.getMemberGroups()) { 116 collectObjectsFromGroup(g, resolveGroups, collector); 117 } 118 } 119 } 120 } 121 122 public HashSet<?> collectObjectsMatchingPermission(DocumentModel input, String permission, boolean ignoreGroups, 123 boolean resolveGroups, Collector<?> collector) { 124 String[] perms = getPermissionsToCheck(permission); 125 ACP acp = input.getACP(); 126 for (ACL acl : acp.getACLs()) { 127 for (ACE ace : acl.getACEs()) { 128 if (ace.isGranted() && permissionMatch(perms, ace.getPermission())) { 129 NuxeoGroup group = userManager.getGroup(ace.getUsername()); 130 if (group == null) { 131 // this may be a user 132 collector.collect(userManager.getPrincipal(ace.getUsername())); 133 } else if (!ignoreGroups) { 134 if (resolveGroups) { 135 resolveGroups(group, collector); 136 } else { 137 collector.collect(group); 138 } 139 } 140 } 141 } 142 } 143 return collector.getResult(); 144 } 145 146 public void resolveGroups(NuxeoGroup group, Collector<?> collector) { 147 if (group != null) { 148 for (String memberUser : group.getMemberUsers()) { 149 collector.collect(userManager.getPrincipal(memberUser)); 150 } 151 for (String subGroup : group.getMemberGroups()) { 152 resolveGroups(userManager.getGroup(subGroup), collector); 153 } 154 } 155 } 156 157 public String[] getPermissionsToCheck(String permission) { 158 String[] groups = permissionProvider.getPermissionGroups(permission); 159 if (groups == null) { 160 return new String[] { permission, SecurityConstants.EVERYTHING }; 161 } else { 162 String[] perms = new String[groups.length + 2]; 163 perms[0] = permission; 164 System.arraycopy(groups, 0, perms, 1, groups.length); 165 perms[groups.length + 1] = SecurityConstants.EVERYTHING; 166 return perms; 167 } 168 } 169 170 public boolean permissionMatch(String[] perms, String perm) { 171 for (String p : perms) { 172 if (p.equals(perm)) { 173 return true; 174 } 175 } 176 return false; 177 } 178 179 interface Collector<T> { 180 181 void collect(NuxeoPrincipal principal); 182 183 void collect(NuxeoGroup group); 184 185 HashSet<T> getResult(); 186 } 187 188 public static class EmailCollector implements Collector<String> { 189 190 protected final String userSchemaName; 191 192 protected final String userEmailFieldName; 193 194 protected HashSet<String> result = new HashSet<String>(); 195 196 EmailCollector(String userSchemaName, String userEmailFieldName) { 197 this.userSchemaName = userSchemaName; 198 this.userEmailFieldName = userEmailFieldName; 199 } 200 201 @Override 202 public void collect(NuxeoPrincipal principal) { 203 if (principal == null) { 204 return; 205 } 206 DocumentModel userEntry = principal.getModel(); 207 String email = (String) userEntry.getProperty(userSchemaName, userEmailFieldName); 208 if (!StringUtils.isEmpty(email)) { 209 result.add(email); 210 } 211 } 212 213 @Override 214 public void collect(NuxeoGroup group) { 215 // do nothing 216 } 217 218 @Override 219 public HashSet<String> getResult() { 220 return result; 221 } 222 } 223 224 static class PrincipalCollector implements Collector<NuxeoPrincipal> { 225 226 protected HashSet<NuxeoPrincipal> result = new HashSet<NuxeoPrincipal>(); 227 228 @Override 229 public void collect(NuxeoPrincipal principal) { 230 if (principal == null) { 231 return; 232 } 233 result.add(principal); 234 } 235 236 @Override 237 public void collect(NuxeoGroup group) { 238 // do nothing 239 } 240 241 @Override 242 public HashSet<NuxeoPrincipal> getResult() { 243 return result; 244 } 245 } 246 247 static class IdCollector implements Collector<String> { 248 249 protected final boolean prefixIds; 250 251 protected HashSet<String> result = new HashSet<String>(); 252 253 IdCollector(boolean prefixIds) { 254 this.prefixIds = prefixIds; 255 } 256 257 @Override 258 public void collect(NuxeoPrincipal principal) { 259 if (principal != null) { 260 String name = principal.getName(); 261 if (name != null) { 262 if (prefixIds) { 263 result.add(NuxeoPrincipal.PREFIX + name); 264 } else { 265 result.add(name); 266 } 267 } 268 } 269 } 270 271 @Override 272 public void collect(NuxeoGroup group) { 273 if (group != null) { 274 String name = group.getName(); 275 if (name != null) { 276 if (prefixIds) { 277 result.add(NuxeoGroup.PREFIX + name); 278 } else { 279 result.add(name); 280 } 281 } 282 } 283 } 284 285 @Override 286 public HashSet<String> getResult() { 287 return result; 288 } 289 290 } 291 292}