1 17 package org.alfresco.repo.security.permissions.impl.acegi; 18 19 import java.lang.reflect.Method ; 20 import java.util.ArrayList ; 21 import java.util.Iterator ; 22 import java.util.List ; 23 import java.util.StringTokenizer ; 24 25 import net.sf.acegisecurity.Authentication; 26 import net.sf.acegisecurity.ConfigAttribute; 27 import net.sf.acegisecurity.ConfigAttributeDefinition; 28 import net.sf.acegisecurity.vote.AccessDecisionVoter; 29 30 import org.alfresco.repo.security.permissions.impl.SimplePermissionReference; 31 import org.alfresco.service.cmr.repository.ChildAssociationRef; 32 import org.alfresco.service.cmr.repository.NodeRef; 33 import org.alfresco.service.cmr.repository.NodeService; 34 import org.alfresco.service.cmr.repository.StoreRef; 35 import org.alfresco.service.cmr.security.AccessStatus; 36 import org.alfresco.service.cmr.security.AuthenticationService; 37 import org.alfresco.service.cmr.security.AuthorityService; 38 import org.alfresco.service.cmr.security.PermissionService; 39 import org.alfresco.service.namespace.NamespacePrefixResolver; 40 import org.alfresco.service.namespace.QName; 41 import org.aopalliance.intercept.MethodInvocation; 42 import org.apache.commons.logging.Log; 43 import org.apache.commons.logging.LogFactory; 44 import org.springframework.beans.factory.InitializingBean; 45 46 50 51 public class ACLEntryVoter implements AccessDecisionVoter, InitializingBean 52 { 53 private static Log log = LogFactory.getLog(ACLEntryVoter.class); 54 55 private static final String ACL_NODE = "ACL_NODE"; 56 57 private static final String ACL_PARENT = "ACL_PARENT"; 58 59 private static final String ACL_ALLOW = "ACL_ALLOW"; 60 61 private static final String ACL_METHOD = "ACL_METHOD"; 62 63 private PermissionService permissionService; 64 65 private NamespacePrefixResolver nspr; 66 67 private NodeService nodeService; 68 69 private AuthenticationService authenticationService; 70 71 private AuthorityService authorityService; 72 73 public ACLEntryVoter() 74 { 75 super(); 76 } 77 78 81 public void setPermissionService(PermissionService permissionService) 82 { 83 this.permissionService = permissionService; 84 } 85 86 public PermissionService getPermissionService() 87 { 88 return permissionService; 89 } 90 91 public NamespacePrefixResolver getNamespacePrefixResolver() 92 { 93 return nspr; 94 } 95 96 public void setNamespacePrefixResolver(NamespacePrefixResolver nspr) 97 { 98 this.nspr = nspr; 99 } 100 101 public NodeService getNodeService() 102 { 103 return nodeService; 104 } 105 106 public void setNodeService(NodeService nodeService) 107 { 108 this.nodeService = nodeService; 109 } 110 111 public AuthenticationService getAuthenticationService() 112 { 113 return authenticationService; 114 } 115 116 public void setAuthenticationService(AuthenticationService authenticationService) 117 { 118 this.authenticationService = authenticationService; 119 } 120 121 public void setAuthorityService(AuthorityService authorityService) 122 { 123 this.authorityService = authorityService; 124 } 125 126 public void afterPropertiesSet() throws Exception 127 { 128 if (permissionService == null) 129 { 130 throw new IllegalArgumentException ("There must be a permission service"); 131 } 132 if (nspr == null) 133 { 134 throw new IllegalArgumentException ("There must be a namespace service"); 135 } 136 if (nodeService == null) 137 { 138 throw new IllegalArgumentException ("There must be a node service"); 139 } 140 if (authenticationService == null) 141 { 142 throw new IllegalArgumentException ("There must be an authentication service"); 143 } 144 if (authorityService == null) 145 { 146 throw new IllegalArgumentException ("There must be an authority service"); 147 } 148 149 } 150 151 public boolean supports(ConfigAttribute attribute) 152 { 153 if ((attribute.getAttribute() != null) 154 && (attribute.getAttribute().startsWith(ACL_NODE) 155 || attribute.getAttribute().startsWith(ACL_PARENT) 156 || attribute.getAttribute().startsWith(ACL_ALLOW) || attribute.getAttribute().startsWith( 157 ACL_METHOD))) 158 { 159 return true; 160 } 161 else 162 { 163 return false; 164 } 165 } 166 167 177 public boolean supports(Class clazz) 178 { 179 return (MethodInvocation.class.isAssignableFrom(clazz)); 180 } 181 182 public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) 183 { 184 if (log.isDebugEnabled()) 185 { 186 MethodInvocation mi = (MethodInvocation) object; 187 log.debug("Method: " + mi.getMethod().toString()); 188 } 189 if (authenticationService.isCurrentUserTheSystemUser()) 190 { 191 if (log.isDebugEnabled()) 192 { 193 log.debug("Access granted for the system user"); 194 } 195 return AccessDecisionVoter.ACCESS_GRANTED; 196 } 197 198 List <ConfigAttributeDefintion> supportedDefinitions = extractSupportedDefinitions(config); 199 200 if (supportedDefinitions.size() == 0) 201 { 202 return AccessDecisionVoter.ACCESS_GRANTED; 203 } 204 205 MethodInvocation invocation = (MethodInvocation) object; 206 207 Method method = invocation.getMethod(); 208 Class [] params = method.getParameterTypes(); 209 210 for (ConfigAttributeDefintion cad : supportedDefinitions) 211 { 212 NodeRef testNodeRef = null; 213 214 if (cad.typeString.equals(ACL_ALLOW)) 215 { 216 return AccessDecisionVoter.ACCESS_GRANTED; 217 } 218 else if (cad.typeString.equals(ACL_METHOD)) 219 { 220 if (authenticationService.getCurrentUserName().equals(cad.authority)) 221 { 222 return AccessDecisionVoter.ACCESS_GRANTED; 223 } 224 else 225 { 226 return authorityService.getAuthorities().contains(cad.authority) ? AccessDecisionVoter.ACCESS_GRANTED 227 : AccessDecisionVoter.ACCESS_DENIED; 228 } 229 } 230 else if (cad.parameter >= invocation.getArguments().length) 231 { 232 continue; 233 } 234 else if (cad.typeString.equals(ACL_NODE)) 235 { 236 if (StoreRef.class.isAssignableFrom(params[cad.parameter])) 237 { 238 if (invocation.getArguments()[cad.parameter] != null) 239 { 240 if (log.isDebugEnabled()) 241 { 242 log.debug("\tPermission test against the store - using permissions on the root node"); 243 } 244 StoreRef storeRef = (StoreRef) invocation.getArguments()[cad.parameter]; 245 if (nodeService.exists(storeRef)) 246 { 247 testNodeRef = nodeService.getRootNode(storeRef); 248 } 249 } 250 } 251 else if (NodeRef.class.isAssignableFrom(params[cad.parameter])) 252 { 253 testNodeRef = (NodeRef) invocation.getArguments()[cad.parameter]; 254 if (log.isDebugEnabled()) 255 { 256 log.debug("\tPermission test on node " + nodeService.getPath(testNodeRef)); 257 } 258 } 259 else if (ChildAssociationRef.class.isAssignableFrom(params[cad.parameter])) 260 { 261 if (invocation.getArguments()[cad.parameter] != null) 262 { 263 testNodeRef = ((ChildAssociationRef) invocation.getArguments()[cad.parameter]).getChildRef(); 264 if (log.isDebugEnabled()) 265 { 266 log.debug("\tPermission test on node " + nodeService.getPath(testNodeRef)); 267 } 268 } 269 } 270 else 271 { 272 throw new ACLEntryVoterException("The specified parameter is not a NodeRef or ChildAssociationRef"); 273 } 274 } 275 else if (cad.typeString.equals(ACL_PARENT)) 276 { 277 if (NodeRef.class.isAssignableFrom(params[cad.parameter])) 280 { 281 NodeRef child = (NodeRef) invocation.getArguments()[cad.parameter]; 282 if (child != null) 283 { 284 testNodeRef = nodeService.getPrimaryParent(child).getParentRef(); 285 if (log.isDebugEnabled()) 286 { 287 log.debug("\tPermission test for parent on node " + nodeService.getPath(testNodeRef)); 288 } 289 } 290 } 291 else if (ChildAssociationRef.class.isAssignableFrom(params[cad.parameter])) 292 { 293 if (invocation.getArguments()[cad.parameter] != null) 294 { 295 testNodeRef = ((ChildAssociationRef) invocation.getArguments()[cad.parameter]).getParentRef(); 296 if (log.isDebugEnabled()) 297 { 298 log.debug("\tPermission test for parent on child assoc ref for node " 299 + nodeService.getPath(testNodeRef)); 300 } 301 } 302 303 } 304 else 305 { 306 throw new ACLEntryVoterException("The specified parameter is not a ChildAssociationRef"); 307 } 308 } 309 310 if (testNodeRef != null) 311 { 312 if (log.isDebugEnabled()) 313 { 314 log.debug("\t\tNode ref is not null"); 315 } 316 if (permissionService.hasPermission(testNodeRef, cad.required.toString()) == AccessStatus.DENIED) 317 { 318 if (log.isDebugEnabled()) 319 { 320 log.debug("\t\tPermission is denied"); 321 Thread.dumpStack(); 322 } 323 return AccessDecisionVoter.ACCESS_DENIED; 324 } 325 } 326 } 327 328 return AccessDecisionVoter.ACCESS_GRANTED; 329 } 330 331 private List <ConfigAttributeDefintion> extractSupportedDefinitions(ConfigAttributeDefinition config) 332 { 333 List <ConfigAttributeDefintion> definitions = new ArrayList <ConfigAttributeDefintion>(); 334 Iterator iter = config.getConfigAttributes(); 335 336 while (iter.hasNext()) 337 { 338 ConfigAttribute attr = (ConfigAttribute) iter.next(); 339 340 if (this.supports(attr)) 341 { 342 definitions.add(new ConfigAttributeDefintion(attr)); 343 } 344 345 } 346 return definitions; 347 } 348 349 private class ConfigAttributeDefintion 350 { 351 String typeString; 352 353 SimplePermissionReference required; 354 355 int parameter; 356 357 String authority; 358 359 ConfigAttributeDefintion(ConfigAttribute attr) 360 { 361 StringTokenizer st = new StringTokenizer (attr.getAttribute(), ".", false); 362 if (st.countTokens() < 1) 363 { 364 throw new ACLEntryVoterException("There must be at least one token in a config attribute"); 365 } 366 typeString = st.nextToken(); 367 368 if (!(typeString.equals(ACL_NODE) || typeString.equals(ACL_PARENT) || typeString.equals(ACL_ALLOW) || typeString 369 .equals(ACL_METHOD))) 370 { 371 throw new ACLEntryVoterException("Invalid type: must be ACL_NODE, ACL_PARENT or ACL_ALLOW"); 372 } 373 374 if (typeString.equals(ACL_NODE) || typeString.equals(ACL_PARENT)) 375 { 376 if (st.countTokens() != 3) 377 { 378 throw new ACLEntryVoterException("There must be four . separated tokens in each config attribute"); 379 } 380 String numberString = st.nextToken(); 381 String qNameString = st.nextToken(); 382 String permissionString = st.nextToken(); 383 384 parameter = Integer.parseInt(numberString); 385 386 QName qName = QName.createQName(qNameString, nspr); 387 388 required = new SimplePermissionReference(qName, permissionString); 389 } 390 else if (typeString.equals(ACL_METHOD)) 391 { 392 if (st.countTokens() != 1) 393 { 394 throw new ACLEntryVoterException( 395 "There must be two . separated tokens in each group or role config attribute"); 396 } 397 authority = st.nextToken(); 398 } 399 400 } 401 } 402 } 403 | Popular Tags |