mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-07-13 13:53:29 +00:00
SEC-1015: Removed acl package from core and also related taglib declaration and implementation class (AclTag).
This commit is contained in:
parent
e5b1073501
commit
0ba690fb0e
@ -1,29 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* Marker interface representing an access control list entry associated with a
|
||||
* specific domain object instance.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public interface AclEntry extends Serializable {}
|
@ -1,52 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
|
||||
|
||||
/**
|
||||
* Obtains the <code>AclEntry</code> instances that apply to a particular
|
||||
* domain object instance.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public interface AclManager {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Obtains the ACLs that apply to the specified domain instance.
|
||||
*
|
||||
* @param domainInstance the instance for which ACL information is required (never <code>null</code>)
|
||||
*
|
||||
* @return the ACLs that apply, or <code>null</code> if no ACLs apply to the specified domain instance
|
||||
*/
|
||||
AclEntry[] getAcls(Object domainInstance);
|
||||
|
||||
/**
|
||||
* Obtains the ACLs that apply to the specified domain instance, but only including those ACLs which have
|
||||
* been granted to the presented <code>Authentication</code> object
|
||||
*
|
||||
* @param domainInstance the instance for which ACL information is required (never <code>null</code>)
|
||||
* @param authentication the prncipal for which ACL information should be filtered (never <code>null</code>)
|
||||
*
|
||||
* @return only those ACLs applying to the domain instance that have been granted to the principal (or
|
||||
* <code>null</code>) if no such ACLs are found
|
||||
*/
|
||||
AclEntry[] getAcls(Object domainInstance, Authentication authentication);
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates a class can process a given domain object instance and
|
||||
* authoritatively return the ACLs that apply.
|
||||
*
|
||||
* <P>
|
||||
* Implementations are typically called from the {@link AclProviderManager}.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public interface AclProvider {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Obtains the ACLs that apply to the specified domain instance.<P>Will never be called unless the {@link
|
||||
* #supports(Object)} method returned <code>true</code>.</p>
|
||||
*
|
||||
* @param domainInstance the instance for which ACL information is required (never <code>null</code>)
|
||||
*
|
||||
* @return the ACLs that apply, or <code>null</code> if no ACLs apply to the specified domain instance
|
||||
*/
|
||||
AclEntry[] getAcls(Object domainInstance);
|
||||
|
||||
/**
|
||||
* Obtains the ACLs that apply to the specified domain instance and presented <code>Authentication</code>
|
||||
* object.<P>Will never be called unless the {@link #supports(Object)} method returned <code>true</code>.</p>
|
||||
*
|
||||
* @param domainInstance the instance for which ACL information is required (never <code>null</code>)
|
||||
* @param authentication the prncipal for which ACL information should be filtered (never <code>null</code>)
|
||||
*
|
||||
* @return only those ACLs applying to the domain instance that have been granted to the principal (or
|
||||
* <code>null</code>) if no such ACLs are found
|
||||
*/
|
||||
AclEntry[] getAcls(Object domainInstance, Authentication authentication);
|
||||
|
||||
/**
|
||||
* Indicates whether this <code>AclProvider</code> can authoritatively return ACL information for the
|
||||
* specified domain object instance.
|
||||
*
|
||||
* @param domainInstance the instance for which ACL information is required (never <code>null</code>)
|
||||
*
|
||||
* @return <code>true</code> if this provider is authoritative for the specified domain object instance,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
boolean supports(Object domainInstance);
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Iterates through a list of {@link AclProvider}s to locate the ACLs that apply to a given domain object instance.<P>If
|
||||
* no compatible provider is found, it is assumed that no ACLs apply for the specified domain object instance and
|
||||
* <code>null</code> is returned.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public class AclProviderManager implements AclManager, InitializingBean {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(AclProviderManager.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private List providers;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
checkIfValidList(this.providers);
|
||||
}
|
||||
|
||||
private void checkIfValidList(List listToCheck) {
|
||||
Assert.notEmpty(listToCheck, "A list of AclManagers is required");
|
||||
}
|
||||
|
||||
public AclEntry[] getAcls(Object domainInstance) {
|
||||
Assert.notNull(domainInstance, "domainInstance is null - violating interface contract");
|
||||
|
||||
Iterator iter = providers.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
AclProvider provider = (AclProvider) iter.next();
|
||||
|
||||
if (provider.supports(domainInstance)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("ACL lookup using " + provider.getClass().getName());
|
||||
}
|
||||
|
||||
return provider.getAcls(domainInstance);
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No AclProvider found for " + domainInstance.toString());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public AclEntry[] getAcls(Object domainInstance, Authentication authentication) {
|
||||
Assert.notNull(domainInstance, "domainInstance is null - violating interface contract");
|
||||
Assert.notNull(authentication, "authentication is null - violating interface contract");
|
||||
|
||||
Iterator iter = providers.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
AclProvider provider = (AclProvider) iter.next();
|
||||
|
||||
if (provider.supports(domainInstance)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("ACL lookup using " + provider.getClass().getName());
|
||||
}
|
||||
|
||||
return provider.getAcls(domainInstance, authentication);
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Provider " + provider.toString() + " does not support " + domainInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No AclProvider found for " + domainInstance.toString());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public List getProviders() {
|
||||
return this.providers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AclProvider} objects to be used for ACL determinations.
|
||||
*
|
||||
* @param newList that should be used for ACL determinations
|
||||
*
|
||||
* @throws IllegalArgumentException if an invalid provider was included in the list
|
||||
*/
|
||||
public void setProviders(List newList) {
|
||||
checkIfValidList(newList);
|
||||
|
||||
Iterator iter = newList.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
Object currentObject = iter.next();
|
||||
Assert.isInstanceOf(AclProvider.class, currentObject, "Invalid Acl Provider. ");
|
||||
}
|
||||
|
||||
this.providers = newList;
|
||||
}
|
||||
}
|
@ -1,252 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
/**
|
||||
* Abstract implementation of {@link BasicAclEntry}.<P>Provides core bit mask handling methods.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public abstract class AbstractBasicAclEntry implements BasicAclEntry {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(AbstractBasicAclEntry.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private AclObjectIdentity aclObjectIdentity;
|
||||
private AclObjectIdentity aclObjectParentIdentity;
|
||||
private Object recipient;
|
||||
private int[] validPermissions;
|
||||
private int mask = 0; // default means no permissions
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public AbstractBasicAclEntry(Object recipient, AclObjectIdentity aclObjectIdentity,
|
||||
AclObjectIdentity aclObjectParentIdentity, int mask) {
|
||||
Assert.notNull(recipient, "recipient cannot be null");
|
||||
|
||||
Assert.notNull(aclObjectIdentity, "aclObjectIdentity cannot be null");
|
||||
|
||||
validPermissions = getValidPermissions();
|
||||
Arrays.sort(validPermissions);
|
||||
|
||||
for (int i = 0; i < validPermissions.length; i++) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Valid permission: " + printPermissionsBlock(validPermissions[i]) + " "
|
||||
+ printBinary(validPermissions[i]) + " (" + validPermissions[i] + ")");
|
||||
}
|
||||
}
|
||||
|
||||
this.recipient = recipient;
|
||||
this.aclObjectIdentity = aclObjectIdentity;
|
||||
this.aclObjectParentIdentity = aclObjectParentIdentity;
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* A protected constructor for use by Hibernate.
|
||||
*/
|
||||
protected AbstractBasicAclEntry() {
|
||||
validPermissions = getValidPermissions();
|
||||
Arrays.sort(validPermissions);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public int addPermission(int permissionToAdd) {
|
||||
return addPermissions(new int[] {permissionToAdd});
|
||||
}
|
||||
|
||||
public int addPermissions(int[] permissionsToAdd) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("BEFORE Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " (" + mask
|
||||
+ ")");
|
||||
}
|
||||
|
||||
for (int i = 0; i < permissionsToAdd.length; i++) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Add permission: " + printPermissionsBlock(permissionsToAdd[i]) + " "
|
||||
+ printBinary(permissionsToAdd[i]) + " (" + permissionsToAdd[i] + ")");
|
||||
}
|
||||
|
||||
this.mask |= permissionsToAdd[i];
|
||||
}
|
||||
|
||||
if (Arrays.binarySearch(validPermissions, this.mask) < 0) {
|
||||
throw new IllegalArgumentException("Resulting permission set will be invalid.");
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("AFTER Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " ("
|
||||
+ mask + ")");
|
||||
}
|
||||
|
||||
return this.mask;
|
||||
}
|
||||
}
|
||||
|
||||
public int deletePermission(int permissionToDelete) {
|
||||
return deletePermissions(new int[] {permissionToDelete});
|
||||
}
|
||||
|
||||
public int deletePermissions(int[] permissionsToDelete) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("BEFORE Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " (" + mask
|
||||
+ ")");
|
||||
}
|
||||
|
||||
for (int i = 0; i < permissionsToDelete.length; i++) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Delete permission: " + printPermissionsBlock(permissionsToDelete[i]) + " "
|
||||
+ printBinary(permissionsToDelete[i]) + " (" + permissionsToDelete[i] + ")");
|
||||
}
|
||||
|
||||
this.mask &= ~permissionsToDelete[i];
|
||||
}
|
||||
|
||||
if (Arrays.binarySearch(validPermissions, this.mask) < 0) {
|
||||
throw new IllegalArgumentException("Resulting permission set will be invalid.");
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("AFTER Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " ("
|
||||
+ mask + ")");
|
||||
}
|
||||
|
||||
return this.mask;
|
||||
}
|
||||
}
|
||||
|
||||
public AclObjectIdentity getAclObjectIdentity() {
|
||||
return this.aclObjectIdentity;
|
||||
}
|
||||
|
||||
public AclObjectIdentity getAclObjectParentIdentity() {
|
||||
return this.aclObjectParentIdentity;
|
||||
}
|
||||
|
||||
public int getMask() {
|
||||
return this.mask;
|
||||
}
|
||||
|
||||
public Object getRecipient() {
|
||||
return this.recipient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must indicate the permissions they support. Each base permission should be an integer with a
|
||||
* base 2. ie: the first permission is 2^^0 (1), the second permission is 2^^1 (2), the third permission is 2^^2
|
||||
* (4) etc. Each base permission should be exposed by the subclass as a <code>public static final int</code>. It
|
||||
* is further recommended that valid combinations of permissions are also exposed as <code>public static final
|
||||
* int</code>s.<P>This method returns all permission integers that are allowed to be used together. <B>This
|
||||
* must include any combinations of valid permissions</b>. So if the permissions indicated by 2^^2 (4) and 2^^1
|
||||
* (2) can be used together, one of the integers returned by this method must be 6 (4 + 2). Otherwise attempts to
|
||||
* set the permission will be rejected, as the final resulting mask will be rejected.</p>
|
||||
* <P>Whilst it may seem unduly time onerous to return every valid permission <B>combination</B>, doing so
|
||||
* delivers maximum flexibility in ensuring ACLs only reflect logical combinations. For example, it would be
|
||||
* inappropriate to grant a "read" and "write" permission along with an "unrestricted" permission, as the latter
|
||||
* implies the former permissions.</p>
|
||||
*
|
||||
* @return <b>every</b> valid combination of permissions
|
||||
*/
|
||||
public abstract int[] getValidPermissions();
|
||||
|
||||
public boolean isPermitted(int permissionToCheck) {
|
||||
return isPermitted(this.mask, permissionToCheck);
|
||||
}
|
||||
|
||||
protected boolean isPermitted(int maskToCheck, int permissionToCheck) {
|
||||
return ((maskToCheck & permissionToCheck) == permissionToCheck);
|
||||
}
|
||||
|
||||
private String printBinary(int i) {
|
||||
String s = Integer.toString(i, 2);
|
||||
|
||||
String pattern = "................................";
|
||||
|
||||
String temp1 = pattern.substring(0, pattern.length() - s.length());
|
||||
|
||||
String temp2 = temp1 + s;
|
||||
|
||||
return temp2.replace('0', '.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the permissions in a human-friendly format. For example, this method may return "CR-D" to
|
||||
* indicate the passed integer permits create, permits read, does not permit update, and permits delete.
|
||||
*
|
||||
* @param i the integer containing the mask which should be printed
|
||||
*
|
||||
* @return the human-friend formatted block
|
||||
*/
|
||||
public abstract String printPermissionsBlock(int i);
|
||||
|
||||
/**
|
||||
* Outputs the permissions in human-friendly format for the current <code>AbstractBasicAclEntry</code>'s
|
||||
* mask.
|
||||
*
|
||||
* @return the human-friendly formatted block for this instance
|
||||
*/
|
||||
public String printPermissionsBlock() {
|
||||
return printPermissionsBlock(this.mask);
|
||||
}
|
||||
|
||||
public void setAclObjectIdentity(AclObjectIdentity aclObjectIdentity) {
|
||||
this.aclObjectIdentity = aclObjectIdentity;
|
||||
}
|
||||
|
||||
public void setAclObjectParentIdentity(AclObjectIdentity aclObjectParentIdentity) {
|
||||
this.aclObjectParentIdentity = aclObjectParentIdentity;
|
||||
}
|
||||
|
||||
public void setMask(int mask) {
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
public void setRecipient(Object recipient) {
|
||||
this.recipient = recipient;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(getClass().getName());
|
||||
sb.append("[").append(aclObjectIdentity).append(",").append(recipient);
|
||||
sb.append("=").append(printPermissionsBlock(mask)).append(" ");
|
||||
sb.append(printBinary(mask)).append(" (");
|
||||
sb.append(mask).append(")").append("]");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public int togglePermission(int permissionToToggle) {
|
||||
this.mask ^= permissionToToggle;
|
||||
|
||||
if (Arrays.binarySearch(validPermissions, this.mask) < 0) {
|
||||
throw new IllegalArgumentException("Resulting permission set will be invalid.");
|
||||
} else {
|
||||
return this.mask;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* Interface representing the identity of an individual domain object instance.
|
||||
*
|
||||
* <P>
|
||||
* It should be noted that <code>AclObjectIdentity</code> instances are created
|
||||
* in various locations throughout the package. As
|
||||
* <code>AclObjectIdentity</code>s are used as the key for caching, it is
|
||||
* essential that implementations provide methods so that object-equality
|
||||
* rather than reference-equality can be relied upon by caches. In other
|
||||
* words, a cache can consider two <code>AclObjectIdentity</code>s equal if
|
||||
* <code>identity1.equals(identity2)</code>, rather than reference-equality of
|
||||
* <code>identity1==identity2</code>.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* In practical terms this means you must implement the standard
|
||||
* <code>java.lang.Object</code> methods shown below. Depending on your
|
||||
* cache's internal structure, you may also need to implement special
|
||||
* interfaces such as <code>java.util.Comparator</code> or
|
||||
* <code>java.lang.Comparable</code>.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public interface AclObjectIdentity extends Serializable {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Refer to the <code>java.lang.Object</code> documentation for the interface contract.
|
||||
*
|
||||
* @param obj to be compared
|
||||
*
|
||||
* @return <code>true</code> if the objects are equal, <code>false</code> otherwise
|
||||
*/
|
||||
boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* Refer to the <code>java.lang.Object</code> documentation for the interface contract.
|
||||
*
|
||||
* @return a hash code representation of this object
|
||||
*/
|
||||
int hashCode();
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
/**
|
||||
* Indicates a domain object instance is able to provide {@link
|
||||
* AclObjectIdentity} information.
|
||||
*
|
||||
* <P>
|
||||
* Domain objects must implement this interface if they wish to provide an
|
||||
* <code>AclObjectIdentity</code> rather than it being determined by relying
|
||||
* classes. Specifically, the {@link BasicAclProvider} detects and uses this
|
||||
* interface.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public interface AclObjectIdentityAware {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Retrieves the <code>AclObjectIdentity</code> for this instance.
|
||||
*
|
||||
* @return the ACL object identity for this instance (can never be <code>null</code>)
|
||||
*/
|
||||
AclObjectIdentity getAclObjectIdentity();
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
/**
|
||||
* Represents a data access object that can return the {@link BasicAclEntry}s
|
||||
* applying to a given ACL object identity.
|
||||
*
|
||||
* <P>
|
||||
* <code>BasicAclDao</code> implementations are responsible for interpreting a
|
||||
* given {@link AclObjectIdentity} and being able to lookup and return the
|
||||
* corresponding {@link BasicAclEntry}[]s.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* <code>BasicAclDao</code>s many, but are not required to, allow the backend
|
||||
* ACL repository to specify the class of <code>BasicAclEntry</code>
|
||||
* implementations that should be returned.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public interface BasicAclDao {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Obtains the ACLs that apply to the specified domain instance.<P>Does <b>not</b> perform caching, include
|
||||
* ACLs from any inheritance hierarchy or filter returned objects based on effective permissions. Implementations
|
||||
* are solely responsible for returning ACLs found in the ACL repository for the specified object identity.</p>
|
||||
*
|
||||
* @param aclObjectIdentity the domain object instance that ACL information is being requested for (never
|
||||
* <code>null</code>)
|
||||
*
|
||||
* @return the ACLs that apply (no <code>null</code>s are permitted in the array), or <code>null</code> if no ACLs
|
||||
* could be found for the specified ACL object identity
|
||||
*/
|
||||
BasicAclEntry[] getAcls(AclObjectIdentity aclObjectIdentity);
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
import org.springframework.security.acl.AclEntry;
|
||||
|
||||
|
||||
/**
|
||||
* Represents an entry in an access control list.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public interface BasicAclEntry extends AclEntry {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Indicates the domain object instance that is subject of this <code>BasicAclEntry</code>. This
|
||||
* information may be of interest to relying classes (voters and business methods) that wish to know the actual
|
||||
* origination of the ACL entry (so as to distinguish individual ACL entries from others contributed by the
|
||||
* inheritance hierarchy).
|
||||
*
|
||||
* @return the ACL object identity that is subject of this ACL entry (never <code>null</code>)
|
||||
*/
|
||||
AclObjectIdentity getAclObjectIdentity();
|
||||
|
||||
/**
|
||||
* Indicates any ACL parent of the domain object instance. This is used by <code>BasicAclProvider</code> to
|
||||
* walk the inheritance hierarchy. An domain object instance need <b>not</b> have a parent.
|
||||
*
|
||||
* @return the ACL object identity that is the parent of this ACL entry (may be <code>null</code> if no parent
|
||||
* should be consulted)
|
||||
*/
|
||||
AclObjectIdentity getAclObjectParentIdentity();
|
||||
|
||||
/**
|
||||
* Access control lists in this package are based on bit masking. The integer value of the bit mask can be
|
||||
* obtained from this method.
|
||||
*
|
||||
* @return the bit mask applicable to this ACL entry (zero indicates a bit mask where no permissions have been
|
||||
* granted)
|
||||
*/
|
||||
int getMask();
|
||||
|
||||
/**
|
||||
* A domain object instance will usually have multiple <code>BasicAclEntry</code>s. Each separate
|
||||
* <code>BasicAclEntry</code> applies to a particular "recipient". Typical examples of recipients include (but do
|
||||
* not necessarily have to include) usernames, role names, complex granted authorities etc.<P><B>It is
|
||||
* essential that only one <code>BasicAclEntry</code> exists for a given recipient</B>. Otherwise conflicts as to
|
||||
* the mask that should apply to a given recipient will occur.</p>
|
||||
* <P>This method indicates which recipient this <code>BasicAclEntry</code> applies to. The returned
|
||||
* object type will vary depending on the type of recipient. For instance, it might be a <code>String</code>
|
||||
* containing a username, or a <code>GrantedAuthorityImpl</code> containing a complex granted authority that is
|
||||
* being granted the permissions contained in this access control entry. The {@link EffectiveAclsResolver} and
|
||||
* {@link BasicAclProvider#getAcls(Object,org.springframework.security.Authentication)} can process the different recipient
|
||||
* types and return only those that apply to a specified <code>Authentication</code> object.</p>
|
||||
*
|
||||
* @return the recipient of this access control list entry (never <code>null</code>)
|
||||
*/
|
||||
Object getRecipient();
|
||||
|
||||
/**
|
||||
* Determine if the mask of this entry includes this permission or not
|
||||
*
|
||||
* @param permissionToCheck
|
||||
*
|
||||
* @return if the entry's mask includes this permission
|
||||
*/
|
||||
boolean isPermitted(int permissionToCheck);
|
||||
|
||||
/**
|
||||
* This setter should <B>only</B> be used by DAO implementations.
|
||||
*
|
||||
* @param aclObjectIdentity an object which can be used to uniquely identify the domain object instance subject of
|
||||
* this ACL entry
|
||||
*/
|
||||
void setAclObjectIdentity(AclObjectIdentity aclObjectIdentity);
|
||||
|
||||
/**
|
||||
* This setter should <B>only</B> be used by DAO implementations.
|
||||
*
|
||||
* @param aclObjectParentIdentity an object which represents the parent of the domain object instance subject of
|
||||
* this ACL entry, or <code>null</code> if either the domain object instance has no parent or its parent
|
||||
* should be not used to compute an inheritance hierarchy
|
||||
*/
|
||||
void setAclObjectParentIdentity(AclObjectIdentity aclObjectParentIdentity);
|
||||
|
||||
/**
|
||||
* This setter should <B>only</B> be used by DAO implementations.
|
||||
*
|
||||
* @param mask the integer representing the permissions bit mask
|
||||
*/
|
||||
void setMask(int mask);
|
||||
|
||||
/**
|
||||
* This setter should <B>only</B> be used by DAO implementations.
|
||||
*
|
||||
* @param recipient a representation of the recipient of this ACL entry that makes sense to an
|
||||
* <code>EffectiveAclsResolver</code> implementation
|
||||
*/
|
||||
void setRecipient(Object recipient);
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
/**
|
||||
* Provides a cache of {@link BasicAclEntry} objects.
|
||||
*
|
||||
* <P>
|
||||
* Implementations should provide appropriate methods to set their cache
|
||||
* parameters (eg time-to-live) and/or force removal of entities before their
|
||||
* normal expiration. These are not part of the
|
||||
* <code>BasicAclEntryCache</code> interface contract because they vary
|
||||
* depending on the type of caching system used (eg in-memory vs disk vs
|
||||
* cluster vs hybrid).
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public interface BasicAclEntryCache {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Obtains an array of {@link BasicAclEntry}s from the cache.
|
||||
*
|
||||
* @param aclObjectIdentity which should be obtained from the cache
|
||||
*
|
||||
* @return any applicable <code>BasicAclEntry</code>s (no <code>null</code>s are permitted in the returned array)
|
||||
* or <code>null</code> if the object identity could not be found or if the cache entry has expired
|
||||
*/
|
||||
BasicAclEntry[] getEntriesFromCache(AclObjectIdentity aclObjectIdentity);
|
||||
|
||||
/**
|
||||
* Places an array of {@link BasicAclEntry}s in the cache.<P>No <code>null</code>s are allowed in the
|
||||
* passed array. If any <code>null</code> is passed, the implementation may throw an exception.</p>
|
||||
*
|
||||
* @param basicAclEntry the ACL entries to cache (the key will be extracted from the {@link
|
||||
* BasicAclEntry#getAclObjectIdentity()} method
|
||||
*/
|
||||
void putEntriesInCache(BasicAclEntry[] basicAclEntry);
|
||||
|
||||
/**
|
||||
* Removes all ACL entries related to an {@link AclObjectIdentity} from the cache.
|
||||
*
|
||||
* @param aclObjectIdentity which should be removed from the cache
|
||||
*/
|
||||
void removeEntriesFromCache(AclObjectIdentity aclObjectIdentity);
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a more extensive data access object
|
||||
* for {@link BasicAclEntry}s.
|
||||
*
|
||||
* <p>
|
||||
* <code>BasicAclExtendedDao</code> implementations are responsible for interpreting a
|
||||
* a given {@link AclObjectIdentity}.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public interface BasicAclExtendedDao extends BasicAclDao {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Changes the permission mask assigned to the <code>BasicAclEntry</code> associated with the specified
|
||||
* <code>AclObjectIdentity</code> and recipient <code>Object</code>.
|
||||
*
|
||||
* @param aclObjectIdentity to locate the relevant <code>BasicAclEntry</code>
|
||||
* @param recipient to locate the relevant <code>BasicAclEntry</code>
|
||||
* @param newMask indicating the new permission
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
void changeMask(AclObjectIdentity aclObjectIdentity, Object recipient, Integer newMask)
|
||||
throws DataAccessException;
|
||||
|
||||
void create(BasicAclEntry basicAclEntry) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Deletes <b>all</b> entries associated with the specified <code>AclObjectIdentity</code>.
|
||||
*
|
||||
* @param aclObjectIdentity to delete, including any <code>BasicAclEntry</code>s
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
void delete(AclObjectIdentity aclObjectIdentity)
|
||||
throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Deletes the <code>BasicAclEntry</code> associated with the specified <code>AclObjectIdentity</code> and
|
||||
* recipient <code>Object</code>.
|
||||
*
|
||||
* @param aclObjectIdentity to delete
|
||||
* @param recipient to delete
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
void delete(AclObjectIdentity aclObjectIdentity, Object recipient)
|
||||
throws DataAccessException;
|
||||
}
|
@ -1,345 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
|
||||
import org.springframework.security.acl.AclEntry;
|
||||
import org.springframework.security.acl.AclProvider;
|
||||
import org.springframework.security.acl.basic.cache.NullAclEntryCache;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves access control lists (ACL) entries for domain object instances from a data access object (DAO).
|
||||
* <p>
|
||||
* This implementation will provide ACL lookup services for any object that it can determine the {@link
|
||||
* AclObjectIdentity} for by calling the {@link #obtainIdentity(Object)} method. Subclasses can override this method
|
||||
* if they only want the <code>BasicAclProvider</code> responding to particular domain object instances.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>BasicAclProvider</code> will walk an inheritance hierarchy if a <code>BasicAclEntry</code> returned by
|
||||
* the DAO indicates it has a parent. NB: inheritance occurs at a <i>domain instance object</i> level. It does not
|
||||
* occur at an ACL recipient level. This means <b>all</b><code>BasicAclEntry</code>s for a given domain instance
|
||||
* object <b>must</b> have the <b>same</b> parent identity, or <b>all</b><code>BasicAclEntry</code>s must have
|
||||
* <code>null</code> as their parent identity.
|
||||
* </p>
|
||||
* <p>
|
||||
* A cache should be used. This is provided by the {@link BasicAclEntryCache}. <code>BasicAclProvider</code> by
|
||||
* default is setup to use the {@link NullAclEntryCache}, which performs no caching.
|
||||
* </p>
|
||||
* <p>To implement the {@link #getAcls(Object, Authentication)} method, <code>BasicAclProvider</code> requires a
|
||||
* {@link EffectiveAclsResolver} to be configured against it. By default the {@link
|
||||
* GrantedAuthorityEffectiveAclsResolver} is used.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public class BasicAclProvider implements AclProvider, InitializingBean {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(BasicAclProvider.class);
|
||||
|
||||
/** Marker added to the cache to indicate an AclObjectIdentity has no corresponding BasicAclEntry[]s */
|
||||
private static final String RECIPIENT_FOR_CACHE_EMPTY = "RESERVED_RECIPIENT_NOBODY";
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
/** Must be set to an appropriate data access object. Defaults to <code>null</code>. */
|
||||
private BasicAclDao basicAclDao;
|
||||
private BasicAclEntryCache basicAclEntryCache = new NullAclEntryCache();
|
||||
private Class defaultAclObjectIdentityClass = NamedEntityObjectIdentity.class;
|
||||
private Class restrictSupportToClass = null;
|
||||
private EffectiveAclsResolver effectiveAclsResolver = new GrantedAuthorityEffectiveAclsResolver();
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
Assert.notNull(basicAclDao, "basicAclDao required");
|
||||
Assert.notNull(basicAclEntryCache, "basicAclEntryCache required");
|
||||
Assert.notNull(basicAclEntryCache, "basicAclEntryCache required");
|
||||
Assert.notNull(effectiveAclsResolver, "effectiveAclsResolver required");
|
||||
Assert.notNull(defaultAclObjectIdentityClass, "defaultAclObjectIdentityClass required");
|
||||
Assert.isTrue(AclObjectIdentity.class.isAssignableFrom(this.defaultAclObjectIdentityClass),
|
||||
"defaultAclObjectIdentityClass must implement AclObjectIdentity");
|
||||
|
||||
try {
|
||||
Constructor constructor = defaultAclObjectIdentityClass.getConstructor(new Class[] {Object.class});
|
||||
} catch (NoSuchMethodException nsme) {
|
||||
throw new IllegalArgumentException(
|
||||
"defaultAclObjectIdentityClass must provide a constructor that accepts the domain object instance!");
|
||||
}
|
||||
}
|
||||
|
||||
public AclEntry[] getAcls(Object domainInstance) {
|
||||
Map map = new HashMap();
|
||||
|
||||
AclObjectIdentity aclIdentity = obtainIdentity(domainInstance);
|
||||
|
||||
Assert.notNull(aclIdentity, "domainInstance is not supported by this provider");
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Looking up: " + aclIdentity.toString());
|
||||
}
|
||||
|
||||
BasicAclEntry[] instanceAclEntries = lookup(aclIdentity);
|
||||
|
||||
// Exit if there is no ACL information or parent for this instance
|
||||
if (instanceAclEntries == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Add the leaf objects to the Map, keyed on recipient
|
||||
for (int i = 0; i < instanceAclEntries.length; i++) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Explicit add: " + instanceAclEntries[i].toString());
|
||||
}
|
||||
|
||||
map.put(instanceAclEntries[i].getRecipient(), instanceAclEntries[i]);
|
||||
}
|
||||
|
||||
AclObjectIdentity parent = instanceAclEntries[0].getAclObjectParentIdentity();
|
||||
|
||||
while (parent != null) {
|
||||
BasicAclEntry[] parentAclEntries = lookup(parent);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Parent lookup: " + parent.toString());
|
||||
}
|
||||
|
||||
// Exit loop if parent couldn't be found (unexpected condition)
|
||||
if (parentAclEntries == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Parent could not be found in ACL repository");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Now add each _NEW_ recipient to the list
|
||||
for (int i = 0; i < parentAclEntries.length; i++) {
|
||||
if (!map.containsKey(parentAclEntries[i].getRecipient())) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Added parent to map: " + parentAclEntries[i].toString());
|
||||
}
|
||||
|
||||
map.put(parentAclEntries[i].getRecipient(), parentAclEntries[i]);
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Did NOT add parent to map: " + parentAclEntries[i].toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare for next iteration of while loop
|
||||
parent = parentAclEntries[0].getAclObjectParentIdentity();
|
||||
}
|
||||
|
||||
Collection collection = map.values();
|
||||
|
||||
return (AclEntry[]) collection.toArray(new AclEntry[] {});
|
||||
}
|
||||
|
||||
public AclEntry[] getAcls(Object domainInstance, Authentication authentication) {
|
||||
AclEntry[] allAcls = (AclEntry[]) this.getAcls(domainInstance);
|
||||
|
||||
return this.effectiveAclsResolver.resolveEffectiveAcls(allAcls, authentication);
|
||||
}
|
||||
|
||||
public BasicAclDao getBasicAclDao() {
|
||||
return basicAclDao;
|
||||
}
|
||||
|
||||
public BasicAclEntryCache getBasicAclEntryCache() {
|
||||
return basicAclEntryCache;
|
||||
}
|
||||
|
||||
public Class getDefaultAclObjectIdentityClass() {
|
||||
return defaultAclObjectIdentityClass;
|
||||
}
|
||||
|
||||
public EffectiveAclsResolver getEffectiveAclsResolver() {
|
||||
return effectiveAclsResolver;
|
||||
}
|
||||
|
||||
public Class getRestrictSupportToClass() {
|
||||
return restrictSupportToClass;
|
||||
}
|
||||
|
||||
private BasicAclEntry[] lookup(AclObjectIdentity aclObjectIdentity) {
|
||||
BasicAclEntry[] result = basicAclEntryCache.getEntriesFromCache(aclObjectIdentity);
|
||||
|
||||
if (result != null) {
|
||||
if (result[0].getRecipient().equals(RECIPIENT_FOR_CACHE_EMPTY)) {
|
||||
return null;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result = basicAclDao.getAcls(aclObjectIdentity);
|
||||
|
||||
if (result == null) {
|
||||
SimpleAclEntry[] emptyAclEntries = {
|
||||
new SimpleAclEntry(RECIPIENT_FOR_CACHE_EMPTY, aclObjectIdentity, null, 0)
|
||||
};
|
||||
basicAclEntryCache.putEntriesInCache(emptyAclEntries);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
basicAclEntryCache.putEntriesInCache(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method looks up the <code>AclObjectIdentity</code> of a passed domain object instance.<P>This
|
||||
* implementation attempts to obtain the <code>AclObjectIdentity</code> via reflection inspection of the class for
|
||||
* the {@link AclObjectIdentityAware} interface. If this fails, an attempt is made to construct a {@link
|
||||
* #getDefaultAclObjectIdentityClass()} object by passing the domain instance object into its constructor.</p>
|
||||
*
|
||||
* @param domainInstance the domain object instance (never <code>null</code>)
|
||||
*
|
||||
* @return an ACL object identity, or <code>null</code> if one could not be obtained
|
||||
*/
|
||||
protected AclObjectIdentity obtainIdentity(Object domainInstance) {
|
||||
if (domainInstance instanceof AclObjectIdentityAware) {
|
||||
AclObjectIdentityAware aclObjectIdentityAware = (AclObjectIdentityAware) domainInstance;
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("domainInstance: " + domainInstance + " cast to AclObjectIdentityAware");
|
||||
}
|
||||
|
||||
return aclObjectIdentityAware.getAclObjectIdentity();
|
||||
}
|
||||
|
||||
try {
|
||||
Constructor constructor = defaultAclObjectIdentityClass.getConstructor(new Class[] {Object.class});
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("domainInstance: " + domainInstance
|
||||
+ " attempting to pass to constructor: " + constructor);
|
||||
}
|
||||
|
||||
return (AclObjectIdentity) constructor.newInstance(new Object[] {domainInstance});
|
||||
} catch (Exception ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Error attempting construction of " + defaultAclObjectIdentityClass + ": "
|
||||
+ ex.getMessage(), ex);
|
||||
|
||||
if (ex.getCause() != null) {
|
||||
logger.debug("Cause: " + ex.getCause().getMessage(), ex.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setBasicAclDao(BasicAclDao basicAclDao) {
|
||||
this.basicAclDao = basicAclDao;
|
||||
}
|
||||
|
||||
public void setBasicAclEntryCache(BasicAclEntryCache basicAclEntryCache) {
|
||||
this.basicAclEntryCache = basicAclEntryCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows selection of the <code>AclObjectIdentity</code> class that an attempt should be made to construct
|
||||
* if the passed object does not implement <code>AclObjectIdentityAware</code>.<P>NB: Any
|
||||
* <code>defaultAclObjectIdentityClass</code><b>must</b> provide a public constructor that accepts an
|
||||
* <code>Object</code>. Otherwise it is not possible for the <code>BasicAclProvider</code> to try to create the
|
||||
* <code>AclObjectIdentity</code> instance at runtime.</p>
|
||||
*
|
||||
* @param defaultAclObjectIdentityClass
|
||||
*/
|
||||
public void setDefaultAclObjectIdentityClass(Class defaultAclObjectIdentityClass) {
|
||||
this.defaultAclObjectIdentityClass = defaultAclObjectIdentityClass;
|
||||
}
|
||||
|
||||
public void setEffectiveAclsResolver(EffectiveAclsResolver effectiveAclsResolver) {
|
||||
this.effectiveAclsResolver = effectiveAclsResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to a value other than <code>null</code>, the {@link #supports(Object)} method will <b>only</b>
|
||||
* support the indicates class. This is useful if you wish to wire multiple <code>BasicAclProvider</code>s in a
|
||||
* list of <code>AclProviderManager.providers</code> but only have particular instances respond to particular
|
||||
* domain object types.
|
||||
*
|
||||
* @param restrictSupportToClass the class to restrict this <code>BasicAclProvider</code> to service request for,
|
||||
* or <code>null</code> (the default) if the <code>BasicAclProvider</code> should respond to every class
|
||||
* presented
|
||||
*/
|
||||
public void setRestrictSupportToClass(Class restrictSupportToClass) {
|
||||
this.restrictSupportToClass = restrictSupportToClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates support for the passed object.<p>An object will only be supported if it (i) is allowed to be
|
||||
* supported as defined by the {@link #setRestrictSupportToClass(Class)} method, <b>and</b> (ii) if an
|
||||
* <code>AclObjectIdentity</code> is returned by {@link #obtainIdentity(Object)} for that object.</p>
|
||||
*
|
||||
* @param domainInstance the instance to check
|
||||
*
|
||||
* @return <code>true</code> if this provider supports the passed object, <code>false</code> otherwise
|
||||
*/
|
||||
public boolean supports(Object domainInstance) {
|
||||
if (domainInstance == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("domainInstance is null");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((restrictSupportToClass != null) && !restrictSupportToClass.isAssignableFrom(domainInstance.getClass())) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("domainInstance not instance of " + restrictSupportToClass);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (obtainIdentity(domainInstance) == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("obtainIdentity returned null");
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("obtainIdentity returned " + obtainIdentity(domainInstance));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
|
||||
import org.springframework.security.acl.AclEntry;
|
||||
|
||||
|
||||
/**
|
||||
* Determines the ACLs that are effective for a given
|
||||
* <code>Authentication</code> object.
|
||||
*
|
||||
* <P>
|
||||
* Implementations will vary depending on their ability to interpret the
|
||||
* "recipient" object types contained in {@link BasicAclEntry} instances, and
|
||||
* how those recipient object types correspond to
|
||||
* <code>Authentication</code>-presented principals and granted authorities.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* Implementations should not filter the resulting ACL list from lower-order
|
||||
* permissions. So if a resulting ACL list grants a "read" permission, an
|
||||
* "unlimited" permission and a "zero" permission (due to the effective ACLs
|
||||
* for different granted authorities held by the <code>Authentication</code>
|
||||
* object), all three permissions would be returned as distinct
|
||||
* <code>BasicAclEntry</code> instances. It is the responsibility of the
|
||||
* relying classes (voters and business methods) to ignore or handle
|
||||
* lower-order permissions in a business logic dependent manner.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public interface EffectiveAclsResolver {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Determines the ACLs that apply to the presented <code>Authentication</code> object.
|
||||
*
|
||||
* @param allAcls every ACL assigned to a domain object instance
|
||||
* @param filteredBy the principal (populated with <code>GrantedAuthority</code>s along with any other members that
|
||||
* relate to role or group membership) that effective ACLs should be returned for
|
||||
*
|
||||
* @return the ACLs that apply to the presented principal, or <code>null</code> if there are none after filtering
|
||||
*/
|
||||
AclEntry[] resolveEffectiveAcls(AclEntry[] allAcls, Authentication filteredBy);
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.GrantedAuthority;
|
||||
|
||||
import org.springframework.security.acl.AclEntry;
|
||||
|
||||
import org.springframework.security.userdetails.UserDetails;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
/**
|
||||
* Simple implementation of {@link EffectiveAclsResolver}.<P>This implementation does not need to understand the
|
||||
* "recipient" types presented in a <code>BasicAclEntry</code> because it merely delegates to the detected {@link
|
||||
* Authentication#getPrincipal()} or {@link Authentication#getAuthorities()}. The principal object or granted
|
||||
* authorities object has its <code>Object.equals(recipient)</code> method called to make the decision as to whether
|
||||
* the recipient in the <code>BasicAclEntry</code> is the same as the principal or granted authority.
|
||||
* <p>
|
||||
* This class should prove an adequate ACLs resolver if you're using standard Spring Security classes. This is
|
||||
* because the typical <code>Authentication</code> token is <code>UsernamePasswordAuthenticationToken</code>, which
|
||||
* for its <code>principal</code> is usually a <code>String</code>. The <code>GrantedAuthorityImpl</code> is typically
|
||||
* used for granted authorities, which tests for equality based on a <code>String</code>. This means
|
||||
* <code>BasicAclDao</code>s simply need to return a <code>String</code> to represent the recipient. If you use
|
||||
* non-<code>String</code> objects, you will probably require an alternative <code>EffectiveAclsResolver</code>.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public class GrantedAuthorityEffectiveAclsResolver implements EffectiveAclsResolver {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(GrantedAuthorityEffectiveAclsResolver.class);
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public AclEntry[] resolveEffectiveAcls(AclEntry[] allAcls, Authentication filteredBy) {
|
||||
if ((allAcls == null) || (allAcls.length == 0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List list = new Vector();
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Locating AclEntry[]s (from set of " + ((allAcls == null) ? 0 : allAcls.length)
|
||||
+ ") that apply to Authentication: " + filteredBy);
|
||||
}
|
||||
|
||||
for (int i = 0; i < allAcls.length; i++) {
|
||||
if (!(allAcls[i] instanceof BasicAclEntry)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Object recipient = ((BasicAclEntry) allAcls[i]).getRecipient();
|
||||
|
||||
// Allow the Authentication's getPrincipal to decide whether
|
||||
// the presented recipient is "equal" (allows BasicAclDaos to
|
||||
// return Strings rather than proper objects in simple cases)
|
||||
if (filteredBy.getPrincipal().equals(recipient)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Principal matches AclEntry recipient: " + recipient);
|
||||
}
|
||||
|
||||
list.add(allAcls[i]);
|
||||
} else if (filteredBy.getPrincipal() instanceof UserDetails
|
||||
&& ((UserDetails) filteredBy.getPrincipal()).getUsername().equals(recipient)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Principal (from UserDetails) matches AclEntry recipient: " + recipient);
|
||||
}
|
||||
|
||||
list.add(allAcls[i]);
|
||||
} else {
|
||||
// No direct match against principal; try each authority.
|
||||
// As with the principal, allow each of the Authentication's
|
||||
// granted authorities to decide whether the presented
|
||||
// recipient is "equal"
|
||||
List<GrantedAuthority >authorities = filteredBy.getAuthorities();
|
||||
|
||||
if ((authorities == null) || (authorities.size() == 0)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Did not match principal and there are no granted authorities, "
|
||||
+ "so cannot compare with recipient: " + recipient);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int k = 0; k < authorities.size(); k++) {
|
||||
if (authorities.get(k).equals(recipient)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("GrantedAuthority: " + authorities.get(k) + " matches recipient: " + recipient);
|
||||
}
|
||||
|
||||
list.add(allAcls[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return null if appropriate (as per interface contract)
|
||||
if (list.size() > 0) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Returning effective AclEntry array with " + list.size() + " elements");
|
||||
}
|
||||
|
||||
return (BasicAclEntry[]) list.toArray(new BasicAclEntry[] {});
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Returning null AclEntry array as zero effective AclEntrys found");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,153 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
|
||||
/**
|
||||
* Simple implementation of {@link AclObjectIdentity}.<P>Uses <code>String</code>s to store the identity of the
|
||||
* domain object instance. Also offers a constructor that uses reflection to build the identity information.</p>
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public class NamedEntityObjectIdentity implements AclObjectIdentity {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private String classname;
|
||||
private String id;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public NamedEntityObjectIdentity(String classname, String id) {
|
||||
Assert.hasText(classname, "classname required");
|
||||
Assert.hasText(id, "id required");
|
||||
this.classname = classname;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the <code>NamedEntityObjectIdentity</code> based on the passed
|
||||
* object instance. The passed object must provide a <code>getId()</code>
|
||||
* method, otherwise an exception will be thrown.
|
||||
*
|
||||
* @param object the domain object instance to create an identity for
|
||||
*
|
||||
* @throws IllegalAccessException
|
||||
* @throws InvocationTargetException
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
public NamedEntityObjectIdentity(Object object) throws IllegalAccessException, InvocationTargetException {
|
||||
Assert.notNull(object, "object cannot be null");
|
||||
|
||||
this.classname = (getPackageName(object.getClass().getName()) == null)
|
||||
? ClassUtils.getShortName(object.getClass())
|
||||
: (getPackageName(object.getClass().getName()) + "." + ClassUtils.getShortName(object.getClass()));
|
||||
|
||||
Class clazz = object.getClass();
|
||||
|
||||
try {
|
||||
Method method = clazz.getMethod("getId", new Class[] {});
|
||||
Object result = method.invoke(object, new Object[] {});
|
||||
this.id = result.toString();
|
||||
} catch (NoSuchMethodException nsme) {
|
||||
throw new IllegalArgumentException("Object of class '" + clazz
|
||||
+ "' does not provide the required getId() method: " + object);
|
||||
}
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Important so caching operates properly.<P>Considers an object of the same class equal if it has the same
|
||||
* <code>classname</code> and <code>id</code> properties.</p>
|
||||
*
|
||||
* @param arg0 object to compare
|
||||
*
|
||||
* @return <code>true</code> if the presented object matches this object
|
||||
*/
|
||||
public boolean equals(Object arg0) {
|
||||
if (arg0 == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(arg0 instanceof NamedEntityObjectIdentity)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NamedEntityObjectIdentity other = (NamedEntityObjectIdentity) arg0;
|
||||
|
||||
if (this.getId().equals(other.getId()) && this.getClassname().equals(other.getClassname())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the classname portion of the object identity.
|
||||
*
|
||||
* @return the classname (never <code>null</code>)
|
||||
*/
|
||||
public String getClassname() {
|
||||
return classname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the instance identity portion of the object identity.
|
||||
*
|
||||
* @return the instance identity (never <code>null</code>)
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
private String getPackageName(String className) {
|
||||
Assert.hasLength(className, "class name must not be empty");
|
||||
|
||||
int lastDotIndex = className.lastIndexOf(".");
|
||||
|
||||
if (lastDotIndex == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return className.substring(0, lastDotIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Important so caching operates properly.
|
||||
*
|
||||
* @return the hash of the classname and id
|
||||
*/
|
||||
public int hashCode() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(this.classname).append(this.id);
|
||||
|
||||
return sb.toString().hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(this.getClass().getName()).append("[");
|
||||
sb.append("Classname: ").append(this.classname);
|
||||
sb.append("; Identity: ").append(this.id).append("]");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,151 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Stores some privileges typical of a domain object.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public class SimpleAclEntry extends AbstractBasicAclEntry {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(SimpleAclEntry.class);
|
||||
|
||||
// Base permissions we permit
|
||||
public static final int NOTHING = 0;
|
||||
public static final int ADMINISTRATION = (int) Math.pow(2, 0);
|
||||
public static final int READ = (int) Math.pow(2, 1);
|
||||
public static final int WRITE = (int) Math.pow(2, 2);
|
||||
public static final int CREATE = (int) Math.pow(2, 3);
|
||||
public static final int DELETE = (int) Math.pow(2, 4);
|
||||
|
||||
// Combinations of base permissions we permit
|
||||
public static final int READ_WRITE_CREATE_DELETE = READ | WRITE | CREATE | DELETE;
|
||||
public static final int READ_WRITE_CREATE = READ | WRITE | CREATE;
|
||||
public static final int READ_WRITE = READ | WRITE;
|
||||
public static final int READ_WRITE_DELETE = READ | WRITE | DELETE;
|
||||
|
||||
// Array required by the abstract superclass via getValidPermissions()
|
||||
private static final int[] VALID_PERMISSIONS = {
|
||||
NOTHING, ADMINISTRATION, READ, WRITE, CREATE, DELETE, READ_WRITE_CREATE_DELETE, READ_WRITE_CREATE,
|
||||
READ_WRITE, READ_WRITE_DELETE
|
||||
};
|
||||
|
||||
private static final String[] VALID_PERMISSIONS_AS_STRING = {
|
||||
"NOTHING", "ADMINISTRATION", "READ", "WRITE", "CREATE", "DELETE", "READ_WRITE_CREATE_DELETE",
|
||||
"READ_WRITE_CREATE", "READ_WRITE", "READ_WRITE_DELETE" };
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* Allows {@link BasicAclDao} implementations to construct this object
|
||||
* using <code>newInstance()</code>.
|
||||
*
|
||||
* <P>
|
||||
* Normal classes should <B>not</B> use this default constructor.
|
||||
* </p>
|
||||
*/
|
||||
public SimpleAclEntry() {
|
||||
super();
|
||||
}
|
||||
|
||||
public SimpleAclEntry(Object recipient, AclObjectIdentity aclObjectIdentity,
|
||||
AclObjectIdentity aclObjectParentIdentity, int mask) {
|
||||
super(recipient, aclObjectIdentity, aclObjectParentIdentity, mask);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* @return a copy of the permissions array, changes to the values won't affect this class.
|
||||
*/
|
||||
public int[] getValidPermissions() {
|
||||
return (int[]) VALID_PERMISSIONS.clone();
|
||||
}
|
||||
|
||||
public String printPermissionsBlock(int i) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
if (isPermitted(i, ADMINISTRATION)) {
|
||||
sb.append('A');
|
||||
} else {
|
||||
sb.append('-');
|
||||
}
|
||||
|
||||
if (isPermitted(i, READ)) {
|
||||
sb.append('R');
|
||||
} else {
|
||||
sb.append('-');
|
||||
}
|
||||
|
||||
if (isPermitted(i, WRITE)) {
|
||||
sb.append('W');
|
||||
} else {
|
||||
sb.append('-');
|
||||
}
|
||||
|
||||
if (isPermitted(i, CREATE)) {
|
||||
sb.append('C');
|
||||
} else {
|
||||
sb.append('-');
|
||||
}
|
||||
|
||||
if (isPermitted(i, DELETE)) {
|
||||
sb.append('D');
|
||||
} else {
|
||||
sb.append('-');
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a permission {@link String} literal and return associated value.
|
||||
*
|
||||
* @param permission one of the field names that represent a permission: <code>ADMINISTRATION</code>,
|
||||
* <code>READ</code>, <code>WRITE</code>,...
|
||||
* @return the value associated to that permission
|
||||
* @throws IllegalArgumentException if argument is not a valid permission
|
||||
*/
|
||||
public static int parsePermission(String permission) {
|
||||
for (int i = 0; i < VALID_PERMISSIONS_AS_STRING.length; i++) {
|
||||
if (VALID_PERMISSIONS_AS_STRING[i].equalsIgnoreCase(permission)) {
|
||||
return VALID_PERMISSIONS[i];
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Permission provided does not exist: " + permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a list of permission {@link String} literals and return associated values.
|
||||
*
|
||||
* @param permissions array with permissions as {@link String}
|
||||
* @see #parsePermission(String) for valid values
|
||||
*/
|
||||
public static int[] parsePermissions(String[] permissions) {
|
||||
int[] requirepermissionAsIntArray = new int[permissions.length];
|
||||
for (int i = 0; i < requirepermissionAsIntArray.length; i++) {
|
||||
requirepermissionAsIntArray[i] = parsePermission(permissions[i]);
|
||||
}
|
||||
return requirepermissionAsIntArray;
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic.cache;
|
||||
|
||||
import org.springframework.security.acl.basic.BasicAclEntry;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* Used by {@link EhCacheBasedAclEntryCache} to store the array of <code>BasicAclEntry</code>s in the cache.<P>This
|
||||
* is necessary because caches store a single object per key, not an array.</p>
|
||||
* <P>This class uses value object semantics. ie: construction-based initialisation without any setters for the
|
||||
* properties.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public class BasicAclEntryHolder implements Serializable {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private BasicAclEntry[] basicAclEntries;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* Constructs the <code>BasicAclEntryHolder</code>.
|
||||
*
|
||||
* @param aclEntries to cache (any <code>null</code>s will cause an
|
||||
* exception, which should not be a problem as the contract for
|
||||
* <code>BasicAclEntryCache</code> allows exceptions if
|
||||
* <code>null</code>s are presented)
|
||||
*
|
||||
* @throws IllegalArgumentException if a <code>null</code> exists anywhere
|
||||
* in the <code>aclEntries</code> or if a <code>null</code> is
|
||||
* passed to the constructor
|
||||
*/
|
||||
public BasicAclEntryHolder(BasicAclEntry[] aclEntries) {
|
||||
Assert.notNull(aclEntries, "aclEntries cannot be null");
|
||||
|
||||
for (int i = 0; i < aclEntries.length; i++) {
|
||||
Assert.notNull(aclEntries[i], "aclEntries cannot be null");
|
||||
}
|
||||
|
||||
this.basicAclEntries = aclEntries;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public BasicAclEntry[] getBasicAclEntries() {
|
||||
return basicAclEntries;
|
||||
}
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic.cache;
|
||||
|
||||
import net.sf.ehcache.CacheException;
|
||||
import net.sf.ehcache.Element;
|
||||
import net.sf.ehcache.Ehcache;
|
||||
|
||||
import org.springframework.security.acl.basic.AclObjectIdentity;
|
||||
import org.springframework.security.acl.basic.BasicAclEntry;
|
||||
import org.springframework.security.acl.basic.BasicAclEntryCache;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Caches <code>BasicAclEntry</code>s using a Spring IoC defined <A
|
||||
* HREF="http://ehcache.sourceforge.net">EHCACHE</a>.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public class EhCacheBasedAclEntryCache implements BasicAclEntryCache, InitializingBean {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(EhCacheBasedAclEntryCache.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private Ehcache cache;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(cache, "cache mandatory");
|
||||
}
|
||||
|
||||
public BasicAclEntry[] getEntriesFromCache(AclObjectIdentity aclObjectIdentity) {
|
||||
Element element = null;
|
||||
|
||||
try {
|
||||
element = cache.get(aclObjectIdentity);
|
||||
} catch (CacheException cacheException) {
|
||||
throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage());
|
||||
}
|
||||
|
||||
// Return null if cache element has expired or not found
|
||||
if (element == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Cache miss: " + aclObjectIdentity);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Cache hit: " + (element != null) + "; object: " + aclObjectIdentity);
|
||||
}
|
||||
|
||||
BasicAclEntryHolder holder = (BasicAclEntryHolder) element.getValue();
|
||||
|
||||
return holder.getBasicAclEntries();
|
||||
}
|
||||
|
||||
public void putEntriesInCache(BasicAclEntry[] basicAclEntry) {
|
||||
BasicAclEntryHolder holder = new BasicAclEntryHolder(basicAclEntry);
|
||||
Element element = new Element(basicAclEntry[0].getAclObjectIdentity(), holder);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Cache put: " + element.getKey());
|
||||
}
|
||||
|
||||
cache.put(element);
|
||||
}
|
||||
|
||||
public void removeEntriesFromCache(AclObjectIdentity aclObjectIdentity) {
|
||||
cache.remove(aclObjectIdentity);
|
||||
}
|
||||
|
||||
public Ehcache getCache() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
public void setCache(Ehcache cache) {
|
||||
this.cache = cache;
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic.cache;
|
||||
|
||||
import org.springframework.security.acl.basic.AclObjectIdentity;
|
||||
import org.springframework.security.acl.basic.BasicAclEntry;
|
||||
import org.springframework.security.acl.basic.BasicAclEntryCache;
|
||||
|
||||
|
||||
/**
|
||||
* Does not perform any caching.<P><B>Do not use in production settings</B>, as ACL queries are likely to be
|
||||
* extensive.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public class NullAclEntryCache implements BasicAclEntryCache {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* As nothing ever stored in the cache, will always return <code>null</code>.
|
||||
*
|
||||
* @param aclObjectIdentity ignored
|
||||
*
|
||||
* @return always <code>null</code>
|
||||
*/
|
||||
public BasicAclEntry[] getEntriesFromCache(AclObjectIdentity aclObjectIdentity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Meets method signature but doesn't store in any cache.
|
||||
*
|
||||
* @param basicAclEntry ignored
|
||||
*/
|
||||
public void putEntriesInCache(BasicAclEntry[] basicAclEntry) {}
|
||||
|
||||
/**
|
||||
* Meets method signature but doesn't remove from cache.
|
||||
*
|
||||
* @param aclObjectIdentity ignored
|
||||
*/
|
||||
public void removeEntriesFromCache(AclObjectIdentity aclObjectIdentity) {}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
Caches ACL information for the <code>BasicAclProvider</code>.
|
||||
</body>
|
||||
</html>
|
@ -1,400 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic.jdbc;
|
||||
|
||||
import org.springframework.security.acl.basic.AclObjectIdentity;
|
||||
import org.springframework.security.acl.basic.BasicAclDao;
|
||||
import org.springframework.security.acl.basic.BasicAclEntry;
|
||||
import org.springframework.security.acl.basic.NamedEntityObjectIdentity;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
|
||||
import org.springframework.jdbc.core.SqlParameter;
|
||||
import org.springframework.jdbc.core.support.JdbcDaoSupport;
|
||||
import org.springframework.jdbc.object.MappingSqlQuery;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves ACL details from a JDBC location.
|
||||
* <p>
|
||||
* A default database structure is assumed. This may be overridden by setting the default query strings to use.
|
||||
* If this does not provide enough flexibility, another strategy would be to subclass this class and override the
|
||||
* {@link MappingSqlQuery} instance used, via the {@link #initMappingSqlQueries()} extension point.
|
||||
* </p>
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
public static final String RECIPIENT_USED_FOR_INHERITENCE_MARKER = "___INHERITENCE_MARKER_ONLY___";
|
||||
public static final String DEF_ACLS_BY_OBJECT_IDENTITY_QUERY =
|
||||
"SELECT RECIPIENT, MASK FROM acl_permission WHERE acl_object_identity = ?";
|
||||
public static final String DEF_OBJECT_PROPERTIES_QUERY =
|
||||
"SELECT CHILD.ID, "
|
||||
+ "CHILD.OBJECT_IDENTITY, "
|
||||
+ "CHILD.ACL_CLASS, "
|
||||
+ "PARENT.OBJECT_IDENTITY as PARENT_OBJECT_IDENTITY "
|
||||
+ "FROM acl_object_identity as CHILD "
|
||||
+ "LEFT OUTER JOIN acl_object_identity as PARENT ON CHILD.parent_object=PARENT.id "
|
||||
+ "WHERE CHILD.object_identity = ?";
|
||||
private static final Log logger = LogFactory.getLog(JdbcDaoImpl.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
protected MappingSqlQuery aclsByObjectIdentity;
|
||||
protected MappingSqlQuery objectProperties;
|
||||
private String aclsByObjectIdentityQuery;
|
||||
private String objectPropertiesQuery;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public JdbcDaoImpl() {
|
||||
aclsByObjectIdentityQuery = DEF_ACLS_BY_OBJECT_IDENTITY_QUERY;
|
||||
objectPropertiesQuery = DEF_OBJECT_PROPERTIES_QUERY;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Responsible for covering a <code>AclObjectIdentity</code> to a <code>String</code> that can be located
|
||||
* in the RDBMS.
|
||||
*
|
||||
* @param aclObjectIdentity to locate
|
||||
*
|
||||
* @return the object identity as a <code>String</code>
|
||||
*/
|
||||
protected String convertAclObjectIdentityToString(AclObjectIdentity aclObjectIdentity) {
|
||||
// Ensure we can process this type of AclObjectIdentity
|
||||
Assert.isInstanceOf(NamedEntityObjectIdentity.class, aclObjectIdentity,
|
||||
"Only aclObjectIdentity of type NamedEntityObjectIdentity supported (was passed: " + aclObjectIdentity
|
||||
+ ")");
|
||||
|
||||
NamedEntityObjectIdentity neoi = (NamedEntityObjectIdentity) aclObjectIdentity;
|
||||
|
||||
// Compose the String we expect to find in the RDBMS
|
||||
return neoi.getClassname() + ":" + neoi.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an individual <code>BasicAclEntry</code> from the passed <code>AclDetailsHolder</code>s.<P>Guarantees
|
||||
* to never return <code>null</code> (exceptions are thrown in the event of any issues).</p>
|
||||
*
|
||||
* @param propertiesInformation mandatory information about which instance to create, the object identity, and the
|
||||
* parent object identity (<code>null</code> or empty <code>String</code>s prohibited for
|
||||
* <code>aclClass</code> and <code>aclObjectIdentity</code>
|
||||
* @param aclInformation optional information about the individual ACL record (if <code>null</code> only an
|
||||
* "inheritence marker" instance is returned which will include a recipient of {@link
|
||||
* #RECIPIENT_USED_FOR_INHERITENCE_MARKER} ; if not <code>null</code>, it is prohibited to present
|
||||
* <code>null</code> or an empty <code>String</code> for <code>recipient</code>)
|
||||
*
|
||||
* @return a fully populated instance suitable for use by external objects
|
||||
*
|
||||
* @throws IllegalArgumentException if the indicated ACL class could not be created
|
||||
*/
|
||||
private BasicAclEntry createBasicAclEntry(AclDetailsHolder propertiesInformation, AclDetailsHolder aclInformation) {
|
||||
BasicAclEntry entry;
|
||||
|
||||
try {
|
||||
entry = (BasicAclEntry) propertiesInformation.getAclClass().newInstance();
|
||||
} catch (InstantiationException ie) {
|
||||
throw new IllegalArgumentException(ie.getMessage());
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new IllegalArgumentException(iae.getMessage());
|
||||
}
|
||||
|
||||
entry.setAclObjectIdentity(propertiesInformation.getAclObjectIdentity());
|
||||
entry.setAclObjectParentIdentity(propertiesInformation.getAclObjectParentIdentity());
|
||||
|
||||
if (aclInformation == null) {
|
||||
// this is an inheritence marker instance only
|
||||
entry.setMask(0);
|
||||
entry.setRecipient(RECIPIENT_USED_FOR_INHERITENCE_MARKER);
|
||||
} else {
|
||||
// this is an individual ACL entry
|
||||
entry.setMask(aclInformation.getMask());
|
||||
entry.setRecipient(aclInformation.getRecipient());
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ACLs associated with the requested <code>AclObjectIdentity</code>.<P>The {@link
|
||||
* BasicAclEntry}s returned by this method will have <code>String</code>-based recipients. This will not be a
|
||||
* problem if you are using the <code>GrantedAuthorityEffectiveAclsResolver</code>, which is the default
|
||||
* configured against <code>BasicAclProvider</code>.</p>
|
||||
* <P>This method will only return ACLs for requests where the <code>AclObjectIdentity</code> is of type
|
||||
* {@link NamedEntityObjectIdentity}. Of course, you can subclass or replace this class and support your own
|
||||
* custom <code>AclObjectIdentity</code> types.</p>
|
||||
*
|
||||
* @param aclObjectIdentity for which ACL information is required (cannot be <code>null</code> and must be an
|
||||
* instance of <code>NamedEntityObjectIdentity</code>)
|
||||
*
|
||||
* @return the ACLs that apply (without any <code>null</code>s inside the array), or <code>null</code> if not found
|
||||
* or if an incompatible <code>AclObjectIdentity</code> was requested
|
||||
*/
|
||||
public BasicAclEntry[] getAcls(AclObjectIdentity aclObjectIdentity) {
|
||||
String aclObjectIdentityString;
|
||||
|
||||
try {
|
||||
aclObjectIdentityString = convertAclObjectIdentityToString(aclObjectIdentity);
|
||||
} catch (IllegalArgumentException unsupported) {
|
||||
return null; // pursuant to contract described in JavaDocs above
|
||||
}
|
||||
|
||||
// Lookup the object's main properties from the RDBMS (guaranteed no nulls)
|
||||
List objects = objectProperties.execute(aclObjectIdentityString);
|
||||
|
||||
if (objects.size() == 0) {
|
||||
// this is an unknown object identity string
|
||||
return null;
|
||||
}
|
||||
|
||||
// Cast to an object properties holder (there should only be one record)
|
||||
AclDetailsHolder propertiesInformation = (AclDetailsHolder) objects.get(0);
|
||||
|
||||
// Lookup the object's ACLs from RDBMS (guaranteed no nulls)
|
||||
List acls = aclsByObjectIdentity.execute(propertiesInformation.getForeignKeyId());
|
||||
|
||||
if (acls.size() == 0) {
|
||||
// return merely an inheritence marker (as we know about the object but it has no related ACLs)
|
||||
return new BasicAclEntry[] {createBasicAclEntry(propertiesInformation, null)};
|
||||
} else {
|
||||
// return the individual ACL instances
|
||||
AclDetailsHolder[] aclHolders = (AclDetailsHolder[]) acls.toArray(new AclDetailsHolder[] {});
|
||||
List toReturnAcls = new Vector();
|
||||
|
||||
for (int i = 0; i < aclHolders.length; i++) {
|
||||
toReturnAcls.add(createBasicAclEntry(propertiesInformation, aclHolders[i]));
|
||||
}
|
||||
|
||||
return (BasicAclEntry[]) toReturnAcls.toArray(new BasicAclEntry[] {});
|
||||
}
|
||||
}
|
||||
|
||||
public MappingSqlQuery getAclsByObjectIdentity() {
|
||||
return aclsByObjectIdentity;
|
||||
}
|
||||
|
||||
public String getAclsByObjectIdentityQuery() {
|
||||
return aclsByObjectIdentityQuery;
|
||||
}
|
||||
|
||||
public String getObjectPropertiesQuery() {
|
||||
return objectPropertiesQuery;
|
||||
}
|
||||
|
||||
protected void initDao() throws ApplicationContextException {
|
||||
initMappingSqlQueries();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension point to allow other MappingSqlQuery objects to be substituted in a subclass
|
||||
*/
|
||||
protected void initMappingSqlQueries() {
|
||||
setAclsByObjectIdentity(new AclsByObjectIdentityMapping(getDataSource()));
|
||||
setObjectProperties(new ObjectPropertiesMapping(getDataSource()));
|
||||
}
|
||||
|
||||
public void setAclsByObjectIdentity(MappingSqlQuery aclsByObjectIdentityQuery) {
|
||||
this.aclsByObjectIdentity = aclsByObjectIdentityQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the default query string used to retrieve ACLs based on object identity to be overriden, if
|
||||
* default table or column names need to be changed. The default query is {@link
|
||||
* #DEF_ACLS_BY_OBJECT_IDENTITY_QUERY}; when modifying this query, ensure that all returned columns are mapped
|
||||
* back to the same column names as in the default query.
|
||||
*
|
||||
* @param queryString The query string to set
|
||||
*/
|
||||
public void setAclsByObjectIdentityQuery(String queryString) {
|
||||
aclsByObjectIdentityQuery = queryString;
|
||||
}
|
||||
|
||||
public void setObjectProperties(MappingSqlQuery objectPropertiesQuery) {
|
||||
this.objectProperties = objectPropertiesQuery;
|
||||
}
|
||||
|
||||
public void setObjectPropertiesQuery(String queryString) {
|
||||
objectPropertiesQuery = queryString;
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
/**
|
||||
* Used to hold details of a domain object instance's properties, or an individual ACL entry.<P>Not all
|
||||
* properties will be set. The actual properties set will depend on which <code>MappingSqlQuery</code> creates the
|
||||
* object.</p>
|
||||
* <P>Does not enforce <code>null</code>s or empty <code>String</code>s as this is performed by the
|
||||
* <code>MappingSqlQuery</code> objects (or preferably the backend RDBMS via schema constraints).</p>
|
||||
*/
|
||||
protected final class AclDetailsHolder {
|
||||
private AclObjectIdentity aclObjectIdentity;
|
||||
private AclObjectIdentity aclObjectParentIdentity;
|
||||
private Class aclClass;
|
||||
private Object recipient;
|
||||
private int mask;
|
||||
private long foreignKeyId;
|
||||
|
||||
/**
|
||||
* Record details of an individual ACL entry (usually from the
|
||||
* ACL_PERMISSION table)
|
||||
*
|
||||
* @param recipient the recipient
|
||||
* @param mask the integer to be masked
|
||||
*/
|
||||
public AclDetailsHolder(Object recipient, int mask) {
|
||||
this.recipient = recipient;
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Record details of a domain object instance's properties (usually
|
||||
* from the ACL_OBJECT_IDENTITY table)
|
||||
*
|
||||
* @param foreignKeyId used by the
|
||||
* <code>AclsByObjectIdentityMapping</code> to locate the
|
||||
* individual ACL entries
|
||||
* @param aclObjectIdentity the object identity of the domain object
|
||||
* instance
|
||||
* @param aclObjectParentIdentity the object identity of the domain
|
||||
* object instance's parent
|
||||
* @param aclClass the class of which a new instance which should be
|
||||
* created for each individual ACL entry (or an inheritence
|
||||
* "holder" class if there are no ACL entries)
|
||||
*/
|
||||
public AclDetailsHolder(long foreignKeyId, AclObjectIdentity aclObjectIdentity,
|
||||
AclObjectIdentity aclObjectParentIdentity, Class aclClass) {
|
||||
this.foreignKeyId = foreignKeyId;
|
||||
this.aclObjectIdentity = aclObjectIdentity;
|
||||
this.aclObjectParentIdentity = aclObjectParentIdentity;
|
||||
this.aclClass = aclClass;
|
||||
}
|
||||
|
||||
public Class getAclClass() {
|
||||
return aclClass;
|
||||
}
|
||||
|
||||
public AclObjectIdentity getAclObjectIdentity() {
|
||||
return aclObjectIdentity;
|
||||
}
|
||||
|
||||
public AclObjectIdentity getAclObjectParentIdentity() {
|
||||
return aclObjectParentIdentity;
|
||||
}
|
||||
|
||||
public long getForeignKeyId() {
|
||||
return foreignKeyId;
|
||||
}
|
||||
|
||||
public int getMask() {
|
||||
return mask;
|
||||
}
|
||||
|
||||
public Object getRecipient() {
|
||||
return recipient;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query object to look up individual ACL entries.<P>Returns the generic <code>AclDetailsHolder</code>
|
||||
* object.</p>
|
||||
* <P>Guarantees to never return <code>null</code> (exceptions are thrown in the event of any issues).</p>
|
||||
* <P>The executed SQL requires the following information be made available from the indicated
|
||||
* placeholders: 1. RECIPIENT, 2. MASK.</p>
|
||||
*/
|
||||
protected class AclsByObjectIdentityMapping extends MappingSqlQuery {
|
||||
protected AclsByObjectIdentityMapping(DataSource ds) {
|
||||
super(ds, aclsByObjectIdentityQuery);
|
||||
declareParameter(new SqlParameter(Types.BIGINT));
|
||||
compile();
|
||||
}
|
||||
|
||||
protected Object mapRow(ResultSet rs, int rownum)
|
||||
throws SQLException {
|
||||
String recipient = rs.getString(1);
|
||||
int mask = rs.getInt(2);
|
||||
Assert.hasText(recipient, "recipient required");
|
||||
|
||||
return new AclDetailsHolder(recipient, mask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query object to look up properties for an object identity.<P>Returns the generic
|
||||
* <code>AclDetailsHolder</code> object.</p>
|
||||
* <P>Guarantees to never return <code>null</code> (exceptions are thrown in the event of any issues).</p>
|
||||
* <P>The executed SQL requires the following information be made available from the indicated
|
||||
* placeholders: 1. ID, 2. OBJECT_IDENTITY, 3. ACL_CLASS and 4. PARENT_OBJECT_IDENTITY.</p>
|
||||
*/
|
||||
protected class ObjectPropertiesMapping extends MappingSqlQuery {
|
||||
protected ObjectPropertiesMapping(DataSource ds) {
|
||||
super(ds, objectPropertiesQuery);
|
||||
declareParameter(new SqlParameter(Types.VARCHAR));
|
||||
compile();
|
||||
}
|
||||
|
||||
private AclObjectIdentity buildIdentity(String identity) {
|
||||
if (identity == null) {
|
||||
// Must be an empty parent, so return null
|
||||
return null;
|
||||
}
|
||||
|
||||
int delim = identity.lastIndexOf(":");
|
||||
String classname = identity.substring(0, delim);
|
||||
String id = identity.substring(delim + 1);
|
||||
|
||||
return new NamedEntityObjectIdentity(classname, id);
|
||||
}
|
||||
|
||||
protected Object mapRow(ResultSet rs, int rownum)
|
||||
throws SQLException {
|
||||
long id = rs.getLong(1); // required
|
||||
String objectIdentity = rs.getString(2); // required
|
||||
String aclClass = rs.getString(3); // required
|
||||
String parentObjectIdentity = rs.getString(4); // optional
|
||||
Assert.hasText(objectIdentity,
|
||||
"required DEF_OBJECT_PROPERTIES_QUERY value (objectIdentity) returned null or empty");
|
||||
Assert.hasText(aclClass, "required DEF_OBJECT_PROPERTIES_QUERY value (aclClass) returned null or empty");
|
||||
|
||||
Class aclClazz;
|
||||
|
||||
try {
|
||||
aclClazz = this.getClass().getClassLoader().loadClass(aclClass);
|
||||
} catch (ClassNotFoundException cnf) {
|
||||
throw new IllegalArgumentException(cnf.getMessage());
|
||||
}
|
||||
|
||||
return new AclDetailsHolder(id,
|
||||
buildIdentity(objectIdentity), buildIdentity(parentObjectIdentity), aclClazz);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,464 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic.jdbc;
|
||||
|
||||
import org.springframework.security.acl.basic.AclObjectIdentity;
|
||||
import org.springframework.security.acl.basic.BasicAclEntry;
|
||||
import org.springframework.security.acl.basic.BasicAclEntryCache;
|
||||
import org.springframework.security.acl.basic.BasicAclExtendedDao;
|
||||
import org.springframework.security.acl.basic.cache.NullAclEntryCache;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
|
||||
import org.springframework.jdbc.core.SqlParameter;
|
||||
import org.springframework.jdbc.object.MappingSqlQuery;
|
||||
import org.springframework.jdbc.object.SqlUpdate;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Extension of the base {@link JdbcDaoImpl}, which implements {@link BasicAclExtendedDao}.</p>
|
||||
* <p>A default database structure is assumed. This may be overridden by setting the default query strings to use.</p>
|
||||
* <p>If you are using a cache with <code>BasicAclProvider</code>, you should specify that cache via {@link
|
||||
* #setBasicAclEntryCache(BasicAclEntryCache)}. This will cause cache evictions (removals) to take place whenever a
|
||||
* DAO mutator method is called.</p>
|
||||
* <p>This implementation works with <code>String</code> based recipients and {@link
|
||||
* org.springframework.security.acl.basic.NamedEntityObjectIdentity} only. The latter can be changed by overriding {@link
|
||||
* #convertAclObjectIdentityToString(AclObjectIdentity)}.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public class JdbcExtendedDaoImpl extends JdbcDaoImpl implements BasicAclExtendedDao {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(JdbcExtendedDaoImpl.class);
|
||||
public static final String DEF_ACL_OBJECT_IDENTITY_DELETE_STATEMENT =
|
||||
"DELETE FROM acl_object_identity WHERE id = ?";
|
||||
public static final String DEF_ACL_OBJECT_IDENTITY_INSERT_STATEMENT =
|
||||
"INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES (?, ?, ?)";
|
||||
public static final String DEF_ACL_PERMISSION_DELETE_STATEMENT =
|
||||
"DELETE FROM acl_permission WHERE acl_object_identity = ? AND recipient = ?";
|
||||
public static final String DEF_ACL_PERMISSION_INSERT_STATEMENT =
|
||||
"INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (?, ?, ?)";
|
||||
public static final String DEF_ACL_PERMISSION_UPDATE_STATEMENT =
|
||||
"UPDATE acl_permission SET mask = ? WHERE id = ?";
|
||||
public static final String DEF_LOOKUP_PERMISSION_ID_QUERY =
|
||||
"SELECT id FROM acl_permission WHERE acl_object_identity = ? AND recipient = ?";
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private AclObjectIdentityDelete aclObjectIdentityDelete;
|
||||
private AclObjectIdentityInsert aclObjectIdentityInsert;
|
||||
private AclPermissionDelete aclPermissionDelete;
|
||||
private AclPermissionInsert aclPermissionInsert;
|
||||
private AclPermissionUpdate aclPermissionUpdate;
|
||||
private BasicAclEntryCache basicAclEntryCache = new NullAclEntryCache();
|
||||
private MappingSqlQuery lookupPermissionIdMapping;
|
||||
private String aclObjectIdentityDeleteStatement;
|
||||
private String aclObjectIdentityInsertStatement;
|
||||
private String aclPermissionDeleteStatement;
|
||||
private String aclPermissionInsertStatement;
|
||||
private String aclPermissionUpdateStatement;
|
||||
private String lookupPermissionIdQuery;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public JdbcExtendedDaoImpl() {
|
||||
aclObjectIdentityDeleteStatement = DEF_ACL_OBJECT_IDENTITY_DELETE_STATEMENT;
|
||||
aclObjectIdentityInsertStatement = DEF_ACL_OBJECT_IDENTITY_INSERT_STATEMENT;
|
||||
aclPermissionDeleteStatement = DEF_ACL_PERMISSION_DELETE_STATEMENT;
|
||||
aclPermissionInsertStatement = DEF_ACL_PERMISSION_INSERT_STATEMENT;
|
||||
aclPermissionUpdateStatement = DEF_ACL_PERMISSION_UPDATE_STATEMENT;
|
||||
lookupPermissionIdQuery = DEF_LOOKUP_PERMISSION_ID_QUERY;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void changeMask(AclObjectIdentity aclObjectIdentity, Object recipient, Integer newMask)
|
||||
throws DataAccessException {
|
||||
basicAclEntryCache.removeEntriesFromCache(aclObjectIdentity);
|
||||
|
||||
// Retrieve acl_object_identity record details
|
||||
AclDetailsHolder aclDetailsHolder = lookupAclDetailsHolder(aclObjectIdentity);
|
||||
|
||||
// Retrieve applicable acl_permission.id
|
||||
long permissionId = lookupPermissionId(aclDetailsHolder.getForeignKeyId(), recipient.toString());
|
||||
|
||||
if (permissionId == -1) {
|
||||
throw new DataRetrievalFailureException("Could not locate existing acl_permission for aclObjectIdentity: "
|
||||
+ aclObjectIdentity + ", recipient: " + recipient.toString());
|
||||
}
|
||||
|
||||
// Change permission
|
||||
aclPermissionUpdate.update(new Long(permissionId), newMask);
|
||||
}
|
||||
|
||||
public void create(BasicAclEntry basicAclEntry) throws DataAccessException {
|
||||
// Create acl_object_identity record if required
|
||||
createAclObjectIdentityIfRequired(basicAclEntry);
|
||||
|
||||
// Only continue if a recipient is specifed (null recipient indicates
|
||||
// just wanted to ensure the acl_object_identity was created)
|
||||
if (basicAclEntry.getRecipient() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Retrieve acl_object_identity record details
|
||||
AclDetailsHolder aclDetailsHolder = lookupAclDetailsHolder(basicAclEntry.getAclObjectIdentity());
|
||||
|
||||
// Ensure there isn't an existing record for this recipient
|
||||
long permissionId = lookupPermissionId(aclDetailsHolder.getForeignKeyId(), basicAclEntry.getRecipient());
|
||||
|
||||
if (permissionId != -1) {
|
||||
throw new DataIntegrityViolationException("Recipient '" + basicAclEntry.getRecipient()
|
||||
+ "' already exists for aclObjectIdentity ID " + aclDetailsHolder.getForeignKeyId()
|
||||
+ " (permission ID " + ")");
|
||||
}
|
||||
|
||||
// Create acl_permission
|
||||
aclPermissionInsert.insert(new Long(aclDetailsHolder.getForeignKeyId()),
|
||||
basicAclEntry.getRecipient().toString(), new Integer(basicAclEntry.getMask()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that creates an acl_object_identity record if required.
|
||||
*
|
||||
* @param basicAclEntry containing the <code>AclObjectIdentity</code> to create
|
||||
*
|
||||
* @throws DataAccessException
|
||||
*/
|
||||
private void createAclObjectIdentityIfRequired(BasicAclEntry basicAclEntry)
|
||||
throws DataAccessException {
|
||||
basicAclEntryCache.removeEntriesFromCache(basicAclEntry.getAclObjectIdentity());
|
||||
|
||||
String aclObjectIdentityString = convertAclObjectIdentityToString(basicAclEntry.getAclObjectIdentity());
|
||||
|
||||
// Lookup the object's main properties from the RDBMS (guaranteed no nulls)
|
||||
List objects = objectProperties.execute(aclObjectIdentityString);
|
||||
|
||||
if (objects.size() == 0) {
|
||||
if (basicAclEntry.getAclObjectParentIdentity() != null) {
|
||||
AclDetailsHolder parentDetails = lookupAclDetailsHolder(basicAclEntry.getAclObjectParentIdentity());
|
||||
|
||||
// Must create the acl_object_identity record
|
||||
aclObjectIdentityInsert.insert(aclObjectIdentityString, new Long(parentDetails.getForeignKeyId()),
|
||||
basicAclEntry.getClass().getName());
|
||||
} else {
|
||||
// Must create the acl_object_identity record
|
||||
aclObjectIdentityInsert.insert(aclObjectIdentityString, null, basicAclEntry.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void delete(AclObjectIdentity aclObjectIdentity)
|
||||
throws DataAccessException {
|
||||
basicAclEntryCache.removeEntriesFromCache(aclObjectIdentity);
|
||||
|
||||
// Retrieve acl_object_identity record details
|
||||
AclDetailsHolder aclDetailsHolder = lookupAclDetailsHolder(aclObjectIdentity);
|
||||
|
||||
// Retrieve all acl_permissions applying to this acl_object_identity
|
||||
Iterator acls = aclsByObjectIdentity.execute(aclDetailsHolder.getForeignKeyId()).iterator();
|
||||
|
||||
// Delete all existing acl_permissions applying to this acl_object_identity
|
||||
while (acls.hasNext()) {
|
||||
AclDetailsHolder permission = (AclDetailsHolder) acls.next();
|
||||
delete(aclObjectIdentity, permission.getRecipient());
|
||||
}
|
||||
|
||||
// Delete acl_object_identity
|
||||
aclObjectIdentityDelete.delete(new Long(aclDetailsHolder.getForeignKeyId()));
|
||||
}
|
||||
|
||||
public void delete(AclObjectIdentity aclObjectIdentity, Object recipient)
|
||||
throws DataAccessException {
|
||||
basicAclEntryCache.removeEntriesFromCache(aclObjectIdentity);
|
||||
|
||||
// Retrieve acl_object_identity record details
|
||||
AclDetailsHolder aclDetailsHolder = lookupAclDetailsHolder(aclObjectIdentity);
|
||||
|
||||
// Delete acl_permission
|
||||
aclPermissionDelete.delete(new Long(aclDetailsHolder.getForeignKeyId()), recipient.toString());
|
||||
}
|
||||
|
||||
public AclObjectIdentityDelete getAclObjectIdentityDelete() {
|
||||
return aclObjectIdentityDelete;
|
||||
}
|
||||
|
||||
public String getAclObjectIdentityDeleteStatement() {
|
||||
return aclObjectIdentityDeleteStatement;
|
||||
}
|
||||
|
||||
public AclObjectIdentityInsert getAclObjectIdentityInsert() {
|
||||
return aclObjectIdentityInsert;
|
||||
}
|
||||
|
||||
public String getAclObjectIdentityInsertStatement() {
|
||||
return aclObjectIdentityInsertStatement;
|
||||
}
|
||||
|
||||
public AclPermissionDelete getAclPermissionDelete() {
|
||||
return aclPermissionDelete;
|
||||
}
|
||||
|
||||
public String getAclPermissionDeleteStatement() {
|
||||
return aclPermissionDeleteStatement;
|
||||
}
|
||||
|
||||
public AclPermissionInsert getAclPermissionInsert() {
|
||||
return aclPermissionInsert;
|
||||
}
|
||||
|
||||
public String getAclPermissionInsertStatement() {
|
||||
return aclPermissionInsertStatement;
|
||||
}
|
||||
|
||||
public AclPermissionUpdate getAclPermissionUpdate() {
|
||||
return aclPermissionUpdate;
|
||||
}
|
||||
|
||||
public String getAclPermissionUpdateStatement() {
|
||||
return aclPermissionUpdateStatement;
|
||||
}
|
||||
|
||||
public BasicAclEntryCache getBasicAclEntryCache() {
|
||||
return basicAclEntryCache;
|
||||
}
|
||||
|
||||
public MappingSqlQuery getLookupPermissionIdMapping() {
|
||||
return lookupPermissionIdMapping;
|
||||
}
|
||||
|
||||
public String getLookupPermissionIdQuery() {
|
||||
return lookupPermissionIdQuery;
|
||||
}
|
||||
|
||||
protected void initDao() throws ApplicationContextException {
|
||||
super.initDao();
|
||||
lookupPermissionIdMapping = new LookupPermissionIdMapping(getDataSource());
|
||||
aclPermissionInsert = new AclPermissionInsert(getDataSource());
|
||||
aclObjectIdentityInsert = new AclObjectIdentityInsert(getDataSource());
|
||||
aclPermissionDelete = new AclPermissionDelete(getDataSource());
|
||||
aclObjectIdentityDelete = new AclObjectIdentityDelete(getDataSource());
|
||||
aclPermissionUpdate = new AclPermissionUpdate(getDataSource());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that obtains a given acl_object_identity record.
|
||||
*
|
||||
* @param aclObjectIdentity to lookup
|
||||
*
|
||||
* @return details of the record
|
||||
*
|
||||
* @throws DataRetrievalFailureException if record could not be found
|
||||
*/
|
||||
private AclDetailsHolder lookupAclDetailsHolder(AclObjectIdentity aclObjectIdentity)
|
||||
throws DataRetrievalFailureException {
|
||||
String aclObjectIdentityString = convertAclObjectIdentityToString(aclObjectIdentity);
|
||||
|
||||
// Lookup the object's main properties from the RDBMS (guaranteed no nulls)
|
||||
List objects = objectProperties.execute(aclObjectIdentityString);
|
||||
|
||||
if (objects.size() == 0) {
|
||||
throw new DataRetrievalFailureException("aclObjectIdentity not found: " + aclObjectIdentityString);
|
||||
}
|
||||
|
||||
// Should only be one record
|
||||
return (AclDetailsHolder) objects.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to lookup the acl_permission applying to a given acl_object_identity.id and
|
||||
* acl_permission.recipient.
|
||||
*
|
||||
* @param aclObjectIdentityId to locate
|
||||
* @param recipient to locate
|
||||
*
|
||||
* @return the acl_permission.id of the record, or -1 if not found
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
private long lookupPermissionId(long aclObjectIdentityId, Object recipient)
|
||||
throws DataAccessException {
|
||||
List list = lookupPermissionIdMapping.execute(new Object[] {new Long(aclObjectIdentityId), recipient});
|
||||
|
||||
if (list.size() == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ((Long) list.get(0)).longValue();
|
||||
}
|
||||
|
||||
public void setAclObjectIdentityDelete(AclObjectIdentityDelete aclObjectIdentityDelete) {
|
||||
this.aclObjectIdentityDelete = aclObjectIdentityDelete;
|
||||
}
|
||||
|
||||
public void setAclObjectIdentityDeleteStatement(String aclObjectIdentityDeleteStatement) {
|
||||
this.aclObjectIdentityDeleteStatement = aclObjectIdentityDeleteStatement;
|
||||
}
|
||||
|
||||
public void setAclObjectIdentityInsert(AclObjectIdentityInsert aclObjectIdentityInsert) {
|
||||
this.aclObjectIdentityInsert = aclObjectIdentityInsert;
|
||||
}
|
||||
|
||||
public void setAclObjectIdentityInsertStatement(String aclObjectIdentityInsertStatement) {
|
||||
this.aclObjectIdentityInsertStatement = aclObjectIdentityInsertStatement;
|
||||
}
|
||||
|
||||
public void setAclPermissionDelete(AclPermissionDelete aclPermissionDelete) {
|
||||
this.aclPermissionDelete = aclPermissionDelete;
|
||||
}
|
||||
|
||||
public void setAclPermissionDeleteStatement(String aclPermissionDeleteStatement) {
|
||||
this.aclPermissionDeleteStatement = aclPermissionDeleteStatement;
|
||||
}
|
||||
|
||||
public void setAclPermissionInsert(AclPermissionInsert aclPermissionInsert) {
|
||||
this.aclPermissionInsert = aclPermissionInsert;
|
||||
}
|
||||
|
||||
public void setAclPermissionInsertStatement(String aclPermissionInsertStatement) {
|
||||
this.aclPermissionInsertStatement = aclPermissionInsertStatement;
|
||||
}
|
||||
|
||||
public void setAclPermissionUpdate(AclPermissionUpdate aclPermissionUpdate) {
|
||||
this.aclPermissionUpdate = aclPermissionUpdate;
|
||||
}
|
||||
|
||||
public void setAclPermissionUpdateStatement(String aclPermissionUpdateStatement) {
|
||||
this.aclPermissionUpdateStatement = aclPermissionUpdateStatement;
|
||||
}
|
||||
|
||||
public void setBasicAclEntryCache(BasicAclEntryCache basicAclEntryCache) {
|
||||
Assert.notNull(basicAclEntryCache, "Cache cannot be set to null");
|
||||
this.basicAclEntryCache = basicAclEntryCache;
|
||||
}
|
||||
|
||||
public void setLookupPermissionIdMapping(MappingSqlQuery lookupPermissionIdMapping) {
|
||||
this.lookupPermissionIdMapping = lookupPermissionIdMapping;
|
||||
}
|
||||
|
||||
public void setLookupPermissionIdQuery(String lookupPermissionIdQuery) {
|
||||
this.lookupPermissionIdQuery = lookupPermissionIdQuery;
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
protected class AclObjectIdentityDelete extends SqlUpdate {
|
||||
protected AclObjectIdentityDelete(DataSource ds) {
|
||||
super(ds, aclObjectIdentityDeleteStatement);
|
||||
declareParameter(new SqlParameter(Types.BIGINT));
|
||||
compile();
|
||||
}
|
||||
|
||||
protected void delete(Long aclObjectIdentity) throws DataAccessException {
|
||||
super.update(aclObjectIdentity.intValue());
|
||||
}
|
||||
}
|
||||
|
||||
protected class AclObjectIdentityInsert extends SqlUpdate {
|
||||
protected AclObjectIdentityInsert(DataSource ds) {
|
||||
super(ds, aclObjectIdentityInsertStatement);
|
||||
declareParameter(new SqlParameter(Types.VARCHAR));
|
||||
declareParameter(new SqlParameter(Types.BIGINT));
|
||||
declareParameter(new SqlParameter(Types.VARCHAR));
|
||||
compile();
|
||||
}
|
||||
|
||||
protected void insert(String objectIdentity, Long parentAclObjectIdentity, String aclClass)
|
||||
throws DataAccessException {
|
||||
Object[] objs = new Object[] {objectIdentity, parentAclObjectIdentity, aclClass};
|
||||
super.update(objs);
|
||||
}
|
||||
}
|
||||
|
||||
protected class AclPermissionDelete extends SqlUpdate {
|
||||
protected AclPermissionDelete(DataSource ds) {
|
||||
super(ds, aclPermissionDeleteStatement);
|
||||
declareParameter(new SqlParameter(Types.BIGINT));
|
||||
declareParameter(new SqlParameter(Types.VARCHAR));
|
||||
compile();
|
||||
}
|
||||
|
||||
protected void delete(Long aclObjectIdentity, String recipient)
|
||||
throws DataAccessException {
|
||||
super.update(new Object[] {aclObjectIdentity, recipient});
|
||||
}
|
||||
}
|
||||
|
||||
protected class AclPermissionInsert extends SqlUpdate {
|
||||
protected AclPermissionInsert(DataSource ds) {
|
||||
super(ds, aclPermissionInsertStatement);
|
||||
declareParameter(new SqlParameter(Types.BIGINT));
|
||||
declareParameter(new SqlParameter(Types.VARCHAR));
|
||||
declareParameter(new SqlParameter(Types.INTEGER));
|
||||
compile();
|
||||
}
|
||||
|
||||
protected void insert(Long aclObjectIdentity, String recipient, Integer mask)
|
||||
throws DataAccessException {
|
||||
Object[] objs = new Object[] {aclObjectIdentity, recipient, mask};
|
||||
super.update(objs);
|
||||
}
|
||||
}
|
||||
|
||||
protected class AclPermissionUpdate extends SqlUpdate {
|
||||
protected AclPermissionUpdate(DataSource ds) {
|
||||
super(ds, aclPermissionUpdateStatement);
|
||||
declareParameter(new SqlParameter(Types.BIGINT));
|
||||
declareParameter(new SqlParameter(Types.INTEGER));
|
||||
compile();
|
||||
}
|
||||
|
||||
protected void update(Long aclPermissionId, Integer newMask)
|
||||
throws DataAccessException {
|
||||
super.update(newMask.intValue(), aclPermissionId.intValue());
|
||||
}
|
||||
}
|
||||
|
||||
protected class LookupPermissionIdMapping extends MappingSqlQuery {
|
||||
protected LookupPermissionIdMapping(DataSource ds) {
|
||||
super(ds, lookupPermissionIdQuery);
|
||||
declareParameter(new SqlParameter(Types.BIGINT));
|
||||
declareParameter(new SqlParameter(Types.VARCHAR));
|
||||
compile();
|
||||
}
|
||||
|
||||
protected Object mapRow(ResultSet rs, int rownum)
|
||||
throws SQLException {
|
||||
return new Long(rs.getLong(1));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
JDBC-based data access object for ACL information.
|
||||
</body>
|
||||
</html>
|
@ -1,5 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
Access control list implementation based on integer bit masks.
|
||||
</body>
|
||||
</html>
|
@ -1,15 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
Enables retrieval of access control lists (ACLs) for domain object instances.
|
||||
|
||||
<P>The goal of this package is to locate the <code>AclEntry</code>s
|
||||
that apply to a given domain object instance.
|
||||
</P>
|
||||
|
||||
<P>
|
||||
An <code>AclManager</code> has ultimate resposibility for obtaining the
|
||||
<code>AclEntry</code>s instances, with a provider-based implementation
|
||||
available via the <code>AclProviderManager</code> class (and
|
||||
its <code>AclProvider</code> interface.</P>
|
||||
</body>
|
||||
</html>
|
@ -1,232 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.springframework.security.afterinvocation;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.security.AccessDeniedException;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.AuthorizationServiceException;
|
||||
import org.springframework.security.ConfigAttribute;
|
||||
import org.springframework.security.acl.AclEntry;
|
||||
import org.springframework.security.acl.AclManager;
|
||||
import org.springframework.security.acl.basic.BasicAclEntry;
|
||||
import org.springframework.security.acl.basic.SimpleAclEntry;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Given a <code>Collection</code> of domain object instances returned from a secure object invocation, remove
|
||||
* any <code>Collection</code> elements the principal does not have appropriate permission to access as defined by the
|
||||
* {@link AclManager}.</p>
|
||||
* <p>The <code>AclManager</code> is used to retrieve the access control list (ACL) permissions associated with
|
||||
* each <code>Collection</code> domain object instance element for the current <code>Authentication</code> object.
|
||||
* This class is designed to process {@link AclEntry}s that are subclasses of {@link
|
||||
* org.springframework.security.acl.basic.BasicAclEntry} only. Generally these are obtained by using the {@link
|
||||
* org.springframework.security.acl.basic.BasicAclProvider}.</p>
|
||||
* <p>This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link
|
||||
* #processConfigAttribute}. The provider will then lookup the ACLs from the <code>AclManager</code> and ensure the
|
||||
* principal is {@link org.springframework.security.acl.basic.BasicAclEntry#isPermitted(int)} for at least one of the {@link
|
||||
* #requirePermission}s for each <code>Collection</code> element. If the principal does not have at least one of the
|
||||
* permissions, that element will not be included in the returned <code>Collection</code>.</p>
|
||||
* <p>Often users will setup a <code>BasicAclEntryAfterInvocationProvider</code> with a {@link
|
||||
* #processConfigAttribute} of <code>AFTER_ACL_COLLECTION_READ</code> and a {@link #requirePermission} of
|
||||
* <code>SimpleAclEntry.READ</code>. These are also the defaults.</p>
|
||||
* <p>The <code>AclManager</code> is allowed to return any implementations of <code>AclEntry</code> it wishes.
|
||||
* However, this provider will only be able to validate against <code>BasicAclEntry</code>s, and thus a
|
||||
* <code>Collection</code> element will be filtered from the resulting <code>Collection</code> if no
|
||||
* <code>AclEntry</code> is of type <code>BasicAclEntry</code>.</p>
|
||||
* <p>If the provided <code>returnObject</code> is <code>null</code>, a <code>null</code><code>Collection</code>
|
||||
* will be returned. If the provided <code>returnObject</code> is not a <code>Collection</code>, an {@link
|
||||
* AuthorizationServiceException} will be thrown.</p>
|
||||
* <p>All comparisons and prefixes are case sensitive.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Paulo Neves
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public class BasicAclEntryAfterInvocationCollectionFilteringProvider implements AfterInvocationProvider,
|
||||
InitializingBean {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(BasicAclEntryAfterInvocationCollectionFilteringProvider.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private AclManager aclManager;
|
||||
private Class processDomainObjectClass = Object.class;
|
||||
private String processConfigAttribute = "AFTER_ACL_COLLECTION_READ";
|
||||
private int[] requirePermission = {SimpleAclEntry.READ};
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory");
|
||||
Assert.notNull(aclManager, "An aclManager is mandatory");
|
||||
|
||||
if ((requirePermission == null) || (requirePermission.length == 0)) {
|
||||
throw new IllegalArgumentException("One or more requirePermission entries is mandatory");
|
||||
}
|
||||
}
|
||||
|
||||
public Object decide(Authentication authentication, Object object, List<ConfigAttribute> config,
|
||||
Object returnedObject) throws AccessDeniedException {
|
||||
Iterator iter = config.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttribute attr = (ConfigAttribute) iter.next();
|
||||
|
||||
if (this.supports(attr)) {
|
||||
// Need to process the Collection for this invocation
|
||||
if (returnedObject == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Return object is null, skipping");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Filterer filterer = null;
|
||||
|
||||
if (returnedObject instanceof Collection) {
|
||||
Collection collection = (Collection) returnedObject;
|
||||
filterer = new CollectionFilterer(collection);
|
||||
} else if (returnedObject.getClass().isArray()) {
|
||||
Object[] array = (Object[]) returnedObject;
|
||||
filterer = new ArrayFilterer(array);
|
||||
} else {
|
||||
throw new AuthorizationServiceException("A Collection or an array (or null) was required as the "
|
||||
+ "returnedObject, but the returnedObject was: " + returnedObject);
|
||||
}
|
||||
|
||||
// Locate unauthorised Collection elements
|
||||
Iterator collectionIter = filterer.iterator();
|
||||
|
||||
while (collectionIter.hasNext()) {
|
||||
Object domainObject = collectionIter.next();
|
||||
|
||||
boolean hasPermission = false;
|
||||
|
||||
if (domainObject == null) {
|
||||
hasPermission = true;
|
||||
} else if (!processDomainObjectClass.isAssignableFrom(domainObject.getClass())) {
|
||||
hasPermission = true;
|
||||
} else {
|
||||
AclEntry[] acls = aclManager.getAcls(domainObject, authentication);
|
||||
|
||||
if ((acls != null) && (acls.length != 0)) {
|
||||
for (int i = 0; i < acls.length; i++) {
|
||||
// Locate processable AclEntrys
|
||||
if (acls[i] instanceof BasicAclEntry) {
|
||||
BasicAclEntry processableAcl = (BasicAclEntry) acls[i];
|
||||
|
||||
// See if principal has any of the required permissions
|
||||
for (int y = 0; y < requirePermission.length; y++) {
|
||||
if (processableAcl.isPermitted(requirePermission[y])) {
|
||||
hasPermission = true;
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Principal is authorised for element: " + domainObject
|
||||
+ " due to ACL: " + processableAcl.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasPermission) {
|
||||
filterer.remove(domainObject);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Principal is NOT authorised for element: " + domainObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filterer.getFilteredObject();
|
||||
}
|
||||
}
|
||||
|
||||
return returnedObject;
|
||||
}
|
||||
|
||||
public AclManager getAclManager() {
|
||||
return aclManager;
|
||||
}
|
||||
|
||||
public String getProcessConfigAttribute() {
|
||||
return processConfigAttribute;
|
||||
}
|
||||
|
||||
public int[] getRequirePermission() {
|
||||
return requirePermission;
|
||||
}
|
||||
|
||||
public void setAclManager(AclManager aclManager) {
|
||||
this.aclManager = aclManager;
|
||||
}
|
||||
|
||||
public void setProcessConfigAttribute(String processConfigAttribute) {
|
||||
this.processConfigAttribute = processConfigAttribute;
|
||||
}
|
||||
|
||||
public void setProcessDomainObjectClass(Class processDomainObjectClass) {
|
||||
Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null");
|
||||
this.processDomainObjectClass = processDomainObjectClass;
|
||||
}
|
||||
|
||||
public void setRequirePermission(int[] requirePermission) {
|
||||
this.requirePermission = requirePermission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow setting permissions with String literals instead of integers as {@link
|
||||
* #setRequirePermission(int[])}
|
||||
*
|
||||
* @param requiredPermissions permission literals
|
||||
*
|
||||
* @see SimpleAclEntry#parsePermissions(String[]) for valid values
|
||||
*/
|
||||
public void setRequirePermissionFromString(String[] requiredPermissions) {
|
||||
setRequirePermission(SimpleAclEntry.parsePermissions(requiredPermissions));
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute())) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation supports any type of class, because it does not query the presented secure object.
|
||||
*
|
||||
* @param clazz the secure object
|
||||
*
|
||||
* @return always <code>true</code>
|
||||
*/
|
||||
public boolean supports(Class<? extends Object> clazz) {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,216 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.afterinvocation;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.MessageSourceAware;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.context.support.MessageSourceAccessor;
|
||||
import org.springframework.security.AccessDeniedException;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.ConfigAttribute;
|
||||
import org.springframework.security.SpringSecurityMessageSource;
|
||||
import org.springframework.security.acl.AclEntry;
|
||||
import org.springframework.security.acl.AclManager;
|
||||
import org.springframework.security.acl.basic.BasicAclEntry;
|
||||
import org.springframework.security.acl.basic.SimpleAclEntry;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* <p>Given a domain object instance returned from a secure object invocation, ensures the principal has
|
||||
* appropriate permission as defined by the {@link AclManager}.</p>
|
||||
* <p>The <code>AclManager</code> is used to retrieve the access control list (ACL) permissions associated with a
|
||||
* domain object instance for the current <code>Authentication</code> object. This class is designed to process {@link
|
||||
* AclEntry}s that are subclasses of {@link org.springframework.security.acl.basic.BasicAclEntry} only. Generally these are
|
||||
* obtained by using the {@link org.springframework.security.acl.basic.BasicAclProvider}.</p>
|
||||
* <p>This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link
|
||||
* #processConfigAttribute}. The provider will then lookup the ACLs from the <code>AclManager</code> and ensure the
|
||||
* principal is {@link org.springframework.security.acl.basic.BasicAclEntry#isPermitted(int)} for at least one of the {@link
|
||||
* #requirePermission}s.</p>
|
||||
* <p>Often users will setup a <code>BasicAclEntryAfterInvocationProvider</code> with a {@link
|
||||
* #processConfigAttribute} of <code>AFTER_ACL_READ</code> and a {@link #requirePermission} of
|
||||
* <code>SimpleAclEntry.READ</code>. These are also the defaults.</p>
|
||||
* <p>If the principal does not have sufficient permissions, an <code>AccessDeniedException</code> will be thrown.</p>
|
||||
* <p>The <code>AclManager</code> is allowed to return any implementations of <code>AclEntry</code> it wishes.
|
||||
* However, this provider will only be able to validate against <code>BasicAclEntry</code>s, and thus access will be
|
||||
* denied if no <code>AclEntry</code> is of type <code>BasicAclEntry</code>.</p>
|
||||
* <p>If the provided <code>returnObject</code> is <code>null</code>, permission will always be granted and
|
||||
* <code>null</code> will be returned.</p>
|
||||
* <p>All comparisons and prefixes are case sensitive.</p>
|
||||
*
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public class BasicAclEntryAfterInvocationProvider implements AfterInvocationProvider, InitializingBean,
|
||||
MessageSourceAware {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(BasicAclEntryAfterInvocationProvider.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private AclManager aclManager;
|
||||
private Class processDomainObjectClass = Object.class;
|
||||
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
|
||||
private String processConfigAttribute = "AFTER_ACL_READ";
|
||||
private int[] requirePermission = {SimpleAclEntry.READ};
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory");
|
||||
Assert.notNull(aclManager, "An aclManager is mandatory");
|
||||
Assert.notNull(messages, "A message source must be set");
|
||||
|
||||
if ((requirePermission == null) || (requirePermission.length == 0)) {
|
||||
throw new IllegalArgumentException("One or more requirePermission entries is mandatory");
|
||||
}
|
||||
}
|
||||
|
||||
public Object decide(Authentication authentication, Object object, List<ConfigAttribute> config,
|
||||
Object returnedObject) throws AccessDeniedException {
|
||||
Iterator iter = config.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttribute attr = (ConfigAttribute) iter.next();
|
||||
|
||||
if (this.supports(attr)) {
|
||||
// Need to make an access decision on this invocation
|
||||
if (returnedObject == null) {
|
||||
// AclManager interface contract prohibits nulls
|
||||
// As they have permission to null/nothing, grant access
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Return object is null, skipping");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!processDomainObjectClass.isAssignableFrom(returnedObject.getClass())) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Return object is not applicable for this provider, skipping");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
AclEntry[] acls = aclManager.getAcls(returnedObject, authentication);
|
||||
|
||||
if ((acls == null) || (acls.length == 0)) {
|
||||
throw new AccessDeniedException(messages.getMessage(
|
||||
"BasicAclEntryAfterInvocationProvider.noPermission",
|
||||
new Object[] {authentication.getName(), returnedObject},
|
||||
"Authentication {0} has NO permissions at all to the domain object {1}", LocaleContextHolder.getLocale()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < acls.length; i++) {
|
||||
// Locate processable AclEntrys
|
||||
if (acls[i] instanceof BasicAclEntry) {
|
||||
BasicAclEntry processableAcl = (BasicAclEntry) acls[i];
|
||||
|
||||
// See if principal has any of the required permissions
|
||||
for (int y = 0; y < requirePermission.length; y++) {
|
||||
if (processableAcl.isPermitted(requirePermission[y])) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Principal DOES have permission to return object: " + returnedObject
|
||||
+ " due to ACL: " + processableAcl.toString());
|
||||
}
|
||||
|
||||
return returnedObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No permissions match
|
||||
throw new AccessDeniedException(messages.getMessage(
|
||||
"BasicAclEntryAfterInvocationProvider.insufficientPermission",
|
||||
new Object[] {authentication.getName(), returnedObject},
|
||||
"Authentication {0} has ACL permissions to the domain object, "
|
||||
+ "but not the required ACL permission to the domain object {1}", LocaleContextHolder.getLocale()));
|
||||
}
|
||||
}
|
||||
|
||||
return returnedObject;
|
||||
}
|
||||
|
||||
public AclManager getAclManager() {
|
||||
return aclManager;
|
||||
}
|
||||
|
||||
public String getProcessConfigAttribute() {
|
||||
return processConfigAttribute;
|
||||
}
|
||||
|
||||
public int[] getRequirePermission() {
|
||||
return requirePermission;
|
||||
}
|
||||
|
||||
public void setAclManager(AclManager aclManager) {
|
||||
this.aclManager = aclManager;
|
||||
}
|
||||
|
||||
public void setMessageSource(MessageSource messageSource) {
|
||||
this.messages = new MessageSourceAccessor(messageSource);
|
||||
}
|
||||
|
||||
public void setProcessConfigAttribute(String processConfigAttribute) {
|
||||
this.processConfigAttribute = processConfigAttribute;
|
||||
}
|
||||
|
||||
public void setProcessDomainObjectClass(Class processDomainObjectClass) {
|
||||
Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null");
|
||||
this.processDomainObjectClass = processDomainObjectClass;
|
||||
}
|
||||
|
||||
public void setRequirePermission(int[] requirePermission) {
|
||||
this.requirePermission = requirePermission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow setting permissions with String literals instead of integers as {@link #setRequirePermission(int[])}
|
||||
*
|
||||
* @param requiredPermissions Permission literals
|
||||
* @see SimpleAclEntry#parsePermissions(String[]) for valid values
|
||||
*/
|
||||
public void setRequirePermissionFromString(String[] requiredPermissions) {
|
||||
setRequirePermission(SimpleAclEntry.parsePermissions(requiredPermissions));
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute())) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation supports any type of class, because it does not query the presented secure object.
|
||||
*
|
||||
* @param clazz the secure object
|
||||
*
|
||||
* @return always <code>true</code>
|
||||
*/
|
||||
public boolean supports(Class<? extends Object> clazz) {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,264 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.vote;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.AuthorizationServiceException;
|
||||
import org.springframework.security.ConfigAttribute;
|
||||
|
||||
import org.springframework.security.acl.AclEntry;
|
||||
import org.springframework.security.acl.AclManager;
|
||||
import org.springframework.security.acl.basic.BasicAclEntry;
|
||||
import org.springframework.security.acl.basic.SimpleAclEntry;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Given a domain object instance passed as a method argument, ensures the principal has appropriate permission
|
||||
* as defined by the {@link AclManager}.</p>
|
||||
* <p>The <code>AclManager</code> is used to retrieve the access control list (ACL) permissions associated with a
|
||||
* domain object instance for the current <code>Authentication</code> object. This class is designed to process {@link
|
||||
* AclEntry}s that are subclasses of {@link org.springframework.security.acl.basic.BasicAclEntry} only. Generally these are
|
||||
* obtained by using the {@link org.springframework.security.acl.basic.BasicAclProvider}.</p>
|
||||
* <p>The voter will vote if any {@link ConfigAttribute#getAttribute()} matches the {@link
|
||||
* #processConfigAttribute}. The provider will then locate the first method argument of type {@link
|
||||
* #processDomainObjectClass}. Assuming that method argument is non-null, the provider will then lookup the ACLs from
|
||||
* the <code>AclManager</code> and ensure the principal is {@link
|
||||
* org.springframework.security.acl.basic.BasicAclEntry#isPermitted(int)} for at least one of the {@link #requirePermission}s.</p>
|
||||
* <p>If the method argument is <code>null</code>, the voter will abstain from voting. If the method argument
|
||||
* could not be found, an {@link org.springframework.security.AuthorizationServiceException} will be thrown.</p>
|
||||
* <p>In practical terms users will typically setup a number of <code>BasicAclEntryVoter</code>s. Each will have a
|
||||
* different {@link #processDomainObjectClass}, {@link #processConfigAttribute} and {@link #requirePermission}
|
||||
* combination. For example, a small application might employ the following instances of
|
||||
* <code>BasicAclEntryVoter</code>:
|
||||
* <ul>
|
||||
* <li>Process domain object class <code>BankAccount</code>, configuration attribute
|
||||
* <code>VOTE_ACL_BANK_ACCONT_READ</code>, require permission <code>SimpleAclEntry.READ</code></li>
|
||||
* <li>Process domain object class <code>BankAccount</code>, configuration attribute
|
||||
* <code>VOTE_ACL_BANK_ACCOUNT_WRITE</code>, require permission list <code>SimpleAclEntry.WRITE</code> and
|
||||
* <code>SimpleAclEntry.CREATE</code> (allowing the principal to have <b>either</b> of these two permissions</li>
|
||||
* <li>Process domain object class <code>Customer</code>, configuration attribute
|
||||
* <code>VOTE_ACL_CUSTOMER_READ</code>, require permission <code>SimpleAclEntry.READ</code></li>
|
||||
* <li>Process domain object class <code>Customer</code>, configuration attribute
|
||||
* <code>VOTE_ACL_CUSTOMER_WRITE</code>, require permission list <code>SimpleAclEntry.WRITE</code> and
|
||||
* <code>SimpleAclEntry.CREATE</code></li>
|
||||
* </ul>
|
||||
* Alternatively, you could have used a common superclass or interface for the {@link #processDomainObjectClass}
|
||||
* if both <code>BankAccount</code> and <code>Customer</code> had common parents.</p>
|
||||
* <p>If the principal does not have sufficient permissions, the voter will vote to deny access.</p>
|
||||
* <p>The <code>AclManager</code> is allowed to return any implementations of <code>AclEntry</code> it wishes.
|
||||
* However, this provider will only be able to validate against <code>AbstractBasicAclEntry</code>s, and thus a vote
|
||||
* to deny access will be made if no <code>AclEntry</code> is of type <code>AbstractBasicAclEntry</code>.</p>
|
||||
* <p>All comparisons and prefixes are case sensitive.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @deprecated Use new spring-security-acl module instead
|
||||
*/
|
||||
public class BasicAclEntryVoter extends AbstractAclVoter implements InitializingBean {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(BasicAclEntryVoter.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private AclManager aclManager;
|
||||
private String internalMethod;
|
||||
private String processConfigAttribute;
|
||||
private int[] requirePermission;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory");
|
||||
Assert.notNull(aclManager, "An aclManager is mandatory");
|
||||
|
||||
if ((requirePermission == null) || (requirePermission.length == 0)) {
|
||||
throw new IllegalArgumentException("One or more requirePermission entries is mandatory");
|
||||
}
|
||||
}
|
||||
|
||||
public AclManager getAclManager() {
|
||||
return aclManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionally specifies a method of the domain object that will be used to obtain a contained domain
|
||||
* object. That contained domain object will be used for the ACL evaluation. This is useful if a domain object
|
||||
* contains a parent that an ACL evaluation should be targeted for, instead of the child domain object (which
|
||||
* perhaps is being created and as such does not yet have any ACL permissions)
|
||||
*
|
||||
* @return <code>null</code> to use the domain object, or the name of a method (that requires no arguments) that
|
||||
* should be invoked to obtain an <code>Object</code> which will be the domain object used for ACL
|
||||
* evaluation
|
||||
*/
|
||||
public String getInternalMethod() {
|
||||
return internalMethod;
|
||||
}
|
||||
|
||||
public String getProcessConfigAttribute() {
|
||||
return processConfigAttribute;
|
||||
}
|
||||
|
||||
public int[] getRequirePermission() {
|
||||
return requirePermission;
|
||||
}
|
||||
|
||||
public void setAclManager(AclManager aclManager) {
|
||||
this.aclManager = aclManager;
|
||||
}
|
||||
|
||||
public void setInternalMethod(String internalMethod) {
|
||||
this.internalMethod = internalMethod;
|
||||
}
|
||||
|
||||
public void setProcessConfigAttribute(String processConfigAttribute) {
|
||||
this.processConfigAttribute = processConfigAttribute;
|
||||
}
|
||||
|
||||
public void setRequirePermission(int[] requirePermission) {
|
||||
this.requirePermission = requirePermission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow setting permissions with String literals instead of integers as {@link #setRequirePermission(int[])}
|
||||
*
|
||||
* @param requirePermission Permission literals
|
||||
* @see SimpleAclEntry#parsePermissions(String[]) for valid values
|
||||
*/
|
||||
public void setRequirePermissionFromString(String[] requirePermission) {
|
||||
setRequirePermission(SimpleAclEntry.parsePermissions(requirePermission));
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute())) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int vote(Authentication authentication, Object object, List<ConfigAttribute> attributes) {
|
||||
Iterator iter = attributes.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttribute attr = (ConfigAttribute) iter.next();
|
||||
|
||||
if (this.supports(attr)) {
|
||||
// Need to make an access decision on this invocation
|
||||
// Attempt to locate the domain object instance to process
|
||||
Object domainObject = getDomainObjectInstance(object);
|
||||
|
||||
// If domain object is null, vote to abstain
|
||||
if (domainObject == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Voting to abstain - domainObject is null");
|
||||
}
|
||||
|
||||
return AccessDecisionVoter.ACCESS_ABSTAIN;
|
||||
}
|
||||
|
||||
// Evaluate if we are required to use an inner domain object
|
||||
if ((internalMethod != null) && !"".equals(internalMethod)) {
|
||||
try {
|
||||
Class clazz = domainObject.getClass();
|
||||
Method method = clazz.getMethod(internalMethod, new Class[] {});
|
||||
domainObject = method.invoke(domainObject, new Object[] {});
|
||||
} catch (NoSuchMethodException nsme) {
|
||||
throw new AuthorizationServiceException("Object of class '" + domainObject.getClass()
|
||||
+ "' does not provide the requested internalMethod: " + internalMethod);
|
||||
} catch (IllegalAccessException iae) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("IllegalAccessException", iae);
|
||||
|
||||
if (iae.getCause() != null) {
|
||||
logger.debug("Cause: " + iae.getCause().getMessage(), iae.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod
|
||||
+ " for object: " + domainObject);
|
||||
} catch (InvocationTargetException ite) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("InvocationTargetException", ite);
|
||||
|
||||
if (ite.getCause() != null) {
|
||||
logger.debug("Cause: " + ite.getCause().getMessage(), ite.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod
|
||||
+ " for object: " + domainObject);
|
||||
}
|
||||
}
|
||||
|
||||
// Obtain the ACLs applicable to the domain object
|
||||
AclEntry[] acls = aclManager.getAcls(domainObject, authentication);
|
||||
|
||||
// If principal has no permissions for domain object, deny
|
||||
if ((acls == null) || (acls.length == 0)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Voting to deny access - no ACLs returned for this principal");
|
||||
}
|
||||
|
||||
return AccessDecisionVoter.ACCESS_DENIED;
|
||||
}
|
||||
|
||||
// Principal has some permissions for domain object, check them
|
||||
for (int i = 0; i < acls.length; i++) {
|
||||
// Locate processable AclEntrys
|
||||
if (acls[i] instanceof BasicAclEntry) {
|
||||
BasicAclEntry processableAcl = (BasicAclEntry) acls[i];
|
||||
|
||||
// See if principal has any of the required permissions
|
||||
for (int y = 0; y < requirePermission.length; y++) {
|
||||
if (processableAcl.isPermitted(requirePermission[y])) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Voting to grant access");
|
||||
}
|
||||
|
||||
return AccessDecisionVoter.ACCESS_GRANTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No permissions match
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
"Voting to deny access - ACLs returned, but insufficient permissions for this principal");
|
||||
}
|
||||
|
||||
return AccessDecisionVoter.ACCESS_DENIED;
|
||||
}
|
||||
}
|
||||
|
||||
// No configuration attribute matched, so abstain
|
||||
return AccessDecisionVoter.ACCESS_ABSTAIN;
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security;
|
||||
|
||||
import org.springframework.security.acl.AclEntry;
|
||||
import org.springframework.security.acl.AclManager;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the indicated collection of <code>AclEntry</code>s when the given <code>Authentication</code> principal
|
||||
* is presented for the indicated domain <code>Object</code> instance.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class MockAclManager implements AclManager {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private Object object;
|
||||
private Object principal;
|
||||
private AclEntry[] acls;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public MockAclManager(Object domainObject, Object principal, AclEntry[] acls) {
|
||||
this.object = domainObject;
|
||||
this.principal = principal;
|
||||
this.acls = acls;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public AclEntry[] getAcls(Object domainInstance, Authentication authentication) {
|
||||
if (domainInstance.equals(object) && authentication.getPrincipal().equals(principal)) {
|
||||
return acls;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public AclEntry[] getAcls(Object domainInstance) {
|
||||
if (domainInstance.equals(object)) {
|
||||
return acls;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,202 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.GrantedAuthority;
|
||||
import org.springframework.security.GrantedAuthorityImpl;
|
||||
|
||||
import org.springframework.security.acl.basic.NamedEntityObjectIdentity;
|
||||
import org.springframework.security.acl.basic.SimpleAclEntry;
|
||||
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link AclProviderManager}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AclProviderManagerTests extends TestCase {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public AclProviderManagerTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public AclProviderManagerTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private AclProviderManager makeProviderManager() {
|
||||
MockProvider provider1 = new MockProvider();
|
||||
List providers = new Vector();
|
||||
providers.add(provider1);
|
||||
|
||||
AclProviderManager mgr = new AclProviderManager();
|
||||
mgr.setProviders(providers);
|
||||
|
||||
return mgr;
|
||||
}
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testAclLookupFails() {
|
||||
AclProviderManager mgr = makeProviderManager();
|
||||
assertNull(mgr.getAcls(new Integer(5)));
|
||||
}
|
||||
|
||||
public void testAclLookupForGivenAuthenticationSuccess() {
|
||||
AclProviderManager mgr = makeProviderManager();
|
||||
assertNotNull(mgr.getAcls("STRING", new UsernamePasswordAuthenticationToken("rod", "not used")));
|
||||
}
|
||||
|
||||
public void testAclLookupSuccess() {
|
||||
AclProviderManager mgr = makeProviderManager();
|
||||
assertNotNull(mgr.getAcls("STRING"));
|
||||
}
|
||||
|
||||
public void testRejectsNulls() {
|
||||
AclProviderManager mgr = new AclProviderManager();
|
||||
|
||||
try {
|
||||
mgr.getAcls(null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
try {
|
||||
mgr.getAcls(null, new UsernamePasswordAuthenticationToken("rod", "not used"));
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
try {
|
||||
mgr.getAcls("SOME_DOMAIN_INSTANCE", null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testReturnsNullIfNoSupportingProvider() {
|
||||
AclProviderManager mgr = makeProviderManager();
|
||||
assertNull(mgr.getAcls(new Integer(4), new UsernamePasswordAuthenticationToken("rod", "not used")));
|
||||
assertNull(mgr.getAcls(new Integer(4)));
|
||||
}
|
||||
|
||||
public void testStartupFailsIfProviderListNotContainingProviders()
|
||||
throws Exception {
|
||||
List providers = new Vector();
|
||||
providers.add("THIS_IS_NOT_A_PROVIDER");
|
||||
|
||||
AclProviderManager mgr = new AclProviderManager();
|
||||
|
||||
try {
|
||||
mgr.setProviders(providers);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupFailsIfProviderListNotSet()
|
||||
throws Exception {
|
||||
AclProviderManager mgr = new AclProviderManager();
|
||||
|
||||
try {
|
||||
mgr.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupFailsIfProviderListNull() throws Exception {
|
||||
AclProviderManager mgr = new AclProviderManager();
|
||||
|
||||
try {
|
||||
mgr.setProviders(null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSuccessfulStartup() throws Exception {
|
||||
AclProviderManager mgr = makeProviderManager();
|
||||
mgr.afterPropertiesSet();
|
||||
assertTrue(true);
|
||||
assertEquals(1, mgr.getProviders().size());
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockProvider implements AclProvider {
|
||||
private UsernamePasswordAuthenticationToken rod = new UsernamePasswordAuthenticationToken("rod",
|
||||
"not used",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_FOO"), new GrantedAuthorityImpl("ROLE_BAR")});
|
||||
private SimpleAclEntry entry100rod = new SimpleAclEntry(rod.getPrincipal(),
|
||||
new NamedEntityObjectIdentity("OBJECT", "100"), null, 2);
|
||||
private UsernamePasswordAuthenticationToken scott = new UsernamePasswordAuthenticationToken("scott",
|
||||
"not used",
|
||||
new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_FOO"),
|
||||
new GrantedAuthorityImpl("ROLE_MANAGER")
|
||||
});
|
||||
private SimpleAclEntry entry100Scott = new SimpleAclEntry(scott.getPrincipal(),
|
||||
new NamedEntityObjectIdentity("OBJECT", "100"), null, 4);
|
||||
|
||||
public AclEntry[] getAcls(Object domainInstance, Authentication authentication) {
|
||||
if (authentication.getPrincipal().equals(scott.getPrincipal())) {
|
||||
return new AclEntry[] {entry100Scott};
|
||||
}
|
||||
|
||||
if (authentication.getPrincipal().equals(rod.getPrincipal())) {
|
||||
return new AclEntry[] {entry100rod};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public AclEntry[] getAcls(Object domainInstance) {
|
||||
return new AclEntry[] {entry100rod, entry100Scott};
|
||||
}
|
||||
|
||||
/**
|
||||
* Only supports <code>Object</code>s of type <code>String</code>
|
||||
*
|
||||
* @param domainInstance DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*/
|
||||
public boolean supports(Object domainInstance) {
|
||||
return (domainInstance instanceof String);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,391 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.PopulatedDatabase;
|
||||
|
||||
import org.springframework.security.acl.AclEntry;
|
||||
import org.springframework.security.acl.basic.cache.BasicAclEntryHolder;
|
||||
import org.springframework.security.acl.basic.cache.NullAclEntryCache;
|
||||
import org.springframework.security.acl.basic.jdbc.JdbcDaoImpl;
|
||||
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link BasicAclProvider}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BasicAclProviderTests extends TestCase {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
public static final String OBJECT_IDENTITY = "org.springframework.security.acl.DomainObject";
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public BasicAclProviderTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public BasicAclProviderTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(BasicAclProviderTests.class);
|
||||
}
|
||||
|
||||
private JdbcDaoImpl makePopulatedJdbcDao() throws Exception {
|
||||
JdbcDaoImpl dao = new JdbcDaoImpl();
|
||||
dao.setDataSource(PopulatedDatabase.getDataSource());
|
||||
dao.afterPropertiesSet();
|
||||
|
||||
return dao;
|
||||
}
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testCachingUsedProperly() throws Exception {
|
||||
BasicAclProvider provider = new BasicAclProvider();
|
||||
provider.setBasicAclDao(makePopulatedJdbcDao());
|
||||
|
||||
MockCache cache = new MockCache();
|
||||
provider.setBasicAclEntryCache(cache);
|
||||
|
||||
assertEquals(0, cache.getGets());
|
||||
assertEquals(0, cache.getGetsHits());
|
||||
assertEquals(0, cache.getPuts());
|
||||
assertEquals(0, cache.getBackingMap().size());
|
||||
|
||||
Object object = new MockDomain(1); // has no parents
|
||||
provider.getAcls(object);
|
||||
|
||||
assertEquals(1, cache.getGets());
|
||||
assertEquals(0, cache.getGetsHits());
|
||||
assertEquals(1, cache.getPuts());
|
||||
assertEquals(1, cache.getBackingMap().size());
|
||||
|
||||
provider.getAcls(object);
|
||||
|
||||
assertEquals(2, cache.getGets());
|
||||
assertEquals(1, cache.getGetsHits());
|
||||
assertEquals(1, cache.getPuts());
|
||||
assertEquals(1, cache.getBackingMap().size());
|
||||
|
||||
object = new MockDomain(1000); // does not exist
|
||||
|
||||
provider.getAcls(object);
|
||||
|
||||
assertEquals(3, cache.getGets());
|
||||
assertEquals(1, cache.getGetsHits());
|
||||
assertEquals(2, cache.getPuts());
|
||||
assertEquals(2, cache.getBackingMap().size());
|
||||
|
||||
provider.getAcls(object);
|
||||
|
||||
assertEquals(4, cache.getGets());
|
||||
assertEquals(2, cache.getGetsHits());
|
||||
assertEquals(2, cache.getPuts());
|
||||
assertEquals(2, cache.getBackingMap().size());
|
||||
|
||||
provider.getAcls(object);
|
||||
|
||||
assertEquals(5, cache.getGets());
|
||||
assertEquals(3, cache.getGetsHits());
|
||||
assertEquals(2, cache.getPuts());
|
||||
assertEquals(2, cache.getBackingMap().size());
|
||||
}
|
||||
|
||||
public void testExceptionThrownIfUnsupportedObjectIsSubmitted()
|
||||
throws Exception {
|
||||
BasicAclProvider provider = new BasicAclProvider();
|
||||
provider.setBasicAclDao(makePopulatedJdbcDao());
|
||||
|
||||
// this one should NOT be supported, as it has no getId() method
|
||||
assertFalse(provider.supports(new Integer(34)));
|
||||
|
||||
// try anyway
|
||||
try {
|
||||
provider.getAcls(new Integer(34));
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetAclsForInstanceNotFound() throws Exception {
|
||||
BasicAclProvider provider = new BasicAclProvider();
|
||||
provider.setBasicAclDao(makePopulatedJdbcDao());
|
||||
|
||||
Object object = new MockDomain(546464646);
|
||||
AclEntry[] acls = provider.getAcls(object);
|
||||
assertNull(acls);
|
||||
}
|
||||
|
||||
public void testGetAclsForInstanceWithParentLevels()
|
||||
throws Exception {
|
||||
BasicAclProvider provider = new BasicAclProvider();
|
||||
provider.setBasicAclDao(makePopulatedJdbcDao());
|
||||
|
||||
Object object = new MockDomain(6);
|
||||
AclEntry[] acls = provider.getAcls(object);
|
||||
assertEquals(2, acls.length);
|
||||
|
||||
assertEquals("scott", ((BasicAclEntry) acls[0]).getRecipient());
|
||||
assertEquals(1, ((BasicAclEntry) acls[0]).getMask());
|
||||
assertEquals("ROLE_SUPERVISOR", ((BasicAclEntry) acls[1]).getRecipient());
|
||||
}
|
||||
|
||||
public void testGetAclsForInstanceWithParentLevelsButNoDirectAclsAgainstInstance()
|
||||
throws Exception {
|
||||
BasicAclProvider provider = new BasicAclProvider();
|
||||
provider.setBasicAclDao(makePopulatedJdbcDao());
|
||||
|
||||
Object object = new MockDomain(5);
|
||||
AclEntry[] acls = provider.getAcls(object);
|
||||
|
||||
assertEquals(3, acls.length);
|
||||
|
||||
assertEquals("scott", ((BasicAclEntry) acls[0]).getRecipient());
|
||||
assertEquals(14, ((BasicAclEntry) acls[0]).getMask());
|
||||
assertEquals("ROLE_SUPERVISOR", ((BasicAclEntry) acls[1]).getRecipient());
|
||||
assertEquals(1, ((BasicAclEntry) acls[1]).getMask());
|
||||
assertEquals(JdbcDaoImpl.RECIPIENT_USED_FOR_INHERITENCE_MARKER, ((BasicAclEntry) acls[2]).getRecipient());
|
||||
}
|
||||
|
||||
public void testGetAclsWithAuthentication() throws Exception {
|
||||
BasicAclProvider provider = new BasicAclProvider();
|
||||
provider.setBasicAclDao(makePopulatedJdbcDao());
|
||||
|
||||
Authentication scott = new UsernamePasswordAuthenticationToken("scott", "unused");
|
||||
|
||||
Object object = new MockDomain(6);
|
||||
AclEntry[] acls = provider.getAcls(object, scott);
|
||||
|
||||
assertEquals(1, acls.length);
|
||||
assertEquals("scott", ((BasicAclEntry) acls[0]).getRecipient());
|
||||
}
|
||||
|
||||
public void testGettersSetters() {
|
||||
BasicAclProvider provider = new BasicAclProvider();
|
||||
assertEquals(NullAclEntryCache.class, provider.getBasicAclEntryCache().getClass());
|
||||
assertEquals(NamedEntityObjectIdentity.class, provider.getDefaultAclObjectIdentityClass());
|
||||
assertEquals(GrantedAuthorityEffectiveAclsResolver.class, provider.getEffectiveAclsResolver().getClass());
|
||||
|
||||
provider.setBasicAclEntryCache(null);
|
||||
assertNull(provider.getBasicAclEntryCache());
|
||||
|
||||
provider.setDefaultAclObjectIdentityClass(null);
|
||||
assertNull(provider.getDefaultAclObjectIdentityClass());
|
||||
|
||||
provider.setEffectiveAclsResolver(null);
|
||||
assertNull(provider.getEffectiveAclsResolver());
|
||||
|
||||
provider.setBasicAclDao(new MockDao());
|
||||
assertNotNull(provider.getBasicAclDao());
|
||||
|
||||
assertNull(provider.getRestrictSupportToClass());
|
||||
provider.setRestrictSupportToClass(SomeDomain.class);
|
||||
assertEquals(SomeDomain.class, provider.getRestrictSupportToClass());
|
||||
}
|
||||
|
||||
public void testStartupFailsIfNullAclDao() throws Exception {
|
||||
BasicAclProvider provider = new BasicAclProvider();
|
||||
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupFailsIfNullEffectiveAclsResolver()
|
||||
throws Exception {
|
||||
BasicAclProvider provider = new BasicAclProvider();
|
||||
provider.setBasicAclDao(makePopulatedJdbcDao());
|
||||
|
||||
provider.setEffectiveAclsResolver(null);
|
||||
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupFailsIfNullEntryCache() throws Exception {
|
||||
BasicAclProvider provider = new BasicAclProvider();
|
||||
provider.setBasicAclDao(makePopulatedJdbcDao());
|
||||
|
||||
provider.setBasicAclEntryCache(null);
|
||||
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupFailsIfProblemWithAclObjectIdentityClass()
|
||||
throws Exception {
|
||||
BasicAclProvider provider = new BasicAclProvider();
|
||||
provider.setBasicAclDao(makePopulatedJdbcDao());
|
||||
|
||||
// check nulls rejected
|
||||
provider.setDefaultAclObjectIdentityClass(null);
|
||||
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// check non-AclObjectIdentity classes are also rejected
|
||||
provider.setDefaultAclObjectIdentityClass(String.class);
|
||||
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// check AclObjectIdentity class without constructor accepting a
|
||||
// domain object is also rejected
|
||||
provider.setDefaultAclObjectIdentityClass(MockAclObjectIdentity.class);
|
||||
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("defaultAclObjectIdentityClass must provide a constructor that accepts the domain object instance!",
|
||||
expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testSupports() throws Exception {
|
||||
BasicAclProvider provider = new BasicAclProvider();
|
||||
provider.setBasicAclDao(makePopulatedJdbcDao());
|
||||
|
||||
// this one should NOT be supported, as it has no getId() method
|
||||
assertFalse(provider.supports(new Integer(34)));
|
||||
|
||||
// this one SHOULD be supported, as it has a getId() method
|
||||
assertTrue(provider.supports(new SomeDomain()));
|
||||
|
||||
// this one SHOULD be supported, as it implements AclObjectIdentityAware
|
||||
assertTrue(provider.supports(new MockDomain(4)));
|
||||
|
||||
// now restrict the provider to only respond to SomeDomain.class requests
|
||||
provider.setRestrictSupportToClass(SomeDomain.class);
|
||||
assertEquals(SomeDomain.class, provider.getRestrictSupportToClass());
|
||||
|
||||
// this one SHOULD be supported, as it has a getId() method AND it meets the restrictSupportToClass criteria
|
||||
assertTrue(provider.supports(new SomeDomain()));
|
||||
|
||||
// this one should NOT be suported, as whilst it implement AclObjectIdentityAware (as proven earlier in the test), it does NOT meet the restrictSupportToClass criteria
|
||||
assertFalse(provider.supports(new MockDomain(4)));
|
||||
}
|
||||
|
||||
public void testSupportsReturnsNullIfObjectNull() {
|
||||
BasicAclProvider provider = new BasicAclProvider();
|
||||
assertFalse(provider.supports(new Integer(34)));
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockCache implements BasicAclEntryCache {
|
||||
private Map map = new HashMap();
|
||||
private int gets = 0;
|
||||
private int getsHits = 0;
|
||||
private int puts = 0;
|
||||
|
||||
public Map getBackingMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
public BasicAclEntry[] getEntriesFromCache(AclObjectIdentity aclObjectIdentity) {
|
||||
gets++;
|
||||
|
||||
Object result = map.get(aclObjectIdentity);
|
||||
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
getsHits++;
|
||||
|
||||
BasicAclEntryHolder holder = (BasicAclEntryHolder) result;
|
||||
|
||||
return holder.getBasicAclEntries();
|
||||
}
|
||||
|
||||
public int getGets() {
|
||||
return gets;
|
||||
}
|
||||
|
||||
public int getGetsHits() {
|
||||
return getsHits;
|
||||
}
|
||||
|
||||
public int getPuts() {
|
||||
return puts;
|
||||
}
|
||||
|
||||
public void putEntriesInCache(BasicAclEntry[] basicAclEntry) {
|
||||
puts++;
|
||||
|
||||
BasicAclEntryHolder holder = new BasicAclEntryHolder(basicAclEntry);
|
||||
map.put(basicAclEntry[0].getAclObjectIdentity(), holder);
|
||||
}
|
||||
|
||||
public void removeEntriesFromCache(AclObjectIdentity aclObjectIdentity) {}
|
||||
}
|
||||
|
||||
private class MockDao implements BasicAclDao {
|
||||
public BasicAclEntry[] getAcls(AclObjectIdentity aclObjectIdentity) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class MockDomain implements AclObjectIdentityAware {
|
||||
private int id;
|
||||
|
||||
public MockDomain(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public AclObjectIdentity getAclObjectIdentity() {
|
||||
return new NamedEntityObjectIdentity(OBJECT_IDENTITY, new Integer(id).toString());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.GrantedAuthority;
|
||||
import org.springframework.security.GrantedAuthorityImpl;
|
||||
|
||||
import org.springframework.security.acl.AclEntry;
|
||||
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
|
||||
import org.springframework.security.userdetails.User;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link GrantedAuthorityEffectiveAclsResolver}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class GrantedAuthorityEffectiveAclsResolverTests extends TestCase {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private SimpleAclEntry entry100RoleEverybody = new SimpleAclEntry("ROLE_EVERYBODY",
|
||||
new NamedEntityObjectIdentity("OBJECT", "100"), null, 14);
|
||||
private SimpleAclEntry entry100RoleOne = new SimpleAclEntry("ROLE_ONE",
|
||||
new NamedEntityObjectIdentity("OBJECT", "100"), null, 0);
|
||||
private SimpleAclEntry entry100RoleTwo = new SimpleAclEntry("ROLE_TWO",
|
||||
new NamedEntityObjectIdentity("OBJECT", "100"), null, 2);
|
||||
private UsernamePasswordAuthenticationToken scott = new UsernamePasswordAuthenticationToken("scott", "not used",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_EVERYBODY"), new GrantedAuthorityImpl("ROLE_TWO")});
|
||||
private SimpleAclEntry entry100Scott = new SimpleAclEntry(scott.getPrincipal(),
|
||||
new NamedEntityObjectIdentity("OBJECT", "100"), null, 4);
|
||||
private UsernamePasswordAuthenticationToken dianne = new UsernamePasswordAuthenticationToken("dianne", "not used");
|
||||
private UsernamePasswordAuthenticationToken rod = new UsernamePasswordAuthenticationToken("rod",
|
||||
"not used",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_EVERYBODY"), new GrantedAuthorityImpl("ROLE_ONE")});
|
||||
private SimpleAclEntry entry100rod = new SimpleAclEntry(rod.getPrincipal(),
|
||||
new NamedEntityObjectIdentity("OBJECT", "100"), null, 2);
|
||||
private UsernamePasswordAuthenticationToken scottWithUserDetails = new UsernamePasswordAuthenticationToken(new User(
|
||||
"scott", "NOT_USED", true, true, true, true,
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_EVERYBODY")}), "not used",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_EVERYBODY"), new GrantedAuthorityImpl("ROLE_TWO")});
|
||||
|
||||
// convenience group
|
||||
private SimpleAclEntry[] acls = {
|
||||
entry100rod, entry100Scott, entry100RoleEverybody, entry100RoleOne, entry100RoleTwo
|
||||
};
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public GrantedAuthorityEffectiveAclsResolverTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public GrantedAuthorityEffectiveAclsResolverTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(GrantedAuthorityEffectiveAclsResolverTests.class);
|
||||
}
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testResolveAclsForDianneWhoHasANullForAuthorities() {
|
||||
GrantedAuthorityEffectiveAclsResolver resolver = new GrantedAuthorityEffectiveAclsResolver();
|
||||
assertNull(resolver.resolveEffectiveAcls(acls, dianne));
|
||||
}
|
||||
|
||||
public void testResolveAclsForrod() {
|
||||
GrantedAuthorityEffectiveAclsResolver resolver = new GrantedAuthorityEffectiveAclsResolver();
|
||||
assertEquals(3, resolver.resolveEffectiveAcls(acls, rod).length);
|
||||
assertEquals(entry100rod, resolver.resolveEffectiveAcls(acls, rod)[0]);
|
||||
assertEquals(entry100RoleEverybody, resolver.resolveEffectiveAcls(acls, rod)[1]);
|
||||
assertEquals(entry100RoleOne, resolver.resolveEffectiveAcls(acls, rod)[2]);
|
||||
}
|
||||
|
||||
public void testResolveAclsForScottWithStringObjectAsPrincipal() {
|
||||
GrantedAuthorityEffectiveAclsResolver resolver = new GrantedAuthorityEffectiveAclsResolver();
|
||||
assertEquals(3, resolver.resolveEffectiveAcls(acls, scott).length);
|
||||
assertEquals(entry100Scott, resolver.resolveEffectiveAcls(acls, scott)[0]);
|
||||
assertEquals(entry100RoleEverybody, resolver.resolveEffectiveAcls(acls, scott)[1]);
|
||||
assertEquals(entry100RoleTwo, resolver.resolveEffectiveAcls(acls, scott)[2]);
|
||||
}
|
||||
|
||||
public void testResolveAclsForScottWithUserDetailsObjectAsPrincipal() {
|
||||
GrantedAuthorityEffectiveAclsResolver resolver = new GrantedAuthorityEffectiveAclsResolver();
|
||||
assertEquals(3, resolver.resolveEffectiveAcls(acls, scottWithUserDetails).length);
|
||||
assertEquals(entry100Scott, resolver.resolveEffectiveAcls(acls, scottWithUserDetails)[0]);
|
||||
assertEquals(entry100RoleEverybody, resolver.resolveEffectiveAcls(acls, scottWithUserDetails)[1]);
|
||||
assertEquals(entry100RoleTwo, resolver.resolveEffectiveAcls(acls, scottWithUserDetails)[2]);
|
||||
}
|
||||
|
||||
public void testResolveAclsReturnsNullIfNoAclsInFirstPlace() {
|
||||
GrantedAuthorityEffectiveAclsResolver resolver = new GrantedAuthorityEffectiveAclsResolver();
|
||||
assertNull(resolver.resolveEffectiveAcls(null, scott));
|
||||
}
|
||||
|
||||
public void testSkipsNonBasicAclEntryObjects() {
|
||||
GrantedAuthorityEffectiveAclsResolver resolver = new GrantedAuthorityEffectiveAclsResolver();
|
||||
AclEntry[] basicAcls = {
|
||||
entry100rod, entry100Scott, entry100RoleEverybody, entry100RoleOne, new MockAcl(), entry100RoleTwo
|
||||
};
|
||||
assertEquals(3, resolver.resolveEffectiveAcls(basicAcls, rod).length);
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockAcl implements AclEntry {
|
||||
// does nothing
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
/**
|
||||
* Implements <code>AclObjectIdentity</code> but is incompatible with <code>BasicAclProvider</code> because it
|
||||
* cannot be constructed by passing in a domain object instance.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class MockAclObjectIdentity implements AclObjectIdentity {
|
||||
// has no "public MockAclObjectIdentity(Object object)" constructor!
|
||||
}
|
@ -1,134 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link NamedEntityObjectIdentity}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class NamedEntityObjectIdentityTests extends TestCase {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public NamedEntityObjectIdentityTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public NamedEntityObjectIdentityTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(NamedEntityObjectIdentityTests.class);
|
||||
}
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testConstructionViaReflection() throws Exception {
|
||||
SomeDomain domainObject = new SomeDomain();
|
||||
domainObject.setId(34);
|
||||
|
||||
NamedEntityObjectIdentity name = new NamedEntityObjectIdentity(domainObject);
|
||||
assertEquals("34", name.getId());
|
||||
assertEquals(domainObject.getClass().getName(), name.getClassname());
|
||||
name.toString();
|
||||
}
|
||||
|
||||
public void testConstructionViaReflectionFailsIfNoGetIdMethod()
|
||||
throws Exception {
|
||||
try {
|
||||
new NamedEntityObjectIdentity(new Integer(45));
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testConstructionViaReflectionFailsIfNullPassed()
|
||||
throws Exception {
|
||||
try {
|
||||
new NamedEntityObjectIdentity(null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testEquality() {
|
||||
NamedEntityObjectIdentity original = new NamedEntityObjectIdentity("foo", "12");
|
||||
assertFalse(original.equals(null));
|
||||
assertFalse(original.equals(new Integer(354)));
|
||||
assertFalse(original.equals(new NamedEntityObjectIdentity("foo", "23232")));
|
||||
assertTrue(original.equals(new NamedEntityObjectIdentity("foo", "12")));
|
||||
assertTrue(original.equals(original));
|
||||
}
|
||||
|
||||
public void testNoArgConstructorDoesntExist() {
|
||||
Class clazz = NamedEntityObjectIdentity.class;
|
||||
|
||||
try {
|
||||
clazz.getDeclaredConstructor((Class[]) null);
|
||||
fail("Should have thrown NoSuchMethodException");
|
||||
} catch (NoSuchMethodException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testNormalConstructionRejectedIfInvalidArguments()
|
||||
throws Exception {
|
||||
try {
|
||||
new NamedEntityObjectIdentity(null, "12");
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
try {
|
||||
new NamedEntityObjectIdentity("classname", null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
try {
|
||||
new NamedEntityObjectIdentity("", "12");
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
try {
|
||||
new NamedEntityObjectIdentity("classname", "");
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testNormalOperation() {
|
||||
NamedEntityObjectIdentity name = new NamedEntityObjectIdentity("domain", "id");
|
||||
assertEquals("domain", name.getClassname());
|
||||
assertEquals("id", name.getId());
|
||||
}
|
||||
}
|
@ -1,207 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Tests {@link SimpleAclEntry}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SimpleAclEntryTests extends TestCase {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public SimpleAclEntryTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public SimpleAclEntryTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(SimpleAclEntryTests.class);
|
||||
}
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testCorrectOperation() {
|
||||
String recipient = "rod";
|
||||
AclObjectIdentity objectIdentity = new NamedEntityObjectIdentity("domain", "12");
|
||||
SimpleAclEntry acl = new SimpleAclEntry(recipient, objectIdentity, null, 0);
|
||||
|
||||
assertFalse(acl.isPermitted(SimpleAclEntry.ADMINISTRATION));
|
||||
acl.addPermission(SimpleAclEntry.ADMINISTRATION);
|
||||
assertTrue(acl.isPermitted(SimpleAclEntry.ADMINISTRATION));
|
||||
assertFalse(acl.isPermitted(SimpleAclEntry.CREATE));
|
||||
assertFalse(acl.isPermitted(SimpleAclEntry.DELETE));
|
||||
assertFalse(acl.isPermitted(SimpleAclEntry.READ));
|
||||
assertFalse(acl.isPermitted(SimpleAclEntry.WRITE));
|
||||
assertEquals("A----", acl.printPermissionsBlock());
|
||||
acl.deletePermission(SimpleAclEntry.ADMINISTRATION);
|
||||
assertFalse(acl.isPermitted(SimpleAclEntry.ADMINISTRATION));
|
||||
assertEquals("-----", acl.printPermissionsBlock());
|
||||
|
||||
acl.addPermissions(new int[] {SimpleAclEntry.READ, SimpleAclEntry.WRITE});
|
||||
acl.addPermission(SimpleAclEntry.CREATE);
|
||||
assertFalse(acl.isPermitted(SimpleAclEntry.ADMINISTRATION));
|
||||
assertTrue(acl.isPermitted(SimpleAclEntry.CREATE));
|
||||
assertFalse(acl.isPermitted(SimpleAclEntry.DELETE));
|
||||
assertTrue(acl.isPermitted(SimpleAclEntry.READ));
|
||||
assertTrue(acl.isPermitted(SimpleAclEntry.WRITE));
|
||||
assertEquals("-RWC-", acl.printPermissionsBlock());
|
||||
|
||||
acl.deletePermission(SimpleAclEntry.CREATE);
|
||||
acl.deletePermissions(new int[] {SimpleAclEntry.READ, SimpleAclEntry.WRITE});
|
||||
assertEquals("-----", acl.printPermissionsBlock());
|
||||
|
||||
acl.togglePermission(SimpleAclEntry.CREATE);
|
||||
assertTrue(acl.isPermitted(SimpleAclEntry.CREATE));
|
||||
assertFalse(acl.isPermitted(SimpleAclEntry.ADMINISTRATION));
|
||||
acl.togglePermission(SimpleAclEntry.CREATE);
|
||||
assertFalse(acl.isPermitted(SimpleAclEntry.CREATE));
|
||||
|
||||
acl.togglePermission(SimpleAclEntry.DELETE);
|
||||
assertTrue(acl.isPermitted(SimpleAclEntry.DELETE));
|
||||
assertEquals("----D", acl.printPermissionsBlock());
|
||||
}
|
||||
|
||||
public void testDetectsNullOnMainConstructor() {
|
||||
String recipient = "rod";
|
||||
AclObjectIdentity objectIdentity = new NamedEntityObjectIdentity("domain", "12");
|
||||
|
||||
try {
|
||||
new SimpleAclEntry(recipient, null, null, 2);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
try {
|
||||
new SimpleAclEntry(null, objectIdentity, null, 2);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGettersSetters() {
|
||||
SimpleAclEntry acl = new SimpleAclEntry();
|
||||
|
||||
AclObjectIdentity objectIdentity = new NamedEntityObjectIdentity("domain", "693");
|
||||
acl.setAclObjectIdentity(objectIdentity);
|
||||
assertEquals(objectIdentity, acl.getAclObjectIdentity());
|
||||
|
||||
AclObjectIdentity parentObjectIdentity = new NamedEntityObjectIdentity("domain", "13");
|
||||
acl.setAclObjectParentIdentity(parentObjectIdentity);
|
||||
assertEquals(parentObjectIdentity, acl.getAclObjectParentIdentity());
|
||||
|
||||
acl.setMask(2);
|
||||
assertEquals(2, acl.getMask());
|
||||
|
||||
acl.setRecipient("scott");
|
||||
assertEquals("scott", acl.getRecipient());
|
||||
}
|
||||
|
||||
public void testRejectsInvalidMasksInAddMethod() {
|
||||
String recipient = "rod";
|
||||
AclObjectIdentity objectIdentity = new NamedEntityObjectIdentity("domain", "12");
|
||||
SimpleAclEntry acl = new SimpleAclEntry(recipient, objectIdentity, null, 4);
|
||||
|
||||
try {
|
||||
acl.addPermission(Integer.MAX_VALUE);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testRejectsInvalidMasksInDeleteMethod() {
|
||||
String recipient = "rod";
|
||||
AclObjectIdentity objectIdentity = new NamedEntityObjectIdentity("domain", "12");
|
||||
SimpleAclEntry acl = new SimpleAclEntry(recipient, objectIdentity, null, 0);
|
||||
acl.addPermissions(new int[] {SimpleAclEntry.READ, SimpleAclEntry.WRITE, SimpleAclEntry.CREATE});
|
||||
|
||||
try {
|
||||
acl.deletePermission(SimpleAclEntry.READ); // can't write if we can't read
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testRejectsInvalidMasksInTogglePermissionMethod() {
|
||||
String recipient = "rod";
|
||||
AclObjectIdentity objectIdentity = new NamedEntityObjectIdentity("domain", "12");
|
||||
SimpleAclEntry acl = new SimpleAclEntry(recipient, objectIdentity, null, 0);
|
||||
acl.addPermissions(new int[] {SimpleAclEntry.READ, SimpleAclEntry.WRITE, SimpleAclEntry.CREATE});
|
||||
|
||||
try {
|
||||
acl.togglePermission(SimpleAclEntry.READ); // can't write if we can't read
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testToString() {
|
||||
String recipient = "rod";
|
||||
AclObjectIdentity objectIdentity = new NamedEntityObjectIdentity("domain", "12");
|
||||
SimpleAclEntry acl = new SimpleAclEntry(recipient, objectIdentity, null, 0);
|
||||
acl.addPermissions(new int[] {SimpleAclEntry.READ, SimpleAclEntry.WRITE, SimpleAclEntry.CREATE});
|
||||
assertTrue(acl.toString().endsWith("rod=-RWC- ............................111. (14)]"));
|
||||
}
|
||||
|
||||
public void testParsePermission() {
|
||||
assertPermission("NOTHING", SimpleAclEntry.NOTHING);
|
||||
assertPermission("ADMINISTRATION", SimpleAclEntry.ADMINISTRATION);
|
||||
assertPermission("READ", SimpleAclEntry.READ);
|
||||
assertPermission("WRITE", SimpleAclEntry.WRITE);
|
||||
assertPermission("CREATE", SimpleAclEntry.CREATE);
|
||||
assertPermission("DELETE", SimpleAclEntry.DELETE);
|
||||
assertPermission("READ_WRITE_DELETE", SimpleAclEntry.READ_WRITE_DELETE);
|
||||
}
|
||||
|
||||
public void testParsePermissionWrongValues() {
|
||||
try {
|
||||
SimpleAclEntry.parsePermission("X");
|
||||
fail(IllegalArgumentException.class.getName() + " must have been thrown.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
private void assertPermission(String permission, int value) {
|
||||
assertEquals(value, SimpleAclEntry.parsePermission(permission));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the value returned by {@link SimpleAclEntry#getValidPermissions()} is not modifiable.
|
||||
*/
|
||||
public void testGetPermissions() {
|
||||
SimpleAclEntry acl = new SimpleAclEntry("", new NamedEntityObjectIdentity("x", "x"), null, 0);
|
||||
int[] permissions = acl.getValidPermissions();
|
||||
int i = permissions[0];
|
||||
permissions[0] -= 100;
|
||||
assertEquals("Value returned by getValidPermissions can be modified", i, acl.getValidPermissions()[0]);
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic;
|
||||
|
||||
/**
|
||||
* Simple object to use when testing <code>NamedEntityObjectIdentity</code>.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SomeDomain {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private int id;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic.cache;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.acl.basic.BasicAclEntry;
|
||||
import org.springframework.security.acl.basic.SimpleAclEntry;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link BasicAclEntryHolder}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BasicAclEntryHolderTests extends TestCase {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public BasicAclEntryHolderTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public BasicAclEntryHolderTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(BasicAclEntryHolderTests.class);
|
||||
}
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testRejectsNull() throws Exception {
|
||||
try {
|
||||
new BasicAclEntryHolder(null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
try {
|
||||
new BasicAclEntryHolder(new BasicAclEntry[] {new SimpleAclEntry(), null, new SimpleAclEntry()});
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic.cache;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.Cache;
|
||||
|
||||
import org.springframework.security.acl.basic.AclObjectIdentity;
|
||||
import org.springframework.security.acl.basic.BasicAclEntry;
|
||||
import org.springframework.security.acl.basic.NamedEntityObjectIdentity;
|
||||
import org.springframework.security.acl.basic.SimpleAclEntry;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link EhCacheBasedAclEntryCache}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class EhCacheBasedAclEntryCacheTests {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final AclObjectIdentity OBJECT_100 = new NamedEntityObjectIdentity("OBJECT", "100");
|
||||
private static final AclObjectIdentity OBJECT_200 = new NamedEntityObjectIdentity("OBJECT", "200");
|
||||
private static final BasicAclEntry OBJECT_100_ROD = new SimpleAclEntry("rod", OBJECT_100, null, 2);
|
||||
private static final BasicAclEntry OBJECT_100_SCOTT = new SimpleAclEntry("scott", OBJECT_100, null, 4);
|
||||
private static final BasicAclEntry OBJECT_200_PETER = new SimpleAclEntry("peter", OBJECT_200, null, 4);
|
||||
|
||||
private static CacheManager cacheManager;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@BeforeClass
|
||||
public static void initCacheManaer() {
|
||||
cacheManager = new CacheManager();
|
||||
cacheManager.addCache(new Cache("ehcachebasedacltests", 500, false, false, 30, 30));
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void shutdownCacheManager() {
|
||||
cacheManager.removalAll();
|
||||
cacheManager.shutdown();
|
||||
}
|
||||
|
||||
private Ehcache getCache() {
|
||||
Ehcache cache = cacheManager.getCache("ehcachebasedacltests");
|
||||
cache.removeAll();
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheOperationSucceeds() throws Exception {
|
||||
EhCacheBasedAclEntryCache cache = new EhCacheBasedAclEntryCache();
|
||||
cache.setCache(getCache());
|
||||
cache.afterPropertiesSet();
|
||||
|
||||
cache.putEntriesInCache(new BasicAclEntry[] {OBJECT_100_SCOTT, OBJECT_100_ROD});
|
||||
cache.putEntriesInCache(new BasicAclEntry[] {OBJECT_200_PETER});
|
||||
|
||||
// Check we can get them from cache again
|
||||
assertEquals(OBJECT_100_SCOTT, cache.getEntriesFromCache(new NamedEntityObjectIdentity("OBJECT", "100"))[0]);
|
||||
assertEquals(OBJECT_100_ROD, cache.getEntriesFromCache(new NamedEntityObjectIdentity("OBJECT", "100"))[1]);
|
||||
assertEquals(OBJECT_200_PETER, cache.getEntriesFromCache(new NamedEntityObjectIdentity("OBJECT", "200"))[0]);
|
||||
assertNull(cache.getEntriesFromCache(new NamedEntityObjectIdentity("OBJECT", "NOT_IN_CACHE")));
|
||||
|
||||
// Check after eviction we cannot get them from cache
|
||||
cache.removeEntriesFromCache(new NamedEntityObjectIdentity("OBJECT", "100"));
|
||||
assertNull(cache.getEntriesFromCache(new NamedEntityObjectIdentity("OBJECT", "100")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startupDetectsMissingCache() throws Exception {
|
||||
EhCacheBasedAclEntryCache cache = new EhCacheBasedAclEntryCache();
|
||||
|
||||
try {
|
||||
cache.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
Ehcache myCache = getCache();
|
||||
cache.setCache(myCache);
|
||||
assertEquals(myCache, cache.getCache());
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic.cache;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.acl.basic.BasicAclEntry;
|
||||
import org.springframework.security.acl.basic.NamedEntityObjectIdentity;
|
||||
import org.springframework.security.acl.basic.SimpleAclEntry;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link NullAclEntryCache}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class NullAclEntryCacheTests extends TestCase {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public NullAclEntryCacheTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public NullAclEntryCacheTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(NullAclEntryCacheTests.class);
|
||||
}
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testCacheOperation() throws Exception {
|
||||
NullAclEntryCache cache = new NullAclEntryCache();
|
||||
cache.putEntriesInCache(new BasicAclEntry[] {new SimpleAclEntry()});
|
||||
cache.getEntriesFromCache(new NamedEntityObjectIdentity("not_used", "not_used"));
|
||||
cache.removeEntriesFromCache(new NamedEntityObjectIdentity("not_used", "not_used"));
|
||||
}
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic.jdbc;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.PopulatedDatabase;
|
||||
|
||||
import org.springframework.security.acl.basic.AclObjectIdentity;
|
||||
import org.springframework.security.acl.basic.BasicAclEntry;
|
||||
import org.springframework.security.acl.basic.NamedEntityObjectIdentity;
|
||||
|
||||
import org.springframework.jdbc.object.MappingSqlQuery;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link JdbcDaoImpl}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class JdbcDaoImplTests extends TestCase {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
public static final String OBJECT_IDENTITY = "org.springframework.security.acl.DomainObject";
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public JdbcDaoImplTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public JdbcDaoImplTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(JdbcDaoImplTests.class);
|
||||
}
|
||||
|
||||
private JdbcDaoImpl makePopulatedJdbcDao() throws Exception {
|
||||
JdbcDaoImpl dao = new JdbcDaoImpl();
|
||||
dao.setDataSource(PopulatedDatabase.getDataSource());
|
||||
dao.afterPropertiesSet();
|
||||
|
||||
return dao;
|
||||
}
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testExceptionThrownIfBasicAclEntryClassNotFound()
|
||||
throws Exception {
|
||||
JdbcDaoImpl dao = makePopulatedJdbcDao();
|
||||
AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "7");
|
||||
|
||||
try {
|
||||
dao.getAcls(identity);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetsEntriesWhichExistInDatabaseAndHaveAcls()
|
||||
throws Exception {
|
||||
JdbcDaoImpl dao = makePopulatedJdbcDao();
|
||||
AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "2");
|
||||
BasicAclEntry[] acls = dao.getAcls(identity);
|
||||
assertEquals(2, acls.length);
|
||||
}
|
||||
|
||||
public void testGetsEntriesWhichExistInDatabaseButHaveNoAcls()
|
||||
throws Exception {
|
||||
JdbcDaoImpl dao = makePopulatedJdbcDao();
|
||||
AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "5");
|
||||
BasicAclEntry[] acls = dao.getAcls(identity);
|
||||
assertEquals(1, acls.length);
|
||||
assertEquals(JdbcDaoImpl.RECIPIENT_USED_FOR_INHERITENCE_MARKER, acls[0].getRecipient());
|
||||
}
|
||||
|
||||
public void testGetsEntriesWhichHaveNoParent() throws Exception {
|
||||
JdbcDaoImpl dao = makePopulatedJdbcDao();
|
||||
AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "1");
|
||||
BasicAclEntry[] acls = dao.getAcls(identity);
|
||||
assertEquals(1, acls.length);
|
||||
assertNull(acls[0].getAclObjectParentIdentity());
|
||||
}
|
||||
|
||||
public void testGettersSetters() throws Exception {
|
||||
JdbcDaoImpl dao = makePopulatedJdbcDao();
|
||||
dao.setAclsByObjectIdentity(new MockMappingSqlQuery());
|
||||
assertNotNull(dao.getAclsByObjectIdentity());
|
||||
|
||||
dao.setAclsByObjectIdentityQuery("foo");
|
||||
assertEquals("foo", dao.getAclsByObjectIdentityQuery());
|
||||
|
||||
dao.setObjectPropertiesQuery("foobar");
|
||||
assertEquals("foobar", dao.getObjectPropertiesQuery());
|
||||
}
|
||||
|
||||
public void testNullReturnedIfEntityNotFound() throws Exception {
|
||||
JdbcDaoImpl dao = makePopulatedJdbcDao();
|
||||
AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "NOT_VALID_ID");
|
||||
BasicAclEntry[] result = dao.getAcls(identity);
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
public void testReturnsNullForUnNamedEntityObjectIdentity()
|
||||
throws Exception {
|
||||
JdbcDaoImpl dao = new JdbcDaoImpl();
|
||||
AclObjectIdentity identity = new AclObjectIdentity() {}
|
||||
;
|
||||
|
||||
assertNull(dao.getAcls(identity));
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockMappingSqlQuery extends MappingSqlQuery {
|
||||
protected Object mapRow(ResultSet arg0, int arg1)
|
||||
throws SQLException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,312 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.acl.basic.jdbc;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.PopulatedDatabase;
|
||||
|
||||
import org.springframework.security.acl.basic.AclObjectIdentity;
|
||||
import org.springframework.security.acl.basic.BasicAclEntry;
|
||||
import org.springframework.security.acl.basic.NamedEntityObjectIdentity;
|
||||
import org.springframework.security.acl.basic.SimpleAclEntry;
|
||||
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
|
||||
import org.springframework.jdbc.object.MappingSqlQuery;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link JdbcExtendedDaoImpl}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class JdbcExtendedDaoImplTests extends TestCase {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
public static final String OBJECT_IDENTITY = "org.springframework.security.acl.DomainObject";
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public JdbcExtendedDaoImplTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public JdbcExtendedDaoImplTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(JdbcExtendedDaoImplTests.class);
|
||||
}
|
||||
|
||||
private JdbcExtendedDaoImpl makePopulatedJdbcDao()
|
||||
throws Exception {
|
||||
JdbcExtendedDaoImpl dao = new JdbcExtendedDaoImpl();
|
||||
dao.setDataSource(PopulatedDatabase.getDataSource());
|
||||
dao.afterPropertiesSet();
|
||||
|
||||
return dao;
|
||||
}
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testChangeMask() throws Exception {
|
||||
JdbcExtendedDaoImpl dao = makePopulatedJdbcDao();
|
||||
AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "204");
|
||||
AclObjectIdentity parentIdentity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "1");
|
||||
|
||||
// Create a BasicAclEntry for this AclObjectIdentity
|
||||
SimpleAclEntry simpleAcl1 = new SimpleAclEntry("rod", identity, parentIdentity, SimpleAclEntry.CREATE);
|
||||
dao.create(simpleAcl1);
|
||||
|
||||
// Create another BasicAclEntry for this AclObjectIdentity
|
||||
SimpleAclEntry simpleAcl2 = new SimpleAclEntry("scott", identity, parentIdentity, SimpleAclEntry.READ);
|
||||
dao.create(simpleAcl2);
|
||||
|
||||
// Check creation was successful
|
||||
BasicAclEntry[] acls = dao.getAcls(identity);
|
||||
assertEquals(2, acls.length);
|
||||
assertEquals(SimpleAclEntry.CREATE, acls[0].getMask());
|
||||
assertEquals(SimpleAclEntry.READ, acls[1].getMask());
|
||||
|
||||
// Attempt to change mask
|
||||
dao.changeMask(identity, "rod", new Integer(SimpleAclEntry.ADMINISTRATION));
|
||||
dao.changeMask(identity, "scott", new Integer(SimpleAclEntry.NOTHING));
|
||||
acls = dao.getAcls(identity);
|
||||
assertEquals(2, acls.length);
|
||||
assertEquals("rod", acls[0].getRecipient());
|
||||
assertEquals(SimpleAclEntry.ADMINISTRATION, acls[0].getMask());
|
||||
assertEquals("scott", acls[1].getRecipient());
|
||||
assertEquals(SimpleAclEntry.NOTHING, acls[1].getMask());
|
||||
}
|
||||
|
||||
public void testChangeMaskThrowsExceptionWhenExistingRecordNotFound()
|
||||
throws Exception {
|
||||
JdbcExtendedDaoImpl dao = makePopulatedJdbcDao();
|
||||
AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "205");
|
||||
AclObjectIdentity parentIdentity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "1");
|
||||
|
||||
// Create at least one record for this AclObjectIdentity
|
||||
SimpleAclEntry simpleAcl1 = new SimpleAclEntry("rod", identity, parentIdentity, SimpleAclEntry.CREATE);
|
||||
dao.create(simpleAcl1);
|
||||
|
||||
// Attempt to change mask, but for a recipient we don't have
|
||||
try {
|
||||
dao.changeMask(identity, "scott", new Integer(SimpleAclEntry.ADMINISTRATION));
|
||||
fail("Should have thrown DataRetrievalFailureException");
|
||||
} catch (DataRetrievalFailureException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testConvertAclObjectIdentity() throws Exception {
|
||||
JdbcExtendedDaoImpl dao = makePopulatedJdbcDao();
|
||||
|
||||
try {
|
||||
dao.convertAclObjectIdentityToString(new AclObjectIdentity() {
|
||||
// not a NamedEntityObjectIdentity
|
||||
});
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreationOfIdentityThenAclInSeparateInvocations()
|
||||
throws Exception {
|
||||
JdbcExtendedDaoImpl dao = makePopulatedJdbcDao();
|
||||
AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "206");
|
||||
AclObjectIdentity parentIdentity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "1");
|
||||
|
||||
// Create just the object identity (NB: recipient and mask is null)
|
||||
SimpleAclEntry simpleAcl1 = new SimpleAclEntry();
|
||||
simpleAcl1.setAclObjectIdentity(identity);
|
||||
simpleAcl1.setAclObjectParentIdentity(parentIdentity);
|
||||
dao.create(simpleAcl1);
|
||||
|
||||
// Delete it
|
||||
dao.delete(identity);
|
||||
}
|
||||
|
||||
public void testDeletionOfAllRecipients() throws Exception {
|
||||
JdbcExtendedDaoImpl dao = makePopulatedJdbcDao();
|
||||
AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "203");
|
||||
|
||||
// Create a BasicAclEntry for this AclObjectIdentity
|
||||
SimpleAclEntry simpleAcl1 = new SimpleAclEntry("rod", identity, null, SimpleAclEntry.CREATE);
|
||||
dao.create(simpleAcl1);
|
||||
|
||||
// Create another BasicAclEntry for this AclObjectIdentity
|
||||
SimpleAclEntry simpleAcl2 = new SimpleAclEntry("scott", identity, null, SimpleAclEntry.READ);
|
||||
dao.create(simpleAcl2);
|
||||
|
||||
// Check creation was successful
|
||||
BasicAclEntry[] acls = dao.getAcls(identity);
|
||||
assertEquals(2, acls.length);
|
||||
|
||||
// Attempt deletion and check delete successful
|
||||
dao.delete(identity);
|
||||
assertNull(dao.getAcls(identity));
|
||||
}
|
||||
|
||||
public void testDeletionOfSpecificRecipient() throws Exception {
|
||||
JdbcExtendedDaoImpl dao = makePopulatedJdbcDao();
|
||||
AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "202");
|
||||
AclObjectIdentity parentIdentity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "1");
|
||||
|
||||
// Create a BasicAclEntry for this AclObjectIdentity
|
||||
SimpleAclEntry simpleAcl1 = new SimpleAclEntry("rod", identity, parentIdentity, SimpleAclEntry.CREATE);
|
||||
dao.create(simpleAcl1);
|
||||
|
||||
// Create another BasicAclEntry for this AclObjectIdentity
|
||||
SimpleAclEntry simpleAcl2 = new SimpleAclEntry("scott", identity, parentIdentity, SimpleAclEntry.READ);
|
||||
dao.create(simpleAcl2);
|
||||
|
||||
// Check creation was successful
|
||||
BasicAclEntry[] acls = dao.getAcls(identity);
|
||||
assertEquals(2, acls.length);
|
||||
|
||||
// Attempt deletion and check delete successful
|
||||
dao.delete(identity, "scott");
|
||||
acls = dao.getAcls(identity);
|
||||
assertEquals(1, acls.length);
|
||||
assertEquals(simpleAcl1.getRecipient(), acls[0].getRecipient());
|
||||
}
|
||||
|
||||
public void testGettersSetters() throws Exception {
|
||||
JdbcExtendedDaoImpl dao = makePopulatedJdbcDao();
|
||||
|
||||
assertNotNull(dao.getAclObjectIdentityDelete());
|
||||
dao.setAclObjectIdentityDelete(null);
|
||||
assertNull(dao.getAclObjectIdentityDelete());
|
||||
|
||||
assertNotNull(dao.getAclObjectIdentityInsert());
|
||||
dao.setAclObjectIdentityInsert(null);
|
||||
assertNull(dao.getAclObjectIdentityInsert());
|
||||
|
||||
assertNotNull(dao.getAclPermissionDelete());
|
||||
dao.setAclPermissionDelete(null);
|
||||
assertNull(dao.getAclPermissionDelete());
|
||||
|
||||
assertNotNull(dao.getAclPermissionInsert());
|
||||
dao.setAclPermissionInsert(null);
|
||||
assertNull(dao.getAclPermissionInsert());
|
||||
|
||||
assertNotNull(dao.getAclPermissionUpdate());
|
||||
dao.setAclPermissionUpdate(null);
|
||||
assertNull(dao.getAclPermissionUpdate());
|
||||
|
||||
assertNotNull(dao.getAclsByObjectIdentity());
|
||||
dao.setAclsByObjectIdentity(null);
|
||||
assertNull(dao.getAclsByObjectIdentity());
|
||||
|
||||
assertNotNull(dao.getLookupPermissionIdMapping());
|
||||
dao.setLookupPermissionIdMapping(null);
|
||||
assertNull(dao.getLookupPermissionIdMapping());
|
||||
|
||||
assertNotNull(dao.getAclObjectIdentityDeleteStatement());
|
||||
dao.setAclObjectIdentityDeleteStatement("SELECT ...");
|
||||
assertEquals("SELECT ...", dao.getAclObjectIdentityDeleteStatement());
|
||||
|
||||
assertNotNull(dao.getAclObjectIdentityInsertStatement());
|
||||
dao.setAclObjectIdentityInsertStatement("SELECT ...");
|
||||
assertEquals("SELECT ...", dao.getAclObjectIdentityInsertStatement());
|
||||
|
||||
assertNotNull(dao.getAclPermissionDeleteStatement());
|
||||
dao.setAclPermissionDeleteStatement("SELECT ...");
|
||||
assertEquals("SELECT ...", dao.getAclPermissionDeleteStatement());
|
||||
|
||||
assertNotNull(dao.getAclPermissionInsertStatement());
|
||||
dao.setAclPermissionInsertStatement("SELECT ...");
|
||||
assertEquals("SELECT ...", dao.getAclPermissionInsertStatement());
|
||||
|
||||
assertNotNull(dao.getAclPermissionUpdateStatement());
|
||||
dao.setAclPermissionUpdateStatement("SELECT ...");
|
||||
assertEquals("SELECT ...", dao.getAclPermissionUpdateStatement());
|
||||
|
||||
assertNotNull(dao.getAclsByObjectIdentityQuery());
|
||||
dao.setAclsByObjectIdentityQuery("SELECT ...");
|
||||
assertEquals("SELECT ...", dao.getAclsByObjectIdentityQuery());
|
||||
|
||||
assertNotNull(dao.getLookupPermissionIdQuery());
|
||||
dao.setLookupPermissionIdQuery("SELECT ...");
|
||||
assertEquals("SELECT ...", dao.getLookupPermissionIdQuery());
|
||||
}
|
||||
|
||||
public void testNormalCreationAndDuplicateDetection()
|
||||
throws Exception {
|
||||
JdbcExtendedDaoImpl dao = makePopulatedJdbcDao();
|
||||
AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "200");
|
||||
AclObjectIdentity parentIdentity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "1");
|
||||
|
||||
// Create a BasicAclEntry for this AclObjectIdentity
|
||||
SimpleAclEntry simpleAcl1 = new SimpleAclEntry("rod", identity, parentIdentity, SimpleAclEntry.CREATE);
|
||||
dao.create(simpleAcl1);
|
||||
|
||||
// Create another BasicAclEntry for this AclObjectIdentity
|
||||
SimpleAclEntry simpleAcl2 = new SimpleAclEntry("scott", identity, parentIdentity, SimpleAclEntry.READ);
|
||||
dao.create(simpleAcl2);
|
||||
|
||||
// Check creation was successful
|
||||
BasicAclEntry[] acls = dao.getAcls(identity);
|
||||
assertEquals(2, acls.length);
|
||||
assertEquals(simpleAcl1.getRecipient(), acls[0].getRecipient());
|
||||
assertEquals(simpleAcl1.getMask(), acls[0].getMask());
|
||||
assertEquals(simpleAcl2.getRecipient(), acls[1].getRecipient());
|
||||
assertEquals(simpleAcl2.getMask(), acls[1].getMask());
|
||||
|
||||
// Check it rejects an attempt to create another identical entry
|
||||
try {
|
||||
dao.create(simpleAcl1);
|
||||
fail("Should have thrown DataIntegrityViolationException");
|
||||
} catch (DataIntegrityViolationException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testRejectsInvalidParent() throws Exception {
|
||||
JdbcExtendedDaoImpl dao = makePopulatedJdbcDao();
|
||||
AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "201");
|
||||
AclObjectIdentity parentIdentity = new NamedEntityObjectIdentity(OBJECT_IDENTITY, "987987987987986");
|
||||
SimpleAclEntry simpleAcl = new SimpleAclEntry("rod", identity, parentIdentity, SimpleAclEntry.CREATE);
|
||||
|
||||
try {
|
||||
dao.create(simpleAcl);
|
||||
fail("Should have thrown DataRetrievalFailureException");
|
||||
} catch (DataRetrievalFailureException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockMappingSqlQuery extends MappingSqlQuery {
|
||||
protected Object mapRow(ResultSet arg0, int arg1)
|
||||
throws SQLException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,373 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.afterinvocation;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.AuthorizationServiceException;
|
||||
import org.springframework.security.ConfigAttribute;
|
||||
import org.springframework.security.MockAclManager;
|
||||
import org.springframework.security.SecurityConfig;
|
||||
import org.springframework.security.acl.AclEntry;
|
||||
import org.springframework.security.acl.AclManager;
|
||||
import org.springframework.security.acl.basic.MockAclObjectIdentity;
|
||||
import org.springframework.security.acl.basic.SimpleAclEntry;
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.util.SimpleMethodInvocation;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link BasicAclEntryAfterInvocationCollectionFilteringProvider}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BasicAclEntryAfterInvocationCollectionFilteringProviderTests extends TestCase {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public BasicAclEntryAfterInvocationCollectionFilteringProviderTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public BasicAclEntryAfterInvocationCollectionFilteringProviderTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void testCorrectOperationWhenPrincipalHasIncorrectPermissionToDomainObject()
|
||||
throws Exception {
|
||||
// Create an AclManager, granting scott only ADMINISTRATION rights
|
||||
AclManager aclManager = new MockAclManager("belmont", "scott",
|
||||
new AclEntry[] {
|
||||
new SimpleAclEntry("scott", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION)
|
||||
});
|
||||
|
||||
BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
|
||||
provider.setAclManager(aclManager);
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
// Create a Collection containing many items
|
||||
List list = new Vector();
|
||||
list.add("sydney");
|
||||
list.add("melbourne");
|
||||
list.add("belmont");
|
||||
list.add("brisbane");
|
||||
|
||||
// Create the Authentication and Config Attribs we'll be presenting
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("scott", "NOT_USED");
|
||||
|
||||
// Filter
|
||||
List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(),
|
||||
SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), list);
|
||||
|
||||
assertEquals(0, filteredList.size());
|
||||
}
|
||||
|
||||
public void testCorrectOperationWhenPrincipalHasNoPermissionToDomainObject()
|
||||
throws Exception {
|
||||
// Create an AclManager
|
||||
AclManager aclManager = new MockAclManager("belmont", "rod",
|
||||
new AclEntry[] {
|
||||
new MockAclEntry(),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
|
||||
});
|
||||
|
||||
BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
|
||||
provider.setAclManager(aclManager);
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
// Create a Collection containing many items, which only "belmont"
|
||||
// should remain in after filtering by provider
|
||||
List list = new Vector();
|
||||
list.add("sydney");
|
||||
list.add("melbourne");
|
||||
list.add("belmont");
|
||||
list.add("brisbane");
|
||||
|
||||
// Create the Authentication and Config Attribs we'll be presenting
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("scott", "NOT_USED");
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("AFTER_ACL_COLLECTION_READ");
|
||||
|
||||
// Filter
|
||||
List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(), attr, list);
|
||||
|
||||
assertEquals(0, filteredList.size());
|
||||
}
|
||||
|
||||
public void testCorrectOperationWhenPrincipalIsAuthorised()
|
||||
throws Exception {
|
||||
// Create an AclManager
|
||||
AclManager aclManager = new MockAclManager("belmont", "rod",
|
||||
new AclEntry[] {
|
||||
new MockAclEntry(),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
|
||||
});
|
||||
|
||||
BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
|
||||
provider.setAclManager(aclManager);
|
||||
assertEquals(aclManager, provider.getAclManager());
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
// Create a Collection containing many items, which only "belmont"
|
||||
// should remain in after filtering by provider
|
||||
List list = new Vector();
|
||||
list.add("sydney");
|
||||
list.add("melbourne");
|
||||
list.add("belmont");
|
||||
list.add("brisbane");
|
||||
|
||||
// Create the Authentication and Config Attribs we'll be presenting
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("rod", "NOT_USED");
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("AFTER_ACL_COLLECTION_READ");
|
||||
|
||||
// Filter
|
||||
List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(), attr, list);
|
||||
|
||||
assertEquals(1, filteredList.size());
|
||||
assertEquals("belmont", filteredList.get(0));
|
||||
}
|
||||
|
||||
public void testCorrectOperationWhenReturnedObjectIsArray()
|
||||
throws Exception {
|
||||
// Create an AclManager
|
||||
AclManager aclManager = new MockAclManager("belmont", "rod",
|
||||
new AclEntry[] {
|
||||
new MockAclEntry(),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
|
||||
});
|
||||
|
||||
BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
|
||||
provider.setAclManager(aclManager);
|
||||
assertEquals(aclManager, provider.getAclManager());
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
// Create a Collection containing many items, which only "belmont"
|
||||
// should remain in after filtering by provider
|
||||
String[] list = new String[4];
|
||||
list[0] = "sydney";
|
||||
list[1] = "melbourne";
|
||||
list[2] = "belmont";
|
||||
list[3] = "brisbane";
|
||||
|
||||
// Create the Authentication and Config Attribs we'll be presenting
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("rod", "NOT_USED");
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("AFTER_ACL_COLLECTION_READ");
|
||||
|
||||
// Filter
|
||||
String[] filteredList = (String[]) provider.decide(auth, new SimpleMethodInvocation(), attr, list);
|
||||
|
||||
assertEquals(1, filteredList.length);
|
||||
assertEquals("belmont", filteredList[0]);
|
||||
}
|
||||
|
||||
public void testDetectsIfReturnedObjectIsNotACollection()
|
||||
throws Exception {
|
||||
// Create an AclManager
|
||||
AclManager aclManager = new MockAclManager("belmont", "rod",
|
||||
new AclEntry[] {
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE),
|
||||
new MockAclEntry()
|
||||
});
|
||||
|
||||
BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
|
||||
provider.setAclManager(aclManager);
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
// Create the Authentication and Config Attribs we'll be presenting
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("rod", "NOT_USED");
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("AFTER_ACL_COLLECTION_READ");
|
||||
|
||||
// Filter
|
||||
try {
|
||||
provider.decide(auth, new SimpleMethodInvocation(), attr, new String("RETURN_OBJECT_NOT_COLLECTION"));
|
||||
fail("Should have thrown AuthorizationServiceException");
|
||||
} catch (AuthorizationServiceException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGrantsAccessIfReturnedObjectIsNull()
|
||||
throws Exception {
|
||||
// Create an AclManager
|
||||
AclManager aclManager = new MockAclManager("belmont", "rod",
|
||||
new AclEntry[] {
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE),
|
||||
new MockAclEntry()
|
||||
});
|
||||
|
||||
BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
|
||||
provider.setAclManager(aclManager);
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
// Create the Authentication and Config Attribs we'll be presenting
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("rod", "NOT_USED");
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("AFTER_ACL_COLLECTION_READ");
|
||||
|
||||
// Filter
|
||||
List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(), attr, null);
|
||||
|
||||
assertNull(filteredList);
|
||||
}
|
||||
|
||||
public void testRespectsModificationsToProcessConfigAttribute() throws Exception {
|
||||
// Create an AclManager
|
||||
AclManager aclManager = new MockAclManager("sydney", "rod",
|
||||
new AclEntry[] {
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new MockAclEntry()
|
||||
});
|
||||
|
||||
BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
|
||||
provider.setAclManager(aclManager);
|
||||
assertEquals("AFTER_ACL_COLLECTION_READ", provider.getProcessConfigAttribute());
|
||||
provider.setProcessConfigAttribute("AFTER_ACL_COLLECTION_ADMIN");
|
||||
assertEquals("AFTER_ACL_COLLECTION_ADMIN", provider.getProcessConfigAttribute());
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
// Create a Collection containing many items, which only "sydney"
|
||||
// should remain in after filtering by provider
|
||||
List list = new Vector();
|
||||
list.add("sydney");
|
||||
list.add("melbourne");
|
||||
list.add("belmont");
|
||||
list.add("brisbane");
|
||||
|
||||
// Create the Authentication and Config Attribs we'll be presenting
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("rod", "NOT_USED");
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("AFTER_ACL_COLLECTION_READ");
|
||||
|
||||
// As no matching config attrib, ensure provider doesn't change list
|
||||
assertEquals(4, ((List) provider.decide(auth, new SimpleMethodInvocation(), attr, list)).size());
|
||||
|
||||
// Filter, this time with the conf attrib provider setup to answer
|
||||
attr = SecurityConfig.createList("AFTER_ACL_COLLECTION_ADMIN");
|
||||
|
||||
List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(), attr, list);
|
||||
|
||||
assertEquals(1, filteredList.size());
|
||||
assertEquals("sydney", filteredList.get(0));
|
||||
}
|
||||
|
||||
public void testRespectsModificationsToRequirePermissions()
|
||||
throws Exception {
|
||||
// Create an AclManager
|
||||
AclManager aclManager = new MockAclManager("sydney", "rod",
|
||||
new AclEntry[] {
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new MockAclEntry()
|
||||
});
|
||||
|
||||
BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
|
||||
provider.setAclManager(aclManager);
|
||||
assertEquals(SimpleAclEntry.READ, provider.getRequirePermission()[0]);
|
||||
provider.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION});
|
||||
assertEquals(SimpleAclEntry.ADMINISTRATION, provider.getRequirePermission()[0]);
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
// Create a Collection containing many items, which only "sydney"
|
||||
// should remain in after filtering by provider
|
||||
List list = new Vector();
|
||||
list.add("sydney");
|
||||
list.add("melbourne");
|
||||
list.add("belmont");
|
||||
list.add("brisbane");
|
||||
|
||||
// Create the Authentication and Config Attribs we'll be presenting
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("rod", "NOT_USED");
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("AFTER_ACL_COLLECTION_READ");
|
||||
|
||||
// Filter
|
||||
List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(), attr, list);
|
||||
|
||||
assertEquals(1, filteredList.size());
|
||||
assertEquals("sydney", filteredList.get(0));
|
||||
}
|
||||
|
||||
public void testStartupDetectsMissingAclManager() throws Exception {
|
||||
BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
|
||||
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("An aclManager is mandatory", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupDetectsMissingProcessConfigAttribute()
|
||||
throws Exception {
|
||||
BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
|
||||
AclManager aclManager = new MockAclManager("sydney", "rod",
|
||||
new AclEntry[] {
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new MockAclEntry()
|
||||
});
|
||||
provider.setAclManager(aclManager);
|
||||
|
||||
provider.setProcessConfigAttribute(null);
|
||||
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("A processConfigAttribute is mandatory", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupDetectsMissingRequirePermission()
|
||||
throws Exception {
|
||||
BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
|
||||
AclManager aclManager = new MockAclManager("sydney", "rod",
|
||||
new AclEntry[] {
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new MockAclEntry()
|
||||
});
|
||||
provider.setAclManager(aclManager);
|
||||
|
||||
provider.setRequirePermission(null);
|
||||
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("One or more requirePermission entries is mandatory", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testSupportsAnything() {
|
||||
assertTrue(new BasicAclEntryAfterInvocationCollectionFilteringProvider().supports(String.class));
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockAclEntry implements AclEntry {
|
||||
// just so AclTag iterates some different types of AclEntrys
|
||||
}
|
||||
}
|
@ -1,257 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.afterinvocation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.AccessDeniedException;
|
||||
import org.springframework.security.ConfigAttribute;
|
||||
import org.springframework.security.ConfigAttributeDefinition;
|
||||
import org.springframework.security.MockAclManager;
|
||||
import org.springframework.security.SecurityConfig;
|
||||
import org.springframework.security.acl.AclEntry;
|
||||
import org.springframework.security.acl.AclManager;
|
||||
import org.springframework.security.acl.basic.MockAclObjectIdentity;
|
||||
import org.springframework.security.acl.basic.SimpleAclEntry;
|
||||
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
|
||||
import org.springframework.security.util.SimpleMethodInvocation;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link BasicAclEntryAfterInvocationProvider}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BasicAclEntryAfterInvocationProviderTests extends TestCase {
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void testCorrectOperationWhenPrincipalHasIncorrectPermissionToDomainObject()
|
||||
throws Exception {
|
||||
// Create an AclManager, granting scott only ADMINISTRATION rights
|
||||
AclManager aclManager = new MockAclManager("belmont", "scott",
|
||||
new AclEntry[]{
|
||||
new SimpleAclEntry("scott", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION)
|
||||
});
|
||||
|
||||
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
|
||||
provider.setAclManager(aclManager);
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
// Create the Authentication and Config Attribs we'll be presenting
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("scott", "NOT_USED");
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("AFTER_ACL_READ");
|
||||
|
||||
try {
|
||||
provider.decide(auth, new SimpleMethodInvocation(), attr, "belmont");
|
||||
fail("Should have thrown AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testCorrectOperationWhenPrincipalHasNoPermissionToDomainObject()
|
||||
throws Exception {
|
||||
// Create an AclManager
|
||||
AclManager aclManager = new MockAclManager("belmont", "rod",
|
||||
new AclEntry[]{
|
||||
new MockAclEntry(),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
|
||||
});
|
||||
|
||||
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
|
||||
provider.setAclManager(aclManager);
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
// Create the Authentication and Config Attribs we'll be presenting
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("scott", "NOT_USED");
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("AFTER_ACL_READ");
|
||||
|
||||
try {
|
||||
provider.decide(auth, new SimpleMethodInvocation(), attr, "belmont");
|
||||
fail("Should have thrown AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testCorrectOperationWhenPrincipalIsAuthorised()
|
||||
throws Exception {
|
||||
// Create an AclManager
|
||||
AclManager aclManager = new MockAclManager("belmont", "rod",
|
||||
new AclEntry[]{
|
||||
new MockAclEntry(),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
|
||||
});
|
||||
|
||||
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
|
||||
provider.setAclManager(aclManager);
|
||||
assertEquals(aclManager, provider.getAclManager());
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
// Create the Authentication and Config Attribs we'll be presenting
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("rod", "NOT_USED");
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("AFTER_ACL_READ");
|
||||
|
||||
// Filter
|
||||
assertEquals("belmont", provider.decide(auth, new SimpleMethodInvocation(), attr, "belmont"));
|
||||
}
|
||||
|
||||
public void testGrantsAccessIfReturnedObjectIsNull()
|
||||
throws Exception {
|
||||
// Create an AclManager
|
||||
AclManager aclManager = new MockAclManager("belmont", "rod",
|
||||
new AclEntry[]{
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE),
|
||||
new MockAclEntry()
|
||||
});
|
||||
|
||||
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
|
||||
provider.setAclManager(aclManager);
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
// Create the Authentication and Config Attribs we'll be presenting
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("rod", "NOT_USED");
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("AFTER_ACL_READ");
|
||||
|
||||
// Filter
|
||||
assertNull(provider.decide(auth, new SimpleMethodInvocation(), attr, null));
|
||||
}
|
||||
|
||||
public void testRespectsModificationsToProcessConfigAttribute()
|
||||
throws Exception {
|
||||
// Create an AclManager
|
||||
AclManager aclManager = new MockAclManager("sydney", "rod",
|
||||
new AclEntry[]{
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new MockAclEntry()
|
||||
});
|
||||
|
||||
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
|
||||
provider.setAclManager(aclManager);
|
||||
assertEquals("AFTER_ACL_READ", provider.getProcessConfigAttribute());
|
||||
provider.setProcessConfigAttribute("AFTER_ACL_ADMIN");
|
||||
assertEquals("AFTER_ACL_ADMIN", provider.getProcessConfigAttribute());
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
// Create the Authentication and Config Attribs we'll be presenting
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("rod", "NOT_USED");
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("AFTER_ACL_READ");
|
||||
|
||||
// As no matching config attrib, ensure provider returns original obj
|
||||
assertEquals("sydney", provider.decide(auth, new SimpleMethodInvocation(), attr, "sydney"));
|
||||
|
||||
// Filter, this time with the conf attrib provider setup to answer
|
||||
attr = SecurityConfig.createList("AFTER_ACL_ADMIN");
|
||||
assertEquals("sydney", provider.decide(auth, new SimpleMethodInvocation(), attr, "sydney"));
|
||||
}
|
||||
|
||||
public void testRespectsModificationsToRequirePermissions()
|
||||
throws Exception {
|
||||
// Create an AclManager
|
||||
AclManager aclManager = new MockAclManager("sydney", "rod",
|
||||
new AclEntry[]{
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new MockAclEntry()
|
||||
});
|
||||
|
||||
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
|
||||
provider.setAclManager(aclManager);
|
||||
assertEquals(SimpleAclEntry.READ, provider.getRequirePermission()[0]);
|
||||
provider.setRequirePermission(new int[]{SimpleAclEntry.ADMINISTRATION});
|
||||
assertEquals(SimpleAclEntry.ADMINISTRATION, provider.getRequirePermission()[0]);
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
// Create the Authentication and Config Attribs we'll be presenting
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("rod", "NOT_USED");
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("AFTER_ACL_READ");
|
||||
|
||||
// Filter
|
||||
assertEquals("sydney", provider.decide(auth, new SimpleMethodInvocation(), attr, "sydney"));
|
||||
}
|
||||
|
||||
public void testStartupDetectsMissingAclManager() throws Exception {
|
||||
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
|
||||
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("An aclManager is mandatory", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupDetectsMissingProcessConfigAttribute()
|
||||
throws Exception {
|
||||
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
|
||||
AclManager aclManager = new MockAclManager("sydney", "rod",
|
||||
new AclEntry[] {
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new MockAclEntry()
|
||||
});
|
||||
provider.setAclManager(aclManager);
|
||||
|
||||
provider.setProcessConfigAttribute(null);
|
||||
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("A processConfigAttribute is mandatory", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupDetectsMissingRequirePermission()
|
||||
throws Exception {
|
||||
BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
|
||||
AclManager aclManager = new MockAclManager("sydney", "rod",
|
||||
new AclEntry[] {
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new MockAclEntry()
|
||||
});
|
||||
provider.setAclManager(aclManager);
|
||||
|
||||
provider.setRequirePermission(null);
|
||||
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("One or more requirePermission entries is mandatory", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testSupportsAnything() {
|
||||
assertTrue(new BasicAclEntryAfterInvocationProvider().supports(String.class));
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockAclEntry implements AclEntry {
|
||||
// just so AclTag iterates some different types of AclEntrys
|
||||
}
|
||||
}
|
@ -1,472 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.vote;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.springframework.security.AuthorizationServiceException;
|
||||
import org.springframework.security.ConfigAttribute;
|
||||
import org.springframework.security.MockAclManager;
|
||||
import org.springframework.security.SecurityConfig;
|
||||
import org.springframework.security.acl.AclEntry;
|
||||
import org.springframework.security.acl.AclManager;
|
||||
import org.springframework.security.acl.basic.MockAclObjectIdentity;
|
||||
import org.springframework.security.acl.basic.SimpleAclEntry;
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.util.SimpleMethodInvocation;
|
||||
|
||||
/**
|
||||
* Tests {@link BasicAclEntryVoter}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BasicAclEntryVoterTests extends TestCase {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public BasicAclEntryVoterTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public BasicAclEntryVoterTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private MethodInvocation getMethodInvocation(SomeDomainObject domainObject)
|
||||
throws Exception {
|
||||
Class clazz = SomeDomainObjectManager.class;
|
||||
Method method = clazz.getMethod("someServiceMethod", new Class[] {SomeDomainObject.class});
|
||||
|
||||
return new SimpleMethodInvocation(new SomeDomainObjectManager(), method, new Object[] {domainObject});
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(BasicAclEntryVoterTests.class);
|
||||
}
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testNormalOperation() throws Exception {
|
||||
// Setup a domain object subject of this test
|
||||
SomeDomainObject domainObject = new SomeDomainObject("foo");
|
||||
|
||||
// Setup an AclManager
|
||||
AclManager aclManager = new MockAclManager(domainObject, "rod",
|
||||
new AclEntry[]{
|
||||
new MockAclEntry(),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
|
||||
});
|
||||
|
||||
// Wire up a voter
|
||||
BasicAclEntryVoter voter = new BasicAclEntryVoter();
|
||||
voter.setAclManager(aclManager);
|
||||
assertEquals(aclManager, voter.getAclManager());
|
||||
voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
|
||||
assertEquals("FOO_ADMIN_OR_WRITE_ACCESS", voter.getProcessConfigAttribute());
|
||||
voter.setRequirePermission(new int[]{SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
|
||||
assertEquals(2, voter.getRequirePermission().length);
|
||||
voter.setProcessDomainObjectClass(SomeDomainObject.class);
|
||||
assertEquals(SomeDomainObject.class, voter.getProcessDomainObjectClass());
|
||||
voter.afterPropertiesSet();
|
||||
|
||||
// Wire up an invocation to be voted on
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("FOO_ADMIN_OR_WRITE_ACCESS");
|
||||
|
||||
// Setup a MockMethodInvocation, so voter can retrieve domainObject
|
||||
MethodInvocation mi = getMethodInvocation(domainObject);
|
||||
|
||||
assertEquals(AccessDecisionVoter.ACCESS_GRANTED,
|
||||
voter.vote(new UsernamePasswordAuthenticationToken("rod", null), mi, attr));
|
||||
}
|
||||
|
||||
public void testOnlySupportsMethodInvocationAndJoinPoint() {
|
||||
BasicAclEntryVoter voter = new BasicAclEntryVoter();
|
||||
assertTrue(voter.supports(MethodInvocation.class));
|
||||
assertTrue(voter.supports(JoinPoint.class));
|
||||
assertFalse(voter.supports(String.class));
|
||||
}
|
||||
|
||||
public void testStartupRejectsMissingAclManager() throws Exception {
|
||||
// Wire up a voter
|
||||
BasicAclEntryVoter voter = new BasicAclEntryVoter();
|
||||
voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
|
||||
voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
|
||||
voter.setProcessDomainObjectClass(SomeDomainObject.class);
|
||||
|
||||
try {
|
||||
voter.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupRejectsMissingProcessConfigAttribute()
|
||||
throws Exception {
|
||||
AclManager aclManager = new MockAclManager("domain1", "rod",
|
||||
new AclEntry[] {
|
||||
new MockAclEntry(),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
|
||||
});
|
||||
|
||||
// Wire up a voter
|
||||
BasicAclEntryVoter voter = new BasicAclEntryVoter();
|
||||
voter.setAclManager(aclManager);
|
||||
voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
|
||||
voter.setProcessDomainObjectClass(SomeDomainObject.class);
|
||||
|
||||
try {
|
||||
voter.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupRejectsMissingProcessDomainObjectClass()
|
||||
throws Exception {
|
||||
BasicAclEntryVoter voter = new BasicAclEntryVoter();
|
||||
|
||||
try {
|
||||
voter.setProcessDomainObjectClass(null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupRejectsMissingRequirePermission()
|
||||
throws Exception {
|
||||
AclManager aclManager = new MockAclManager("domain1", "rod",
|
||||
new AclEntry[] {
|
||||
new MockAclEntry(),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
|
||||
});
|
||||
|
||||
// Wire up a voter
|
||||
BasicAclEntryVoter voter = new BasicAclEntryVoter();
|
||||
voter.setAclManager(aclManager);
|
||||
voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
|
||||
voter.setProcessDomainObjectClass(SomeDomainObject.class);
|
||||
|
||||
try {
|
||||
voter.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSupportsConfigAttribute() {
|
||||
BasicAclEntryVoter voter = new BasicAclEntryVoter();
|
||||
voter.setProcessConfigAttribute("foobar");
|
||||
assertTrue(voter.supports(new SecurityConfig("foobar")));
|
||||
}
|
||||
|
||||
public void testVoterAbstainsIfDomainObjectIsNull()
|
||||
throws Exception {
|
||||
// Setup a domain object subject of this test
|
||||
SomeDomainObject domainObject = new SomeDomainObject("foo");
|
||||
|
||||
// Setup an AclManager
|
||||
AclManager aclManager = new MockAclManager(domainObject, "rod",
|
||||
new AclEntry[]{
|
||||
new MockAclEntry(),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
|
||||
});
|
||||
|
||||
// Wire up a voter
|
||||
BasicAclEntryVoter voter = new BasicAclEntryVoter();
|
||||
voter.setAclManager(aclManager);
|
||||
voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
|
||||
voter.setRequirePermission(new int[]{SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
|
||||
voter.setProcessDomainObjectClass(SomeDomainObject.class);
|
||||
voter.afterPropertiesSet();
|
||||
|
||||
// Wire up an invocation to be voted on
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("A_DIFFERENT_ATTRIBUTE");
|
||||
|
||||
// Setup a MockMethodInvocation, so voter can retrieve domainObject
|
||||
MethodInvocation mi = getMethodInvocation(domainObject);
|
||||
|
||||
assertEquals(AccessDecisionVoter.ACCESS_ABSTAIN,
|
||||
voter.vote(new UsernamePasswordAuthenticationToken("rod", null), mi, attr));
|
||||
}
|
||||
|
||||
public void testVoterAbstainsIfNotMatchingConfigAttribute()
|
||||
throws Exception {
|
||||
// Setup a domain object subject of this test
|
||||
SomeDomainObject domainObject = null;
|
||||
|
||||
// Setup an AclManager
|
||||
AclManager aclManager = new MockAclManager(domainObject, "rod",
|
||||
new AclEntry[]{
|
||||
new MockAclEntry(),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
|
||||
});
|
||||
|
||||
// Wire up a voter
|
||||
BasicAclEntryVoter voter = new BasicAclEntryVoter();
|
||||
voter.setAclManager(aclManager);
|
||||
voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
|
||||
voter.setRequirePermission(new int[]{SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
|
||||
voter.setProcessDomainObjectClass(SomeDomainObject.class);
|
||||
voter.afterPropertiesSet();
|
||||
|
||||
// Wire up an invocation to be voted on
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("FOO_ADMIN_OR_WRITE_ACCESS");
|
||||
|
||||
// Setup a MockMethodInvocation, so voter can retrieve domainObject
|
||||
MethodInvocation mi = getMethodInvocation(domainObject);
|
||||
|
||||
assertEquals(AccessDecisionVoter.ACCESS_ABSTAIN,
|
||||
voter.vote(new UsernamePasswordAuthenticationToken("rod", null), mi, attr));
|
||||
}
|
||||
|
||||
public void testVoterCanDenyAccessBasedOnInternalMethodOfDomainObject()
|
||||
throws Exception {
|
||||
// Setup a domain object subject of this test
|
||||
SomeDomainObject domainObject = new SomeDomainObject("foo");
|
||||
|
||||
// Setup an AclManager
|
||||
AclManager aclManager = new MockAclManager(domainObject.getParent(), "rod",
|
||||
new AclEntry[]{
|
||||
new MockAclEntry(),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
|
||||
});
|
||||
|
||||
// Wire up a voter
|
||||
BasicAclEntryVoter voter = new BasicAclEntryVoter();
|
||||
voter.setAclManager(aclManager);
|
||||
voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
|
||||
voter.setRequirePermission(new int[]{SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
|
||||
voter.setProcessDomainObjectClass(SomeDomainObject.class);
|
||||
voter.setInternalMethod("getParent");
|
||||
voter.afterPropertiesSet();
|
||||
|
||||
// Wire up an invocation to be voted on
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("FOO_ADMIN_OR_WRITE_ACCESS");
|
||||
|
||||
// Setup a MockMethodInvocation, so voter can retrieve domainObject
|
||||
MethodInvocation mi = getMethodInvocation(domainObject);
|
||||
|
||||
assertEquals(AccessDecisionVoter.ACCESS_DENIED,
|
||||
voter.vote(new UsernamePasswordAuthenticationToken("rod", null), mi, attr));
|
||||
}
|
||||
|
||||
public void testVoterCanDenyAccessIfPrincipalHasNoPermissionsAtAllToDomainObject()
|
||||
throws Exception {
|
||||
// Setup a domain object subject of this test
|
||||
SomeDomainObject domainObject = new SomeDomainObject("foo");
|
||||
|
||||
// Setup an AclManager
|
||||
AclManager aclManager = new MockAclManager(domainObject, "rod",
|
||||
new AclEntry[]{
|
||||
new MockAclEntry(),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
|
||||
});
|
||||
|
||||
// Wire up a voter
|
||||
BasicAclEntryVoter voter = new BasicAclEntryVoter();
|
||||
voter.setAclManager(aclManager);
|
||||
voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
|
||||
voter.setRequirePermission(new int[]{SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
|
||||
voter.setProcessDomainObjectClass(SomeDomainObject.class);
|
||||
voter.setInternalMethod("getParent");
|
||||
voter.afterPropertiesSet();
|
||||
|
||||
// Wire up an invocation to be voted on
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("FOO_ADMIN_OR_WRITE_ACCESS");
|
||||
|
||||
// Setup a MockMethodInvocation, so voter can retrieve domainObject
|
||||
MethodInvocation mi = getMethodInvocation(domainObject);
|
||||
|
||||
// NB: scott is the principal, not rod
|
||||
assertEquals(AccessDecisionVoter.ACCESS_DENIED,
|
||||
voter.vote(new UsernamePasswordAuthenticationToken("scott", null), mi, attr));
|
||||
}
|
||||
|
||||
public void testVoterCanGrantAccessBasedOnInternalMethodOfDomainObject()
|
||||
throws Exception {
|
||||
// Setup a domain object subject of this test
|
||||
SomeDomainObject domainObject = new SomeDomainObject("foo");
|
||||
|
||||
// Setup an AclManager
|
||||
AclManager aclManager = new MockAclManager(domainObject.getParent(), "rod",
|
||||
new AclEntry[]{
|
||||
new MockAclEntry(),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
|
||||
});
|
||||
|
||||
// Wire up a voter
|
||||
BasicAclEntryVoter voter = new BasicAclEntryVoter();
|
||||
voter.setAclManager(aclManager);
|
||||
voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
|
||||
voter.setRequirePermission(new int[]{SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
|
||||
voter.setProcessDomainObjectClass(SomeDomainObject.class);
|
||||
voter.setInternalMethod("getParent");
|
||||
assertEquals("getParent", voter.getInternalMethod());
|
||||
voter.afterPropertiesSet();
|
||||
|
||||
// Wire up an invocation to be voted on
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("FOO_ADMIN_OR_WRITE_ACCESS");
|
||||
|
||||
// Setup a MockMethodInvocation, so voter can retrieve domainObject
|
||||
// (well actually it will access domainObject.getParent())
|
||||
MethodInvocation mi = getMethodInvocation(domainObject);
|
||||
|
||||
assertEquals(AccessDecisionVoter.ACCESS_GRANTED,
|
||||
voter.vote(new UsernamePasswordAuthenticationToken("rod", null), mi, attr));
|
||||
}
|
||||
|
||||
public void testVoterThrowsExceptionIfInvalidInternalMethodOfDomainObject()
|
||||
throws Exception {
|
||||
// Setup a domain object subject of this test
|
||||
SomeDomainObject domainObject = new SomeDomainObject("foo");
|
||||
|
||||
// Setup an AclManager
|
||||
AclManager aclManager = new MockAclManager(domainObject.getParent(), "rod",
|
||||
new AclEntry[]{
|
||||
new MockAclEntry(),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
|
||||
});
|
||||
|
||||
// Wire up a voter
|
||||
BasicAclEntryVoter voter = new BasicAclEntryVoter();
|
||||
voter.setAclManager(aclManager);
|
||||
voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
|
||||
voter.setRequirePermission(new int[]{SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
|
||||
voter.setProcessDomainObjectClass(SomeDomainObject.class);
|
||||
voter.setInternalMethod("getNonExistentParentName");
|
||||
voter.afterPropertiesSet();
|
||||
|
||||
// Wire up an invocation to be voted on
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("FOO_ADMIN_OR_WRITE_ACCESS");
|
||||
|
||||
// Setup a MockMethodInvocation, so voter can retrieve domainObject
|
||||
// (well actually it will access domainObject.getParent())
|
||||
MethodInvocation mi = getMethodInvocation(domainObject);
|
||||
|
||||
try {
|
||||
voter.vote(new UsernamePasswordAuthenticationToken("rod", null), mi, attr);
|
||||
fail("Should have thrown AuthorizationServiceException");
|
||||
} catch (AuthorizationServiceException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testVoterThrowsExceptionIfProcessDomainObjectNotFound()
|
||||
throws Exception {
|
||||
// Setup a domain object subject of this test
|
||||
SomeDomainObject domainObject = new SomeDomainObject("foo");
|
||||
|
||||
// Setup an AclManager
|
||||
AclManager aclManager = new MockAclManager(domainObject.getParent(), "rod",
|
||||
new AclEntry[]{
|
||||
new MockAclEntry(),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
|
||||
});
|
||||
|
||||
// Wire up a voter
|
||||
BasicAclEntryVoter voter = new BasicAclEntryVoter();
|
||||
voter.setAclManager(aclManager);
|
||||
voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
|
||||
voter.setRequirePermission(new int[]{SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
|
||||
voter.setProcessDomainObjectClass(SomeDomainObject.class);
|
||||
voter.afterPropertiesSet();
|
||||
|
||||
// Wire up an invocation to be voted on
|
||||
List<ConfigAttribute> attr = SecurityConfig.createList("FOO_ADMIN_OR_WRITE_ACCESS");
|
||||
|
||||
// Setup a MockMethodInvocation that doesn't provide SomeDomainObject arg
|
||||
Class clazz = String.class;
|
||||
Method method = clazz.getMethod("toString", new Class[]{});
|
||||
|
||||
MethodInvocation mi = new SimpleMethodInvocation(new String(), method, new Object[]{domainObject});
|
||||
|
||||
try {
|
||||
voter.vote(new UsernamePasswordAuthenticationToken("rod", null), mi, attr);
|
||||
fail("Should have thrown AuthorizationServiceException");
|
||||
} catch (AuthorizationServiceException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSetRequirePermissionFromString() {
|
||||
assertPermission("NOTHING", SimpleAclEntry.NOTHING);
|
||||
assertPermission("ADMINISTRATION", SimpleAclEntry.ADMINISTRATION);
|
||||
assertPermission("READ", SimpleAclEntry.READ);
|
||||
assertPermission("WRITE", SimpleAclEntry.WRITE);
|
||||
assertPermission("CREATE", SimpleAclEntry.CREATE);
|
||||
assertPermission("DELETE", SimpleAclEntry.DELETE);
|
||||
assertPermission(new String[] { "WRITE", "CREATE" }, new int[] { SimpleAclEntry.WRITE, SimpleAclEntry.CREATE });
|
||||
}
|
||||
|
||||
public void testSetRequirePermissionFromStringWrongValues() {
|
||||
BasicAclEntryVoter voter = new BasicAclEntryVoter();
|
||||
try {
|
||||
voter.setRequirePermissionFromString(new String[] { "X" });
|
||||
fail(IllegalArgumentException.class.getName() + " must have been thrown.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
private void assertPermission(String text, int value) {
|
||||
assertPermission(new String[] { text }, new int[] { value });
|
||||
}
|
||||
|
||||
private void assertPermission(String[] text, int[] value) {
|
||||
BasicAclEntryVoter voter = new BasicAclEntryVoter();
|
||||
voter.setRequirePermissionFromString(text);
|
||||
assertEquals("Test incorreclty coded", value.length, text.length);
|
||||
assertEquals(value.length, voter.getRequirePermission().length);
|
||||
for (int i = 0; i < value.length; i++) {
|
||||
assertEquals(value[i], voter.getRequirePermission()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockAclEntry implements AclEntry {
|
||||
// just so AclTag iterates some different types of AclEntrys
|
||||
}
|
||||
}
|
@ -1,214 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.taglibs.authz;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
|
||||
import org.springframework.security.acl.AclEntry;
|
||||
import org.springframework.security.acl.AclManager;
|
||||
import org.springframework.security.acl.basic.BasicAclEntry;
|
||||
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
import org.springframework.web.util.ExpressionEvaluationUtils;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
import javax.servlet.jsp.tagext.Tag;
|
||||
import javax.servlet.jsp.tagext.TagSupport;
|
||||
|
||||
|
||||
/**
|
||||
* An implementation of {@link javax.servlet.jsp.tagext.Tag} that allows its body through if some authorizations
|
||||
* are granted to the request's principal.
|
||||
* <p>
|
||||
* Only works with permissions that are subclasses of {@link org.springframework.security.acl.basic.BasicAclEntry}.
|
||||
* <p>
|
||||
* One or more comma separate integer permissions are specified via the <code>hasPermission</code> attribute.
|
||||
* The tag will include its body if <b>any</b> of the integer permissions have been granted to the current
|
||||
* <code>Authentication</code> (obtained from the <code>SecurityContextHolder</code>).
|
||||
* <p>
|
||||
* For this class to operate it must be able to access the application context via the
|
||||
* <code>WebApplicationContextUtils</code> and locate an {@link AclManager}. Application contexts have no need to have
|
||||
* more than one <code>AclManager</code> (as a provider-based implementation can be used so that it locates a provider
|
||||
* that is authoritative for the given domain object instance), so the first <code>AclManager</code> located will be
|
||||
* used.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AclTag extends TagSupport {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(AclTag.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private Object domainObject;
|
||||
private String hasPermission = "";
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public int doStartTag() throws JspException {
|
||||
if ((null == hasPermission) || "".equals(hasPermission)) {
|
||||
return Tag.SKIP_BODY;
|
||||
}
|
||||
|
||||
final String evaledPermissionsString = ExpressionEvaluationUtils.evaluateString("hasPermission", hasPermission,
|
||||
pageContext);
|
||||
|
||||
Integer[] requiredIntegers = null;
|
||||
|
||||
try {
|
||||
requiredIntegers = parseIntegersString(evaledPermissionsString);
|
||||
} catch (NumberFormatException nfe) {
|
||||
throw new JspException(nfe);
|
||||
}
|
||||
|
||||
Object resolvedDomainObject = null;
|
||||
|
||||
if (domainObject instanceof String) {
|
||||
resolvedDomainObject = ExpressionEvaluationUtils.evaluate("domainObject", (String) domainObject,
|
||||
Object.class, pageContext);
|
||||
} else {
|
||||
resolvedDomainObject = domainObject;
|
||||
}
|
||||
|
||||
if (resolvedDomainObject == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("domainObject resolved to null, so including tag body");
|
||||
}
|
||||
|
||||
// Of course they have access to a null object!
|
||||
return Tag.EVAL_BODY_INCLUDE;
|
||||
}
|
||||
|
||||
if (SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
"SecurityContextHolder did not return a non-null Authentication object, so skipping tag body");
|
||||
}
|
||||
|
||||
return Tag.SKIP_BODY;
|
||||
}
|
||||
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
ApplicationContext context = getContext(pageContext);
|
||||
String[] beans = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, AclManager.class, false, false);
|
||||
|
||||
if (beans.length == 0) {
|
||||
throw new JspException("No AclManager would found the application context: " + context.toString());
|
||||
}
|
||||
|
||||
AclManager aclManager = (AclManager) context.getBean(beans[0]);
|
||||
|
||||
// Obtain aclEntrys applying to the current Authentication object
|
||||
AclEntry[] acls = aclManager.getAcls(resolvedDomainObject, auth);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Authentication: '" + auth + "' has: " + ((acls == null) ? 0 : acls.length)
|
||||
+ " AclEntrys for domain object: '" + resolvedDomainObject + "' from AclManager: '"
|
||||
+ aclManager.toString() + "'");
|
||||
}
|
||||
|
||||
if ((acls == null) || (acls.length == 0)) {
|
||||
return Tag.SKIP_BODY;
|
||||
}
|
||||
|
||||
for (int i = 0; i < acls.length; i++) {
|
||||
// Locate processable AclEntrys
|
||||
if (acls[i] instanceof BasicAclEntry) {
|
||||
BasicAclEntry processableAcl = (BasicAclEntry) acls[i];
|
||||
|
||||
// See if principal has any of the required permissions
|
||||
for (int y = 0; y < requiredIntegers.length; y++) {
|
||||
if (processableAcl.isPermitted(requiredIntegers[y].intValue())) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Including tag body as found permission: " + requiredIntegers[y]
|
||||
+ " due to AclEntry: '" + processableAcl + "'");
|
||||
}
|
||||
|
||||
return Tag.EVAL_BODY_INCLUDE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No permission, so skipping tag body");
|
||||
}
|
||||
|
||||
return Tag.SKIP_BODY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows test cases to override where application context obtained from.
|
||||
*
|
||||
* @param pageContext so the <code>ServletContext</code> can be accessed as required by Spring's
|
||||
* <code>WebApplicationContextUtils</code>
|
||||
*
|
||||
* @return the Spring application context (never <code>null</code>)
|
||||
*/
|
||||
protected ApplicationContext getContext(PageContext pageContext) {
|
||||
ServletContext servletContext = pageContext.getServletContext();
|
||||
|
||||
return WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
|
||||
}
|
||||
|
||||
public Object getDomainObject() {
|
||||
return domainObject;
|
||||
}
|
||||
|
||||
public String getHasPermission() {
|
||||
return hasPermission;
|
||||
}
|
||||
|
||||
private Integer[] parseIntegersString(String integersString)
|
||||
throws NumberFormatException {
|
||||
final Set integers = new HashSet();
|
||||
final StringTokenizer tokenizer;
|
||||
tokenizer = new StringTokenizer(integersString, ",", false);
|
||||
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
String integer = tokenizer.nextToken();
|
||||
integers.add(new Integer(integer));
|
||||
}
|
||||
|
||||
return (Integer[]) integers.toArray(new Integer[] {});
|
||||
}
|
||||
|
||||
public void setDomainObject(Object domainObject) {
|
||||
this.domainObject = domainObject;
|
||||
}
|
||||
|
||||
public void setHasPermission(String hasPermission) {
|
||||
this.hasPermission = hasPermission;
|
||||
}
|
||||
}
|
@ -17,7 +17,6 @@ package org.springframework.security.taglibs.velocity;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
|
||||
import org.springframework.security.taglibs.authz.AclTag;
|
||||
import org.springframework.security.taglibs.authz.AuthenticationTag;
|
||||
import org.springframework.security.taglibs.authz.AuthorizeTag;
|
||||
|
||||
|
@ -88,38 +88,6 @@
|
||||
</attribute>
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
<name>acl</name>
|
||||
<tag-class>org.springframework.security.taglibs.authz.AclTag</tag-class>
|
||||
<description>
|
||||
Allows inclusion of a tag body if the current Authentication
|
||||
has one of the specified permissions to the presented
|
||||
domain object instance. This tag uses the first AclManager
|
||||
it locates via
|
||||
WebApplicationContextUtils.getRequiredWebApplicationContext(HttpServletContext).
|
||||
</description>
|
||||
|
||||
<attribute>
|
||||
<name>hasPermission</name>
|
||||
<required>true</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
<description>
|
||||
A comma separated list of integers, each representing a
|
||||
required bit mask permission from a subclass of
|
||||
org.springframework.security.acl.basic.AbstractBasicAclEntry.
|
||||
</description>
|
||||
</attribute>
|
||||
<attribute>
|
||||
<name>domainObject</name>
|
||||
<required>true</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
<description>
|
||||
The actual domain object instance for which permissions
|
||||
are being evaluated.
|
||||
</description>
|
||||
</attribute>
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
<name>accesscontrollist</name>
|
||||
<tag-class>org.springframework.security.taglibs.authz.AccessControlListTag</tag-class>
|
||||
|
@ -1,179 +0,0 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.security.taglibs.authz;
|
||||
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
import javax.servlet.jsp.tagext.Tag;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.acl.AclEntry;
|
||||
import org.springframework.security.acl.AclManager;
|
||||
import org.springframework.security.acl.basic.AclObjectIdentity;
|
||||
import org.springframework.security.acl.basic.SimpleAclEntry;
|
||||
import org.springframework.security.context.SecurityContextHolder;
|
||||
import org.springframework.security.providers.TestingAuthenticationToken;
|
||||
import org.springframework.security.util.AuthorityUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link AclTag}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AclTagTests extends TestCase {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private final MyAclTag aclTag = new MyAclTag();
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
public void testInclusionDeniedWhenAclManagerUnawareOfObject() throws JspException {
|
||||
Authentication auth = new TestingAuthenticationToken("rod", "koala", AuthorityUtils.NO_AUTHORITIES );
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
aclTag.setHasPermission(new Long(SimpleAclEntry.ADMINISTRATION).toString());
|
||||
aclTag.setDomainObject(new Integer(54));
|
||||
assertEquals(Tag.SKIP_BODY, aclTag.doStartTag());
|
||||
}
|
||||
|
||||
public void testInclusionDeniedWhenNoListOfPermissionsGiven() throws JspException {
|
||||
Authentication auth = new TestingAuthenticationToken("rod", "koala", AuthorityUtils.NO_AUTHORITIES );
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
aclTag.setHasPermission(null);
|
||||
aclTag.setDomainObject("object1");
|
||||
assertEquals(Tag.SKIP_BODY, aclTag.doStartTag());
|
||||
}
|
||||
|
||||
public void testInclusionDeniedWhenPrincipalDoesNotHoldAnyPermissions() throws JspException {
|
||||
Authentication auth = new TestingAuthenticationToken("john", "crow", AuthorityUtils.NO_AUTHORITIES );
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
aclTag.setHasPermission(new Integer(SimpleAclEntry.ADMINISTRATION) + "," + new Integer(SimpleAclEntry.READ));
|
||||
assertEquals(new Integer(SimpleAclEntry.ADMINISTRATION) + "," + new Integer(SimpleAclEntry.READ),
|
||||
aclTag.getHasPermission());
|
||||
aclTag.setDomainObject("object1");
|
||||
assertEquals("object1", aclTag.getDomainObject());
|
||||
assertEquals(Tag.SKIP_BODY, aclTag.doStartTag());
|
||||
}
|
||||
|
||||
public void testInclusionDeniedWhenPrincipalDoesNotHoldRequiredPermissions() throws JspException {
|
||||
Authentication auth = new TestingAuthenticationToken("rod", "koala", AuthorityUtils.NO_AUTHORITIES );
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
aclTag.setHasPermission(new Integer(SimpleAclEntry.DELETE).toString());
|
||||
aclTag.setDomainObject("object1");
|
||||
assertEquals(Tag.SKIP_BODY, aclTag.doStartTag());
|
||||
}
|
||||
|
||||
public void testInclusionDeniedWhenSecurityContextEmpty() throws JspException {
|
||||
SecurityContextHolder.getContext().setAuthentication(null);
|
||||
|
||||
aclTag.setHasPermission(new Long(SimpleAclEntry.ADMINISTRATION).toString());
|
||||
aclTag.setDomainObject("object1");
|
||||
assertEquals(Tag.SKIP_BODY, aclTag.doStartTag());
|
||||
}
|
||||
|
||||
public void testInclusionPermittedWhenDomainObjectIsNull() throws JspException {
|
||||
aclTag.setHasPermission(new Integer(SimpleAclEntry.READ).toString());
|
||||
aclTag.setDomainObject(null);
|
||||
assertEquals(Tag.EVAL_BODY_INCLUDE, aclTag.doStartTag());
|
||||
}
|
||||
|
||||
public void testJspExceptionThrownIfHasPermissionNotValidFormat() throws JspException {
|
||||
Authentication auth = new TestingAuthenticationToken("john", "crow", AuthorityUtils.NO_AUTHORITIES );
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
aclTag.setHasPermission("0,5, 6"); // shouldn't be any space
|
||||
|
||||
try {
|
||||
aclTag.doStartTag();
|
||||
fail("Should have thrown JspException");
|
||||
} catch (JspException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testOperationWhenPrincipalHoldsPermissionOfMultipleList() throws JspException {
|
||||
Authentication auth = new TestingAuthenticationToken("rod", "koala", AuthorityUtils.NO_AUTHORITIES );
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
aclTag.setHasPermission(new Integer(SimpleAclEntry.ADMINISTRATION) + "," + new Integer(SimpleAclEntry.READ));
|
||||
aclTag.setDomainObject("object1");
|
||||
assertEquals(Tag.EVAL_BODY_INCLUDE, aclTag.doStartTag());
|
||||
}
|
||||
|
||||
public void testOperationWhenPrincipalHoldsPermissionOfSingleList() throws JspException {
|
||||
Authentication auth = new TestingAuthenticationToken("rod", "koala", AuthorityUtils.NO_AUTHORITIES );
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
aclTag.setHasPermission(new Integer(SimpleAclEntry.READ).toString());
|
||||
aclTag.setDomainObject("object1");
|
||||
assertEquals(Tag.EVAL_BODY_INCLUDE, aclTag.doStartTag());
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockAclEntry implements AclEntry {
|
||||
// just so AclTag iterates some different types of AclEntrys
|
||||
}
|
||||
|
||||
private class MyAclTag extends AclTag {
|
||||
protected ApplicationContext getContext(PageContext pageContext) {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
|
||||
final AclEntry[] acls = new AclEntry[] {
|
||||
new MockAclEntry(),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
|
||||
new SimpleAclEntry("rod", new MockAclObjectIdentity(), null, SimpleAclEntry.READ)
|
||||
};
|
||||
|
||||
|
||||
// Create an AclManager
|
||||
AclManager aclManager = new AclManager() {
|
||||
String object = "object1";
|
||||
String principal = "rod";
|
||||
|
||||
public AclEntry[] getAcls(Object domainInstance) {
|
||||
return domainInstance.equals(object) ? acls : null;
|
||||
}
|
||||
|
||||
public AclEntry[] getAcls(Object domainInstance, Authentication authentication) {
|
||||
return domainInstance.equals(object) && authentication.getPrincipal().equals(principal) ? acls : null;
|
||||
}
|
||||
};
|
||||
|
||||
// Register the AclManager into our ApplicationContext
|
||||
context.getBeanFactory().registerSingleton("aclManager", aclManager);
|
||||
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MockAclObjectIdentity implements AclObjectIdentity {
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user