001/* 002 * (C) Copyright 2013 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 * Martin Pernollet 018 */ 019 020package org.nuxeo.ecm.platform.groups.audit.service.acl.data; 021 022import java.util.HashSet; 023 024import org.apache.commons.logging.Log; 025import org.apache.commons.logging.LogFactory; 026import org.nuxeo.ecm.core.api.DocumentModel; 027import org.nuxeo.ecm.core.api.security.ACE; 028import org.nuxeo.ecm.core.api.security.ACL; 029import org.nuxeo.ecm.core.api.security.ACP; 030import org.nuxeo.ecm.core.api.security.SecurityConstants; 031import org.nuxeo.ecm.platform.groups.audit.service.acl.Pair; 032import org.nuxeo.ecm.platform.groups.audit.service.acl.filter.IContentFilter; 033 034import com.google.common.collect.HashMultimap; 035import com.google.common.collect.Multimap; 036 037import static org.nuxeo.ecm.core.api.security.ACL.LOCAL_ACL; 038 039public class AclSummaryExtractor { 040 private static final Log log = LogFactory.getLog(AclSummaryExtractor.class); 041 042 protected IContentFilter filter; 043 044 public AclSummaryExtractor(IContentFilter filter) { 045 this.filter = filter; 046 } 047 048 /** 049 * Return a compact version of a document ACLs, e.g.: 050 * <ul> 051 * <li>user1 -> [(READ,true), (WRITE,false), (ADD_CHILDREN,false), ...] 052 * <li>user2 -> [(READ,true), (WRITE,true), (ADD_CHILDREN,true), ...] 053 * <li> 054 * </ul> 055 * Remark: content might be ignored according to the policy implemented by {@link IContentFilter}. 056 * 057 * @param doc 058 * @return 059 */ 060 public Multimap<String, Pair<String, Boolean>> getAllAclByUser(DocumentModel doc) { 061 ACP acp = doc.getACP(); 062 ACL[] acls = acp.getACLs(); 063 return getAclByUser(acls); 064 } 065 066 public Multimap<String, Pair<String, Boolean>> getAclLocalByUser(DocumentModel doc) { 067 ACP acp = doc.getACP(); 068 ACL acl = acp.getACL(LOCAL_ACL); 069 return getAclByUser(acl); 070 } 071 072 public Multimap<String, Pair<String, Boolean>> getAclInheritedByUser(DocumentModel doc) { 073 ACP acp = doc.getACP(); 074 ACL acl = acp.getACL(ACL.INHERITED_ACL); 075 return getAclByUser(acl); 076 } 077 078 public Multimap<String, Pair<String, Boolean>> getAclByUser(ACL[] acls) { 079 Multimap<String, Pair<String, Boolean>> aclByUser = HashMultimap.create(); 080 081 for (ACL acl : acls) { 082 fillAceByUser(aclByUser, acl); 083 } 084 return aclByUser; 085 } 086 087 public Multimap<String, Pair<String, Boolean>> getAclByUser(ACL acl) { 088 Multimap<String, Pair<String, Boolean>> aclByUser = HashMultimap.create(); 089 fillAceByUser(aclByUser, acl); 090 return aclByUser; 091 } 092 093 protected void fillAceByUser(Multimap<String, Pair<String, Boolean>> aclByUser, ACL acl) { 094 if (acl == null) 095 return; 096 for (ACE ace : acl.getACEs()) { 097 if (filter.acceptsUserOrGroup(ace.getUsername())) { 098 String userOrGroup = ace.getUsername(); 099 String permission = ace.getPermission(); 100 boolean allow = ace.isGranted(); 101 Pair<String, Boolean> pair = Pair.of(permission, allow); 102 aclByUser.put(userOrGroup, pair); 103 104 if (ace.isGranted() && ace.isDenied()) 105 log.warn("stupid state: ace granted and denied at the same time. Considered granted"); 106 } 107 } 108 } 109 110 /** 111 * Returns true if this document owns an ACE locking inheritance Remark: content might be ignored according to the 112 * policy implemented by {@link IContentFilter}. 113 * 114 * @see isLockInheritance(ACE) 115 * @param doc 116 * @return 117 */ 118 public boolean hasLockInheritanceACE(DocumentModel doc) { 119 // Fetch only local ACL to prevent from having blocking inheritance on 120 // all child. 121 ACL acl = doc.getACP().getOrCreateACL(LOCAL_ACL); 122 123 for (ACE ace : acl.getACEs()) { 124 if (filter.acceptsUserOrGroup(ace.getUsername())) { 125 if (isLockInheritance(ace)) 126 return true; 127 } 128 } 129 return false; 130 } 131 132 public boolean hasLockInheritanceACE(Multimap<String, Pair<String, Boolean>> acls) { 133 for (String user : acls.keySet()) { 134 for (Pair<String, Boolean> ace : acls.get(user)) { 135 if (SecurityConstants.EVERYONE.equals(user)) { 136 if (filter.acceptsUserOrGroup(user)) { 137 if (SecurityConstants.EVERYTHING.equals(ace.a) && !ace.b) 138 return true; 139 } 140 } 141 } 142 } 143 return false; 144 } 145 146 /** 147 * Return true if this ACE locks inheritance, in other word: 148 * <ul> 149 * <li>EVERYONE 150 * <li>EVERYTHING 151 * <li>deny 152 * </ul> 153 */ 154 public boolean isLockInheritance(ACE ace) { 155 return (SecurityConstants.EVERYONE.equals(ace.getUsername()) 156 && SecurityConstants.EVERYTHING.equals(ace.getPermission()) && ace.isDenied()); 157 } 158 159 public boolean isLockInheritance(String user, Pair<String, Boolean> ace) { 160 return (SecurityConstants.EVERYONE.equals(user) && SecurityConstants.EVERYTHING.equals(ace.a) && !ace.b); 161 } 162 163 /** 164 * Return the set of users and permissions mentionned in this document's ACLs. Remark: content might be ignored 165 * according to the policy implemented by {@link IContentFilter}. 166 * 167 * @param doc 168 * @return 169 */ 170 public Pair<HashSet<String>, HashSet<String>> getAclSummary(DocumentModel doc) { 171 Pair<HashSet<String>, HashSet<String>> summary = newSummary(); 172 ACP acp = doc.getACP(); 173 ACL[] acls = acp.getACLs(); 174 175 for (ACL acl : acls) { 176 for (ACE ace : acl.getACEs()) { 177 String userOrGroup = ace.getUsername(); 178 if (filter.acceptsUserOrGroup(userOrGroup)) { 179 String permission = ace.getPermission(); 180 summary.a.add(userOrGroup); 181 summary.b.add(permission); 182 } 183 } 184 } 185 return summary; 186 } 187 188 protected Pair<HashSet<String>, HashSet<String>> newSummary() { 189 return Pair.of(new HashSet<String>(), new HashSet<String>()); 190 } 191 192 public void printAce(DocumentModel doc) { 193 ACP acp = doc.getACP(); 194 ACL[] acls = acp.getACLs(); 195 196 for (ACL acl : acls) { 197 for (ACE ace : acl.getACEs()) { 198 System.out.println(ace); 199 } 200 } 201 } 202}