/* * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * bstefanescu */ package org.nuxeo.ecm.automation.features; import java.util.HashSet; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.NuxeoGroup; import org.nuxeo.ecm.core.api.NuxeoPrincipal; import org.nuxeo.ecm.core.api.security.ACE; import org.nuxeo.ecm.core.api.security.ACL; import org.nuxeo.ecm.core.api.security.ACP; import org.nuxeo.ecm.core.api.security.PermissionProvider; import org.nuxeo.ecm.core.api.security.SecurityConstants; import org.nuxeo.ecm.platform.usermanager.UserManager; /** * Provides helper methods to find extract permissions/principals info from documents. * * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> * @author Anahide Tchertchian */ public class PrincipalHelper { protected UserManager userManager; protected PermissionProvider permissionProvider; public PrincipalHelper(UserManager userManager, PermissionProvider permissionProvider) { this.userManager = userManager; this.permissionProvider = permissionProvider; } @SuppressWarnings("unchecked") public Set<String> getEmailsForPermission(DocumentModel input, String permission, boolean ignoreGroups) { return (Set<String>) collectObjectsMatchingPermission(input, permission, ignoreGroups, true, new EmailCollector(userManager.getUserSchemaName(), userManager.getUserEmailField())); } /** * Resolves the list of identifiers for users and groups who have the given permission on given document. * * @param input document model to resolve users and groups on. * @param permission the permission to check * @param ignoreGroups if true, will ignore groups in resolution of ids * @param resolveGroups if true, will resolve user members, iterating in the hierarchy of groups * @param prefixIds if true, will prefix identifiers with {@link NuxeoPrincipal#PREFIX} and * {@link NuxeoGroup#PREFIX} */ @SuppressWarnings("unchecked") public Set<String> getUserAndGroupIdsForPermission(DocumentModel input, String permission, boolean ignoreGroups, boolean resolveGroups, boolean prefixIds) { return (Set<String>) collectObjectsMatchingPermission(input, permission, ignoreGroups, resolveGroups, new IdCollector(prefixIds)); } @SuppressWarnings("unchecked") public Set<NuxeoPrincipal> getPrincipalsForPermission(DocumentModel input, String permission, boolean ignoreGroups, boolean resolveGroups) { return (Set<NuxeoPrincipal>) collectObjectsMatchingPermission(input, permission, ignoreGroups, resolveGroups, new PrincipalCollector()); } public Set<String> getEmailsFromGroup(String groupId, boolean resolveGroups) { EmailCollector collector = new EmailCollector(userManager.getUserSchemaName(), userManager.getUserEmailField()); collectObjectsFromGroup(groupId, resolveGroups, collector); return collector.getResult(); } public Set<NuxeoPrincipal> getPrincipalsFromGroup(String groupId, boolean resolveGroups) { PrincipalCollector collector = new PrincipalCollector(); collectObjectsFromGroup(groupId, resolveGroups, collector); return collector.getResult(); } public Set<String> getUserNamesFromGroup(String groupId, boolean resolveGroups, boolean prefixIds) { IdCollector collector = new IdCollector(prefixIds); collectObjectsFromGroup(groupId, resolveGroups, collector); return collector.getResult(); } public void collectObjectsFromGroup(String groupId, boolean resolveGroups, Collector<?> collector) { NuxeoGroup group = userManager.getGroup(groupId); if (group == null) { userManager.getPrincipal(groupId); } else { for (String u : group.getMemberUsers()) { NuxeoPrincipal principal = userManager.getPrincipal(u); if (principal != null) { collector.collect(principal); } } if (resolveGroups) { for (String g : group.getMemberGroups()) { collectObjectsFromGroup(g, resolveGroups, collector); } } } } public HashSet<?> collectObjectsMatchingPermission(DocumentModel input, String permission, boolean ignoreGroups, boolean resolveGroups, Collector<?> collector) { String[] perms = getPermissionsToCheck(permission); ACP acp = input.getACP(); for (ACL acl : acp.getACLs()) { for (ACE ace : acl.getACEs()) { if (ace.isGranted() && permissionMatch(perms, ace.getPermission())) { NuxeoGroup group = userManager.getGroup(ace.getUsername()); if (group == null) { // this may be a user collector.collect(userManager.getPrincipal(ace.getUsername())); } else if (!ignoreGroups) { if (resolveGroups) { resolveGroups(group, collector); } else { collector.collect(group); } } } } } return collector.getResult(); } public void resolveGroups(NuxeoGroup group, Collector<?> collector) { if (group != null) { for (String memberUser : group.getMemberUsers()) { collector.collect(userManager.getPrincipal(memberUser)); } for (String subGroup : group.getMemberGroups()) { resolveGroups(userManager.getGroup(subGroup), collector); } } } public String[] getPermissionsToCheck(String permission) { String[] groups = permissionProvider.getPermissionGroups(permission); if (groups == null) { return new String[] { permission, SecurityConstants.EVERYTHING }; } else { String[] perms = new String[groups.length + 2]; perms[0] = permission; System.arraycopy(groups, 0, perms, 1, groups.length); perms[groups.length + 1] = SecurityConstants.EVERYTHING; return perms; } } public boolean permissionMatch(String[] perms, String perm) { for (String p : perms) { if (p.equals(perm)) { return true; } } return false; } interface Collector<T> { void collect(NuxeoPrincipal principal); void collect(NuxeoGroup group); HashSet<T> getResult(); } public static class EmailCollector implements Collector<String> { protected final String userSchemaName; protected final String userEmailFieldName; protected HashSet<String> result = new HashSet<String>(); EmailCollector(String userSchemaName, String userEmailFieldName) { this.userSchemaName = userSchemaName; this.userEmailFieldName = userEmailFieldName; } @Override public void collect(NuxeoPrincipal principal) { if (principal == null) { return; } DocumentModel userEntry = principal.getModel(); String email = (String) userEntry.getProperty(userSchemaName, userEmailFieldName); if (!StringUtils.isEmpty(email)) { result.add(email); } } @Override public void collect(NuxeoGroup group) { // do nothing } @Override public HashSet<String> getResult() { return result; } } static class PrincipalCollector implements Collector<NuxeoPrincipal> { protected HashSet<NuxeoPrincipal> result = new HashSet<NuxeoPrincipal>(); @Override public void collect(NuxeoPrincipal principal) { if (principal == null) { return; } result.add(principal); } @Override public void collect(NuxeoGroup group) { // do nothing } @Override public HashSet<NuxeoPrincipal> getResult() { return result; } } static class IdCollector implements Collector<String> { protected final boolean prefixIds; protected HashSet<String> result = new HashSet<String>(); IdCollector(boolean prefixIds) { this.prefixIds = prefixIds; } @Override public void collect(NuxeoPrincipal principal) { if (principal != null) { String name = principal.getName(); if (name != null) { if (prefixIds) { result.add(NuxeoPrincipal.PREFIX + name); } else { result.add(name); } } } } @Override public void collect(NuxeoGroup group) { if (group != null) { String name = group.getName(); if (name != null) { if (prefixIds) { result.add(NuxeoGroup.PREFIX + name); } else { result.add(name); } } } } @Override public HashSet<String> getResult() { return result; } } }