Merge Formatting Changes
Issue gh-8945
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls;
|
package org.springframework.security.acls;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
@@ -24,6 +25,7 @@ import java.util.List;
|
|||||||
import org.aopalliance.intercept.MethodInvocation;
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import org.springframework.security.access.AuthorizationServiceException;
|
import org.springframework.security.access.AuthorizationServiceException;
|
||||||
import org.springframework.security.access.ConfigAttribute;
|
import org.springframework.security.access.ConfigAttribute;
|
||||||
import org.springframework.security.access.vote.AbstractAclVoter;
|
import org.springframework.security.access.vote.AbstractAclVoter;
|
||||||
@@ -39,6 +41,7 @@ import org.springframework.security.acls.model.Sid;
|
|||||||
import org.springframework.security.acls.model.SidRetrievalStrategy;
|
import org.springframework.security.acls.model.SidRetrievalStrategy;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,59 +95,45 @@ import org.springframework.util.StringUtils;
|
|||||||
* <p>
|
* <p>
|
||||||
* All comparisons and prefixes are case sensitive.
|
* All comparisons and prefixes are case sensitive.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class AclEntryVoter extends AbstractAclVoter {
|
public class AclEntryVoter extends AbstractAclVoter {
|
||||||
// ~ Static fields/initializers
|
|
||||||
// =====================================================================================
|
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(AclEntryVoter.class);
|
private static final Log logger = LogFactory.getLog(AclEntryVoter.class);
|
||||||
|
|
||||||
// ~ Instance fields
|
private final AclService aclService;
|
||||||
// ================================================================================================
|
|
||||||
|
private final String processConfigAttribute;
|
||||||
|
|
||||||
|
private final List<Permission> requirePermission;
|
||||||
|
|
||||||
private AclService aclService;
|
|
||||||
private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
||||||
|
|
||||||
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
||||||
|
|
||||||
private String internalMethod;
|
private String internalMethod;
|
||||||
private String processConfigAttribute;
|
|
||||||
private List<Permission> requirePermission;
|
|
||||||
|
|
||||||
// ~ Constructors
|
public AclEntryVoter(AclService aclService, String processConfigAttribute, Permission[] requirePermission) {
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
public AclEntryVoter(AclService aclService, String processConfigAttribute,
|
|
||||||
Permission[] requirePermission) {
|
|
||||||
Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory");
|
Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory");
|
||||||
Assert.notNull(aclService, "An AclService is mandatory");
|
Assert.notNull(aclService, "An AclService is mandatory");
|
||||||
|
Assert.isTrue(!ObjectUtils.isEmpty(requirePermission), "One or more requirePermission entries is mandatory");
|
||||||
if ((requirePermission == null) || (requirePermission.length == 0)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"One or more requirePermission entries is mandatory");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.aclService = aclService;
|
this.aclService = aclService;
|
||||||
this.processConfigAttribute = processConfigAttribute;
|
this.processConfigAttribute = processConfigAttribute;
|
||||||
this.requirePermission = Arrays.asList(requirePermission);
|
this.requirePermission = Arrays.asList(requirePermission);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optionally specifies a method of the domain object that will be used to obtain a
|
* 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
|
* 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. 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
|
* 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)
|
* 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
|
* @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>
|
* requires no arguments) that should be invoked to obtain an <code>Object</code>
|
||||||
* which will be the domain object used for ACL evaluation
|
* which will be the domain object used for ACL evaluation
|
||||||
*/
|
*/
|
||||||
protected String getInternalMethod() {
|
protected String getInternalMethod() {
|
||||||
return internalMethod;
|
return this.internalMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInternalMethod(String internalMethod) {
|
public void setInternalMethod(String internalMethod) {
|
||||||
@@ -152,13 +141,11 @@ public class AclEntryVoter extends AbstractAclVoter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected String getProcessConfigAttribute() {
|
protected String getProcessConfigAttribute() {
|
||||||
return processConfigAttribute;
|
return this.processConfigAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setObjectIdentityRetrievalStrategy(
|
public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
|
||||||
ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
|
Assert.notNull(objectIdentityRetrievalStrategy, "ObjectIdentityRetrievalStrategy required");
|
||||||
Assert.notNull(objectIdentityRetrievalStrategy,
|
|
||||||
"ObjectIdentityRetrievalStrategy required");
|
|
||||||
this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy;
|
this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,103 +154,60 @@ public class AclEntryVoter extends AbstractAclVoter {
|
|||||||
this.sidRetrievalStrategy = sidRetrievalStrategy;
|
this.sidRetrievalStrategy = sidRetrievalStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean supports(ConfigAttribute attribute) {
|
public boolean supports(ConfigAttribute attribute) {
|
||||||
return (attribute.getAttribute() != null)
|
return (attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute());
|
||||||
&& attribute.getAttribute().equals(getProcessConfigAttribute());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int vote(Authentication authentication, MethodInvocation object,
|
@Override
|
||||||
Collection<ConfigAttribute> attributes) {
|
public int vote(Authentication authentication, MethodInvocation object, Collection<ConfigAttribute> attributes) {
|
||||||
|
|
||||||
for (ConfigAttribute attr : attributes) {
|
for (ConfigAttribute attr : attributes) {
|
||||||
|
if (!supports(attr)) {
|
||||||
if (!this.supports(attr)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to make an access decision on this invocation
|
// Need to make an access decision on this invocation
|
||||||
// Attempt to locate the domain object instance to process
|
// Attempt to locate the domain object instance to process
|
||||||
Object domainObject = getDomainObjectInstance(object);
|
Object domainObject = getDomainObjectInstance(object);
|
||||||
|
|
||||||
// If domain object is null, vote to abstain
|
// If domain object is null, vote to abstain
|
||||||
if (domainObject == null) {
|
if (domainObject == null) {
|
||||||
if (logger.isDebugEnabled()) {
|
logger.debug("Voting to abstain - domainObject is null");
|
||||||
logger.debug("Voting to abstain - domainObject is null");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ACCESS_ABSTAIN;
|
return ACCESS_ABSTAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate if we are required to use an inner domain object
|
// Evaluate if we are required to use an inner domain object
|
||||||
if (StringUtils.hasText(internalMethod)) {
|
if (StringUtils.hasText(this.internalMethod)) {
|
||||||
try {
|
domainObject = invokeInternalMethod(domainObject);
|
||||||
Class<?> clazz = domainObject.getClass();
|
|
||||||
Method method = clazz.getMethod(internalMethod, new Class[0]);
|
|
||||||
domainObject = method.invoke(domainObject);
|
|
||||||
}
|
|
||||||
catch (NoSuchMethodException nsme) {
|
|
||||||
throw new AuthorizationServiceException("Object of class '"
|
|
||||||
+ domainObject.getClass()
|
|
||||||
+ "' does not provide the requested internalMethod: "
|
|
||||||
+ internalMethod);
|
|
||||||
}
|
|
||||||
catch (IllegalAccessException iae) {
|
|
||||||
logger.debug("IllegalAccessException", iae);
|
|
||||||
|
|
||||||
throw new AuthorizationServiceException(
|
|
||||||
"Problem invoking internalMethod: " + internalMethod
|
|
||||||
+ " for object: " + domainObject);
|
|
||||||
}
|
|
||||||
catch (InvocationTargetException ite) {
|
|
||||||
logger.debug("InvocationTargetException", ite);
|
|
||||||
|
|
||||||
throw new AuthorizationServiceException(
|
|
||||||
"Problem invoking internalMethod: " + internalMethod
|
|
||||||
+ " for object: " + domainObject);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtain the OID applicable to the domain object
|
// Obtain the OID applicable to the domain object
|
||||||
ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy
|
ObjectIdentity objectIdentity = this.objectIdentityRetrievalStrategy.getObjectIdentity(domainObject);
|
||||||
.getObjectIdentity(domainObject);
|
|
||||||
|
|
||||||
// Obtain the SIDs applicable to the principal
|
// Obtain the SIDs applicable to the principal
|
||||||
List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
|
List<Sid> sids = this.sidRetrievalStrategy.getSids(authentication);
|
||||||
|
|
||||||
Acl acl;
|
Acl acl;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Lookup only ACLs for SIDs we're interested in
|
// Lookup only ACLs for SIDs we're interested in
|
||||||
acl = aclService.readAclById(objectIdentity, sids);
|
acl = this.aclService.readAclById(objectIdentity, sids);
|
||||||
}
|
}
|
||||||
catch (NotFoundException nfe) {
|
catch (NotFoundException ex) {
|
||||||
if (logger.isDebugEnabled()) {
|
logger.debug("Voting to deny access - no ACLs apply for this principal");
|
||||||
logger.debug("Voting to deny access - no ACLs apply for this principal");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ACCESS_DENIED;
|
return ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (acl.isGranted(requirePermission, sids, false)) {
|
if (acl.isGranted(this.requirePermission, sids, false)) {
|
||||||
if (logger.isDebugEnabled()) {
|
logger.debug("Voting to grant access");
|
||||||
logger.debug("Voting to grant access");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ACCESS_GRANTED;
|
return ACCESS_GRANTED;
|
||||||
}
|
}
|
||||||
else {
|
logger.debug("Voting to deny access - ACLs returned, but insufficient permissions for this principal");
|
||||||
if (logger.isDebugEnabled()) {
|
return ACCESS_DENIED;
|
||||||
logger.debug("Voting to deny access - ACLs returned, but insufficient permissions for this principal");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ACCESS_DENIED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (NotFoundException nfe) {
|
catch (NotFoundException ex) {
|
||||||
if (logger.isDebugEnabled()) {
|
logger.debug("Voting to deny access - no ACLs apply for this principal");
|
||||||
logger.debug("Voting to deny access - no ACLs apply for this principal");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ACCESS_DENIED;
|
return ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -271,4 +215,27 @@ public class AclEntryVoter extends AbstractAclVoter {
|
|||||||
// No configuration attribute matched, so abstain
|
// No configuration attribute matched, so abstain
|
||||||
return ACCESS_ABSTAIN;
|
return ACCESS_ABSTAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Object invokeInternalMethod(Object domainObject) {
|
||||||
|
try {
|
||||||
|
Class<?> domainObjectType = domainObject.getClass();
|
||||||
|
Method method = domainObjectType.getMethod(this.internalMethod, new Class[0]);
|
||||||
|
return method.invoke(domainObject);
|
||||||
|
}
|
||||||
|
catch (NoSuchMethodException ex) {
|
||||||
|
throw new AuthorizationServiceException("Object of class '" + domainObject.getClass()
|
||||||
|
+ "' does not provide the requested internalMethod: " + this.internalMethod);
|
||||||
|
}
|
||||||
|
catch (IllegalAccessException ex) {
|
||||||
|
logger.debug("IllegalAccessException", ex);
|
||||||
|
throw new AuthorizationServiceException(
|
||||||
|
"Problem invoking internalMethod: " + this.internalMethod + " for object: " + domainObject);
|
||||||
|
}
|
||||||
|
catch (InvocationTargetException ex) {
|
||||||
|
logger.debug("InvocationTargetException", ex);
|
||||||
|
throw new AuthorizationServiceException(
|
||||||
|
"Problem invoking internalMethod: " + this.internalMethod + " for object: " + domainObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-16
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls;
|
package org.springframework.security.acls;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -21,6 +22,8 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import org.springframework.core.log.LogMessage;
|
||||||
import org.springframework.security.access.PermissionCacheOptimizer;
|
import org.springframework.security.access.PermissionCacheOptimizer;
|
||||||
import org.springframework.security.acls.domain.ObjectIdentityRetrievalStrategyImpl;
|
import org.springframework.security.acls.domain.ObjectIdentityRetrievalStrategyImpl;
|
||||||
import org.springframework.security.acls.domain.SidRetrievalStrategyImpl;
|
import org.springframework.security.acls.domain.SidRetrievalStrategyImpl;
|
||||||
@@ -38,45 +41,42 @@ import org.springframework.security.core.Authentication;
|
|||||||
* @since 3.1
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
public class AclPermissionCacheOptimizer implements PermissionCacheOptimizer {
|
public class AclPermissionCacheOptimizer implements PermissionCacheOptimizer {
|
||||||
|
|
||||||
private final Log logger = LogFactory.getLog(getClass());
|
private final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
private final AclService aclService;
|
private final AclService aclService;
|
||||||
|
|
||||||
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
||||||
|
|
||||||
private ObjectIdentityRetrievalStrategy oidRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
private ObjectIdentityRetrievalStrategy oidRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
||||||
|
|
||||||
public AclPermissionCacheOptimizer(AclService aclService) {
|
public AclPermissionCacheOptimizer(AclService aclService) {
|
||||||
this.aclService = aclService;
|
this.aclService = aclService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void cachePermissionsFor(Authentication authentication, Collection<?> objects) {
|
public void cachePermissionsFor(Authentication authentication, Collection<?> objects) {
|
||||||
if (objects.isEmpty()) {
|
if (objects.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ObjectIdentity> oidsToCache = new ArrayList<>(objects.size());
|
List<ObjectIdentity> oidsToCache = new ArrayList<>(objects.size());
|
||||||
|
|
||||||
for (Object domainObject : objects) {
|
for (Object domainObject : objects) {
|
||||||
if (domainObject == null) {
|
if (domainObject != null) {
|
||||||
continue;
|
ObjectIdentity oid = this.oidRetrievalStrategy.getObjectIdentity(domainObject);
|
||||||
|
oidsToCache.add(oid);
|
||||||
}
|
}
|
||||||
ObjectIdentity oid = oidRetrievalStrategy.getObjectIdentity(domainObject);
|
|
||||||
oidsToCache.add(oid);
|
|
||||||
}
|
}
|
||||||
|
List<Sid> sids = this.sidRetrievalStrategy.getSids(authentication);
|
||||||
List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
|
this.logger.debug(LogMessage.of(() -> "Eagerly loading Acls for " + oidsToCache.size() + " objects"));
|
||||||
|
this.aclService.readAclsById(oidsToCache, sids);
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("Eagerly loading Acls for " + oidsToCache.size() + " objects");
|
|
||||||
}
|
|
||||||
|
|
||||||
aclService.readAclsById(oidsToCache, sids);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setObjectIdentityRetrievalStrategy(
|
public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
|
||||||
ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
|
|
||||||
this.oidRetrievalStrategy = objectIdentityRetrievalStrategy;
|
this.oidRetrievalStrategy = objectIdentityRetrievalStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) {
|
public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) {
|
||||||
this.sidRetrievalStrategy = sidRetrievalStrategy;
|
this.sidRetrievalStrategy = sidRetrievalStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls;
|
package org.springframework.security.acls;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -22,6 +23,8 @@ import java.util.Locale;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import org.springframework.core.log.LogMessage;
|
||||||
import org.springframework.security.access.PermissionEvaluator;
|
import org.springframework.security.access.PermissionEvaluator;
|
||||||
import org.springframework.security.acls.domain.DefaultPermissionFactory;
|
import org.springframework.security.acls.domain.DefaultPermissionFactory;
|
||||||
import org.springframework.security.acls.domain.ObjectIdentityRetrievalStrategyImpl;
|
import org.springframework.security.acls.domain.ObjectIdentityRetrievalStrategyImpl;
|
||||||
@@ -51,9 +54,13 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
|
|||||||
private final Log logger = LogFactory.getLog(getClass());
|
private final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
private final AclService aclService;
|
private final AclService aclService;
|
||||||
|
|
||||||
private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
||||||
|
|
||||||
private ObjectIdentityGenerator objectIdentityGenerator = new ObjectIdentityRetrievalStrategyImpl();
|
private ObjectIdentityGenerator objectIdentityGenerator = new ObjectIdentityRetrievalStrategyImpl();
|
||||||
|
|
||||||
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
||||||
|
|
||||||
private PermissionFactory permissionFactory = new DefaultPermissionFactory();
|
private PermissionFactory permissionFactory = new DefaultPermissionFactory();
|
||||||
|
|
||||||
public AclPermissionEvaluator(AclService aclService) {
|
public AclPermissionEvaluator(AclService aclService) {
|
||||||
@@ -65,100 +72,72 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
|
|||||||
* the ACL configuration. If the domain object is null, returns false (this can always
|
* the ACL configuration. If the domain object is null, returns false (this can always
|
||||||
* be overridden using a null check in the expression itself).
|
* be overridden using a null check in the expression itself).
|
||||||
*/
|
*/
|
||||||
public boolean hasPermission(Authentication authentication, Object domainObject,
|
@Override
|
||||||
Object permission) {
|
public boolean hasPermission(Authentication authentication, Object domainObject, Object permission) {
|
||||||
if (domainObject == null) {
|
if (domainObject == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
ObjectIdentity objectIdentity = this.objectIdentityRetrievalStrategy.getObjectIdentity(domainObject);
|
||||||
ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy
|
|
||||||
.getObjectIdentity(domainObject);
|
|
||||||
|
|
||||||
return checkPermission(authentication, objectIdentity, permission);
|
return checkPermission(authentication, objectIdentity, permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasPermission(Authentication authentication, Serializable targetId,
|
@Override
|
||||||
String targetType, Object permission) {
|
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType,
|
||||||
ObjectIdentity objectIdentity = objectIdentityGenerator.createObjectIdentity(
|
|
||||||
targetId, targetType);
|
|
||||||
|
|
||||||
return checkPermission(authentication, objectIdentity, permission);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean checkPermission(Authentication authentication, ObjectIdentity oid,
|
|
||||||
Object permission) {
|
Object permission) {
|
||||||
|
ObjectIdentity objectIdentity = this.objectIdentityGenerator.createObjectIdentity(targetId, targetType);
|
||||||
|
return checkPermission(authentication, objectIdentity, permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkPermission(Authentication authentication, ObjectIdentity oid, Object permission) {
|
||||||
// Obtain the SIDs applicable to the principal
|
// Obtain the SIDs applicable to the principal
|
||||||
List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
|
List<Sid> sids = this.sidRetrievalStrategy.getSids(authentication);
|
||||||
List<Permission> requiredPermission = resolvePermission(permission);
|
List<Permission> requiredPermission = resolvePermission(permission);
|
||||||
|
this.logger.debug(LogMessage.of(() -> "Checking permission '" + permission + "' for object '" + oid + "'"));
|
||||||
final boolean debug = logger.isDebugEnabled();
|
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
logger.debug("Checking permission '" + permission + "' for object '" + oid
|
|
||||||
+ "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Lookup only ACLs for SIDs we're interested in
|
// Lookup only ACLs for SIDs we're interested in
|
||||||
Acl acl = aclService.readAclById(oid, sids);
|
Acl acl = this.aclService.readAclById(oid, sids);
|
||||||
|
|
||||||
if (acl.isGranted(requiredPermission, sids, false)) {
|
if (acl.isGranted(requiredPermission, sids, false)) {
|
||||||
if (debug) {
|
this.logger.debug("Access is granted");
|
||||||
logger.debug("Access is granted");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
this.logger.debug("Returning false - ACLs returned, but insufficient permissions for this principal");
|
||||||
if (debug) {
|
|
||||||
logger.debug("Returning false - ACLs returned, but insufficient permissions for this principal");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (NotFoundException nfe) {
|
catch (NotFoundException nfe) {
|
||||||
if (debug) {
|
this.logger.debug("Returning false - no ACLs apply for this principal");
|
||||||
logger.debug("Returning false - no ACLs apply for this principal");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Permission> resolvePermission(Object permission) {
|
List<Permission> resolvePermission(Object permission) {
|
||||||
if (permission instanceof Integer) {
|
if (permission instanceof Integer) {
|
||||||
return Arrays.asList(permissionFactory.buildFromMask((Integer) permission));
|
return Arrays.asList(this.permissionFactory.buildFromMask((Integer) permission));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (permission instanceof Permission) {
|
if (permission instanceof Permission) {
|
||||||
return Arrays.asList((Permission) permission);
|
return Arrays.asList((Permission) permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (permission instanceof Permission[]) {
|
if (permission instanceof Permission[]) {
|
||||||
return Arrays.asList((Permission[]) permission);
|
return Arrays.asList((Permission[]) permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (permission instanceof String) {
|
if (permission instanceof String) {
|
||||||
String permString = (String) permission;
|
String permString = (String) permission;
|
||||||
Permission p;
|
Permission p = buildPermission(permString);
|
||||||
|
|
||||||
try {
|
|
||||||
p = permissionFactory.buildFromName(permString);
|
|
||||||
}
|
|
||||||
catch (IllegalArgumentException notfound) {
|
|
||||||
p = permissionFactory.buildFromName(permString.toUpperCase(Locale.ENGLISH));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p != null) {
|
if (p != null) {
|
||||||
return Arrays.asList(p);
|
return Arrays.asList(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException("Unsupported permission: " + permission);
|
throw new IllegalArgumentException("Unsupported permission: " + permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setObjectIdentityRetrievalStrategy(
|
private Permission buildPermission(String permString) {
|
||||||
ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
|
try {
|
||||||
|
return this.permissionFactory.buildFromName(permString);
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException notfound) {
|
||||||
|
return this.permissionFactory.buildFromName(permString.toUpperCase(Locale.ENGLISH));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
|
||||||
this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy;
|
this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,4 +152,5 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
|
|||||||
public void setPermissionFactory(PermissionFactory permissionFactory) {
|
public void setPermissionFactory(PermissionFactory permissionFactory) {
|
||||||
this.permissionFactory = permissionFactory;
|
this.permissionFactory = permissionFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-35
@@ -32,6 +32,7 @@ import org.springframework.security.acls.model.Sid;
|
|||||||
import org.springframework.security.acls.model.SidRetrievalStrategy;
|
import org.springframework.security.acls.model.SidRetrievalStrategy;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract {@link AfterInvocationProvider} which provides commonly-used ACL-related
|
* Abstract {@link AfterInvocationProvider} which provides commonly-used ACL-related
|
||||||
@@ -40,64 +41,52 @@ import org.springframework.util.Assert;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractAclProvider implements AfterInvocationProvider {
|
public abstract class AbstractAclProvider implements AfterInvocationProvider {
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
protected final AclService aclService;
|
protected final AclService aclService;
|
||||||
protected Class<?> processDomainObjectClass = Object.class;
|
|
||||||
protected ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
|
||||||
protected SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
|
||||||
protected String processConfigAttribute;
|
|
||||||
protected final List<Permission> requirePermission;
|
|
||||||
|
|
||||||
// ~ Constructors
|
protected String processConfigAttribute;
|
||||||
// ===================================================================================================
|
|
||||||
|
protected Class<?> processDomainObjectClass = Object.class;
|
||||||
|
|
||||||
|
protected ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
||||||
|
|
||||||
|
protected SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
||||||
|
|
||||||
|
protected final List<Permission> requirePermission;
|
||||||
|
|
||||||
public AbstractAclProvider(AclService aclService, String processConfigAttribute,
|
public AbstractAclProvider(AclService aclService, String processConfigAttribute,
|
||||||
List<Permission> requirePermission) {
|
List<Permission> requirePermission) {
|
||||||
Assert.hasText(processConfigAttribute, "A processConfigAttribute is mandatory");
|
Assert.hasText(processConfigAttribute, "A processConfigAttribute is mandatory");
|
||||||
Assert.notNull(aclService, "An AclService is mandatory");
|
Assert.notNull(aclService, "An AclService is mandatory");
|
||||||
|
Assert.isTrue(!ObjectUtils.isEmpty(requirePermission), "One or more requirePermission entries is mandatory");
|
||||||
if (requirePermission == null || requirePermission.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"One or more requirePermission entries is mandatory");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.aclService = aclService;
|
this.aclService = aclService;
|
||||||
this.processConfigAttribute = processConfigAttribute;
|
this.processConfigAttribute = processConfigAttribute;
|
||||||
this.requirePermission = requirePermission;
|
this.requirePermission = requirePermission;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
protected Class<?> getProcessDomainObjectClass() {
|
protected Class<?> getProcessDomainObjectClass() {
|
||||||
return processDomainObjectClass;
|
return this.processDomainObjectClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean hasPermission(Authentication authentication, Object domainObject) {
|
protected boolean hasPermission(Authentication authentication, Object domainObject) {
|
||||||
// Obtain the OID applicable to the domain object
|
// Obtain the OID applicable to the domain object
|
||||||
ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy
|
ObjectIdentity objectIdentity = this.objectIdentityRetrievalStrategy.getObjectIdentity(domainObject);
|
||||||
.getObjectIdentity(domainObject);
|
|
||||||
|
|
||||||
// Obtain the SIDs applicable to the principal
|
// Obtain the SIDs applicable to the principal
|
||||||
List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
|
List<Sid> sids = this.sidRetrievalStrategy.getSids(authentication);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Lookup only ACLs for SIDs we're interested in
|
// Lookup only ACLs for SIDs we're interested in
|
||||||
Acl acl = aclService.readAclById(objectIdentity, sids);
|
Acl acl = this.aclService.readAclById(objectIdentity, sids);
|
||||||
|
return acl.isGranted(this.requirePermission, sids, false);
|
||||||
return acl.isGranted(requirePermission, sids, false);
|
|
||||||
}
|
}
|
||||||
catch (NotFoundException ignore) {
|
catch (NotFoundException ex) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setObjectIdentityRetrievalStrategy(
|
public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
|
||||||
ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
|
Assert.notNull(objectIdentityRetrievalStrategy, "ObjectIdentityRetrievalStrategy required");
|
||||||
Assert.notNull(objectIdentityRetrievalStrategy,
|
|
||||||
"ObjectIdentityRetrievalStrategy required");
|
|
||||||
this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy;
|
this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,8 +96,7 @@ public abstract class AbstractAclProvider implements AfterInvocationProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setProcessDomainObjectClass(Class<?> processDomainObjectClass) {
|
public void setProcessDomainObjectClass(Class<?> processDomainObjectClass) {
|
||||||
Assert.notNull(processDomainObjectClass,
|
Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null");
|
||||||
"processDomainObjectClass cannot be set to null");
|
|
||||||
this.processDomainObjectClass = processDomainObjectClass;
|
this.processDomainObjectClass = processDomainObjectClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,19 +105,20 @@ public abstract class AbstractAclProvider implements AfterInvocationProvider {
|
|||||||
this.sidRetrievalStrategy = sidRetrievalStrategy;
|
this.sidRetrievalStrategy = sidRetrievalStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean supports(ConfigAttribute attribute) {
|
public boolean supports(ConfigAttribute attribute) {
|
||||||
return processConfigAttribute.equals(attribute.getAttribute());
|
return this.processConfigAttribute.equals(attribute.getAttribute());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This implementation supports any type of class, because it does not query the
|
* This implementation supports any type of class, because it does not query the
|
||||||
* presented secure object.
|
* presented secure object.
|
||||||
*
|
|
||||||
* @param clazz the secure object
|
* @param clazz the secure object
|
||||||
*
|
|
||||||
* @return always <code>true</code>
|
* @return always <code>true</code>
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public boolean supports(Class<?> clazz) {
|
public boolean supports(Class<?> clazz) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-42
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.afterinvocation;
|
package org.springframework.security.acls.afterinvocation;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -20,6 +21,8 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import org.springframework.core.log.LogMessage;
|
||||||
import org.springframework.security.access.AccessDeniedException;
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
import org.springframework.security.access.AuthorizationServiceException;
|
import org.springframework.security.access.AuthorizationServiceException;
|
||||||
import org.springframework.security.access.ConfigAttribute;
|
import org.springframework.security.access.ConfigAttribute;
|
||||||
@@ -60,33 +63,21 @@ import org.springframework.security.core.Authentication;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
* @author Paulo Neves
|
* @author Paulo Neves
|
||||||
*/
|
*/
|
||||||
public class AclEntryAfterInvocationCollectionFilteringProvider extends
|
public class AclEntryAfterInvocationCollectionFilteringProvider extends AbstractAclProvider {
|
||||||
AbstractAclProvider {
|
|
||||||
// ~ Static fields/initializers
|
|
||||||
// =====================================================================================
|
|
||||||
|
|
||||||
protected static final Log logger = LogFactory
|
protected static final Log logger = LogFactory.getLog(AclEntryAfterInvocationCollectionFilteringProvider.class);
|
||||||
.getLog(AclEntryAfterInvocationCollectionFilteringProvider.class);
|
|
||||||
|
|
||||||
// ~ Constructors
|
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
public AclEntryAfterInvocationCollectionFilteringProvider(AclService aclService,
|
public AclEntryAfterInvocationCollectionFilteringProvider(AclService aclService,
|
||||||
List<Permission> requirePermission) {
|
List<Permission> requirePermission) {
|
||||||
super(aclService, "AFTER_ACL_COLLECTION_READ", requirePermission);
|
super(aclService, "AFTER_ACL_COLLECTION_READ", requirePermission);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
@Override
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Object decide(Authentication authentication, Object object,
|
public Object decide(Authentication authentication, Object object, Collection<ConfigAttribute> config,
|
||||||
Collection<ConfigAttribute> config, Object returnedObject)
|
Object returnedObject) throws AccessDeniedException {
|
||||||
throws AccessDeniedException {
|
|
||||||
|
|
||||||
if (returnedObject == null) {
|
if (returnedObject == null) {
|
||||||
logger.debug("Return object is null, skipping");
|
logger.debug("Return object is null, skipping");
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,44 +87,34 @@ public class AclEntryAfterInvocationCollectionFilteringProvider extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Need to process the Collection for this invocation
|
// Need to process the Collection for this invocation
|
||||||
Filterer filterer;
|
Filterer filterer = getFilterer(returnedObject);
|
||||||
|
|
||||||
if (returnedObject instanceof Collection) {
|
|
||||||
filterer = new CollectionFilterer((Collection) returnedObject);
|
|
||||||
}
|
|
||||||
else if (returnedObject.getClass().isArray()) {
|
|
||||||
filterer = new ArrayFilterer((Object[]) returnedObject);
|
|
||||||
}
|
|
||||||
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
|
// Locate unauthorised Collection elements
|
||||||
for (Object domainObject : filterer) {
|
for (Object domainObject : filterer) {
|
||||||
// Ignore nulls or entries which aren't instances of the configured domain
|
// Ignore nulls or entries which aren't instances of the configured domain
|
||||||
// object class
|
// object class
|
||||||
if (domainObject == null
|
if (domainObject == null || !getProcessDomainObjectClass().isAssignableFrom(domainObject.getClass())) {
|
||||||
|| !getProcessDomainObjectClass().isAssignableFrom(
|
|
||||||
domainObject.getClass())) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasPermission(authentication, domainObject)) {
|
if (!hasPermission(authentication, domainObject)) {
|
||||||
filterer.remove(domainObject);
|
filterer.remove(domainObject);
|
||||||
|
logger.debug(LogMessage.of(() -> "Principal is NOT authorised for element: " + domainObject));
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("Principal is NOT authorised for element: "
|
|
||||||
+ domainObject);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return filterer.getFilteredObject();
|
return filterer.getFilteredObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnedObject;
|
return returnedObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Filterer getFilterer(Object returnedObject) {
|
||||||
|
if (returnedObject instanceof Collection) {
|
||||||
|
return new CollectionFilterer((Collection) returnedObject);
|
||||||
|
}
|
||||||
|
if (returnedObject.getClass().isArray()) {
|
||||||
|
return new ArrayFilterer((Object[]) returnedObject);
|
||||||
|
}
|
||||||
|
throw new AuthorizationServiceException("A Collection or an array (or null) was required as the "
|
||||||
|
+ "returnedObject, but the returnedObject was: " + returnedObject);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-29
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.afterinvocation;
|
package org.springframework.security.acls.afterinvocation;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -20,6 +21,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.MessageSource;
|
||||||
import org.springframework.context.MessageSourceAware;
|
import org.springframework.context.MessageSourceAware;
|
||||||
import org.springframework.context.support.MessageSourceAccessor;
|
import org.springframework.context.support.MessageSourceAccessor;
|
||||||
@@ -58,50 +60,34 @@ import org.springframework.security.core.SpringSecurityMessageSource;
|
|||||||
* <p>
|
* <p>
|
||||||
* All comparisons and prefixes are case sensitive.
|
* All comparisons and prefixes are case sensitive.
|
||||||
*/
|
*/
|
||||||
public class AclEntryAfterInvocationProvider extends AbstractAclProvider implements
|
public class AclEntryAfterInvocationProvider extends AbstractAclProvider implements MessageSourceAware {
|
||||||
MessageSourceAware {
|
|
||||||
// ~ Static fields/initializers
|
|
||||||
// =====================================================================================
|
|
||||||
|
|
||||||
protected static final Log logger = LogFactory
|
protected static final Log logger = LogFactory.getLog(AclEntryAfterInvocationProvider.class);
|
||||||
.getLog(AclEntryAfterInvocationProvider.class);
|
|
||||||
|
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
|
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
|
||||||
|
|
||||||
// ~ Constructors
|
public AclEntryAfterInvocationProvider(AclService aclService, List<Permission> requirePermission) {
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
public AclEntryAfterInvocationProvider(AclService aclService,
|
|
||||||
List<Permission> requirePermission) {
|
|
||||||
this(aclService, "AFTER_ACL_READ", requirePermission);
|
this(aclService, "AFTER_ACL_READ", requirePermission);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AclEntryAfterInvocationProvider(AclService aclService,
|
public AclEntryAfterInvocationProvider(AclService aclService, String processConfigAttribute,
|
||||||
String processConfigAttribute, List<Permission> requirePermission) {
|
List<Permission> requirePermission) {
|
||||||
super(aclService, processConfigAttribute, requirePermission);
|
super(aclService, processConfigAttribute, requirePermission);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
@Override
|
||||||
// ========================================================================================================
|
public Object decide(Authentication authentication, Object object, Collection<ConfigAttribute> config,
|
||||||
|
Object returnedObject) throws AccessDeniedException {
|
||||||
public Object decide(Authentication authentication, Object object,
|
|
||||||
Collection<ConfigAttribute> config, Object returnedObject)
|
|
||||||
throws AccessDeniedException {
|
|
||||||
|
|
||||||
if (returnedObject == null) {
|
if (returnedObject == null) {
|
||||||
// AclManager interface contract prohibits nulls
|
// AclManager interface contract prohibits nulls
|
||||||
// As they have permission to null/nothing, grant access
|
// As they have permission to null/nothing, grant access
|
||||||
logger.debug("Return object is null, skipping");
|
logger.debug("Return object is null, skipping");
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!getProcessDomainObjectClass().isAssignableFrom(returnedObject.getClass())) {
|
if (!getProcessDomainObjectClass().isAssignableFrom(returnedObject.getClass())) {
|
||||||
logger.debug("Return object is not applicable for this provider, skipping");
|
logger.debug("Return object is not applicable for this provider, skipping");
|
||||||
|
|
||||||
return returnedObject;
|
return returnedObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,24 +95,24 @@ public class AclEntryAfterInvocationProvider extends AbstractAclProvider impleme
|
|||||||
if (!this.supports(attr)) {
|
if (!this.supports(attr)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Need to make an access decision on this invocation
|
|
||||||
|
|
||||||
|
// Need to make an access decision on this invocation
|
||||||
if (hasPermission(authentication, returnedObject)) {
|
if (hasPermission(authentication, returnedObject)) {
|
||||||
return returnedObject;
|
return returnedObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug("Denying access");
|
logger.debug("Denying access");
|
||||||
|
throw new AccessDeniedException(this.messages.getMessage("AclEntryAfterInvocationProvider.noPermission",
|
||||||
throw new AccessDeniedException(messages.getMessage(
|
new Object[] { authentication.getName(), returnedObject },
|
||||||
"AclEntryAfterInvocationProvider.noPermission", new Object[] {
|
|
||||||
authentication.getName(), returnedObject },
|
|
||||||
"Authentication {0} has NO permissions to the domain object {1}"));
|
"Authentication {0} has NO permissions to the domain object {1}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnedObject;
|
return returnedObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setMessageSource(MessageSource messageSource) {
|
public void setMessageSource(MessageSource messageSource) {
|
||||||
this.messages = new MessageSourceAccessor(messageSource);
|
this.messages = new MessageSourceAccessor(messageSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+38
-57
@@ -25,6 +25,8 @@ import java.util.Set;
|
|||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import org.springframework.core.log.LogMessage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A filter used to filter arrays.
|
* A filter used to filter arrays.
|
||||||
*
|
*
|
||||||
@@ -32,91 +34,70 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
* @author Paulo Neves
|
* @author Paulo Neves
|
||||||
*/
|
*/
|
||||||
class ArrayFilterer<T> implements Filterer<T> {
|
class ArrayFilterer<T> implements Filterer<T> {
|
||||||
// ~ Static fields/initializers
|
|
||||||
// =====================================================================================
|
|
||||||
|
|
||||||
protected static final Log logger = LogFactory.getLog(ArrayFilterer.class);
|
protected static final Log logger = LogFactory.getLog(ArrayFilterer.class);
|
||||||
|
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
private final Set<T> removeList;
|
private final Set<T> removeList;
|
||||||
private final T[] list;
|
|
||||||
|
|
||||||
// ~ Constructors
|
private final T[] list;
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
ArrayFilterer(T[] list) {
|
ArrayFilterer(T[] list) {
|
||||||
this.list = list;
|
this.list = list;
|
||||||
|
|
||||||
// Collect the removed objects to a HashSet so that
|
// Collect the removed objects to a HashSet so that
|
||||||
// it is fast to lookup them when a filtered array
|
// it is fast to lookup them when a filtered array
|
||||||
// is constructed.
|
// is constructed.
|
||||||
removeList = new HashSet<>();
|
this.removeList = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
@Override
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see org.springframework.security.acls.afterinvocation.Filterer#getFilteredObject()
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public T[] getFilteredObject() {
|
public T[] getFilteredObject() {
|
||||||
// Recreate an array of same type and filter the removed objects.
|
// Recreate an array of same type and filter the removed objects.
|
||||||
int originalSize = list.length;
|
int originalSize = this.list.length;
|
||||||
int sizeOfResultingList = originalSize - removeList.size();
|
int sizeOfResultingList = originalSize - this.removeList.size();
|
||||||
T[] filtered = (T[]) Array.newInstance(list.getClass().getComponentType(),
|
T[] filtered = (T[]) Array.newInstance(this.list.getClass().getComponentType(), sizeOfResultingList);
|
||||||
sizeOfResultingList);
|
for (int i = 0, j = 0; i < this.list.length; i++) {
|
||||||
|
T object = this.list[i];
|
||||||
for (int i = 0, j = 0; i < list.length; i++) {
|
if (!this.removeList.contains(object)) {
|
||||||
T object = list[i];
|
|
||||||
|
|
||||||
if (!removeList.contains(object)) {
|
|
||||||
filtered[j] = object;
|
filtered[j] = object;
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
logger.debug(LogMessage.of(() -> "Original array contained " + originalSize + " elements; now contains "
|
||||||
if (logger.isDebugEnabled()) {
|
+ sizeOfResultingList + " elements"));
|
||||||
logger.debug("Original array contained " + originalSize
|
|
||||||
+ " elements; now contains " + sizeOfResultingList + " elements");
|
|
||||||
}
|
|
||||||
|
|
||||||
return filtered;
|
return filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
*
|
|
||||||
* @see org.springframework.security.acls.afterinvocation.Filterer#iterator()
|
|
||||||
*/
|
|
||||||
public Iterator<T> iterator() {
|
public Iterator<T> iterator() {
|
||||||
return new Iterator<T>() {
|
return new ArrayFiltererIterator();
|
||||||
private int index = 0;
|
}
|
||||||
|
|
||||||
public boolean hasNext() {
|
@Override
|
||||||
return index < list.length;
|
public void remove(T object) {
|
||||||
}
|
this.removeList.add(object);
|
||||||
|
|
||||||
public T next() {
|
|
||||||
if (!hasNext()) {
|
|
||||||
throw new NoSuchElementException();
|
|
||||||
}
|
|
||||||
return list[index++];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void remove() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Iterator for {@link ArrayFilterer} elements.
|
||||||
* @see org.springframework.security.acls.afterinvocation.Filterer#remove(java.lang.Object)
|
|
||||||
*/
|
*/
|
||||||
public void remove(T object) {
|
private class ArrayFiltererIterator implements Iterator<T> {
|
||||||
removeList.add(object);
|
|
||||||
|
private int index = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return this.index < ArrayFilterer.this.list.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T next() {
|
||||||
|
if (hasNext()) {
|
||||||
|
return ArrayFilterer.this.list[this.index++];
|
||||||
|
}
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-42
@@ -16,14 +16,16 @@
|
|||||||
|
|
||||||
package org.springframework.security.acls.afterinvocation;
|
package org.springframework.security.acls.afterinvocation;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import org.springframework.core.log.LogMessage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A filter used to filter Collections.
|
* A filter used to filter Collections.
|
||||||
*
|
*
|
||||||
@@ -31,24 +33,15 @@ import java.util.Set;
|
|||||||
* @author Paulo Neves
|
* @author Paulo Neves
|
||||||
*/
|
*/
|
||||||
class CollectionFilterer<T> implements Filterer<T> {
|
class CollectionFilterer<T> implements Filterer<T> {
|
||||||
// ~ Static fields/initializers
|
|
||||||
// =====================================================================================
|
|
||||||
|
|
||||||
protected static final Log logger = LogFactory.getLog(CollectionFilterer.class);
|
protected static final Log logger = LogFactory.getLog(CollectionFilterer.class);
|
||||||
|
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
private final Collection<T> collection;
|
private final Collection<T> collection;
|
||||||
|
|
||||||
private final Set<T> removeList;
|
private final Set<T> removeList;
|
||||||
|
|
||||||
// ~ Constructors
|
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
CollectionFilterer(Collection<T> collection) {
|
CollectionFilterer(Collection<T> collection) {
|
||||||
this.collection = collection;
|
this.collection = collection;
|
||||||
|
|
||||||
// We create a Set of objects to be removed from the Collection,
|
// We create a Set of objects to be removed from the Collection,
|
||||||
// as ConcurrentModificationException prevents removal during
|
// as ConcurrentModificationException prevents removal during
|
||||||
// iteration, and making a new Collection to be returned is
|
// iteration, and making a new Collection to be returned is
|
||||||
@@ -56,47 +49,30 @@ class CollectionFilterer<T> implements Filterer<T> {
|
|||||||
// to the method may not necessarily be re-constructable (as
|
// to the method may not necessarily be re-constructable (as
|
||||||
// the Collection(collection) constructor is not guaranteed and
|
// the Collection(collection) constructor is not guaranteed and
|
||||||
// manually adding may lose sort order or other capabilities)
|
// manually adding may lose sort order or other capabilities)
|
||||||
removeList = new HashSet<>();
|
this.removeList = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
@Override
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see org.springframework.security.acls.afterinvocation.Filterer#getFilteredObject()
|
|
||||||
*/
|
|
||||||
public Object getFilteredObject() {
|
public Object getFilteredObject() {
|
||||||
// Now the Iterator has ended, remove Objects from Collection
|
// Now the Iterator has ended, remove Objects from Collection
|
||||||
Iterator<T> removeIter = removeList.iterator();
|
Iterator<T> removeIter = this.removeList.iterator();
|
||||||
|
int originalSize = this.collection.size();
|
||||||
int originalSize = collection.size();
|
|
||||||
|
|
||||||
while (removeIter.hasNext()) {
|
while (removeIter.hasNext()) {
|
||||||
collection.remove(removeIter.next());
|
this.collection.remove(removeIter.next());
|
||||||
}
|
}
|
||||||
|
logger.debug(LogMessage.of(() -> "Original collection contained " + originalSize + " elements; now contains "
|
||||||
if (logger.isDebugEnabled()) {
|
+ this.collection.size() + " elements"));
|
||||||
logger.debug("Original collection contained " + originalSize
|
return this.collection;
|
||||||
+ " elements; now contains " + collection.size() + " elements");
|
|
||||||
}
|
|
||||||
|
|
||||||
return collection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
*
|
|
||||||
* @see org.springframework.security.acls.afterinvocation.Filterer#iterator()
|
|
||||||
*/
|
|
||||||
public Iterator<T> iterator() {
|
public Iterator<T> iterator() {
|
||||||
return collection.iterator();
|
return this.collection.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
*
|
|
||||||
* @see org.springframework.security.acls.afterinvocation.Filterer#remove(java.lang.Object)
|
|
||||||
*/
|
|
||||||
public void remove(T object) {
|
public void remove(T object) {
|
||||||
removeList.add(object);
|
this.removeList.add(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,27 +25,24 @@ import java.util.Iterator;
|
|||||||
* @author Paulo Neves
|
* @author Paulo Neves
|
||||||
*/
|
*/
|
||||||
interface Filterer<T> extends Iterable<T> {
|
interface Filterer<T> extends Iterable<T> {
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the filtered collection or array.
|
* Gets the filtered collection or array.
|
||||||
*
|
|
||||||
* @return the filtered collection or array
|
* @return the filtered collection or array
|
||||||
*/
|
*/
|
||||||
Object getFilteredObject();
|
Object getFilteredObject();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an iterator over the filtered collection or array.
|
* Returns an iterator over the filtered collection or array.
|
||||||
*
|
|
||||||
* @return an Iterator
|
* @return an Iterator
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
Iterator<T> iterator();
|
Iterator<T> iterator();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the given object from the resulting list.
|
* Removes the given object from the resulting list.
|
||||||
*
|
|
||||||
* @param object the object to be removed
|
* @param object the object to be removed
|
||||||
*/
|
*/
|
||||||
void remove(T object);
|
void remove(T object);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -13,9 +13,9 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* After-invocation providers for collection and array filtering. Consider using a {@code PostFilter} annotation in
|
* After-invocation providers for collection and array filtering. Consider using a
|
||||||
* preference.
|
* {@code PostFilter} annotation in preference.
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.acls.afterinvocation;
|
package org.springframework.security.acls.afterinvocation;
|
||||||
|
|
||||||
|
|||||||
+25
-30
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.Permission;
|
import org.springframework.security.acls.model.Permission;
|
||||||
@@ -25,18 +26,13 @@ import org.springframework.security.acls.model.Permission;
|
|||||||
*/
|
*/
|
||||||
public abstract class AbstractPermission implements Permission {
|
public abstract class AbstractPermission implements Permission {
|
||||||
|
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
protected final char code;
|
protected final char code;
|
||||||
|
|
||||||
protected int mask;
|
protected int mask;
|
||||||
|
|
||||||
// ~ Constructors
|
|
||||||
// ===================================================================================================
|
|
||||||
/**
|
/**
|
||||||
* Sets the permission mask and uses the '*' character to represent active bits when
|
* Sets the permission mask and uses the '*' character to represent active bits when
|
||||||
* represented as a bit pattern string.
|
* represented as a bit pattern string.
|
||||||
*
|
|
||||||
* @param mask the integer bit mask for the permission
|
* @param mask the integer bit mask for the permission
|
||||||
*/
|
*/
|
||||||
protected AbstractPermission(int mask) {
|
protected AbstractPermission(int mask) {
|
||||||
@@ -46,7 +42,6 @@ public abstract class AbstractPermission implements Permission {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the permission mask and uses the specified character for active bits.
|
* Sets the permission mask and uses the specified character for active bits.
|
||||||
*
|
|
||||||
* @param mask the integer bit mask for the permission
|
* @param mask the integer bit mask for the permission
|
||||||
* @param code the character to print for each active bit in the mask (see
|
* @param code the character to print for each active bit in the mask (see
|
||||||
* {@link Permission#getPattern()})
|
* {@link Permission#getPattern()})
|
||||||
@@ -56,36 +51,36 @@ public abstract class AbstractPermission implements Permission {
|
|||||||
this.code = code;
|
this.code = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
@Override
|
||||||
// ========================================================================================================
|
public final boolean equals(Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
public final boolean equals(Object arg0) {
|
|
||||||
if (arg0 == null) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!(obj instanceof Permission)) {
|
||||||
if (!(arg0 instanceof Permission)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Permission other = (Permission) obj;
|
||||||
Permission rhs = (Permission) arg0;
|
return (this.mask == other.getMask());
|
||||||
|
|
||||||
return (this.mask == rhs.getMask());
|
|
||||||
}
|
|
||||||
|
|
||||||
public final int getMask() {
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPattern() {
|
|
||||||
return AclFormattingUtils.printBinary(mask, code);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final String toString() {
|
|
||||||
return this.getClass().getSimpleName() + "[" + getPattern() + "=" + mask + "]";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public final int hashCode() {
|
public final int hashCode() {
|
||||||
return this.mask;
|
return this.mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final String toString() {
|
||||||
|
return this.getClass().getSimpleName() + "[" + getPattern() + "=" + this.mask + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final int getMask() {
|
||||||
|
return this.mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPattern() {
|
||||||
|
return AclFormattingUtils.printBinary(this.mask, this.code);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-45
@@ -13,42 +13,41 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.AccessControlEntry;
|
import org.springframework.security.acls.model.AccessControlEntry;
|
||||||
import org.springframework.security.acls.model.Acl;
|
import org.springframework.security.acls.model.Acl;
|
||||||
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
||||||
import org.springframework.security.acls.model.Permission;
|
import org.springframework.security.acls.model.Permission;
|
||||||
import org.springframework.security.acls.model.Sid;
|
import org.springframework.security.acls.model.Sid;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An immutable default implementation of <code>AccessControlEntry</code>.
|
* An immutable default implementation of <code>AccessControlEntry</code>.
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class AccessControlEntryImpl implements AccessControlEntry,
|
public class AccessControlEntryImpl implements AccessControlEntry, AuditableAccessControlEntry {
|
||||||
AuditableAccessControlEntry {
|
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
private final Acl acl;
|
private final Acl acl;
|
||||||
|
|
||||||
private Permission permission;
|
private Permission permission;
|
||||||
|
|
||||||
private final Serializable id;
|
private final Serializable id;
|
||||||
|
|
||||||
private final Sid sid;
|
private final Sid sid;
|
||||||
|
|
||||||
private boolean auditFailure = false;
|
private boolean auditFailure = false;
|
||||||
|
|
||||||
private boolean auditSuccess = false;
|
private boolean auditSuccess = false;
|
||||||
|
|
||||||
private final boolean granting;
|
private final boolean granting;
|
||||||
|
|
||||||
// ~ Constructors
|
public AccessControlEntryImpl(Serializable id, Acl acl, Sid sid, Permission permission, boolean granting,
|
||||||
// ===================================================================================================
|
boolean auditSuccess, boolean auditFailure) {
|
||||||
|
|
||||||
public AccessControlEntryImpl(Serializable id, Acl acl, Sid sid,
|
|
||||||
Permission permission, boolean granting, boolean auditSuccess,
|
|
||||||
boolean auditFailure) {
|
|
||||||
Assert.notNull(acl, "Acl required");
|
Assert.notNull(acl, "Acl required");
|
||||||
Assert.notNull(sid, "Sid required");
|
Assert.notNull(sid, "Sid required");
|
||||||
Assert.notNull(permission, "Permission required");
|
Assert.notNull(permission, "Permission required");
|
||||||
@@ -61,78 +60,66 @@ public class AccessControlEntryImpl implements AccessControlEntry,
|
|||||||
this.auditFailure = auditFailure;
|
this.auditFailure = auditFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object arg0) {
|
public boolean equals(Object arg0) {
|
||||||
if (!(arg0 instanceof AccessControlEntryImpl)) {
|
if (!(arg0 instanceof AccessControlEntryImpl)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
AccessControlEntryImpl other = (AccessControlEntryImpl) arg0;
|
||||||
AccessControlEntryImpl rhs = (AccessControlEntryImpl) arg0;
|
|
||||||
|
|
||||||
if (this.acl == null) {
|
if (this.acl == null) {
|
||||||
if (rhs.getAcl() != null) {
|
if (other.getAcl() != null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Both this.acl and rhs.acl are null and thus equal
|
// Both this.acl and rhs.acl are null and thus equal
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// this.acl is non-null
|
// this.acl is non-null
|
||||||
if (rhs.getAcl() == null) {
|
if (other.getAcl() == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Both this.acl and rhs.acl are non-null, so do a comparison
|
// Both this.acl and rhs.acl are non-null, so do a comparison
|
||||||
if (this.acl.getObjectIdentity() == null) {
|
if (this.acl.getObjectIdentity() == null) {
|
||||||
if (rhs.acl.getObjectIdentity() != null) {
|
if (other.acl.getObjectIdentity() != null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Both this.acl and rhs.acl are null and thus equal
|
// Both this.acl and rhs.acl are null and thus equal
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Both this.acl.objectIdentity and rhs.acl.objectIdentity are non-null
|
// Both this.acl.objectIdentity and rhs.acl.objectIdentity are non-null
|
||||||
if (!this.acl.getObjectIdentity()
|
if (!this.acl.getObjectIdentity().equals(other.getAcl().getObjectIdentity())) {
|
||||||
.equals(rhs.getAcl().getObjectIdentity())) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.id == null) {
|
if (this.id == null) {
|
||||||
if (rhs.id != null) {
|
if (other.id != null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Both this.id and rhs.id are null and thus equal
|
// Both this.id and rhs.id are null and thus equal
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// this.id is non-null
|
// this.id is non-null
|
||||||
if (rhs.id == null) {
|
if (other.id == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Both this.id and rhs.id are non-null
|
// Both this.id and rhs.id are non-null
|
||||||
if (!this.id.equals(rhs.id)) {
|
if (!this.id.equals(other.id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ((this.auditFailure != other.isAuditFailure()) || (this.auditSuccess != other.isAuditSuccess())
|
||||||
if ((this.auditFailure != rhs.isAuditFailure())
|
|| (this.granting != other.isGranting()) || !this.permission.equals(other.getPermission())
|
||||||
|| (this.auditSuccess != rhs.isAuditSuccess())
|
|| !this.sid.equals(other.getSid())) {
|
||||||
|| (this.granting != rhs.isGranting())
|
|
||||||
|| !this.permission.equals(rhs.getPermission())
|
|
||||||
|| !this.sid.equals(rhs.getSid())) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = this.permission.hashCode();
|
int result = this.permission.hashCode();
|
||||||
result = 31 * result + (this.id != null ? this.id.hashCode() : 0);
|
result = 31 * result + ((this.id != null) ? this.id.hashCode() : 0);
|
||||||
result = 31 * result + (this.sid.hashCode());
|
result = 31 * result + (this.sid.hashCode());
|
||||||
result = 31 * result + (this.auditFailure ? 1 : 0);
|
result = 31 * result + (this.auditFailure ? 1 : 0);
|
||||||
result = 31 * result + (this.auditSuccess ? 1 : 0);
|
result = 31 * result + (this.auditSuccess ? 1 : 0);
|
||||||
@@ -142,37 +129,37 @@ public class AccessControlEntryImpl implements AccessControlEntry,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Acl getAcl() {
|
public Acl getAcl() {
|
||||||
return acl;
|
return this.acl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Serializable getId() {
|
public Serializable getId() {
|
||||||
return id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Permission getPermission() {
|
public Permission getPermission() {
|
||||||
return permission;
|
return this.permission;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Sid getSid() {
|
public Sid getSid() {
|
||||||
return sid;
|
return this.sid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAuditFailure() {
|
public boolean isAuditFailure() {
|
||||||
return auditFailure;
|
return this.auditFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAuditSuccess() {
|
public boolean isAuditSuccess() {
|
||||||
return auditSuccess;
|
return this.auditSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isGranting() {
|
public boolean isGranting() {
|
||||||
return granting;
|
return this.granting;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAuditFailure(boolean auditFailure) {
|
void setAuditFailure(boolean auditFailure) {
|
||||||
@@ -199,7 +186,7 @@ public class AccessControlEntryImpl implements AccessControlEntry,
|
|||||||
sb.append("auditSuccess: ").append(this.auditSuccess).append("; ");
|
sb.append("auditSuccess: ").append(this.auditSuccess).append("; ");
|
||||||
sb.append("auditFailure: ").append(this.auditFailure);
|
sb.append("auditFailure: ").append(this.auditFailure);
|
||||||
sb.append("]");
|
sb.append("]");
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-5
@@ -25,15 +25,13 @@ import org.springframework.security.acls.model.Acl;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public interface AclAuthorizationStrategy {
|
public interface AclAuthorizationStrategy {
|
||||||
// ~ Static fields/initializers
|
|
||||||
// =====================================================================================
|
|
||||||
|
|
||||||
int CHANGE_OWNERSHIP = 0;
|
int CHANGE_OWNERSHIP = 0;
|
||||||
|
|
||||||
int CHANGE_AUDITING = 1;
|
int CHANGE_AUDITING = 1;
|
||||||
|
|
||||||
int CHANGE_GENERAL = 2;
|
int CHANGE_GENERAL = 2;
|
||||||
|
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
void securityCheck(Acl acl, int changeType);
|
void securityCheck(Acl acl, int changeType);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-46
@@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.security.access.AccessDeniedException;
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
import org.springframework.security.acls.model.Acl;
|
import org.springframework.security.acls.model.Acl;
|
||||||
import org.springframework.security.acls.model.Sid;
|
import org.springframework.security.acls.model.Sid;
|
||||||
@@ -26,10 +30,6 @@ import org.springframework.security.core.authority.AuthorityUtils;
|
|||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default implementation of {@link AclAuthorizationStrategy}.
|
* Default implementation of {@link AclAuthorizationStrategy}.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -45,21 +45,18 @@ import java.util.Set;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
|
public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
private final GrantedAuthority gaGeneralChanges;
|
private final GrantedAuthority gaGeneralChanges;
|
||||||
private final GrantedAuthority gaModifyAuditing;
|
|
||||||
private final GrantedAuthority gaTakeOwnership;
|
|
||||||
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
|
||||||
|
|
||||||
// ~ Constructors
|
private final GrantedAuthority gaModifyAuditing;
|
||||||
// ===================================================================================================
|
|
||||||
|
private final GrantedAuthority gaTakeOwnership;
|
||||||
|
|
||||||
|
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. The only mandatory parameter relates to the system-wide
|
* Constructor. The only mandatory parameter relates to the system-wide
|
||||||
* {@link GrantedAuthority} instances that can be held to always permit ACL changes.
|
* {@link GrantedAuthority} instances that can be held to always permit ACL changes.
|
||||||
*
|
|
||||||
* @param auths the <code>GrantedAuthority</code>s that have special permissions
|
* @param auths the <code>GrantedAuthority</code>s that have special permissions
|
||||||
* (index 0 is the authority needed to change ownership, index 1 is the authority
|
* (index 0 is the authority needed to change ownership, index 1 is the authority
|
||||||
* needed to modify auditing details, index 2 is the authority needed to change other
|
* needed to modify auditing details, index 2 is the authority needed to change other
|
||||||
@@ -71,53 +68,33 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
|
|||||||
Assert.isTrue(auths != null && (auths.length == 3 || auths.length == 1),
|
Assert.isTrue(auths != null && (auths.length == 3 || auths.length == 1),
|
||||||
"One or three GrantedAuthority instances required");
|
"One or three GrantedAuthority instances required");
|
||||||
if (auths.length == 3) {
|
if (auths.length == 3) {
|
||||||
gaTakeOwnership = auths[0];
|
this.gaTakeOwnership = auths[0];
|
||||||
gaModifyAuditing = auths[1];
|
this.gaModifyAuditing = auths[1];
|
||||||
gaGeneralChanges = auths[2];
|
this.gaGeneralChanges = auths[2];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gaTakeOwnership = gaModifyAuditing = gaGeneralChanges = auths[0];
|
this.gaTakeOwnership = auths[0];
|
||||||
|
this.gaModifyAuditing = auths[0];
|
||||||
|
this.gaGeneralChanges = auths[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
@Override
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
public void securityCheck(Acl acl, int changeType) {
|
public void securityCheck(Acl acl, int changeType) {
|
||||||
if ((SecurityContextHolder.getContext() == null)
|
if ((SecurityContextHolder.getContext() == null)
|
||||||
|| (SecurityContextHolder.getContext().getAuthentication() == null)
|
|| (SecurityContextHolder.getContext().getAuthentication() == null)
|
||||||
|| !SecurityContextHolder.getContext().getAuthentication()
|
|| !SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) {
|
||||||
.isAuthenticated()) {
|
throw new AccessDeniedException("Authenticated principal required to operate with ACLs");
|
||||||
throw new AccessDeniedException(
|
|
||||||
"Authenticated principal required to operate with ACLs");
|
|
||||||
}
|
}
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
Authentication authentication = SecurityContextHolder.getContext()
|
|
||||||
.getAuthentication();
|
|
||||||
|
|
||||||
// Check if authorized by virtue of ACL ownership
|
// Check if authorized by virtue of ACL ownership
|
||||||
Sid currentUser = createCurrentUser(authentication);
|
Sid currentUser = createCurrentUser(authentication);
|
||||||
|
|
||||||
if (currentUser.equals(acl.getOwner())
|
if (currentUser.equals(acl.getOwner())
|
||||||
&& ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) {
|
&& ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not authorized by ACL ownership; try via adminstrative permissions
|
// Not authorized by ACL ownership; try via adminstrative permissions
|
||||||
GrantedAuthority requiredAuthority;
|
GrantedAuthority requiredAuthority = getRequiredAuthority(changeType);
|
||||||
|
|
||||||
if (changeType == CHANGE_AUDITING) {
|
|
||||||
requiredAuthority = this.gaModifyAuditing;
|
|
||||||
}
|
|
||||||
else if (changeType == CHANGE_GENERAL) {
|
|
||||||
requiredAuthority = this.gaGeneralChanges;
|
|
||||||
}
|
|
||||||
else if (changeType == CHANGE_OWNERSHIP) {
|
|
||||||
requiredAuthority = this.gaTakeOwnership;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new IllegalArgumentException("Unknown change type");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate this principal's authorities to determine right
|
// Iterate this principal's authorities to determine right
|
||||||
Set<String> authorities = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
|
Set<String> authorities = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
|
||||||
@@ -126,8 +103,7 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Try to get permission via ACEs within the ACL
|
// Try to get permission via ACEs within the ACL
|
||||||
List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
|
List<Sid> sids = this.sidRetrievalStrategy.getSids(authentication);
|
||||||
|
|
||||||
if (acl.isGranted(Arrays.asList(BasePermission.ADMINISTRATION), sids, false)) {
|
if (acl.isGranted(Arrays.asList(BasePermission.ADMINISTRATION), sids, false)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -136,9 +112,21 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
|
|||||||
"Principal does not have required ACL permissions to perform requested operation");
|
"Principal does not have required ACL permissions to perform requested operation");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private GrantedAuthority getRequiredAuthority(int changeType) {
|
||||||
|
if (changeType == CHANGE_AUDITING) {
|
||||||
|
return this.gaModifyAuditing;
|
||||||
|
}
|
||||||
|
if (changeType == CHANGE_GENERAL) {
|
||||||
|
return this.gaGeneralChanges;
|
||||||
|
}
|
||||||
|
if (changeType == CHANGE_OWNERSHIP) {
|
||||||
|
return this.gaTakeOwnership;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unknown change type");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a principal-like sid from the authentication information.
|
* Creates a principal-like sid from the authentication information.
|
||||||
*
|
|
||||||
* @param authentication the authentication information that can provide principal and
|
* @param authentication the authentication information that can provide principal and
|
||||||
* thus the sid's id will be dependant on the value inside
|
* thus the sid's id will be dependant on the value inside
|
||||||
* @return a sid with the ID taken from the authentication information
|
* @return a sid with the ID taken from the authentication information
|
||||||
@@ -151,4 +139,5 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
|
|||||||
Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required");
|
Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required");
|
||||||
this.sidRetrievalStrategy = sidRetrievalStrategy;
|
this.sidRetrievalStrategy = sidRetrievalStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.Permission;
|
import org.springframework.security.acls.model.Permission;
|
||||||
@@ -30,9 +31,7 @@ public abstract class AclFormattingUtils {
|
|||||||
Assert.notNull(removeBits, "Bits To Remove string required");
|
Assert.notNull(removeBits, "Bits To Remove string required");
|
||||||
Assert.isTrue(original.length() == removeBits.length(),
|
Assert.isTrue(original.length() == removeBits.length(),
|
||||||
"Original and Bits To Remove strings must be identical length");
|
"Original and Bits To Remove strings must be identical length");
|
||||||
|
|
||||||
char[] replacement = new char[original.length()];
|
char[] replacement = new char[original.length()];
|
||||||
|
|
||||||
for (int i = 0; i < original.length(); i++) {
|
for (int i = 0; i < original.length(); i++) {
|
||||||
if (removeBits.charAt(i) == Permission.RESERVED_OFF) {
|
if (removeBits.charAt(i) == Permission.RESERVED_OFF) {
|
||||||
replacement[i] = original.charAt(i);
|
replacement[i] = original.charAt(i);
|
||||||
@@ -41,7 +40,6 @@ public abstract class AclFormattingUtils {
|
|||||||
replacement[i] = Permission.RESERVED_OFF;
|
replacement[i] = Permission.RESERVED_OFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new String(replacement);
|
return new String(replacement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,9 +48,7 @@ public abstract class AclFormattingUtils {
|
|||||||
Assert.notNull(extraBits, "Extra Bits string required");
|
Assert.notNull(extraBits, "Extra Bits string required");
|
||||||
Assert.isTrue(original.length() == extraBits.length(),
|
Assert.isTrue(original.length() == extraBits.length(),
|
||||||
"Original and Extra Bits strings must be identical length");
|
"Original and Extra Bits strings must be identical length");
|
||||||
|
|
||||||
char[] replacement = new char[extraBits.length()];
|
char[] replacement = new char[extraBits.length()];
|
||||||
|
|
||||||
for (int i = 0; i < extraBits.length(); i++) {
|
for (int i = 0; i < extraBits.length(); i++) {
|
||||||
if (extraBits.charAt(i) == Permission.RESERVED_OFF) {
|
if (extraBits.charAt(i) == Permission.RESERVED_OFF) {
|
||||||
replacement[i] = original.charAt(i);
|
replacement[i] = original.charAt(i);
|
||||||
@@ -61,7 +57,6 @@ public abstract class AclFormattingUtils {
|
|||||||
replacement[i] = extraBits.charAt(i);
|
replacement[i] = extraBits.charAt(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new String(replacement);
|
return new String(replacement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,9 +65,7 @@ public abstract class AclFormattingUtils {
|
|||||||
* bit being denoted by character '*'.
|
* bit being denoted by character '*'.
|
||||||
* <p>
|
* <p>
|
||||||
* Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}.
|
* Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}.
|
||||||
*
|
|
||||||
* @param i the integer bit mask to print the active bits for
|
* @param i the integer bit mask to print the active bits for
|
||||||
*
|
|
||||||
* @return a 32-character representation of the bit mask
|
* @return a 32-character representation of the bit mask
|
||||||
*/
|
*/
|
||||||
public static String printBinary(int i) {
|
public static String printBinary(int i) {
|
||||||
@@ -84,29 +77,23 @@ public abstract class AclFormattingUtils {
|
|||||||
* bit being denoted by the passed character.
|
* bit being denoted by the passed character.
|
||||||
* <p>
|
* <p>
|
||||||
* Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}.
|
* Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}.
|
||||||
*
|
|
||||||
* @param mask the integer bit mask to print the active bits for
|
* @param mask the integer bit mask to print the active bits for
|
||||||
* @param code the character to print when an active bit is detected
|
* @param code the character to print when an active bit is detected
|
||||||
*
|
|
||||||
* @return a 32-character representation of the bit mask
|
* @return a 32-character representation of the bit mask
|
||||||
*/
|
*/
|
||||||
public static String printBinary(int mask, char code) {
|
public static String printBinary(int mask, char code) {
|
||||||
Assert.doesNotContain(Character.toString(code),
|
Assert.doesNotContain(Character.toString(code), Character.toString(Permission.RESERVED_ON),
|
||||||
Character.toString(Permission.RESERVED_ON),
|
|
||||||
() -> Permission.RESERVED_ON + " is a reserved character code");
|
() -> Permission.RESERVED_ON + " is a reserved character code");
|
||||||
Assert.doesNotContain(Character.toString(code),
|
Assert.doesNotContain(Character.toString(code), Character.toString(Permission.RESERVED_OFF),
|
||||||
Character.toString(Permission.RESERVED_OFF),
|
|
||||||
() -> Permission.RESERVED_OFF + " is a reserved character code");
|
() -> Permission.RESERVED_OFF + " is a reserved character code");
|
||||||
|
return printBinary(mask, Permission.RESERVED_ON, Permission.RESERVED_OFF).replace(Permission.RESERVED_ON, code);
|
||||||
return printBinary(mask, Permission.RESERVED_ON, Permission.RESERVED_OFF)
|
|
||||||
.replace(Permission.RESERVED_ON, code);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String printBinary(int i, char on, char off) {
|
private static String printBinary(int i, char on, char off) {
|
||||||
String s = Integer.toBinaryString(i);
|
String s = Integer.toBinaryString(i);
|
||||||
String pattern = Permission.THIRTY_TWO_RESERVED_OFF;
|
String pattern = Permission.THIRTY_TWO_RESERVED_OFF;
|
||||||
String temp2 = pattern.substring(0, pattern.length() - s.length()) + s;
|
String temp2 = pattern.substring(0, pattern.length() - s.length()) + s;
|
||||||
|
|
||||||
return temp2.replace('0', off).replace('1', on);
|
return temp2.replace('0', off).replace('1', on);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -31,6 +32,7 @@ import org.springframework.security.acls.model.PermissionGrantingStrategy;
|
|||||||
import org.springframework.security.acls.model.Sid;
|
import org.springframework.security.acls.model.Sid;
|
||||||
import org.springframework.security.acls.model.UnloadedSidException;
|
import org.springframework.security.acls.model.UnloadedSidException;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base implementation of <code>Acl</code>.
|
* Base implementation of <code>Acl</code>.
|
||||||
@@ -38,35 +40,38 @@ import org.springframework.util.Assert;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
private Acl parentAcl;
|
private Acl parentAcl;
|
||||||
private transient AclAuthorizationStrategy aclAuthorizationStrategy;
|
|
||||||
private transient PermissionGrantingStrategy permissionGrantingStrategy;
|
|
||||||
private final List<AccessControlEntry> aces = new ArrayList<>();
|
|
||||||
private ObjectIdentity objectIdentity;
|
|
||||||
private Serializable id;
|
|
||||||
private Sid owner; // OwnershipAcl
|
|
||||||
private List<Sid> loadedSids = null; // includes all SIDs the WHERE clause covered,
|
|
||||||
// even if there was no ACE for a SID
|
|
||||||
private boolean entriesInheriting = true;
|
|
||||||
|
|
||||||
// ~ Constructors
|
private transient AclAuthorizationStrategy aclAuthorizationStrategy;
|
||||||
// ===================================================================================================
|
|
||||||
|
private transient PermissionGrantingStrategy permissionGrantingStrategy;
|
||||||
|
|
||||||
|
private final List<AccessControlEntry> aces = new ArrayList<>();
|
||||||
|
|
||||||
|
private ObjectIdentity objectIdentity;
|
||||||
|
|
||||||
|
private Serializable id;
|
||||||
|
|
||||||
|
// OwnershipAcl
|
||||||
|
private Sid owner;
|
||||||
|
|
||||||
|
// includes all SIDs the WHERE clause covered, even if there was no ACE for a SID
|
||||||
|
private List<Sid> loadedSids = null;
|
||||||
|
|
||||||
|
private boolean entriesInheriting = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minimal constructor, which should be used
|
* Minimal constructor, which should be used
|
||||||
* {@link org.springframework.security.acls.model.MutableAclService#createAcl(ObjectIdentity)}
|
* {@link org.springframework.security.acls.model.MutableAclService#createAcl(ObjectIdentity)}
|
||||||
* .
|
* .
|
||||||
*
|
|
||||||
* @param objectIdentity the object identity this ACL relates to (required)
|
* @param objectIdentity the object identity this ACL relates to (required)
|
||||||
* @param id the primary key assigned to this ACL (required)
|
* @param id the primary key assigned to this ACL (required)
|
||||||
* @param aclAuthorizationStrategy authorization strategy (required)
|
* @param aclAuthorizationStrategy authorization strategy (required)
|
||||||
* @param auditLogger audit logger (required)
|
* @param auditLogger audit logger (required)
|
||||||
*/
|
*/
|
||||||
public AclImpl(ObjectIdentity objectIdentity, Serializable id,
|
public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy,
|
||||||
AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) {
|
AuditLogger auditLogger) {
|
||||||
Assert.notNull(objectIdentity, "Object Identity required");
|
Assert.notNull(objectIdentity, "Object Identity required");
|
||||||
Assert.notNull(id, "Id required");
|
Assert.notNull(id, "Id required");
|
||||||
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
|
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
|
||||||
@@ -74,14 +79,12 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
this.objectIdentity = objectIdentity;
|
this.objectIdentity = objectIdentity;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
|
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
|
||||||
this.permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(
|
this.permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(auditLogger);
|
||||||
auditLogger);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Full constructor, which should be used by persistence tools that do not provide
|
* Full constructor, which should be used by persistence tools that do not provide
|
||||||
* field-level access features.
|
* field-level access features.
|
||||||
*
|
|
||||||
* @param objectIdentity the object identity this ACL relates to
|
* @param objectIdentity the object identity this ACL relates to
|
||||||
* @param id the primary key assigned to this ACL
|
* @param id the primary key assigned to this ACL
|
||||||
* @param aclAuthorizationStrategy authorization strategy
|
* @param aclAuthorizationStrategy authorization strategy
|
||||||
@@ -93,15 +96,13 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
* @param entriesInheriting if ACEs from the parent should inherit into this ACL
|
* @param entriesInheriting if ACEs from the parent should inherit into this ACL
|
||||||
* @param owner the owner (required)
|
* @param owner the owner (required)
|
||||||
*/
|
*/
|
||||||
public AclImpl(ObjectIdentity objectIdentity, Serializable id,
|
public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy,
|
||||||
AclAuthorizationStrategy aclAuthorizationStrategy,
|
PermissionGrantingStrategy grantingStrategy, Acl parentAcl, List<Sid> loadedSids, boolean entriesInheriting,
|
||||||
PermissionGrantingStrategy grantingStrategy, Acl parentAcl,
|
Sid owner) {
|
||||||
List<Sid> loadedSids, boolean entriesInheriting, Sid owner) {
|
|
||||||
Assert.notNull(objectIdentity, "Object Identity required");
|
Assert.notNull(objectIdentity, "Object Identity required");
|
||||||
Assert.notNull(id, "Id required");
|
Assert.notNull(id, "Id required");
|
||||||
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
|
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
|
||||||
Assert.notNull(owner, "Owner required");
|
Assert.notNull(owner, "Owner required");
|
||||||
|
|
||||||
this.objectIdentity = objectIdentity;
|
this.objectIdentity = objectIdentity;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
|
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
|
||||||
@@ -120,16 +121,11 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
private AclImpl() {
|
private AclImpl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteAce(int aceIndex) throws NotFoundException {
|
public void deleteAce(int aceIndex) throws NotFoundException {
|
||||||
aclAuthorizationStrategy.securityCheck(this,
|
this.aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||||
AclAuthorizationStrategy.CHANGE_GENERAL);
|
|
||||||
verifyAceIndexExists(aceIndex);
|
verifyAceIndexExists(aceIndex);
|
||||||
|
synchronized (this.aces) {
|
||||||
synchronized (aces) {
|
|
||||||
this.aces.remove(aceIndex);
|
this.aces.remove(aceIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,32 +135,26 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
throw new NotFoundException("aceIndex must be greater than or equal to zero");
|
throw new NotFoundException("aceIndex must be greater than or equal to zero");
|
||||||
}
|
}
|
||||||
if (aceIndex >= this.aces.size()) {
|
if (aceIndex >= this.aces.size()) {
|
||||||
throw new NotFoundException(
|
throw new NotFoundException("aceIndex must refer to an index of the AccessControlEntry list. "
|
||||||
"aceIndex must refer to an index of the AccessControlEntry list. "
|
+ "List size is " + this.aces.size() + ", index was " + aceIndex);
|
||||||
+ "List size is " + aces.size() + ", index was " + aceIndex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void insertAce(int atIndexLocation, Permission permission, Sid sid,
|
public void insertAce(int atIndexLocation, Permission permission, Sid sid, boolean granting)
|
||||||
boolean granting) throws NotFoundException {
|
throws NotFoundException {
|
||||||
aclAuthorizationStrategy.securityCheck(this,
|
this.aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||||
AclAuthorizationStrategy.CHANGE_GENERAL);
|
|
||||||
Assert.notNull(permission, "Permission required");
|
Assert.notNull(permission, "Permission required");
|
||||||
Assert.notNull(sid, "Sid required");
|
Assert.notNull(sid, "Sid required");
|
||||||
if (atIndexLocation < 0) {
|
if (atIndexLocation < 0) {
|
||||||
throw new NotFoundException(
|
throw new NotFoundException("atIndexLocation must be greater than or equal to zero");
|
||||||
"atIndexLocation must be greater than or equal to zero");
|
|
||||||
}
|
}
|
||||||
if (atIndexLocation > this.aces.size()) {
|
if (atIndexLocation > this.aces.size()) {
|
||||||
throw new NotFoundException(
|
throw new NotFoundException(
|
||||||
"atIndexLocation must be less than or equal to the size of the AccessControlEntry collection");
|
"atIndexLocation must be less than or equal to the size of the AccessControlEntry collection");
|
||||||
}
|
}
|
||||||
|
AccessControlEntryImpl ace = new AccessControlEntryImpl(null, this, sid, permission, granting, false, false);
|
||||||
AccessControlEntryImpl ace = new AccessControlEntryImpl(null, this, sid,
|
synchronized (this.aces) {
|
||||||
permission, granting, false, false);
|
|
||||||
|
|
||||||
synchronized (aces) {
|
|
||||||
this.aces.add(atIndexLocation, ace);
|
this.aces.add(atIndexLocation, ace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,7 +163,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
public List<AccessControlEntry> getEntries() {
|
public List<AccessControlEntry> getEntries() {
|
||||||
// Can safely return AccessControlEntry directly, as they're immutable outside the
|
// Can safely return AccessControlEntry directly, as they're immutable outside the
|
||||||
// ACL package
|
// ACL package
|
||||||
return new ArrayList<>(aces);
|
return new ArrayList<>(this.aces);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -183,33 +173,29 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ObjectIdentity getObjectIdentity() {
|
public ObjectIdentity getObjectIdentity() {
|
||||||
return objectIdentity;
|
return this.objectIdentity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEntriesInheriting() {
|
public boolean isEntriesInheriting() {
|
||||||
return entriesInheriting;
|
return this.entriesInheriting;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delegates to the {@link PermissionGrantingStrategy}.
|
* Delegates to the {@link PermissionGrantingStrategy}.
|
||||||
*
|
|
||||||
* @throws UnloadedSidException if the passed SIDs are unknown to this ACL because the
|
* @throws UnloadedSidException if the passed SIDs are unknown to this ACL because the
|
||||||
* ACL was only loaded for a subset of SIDs
|
* ACL was only loaded for a subset of SIDs
|
||||||
* @see DefaultPermissionGrantingStrategy
|
* @see DefaultPermissionGrantingStrategy
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isGranted(List<Permission> permission, List<Sid> sids,
|
public boolean isGranted(List<Permission> permission, List<Sid> sids, boolean administrativeMode)
|
||||||
boolean administrativeMode) throws NotFoundException, UnloadedSidException {
|
throws NotFoundException, UnloadedSidException {
|
||||||
Assert.notEmpty(permission, "Permissions required");
|
Assert.notEmpty(permission, "Permissions required");
|
||||||
Assert.notEmpty(sids, "SIDs required");
|
Assert.notEmpty(sids, "SIDs required");
|
||||||
|
|
||||||
if (!this.isSidLoaded(sids)) {
|
if (!this.isSidLoaded(sids)) {
|
||||||
throw new UnloadedSidException("ACL was not loaded for one or more SID");
|
throw new UnloadedSidException("ACL was not loaded for one or more SID");
|
||||||
}
|
}
|
||||||
|
return this.permissionGrantingStrategy.isGranted(this, permission, sids, administrativeMode);
|
||||||
return permissionGrantingStrategy.isGranted(this, permission, sids,
|
|
||||||
administrativeMode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -223,16 +209,13 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
// This ACL applies to a SID subset only. Iterate to check it applies.
|
// This ACL applies to a SID subset only. Iterate to check it applies.
|
||||||
for (Sid sid : sids) {
|
for (Sid sid : sids) {
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
|
for (Sid loadedSid : this.loadedSids) {
|
||||||
for (Sid loadedSid : loadedSids) {
|
|
||||||
if (sid.equals(loadedSid)) {
|
if (sid.equals(loadedSid)) {
|
||||||
// this SID is OK
|
// this SID is OK
|
||||||
found = true;
|
found = true;
|
||||||
|
|
||||||
break; // out of loadedSids for loop
|
break; // out of loadedSids for loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -243,15 +226,13 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setEntriesInheriting(boolean entriesInheriting) {
|
public void setEntriesInheriting(boolean entriesInheriting) {
|
||||||
aclAuthorizationStrategy.securityCheck(this,
|
this.aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||||
AclAuthorizationStrategy.CHANGE_GENERAL);
|
|
||||||
this.entriesInheriting = entriesInheriting;
|
this.entriesInheriting = entriesInheriting;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setOwner(Sid newOwner) {
|
public void setOwner(Sid newOwner) {
|
||||||
aclAuthorizationStrategy.securityCheck(this,
|
this.aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
||||||
AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
|
||||||
Assert.notNull(newOwner, "Owner required");
|
Assert.notNull(newOwner, "Owner required");
|
||||||
this.owner = newOwner;
|
this.owner = newOwner;
|
||||||
}
|
}
|
||||||
@@ -263,38 +244,32 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setParent(Acl newParent) {
|
public void setParent(Acl newParent) {
|
||||||
aclAuthorizationStrategy.securityCheck(this,
|
this.aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||||
AclAuthorizationStrategy.CHANGE_GENERAL);
|
Assert.isTrue(newParent == null || !newParent.equals(this), "Cannot be the parent of yourself");
|
||||||
Assert.isTrue(newParent == null || !newParent.equals(this),
|
|
||||||
"Cannot be the parent of yourself");
|
|
||||||
this.parentAcl = newParent;
|
this.parentAcl = newParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Acl getParentAcl() {
|
public Acl getParentAcl() {
|
||||||
return parentAcl;
|
return this.parentAcl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateAce(int aceIndex, Permission permission) throws NotFoundException {
|
public void updateAce(int aceIndex, Permission permission) throws NotFoundException {
|
||||||
aclAuthorizationStrategy.securityCheck(this,
|
this.aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||||
AclAuthorizationStrategy.CHANGE_GENERAL);
|
|
||||||
verifyAceIndexExists(aceIndex);
|
verifyAceIndexExists(aceIndex);
|
||||||
|
synchronized (this.aces) {
|
||||||
synchronized (aces) {
|
AccessControlEntryImpl ace = (AccessControlEntryImpl) this.aces.get(aceIndex);
|
||||||
AccessControlEntryImpl ace = (AccessControlEntryImpl) aces.get(aceIndex);
|
|
||||||
ace.setPermission(permission);
|
ace.setPermission(permission);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure) {
|
public void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure) {
|
||||||
aclAuthorizationStrategy.securityCheck(this,
|
this.aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_AUDITING);
|
||||||
AclAuthorizationStrategy.CHANGE_AUDITING);
|
|
||||||
verifyAceIndexExists(aceIndex);
|
verifyAceIndexExists(aceIndex);
|
||||||
|
synchronized (this.aces) {
|
||||||
synchronized (aces) {
|
AccessControlEntryImpl ace = (AccessControlEntryImpl) this.aces.get(aceIndex);
|
||||||
AccessControlEntryImpl ace = (AccessControlEntryImpl) aces.get(aceIndex);
|
|
||||||
ace.setAuditSuccess(auditSuccess);
|
ace.setAuditSuccess(auditSuccess);
|
||||||
ace.setAuditFailure(auditFailure);
|
ace.setAuditFailure(auditFailure);
|
||||||
}
|
}
|
||||||
@@ -302,57 +277,35 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (obj instanceof AclImpl) {
|
if (obj == this) {
|
||||||
AclImpl rhs = (AclImpl) obj;
|
return true;
|
||||||
if (this.aces.equals(rhs.aces)) {
|
|
||||||
if ((this.parentAcl == null && rhs.parentAcl == null)
|
|
||||||
|| (this.parentAcl != null && this.parentAcl
|
|
||||||
.equals(rhs.parentAcl))) {
|
|
||||||
if ((this.objectIdentity == null && rhs.objectIdentity == null)
|
|
||||||
|| (this.objectIdentity != null && this.objectIdentity
|
|
||||||
.equals(rhs.objectIdentity))) {
|
|
||||||
if ((this.id == null && rhs.id == null)
|
|
||||||
|| (this.id != null && this.id.equals(rhs.id))) {
|
|
||||||
if ((this.owner == null && rhs.owner == null)
|
|
||||||
|| (this.owner != null && this.owner
|
|
||||||
.equals(rhs.owner))) {
|
|
||||||
if (this.entriesInheriting == rhs.entriesInheriting) {
|
|
||||||
if ((this.loadedSids == null && rhs.loadedSids == null)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (this.loadedSids != null
|
|
||||||
&& (this.loadedSids.size() == rhs.loadedSids
|
|
||||||
.size())) {
|
|
||||||
for (int i = 0; i < this.loadedSids.size(); i++) {
|
|
||||||
if (!this.loadedSids.get(i).equals(
|
|
||||||
rhs.loadedSids.get(i))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
if (obj == null || !(obj instanceof AclImpl)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
AclImpl other = (AclImpl) obj;
|
||||||
|
boolean result = true;
|
||||||
|
result = result && this.aces.equals(other.aces);
|
||||||
|
result = result && ObjectUtils.nullSafeEquals(this.parentAcl, other.parentAcl);
|
||||||
|
result = result && ObjectUtils.nullSafeEquals(this.objectIdentity, other.objectIdentity);
|
||||||
|
result = result && ObjectUtils.nullSafeEquals(this.id, other.id);
|
||||||
|
result = result && ObjectUtils.nullSafeEquals(this.owner, other.owner);
|
||||||
|
result = result && this.entriesInheriting == other.entriesInheriting;
|
||||||
|
result = result && ObjectUtils.nullSafeEquals(this.loadedSids, other.loadedSids);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = this.parentAcl != null ? this.parentAcl.hashCode() : 0;
|
int result = (this.parentAcl != null) ? this.parentAcl.hashCode() : 0;
|
||||||
result = 31 * result + this.aclAuthorizationStrategy.hashCode();
|
result = 31 * result + this.aclAuthorizationStrategy.hashCode();
|
||||||
result = 31 * result + (this.permissionGrantingStrategy != null ?
|
result = 31 * result
|
||||||
this.permissionGrantingStrategy.hashCode() :
|
+ ((this.permissionGrantingStrategy != null) ? this.permissionGrantingStrategy.hashCode() : 0);
|
||||||
0);
|
result = 31 * result + ((this.aces != null) ? this.aces.hashCode() : 0);
|
||||||
result = 31 * result + (this.aces != null ? this.aces.hashCode() : 0);
|
|
||||||
result = 31 * result + this.objectIdentity.hashCode();
|
result = 31 * result + this.objectIdentity.hashCode();
|
||||||
result = 31 * result + this.id.hashCode();
|
result = 31 * result + this.id.hashCode();
|
||||||
result = 31 * result + (this.owner != null ? this.owner.hashCode() : 0);
|
result = 31 * result + ((this.owner != null) ? this.owner.hashCode() : 0);
|
||||||
result = 31 * result + (this.loadedSids != null ? this.loadedSids.hashCode() : 0);
|
result = 31 * result + ((this.loadedSids != null) ? this.loadedSids.hashCode() : 0);
|
||||||
result = 31 * result + (this.entriesInheriting ? 1 : 0);
|
result = 31 * result + (this.entriesInheriting ? 1 : 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -364,33 +317,23 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
sb.append("id: ").append(this.id).append("; ");
|
sb.append("id: ").append(this.id).append("; ");
|
||||||
sb.append("objectIdentity: ").append(this.objectIdentity).append("; ");
|
sb.append("objectIdentity: ").append(this.objectIdentity).append("; ");
|
||||||
sb.append("owner: ").append(this.owner).append("; ");
|
sb.append("owner: ").append(this.owner).append("; ");
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
for (AccessControlEntry ace : this.aces) {
|
||||||
for (AccessControlEntry ace : aces) {
|
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
if (count == 1) {
|
if (count == 1) {
|
||||||
sb.append("\n");
|
sb.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.append(ace).append("\n");
|
sb.append(ace).append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
sb.append("no ACEs; ");
|
sb.append("no ACEs; ");
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.append("inheriting: ").append(this.entriesInheriting).append("; ");
|
sb.append("inheriting: ").append(this.entriesInheriting).append("; ");
|
||||||
sb.append("parent: ").append(
|
sb.append("parent: ").append((this.parentAcl == null) ? "Null" : this.parentAcl.getObjectIdentity().toString());
|
||||||
(this.parentAcl == null) ? "Null" : this.parentAcl.getObjectIdentity()
|
|
||||||
.toString());
|
|
||||||
sb.append("; ");
|
sb.append("; ");
|
||||||
sb.append("aclAuthorizationStrategy: ").append(this.aclAuthorizationStrategy)
|
sb.append("aclAuthorizationStrategy: ").append(this.aclAuthorizationStrategy).append("; ");
|
||||||
.append("; ");
|
|
||||||
sb.append("permissionGrantingStrategy: ").append(this.permissionGrantingStrategy);
|
sb.append("permissionGrantingStrategy: ").append(this.permissionGrantingStrategy);
|
||||||
sb.append("]");
|
sb.append("]");
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.AccessControlEntry;
|
import org.springframework.security.acls.model.AccessControlEntry;
|
||||||
@@ -21,11 +22,9 @@ import org.springframework.security.acls.model.AccessControlEntry;
|
|||||||
* Used by <code>AclImpl</code> to log audit events.
|
* Used by <code>AclImpl</code> to log audit events.
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface AuditLogger {
|
public interface AuditLogger {
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
void logIfNeeded(boolean granted, AccessControlEntry ace);
|
void logIfNeeded(boolean granted, AccessControlEntry ace);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.Permission;
|
import org.springframework.security.acls.model.Permission;
|
||||||
@@ -28,10 +29,15 @@ import org.springframework.security.acls.model.Permission;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class BasePermission extends AbstractPermission {
|
public class BasePermission extends AbstractPermission {
|
||||||
|
|
||||||
public static final Permission READ = new BasePermission(1 << 0, 'R'); // 1
|
public static final Permission READ = new BasePermission(1 << 0, 'R'); // 1
|
||||||
|
|
||||||
public static final Permission WRITE = new BasePermission(1 << 1, 'W'); // 2
|
public static final Permission WRITE = new BasePermission(1 << 1, 'W'); // 2
|
||||||
|
|
||||||
public static final Permission CREATE = new BasePermission(1 << 2, 'C'); // 4
|
public static final Permission CREATE = new BasePermission(1 << 2, 'C'); // 4
|
||||||
|
|
||||||
public static final Permission DELETE = new BasePermission(1 << 3, 'D'); // 8
|
public static final Permission DELETE = new BasePermission(1 << 3, 'D'); // 8
|
||||||
|
|
||||||
public static final Permission ADMINISTRATION = new BasePermission(1 << 4, 'A'); // 16
|
public static final Permission ADMINISTRATION = new BasePermission(1 << 4, 'A'); // 16
|
||||||
|
|
||||||
protected BasePermission(int mask) {
|
protected BasePermission(int mask) {
|
||||||
@@ -41,4 +47,5 @@ public class BasePermission extends AbstractPermission {
|
|||||||
protected BasePermission(int mask, char code) {
|
protected BasePermission(int mask, char code) {
|
||||||
super(mask, code);
|
super(mask, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,11 +13,11 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.AccessControlEntry;
|
import org.springframework.security.acls.model.AccessControlEntry;
|
||||||
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,15 +26,12 @@ import org.springframework.util.Assert;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class ConsoleAuditLogger implements AuditLogger {
|
public class ConsoleAuditLogger implements AuditLogger {
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
|
@Override
|
||||||
public void logIfNeeded(boolean granted, AccessControlEntry ace) {
|
public void logIfNeeded(boolean granted, AccessControlEntry ace) {
|
||||||
Assert.notNull(ace, "AccessControlEntry required");
|
Assert.notNull(ace, "AccessControlEntry required");
|
||||||
|
|
||||||
if (ace instanceof AuditableAccessControlEntry) {
|
if (ace instanceof AuditableAccessControlEntry) {
|
||||||
AuditableAccessControlEntry auditableAce = (AuditableAccessControlEntry) ace;
|
AuditableAccessControlEntry auditableAce = (AuditableAccessControlEntry) ace;
|
||||||
|
|
||||||
if (granted && auditableAce.isAuditSuccess()) {
|
if (granted && auditableAce.isAuditSuccess()) {
|
||||||
System.out.println("GRANTED due to ACE: " + ace);
|
System.out.println("GRANTED due to ACE: " + ace);
|
||||||
}
|
}
|
||||||
@@ -43,4 +40,5 @@ public class ConsoleAuditLogger implements AuditLogger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-7
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.Permission;
|
import org.springframework.security.acls.model.Permission;
|
||||||
@@ -37,27 +38,23 @@ public class CumulativePermission extends AbstractPermission {
|
|||||||
|
|
||||||
public CumulativePermission clear(Permission permission) {
|
public CumulativePermission clear(Permission permission) {
|
||||||
this.mask &= ~permission.getMask();
|
this.mask &= ~permission.getMask();
|
||||||
this.pattern = AclFormattingUtils.demergePatterns(this.pattern,
|
this.pattern = AclFormattingUtils.demergePatterns(this.pattern, permission.getPattern());
|
||||||
permission.getPattern());
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CumulativePermission clear() {
|
public CumulativePermission clear() {
|
||||||
this.mask = 0;
|
this.mask = 0;
|
||||||
this.pattern = THIRTY_TWO_RESERVED_OFF;
|
this.pattern = THIRTY_TWO_RESERVED_OFF;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CumulativePermission set(Permission permission) {
|
public CumulativePermission set(Permission permission) {
|
||||||
this.mask |= permission.getMask();
|
this.mask |= permission.getMask();
|
||||||
this.pattern = AclFormattingUtils.mergePatterns(this.pattern,
|
this.pattern = AclFormattingUtils.mergePatterns(this.pattern, permission.getPattern());
|
||||||
permission.getPattern());
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getPattern() {
|
public String getPattern() {
|
||||||
return this.pattern;
|
return this.pattern;
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-32
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
@@ -38,7 +39,9 @@ import org.springframework.util.Assert;
|
|||||||
* @since 2.0.3
|
* @since 2.0.3
|
||||||
*/
|
*/
|
||||||
public class DefaultPermissionFactory implements PermissionFactory {
|
public class DefaultPermissionFactory implements PermissionFactory {
|
||||||
|
|
||||||
private final Map<Integer, Permission> registeredPermissionsByInteger = new HashMap<>();
|
private final Map<Integer, Permission> registeredPermissionsByInteger = new HashMap<>();
|
||||||
|
|
||||||
private final Map<String, Permission> registeredPermissionsByName = new HashMap<>();
|
private final Map<String, Permission> registeredPermissionsByName = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,7 +60,6 @@ public class DefaultPermissionFactory implements PermissionFactory {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a map of named <tt>Permission</tt> instances.
|
* Registers a map of named <tt>Permission</tt> instances.
|
||||||
*
|
|
||||||
* @param namedPermissions the map of <tt>Permission</tt>s, keyed by name.
|
* @param namedPermissions the map of <tt>Permission</tt>s, keyed by name.
|
||||||
*/
|
*/
|
||||||
public DefaultPermissionFactory(Map<String, ? extends Permission> namedPermissions) {
|
public DefaultPermissionFactory(Map<String, ? extends Permission> namedPermissions) {
|
||||||
@@ -71,27 +73,22 @@ public class DefaultPermissionFactory implements PermissionFactory {
|
|||||||
* <p>
|
* <p>
|
||||||
* These permissions will be registered under the name of the field. See
|
* These permissions will be registered under the name of the field. See
|
||||||
* {@link BasePermission} for an example.
|
* {@link BasePermission} for an example.
|
||||||
*
|
|
||||||
* @param clazz a {@link Permission} class with public static fields to register
|
* @param clazz a {@link Permission} class with public static fields to register
|
||||||
*/
|
*/
|
||||||
protected void registerPublicPermissions(Class<? extends Permission> clazz) {
|
protected void registerPublicPermissions(Class<? extends Permission> clazz) {
|
||||||
Assert.notNull(clazz, "Class required");
|
Assert.notNull(clazz, "Class required");
|
||||||
|
|
||||||
Field[] fields = clazz.getFields();
|
Field[] fields = clazz.getFields();
|
||||||
|
|
||||||
for (Field field : fields) {
|
for (Field field : fields) {
|
||||||
try {
|
try {
|
||||||
Object fieldValue = field.get(null);
|
Object fieldValue = field.get(null);
|
||||||
|
|
||||||
if (Permission.class.isAssignableFrom(fieldValue.getClass())) {
|
if (Permission.class.isAssignableFrom(fieldValue.getClass())) {
|
||||||
// Found a Permission static field
|
// Found a Permission static field
|
||||||
Permission perm = (Permission) fieldValue;
|
Permission perm = (Permission) fieldValue;
|
||||||
String permissionName = field.getName();
|
String permissionName = field.getName();
|
||||||
|
|
||||||
registerPermission(perm, permissionName);
|
registerPermission(perm, permissionName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ignore) {
|
catch (Exception ex) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,68 +96,57 @@ public class DefaultPermissionFactory implements PermissionFactory {
|
|||||||
protected void registerPermission(Permission perm, String permissionName) {
|
protected void registerPermission(Permission perm, String permissionName) {
|
||||||
Assert.notNull(perm, "Permission required");
|
Assert.notNull(perm, "Permission required");
|
||||||
Assert.hasText(permissionName, "Permission name required");
|
Assert.hasText(permissionName, "Permission name required");
|
||||||
|
|
||||||
Integer mask = perm.getMask();
|
Integer mask = perm.getMask();
|
||||||
|
|
||||||
// Ensure no existing Permission uses this integer or code
|
// Ensure no existing Permission uses this integer or code
|
||||||
Assert.isTrue(!registeredPermissionsByInteger.containsKey(mask),
|
Assert.isTrue(!this.registeredPermissionsByInteger.containsKey(mask),
|
||||||
() -> "An existing Permission already provides mask " + mask);
|
() -> "An existing Permission already provides mask " + mask);
|
||||||
Assert.isTrue(!registeredPermissionsByName.containsKey(permissionName),
|
Assert.isTrue(!this.registeredPermissionsByName.containsKey(permissionName),
|
||||||
() -> "An existing Permission already provides name '" + permissionName + "'");
|
() -> "An existing Permission already provides name '" + permissionName + "'");
|
||||||
|
|
||||||
// Register the new Permission
|
// Register the new Permission
|
||||||
registeredPermissionsByInteger.put(mask, perm);
|
this.registeredPermissionsByInteger.put(mask, perm);
|
||||||
registeredPermissionsByName.put(permissionName, perm);
|
this.registeredPermissionsByName.put(permissionName, perm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Permission buildFromMask(int mask) {
|
public Permission buildFromMask(int mask) {
|
||||||
if (registeredPermissionsByInteger.containsKey(mask)) {
|
if (this.registeredPermissionsByInteger.containsKey(mask)) {
|
||||||
// The requested mask has an exact match against a statically-defined
|
// The requested mask has an exact match against a statically-defined
|
||||||
// Permission, so return it
|
// Permission, so return it
|
||||||
return registeredPermissionsByInteger.get(mask);
|
return this.registeredPermissionsByInteger.get(mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
// To get this far, we have to use a CumulativePermission
|
// To get this far, we have to use a CumulativePermission
|
||||||
CumulativePermission permission = new CumulativePermission();
|
CumulativePermission permission = new CumulativePermission();
|
||||||
|
|
||||||
for (int i = 0; i < 32; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
int permissionToCheck = 1 << i;
|
int permissionToCheck = 1 << i;
|
||||||
|
|
||||||
if ((mask & permissionToCheck) == permissionToCheck) {
|
if ((mask & permissionToCheck) == permissionToCheck) {
|
||||||
Permission p = registeredPermissionsByInteger.get(permissionToCheck);
|
Permission p = this.registeredPermissionsByInteger.get(permissionToCheck);
|
||||||
|
Assert.state(p != null,
|
||||||
if (p == null) {
|
() -> "Mask '" + permissionToCheck + "' does not have a corresponding static Permission");
|
||||||
throw new IllegalStateException("Mask '" + permissionToCheck
|
|
||||||
+ "' does not have a corresponding static Permission");
|
|
||||||
}
|
|
||||||
permission.set(p);
|
permission.set(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return permission;
|
return permission;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Permission buildFromName(String name) {
|
public Permission buildFromName(String name) {
|
||||||
Permission p = registeredPermissionsByName.get(name);
|
Permission p = this.registeredPermissionsByName.get(name);
|
||||||
|
Assert.notNull(p, "Unknown permission '" + name + "'");
|
||||||
if (p == null) {
|
|
||||||
throw new IllegalArgumentException("Unknown permission '" + name + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public List<Permission> buildFromNames(List<String> names) {
|
public List<Permission> buildFromNames(List<String> names) {
|
||||||
if ((names == null) || (names.size() == 0)) {
|
if ((names == null) || (names.size() == 0)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Permission> permissions = new ArrayList<>(names.size());
|
List<Permission> permissions = new ArrayList<>(names.size());
|
||||||
|
|
||||||
for (String name : names) {
|
for (String name : names) {
|
||||||
permissions.add(buildFromName(name));
|
permissions.add(buildFromName(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
return permissions;
|
return permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
-30
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -61,42 +62,33 @@ public class DefaultPermissionGrantingStrategy implements PermissionGrantingStra
|
|||||||
* decide how to handle the permission check. Similarly, if any of the SID arguments
|
* decide how to handle the permission check. Similarly, if any of the SID arguments
|
||||||
* presented to the method were not loaded by the ACL,
|
* presented to the method were not loaded by the ACL,
|
||||||
* <code>UnloadedSidException</code> will be thrown.
|
* <code>UnloadedSidException</code> will be thrown.
|
||||||
*
|
|
||||||
* @param permission the exact permissions to scan for (order is important)
|
* @param permission the exact permissions to scan for (order is important)
|
||||||
* @param sids the exact SIDs to scan for (order is important)
|
* @param sids the exact SIDs to scan for (order is important)
|
||||||
* @param administrativeMode if <code>true</code> denotes the query is for
|
* @param administrativeMode if <code>true</code> denotes the query is for
|
||||||
* administrative purposes and no auditing will be undertaken
|
* administrative purposes and no auditing will be undertaken
|
||||||
*
|
|
||||||
* @return <code>true</code> if one of the permissions has been granted,
|
* @return <code>true</code> if one of the permissions has been granted,
|
||||||
* <code>false</code> if one of the permissions has been specifically revoked
|
* <code>false</code> if one of the permissions has been specifically revoked
|
||||||
*
|
|
||||||
* @throws NotFoundException if an exact ACE for one of the permission bit masks and
|
* @throws NotFoundException if an exact ACE for one of the permission bit masks and
|
||||||
* SID combination could not be found
|
* SID combination could not be found
|
||||||
*/
|
*/
|
||||||
public boolean isGranted(Acl acl, List<Permission> permission, List<Sid> sids,
|
@Override
|
||||||
boolean administrativeMode) throws NotFoundException {
|
public boolean isGranted(Acl acl, List<Permission> permission, List<Sid> sids, boolean administrativeMode)
|
||||||
|
throws NotFoundException {
|
||||||
final List<AccessControlEntry> aces = acl.getEntries();
|
List<AccessControlEntry> aces = acl.getEntries();
|
||||||
|
|
||||||
AccessControlEntry firstRejection = null;
|
AccessControlEntry firstRejection = null;
|
||||||
|
|
||||||
for (Permission p : permission) {
|
for (Permission p : permission) {
|
||||||
for (Sid sid : sids) {
|
for (Sid sid : sids) {
|
||||||
// Attempt to find exact match for this permission mask and SID
|
// Attempt to find exact match for this permission mask and SID
|
||||||
boolean scanNextSid = true;
|
boolean scanNextSid = true;
|
||||||
|
|
||||||
for (AccessControlEntry ace : aces) {
|
for (AccessControlEntry ace : aces) {
|
||||||
|
if (isGranted(ace, p) && ace.getSid().equals(sid)) {
|
||||||
if (isGranted(ace, p)
|
|
||||||
&& ace.getSid().equals(sid)) {
|
|
||||||
// Found a matching ACE, so its authorization decision will
|
// Found a matching ACE, so its authorization decision will
|
||||||
// prevail
|
// prevail
|
||||||
if (ace.isGranting()) {
|
if (ace.isGranting()) {
|
||||||
// Success
|
// Success
|
||||||
if (!administrativeMode) {
|
if (!administrativeMode) {
|
||||||
auditLogger.logIfNeeded(true, ace);
|
this.auditLogger.logIfNeeded(true, ace);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,13 +99,11 @@ public class DefaultPermissionGrantingStrategy implements PermissionGrantingStra
|
|||||||
// Store first rejection for auditing reasons
|
// Store first rejection for auditing reasons
|
||||||
firstRejection = ace;
|
firstRejection = ace;
|
||||||
}
|
}
|
||||||
|
|
||||||
scanNextSid = false; // helps break the loop
|
scanNextSid = false; // helps break the loop
|
||||||
|
|
||||||
break; // exit aces loop
|
break; // exit aces loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!scanNextSid) {
|
if (!scanNextSid) {
|
||||||
break; // exit SID for loop (now try next permission)
|
break; // exit SID for loop (now try next permission)
|
||||||
}
|
}
|
||||||
@@ -124,9 +114,8 @@ public class DefaultPermissionGrantingStrategy implements PermissionGrantingStra
|
|||||||
// We found an ACE to reject the request at this point, as no
|
// We found an ACE to reject the request at this point, as no
|
||||||
// other ACEs were found that granted a different permission
|
// other ACEs were found that granted a different permission
|
||||||
if (!administrativeMode) {
|
if (!administrativeMode) {
|
||||||
auditLogger.logIfNeeded(false, firstRejection);
|
this.auditLogger.logIfNeeded(false, firstRejection);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,26 +124,22 @@ public class DefaultPermissionGrantingStrategy implements PermissionGrantingStra
|
|||||||
// We have a parent, so let them try to find a matching ACE
|
// We have a parent, so let them try to find a matching ACE
|
||||||
return acl.getParentAcl().isGranted(permission, sids, false);
|
return acl.getParentAcl().isGranted(permission, sids, false);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// We either have no parent, or we're the uppermost parent
|
// We either have no parent, or we're the uppermost parent
|
||||||
throw new NotFoundException(
|
throw new NotFoundException("Unable to locate a matching ACE for passed permissions and SIDs");
|
||||||
"Unable to locate a matching ACE for passed permissions and SIDs");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares an ACE Permission to the given Permission.
|
* Compares an ACE Permission to the given Permission. By default, we compare the
|
||||||
* By default, we compare the Permission masks for exact match.
|
* Permission masks for exact match. Subclasses of this strategy can override this
|
||||||
* Subclasses of this strategy can override this behavior and implement
|
* behavior and implement more sophisticated comparisons, e.g. a bitwise comparison
|
||||||
* more sophisticated comparisons, e.g. a bitwise comparison for ACEs that grant access.
|
* for ACEs that grant access. <pre>{@code
|
||||||
* <pre>{@code
|
|
||||||
* if (ace.isGranting() && p.getMask() != 0) {
|
* if (ace.isGranting() && p.getMask() != 0) {
|
||||||
* return (ace.getPermission().getMask() & p.getMask()) != 0;
|
* return (ace.getPermission().getMask() & p.getMask()) != 0;
|
||||||
* } else {
|
* } else {
|
||||||
* return ace.getPermission().getMask() == p.getMask();
|
* return ace.getPermission().getMask() == p.getMask();
|
||||||
* }
|
* }
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
|
||||||
* @param ace the ACE from the Acl holding the mask.
|
* @param ace the ACE from the Acl holding the mask.
|
||||||
* @param p the Permission we are checking against.
|
* @param p the Permission we are checking against.
|
||||||
* @return true, if the respective masks are considered to be equal.
|
* @return true, if the respective masks are considered to be equal.
|
||||||
|
|||||||
+26
-49
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -38,18 +39,14 @@ import org.springframework.util.Assert;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class EhCacheBasedAclCache implements AclCache {
|
public class EhCacheBasedAclCache implements AclCache {
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
private final Ehcache cache;
|
private final Ehcache cache;
|
||||||
|
|
||||||
private PermissionGrantingStrategy permissionGrantingStrategy;
|
private PermissionGrantingStrategy permissionGrantingStrategy;
|
||||||
|
|
||||||
private AclAuthorizationStrategy aclAuthorizationStrategy;
|
private AclAuthorizationStrategy aclAuthorizationStrategy;
|
||||||
|
|
||||||
// ~ Constructors
|
public EhCacheBasedAclCache(Ehcache cache, PermissionGrantingStrategy permissionGrantingStrategy,
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
public EhCacheBasedAclCache(Ehcache cache,
|
|
||||||
PermissionGrantingStrategy permissionGrantingStrategy,
|
|
||||||
AclAuthorizationStrategy aclAuthorizationStrategy) {
|
AclAuthorizationStrategy aclAuthorizationStrategy) {
|
||||||
Assert.notNull(cache, "Cache required");
|
Assert.notNull(cache, "Cache required");
|
||||||
Assert.notNull(permissionGrantingStrategy, "PermissionGrantingStrategy required");
|
Assert.notNull(permissionGrantingStrategy, "PermissionGrantingStrategy required");
|
||||||
@@ -59,72 +56,55 @@ public class EhCacheBasedAclCache implements AclCache {
|
|||||||
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
|
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
@Override
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
public void evictFromCache(Serializable pk) {
|
public void evictFromCache(Serializable pk) {
|
||||||
Assert.notNull(pk, "Primary key (identifier) required");
|
Assert.notNull(pk, "Primary key (identifier) required");
|
||||||
|
|
||||||
MutableAcl acl = getFromCache(pk);
|
MutableAcl acl = getFromCache(pk);
|
||||||
|
|
||||||
if (acl != null) {
|
if (acl != null) {
|
||||||
cache.remove(acl.getId());
|
this.cache.remove(acl.getId());
|
||||||
cache.remove(acl.getObjectIdentity());
|
this.cache.remove(acl.getObjectIdentity());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void evictFromCache(ObjectIdentity objectIdentity) {
|
public void evictFromCache(ObjectIdentity objectIdentity) {
|
||||||
Assert.notNull(objectIdentity, "ObjectIdentity required");
|
Assert.notNull(objectIdentity, "ObjectIdentity required");
|
||||||
|
|
||||||
MutableAcl acl = getFromCache(objectIdentity);
|
MutableAcl acl = getFromCache(objectIdentity);
|
||||||
|
|
||||||
if (acl != null) {
|
if (acl != null) {
|
||||||
cache.remove(acl.getId());
|
this.cache.remove(acl.getId());
|
||||||
cache.remove(acl.getObjectIdentity());
|
this.cache.remove(acl.getObjectIdentity());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public MutableAcl getFromCache(ObjectIdentity objectIdentity) {
|
public MutableAcl getFromCache(ObjectIdentity objectIdentity) {
|
||||||
Assert.notNull(objectIdentity, "ObjectIdentity required");
|
Assert.notNull(objectIdentity, "ObjectIdentity required");
|
||||||
|
|
||||||
Element element = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
element = cache.get(objectIdentity);
|
Element element = this.cache.get(objectIdentity);
|
||||||
|
return (element != null) ? initializeTransientFields((MutableAcl) element.getValue()) : null;
|
||||||
}
|
}
|
||||||
catch (CacheException ignored) {
|
catch (CacheException ex) {
|
||||||
}
|
|
||||||
|
|
||||||
if (element == null) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return initializeTransientFields((MutableAcl) element.getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public MutableAcl getFromCache(Serializable pk) {
|
public MutableAcl getFromCache(Serializable pk) {
|
||||||
Assert.notNull(pk, "Primary key (identifier) required");
|
Assert.notNull(pk, "Primary key (identifier) required");
|
||||||
|
|
||||||
Element element = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
element = cache.get(pk);
|
Element element = this.cache.get(pk);
|
||||||
|
return (element != null) ? initializeTransientFields((MutableAcl) element.getValue()) : null;
|
||||||
}
|
}
|
||||||
catch (CacheException ignored) {
|
catch (CacheException ex) {
|
||||||
}
|
|
||||||
|
|
||||||
if (element == null) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return initializeTransientFields((MutableAcl) element.getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void putInCache(MutableAcl acl) {
|
public void putInCache(MutableAcl acl) {
|
||||||
Assert.notNull(acl, "Acl required");
|
Assert.notNull(acl, "Acl required");
|
||||||
Assert.notNull(acl.getObjectIdentity(), "ObjectIdentity required");
|
Assert.notNull(acl.getObjectIdentity(), "ObjectIdentity required");
|
||||||
Assert.notNull(acl.getId(), "ID required");
|
Assert.notNull(acl.getId(), "ID required");
|
||||||
|
|
||||||
if (this.aclAuthorizationStrategy == null) {
|
if (this.aclAuthorizationStrategy == null) {
|
||||||
if (acl instanceof AclImpl) {
|
if (acl instanceof AclImpl) {
|
||||||
this.aclAuthorizationStrategy = (AclAuthorizationStrategy) FieldUtils
|
this.aclAuthorizationStrategy = (AclAuthorizationStrategy) FieldUtils
|
||||||
@@ -133,30 +113,27 @@ public class EhCacheBasedAclCache implements AclCache {
|
|||||||
.getProtectedFieldValue("permissionGrantingStrategy", acl);
|
.getProtectedFieldValue("permissionGrantingStrategy", acl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((acl.getParentAcl() != null) && (acl.getParentAcl() instanceof MutableAcl)) {
|
if ((acl.getParentAcl() != null) && (acl.getParentAcl() instanceof MutableAcl)) {
|
||||||
putInCache((MutableAcl) acl.getParentAcl());
|
putInCache((MutableAcl) acl.getParentAcl());
|
||||||
}
|
}
|
||||||
|
this.cache.put(new Element(acl.getObjectIdentity(), acl));
|
||||||
cache.put(new Element(acl.getObjectIdentity(), acl));
|
this.cache.put(new Element(acl.getId(), acl));
|
||||||
cache.put(new Element(acl.getId(), acl));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private MutableAcl initializeTransientFields(MutableAcl value) {
|
private MutableAcl initializeTransientFields(MutableAcl value) {
|
||||||
if (value instanceof AclImpl) {
|
if (value instanceof AclImpl) {
|
||||||
FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value,
|
FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value, this.aclAuthorizationStrategy);
|
||||||
this.aclAuthorizationStrategy);
|
FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value, this.permissionGrantingStrategy);
|
||||||
FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value,
|
|
||||||
this.permissionGrantingStrategy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.getParentAcl() != null) {
|
if (value.getParentAcl() != null) {
|
||||||
initializeTransientFields((MutableAcl) value.getParentAcl());
|
initializeTransientFields((MutableAcl) value.getParentAcl());
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void clearCache() {
|
public void clearCache() {
|
||||||
cache.removeAll();
|
this.cache.removeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-15
@@ -13,11 +13,11 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.Sid;
|
import org.springframework.security.acls.model.Sid;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -31,14 +31,9 @@ import org.springframework.util.Assert;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class GrantedAuthoritySid implements Sid {
|
public class GrantedAuthoritySid implements Sid {
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
private final String grantedAuthority;
|
private final String grantedAuthority;
|
||||||
|
|
||||||
// ~ Constructors
|
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
public GrantedAuthoritySid(String grantedAuthority) {
|
public GrantedAuthoritySid(String grantedAuthority) {
|
||||||
Assert.hasText(grantedAuthority, "GrantedAuthority required");
|
Assert.hasText(grantedAuthority, "GrantedAuthority required");
|
||||||
this.grantedAuthority = grantedAuthority;
|
this.grantedAuthority = grantedAuthority;
|
||||||
@@ -46,25 +41,19 @@ public class GrantedAuthoritySid implements Sid {
|
|||||||
|
|
||||||
public GrantedAuthoritySid(GrantedAuthority grantedAuthority) {
|
public GrantedAuthoritySid(GrantedAuthority grantedAuthority) {
|
||||||
Assert.notNull(grantedAuthority, "GrantedAuthority required");
|
Assert.notNull(grantedAuthority, "GrantedAuthority required");
|
||||||
Assert.notNull(
|
Assert.notNull(grantedAuthority.getAuthority(),
|
||||||
grantedAuthority.getAuthority(),
|
|
||||||
"This Sid is only compatible with GrantedAuthoritys that provide a non-null getAuthority()");
|
"This Sid is only compatible with GrantedAuthoritys that provide a non-null getAuthority()");
|
||||||
this.grantedAuthority = grantedAuthority.getAuthority();
|
this.grantedAuthority = grantedAuthority.getAuthority();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object object) {
|
public boolean equals(Object object) {
|
||||||
if ((object == null) || !(object instanceof GrantedAuthoritySid)) {
|
if ((object == null) || !(object instanceof GrantedAuthoritySid)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delegate to getGrantedAuthority() to perform actual comparison (both should be
|
// Delegate to getGrantedAuthority() to perform actual comparison (both should be
|
||||||
// identical)
|
// identical)
|
||||||
return ((GrantedAuthoritySid) object).getGrantedAuthority().equals(
|
return ((GrantedAuthoritySid) object).getGrantedAuthority().equals(this.getGrantedAuthority());
|
||||||
this.getGrantedAuthority());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -73,11 +62,12 @@ public class GrantedAuthoritySid implements Sid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getGrantedAuthority() {
|
public String getGrantedAuthority() {
|
||||||
return grantedAuthority;
|
return this.grantedAuthority;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "GrantedAuthoritySid[" + this.grantedAuthority + "]";
|
return "GrantedAuthoritySid[" + this.grantedAuthority + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-7
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,12 +22,9 @@ package org.springframework.security.acls.domain;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class IdentityUnavailableException extends RuntimeException {
|
public class IdentityUnavailableException extends RuntimeException {
|
||||||
// ~ Constructors
|
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an <code>IdentityUnavailableException</code> with the specified message.
|
* Constructs an <code>IdentityUnavailableException</code> with the specified message.
|
||||||
*
|
|
||||||
* @param msg the detail message
|
* @param msg the detail message
|
||||||
*/
|
*/
|
||||||
public IdentityUnavailableException(String msg) {
|
public IdentityUnavailableException(String msg) {
|
||||||
@@ -36,11 +34,11 @@ public class IdentityUnavailableException extends RuntimeException {
|
|||||||
/**
|
/**
|
||||||
* Constructs an <code>IdentityUnavailableException</code> with the specified message
|
* Constructs an <code>IdentityUnavailableException</code> with the specified message
|
||||||
* and root cause.
|
* and root cause.
|
||||||
*
|
|
||||||
* @param msg the detail message
|
* @param msg the detail message
|
||||||
* @param t root cause
|
* @param cause root cause
|
||||||
*/
|
*/
|
||||||
public IdentityUnavailableException(String msg, Throwable t) {
|
public IdentityUnavailableException(String msg, Throwable cause) {
|
||||||
super(msg, t);
|
super(msg, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-44
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -31,19 +32,14 @@ import org.springframework.util.ClassUtils;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class ObjectIdentityImpl implements ObjectIdentity {
|
public class ObjectIdentityImpl implements ObjectIdentity {
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
private final String type;
|
private final String type;
|
||||||
private Serializable identifier;
|
|
||||||
|
|
||||||
// ~ Constructors
|
private Serializable identifier;
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
public ObjectIdentityImpl(String type, Serializable identifier) {
|
public ObjectIdentityImpl(String type, Serializable identifier) {
|
||||||
Assert.hasText(type, "Type required");
|
Assert.hasText(type, "Type required");
|
||||||
Assert.notNull(identifier, "identifier required");
|
Assert.notNull(identifier, "identifier required");
|
||||||
|
|
||||||
this.identifier = identifier;
|
this.identifier = identifier;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
@@ -66,36 +62,28 @@ public class ObjectIdentityImpl implements ObjectIdentity {
|
|||||||
* <p>
|
* <p>
|
||||||
* The class name of the object passed will be considered the {@link #type}, so if
|
* The class name of the object passed will be considered the {@link #type}, so if
|
||||||
* more control is required, a different constructor should be used.
|
* more control is required, a different constructor should be used.
|
||||||
*
|
|
||||||
* @param object the domain object instance to create an identity for.
|
* @param object the domain object instance to create an identity for.
|
||||||
*
|
|
||||||
* @throws IdentityUnavailableException if identity could not be extracted
|
* @throws IdentityUnavailableException if identity could not be extracted
|
||||||
*/
|
*/
|
||||||
public ObjectIdentityImpl(Object object) throws IdentityUnavailableException {
|
public ObjectIdentityImpl(Object object) throws IdentityUnavailableException {
|
||||||
Assert.notNull(object, "object cannot be null");
|
Assert.notNull(object, "object cannot be null");
|
||||||
|
|
||||||
Class<?> typeClass = ClassUtils.getUserClass(object.getClass());
|
Class<?> typeClass = ClassUtils.getUserClass(object.getClass());
|
||||||
type = typeClass.getName();
|
this.type = typeClass.getName();
|
||||||
|
Object result = invokeGetIdMethod(object, typeClass);
|
||||||
Object result;
|
|
||||||
|
|
||||||
try {
|
|
||||||
Method method = typeClass.getMethod("getId", new Class[] {});
|
|
||||||
result = method.invoke(object);
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new IdentityUnavailableException(
|
|
||||||
"Could not extract identity from object " + object, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.notNull(result, "getId() is required to return a non-null value");
|
Assert.notNull(result, "getId() is required to return a non-null value");
|
||||||
Assert.isInstanceOf(Serializable.class, result,
|
Assert.isInstanceOf(Serializable.class, result, "Getter must provide a return value of type Serializable");
|
||||||
"Getter must provide a return value of type Serializable");
|
|
||||||
this.identifier = (Serializable) result;
|
this.identifier = (Serializable) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
private Object invokeGetIdMethod(Object object, Class<?> typeClass) {
|
||||||
// ========================================================================================================
|
try {
|
||||||
|
Method method = typeClass.getMethod("getId", new Class[] {});
|
||||||
|
return method.invoke(object);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new IdentityUnavailableException("Could not extract identity from object " + object, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Important so caching operates properly.
|
* Important so caching operates properly.
|
||||||
@@ -105,49 +93,42 @@ public class ObjectIdentityImpl implements ObjectIdentity {
|
|||||||
* <p>
|
* <p>
|
||||||
* Numeric identities (Integer and Long values) are considered equal if they are
|
* Numeric identities (Integer and Long values) are considered equal if they are
|
||||||
* numerically equal. Other serializable types are evaluated using a simple equality.
|
* numerically equal. Other serializable types are evaluated using a simple equality.
|
||||||
*
|
* @param obj object to compare
|
||||||
* @param arg0 object to compare
|
|
||||||
*
|
|
||||||
* @return <code>true</code> if the presented object matches this object
|
* @return <code>true</code> if the presented object matches this object
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object arg0) {
|
public boolean equals(Object obj) {
|
||||||
if (arg0 == null || !(arg0 instanceof ObjectIdentityImpl)) {
|
if (obj == null || !(obj instanceof ObjectIdentityImpl)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
ObjectIdentityImpl other = (ObjectIdentityImpl) obj;
|
||||||
ObjectIdentityImpl other = (ObjectIdentityImpl) arg0;
|
if (this.identifier instanceof Number && other.identifier instanceof Number) {
|
||||||
|
|
||||||
if (identifier instanceof Number && other.identifier instanceof Number) {
|
|
||||||
// Integers and Longs with same value should be considered equal
|
// Integers and Longs with same value should be considered equal
|
||||||
if (((Number) identifier).longValue() != ((Number) other.identifier)
|
if (((Number) this.identifier).longValue() != ((Number) other.identifier).longValue()) {
|
||||||
.longValue()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Use plain equality for other serializable types
|
// Use plain equality for other serializable types
|
||||||
if (!identifier.equals(other.identifier)) {
|
if (!this.identifier.equals(other.identifier)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return this.type.equals(other.type);
|
||||||
return type.equals(other.type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Serializable getIdentifier() {
|
public Serializable getIdentifier() {
|
||||||
return identifier;
|
return this.identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return type;
|
return this.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Important so caching operates properly.
|
* Important so caching operates properly.
|
||||||
*
|
|
||||||
* @return the hash
|
* @return the hash
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -163,7 +144,7 @@ public class ObjectIdentityImpl implements ObjectIdentity {
|
|||||||
sb.append(this.getClass().getName()).append("[");
|
sb.append(this.getClass().getName()).append("[");
|
||||||
sb.append("Type: ").append(this.type);
|
sb.append("Type: ").append(this.type);
|
||||||
sb.append("; Identifier: ").append(this.identifier).append("]");
|
sb.append("; Identifier: ").append(this.identifier).append("]");
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -29,16 +29,16 @@ import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
|
|||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class ObjectIdentityRetrievalStrategyImpl implements
|
public class ObjectIdentityRetrievalStrategyImpl implements ObjectIdentityRetrievalStrategy, ObjectIdentityGenerator {
|
||||||
ObjectIdentityRetrievalStrategy, ObjectIdentityGenerator {
|
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
|
@Override
|
||||||
public ObjectIdentity getObjectIdentity(Object domainObject) {
|
public ObjectIdentity getObjectIdentity(Object domainObject) {
|
||||||
return new ObjectIdentityImpl(domainObject);
|
return new ObjectIdentityImpl(domainObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ObjectIdentity createObjectIdentity(Serializable id, String type) {
|
public ObjectIdentity createObjectIdentity(Serializable id, String type) {
|
||||||
return new ObjectIdentityImpl(type, id);
|
return new ObjectIdentityImpl(type, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -25,16 +26,13 @@ import org.springframework.security.acls.model.Permission;
|
|||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
* @since 2.0.3
|
* @since 2.0.3
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface PermissionFactory {
|
public interface PermissionFactory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dynamically creates a <code>CumulativePermission</code> or
|
* Dynamically creates a <code>CumulativePermission</code> or
|
||||||
* <code>BasePermission</code> representing the active bits in the passed mask.
|
* <code>BasePermission</code> representing the active bits in the passed mask.
|
||||||
*
|
|
||||||
* @param mask to build
|
* @param mask to build
|
||||||
*
|
|
||||||
* @return a Permission representing the requested object
|
* @return a Permission representing the requested object
|
||||||
*/
|
*/
|
||||||
Permission buildFromMask(int mask);
|
Permission buildFromMask(int mask);
|
||||||
@@ -42,4 +40,5 @@ public interface PermissionFactory {
|
|||||||
Permission buildFromName(String name);
|
Permission buildFromName(String name);
|
||||||
|
|
||||||
List<Permission> buildFromNames(List<String> names);
|
List<Permission> buildFromNames(List<String> names);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,11 +13,11 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.Sid;
|
import org.springframework.security.acls.model.Sid;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -31,14 +31,9 @@ import org.springframework.util.Assert;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class PrincipalSid implements Sid {
|
public class PrincipalSid implements Sid {
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
private final String principal;
|
private final String principal;
|
||||||
|
|
||||||
// ~ Constructors
|
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
public PrincipalSid(String principal) {
|
public PrincipalSid(String principal) {
|
||||||
Assert.hasText(principal, "Principal required");
|
Assert.hasText(principal, "Principal required");
|
||||||
this.principal = principal;
|
this.principal = principal;
|
||||||
@@ -47,19 +42,14 @@ public class PrincipalSid implements Sid {
|
|||||||
public PrincipalSid(Authentication authentication) {
|
public PrincipalSid(Authentication authentication) {
|
||||||
Assert.notNull(authentication, "Authentication required");
|
Assert.notNull(authentication, "Authentication required");
|
||||||
Assert.notNull(authentication.getPrincipal(), "Principal required");
|
Assert.notNull(authentication.getPrincipal(), "Principal required");
|
||||||
|
|
||||||
this.principal = authentication.getName();
|
this.principal = authentication.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object object) {
|
public boolean equals(Object object) {
|
||||||
if ((object == null) || !(object instanceof PrincipalSid)) {
|
if ((object == null) || !(object instanceof PrincipalSid)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delegate to getPrincipal() to perform actual comparison (both should be
|
// Delegate to getPrincipal() to perform actual comparison (both should be
|
||||||
// identical)
|
// identical)
|
||||||
return ((PrincipalSid) object).getPrincipal().equals(this.getPrincipal());
|
return ((PrincipalSid) object).getPrincipal().equals(this.getPrincipal());
|
||||||
@@ -71,11 +61,12 @@ public class PrincipalSid implements Sid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getPrincipal() {
|
public String getPrincipal() {
|
||||||
return principal;
|
return this.principal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "PrincipalSid[" + this.principal + "]";
|
return "PrincipalSid[" + this.principal + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-7
@@ -51,20 +51,16 @@ public class SidRetrievalStrategyImpl implements SidRetrievalStrategy {
|
|||||||
this.roleHierarchy = roleHierarchy;
|
this.roleHierarchy = roleHierarchy;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
@Override
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
public List<Sid> getSids(Authentication authentication) {
|
public List<Sid> getSids(Authentication authentication) {
|
||||||
Collection<? extends GrantedAuthority> authorities = roleHierarchy
|
Collection<? extends GrantedAuthority> authorities = this.roleHierarchy
|
||||||
.getReachableGrantedAuthorities(authentication.getAuthorities());
|
.getReachableGrantedAuthorities(authentication.getAuthorities());
|
||||||
List<Sid> sids = new ArrayList<>(authorities.size() + 1);
|
List<Sid> sids = new ArrayList<>(authorities.size() + 1);
|
||||||
|
|
||||||
sids.add(new PrincipalSid(authentication));
|
sids.add(new PrincipalSid(authentication));
|
||||||
|
|
||||||
for (GrantedAuthority authority : authorities) {
|
for (GrantedAuthority authority : authorities) {
|
||||||
sids.add(new GrantedAuthoritySid(authority));
|
sids.add(new GrantedAuthoritySid(authority));
|
||||||
}
|
}
|
||||||
|
|
||||||
return sids;
|
return sids;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-33
@@ -13,8 +13,11 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.springframework.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
import org.springframework.security.acls.model.AclCache;
|
import org.springframework.security.acls.model.AclCache;
|
||||||
import org.springframework.security.acls.model.MutableAcl;
|
import org.springframework.security.acls.model.MutableAcl;
|
||||||
@@ -23,8 +26,6 @@ import org.springframework.security.acls.model.PermissionGrantingStrategy;
|
|||||||
import org.springframework.security.util.FieldUtils;
|
import org.springframework.security.util.FieldUtils;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple implementation of {@link org.springframework.security.acls.model.AclCache} that
|
* Simple implementation of {@link org.springframework.security.acls.model.AclCache} that
|
||||||
* delegates to {@link Cache} implementation.
|
* delegates to {@link Cache} implementation.
|
||||||
@@ -39,18 +40,14 @@ import java.io.Serializable;
|
|||||||
* @since 3.2
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
public class SpringCacheBasedAclCache implements AclCache {
|
public class SpringCacheBasedAclCache implements AclCache {
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
private final Cache cache;
|
private final Cache cache;
|
||||||
|
|
||||||
private PermissionGrantingStrategy permissionGrantingStrategy;
|
private PermissionGrantingStrategy permissionGrantingStrategy;
|
||||||
|
|
||||||
private AclAuthorizationStrategy aclAuthorizationStrategy;
|
private AclAuthorizationStrategy aclAuthorizationStrategy;
|
||||||
|
|
||||||
// ~ Constructors
|
public SpringCacheBasedAclCache(Cache cache, PermissionGrantingStrategy permissionGrantingStrategy,
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
public SpringCacheBasedAclCache(Cache cache,
|
|
||||||
PermissionGrantingStrategy permissionGrantingStrategy,
|
|
||||||
AclAuthorizationStrategy aclAuthorizationStrategy) {
|
AclAuthorizationStrategy aclAuthorizationStrategy) {
|
||||||
Assert.notNull(cache, "Cache required");
|
Assert.notNull(cache, "Cache required");
|
||||||
Assert.notNull(permissionGrantingStrategy, "PermissionGrantingStrategy required");
|
Assert.notNull(permissionGrantingStrategy, "PermissionGrantingStrategy required");
|
||||||
@@ -60,79 +57,72 @@ public class SpringCacheBasedAclCache implements AclCache {
|
|||||||
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
|
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
@Override
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
public void evictFromCache(Serializable pk) {
|
public void evictFromCache(Serializable pk) {
|
||||||
Assert.notNull(pk, "Primary key (identifier) required");
|
Assert.notNull(pk, "Primary key (identifier) required");
|
||||||
|
|
||||||
MutableAcl acl = getFromCache(pk);
|
MutableAcl acl = getFromCache(pk);
|
||||||
|
|
||||||
if (acl != null) {
|
if (acl != null) {
|
||||||
cache.evict(acl.getId());
|
this.cache.evict(acl.getId());
|
||||||
cache.evict(acl.getObjectIdentity());
|
this.cache.evict(acl.getObjectIdentity());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void evictFromCache(ObjectIdentity objectIdentity) {
|
public void evictFromCache(ObjectIdentity objectIdentity) {
|
||||||
Assert.notNull(objectIdentity, "ObjectIdentity required");
|
Assert.notNull(objectIdentity, "ObjectIdentity required");
|
||||||
|
|
||||||
MutableAcl acl = getFromCache(objectIdentity);
|
MutableAcl acl = getFromCache(objectIdentity);
|
||||||
|
|
||||||
if (acl != null) {
|
if (acl != null) {
|
||||||
cache.evict(acl.getId());
|
this.cache.evict(acl.getId());
|
||||||
cache.evict(acl.getObjectIdentity());
|
this.cache.evict(acl.getObjectIdentity());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public MutableAcl getFromCache(ObjectIdentity objectIdentity) {
|
public MutableAcl getFromCache(ObjectIdentity objectIdentity) {
|
||||||
Assert.notNull(objectIdentity, "ObjectIdentity required");
|
Assert.notNull(objectIdentity, "ObjectIdentity required");
|
||||||
return getFromCache((Object) objectIdentity);
|
return getFromCache((Object) objectIdentity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public MutableAcl getFromCache(Serializable pk) {
|
public MutableAcl getFromCache(Serializable pk) {
|
||||||
Assert.notNull(pk, "Primary key (identifier) required");
|
Assert.notNull(pk, "Primary key (identifier) required");
|
||||||
return getFromCache((Object) pk);
|
return getFromCache((Object) pk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void putInCache(MutableAcl acl) {
|
public void putInCache(MutableAcl acl) {
|
||||||
Assert.notNull(acl, "Acl required");
|
Assert.notNull(acl, "Acl required");
|
||||||
Assert.notNull(acl.getObjectIdentity(), "ObjectIdentity required");
|
Assert.notNull(acl.getObjectIdentity(), "ObjectIdentity required");
|
||||||
Assert.notNull(acl.getId(), "ID required");
|
Assert.notNull(acl.getId(), "ID required");
|
||||||
|
|
||||||
if ((acl.getParentAcl() != null) && (acl.getParentAcl() instanceof MutableAcl)) {
|
if ((acl.getParentAcl() != null) && (acl.getParentAcl() instanceof MutableAcl)) {
|
||||||
putInCache((MutableAcl) acl.getParentAcl());
|
putInCache((MutableAcl) acl.getParentAcl());
|
||||||
}
|
}
|
||||||
|
this.cache.put(acl.getObjectIdentity(), acl);
|
||||||
cache.put(acl.getObjectIdentity(), acl);
|
this.cache.put(acl.getId(), acl);
|
||||||
cache.put(acl.getId(), acl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private MutableAcl getFromCache(Object key) {
|
private MutableAcl getFromCache(Object key) {
|
||||||
Cache.ValueWrapper element = cache.get(key);
|
Cache.ValueWrapper element = this.cache.get(key);
|
||||||
|
|
||||||
if (element == null) {
|
if (element == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return initializeTransientFields((MutableAcl) element.get());
|
return initializeTransientFields((MutableAcl) element.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
private MutableAcl initializeTransientFields(MutableAcl value) {
|
private MutableAcl initializeTransientFields(MutableAcl value) {
|
||||||
if (value instanceof AclImpl) {
|
if (value instanceof AclImpl) {
|
||||||
FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value,
|
FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value, this.aclAuthorizationStrategy);
|
||||||
this.aclAuthorizationStrategy);
|
FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value, this.permissionGrantingStrategy);
|
||||||
FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value,
|
|
||||||
this.permissionGrantingStrategy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.getParentAcl() != null) {
|
if (value.getParentAcl() != null) {
|
||||||
initializeTransientFields((MutableAcl) value.getParentAcl());
|
initializeTransientFields((MutableAcl) value.getParentAcl());
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void clearCache() {
|
public void clearCache() {
|
||||||
cache.clear();
|
this.cache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic implementation of access control lists (ACLs) interfaces.
|
* Basic implementation of access control lists (ACLs) interfaces.
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.jdbc;
|
package org.springframework.security.acls.jdbc;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -22,6 +23,7 @@ import java.util.UUID;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import org.springframework.core.convert.ConversionFailedException;
|
import org.springframework.core.convert.ConversionFailedException;
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
@@ -31,12 +33,16 @@ import org.springframework.security.acls.model.ObjectIdentity;
|
|||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class for helping convert database representations of {@link ObjectIdentity#getIdentifier()} into
|
* Utility class for helping convert database representations of
|
||||||
* the correct Java type as specified by <code>acl_class.class_id_type</code>.
|
* {@link ObjectIdentity#getIdentifier()} into the correct Java type as specified by
|
||||||
|
* <code>acl_class.class_id_type</code>.
|
||||||
|
*
|
||||||
* @author paulwheeler
|
* @author paulwheeler
|
||||||
*/
|
*/
|
||||||
class AclClassIdUtils {
|
class AclClassIdUtils {
|
||||||
|
|
||||||
private static final String DEFAULT_CLASS_ID_TYPE_COLUMN_NAME = "class_id_type";
|
private static final String DEFAULT_CLASS_ID_TYPE_COLUMN_NAME = "class_id_type";
|
||||||
|
|
||||||
private static final Log log = LogFactory.getLog(AclClassIdUtils.class);
|
private static final Log log = LogFactory.getLog(AclClassIdUtils.class);
|
||||||
|
|
||||||
private ConversionService conversionService;
|
private ConversionService conversionService;
|
||||||
@@ -54,88 +60,85 @@ class AclClassIdUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the raw type from the database into the right Java type. For most applications the 'raw type' will be Long, for some applications
|
* Converts the raw type from the database into the right Java type. For most
|
||||||
* it could be String.
|
* applications the 'raw type' will be Long, for some applications it could be String.
|
||||||
* @param identifier The identifier from the database
|
* @param identifier The identifier from the database
|
||||||
* @param resultSet Result set of the query
|
* @param resultSet Result set of the query
|
||||||
* @return The identifier in the appropriate target Java type. Typically Long or UUID.
|
* @return The identifier in the appropriate target Java type. Typically Long or UUID.
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
Serializable identifierFrom(Serializable identifier, ResultSet resultSet) throws SQLException {
|
Serializable identifierFrom(Serializable identifier, ResultSet resultSet) throws SQLException {
|
||||||
if (isString(identifier) && hasValidClassIdType(resultSet)
|
if (isString(identifier) && hasValidClassIdType(resultSet)
|
||||||
&& canConvertFromStringTo(classIdTypeFrom(resultSet))) {
|
&& canConvertFromStringTo(classIdTypeFrom(resultSet))) {
|
||||||
|
return convertFromStringTo((String) identifier, classIdTypeFrom(resultSet));
|
||||||
identifier = convertFromStringTo((String) identifier, classIdTypeFrom(resultSet));
|
|
||||||
} else {
|
|
||||||
// Assume it should be a Long type
|
|
||||||
identifier = convertToLong(identifier);
|
|
||||||
}
|
}
|
||||||
|
// Assume it should be a Long type
|
||||||
return identifier;
|
return convertToLong(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasValidClassIdType(ResultSet resultSet) {
|
private boolean hasValidClassIdType(ResultSet resultSet) {
|
||||||
boolean hasClassIdType = false;
|
|
||||||
try {
|
try {
|
||||||
hasClassIdType = classIdTypeFrom(resultSet) != null;
|
return classIdTypeFrom(resultSet) != null;
|
||||||
} catch (SQLException e) {
|
}
|
||||||
log.debug("Unable to obtain the class id type", e);
|
catch (SQLException ex) {
|
||||||
|
log.debug("Unable to obtain the class id type", ex);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return hasClassIdType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T extends Serializable> Class<T> classIdTypeFrom(ResultSet resultSet) throws SQLException {
|
private <T extends Serializable> Class<T> classIdTypeFrom(ResultSet resultSet) throws SQLException {
|
||||||
return classIdTypeFrom(resultSet.getString(DEFAULT_CLASS_ID_TYPE_COLUMN_NAME));
|
return classIdTypeFrom(resultSet.getString(DEFAULT_CLASS_ID_TYPE_COLUMN_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T extends Serializable> Class<T> classIdTypeFrom(String className) {
|
private <T extends Serializable> Class<T> classIdTypeFrom(String className) {
|
||||||
Class targetType = null;
|
if (className == null) {
|
||||||
if (className != null) {
|
return null;
|
||||||
try {
|
}
|
||||||
targetType = Class.forName(className);
|
try {
|
||||||
} catch (ClassNotFoundException e) {
|
return (Class) Class.forName(className);
|
||||||
log.debug("Unable to find class id type on classpath", e);
|
}
|
||||||
}
|
catch (ClassNotFoundException ex) {
|
||||||
|
log.debug("Unable to find class id type on classpath", ex);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return targetType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> boolean canConvertFromStringTo(Class<T> targetType) {
|
private <T> boolean canConvertFromStringTo(Class<T> targetType) {
|
||||||
return conversionService.canConvert(String.class, targetType);
|
return this.conversionService.canConvert(String.class, targetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T extends Serializable> T convertFromStringTo(String identifier, Class<T> targetType) {
|
private <T extends Serializable> T convertFromStringTo(String identifier, Class<T> targetType) {
|
||||||
return conversionService.convert(identifier, targetType);
|
return this.conversionService.convert(identifier, targetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts to a {@link Long}, attempting to use the {@link ConversionService} if available.
|
* Converts to a {@link Long}, attempting to use the {@link ConversionService} if
|
||||||
* @param identifier The identifier
|
* available.
|
||||||
|
* @param identifier The identifier
|
||||||
* @return Long version of the identifier
|
* @return Long version of the identifier
|
||||||
* @throws NumberFormatException if the string cannot be parsed to a long.
|
* @throws NumberFormatException if the string cannot be parsed to a long.
|
||||||
* @throws org.springframework.core.convert.ConversionException if a conversion exception occurred
|
* @throws org.springframework.core.convert.ConversionException if a conversion
|
||||||
|
* exception occurred
|
||||||
* @throws IllegalArgumentException if targetType is null
|
* @throws IllegalArgumentException if targetType is null
|
||||||
*/
|
*/
|
||||||
private Long convertToLong(Serializable identifier) {
|
private Long convertToLong(Serializable identifier) {
|
||||||
Long idAsLong;
|
if (this.conversionService.canConvert(identifier.getClass(), Long.class)) {
|
||||||
if (conversionService.canConvert(identifier.getClass(), Long.class)) {
|
return this.conversionService.convert(identifier, Long.class);
|
||||||
idAsLong = conversionService.convert(identifier, Long.class);
|
|
||||||
} else {
|
|
||||||
idAsLong = Long.valueOf(identifier.toString());
|
|
||||||
}
|
}
|
||||||
return idAsLong;
|
return Long.valueOf(identifier.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isString(Serializable object) {
|
private boolean isString(Serializable object) {
|
||||||
return object.getClass().isAssignableFrom(String.class);
|
return object.getClass().isAssignableFrom(String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConversionService(ConversionService conversionService) {
|
void setConversionService(ConversionService conversionService) {
|
||||||
Assert.notNull(conversionService, "conversionService must not be null");
|
Assert.notNull(conversionService, "conversionService must not be null");
|
||||||
this.conversionService = conversionService;
|
this.conversionService = conversionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class StringToLongConverter implements Converter<String, Long> {
|
private static class StringToLongConverter implements Converter<String, Long> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long convert(String identifierAsString) {
|
public Long convert(String identifierAsString) {
|
||||||
if (identifierAsString == null) {
|
if (identifierAsString == null) {
|
||||||
@@ -145,9 +148,11 @@ class AclClassIdUtils {
|
|||||||
}
|
}
|
||||||
return Long.parseLong(identifierAsString);
|
return Long.parseLong(identifierAsString);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class StringToUUIDConverter implements Converter<String, UUID> {
|
private static class StringToUUIDConverter implements Converter<String, UUID> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UUID convert(String identifierAsString) {
|
public UUID convert(String identifierAsString) {
|
||||||
if (identifierAsString == null) {
|
if (identifierAsString == null) {
|
||||||
@@ -157,5 +162,7 @@ class AclClassIdUtils {
|
|||||||
}
|
}
|
||||||
return UUID.fromString(identifierAsString);
|
return UUID.fromString(identifierAsString);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+148
-204
@@ -13,10 +13,12 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.jdbc;
|
package org.springframework.security.acls.jdbc;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -68,9 +70,9 @@ import org.springframework.util.Assert;
|
|||||||
* as it is likely to change in future releases and therefore subclassing is unsupported.
|
* as it is likely to change in future releases and therefore subclassing is unsupported.
|
||||||
* <p>
|
* <p>
|
||||||
* There are two SQL queries executed, one in the <tt>lookupPrimaryKeys</tt> method and
|
* There are two SQL queries executed, one in the <tt>lookupPrimaryKeys</tt> method and
|
||||||
* one in <tt>lookupObjectIdentities</tt>. These are built from the same select and
|
* one in <tt>lookupObjectIdentities</tt>. These are built from the same select and "order
|
||||||
* "order by" clause, using a different where clause in each case. In order to use custom
|
* by" clause, using a different where clause in each case. In order to use custom schema
|
||||||
* schema or column names, each of these SQL clauses can be customized, but they must be
|
* or column names, each of these SQL clauses can be customized, but they must be
|
||||||
* consistent with each other and with the expected result set generated by the the
|
* consistent with each other and with the expected result set generated by the the
|
||||||
* default values.
|
* default values.
|
||||||
*
|
*
|
||||||
@@ -78,183 +80,151 @@ import org.springframework.util.Assert;
|
|||||||
*/
|
*/
|
||||||
public class BasicLookupStrategy implements LookupStrategy {
|
public class BasicLookupStrategy implements LookupStrategy {
|
||||||
|
|
||||||
private final static String DEFAULT_SELECT_CLAUSE_COLUMNS = "select acl_object_identity.object_id_identity, "
|
private static final String DEFAULT_SELECT_CLAUSE_COLUMNS = "select acl_object_identity.object_id_identity, "
|
||||||
+ "acl_entry.ace_order, "
|
+ "acl_entry.ace_order, " + "acl_object_identity.id as acl_id, " + "acl_object_identity.parent_object, "
|
||||||
+ "acl_object_identity.id as acl_id, "
|
+ "acl_object_identity.entries_inheriting, " + "acl_entry.id as ace_id, " + "acl_entry.mask, "
|
||||||
+ "acl_object_identity.parent_object, "
|
+ "acl_entry.granting, " + "acl_entry.audit_success, " + "acl_entry.audit_failure, "
|
||||||
+ "acl_object_identity.entries_inheriting, "
|
+ "acl_sid.principal as ace_principal, " + "acl_sid.sid as ace_sid, "
|
||||||
+ "acl_entry.id as ace_id, "
|
+ "acli_sid.principal as acl_principal, " + "acli_sid.sid as acl_sid, " + "acl_class.class ";
|
||||||
+ "acl_entry.mask, "
|
|
||||||
+ "acl_entry.granting, "
|
private static final String DEFAULT_SELECT_CLAUSE_ACL_CLASS_ID_TYPE_COLUMN = ", acl_class.class_id_type ";
|
||||||
+ "acl_entry.audit_success, "
|
|
||||||
+ "acl_entry.audit_failure, "
|
private static final String DEFAULT_SELECT_CLAUSE_FROM = "from acl_object_identity "
|
||||||
+ "acl_sid.principal as ace_principal, "
|
|
||||||
+ "acl_sid.sid as ace_sid, "
|
|
||||||
+ "acli_sid.principal as acl_principal, "
|
|
||||||
+ "acli_sid.sid as acl_sid, "
|
|
||||||
+ "acl_class.class ";
|
|
||||||
private final static String DEFAULT_SELECT_CLAUSE_ACL_CLASS_ID_TYPE_COLUMN = ", acl_class.class_id_type ";
|
|
||||||
private final static String DEFAULT_SELECT_CLAUSE_FROM = "from acl_object_identity "
|
|
||||||
+ "left join acl_sid acli_sid on acli_sid.id = acl_object_identity.owner_sid "
|
+ "left join acl_sid acli_sid on acli_sid.id = acl_object_identity.owner_sid "
|
||||||
+ "left join acl_class on acl_class.id = acl_object_identity.object_id_class "
|
+ "left join acl_class on acl_class.id = acl_object_identity.object_id_class "
|
||||||
+ "left join acl_entry on acl_object_identity.id = acl_entry.acl_object_identity "
|
+ "left join acl_entry on acl_object_identity.id = acl_entry.acl_object_identity "
|
||||||
+ "left join acl_sid on acl_entry.sid = acl_sid.id " + "where ( ";
|
+ "left join acl_sid on acl_entry.sid = acl_sid.id " + "where ( ";
|
||||||
|
|
||||||
public final static String DEFAULT_SELECT_CLAUSE = DEFAULT_SELECT_CLAUSE_COLUMNS + DEFAULT_SELECT_CLAUSE_FROM;
|
public static final String DEFAULT_SELECT_CLAUSE = DEFAULT_SELECT_CLAUSE_COLUMNS + DEFAULT_SELECT_CLAUSE_FROM;
|
||||||
|
|
||||||
public final static String DEFAULT_ACL_CLASS_ID_SELECT_CLAUSE = DEFAULT_SELECT_CLAUSE_COLUMNS +
|
public static final String DEFAULT_ACL_CLASS_ID_SELECT_CLAUSE = DEFAULT_SELECT_CLAUSE_COLUMNS
|
||||||
DEFAULT_SELECT_CLAUSE_ACL_CLASS_ID_TYPE_COLUMN + DEFAULT_SELECT_CLAUSE_FROM;
|
+ DEFAULT_SELECT_CLAUSE_ACL_CLASS_ID_TYPE_COLUMN + DEFAULT_SELECT_CLAUSE_FROM;
|
||||||
|
|
||||||
private final static String DEFAULT_LOOKUP_KEYS_WHERE_CLAUSE = "(acl_object_identity.id = ?)";
|
private static final String DEFAULT_LOOKUP_KEYS_WHERE_CLAUSE = "(acl_object_identity.id = ?)";
|
||||||
|
|
||||||
private final static String DEFAULT_LOOKUP_IDENTITIES_WHERE_CLAUSE = "(acl_object_identity.object_id_identity = ? and acl_class.class = ?)";
|
private static final String DEFAULT_LOOKUP_IDENTITIES_WHERE_CLAUSE = "(acl_object_identity.object_id_identity = ? and acl_class.class = ?)";
|
||||||
|
|
||||||
public final static String DEFAULT_ORDER_BY_CLAUSE = ") order by acl_object_identity.object_id_identity"
|
public static final String DEFAULT_ORDER_BY_CLAUSE = ") order by acl_object_identity.object_id_identity"
|
||||||
+ " asc, acl_entry.ace_order asc";
|
+ " asc, acl_entry.ace_order asc";
|
||||||
|
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
private final AclAuthorizationStrategy aclAuthorizationStrategy;
|
private final AclAuthorizationStrategy aclAuthorizationStrategy;
|
||||||
|
|
||||||
private PermissionFactory permissionFactory = new DefaultPermissionFactory();
|
private PermissionFactory permissionFactory = new DefaultPermissionFactory();
|
||||||
|
|
||||||
private final AclCache aclCache;
|
private final AclCache aclCache;
|
||||||
|
|
||||||
private final PermissionGrantingStrategy grantingStrategy;
|
private final PermissionGrantingStrategy grantingStrategy;
|
||||||
|
|
||||||
private final JdbcTemplate jdbcTemplate;
|
private final JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
private int batchSize = 50;
|
private int batchSize = 50;
|
||||||
|
|
||||||
private final Field fieldAces = FieldUtils.getField(AclImpl.class, "aces");
|
private final Field fieldAces = FieldUtils.getField(AclImpl.class, "aces");
|
||||||
private final Field fieldAcl = FieldUtils.getField(AccessControlEntryImpl.class,
|
|
||||||
"acl");
|
private final Field fieldAcl = FieldUtils.getField(AccessControlEntryImpl.class, "acl");
|
||||||
|
|
||||||
// SQL Customization fields
|
// SQL Customization fields
|
||||||
private String selectClause = DEFAULT_SELECT_CLAUSE;
|
private String selectClause = DEFAULT_SELECT_CLAUSE;
|
||||||
|
|
||||||
private String lookupPrimaryKeysWhereClause = DEFAULT_LOOKUP_KEYS_WHERE_CLAUSE;
|
private String lookupPrimaryKeysWhereClause = DEFAULT_LOOKUP_KEYS_WHERE_CLAUSE;
|
||||||
|
|
||||||
private String lookupObjectIdentitiesWhereClause = DEFAULT_LOOKUP_IDENTITIES_WHERE_CLAUSE;
|
private String lookupObjectIdentitiesWhereClause = DEFAULT_LOOKUP_IDENTITIES_WHERE_CLAUSE;
|
||||||
|
|
||||||
private String orderByClause = DEFAULT_ORDER_BY_CLAUSE;
|
private String orderByClause = DEFAULT_ORDER_BY_CLAUSE;
|
||||||
|
|
||||||
private AclClassIdUtils aclClassIdUtils;
|
private AclClassIdUtils aclClassIdUtils;
|
||||||
|
|
||||||
// ~ Constructors
|
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor accepting mandatory arguments
|
* Constructor accepting mandatory arguments
|
||||||
*
|
|
||||||
* @param dataSource to access the database
|
* @param dataSource to access the database
|
||||||
* @param aclCache the cache where fully-loaded elements can be stored
|
* @param aclCache the cache where fully-loaded elements can be stored
|
||||||
* @param aclAuthorizationStrategy authorization strategy (required)
|
* @param aclAuthorizationStrategy authorization strategy (required)
|
||||||
*/
|
*/
|
||||||
public BasicLookupStrategy(DataSource dataSource, AclCache aclCache,
|
public BasicLookupStrategy(DataSource dataSource, AclCache aclCache,
|
||||||
AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) {
|
AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) {
|
||||||
this(dataSource, aclCache, aclAuthorizationStrategy,
|
this(dataSource, aclCache, aclAuthorizationStrategy, new DefaultPermissionGrantingStrategy(auditLogger));
|
||||||
new DefaultPermissionGrantingStrategy(auditLogger));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
*
|
|
||||||
* @param dataSource to access the database
|
* @param dataSource to access the database
|
||||||
* @param aclCache the cache where fully-loaded elements can be stored
|
* @param aclCache the cache where fully-loaded elements can be stored
|
||||||
* @param aclAuthorizationStrategy authorization strategy (required)
|
* @param aclAuthorizationStrategy authorization strategy (required)
|
||||||
* @param grantingStrategy the PermissionGrantingStrategy
|
* @param grantingStrategy the PermissionGrantingStrategy
|
||||||
*/
|
*/
|
||||||
public BasicLookupStrategy(DataSource dataSource, AclCache aclCache,
|
public BasicLookupStrategy(DataSource dataSource, AclCache aclCache,
|
||||||
AclAuthorizationStrategy aclAuthorizationStrategy,
|
AclAuthorizationStrategy aclAuthorizationStrategy, PermissionGrantingStrategy grantingStrategy) {
|
||||||
PermissionGrantingStrategy grantingStrategy) {
|
|
||||||
Assert.notNull(dataSource, "DataSource required");
|
Assert.notNull(dataSource, "DataSource required");
|
||||||
Assert.notNull(aclCache, "AclCache required");
|
Assert.notNull(aclCache, "AclCache required");
|
||||||
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
|
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
|
||||||
Assert.notNull(grantingStrategy, "grantingStrategy required");
|
Assert.notNull(grantingStrategy, "grantingStrategy required");
|
||||||
jdbcTemplate = new JdbcTemplate(dataSource);
|
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||||
this.aclCache = aclCache;
|
this.aclCache = aclCache;
|
||||||
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
|
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
|
||||||
this.grantingStrategy = grantingStrategy;
|
this.grantingStrategy = grantingStrategy;
|
||||||
this.aclClassIdUtils = new AclClassIdUtils();
|
this.aclClassIdUtils = new AclClassIdUtils();
|
||||||
fieldAces.setAccessible(true);
|
this.fieldAces.setAccessible(true);
|
||||||
fieldAcl.setAccessible(true);
|
this.fieldAcl.setAccessible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
private String computeRepeatingSql(String repeatingSql, int requiredRepetitions) {
|
private String computeRepeatingSql(String repeatingSql, int requiredRepetitions) {
|
||||||
assert requiredRepetitions > 0 : "requiredRepetitions must be > 0";
|
Assert.isTrue(requiredRepetitions > 0, "requiredRepetitions must be > 0");
|
||||||
|
String startSql = this.selectClause;
|
||||||
final String startSql = selectClause;
|
String endSql = this.orderByClause;
|
||||||
|
StringBuilder sqlStringBldr = new StringBuilder(
|
||||||
final String endSql = orderByClause;
|
startSql.length() + endSql.length() + requiredRepetitions * (repeatingSql.length() + 4));
|
||||||
|
|
||||||
StringBuilder sqlStringBldr = new StringBuilder(startSql.length()
|
|
||||||
+ endSql.length() + requiredRepetitions * (repeatingSql.length() + 4));
|
|
||||||
sqlStringBldr.append(startSql);
|
sqlStringBldr.append(startSql);
|
||||||
|
|
||||||
for (int i = 1; i <= requiredRepetitions; i++) {
|
for (int i = 1; i <= requiredRepetitions; i++) {
|
||||||
sqlStringBldr.append(repeatingSql);
|
sqlStringBldr.append(repeatingSql);
|
||||||
|
|
||||||
if (i != requiredRepetitions) {
|
if (i != requiredRepetitions) {
|
||||||
sqlStringBldr.append(" or ");
|
sqlStringBldr.append(" or ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlStringBldr.append(endSql);
|
sqlStringBldr.append(endSql);
|
||||||
|
|
||||||
return sqlStringBldr.toString();
|
return sqlStringBldr.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private List<AccessControlEntryImpl> readAces(AclImpl acl) {
|
private List<AccessControlEntryImpl> readAces(AclImpl acl) {
|
||||||
try {
|
try {
|
||||||
return (List<AccessControlEntryImpl>) fieldAces.get(acl);
|
return (List<AccessControlEntryImpl>) this.fieldAces.get(acl);
|
||||||
}
|
}
|
||||||
catch (IllegalAccessException e) {
|
catch (IllegalAccessException ex) {
|
||||||
throw new IllegalStateException("Could not obtain AclImpl.aces field", e);
|
throw new IllegalStateException("Could not obtain AclImpl.aces field", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAclOnAce(AccessControlEntryImpl ace, AclImpl acl) {
|
private void setAclOnAce(AccessControlEntryImpl ace, AclImpl acl) {
|
||||||
try {
|
try {
|
||||||
fieldAcl.set(ace, acl);
|
this.fieldAcl.set(ace, acl);
|
||||||
}
|
}
|
||||||
catch (IllegalAccessException e) {
|
catch (IllegalAccessException ex) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException("Could not or set AclImpl on AccessControlEntryImpl fields", ex);
|
||||||
"Could not or set AclImpl on AccessControlEntryImpl fields", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAces(AclImpl acl, List<AccessControlEntryImpl> aces) {
|
private void setAces(AclImpl acl, List<AccessControlEntryImpl> aces) {
|
||||||
try {
|
try {
|
||||||
fieldAces.set(acl, aces);
|
this.fieldAces.set(acl, aces);
|
||||||
}
|
}
|
||||||
catch (IllegalAccessException e) {
|
catch (IllegalAccessException ex) {
|
||||||
throw new IllegalStateException("Could not set AclImpl entries", e);
|
throw new IllegalStateException("Could not set AclImpl entries", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locates the primary key IDs specified in "findNow", adding AclImpl instances with
|
* Locates the primary key IDs specified in "findNow", adding AclImpl instances with
|
||||||
* StubAclParents to the "acls" Map.
|
* StubAclParents to the "acls" Map.
|
||||||
*
|
|
||||||
* @param acls the AclImpls (with StubAclParents)
|
* @param acls the AclImpls (with StubAclParents)
|
||||||
* @param findNow Long-based primary keys to retrieve
|
* @param findNow Long-based primary keys to retrieve
|
||||||
* @param sids
|
* @param sids
|
||||||
*/
|
*/
|
||||||
private void lookupPrimaryKeys(final Map<Serializable, Acl> acls,
|
private void lookupPrimaryKeys(final Map<Serializable, Acl> acls, final Set<Long> findNow, final List<Sid> sids) {
|
||||||
final Set<Long> findNow, final List<Sid> sids) {
|
|
||||||
Assert.notNull(acls, "ACLs are required");
|
Assert.notNull(acls, "ACLs are required");
|
||||||
Assert.notEmpty(findNow, "Items to find now required");
|
Assert.notEmpty(findNow, "Items to find now required");
|
||||||
|
String sql = computeRepeatingSql(this.lookupPrimaryKeysWhereClause, findNow.size());
|
||||||
String sql = computeRepeatingSql(lookupPrimaryKeysWhereClause, findNow.size());
|
Set<Long> parentsToLookup = this.jdbcTemplate.query(sql, (ps) -> setKeys(ps, findNow),
|
||||||
|
new ProcessResultSet(acls, sids));
|
||||||
Set<Long> parentsToLookup = jdbcTemplate.query(sql,
|
|
||||||
ps -> {
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
for (Long toFind : findNow) {
|
|
||||||
i++;
|
|
||||||
ps.setLong(i, toFind);
|
|
||||||
}
|
|
||||||
}, new ProcessResultSet(acls, sids));
|
|
||||||
|
|
||||||
// Lookup the parents, now that our JdbcTemplate has released the database
|
// Lookup the parents, now that our JdbcTemplate has released the database
|
||||||
// connection (SEC-547)
|
// connection (SEC-547)
|
||||||
if (parentsToLookup.size() > 0) {
|
if (parentsToLookup.size() > 0) {
|
||||||
@@ -262,6 +232,14 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setKeys(PreparedStatement ps, Set<Long> findNow) throws SQLException {
|
||||||
|
int i = 0;
|
||||||
|
for (Long toFind : findNow) {
|
||||||
|
i++;
|
||||||
|
ps.setLong(i, toFind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main method.
|
* The main method.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -271,85 +249,61 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
* develop a custom {@link LookupStrategy} implementation instead.
|
* develop a custom {@link LookupStrategy} implementation instead.
|
||||||
* <p>
|
* <p>
|
||||||
* The implementation works in batch sizes specified by {@link #batchSize}.
|
* The implementation works in batch sizes specified by {@link #batchSize}.
|
||||||
*
|
|
||||||
* @param objects the identities to lookup (required)
|
* @param objects the identities to lookup (required)
|
||||||
* @param sids the SIDs for which identities are required (ignored by this
|
* @param sids the SIDs for which identities are required (ignored by this
|
||||||
* implementation)
|
* implementation)
|
||||||
*
|
|
||||||
* @return a <tt>Map</tt> where keys represent the {@link ObjectIdentity} of the
|
* @return a <tt>Map</tt> where keys represent the {@link ObjectIdentity} of the
|
||||||
* located {@link Acl} and values are the located {@link Acl} (never <tt>null</tt>
|
* located {@link Acl} and values are the located {@link Acl} (never <tt>null</tt>
|
||||||
* although some entries may be missing; this method should not throw
|
* although some entries may be missing; this method should not throw
|
||||||
* {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used to
|
* {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used to
|
||||||
* automatically create entries if required)
|
* automatically create entries if required)
|
||||||
*/
|
*/
|
||||||
public final Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects,
|
@Override
|
||||||
List<Sid> sids) {
|
public final Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids) {
|
||||||
Assert.isTrue(batchSize >= 1, "BatchSize must be >= 1");
|
Assert.isTrue(this.batchSize >= 1, "BatchSize must be >= 1");
|
||||||
Assert.notEmpty(objects, "Objects to lookup required");
|
Assert.notEmpty(objects, "Objects to lookup required");
|
||||||
|
|
||||||
// Map<ObjectIdentity,Acl>
|
// Map<ObjectIdentity,Acl>
|
||||||
Map<ObjectIdentity, Acl> result = new HashMap<>(); // contains
|
// contains FULLY loaded Acl objects
|
||||||
// FULLY
|
Map<ObjectIdentity, Acl> result = new HashMap<>();
|
||||||
// loaded
|
|
||||||
// Acl
|
|
||||||
// objects
|
|
||||||
|
|
||||||
Set<ObjectIdentity> currentBatchToLoad = new HashSet<>();
|
Set<ObjectIdentity> currentBatchToLoad = new HashSet<>();
|
||||||
|
|
||||||
for (int i = 0; i < objects.size(); i++) {
|
for (int i = 0; i < objects.size(); i++) {
|
||||||
final ObjectIdentity oid = objects.get(i);
|
final ObjectIdentity oid = objects.get(i);
|
||||||
boolean aclFound = false;
|
boolean aclFound = false;
|
||||||
|
|
||||||
// Check we don't already have this ACL in the results
|
// Check we don't already have this ACL in the results
|
||||||
if (result.containsKey(oid)) {
|
if (result.containsKey(oid)) {
|
||||||
aclFound = true;
|
aclFound = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check cache for the present ACL entry
|
// Check cache for the present ACL entry
|
||||||
if (!aclFound) {
|
if (!aclFound) {
|
||||||
Acl acl = aclCache.getFromCache(oid);
|
Acl acl = this.aclCache.getFromCache(oid);
|
||||||
|
|
||||||
// Ensure any cached element supports all the requested SIDs
|
// Ensure any cached element supports all the requested SIDs
|
||||||
// (they should always, as our base impl doesn't filter on SID)
|
// (they should always, as our base impl doesn't filter on SID)
|
||||||
if (acl != null) {
|
if (acl != null) {
|
||||||
if (acl.isSidLoaded(sids)) {
|
Assert.state(acl.isSidLoaded(sids),
|
||||||
result.put(acl.getObjectIdentity(), acl);
|
"Error: SID-filtered element detected when implementation does not perform SID filtering "
|
||||||
aclFound = true;
|
+ "- have you added something to the cache manually?");
|
||||||
}
|
result.put(acl.getObjectIdentity(), acl);
|
||||||
else {
|
aclFound = true;
|
||||||
throw new IllegalStateException(
|
|
||||||
"Error: SID-filtered element detected when implementation does not perform SID filtering "
|
|
||||||
+ "- have you added something to the cache manually?");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the ACL from the database
|
// Load the ACL from the database
|
||||||
if (!aclFound) {
|
if (!aclFound) {
|
||||||
currentBatchToLoad.add(oid);
|
currentBatchToLoad.add(oid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is it time to load from JDBC the currentBatchToLoad?
|
// Is it time to load from JDBC the currentBatchToLoad?
|
||||||
if ((currentBatchToLoad.size() == this.batchSize)
|
if ((currentBatchToLoad.size() == this.batchSize) || ((i + 1) == objects.size())) {
|
||||||
|| ((i + 1) == objects.size())) {
|
|
||||||
if (currentBatchToLoad.size() > 0) {
|
if (currentBatchToLoad.size() > 0) {
|
||||||
Map<ObjectIdentity, Acl> loadedBatch = lookupObjectIdentities(
|
Map<ObjectIdentity, Acl> loadedBatch = lookupObjectIdentities(currentBatchToLoad, sids);
|
||||||
currentBatchToLoad, sids);
|
|
||||||
|
|
||||||
// Add loaded batch (all elements 100% initialized) to results
|
// Add loaded batch (all elements 100% initialized) to results
|
||||||
result.putAll(loadedBatch);
|
result.putAll(loadedBatch);
|
||||||
|
|
||||||
// Add the loaded batch to the cache
|
// Add the loaded batch to the cache
|
||||||
|
|
||||||
for (Acl loadedAcl : loadedBatch.values()) {
|
for (Acl loadedAcl : loadedBatch.values()) {
|
||||||
aclCache.putInCache((AclImpl) loadedAcl);
|
this.aclCache.putInCache((AclImpl) loadedAcl);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentBatchToLoad.clear();
|
currentBatchToLoad.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,39 +316,20 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
* <p>
|
* <p>
|
||||||
* This subclass is required to return fully valid <code>Acl</code>s, including
|
* This subclass is required to return fully valid <code>Acl</code>s, including
|
||||||
* properly-configured parent ACLs.
|
* properly-configured parent ACLs.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
private Map<ObjectIdentity, Acl> lookupObjectIdentities(
|
private Map<ObjectIdentity, Acl> lookupObjectIdentities(final Collection<ObjectIdentity> objectIdentities,
|
||||||
final Collection<ObjectIdentity> objectIdentities, List<Sid> sids) {
|
List<Sid> sids) {
|
||||||
Assert.notEmpty(objectIdentities, "Must provide identities to lookup");
|
Assert.notEmpty(objectIdentities, "Must provide identities to lookup");
|
||||||
|
|
||||||
final Map<Serializable, Acl> acls = new HashMap<>(); // contains
|
// contains Acls with StubAclParents
|
||||||
// Acls
|
Map<Serializable, Acl> acls = new HashMap<>();
|
||||||
// with
|
|
||||||
// StubAclParents
|
|
||||||
|
|
||||||
// Make the "acls" map contain all requested objectIdentities
|
// Make the "acls" map contain all requested objectIdentities
|
||||||
// (including markers to each parent in the hierarchy)
|
// (including markers to each parent in the hierarchy)
|
||||||
String sql = computeRepeatingSql(lookupObjectIdentitiesWhereClause,
|
String sql = computeRepeatingSql(this.lookupObjectIdentitiesWhereClause, objectIdentities.size());
|
||||||
objectIdentities.size());
|
|
||||||
|
|
||||||
Set<Long> parentsToLookup = jdbcTemplate.query(sql,
|
Set<Long> parentsToLookup = this.jdbcTemplate.query(sql,
|
||||||
ps -> {
|
(ps) -> setupLookupObjectIdentitiesStatement(ps, objectIdentities), new ProcessResultSet(acls, sids));
|
||||||
int i = 0;
|
|
||||||
for (ObjectIdentity oid : objectIdentities) {
|
|
||||||
// Determine prepared statement values for this iteration
|
|
||||||
String type = oid.getType();
|
|
||||||
|
|
||||||
// No need to check for nulls, as guaranteed non-null by
|
|
||||||
// ObjectIdentity.getIdentifier() interface contract
|
|
||||||
String identifier = oid.getIdentifier().toString();
|
|
||||||
|
|
||||||
// Inject values
|
|
||||||
ps.setString((2 * i) + 1, identifier);
|
|
||||||
ps.setString((2 * i) + 2, type);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}, new ProcessResultSet(acls, sids));
|
|
||||||
|
|
||||||
// Lookup the parents, now that our JdbcTemplate has released the database
|
// Lookup the parents, now that our JdbcTemplate has released the database
|
||||||
// connection (SEC-547)
|
// connection (SEC-547)
|
||||||
@@ -404,13 +339,9 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
|
|
||||||
// Finally, convert our "acls" containing StubAclParents into true Acls
|
// Finally, convert our "acls" containing StubAclParents into true Acls
|
||||||
Map<ObjectIdentity, Acl> resultMap = new HashMap<>();
|
Map<ObjectIdentity, Acl> resultMap = new HashMap<>();
|
||||||
|
|
||||||
for (Acl inputAcl : acls.values()) {
|
for (Acl inputAcl : acls.values()) {
|
||||||
Assert.isInstanceOf(AclImpl.class, inputAcl,
|
Assert.isInstanceOf(AclImpl.class, inputAcl, "Map should have contained an AclImpl");
|
||||||
"Map should have contained an AclImpl");
|
Assert.isInstanceOf(Long.class, ((AclImpl) inputAcl).getId(), "Acl.getId() must be Long");
|
||||||
Assert.isInstanceOf(Long.class, ((AclImpl) inputAcl).getId(),
|
|
||||||
"Acl.getId() must be Long");
|
|
||||||
|
|
||||||
Acl result = convert(acls, (Long) ((AclImpl) inputAcl).getId());
|
Acl result = convert(acls, (Long) ((AclImpl) inputAcl).getId());
|
||||||
resultMap.put(result.getObjectIdentity(), result);
|
resultMap.put(result.getObjectIdentity(), result);
|
||||||
}
|
}
|
||||||
@@ -418,15 +349,31 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
return resultMap;
|
return resultMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setupLookupObjectIdentitiesStatement(PreparedStatement ps, Collection<ObjectIdentity> objectIdentities)
|
||||||
|
throws SQLException {
|
||||||
|
int i = 0;
|
||||||
|
for (ObjectIdentity oid : objectIdentities) {
|
||||||
|
// Determine prepared statement values for this iteration
|
||||||
|
String type = oid.getType();
|
||||||
|
|
||||||
|
// No need to check for nulls, as guaranteed non-null by
|
||||||
|
// ObjectIdentity.getIdentifier() interface contract
|
||||||
|
String identifier = oid.getIdentifier().toString();
|
||||||
|
|
||||||
|
// Inject values
|
||||||
|
ps.setString((2 * i) + 1, identifier);
|
||||||
|
ps.setString((2 * i) + 2, type);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The final phase of converting the <code>Map</code> of <code>AclImpl</code>
|
* The final phase of converting the <code>Map</code> of <code>AclImpl</code>
|
||||||
* instances which contain <code>StubAclParent</code>s into proper, valid
|
* instances which contain <code>StubAclParent</code>s into proper, valid
|
||||||
* <code>AclImpl</code>s with correct ACL parents.
|
* <code>AclImpl</code>s with correct ACL parents.
|
||||||
*
|
|
||||||
* @param inputMap the unconverted <code>AclImpl</code>s
|
* @param inputMap the unconverted <code>AclImpl</code>s
|
||||||
* @param currentIdentity the current<code>Acl</code> that we wish to convert (this
|
* @param currentIdentity the current<code>Acl</code> that we wish to convert (this
|
||||||
* may be
|
* may be
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
private AclImpl convert(Map<Serializable, Acl> inputMap, Long currentIdentity) {
|
private AclImpl convert(Map<Serializable, Acl> inputMap, Long currentIdentity) {
|
||||||
Assert.notEmpty(inputMap, "InputMap required");
|
Assert.notEmpty(inputMap, "InputMap required");
|
||||||
@@ -434,8 +381,7 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
|
|
||||||
// Retrieve this Acl from the InputMap
|
// Retrieve this Acl from the InputMap
|
||||||
Acl uncastAcl = inputMap.get(currentIdentity);
|
Acl uncastAcl = inputMap.get(currentIdentity);
|
||||||
Assert.isInstanceOf(AclImpl.class, uncastAcl,
|
Assert.isInstanceOf(AclImpl.class, uncastAcl, "The inputMap contained a non-AclImpl");
|
||||||
"The inputMap contained a non-AclImpl");
|
|
||||||
|
|
||||||
AclImpl inputAcl = (AclImpl) uncastAcl;
|
AclImpl inputAcl = (AclImpl) uncastAcl;
|
||||||
|
|
||||||
@@ -448,9 +394,8 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now we have the parent (if there is one), create the true AclImpl
|
// Now we have the parent (if there is one), create the true AclImpl
|
||||||
AclImpl result = new AclImpl(inputAcl.getObjectIdentity(),
|
AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), inputAcl.getId(), this.aclAuthorizationStrategy,
|
||||||
inputAcl.getId(), aclAuthorizationStrategy, grantingStrategy,
|
this.grantingStrategy, parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner());
|
||||||
parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner());
|
|
||||||
|
|
||||||
// Copy the "aces" from the input to the destination
|
// Copy the "aces" from the input to the destination
|
||||||
|
|
||||||
@@ -477,7 +422,6 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a particular implementation of {@link Sid} depending on the arguments.
|
* Creates a particular implementation of {@link Sid} depending on the arguments.
|
||||||
*
|
|
||||||
* @param sid the name of the sid representing its unique identifier. In typical ACL
|
* @param sid the name of the sid representing its unique identifier. In typical ACL
|
||||||
* database schema it's located in table {@code acl_sid} table, {@code sid} column.
|
* database schema it's located in table {@code acl_sid} table, {@code sid} column.
|
||||||
* @param isPrincipal whether it's a user or granted authority like role
|
* @param isPrincipal whether it's a user or granted authority like role
|
||||||
@@ -487,16 +431,13 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
if (isPrincipal) {
|
if (isPrincipal) {
|
||||||
return new PrincipalSid(sid);
|
return new PrincipalSid(sid);
|
||||||
}
|
}
|
||||||
else {
|
return new GrantedAuthoritySid(sid);
|
||||||
return new GrantedAuthoritySid(sid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@code PermissionFactory} instance which will be used to convert loaded
|
* Sets the {@code PermissionFactory} instance which will be used to convert loaded
|
||||||
* permission data values to {@code Permission}s. A {@code DefaultPermissionFactory}
|
* permission data values to {@code Permission}s. A {@code DefaultPermissionFactory}
|
||||||
* will be used by default.
|
* will be used by default.
|
||||||
*
|
|
||||||
* @param permissionFactory
|
* @param permissionFactory
|
||||||
*/
|
*/
|
||||||
public final void setPermissionFactory(PermissionFactory permissionFactory) {
|
public final void setPermissionFactory(PermissionFactory permissionFactory) {
|
||||||
@@ -510,7 +451,6 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
/**
|
/**
|
||||||
* The SQL for the select clause. If customizing in order to modify column names,
|
* The SQL for the select clause. If customizing in order to modify column names,
|
||||||
* schema etc, the other SQL customization fields must also be set to match.
|
* schema etc, the other SQL customization fields must also be set to match.
|
||||||
*
|
|
||||||
* @param selectClause the select clause, which defaults to
|
* @param selectClause the select clause, which defaults to
|
||||||
* {@link #DEFAULT_SELECT_CLAUSE}.
|
* {@link #DEFAULT_SELECT_CLAUSE}.
|
||||||
*/
|
*/
|
||||||
@@ -528,8 +468,7 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
/**
|
/**
|
||||||
* The SQL for the where clause used in the <tt>lookupObjectIdentities</tt> method.
|
* The SQL for the where clause used in the <tt>lookupObjectIdentities</tt> method.
|
||||||
*/
|
*/
|
||||||
public final void setLookupObjectIdentitiesWhereClause(
|
public final void setLookupObjectIdentitiesWhereClause(String lookupObjectIdentitiesWhereClause) {
|
||||||
String lookupObjectIdentitiesWhereClause) {
|
|
||||||
this.lookupObjectIdentitiesWhereClause = lookupObjectIdentitiesWhereClause;
|
this.lookupObjectIdentitiesWhereClause = lookupObjectIdentitiesWhereClause;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -542,8 +481,9 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
|
|
||||||
public final void setAclClassIdSupported(boolean aclClassIdSupported) {
|
public final void setAclClassIdSupported(boolean aclClassIdSupported) {
|
||||||
if (aclClassIdSupported) {
|
if (aclClassIdSupported) {
|
||||||
Assert.isTrue(this.selectClause.equals(DEFAULT_SELECT_CLAUSE), "Cannot set aclClassIdSupported and override the select clause; "
|
Assert.isTrue(this.selectClause.equals(DEFAULT_SELECT_CLAUSE),
|
||||||
+ "just override the select clause");
|
"Cannot set aclClassIdSupported and override the select clause; "
|
||||||
|
+ "just override the select clause");
|
||||||
this.selectClause = DEFAULT_ACL_CLASS_ID_SELECT_CLAUSE;
|
this.selectClause = DEFAULT_ACL_CLASS_ID_SELECT_CLAUSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -552,11 +492,10 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
this.aclClassIdUtils = new AclClassIdUtils(conversionService);
|
this.aclClassIdUtils = new AclClassIdUtils(conversionService);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Inner Classes
|
|
||||||
// ==================================================================================================
|
|
||||||
|
|
||||||
private class ProcessResultSet implements ResultSetExtractor<Set<Long>> {
|
private class ProcessResultSet implements ResultSetExtractor<Set<Long>> {
|
||||||
|
|
||||||
private final Map<Serializable, Acl> acls;
|
private final Map<Serializable, Acl> acls;
|
||||||
|
|
||||||
private final List<Sid> sids;
|
private final List<Sid> sids;
|
||||||
|
|
||||||
ProcessResultSet(Map<Serializable, Acl> acls, List<Sid> sids) {
|
ProcessResultSet(Map<Serializable, Acl> acls, List<Sid> sids) {
|
||||||
@@ -575,32 +514,32 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
* <tt>null</tt>)
|
* <tt>null</tt>)
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Set<Long> extractData(ResultSet rs) throws SQLException {
|
public Set<Long> extractData(ResultSet rs) throws SQLException {
|
||||||
Set<Long> parentIdsToLookup = new HashSet<>(); // Set of parent_id Longs
|
Set<Long> parentIdsToLookup = new HashSet<>(); // Set of parent_id Longs
|
||||||
|
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
// Convert current row into an Acl (albeit with a StubAclParent)
|
// Convert current row into an Acl (albeit with a StubAclParent)
|
||||||
convertCurrentResultIntoObject(acls, rs);
|
convertCurrentResultIntoObject(this.acls, rs);
|
||||||
|
|
||||||
// Figure out if this row means we need to lookup another parent
|
// Figure out if this row means we need to lookup another parent
|
||||||
long parentId = rs.getLong("parent_object");
|
long parentId = rs.getLong("parent_object");
|
||||||
|
|
||||||
if (parentId != 0) {
|
if (parentId != 0) {
|
||||||
// See if it's already in the "acls"
|
// See if it's already in the "acls"
|
||||||
if (acls.containsKey(parentId)) {
|
if (this.acls.containsKey(parentId)) {
|
||||||
continue; // skip this while iteration
|
continue; // skip this while iteration
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now try to find it in the cache
|
// Now try to find it in the cache
|
||||||
MutableAcl cached = aclCache.getFromCache(parentId);
|
MutableAcl cached = BasicLookupStrategy.this.aclCache.getFromCache(parentId);
|
||||||
|
if ((cached == null) || !cached.isSidLoaded(this.sids)) {
|
||||||
if ((cached == null) || !cached.isSidLoaded(sids)) {
|
|
||||||
parentIdsToLookup.add(parentId);
|
parentIdsToLookup.add(parentId);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Pop into the acls map, so our convert method doesn't
|
// Pop into the acls map, so our convert method doesn't
|
||||||
// need to deal with an unsynchronized AclCache
|
// need to deal with an unsynchronized AclCache
|
||||||
acls.put(cached.getId(), cached);
|
this.acls.put(cached.getId(), cached);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -612,15 +551,12 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
/**
|
/**
|
||||||
* Accepts the current <code>ResultSet</code> row, and converts it into an
|
* Accepts the current <code>ResultSet</code> row, and converts it into an
|
||||||
* <code>AclImpl</code> that contains a <code>StubAclParent</code>
|
* <code>AclImpl</code> that contains a <code>StubAclParent</code>
|
||||||
*
|
|
||||||
* @param acls the Map we should add the converted Acl to
|
* @param acls the Map we should add the converted Acl to
|
||||||
* @param rs the ResultSet focused on a current row
|
* @param rs the ResultSet focused on a current row
|
||||||
*
|
|
||||||
* @throws SQLException if something goes wrong converting values
|
* @throws SQLException if something goes wrong converting values
|
||||||
* @throws ConversionException if can't convert to the desired Java type
|
* @throws ConversionException if can't convert to the desired Java type
|
||||||
*/
|
*/
|
||||||
private void convertCurrentResultIntoObject(Map<Serializable, Acl> acls,
|
private void convertCurrentResultIntoObject(Map<Serializable, Acl> acls, ResultSet rs) throws SQLException {
|
||||||
ResultSet rs) throws SQLException {
|
|
||||||
Long id = rs.getLong("acl_id");
|
Long id = rs.getLong("acl_id");
|
||||||
|
|
||||||
// If we already have an ACL for this ID, just create the ACE
|
// If we already have an ACL for this ID, just create the ACE
|
||||||
@@ -629,11 +565,11 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
if (acl == null) {
|
if (acl == null) {
|
||||||
// Make an AclImpl and pop it into the Map
|
// Make an AclImpl and pop it into the Map
|
||||||
|
|
||||||
// If the Java type is a String, check to see if we can convert it to the target id type, e.g. UUID.
|
// If the Java type is a String, check to see if we can convert it to the
|
||||||
|
// target id type, e.g. UUID.
|
||||||
Serializable identifier = (Serializable) rs.getObject("object_id_identity");
|
Serializable identifier = (Serializable) rs.getObject("object_id_identity");
|
||||||
identifier = aclClassIdUtils.identifierFrom(identifier, rs);
|
identifier = BasicLookupStrategy.this.aclClassIdUtils.identifierFrom(identifier, rs);
|
||||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(
|
ObjectIdentity objectIdentity = new ObjectIdentityImpl(rs.getString("class"), identifier);
|
||||||
rs.getString("class"), identifier);
|
|
||||||
|
|
||||||
Acl parentAcl = null;
|
Acl parentAcl = null;
|
||||||
long parentAclId = rs.getLong("parent_object");
|
long parentAclId = rs.getLong("parent_object");
|
||||||
@@ -643,11 +579,10 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean entriesInheriting = rs.getBoolean("entries_inheriting");
|
boolean entriesInheriting = rs.getBoolean("entries_inheriting");
|
||||||
Sid owner = createSid(rs.getBoolean("acl_principal"),
|
Sid owner = createSid(rs.getBoolean("acl_principal"), rs.getString("acl_sid"));
|
||||||
rs.getString("acl_sid"));
|
|
||||||
|
|
||||||
acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy,
|
acl = new AclImpl(objectIdentity, id, BasicLookupStrategy.this.aclAuthorizationStrategy,
|
||||||
grantingStrategy, parentAcl, null, entriesInheriting, owner);
|
BasicLookupStrategy.this.grantingStrategy, parentAcl, null, entriesInheriting, owner);
|
||||||
|
|
||||||
acls.put(id, acl);
|
acls.put(id, acl);
|
||||||
}
|
}
|
||||||
@@ -657,17 +592,16 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
// ACE_SID)
|
// ACE_SID)
|
||||||
if (rs.getString("ace_sid") != null) {
|
if (rs.getString("ace_sid") != null) {
|
||||||
Long aceId = rs.getLong("ace_id");
|
Long aceId = rs.getLong("ace_id");
|
||||||
Sid recipient = createSid(rs.getBoolean("ace_principal"),
|
Sid recipient = createSid(rs.getBoolean("ace_principal"), rs.getString("ace_sid"));
|
||||||
rs.getString("ace_sid"));
|
|
||||||
|
|
||||||
int mask = rs.getInt("mask");
|
int mask = rs.getInt("mask");
|
||||||
Permission permission = permissionFactory.buildFromMask(mask);
|
Permission permission = BasicLookupStrategy.this.permissionFactory.buildFromMask(mask);
|
||||||
boolean granting = rs.getBoolean("granting");
|
boolean granting = rs.getBoolean("granting");
|
||||||
boolean auditSuccess = rs.getBoolean("audit_success");
|
boolean auditSuccess = rs.getBoolean("audit_success");
|
||||||
boolean auditFailure = rs.getBoolean("audit_failure");
|
boolean auditFailure = rs.getBoolean("audit_failure");
|
||||||
|
|
||||||
AccessControlEntryImpl ace = new AccessControlEntryImpl(aceId, acl,
|
AccessControlEntryImpl ace = new AccessControlEntryImpl(aceId, acl, recipient, permission, granting,
|
||||||
recipient, permission, granting, auditSuccess, auditFailure);
|
auditSuccess, auditFailure);
|
||||||
|
|
||||||
// Field acesField = FieldUtils.getField(AclImpl.class, "aces");
|
// Field acesField = FieldUtils.getField(AclImpl.class, "aces");
|
||||||
List<AccessControlEntryImpl> aces = readAces((AclImpl) acl);
|
List<AccessControlEntryImpl> aces = readAces((AclImpl) acl);
|
||||||
@@ -678,47 +612,57 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class StubAclParent implements Acl {
|
private static class StubAclParent implements Acl {
|
||||||
|
|
||||||
private final Long id;
|
private final Long id;
|
||||||
|
|
||||||
StubAclParent(Long id) {
|
StubAclParent(Long id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Long getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public List<AccessControlEntry> getEntries() {
|
public List<AccessControlEntry> getEntries() {
|
||||||
throw new UnsupportedOperationException("Stub only");
|
throw new UnsupportedOperationException("Stub only");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getId() {
|
@Override
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ObjectIdentity getObjectIdentity() {
|
public ObjectIdentity getObjectIdentity() {
|
||||||
throw new UnsupportedOperationException("Stub only");
|
throw new UnsupportedOperationException("Stub only");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Sid getOwner() {
|
public Sid getOwner() {
|
||||||
throw new UnsupportedOperationException("Stub only");
|
throw new UnsupportedOperationException("Stub only");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Acl getParentAcl() {
|
public Acl getParentAcl() {
|
||||||
throw new UnsupportedOperationException("Stub only");
|
throw new UnsupportedOperationException("Stub only");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isEntriesInheriting() {
|
public boolean isEntriesInheriting() {
|
||||||
throw new UnsupportedOperationException("Stub only");
|
throw new UnsupportedOperationException("Stub only");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGranted(List<Permission> permission, List<Sid> sids,
|
@Override
|
||||||
boolean administrativeMode) throws NotFoundException,
|
public boolean isGranted(List<Permission> permission, List<Sid> sids, boolean administrativeMode)
|
||||||
UnloadedSidException {
|
throws NotFoundException, UnloadedSidException {
|
||||||
throw new UnsupportedOperationException("Stub only");
|
throw new UnsupportedOperationException("Stub only");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isSidLoaded(List<Sid> sids) {
|
public boolean isSidLoaded(List<Sid> sids) {
|
||||||
throw new UnsupportedOperationException("Stub only");
|
throw new UnsupportedOperationException("Stub only");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,9 +13,12 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.jdbc;
|
package org.springframework.security.acls.jdbc;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -24,6 +27,7 @@ import javax.sql.DataSource;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.jdbc.core.JdbcOperations;
|
import org.springframework.jdbc.core.JdbcOperations;
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
@@ -45,34 +49,37 @@ import org.springframework.util.Assert;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class JdbcAclService implements AclService {
|
public class JdbcAclService implements AclService {
|
||||||
// ~ Static fields/initializers
|
|
||||||
// =====================================================================================
|
|
||||||
|
|
||||||
protected static final Log log = LogFactory.getLog(JdbcAclService.class);
|
protected static final Log log = LogFactory.getLog(JdbcAclService.class);
|
||||||
|
|
||||||
private static final String DEFAULT_SELECT_ACL_CLASS_COLUMNS = "class.class as class";
|
private static final String DEFAULT_SELECT_ACL_CLASS_COLUMNS = "class.class as class";
|
||||||
private static final String DEFAULT_SELECT_ACL_CLASS_COLUMNS_WITH_ID_TYPE = DEFAULT_SELECT_ACL_CLASS_COLUMNS + ", class.class_id_type as class_id_type";
|
|
||||||
private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL = "select obj.object_id_identity as obj_id, " + DEFAULT_SELECT_ACL_CLASS_COLUMNS
|
private static final String DEFAULT_SELECT_ACL_CLASS_COLUMNS_WITH_ID_TYPE = DEFAULT_SELECT_ACL_CLASS_COLUMNS
|
||||||
+ " from acl_object_identity obj, acl_object_identity parent, acl_class class "
|
+ ", class.class_id_type as class_id_type";
|
||||||
+ "where obj.parent_object = parent.id and obj.object_id_class = class.id "
|
|
||||||
+ "and parent.object_id_identity = ? and parent.object_id_class = ("
|
private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL = "select obj.object_id_identity as obj_id, "
|
||||||
+ "select id FROM acl_class where acl_class.class = ?)";
|
+ DEFAULT_SELECT_ACL_CLASS_COLUMNS
|
||||||
private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE = "select obj.object_id_identity as obj_id, " + DEFAULT_SELECT_ACL_CLASS_COLUMNS_WITH_ID_TYPE
|
|
||||||
+ " from acl_object_identity obj, acl_object_identity parent, acl_class class "
|
+ " from acl_object_identity obj, acl_object_identity parent, acl_class class "
|
||||||
+ "where obj.parent_object = parent.id and obj.object_id_class = class.id "
|
+ "where obj.parent_object = parent.id and obj.object_id_class = class.id "
|
||||||
+ "and parent.object_id_identity = ? and parent.object_id_class = ("
|
+ "and parent.object_id_identity = ? and parent.object_id_class = ("
|
||||||
+ "select id FROM acl_class where acl_class.class = ?)";
|
+ "select id FROM acl_class where acl_class.class = ?)";
|
||||||
|
|
||||||
// ~ Instance fields
|
private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE = "select obj.object_id_identity as obj_id, "
|
||||||
// ================================================================================================
|
+ DEFAULT_SELECT_ACL_CLASS_COLUMNS_WITH_ID_TYPE
|
||||||
|
+ " from acl_object_identity obj, acl_object_identity parent, acl_class class "
|
||||||
|
+ "where obj.parent_object = parent.id and obj.object_id_class = class.id "
|
||||||
|
+ "and parent.object_id_identity = ? and parent.object_id_class = ("
|
||||||
|
+ "select id FROM acl_class where acl_class.class = ?)";
|
||||||
|
|
||||||
protected final JdbcOperations jdbcOperations;
|
protected final JdbcOperations jdbcOperations;
|
||||||
private final LookupStrategy lookupStrategy;
|
|
||||||
private boolean aclClassIdSupported;
|
|
||||||
private String findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL;
|
|
||||||
private AclClassIdUtils aclClassIdUtils;
|
|
||||||
|
|
||||||
// ~ Constructors
|
private final LookupStrategy lookupStrategy;
|
||||||
// ===================================================================================================
|
|
||||||
|
private boolean aclClassIdSupported;
|
||||||
|
|
||||||
|
private String findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL;
|
||||||
|
|
||||||
|
private AclClassIdUtils aclClassIdUtils;
|
||||||
|
|
||||||
public JdbcAclService(DataSource dataSource, LookupStrategy lookupStrategy) {
|
public JdbcAclService(DataSource dataSource, LookupStrategy lookupStrategy) {
|
||||||
this(new JdbcTemplate(dataSource), lookupStrategy);
|
this(new JdbcTemplate(dataSource), lookupStrategy);
|
||||||
@@ -86,64 +93,55 @@ public class JdbcAclService implements AclService {
|
|||||||
this.aclClassIdUtils = new AclClassIdUtils();
|
this.aclClassIdUtils = new AclClassIdUtils();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
@Override
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
|
public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
|
||||||
Object[] args = { parentIdentity.getIdentifier().toString(), parentIdentity.getType() };
|
Object[] args = { parentIdentity.getIdentifier().toString(), parentIdentity.getType() };
|
||||||
List<ObjectIdentity> objects = jdbcOperations.query(findChildrenSql, args,
|
List<ObjectIdentity> objects = this.jdbcOperations.query(this.findChildrenSql, args,
|
||||||
(rs, rowNum) -> {
|
(rs, rowNum) -> mapObjectIdentityRow(rs));
|
||||||
String javaType = rs.getString("class");
|
return (!objects.isEmpty()) ? objects : null;
|
||||||
Serializable identifier = (Serializable) rs.getObject("obj_id");
|
|
||||||
identifier = aclClassIdUtils.identifierFrom(identifier, rs);
|
|
||||||
return new ObjectIdentityImpl(javaType, identifier);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (objects.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return objects;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Acl readAclById(ObjectIdentity object, List<Sid> sids)
|
private ObjectIdentity mapObjectIdentityRow(ResultSet rs) throws SQLException {
|
||||||
throws NotFoundException {
|
String javaType = rs.getString("class");
|
||||||
|
Serializable identifier = (Serializable) rs.getObject("obj_id");
|
||||||
|
identifier = this.aclClassIdUtils.identifierFrom(identifier, rs);
|
||||||
|
return new ObjectIdentityImpl(javaType, identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Acl readAclById(ObjectIdentity object, List<Sid> sids) throws NotFoundException {
|
||||||
Map<ObjectIdentity, Acl> map = readAclsById(Collections.singletonList(object), sids);
|
Map<ObjectIdentity, Acl> map = readAclsById(Collections.singletonList(object), sids);
|
||||||
Assert.isTrue(map.containsKey(object),
|
Assert.isTrue(map.containsKey(object),
|
||||||
() -> "There should have been an Acl entry for ObjectIdentity " + object);
|
() -> "There should have been an Acl entry for ObjectIdentity " + object);
|
||||||
|
|
||||||
return map.get(object);
|
return map.get(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Acl readAclById(ObjectIdentity object) throws NotFoundException {
|
public Acl readAclById(ObjectIdentity object) throws NotFoundException {
|
||||||
return readAclById(object, null);
|
return readAclById(object, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects)
|
@Override
|
||||||
throws NotFoundException {
|
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects) throws NotFoundException {
|
||||||
return readAclsById(objects, null);
|
return readAclsById(objects, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects,
|
@Override
|
||||||
List<Sid> sids) throws NotFoundException {
|
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids)
|
||||||
Map<ObjectIdentity, Acl> result = lookupStrategy.readAclsById(objects, sids);
|
throws NotFoundException {
|
||||||
|
Map<ObjectIdentity, Acl> result = this.lookupStrategy.readAclsById(objects, sids);
|
||||||
// Check every requested object identity was found (throw NotFoundException if
|
// Check every requested object identity was found (throw NotFoundException if
|
||||||
// needed)
|
// needed)
|
||||||
for (ObjectIdentity oid : objects) {
|
for (ObjectIdentity oid : objects) {
|
||||||
if (!result.containsKey(oid)) {
|
if (!result.containsKey(oid)) {
|
||||||
throw new NotFoundException(
|
throw new NotFoundException("Unable to find ACL information for object identity '" + oid + "'");
|
||||||
"Unable to find ACL information for object identity '" + oid
|
|
||||||
+ "'");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows customization of the SQL query used to find child object identities.
|
* Allows customization of the SQL query used to find child object identities.
|
||||||
*
|
|
||||||
* @param findChildrenSql
|
* @param findChildrenSql
|
||||||
*/
|
*/
|
||||||
public void setFindChildrenQuery(String findChildrenSql) {
|
public void setFindChildrenQuery(String findChildrenSql) {
|
||||||
@@ -156,7 +154,8 @@ public class JdbcAclService implements AclService {
|
|||||||
// Change the default children select if it hasn't been overridden
|
// Change the default children select if it hasn't been overridden
|
||||||
if (this.findChildrenSql.equals(DEFAULT_SELECT_ACL_WITH_PARENT_SQL)) {
|
if (this.findChildrenSql.equals(DEFAULT_SELECT_ACL_WITH_PARENT_SQL)) {
|
||||||
this.findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE;
|
this.findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
log.debug("Find children statement has already been overridden, so not overridding the default");
|
log.debug("Find children statement has already been overridden, so not overridding the default");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,6 +166,7 @@ public class JdbcAclService implements AclService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isAclClassIdSupported() {
|
protected boolean isAclClassIdSupported() {
|
||||||
return aclClassIdSupported;
|
return this.aclClassIdSupported;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+72
-102
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.jdbc;
|
package org.springframework.security.acls.jdbc;
|
||||||
|
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
@@ -58,55 +59,58 @@ import org.springframework.util.Assert;
|
|||||||
* @author Johannes Zlattinger
|
* @author Johannes Zlattinger
|
||||||
*/
|
*/
|
||||||
public class JdbcMutableAclService extends JdbcAclService implements MutableAclService {
|
public class JdbcMutableAclService extends JdbcAclService implements MutableAclService {
|
||||||
|
|
||||||
private static final String DEFAULT_INSERT_INTO_ACL_CLASS = "insert into acl_class (class) values (?)";
|
private static final String DEFAULT_INSERT_INTO_ACL_CLASS = "insert into acl_class (class) values (?)";
|
||||||
|
|
||||||
private static final String DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID = "insert into acl_class (class, class_id_type) values (?, ?)";
|
private static final String DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID = "insert into acl_class (class, class_id_type) values (?, ?)";
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
private boolean foreignKeysInDatabase = true;
|
private boolean foreignKeysInDatabase = true;
|
||||||
|
|
||||||
private final AclCache aclCache;
|
private final AclCache aclCache;
|
||||||
|
|
||||||
private String deleteEntryByObjectIdentityForeignKey = "delete from acl_entry where acl_object_identity=?";
|
private String deleteEntryByObjectIdentityForeignKey = "delete from acl_entry where acl_object_identity=?";
|
||||||
|
|
||||||
private String deleteObjectIdentityByPrimaryKey = "delete from acl_object_identity where id=?";
|
private String deleteObjectIdentityByPrimaryKey = "delete from acl_object_identity where id=?";
|
||||||
|
|
||||||
private String classIdentityQuery = "call identity()";
|
private String classIdentityQuery = "call identity()";
|
||||||
|
|
||||||
private String sidIdentityQuery = "call identity()";
|
private String sidIdentityQuery = "call identity()";
|
||||||
|
|
||||||
private String insertClass = DEFAULT_INSERT_INTO_ACL_CLASS;
|
private String insertClass = DEFAULT_INSERT_INTO_ACL_CLASS;
|
||||||
|
|
||||||
private String insertEntry = "insert into acl_entry "
|
private String insertEntry = "insert into acl_entry "
|
||||||
+ "(acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure)"
|
+ "(acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure)"
|
||||||
+ "values (?, ?, ?, ?, ?, ?, ?)";
|
+ "values (?, ?, ?, ?, ?, ?, ?)";
|
||||||
|
|
||||||
private String insertObjectIdentity = "insert into acl_object_identity "
|
private String insertObjectIdentity = "insert into acl_object_identity "
|
||||||
+ "(object_id_class, object_id_identity, owner_sid, entries_inheriting) "
|
+ "(object_id_class, object_id_identity, owner_sid, entries_inheriting) " + "values (?, ?, ?, ?)";
|
||||||
+ "values (?, ?, ?, ?)";
|
|
||||||
private String insertSid = "insert into acl_sid (principal, sid) values (?, ?)";
|
private String insertSid = "insert into acl_sid (principal, sid) values (?, ?)";
|
||||||
|
|
||||||
private String selectClassPrimaryKey = "select id from acl_class where class=?";
|
private String selectClassPrimaryKey = "select id from acl_class where class=?";
|
||||||
|
|
||||||
private String selectObjectIdentityPrimaryKey = "select acl_object_identity.id from acl_object_identity, acl_class "
|
private String selectObjectIdentityPrimaryKey = "select acl_object_identity.id from acl_object_identity, acl_class "
|
||||||
+ "where acl_object_identity.object_id_class = acl_class.id and acl_class.class=? "
|
+ "where acl_object_identity.object_id_class = acl_class.id and acl_class.class=? "
|
||||||
+ "and acl_object_identity.object_id_identity = ?";
|
+ "and acl_object_identity.object_id_identity = ?";
|
||||||
|
|
||||||
private String selectSidPrimaryKey = "select id from acl_sid where principal=? and sid=?";
|
private String selectSidPrimaryKey = "select id from acl_sid where principal=? and sid=?";
|
||||||
|
|
||||||
private String updateObjectIdentity = "update acl_object_identity set "
|
private String updateObjectIdentity = "update acl_object_identity set "
|
||||||
+ "parent_object = ?, owner_sid = ?, entries_inheriting = ?"
|
+ "parent_object = ?, owner_sid = ?, entries_inheriting = ?" + " where id = ?";
|
||||||
+ " where id = ?";
|
|
||||||
|
|
||||||
// ~ Constructors
|
public JdbcMutableAclService(DataSource dataSource, LookupStrategy lookupStrategy, AclCache aclCache) {
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
public JdbcMutableAclService(DataSource dataSource, LookupStrategy lookupStrategy,
|
|
||||||
AclCache aclCache) {
|
|
||||||
super(dataSource, lookupStrategy);
|
super(dataSource, lookupStrategy);
|
||||||
Assert.notNull(aclCache, "AclCache required");
|
Assert.notNull(aclCache, "AclCache required");
|
||||||
this.aclCache = aclCache;
|
this.aclCache = aclCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
@Override
|
||||||
// ========================================================================================================
|
public MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException {
|
||||||
|
|
||||||
public MutableAcl createAcl(ObjectIdentity objectIdentity)
|
|
||||||
throws AlreadyExistsException {
|
|
||||||
Assert.notNull(objectIdentity, "Object Identity required");
|
Assert.notNull(objectIdentity, "Object Identity required");
|
||||||
|
|
||||||
// Check this object identity hasn't already been persisted
|
// Check this object identity hasn't already been persisted
|
||||||
if (retrieveObjectIdentityPrimaryKey(objectIdentity) != null) {
|
if (retrieveObjectIdentityPrimaryKey(objectIdentity) != null) {
|
||||||
throw new AlreadyExistsException("Object identity '" + objectIdentity
|
throw new AlreadyExistsException("Object identity '" + objectIdentity + "' already exists");
|
||||||
+ "' already exists");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to retrieve the current principal, in order to know who "owns" this ACL
|
// Need to retrieve the current principal, in order to know who "owns" this ACL
|
||||||
@@ -128,22 +132,23 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
/**
|
/**
|
||||||
* Creates a new row in acl_entry for every ACE defined in the passed MutableAcl
|
* Creates a new row in acl_entry for every ACE defined in the passed MutableAcl
|
||||||
* object.
|
* object.
|
||||||
*
|
|
||||||
* @param acl containing the ACEs to insert
|
* @param acl containing the ACEs to insert
|
||||||
*/
|
*/
|
||||||
protected void createEntries(final MutableAcl acl) {
|
protected void createEntries(final MutableAcl acl) {
|
||||||
if (acl.getEntries().isEmpty()) {
|
if (acl.getEntries().isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
jdbcOperations.batchUpdate(insertEntry, new BatchPreparedStatementSetter() {
|
this.jdbcOperations.batchUpdate(this.insertEntry, new BatchPreparedStatementSetter() {
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getBatchSize() {
|
public int getBatchSize() {
|
||||||
return acl.getEntries().size();
|
return acl.getEntries().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setValues(PreparedStatement stmt, int i) throws SQLException {
|
public void setValues(PreparedStatement stmt, int i) throws SQLException {
|
||||||
AccessControlEntry entry_ = acl.getEntries().get(i);
|
AccessControlEntry entry_ = acl.getEntries().get(i);
|
||||||
Assert.isTrue(entry_ instanceof AccessControlEntryImpl,
|
Assert.isTrue(entry_ instanceof AccessControlEntryImpl, "Unknown ACE class");
|
||||||
"Unknown ACE class");
|
|
||||||
AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_;
|
AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_;
|
||||||
|
|
||||||
stmt.setLong(1, (Long) acl.getId());
|
stmt.setLong(1, (Long) acl.getId());
|
||||||
@@ -154,6 +159,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
stmt.setBoolean(6, entry.isAuditSuccess());
|
stmt.setBoolean(6, entry.isAuditSuccess());
|
||||||
stmt.setBoolean(7, entry.isAuditFailure());
|
stmt.setBoolean(7, entry.isAuditFailure());
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +167,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
* Creates an entry in the acl_object_identity table for the passed ObjectIdentity.
|
* Creates an entry in the acl_object_identity table for the passed ObjectIdentity.
|
||||||
* The Sid is also necessary, as acl_object_identity has defined the sid column as
|
* The Sid is also necessary, as acl_object_identity has defined the sid column as
|
||||||
* non-null.
|
* non-null.
|
||||||
*
|
|
||||||
* @param object to represent an acl_object_identity for
|
* @param object to represent an acl_object_identity for
|
||||||
* @param owner for the SID column (will be created if there is no acl_sid entry for
|
* @param owner for the SID column (will be created if there is no acl_sid entry for
|
||||||
* this particular Sid already)
|
* this particular Sid already)
|
||||||
@@ -169,22 +174,20 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
protected void createObjectIdentity(ObjectIdentity object, Sid owner) {
|
protected void createObjectIdentity(ObjectIdentity object, Sid owner) {
|
||||||
Long sidId = createOrRetrieveSidPrimaryKey(owner, true);
|
Long sidId = createOrRetrieveSidPrimaryKey(owner, true);
|
||||||
Long classId = createOrRetrieveClassPrimaryKey(object.getType(), true, object.getIdentifier().getClass());
|
Long classId = createOrRetrieveClassPrimaryKey(object.getType(), true, object.getIdentifier().getClass());
|
||||||
jdbcOperations.update(insertObjectIdentity, classId, object.getIdentifier().toString(), sidId,
|
this.jdbcOperations.update(this.insertObjectIdentity, classId, object.getIdentifier().toString(), sidId,
|
||||||
Boolean.TRUE);
|
Boolean.TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the primary key from {@code acl_class}, creating a new row if needed and
|
* Retrieves the primary key from {@code acl_class}, creating a new row if needed and
|
||||||
* the {@code allowCreate} property is {@code true}.
|
* the {@code allowCreate} property is {@code true}.
|
||||||
*
|
|
||||||
* @param type to find or create an entry for (often the fully-qualified class name)
|
* @param type to find or create an entry for (often the fully-qualified class name)
|
||||||
* @param allowCreate true if creation is permitted if not found
|
* @param allowCreate true if creation is permitted if not found
|
||||||
*
|
|
||||||
* @return the primary key or null if not found
|
* @return the primary key or null if not found
|
||||||
*/
|
*/
|
||||||
protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate, Class idType) {
|
protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate, Class idType) {
|
||||||
List<Long> classIds = jdbcOperations.queryForList(selectClassPrimaryKey,
|
List<Long> classIds = this.jdbcOperations.queryForList(this.selectClassPrimaryKey, new Object[] { type },
|
||||||
new Object[] { type }, Long.class);
|
Long.class);
|
||||||
|
|
||||||
if (!classIds.isEmpty()) {
|
if (!classIds.isEmpty()) {
|
||||||
return classIds.get(0);
|
return classIds.get(0);
|
||||||
@@ -192,13 +195,13 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
|
|
||||||
if (allowCreate) {
|
if (allowCreate) {
|
||||||
if (!isAclClassIdSupported()) {
|
if (!isAclClassIdSupported()) {
|
||||||
jdbcOperations.update(insertClass, type);
|
this.jdbcOperations.update(this.insertClass, type);
|
||||||
} else {
|
|
||||||
jdbcOperations.update(insertClass, type, idType.getCanonicalName());
|
|
||||||
}
|
}
|
||||||
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(),
|
else {
|
||||||
"Transaction must be running");
|
this.jdbcOperations.update(this.insertClass, type, idType.getCanonicalName());
|
||||||
return jdbcOperations.queryForObject(classIdentityQuery, Long.class);
|
}
|
||||||
|
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running");
|
||||||
|
return this.jdbcOperations.queryForObject(this.classIdentityQuery, Long.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -207,33 +210,23 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
/**
|
/**
|
||||||
* Retrieves the primary key from acl_sid, creating a new row if needed and the
|
* Retrieves the primary key from acl_sid, creating a new row if needed and the
|
||||||
* allowCreate property is true.
|
* allowCreate property is true.
|
||||||
*
|
|
||||||
* @param sid to find or create
|
* @param sid to find or create
|
||||||
* @param allowCreate true if creation is permitted if not found
|
* @param allowCreate true if creation is permitted if not found
|
||||||
*
|
|
||||||
* @return the primary key or null if not found
|
* @return the primary key or null if not found
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException if the <tt>Sid</tt> is not a recognized
|
* @throws IllegalArgumentException if the <tt>Sid</tt> is not a recognized
|
||||||
* implementation.
|
* implementation.
|
||||||
*/
|
*/
|
||||||
protected Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) {
|
protected Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) {
|
||||||
Assert.notNull(sid, "Sid required");
|
Assert.notNull(sid, "Sid required");
|
||||||
|
|
||||||
String sidName;
|
|
||||||
boolean sidIsPrincipal = true;
|
|
||||||
|
|
||||||
if (sid instanceof PrincipalSid) {
|
if (sid instanceof PrincipalSid) {
|
||||||
sidName = ((PrincipalSid) sid).getPrincipal();
|
String sidName = ((PrincipalSid) sid).getPrincipal();
|
||||||
|
return createOrRetrieveSidPrimaryKey(sidName, true, allowCreate);
|
||||||
}
|
}
|
||||||
else if (sid instanceof GrantedAuthoritySid) {
|
if (sid instanceof GrantedAuthoritySid) {
|
||||||
sidName = ((GrantedAuthoritySid) sid).getGrantedAuthority();
|
String sidName = ((GrantedAuthoritySid) sid).getGrantedAuthority();
|
||||||
sidIsPrincipal = false;
|
return createOrRetrieveSidPrimaryKey(sidName, false, allowCreate);
|
||||||
}
|
}
|
||||||
else {
|
throw new IllegalArgumentException("Unsupported implementation of Sid");
|
||||||
throw new IllegalArgumentException("Unsupported implementation of Sid");
|
|
||||||
}
|
|
||||||
|
|
||||||
return createOrRetrieveSidPrimaryKey(sidName, sidIsPrincipal, allowCreate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -244,32 +237,24 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
* @param allowCreate true if creation is permitted if not found
|
* @param allowCreate true if creation is permitted if not found
|
||||||
* @return the primary key or null if not found
|
* @return the primary key or null if not found
|
||||||
*/
|
*/
|
||||||
protected Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal,
|
protected Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal, boolean allowCreate) {
|
||||||
boolean allowCreate) {
|
List<Long> sidIds = this.jdbcOperations.queryForList(this.selectSidPrimaryKey,
|
||||||
|
new Object[] { sidIsPrincipal, sidName }, Long.class);
|
||||||
List<Long> sidIds = jdbcOperations.queryForList(selectSidPrimaryKey, new Object[] {
|
|
||||||
sidIsPrincipal, sidName }, Long.class);
|
|
||||||
|
|
||||||
if (!sidIds.isEmpty()) {
|
if (!sidIds.isEmpty()) {
|
||||||
return sidIds.get(0);
|
return sidIds.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allowCreate) {
|
if (allowCreate) {
|
||||||
jdbcOperations.update(insertSid, sidIsPrincipal, sidName);
|
this.jdbcOperations.update(this.insertSid, sidIsPrincipal, sidName);
|
||||||
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(),
|
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running");
|
||||||
"Transaction must be running");
|
return this.jdbcOperations.queryForObject(this.sidIdentityQuery, Long.class);
|
||||||
return jdbcOperations.queryForObject(sidIdentityQuery, Long.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren)
|
@Override
|
||||||
throws ChildrenExistException {
|
public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException {
|
||||||
Assert.notNull(objectIdentity, "Object Identity required");
|
Assert.notNull(objectIdentity, "Object Identity required");
|
||||||
Assert.notNull(objectIdentity.getIdentifier(),
|
Assert.notNull(objectIdentity.getIdentifier(), "Object Identity doesn't provide an identifier");
|
||||||
"Object Identity doesn't provide an identifier");
|
|
||||||
|
|
||||||
if (deleteChildren) {
|
if (deleteChildren) {
|
||||||
List<ObjectIdentity> children = findChildren(objectIdentity);
|
List<ObjectIdentity> children = findChildren(objectIdentity);
|
||||||
if (children != null) {
|
if (children != null) {
|
||||||
@@ -279,14 +264,13 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!foreignKeysInDatabase) {
|
if (!this.foreignKeysInDatabase) {
|
||||||
// We need to perform a manual verification for what a FK would normally
|
// We need to perform a manual verification for what a FK would normally
|
||||||
// do
|
// do. We generally don't do this, in the interests of deadlock management
|
||||||
// We generally don't do this, in the interests of deadlock management
|
|
||||||
List<ObjectIdentity> children = findChildren(objectIdentity);
|
List<ObjectIdentity> children = findChildren(objectIdentity);
|
||||||
if (children != null) {
|
if (children != null) {
|
||||||
throw new ChildrenExistException("Cannot delete '" + objectIdentity
|
throw new ChildrenExistException(
|
||||||
+ "' (has " + children.size() + " children)");
|
"Cannot delete '" + objectIdentity + "' (has " + children.size() + " children)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -300,17 +284,16 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
deleteObjectIdentity(oidPrimaryKey);
|
deleteObjectIdentity(oidPrimaryKey);
|
||||||
|
|
||||||
// Clear the cache
|
// Clear the cache
|
||||||
aclCache.evictFromCache(objectIdentity);
|
this.aclCache.evictFromCache(objectIdentity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all ACEs defined in the acl_entry table belonging to the presented
|
* Deletes all ACEs defined in the acl_entry table belonging to the presented
|
||||||
* ObjectIdentity primary key.
|
* ObjectIdentity primary key.
|
||||||
*
|
|
||||||
* @param oidPrimaryKey the rows in acl_entry to delete
|
* @param oidPrimaryKey the rows in acl_entry to delete
|
||||||
*/
|
*/
|
||||||
protected void deleteEntries(Long oidPrimaryKey) {
|
protected void deleteEntries(Long oidPrimaryKey) {
|
||||||
jdbcOperations.update(deleteEntryByObjectIdentityForeignKey, oidPrimaryKey);
|
this.jdbcOperations.update(this.deleteEntryByObjectIdentityForeignKey, oidPrimaryKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -319,27 +302,24 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
* <p>
|
* <p>
|
||||||
* We do not delete any entries from acl_class, even if no classes are using that
|
* We do not delete any entries from acl_class, even if no classes are using that
|
||||||
* class any longer. This is a deadlock avoidance approach.
|
* class any longer. This is a deadlock avoidance approach.
|
||||||
*
|
|
||||||
* @param oidPrimaryKey to delete the acl_object_identity
|
* @param oidPrimaryKey to delete the acl_object_identity
|
||||||
*/
|
*/
|
||||||
protected void deleteObjectIdentity(Long oidPrimaryKey) {
|
protected void deleteObjectIdentity(Long oidPrimaryKey) {
|
||||||
// Delete the acl_object_identity row
|
// Delete the acl_object_identity row
|
||||||
jdbcOperations.update(deleteObjectIdentityByPrimaryKey, oidPrimaryKey);
|
this.jdbcOperations.update(this.deleteObjectIdentityByPrimaryKey, oidPrimaryKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the primary key from the acl_object_identity table for the passed
|
* Retrieves the primary key from the acl_object_identity table for the passed
|
||||||
* ObjectIdentity. Unlike some other methods in this implementation, this method will
|
* ObjectIdentity. Unlike some other methods in this implementation, this method will
|
||||||
* NOT create a row (use {@link #createObjectIdentity(ObjectIdentity, Sid)} instead).
|
* NOT create a row (use {@link #createObjectIdentity(ObjectIdentity, Sid)} instead).
|
||||||
*
|
|
||||||
* @param oid to find
|
* @param oid to find
|
||||||
*
|
|
||||||
* @return the object identity or null if not found
|
* @return the object identity or null if not found
|
||||||
*/
|
*/
|
||||||
protected Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) {
|
protected Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) {
|
||||||
try {
|
try {
|
||||||
return jdbcOperations.queryForObject(selectObjectIdentityPrimaryKey, Long.class,
|
return this.jdbcOperations.queryForObject(this.selectObjectIdentityPrimaryKey, Long.class, oid.getType(),
|
||||||
oid.getType(), oid.getIdentifier().toString());
|
oid.getIdentifier().toString());
|
||||||
}
|
}
|
||||||
catch (DataAccessException notFound) {
|
catch (DataAccessException notFound) {
|
||||||
return null;
|
return null;
|
||||||
@@ -352,6 +332,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
* dirty state checking, or more likely use ORM capabilities for create, update and
|
* dirty state checking, or more likely use ORM capabilities for create, update and
|
||||||
* delete operations of {@link MutableAcl}.
|
* delete operations of {@link MutableAcl}.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException {
|
public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException {
|
||||||
Assert.notNull(acl.getId(), "Object Identity doesn't provide an identifier");
|
Assert.notNull(acl.getId(), "Object Identity doesn't provide an identifier");
|
||||||
|
|
||||||
@@ -380,37 +361,28 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
clearCacheIncludingChildren(child);
|
clearCacheIncludingChildren(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aclCache.evictFromCache(objectIdentity);
|
this.aclCache.evictFromCache(objectIdentity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates an existing acl_object_identity row, with new information presented in the
|
* Updates an existing acl_object_identity row, with new information presented in the
|
||||||
* passed MutableAcl object. Also will create an acl_sid entry if needed for the Sid
|
* passed MutableAcl object. Also will create an acl_sid entry if needed for the Sid
|
||||||
* that owns the MutableAcl.
|
* that owns the MutableAcl.
|
||||||
*
|
|
||||||
* @param acl to modify (a row must already exist in acl_object_identity)
|
* @param acl to modify (a row must already exist in acl_object_identity)
|
||||||
*
|
|
||||||
* @throws NotFoundException if the ACL could not be found to update.
|
* @throws NotFoundException if the ACL could not be found to update.
|
||||||
*/
|
*/
|
||||||
protected void updateObjectIdentity(MutableAcl acl) {
|
protected void updateObjectIdentity(MutableAcl acl) {
|
||||||
Long parentId = null;
|
Long parentId = null;
|
||||||
|
|
||||||
if (acl.getParentAcl() != null) {
|
if (acl.getParentAcl() != null) {
|
||||||
Assert.isInstanceOf(ObjectIdentityImpl.class, acl.getParentAcl()
|
Assert.isInstanceOf(ObjectIdentityImpl.class, acl.getParentAcl().getObjectIdentity(),
|
||||||
.getObjectIdentity(),
|
|
||||||
"Implementation only supports ObjectIdentityImpl");
|
"Implementation only supports ObjectIdentityImpl");
|
||||||
|
ObjectIdentityImpl oii = (ObjectIdentityImpl) acl.getParentAcl().getObjectIdentity();
|
||||||
ObjectIdentityImpl oii = (ObjectIdentityImpl) acl.getParentAcl()
|
|
||||||
.getObjectIdentity();
|
|
||||||
parentId = retrieveObjectIdentityPrimaryKey(oii);
|
parentId = retrieveObjectIdentityPrimaryKey(oii);
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.notNull(acl.getOwner(), "Owner is required in this implementation");
|
Assert.notNull(acl.getOwner(), "Owner is required in this implementation");
|
||||||
|
|
||||||
Long ownerSid = createOrRetrieveSidPrimaryKey(acl.getOwner(), true);
|
Long ownerSid = createOrRetrieveSidPrimaryKey(acl.getOwner(), true);
|
||||||
int count = jdbcOperations.update(updateObjectIdentity, parentId, ownerSid,
|
int count = this.jdbcOperations.update(this.updateObjectIdentity, parentId, ownerSid, acl.isEntriesInheriting(),
|
||||||
acl.isEntriesInheriting(), acl.getId());
|
acl.getId());
|
||||||
|
|
||||||
if (count != 1) {
|
if (count != 1) {
|
||||||
throw new NotFoundException("Unable to locate ACL to update");
|
throw new NotFoundException("Unable to locate ACL to update");
|
||||||
}
|
}
|
||||||
@@ -419,7 +391,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
/**
|
/**
|
||||||
* Sets the query that will be used to retrieve the identity of a newly created row in
|
* Sets the query that will be used to retrieve the identity of a newly created row in
|
||||||
* the <tt>acl_class</tt> table.
|
* the <tt>acl_class</tt> table.
|
||||||
*
|
|
||||||
* @param classIdentityQuery the query, which should return the identifier. Defaults
|
* @param classIdentityQuery the query, which should return the identifier. Defaults
|
||||||
* to <tt>call identity()</tt>
|
* to <tt>call identity()</tt>
|
||||||
*/
|
*/
|
||||||
@@ -431,7 +402,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
/**
|
/**
|
||||||
* Sets the query that will be used to retrieve the identity of a newly created row in
|
* Sets the query that will be used to retrieve the identity of a newly created row in
|
||||||
* the <tt>acl_sid</tt> table.
|
* the <tt>acl_sid</tt> table.
|
||||||
*
|
|
||||||
* @param sidIdentityQuery the query, which should return the identifier. Defaults to
|
* @param sidIdentityQuery the query, which should return the identifier. Defaults to
|
||||||
* <tt>call identity()</tt>
|
* <tt>call identity()</tt>
|
||||||
*/
|
*/
|
||||||
@@ -440,13 +410,11 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
this.sidIdentityQuery = sidIdentityQuery;
|
this.sidIdentityQuery = sidIdentityQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDeleteEntryByObjectIdentityForeignKeySql(
|
public void setDeleteEntryByObjectIdentityForeignKeySql(String deleteEntryByObjectIdentityForeignKey) {
|
||||||
String deleteEntryByObjectIdentityForeignKey) {
|
|
||||||
this.deleteEntryByObjectIdentityForeignKey = deleteEntryByObjectIdentityForeignKey;
|
this.deleteEntryByObjectIdentityForeignKey = deleteEntryByObjectIdentityForeignKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDeleteObjectIdentityByPrimaryKeySql(
|
public void setDeleteObjectIdentityByPrimaryKeySql(String deleteObjectIdentityByPrimaryKey) {
|
||||||
String deleteObjectIdentityByPrimaryKey) {
|
|
||||||
this.deleteObjectIdentityByPrimaryKey = deleteObjectIdentityByPrimaryKey;
|
this.deleteObjectIdentityByPrimaryKey = deleteObjectIdentityByPrimaryKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,9 +466,11 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
// Change the default insert if it hasn't been overridden
|
// Change the default insert if it hasn't been overridden
|
||||||
if (this.insertClass.equals(DEFAULT_INSERT_INTO_ACL_CLASS)) {
|
if (this.insertClass.equals(DEFAULT_INSERT_INTO_ACL_CLASS)) {
|
||||||
this.insertClass = DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID;
|
this.insertClass = DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
log.debug("Insert class statement has already been overridden, so not overridding the default");
|
log.debug("Insert class statement has already been overridden, so not overridding the default");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,32 +13,29 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.jdbc;
|
package org.springframework.security.acls.jdbc;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.Acl;
|
import org.springframework.security.acls.model.Acl;
|
||||||
import org.springframework.security.acls.model.NotFoundException;
|
import org.springframework.security.acls.model.NotFoundException;
|
||||||
import org.springframework.security.acls.model.ObjectIdentity;
|
import org.springframework.security.acls.model.ObjectIdentity;
|
||||||
import org.springframework.security.acls.model.Sid;
|
import org.springframework.security.acls.model.Sid;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs lookups for {@link org.springframework.security.acls.model.AclService}.
|
* Performs lookups for {@link org.springframework.security.acls.model.AclService}.
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public interface LookupStrategy {
|
public interface LookupStrategy {
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform database-specific optimized lookup.
|
* Perform database-specific optimized lookup.
|
||||||
*
|
|
||||||
* @param objects the identities to lookup (required)
|
* @param objects the identities to lookup (required)
|
||||||
* @param sids the SIDs for which identities are required (may be <tt>null</tt> -
|
* @param sids the SIDs for which identities are required (may be <tt>null</tt> -
|
||||||
* implementations may elect not to provide SID optimisations)
|
* implementations may elect not to provide SID optimisations)
|
||||||
*
|
|
||||||
* @return a <tt>Map</tt> where keys represent the {@link ObjectIdentity} of the
|
* @return a <tt>Map</tt> where keys represent the {@link ObjectIdentity} of the
|
||||||
* located {@link Acl} and values are the located {@link Acl} (never <tt>null</tt>
|
* located {@link Acl} and values are the located {@link Acl} (never <tt>null</tt>
|
||||||
* although some entries may be missing; this method should not throw
|
* although some entries may be missing; this method should not throw
|
||||||
@@ -46,4 +43,5 @@ public interface LookupStrategy {
|
|||||||
* automatically create entries if required)
|
* automatically create entries if required)
|
||||||
*/
|
*/
|
||||||
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids);
|
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JDBC-based persistence of ACL information
|
* JDBC-based persistence of ACL information
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.acls.jdbc;
|
package org.springframework.security.acls.jdbc;
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -26,17 +27,13 @@ import java.io.Serializable;
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface AccessControlEntry extends Serializable {
|
public interface AccessControlEntry extends Serializable {
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
Acl getAcl();
|
Acl getAcl();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains an identifier that represents this ACE.
|
* Obtains an identifier that represents this ACE.
|
||||||
*
|
|
||||||
* @return the identifier, or <code>null</code> if unsaved
|
* @return the identifier, or <code>null</code> if unsaved
|
||||||
*/
|
*/
|
||||||
Serializable getId();
|
Serializable getId();
|
||||||
@@ -46,10 +43,10 @@ public interface AccessControlEntry extends Serializable {
|
|||||||
Sid getSid();
|
Sid getSid();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates the permission is being granted to the relevant Sid. If false,
|
* Indicates the permission is being granted to the relevant Sid. If false, indicates
|
||||||
* indicates the permission is being revoked/blocked.
|
* the permission is being revoked/blocked.
|
||||||
*
|
|
||||||
* @return true if being granted, false otherwise
|
* @return true if being granted, false otherwise
|
||||||
*/
|
*/
|
||||||
boolean isGranting();
|
boolean isGranting();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -63,7 +64,6 @@ public interface Acl extends Serializable {
|
|||||||
* subset of <tt>Sid</tt>s. The caller is responsible for correctly handling the
|
* subset of <tt>Sid</tt>s. The caller is responsible for correctly handling the
|
||||||
* result if only a subset of <tt>Sid</tt>s is represented.
|
* result if only a subset of <tt>Sid</tt>s is represented.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
|
||||||
* @return the list of entries represented by the <tt>Acl</tt>, or <tt>null</tt> if
|
* @return the list of entries represented by the <tt>Acl</tt>, or <tt>null</tt> if
|
||||||
* there are no entries presently associated with this <tt>Acl</tt>.
|
* there are no entries presently associated with this <tt>Acl</tt>.
|
||||||
*/
|
*/
|
||||||
@@ -72,7 +72,6 @@ public interface Acl extends Serializable {
|
|||||||
/**
|
/**
|
||||||
* Obtains the domain object this <tt>Acl</tt> provides entries for. This is immutable
|
* Obtains the domain object this <tt>Acl</tt> provides entries for. This is immutable
|
||||||
* once an <tt>Acl</tt> is created.
|
* once an <tt>Acl</tt> is created.
|
||||||
*
|
|
||||||
* @return the object identity (never <tt>null</tt>)
|
* @return the object identity (never <tt>null</tt>)
|
||||||
*/
|
*/
|
||||||
ObjectIdentity getObjectIdentity();
|
ObjectIdentity getObjectIdentity();
|
||||||
@@ -80,7 +79,6 @@ public interface Acl extends Serializable {
|
|||||||
/**
|
/**
|
||||||
* Determines the owner of the <tt>Acl</tt>. The meaning of ownership varies by
|
* Determines the owner of the <tt>Acl</tt>. The meaning of ownership varies by
|
||||||
* implementation and is unspecified.
|
* implementation and is unspecified.
|
||||||
*
|
|
||||||
* @return the owner (may be <tt>null</tt> if the implementation does not use
|
* @return the owner (may be <tt>null</tt> if the implementation does not use
|
||||||
* ownership concepts)
|
* ownership concepts)
|
||||||
*/
|
*/
|
||||||
@@ -102,7 +100,6 @@ public interface Acl extends Serializable {
|
|||||||
* subset of <tt>Sid</tt>s. The caller is responsible for correctly handling the
|
* subset of <tt>Sid</tt>s. The caller is responsible for correctly handling the
|
||||||
* result if only a subset of <tt>Sid</tt>s is represented.
|
* result if only a subset of <tt>Sid</tt>s is represented.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
|
||||||
* @return the parent <tt>Acl</tt> (may be <tt>null</tt> if this <tt>Acl</tt> does not
|
* @return the parent <tt>Acl</tt> (may be <tt>null</tt> if this <tt>Acl</tt> does not
|
||||||
* have a parent)
|
* have a parent)
|
||||||
*/
|
*/
|
||||||
@@ -118,7 +115,6 @@ public interface Acl extends Serializable {
|
|||||||
* parent for navigation purposes. Thus, this method denotes whether or not the
|
* parent for navigation purposes. Thus, this method denotes whether or not the
|
||||||
* navigation relationship also extends to the actual inheritance of entries.
|
* navigation relationship also extends to the actual inheritance of entries.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
|
||||||
* @return <tt>true</tt> if parent ACL entries inherit into the current <tt>Acl</tt>
|
* @return <tt>true</tt> if parent ACL entries inherit into the current <tt>Acl</tt>
|
||||||
*/
|
*/
|
||||||
boolean isEntriesInheriting();
|
boolean isEntriesInheriting();
|
||||||
@@ -158,7 +154,6 @@ public interface Acl extends Serializable {
|
|||||||
* authorization decision for a {@link Sid} that was never loaded in this <tt>Acl</tt>
|
* authorization decision for a {@link Sid} that was never loaded in this <tt>Acl</tt>
|
||||||
* .
|
* .
|
||||||
* </p>
|
* </p>
|
||||||
*
|
|
||||||
* @param permission the permission or permissions required (at least one entry
|
* @param permission the permission or permissions required (at least one entry
|
||||||
* required)
|
* required)
|
||||||
* @param sids the security identities held by the principal (at least one entry
|
* @param sids the security identities held by the principal (at least one entry
|
||||||
@@ -166,17 +161,15 @@ public interface Acl extends Serializable {
|
|||||||
* @param administrativeMode if <tt>true</tt> denotes the query is for administrative
|
* @param administrativeMode if <tt>true</tt> denotes the query is for administrative
|
||||||
* purposes and no logging or auditing (if supported by the implementation) should be
|
* purposes and no logging or auditing (if supported by the implementation) should be
|
||||||
* undertaken
|
* undertaken
|
||||||
*
|
|
||||||
* @return <tt>true</tt> if authorization is granted
|
* @return <tt>true</tt> if authorization is granted
|
||||||
*
|
|
||||||
* @throws NotFoundException MUST be thrown if an implementation cannot make an
|
* @throws NotFoundException MUST be thrown if an implementation cannot make an
|
||||||
* authoritative authorization decision, usually because there is no ACL information
|
* authoritative authorization decision, usually because there is no ACL information
|
||||||
* for this particular permission and/or SID
|
* for this particular permission and/or SID
|
||||||
* @throws UnloadedSidException thrown if the <tt>Acl</tt> does not have details for
|
* @throws UnloadedSidException thrown if the <tt>Acl</tt> does not have details for
|
||||||
* one or more of the <tt>Sid</tt>s passed as arguments
|
* one or more of the <tt>Sid</tt>s passed as arguments
|
||||||
*/
|
*/
|
||||||
boolean isGranted(List<Permission> permission, List<Sid> sids,
|
boolean isGranted(List<Permission> permission, List<Sid> sids, boolean administrativeMode)
|
||||||
boolean administrativeMode) throws NotFoundException, UnloadedSidException;
|
throws NotFoundException, UnloadedSidException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For efficiency reasons an <tt>Acl</tt> may be loaded and <em>not</em> contain
|
* For efficiency reasons an <tt>Acl</tt> may be loaded and <em>not</em> contain
|
||||||
@@ -191,12 +184,11 @@ public interface Acl extends Serializable {
|
|||||||
* all <tt>Sid</tt>s. This method denotes whether or not the specified <tt>Sid</tt>s
|
* all <tt>Sid</tt>s. This method denotes whether or not the specified <tt>Sid</tt>s
|
||||||
* have been loaded or not.
|
* have been loaded or not.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
|
||||||
* @param sids one or more security identities the caller is interest in knowing
|
* @param sids one or more security identities the caller is interest in knowing
|
||||||
* whether this <tt>Sid</tt> supports
|
* whether this <tt>Sid</tt> supports
|
||||||
*
|
|
||||||
* @return <tt>true</tt> if every passed <tt>Sid</tt> is represented by this
|
* @return <tt>true</tt> if every passed <tt>Sid</tt> is represented by this
|
||||||
* <tt>Acl</tt> instance
|
* <tt>Acl</tt> instance
|
||||||
*/
|
*/
|
||||||
boolean isSidLoaded(List<Sid> sids);
|
boolean isSidLoaded(List<Sid> sids);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,21 +13,19 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
import org.springframework.security.acls.jdbc.JdbcAclService;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.springframework.security.acls.jdbc.JdbcAclService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A caching layer for {@link JdbcAclService}.
|
* A caching layer for {@link JdbcAclService}.
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface AclCache {
|
public interface AclCache {
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
void evictFromCache(Serializable pk);
|
void evictFromCache(Serializable pk);
|
||||||
|
|
||||||
@@ -40,4 +38,5 @@ public interface AclCache {
|
|||||||
void putInCache(MutableAcl acl);
|
void putInCache(MutableAcl acl);
|
||||||
|
|
||||||
void clearCache();
|
void clearCache();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,7 +27,6 @@ public abstract class AclDataAccessException extends RuntimeException {
|
|||||||
/**
|
/**
|
||||||
* Constructs an <code>AclDataAccessException</code> with the specified message and
|
* Constructs an <code>AclDataAccessException</code> with the specified message and
|
||||||
* root cause.
|
* root cause.
|
||||||
*
|
|
||||||
* @param msg the detail message
|
* @param msg the detail message
|
||||||
* @param cause the root cause
|
* @param cause the root cause
|
||||||
*/
|
*/
|
||||||
@@ -37,10 +37,10 @@ public abstract class AclDataAccessException extends RuntimeException {
|
|||||||
/**
|
/**
|
||||||
* Constructs an <code>AclDataAccessException</code> with the specified message and no
|
* Constructs an <code>AclDataAccessException</code> with the specified message and no
|
||||||
* root cause.
|
* root cause.
|
||||||
*
|
|
||||||
* @param msg the detail message
|
* @param msg the detail message
|
||||||
*/
|
*/
|
||||||
public AclDataAccessException(String msg) {
|
public AclDataAccessException(String msg) {
|
||||||
super(msg);
|
super(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -24,15 +25,11 @@ import java.util.Map;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public interface AclService {
|
public interface AclService {
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locates all object identities that use the specified parent. This is useful for
|
* Locates all object identities that use the specified parent. This is useful for
|
||||||
* administration tools.
|
* administration tools.
|
||||||
*
|
|
||||||
* @param parentIdentity to locate children of
|
* @param parentIdentity to locate children of
|
||||||
*
|
|
||||||
* @return the children (or <tt>null</tt> if none were found)
|
* @return the children (or <tt>null</tt> if none were found)
|
||||||
*/
|
*/
|
||||||
List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity);
|
List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity);
|
||||||
@@ -44,12 +41,9 @@ public interface AclService {
|
|||||||
* implementation's potential ability to filter <tt>Acl</tt> entries based on a
|
* implementation's potential ability to filter <tt>Acl</tt> entries based on a
|
||||||
* {@link Sid} parameter.
|
* {@link Sid} parameter.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
|
||||||
* @param object to locate an {@link Acl} for
|
* @param object to locate an {@link Acl} for
|
||||||
*
|
|
||||||
* @return the {@link Acl} for the requested {@link ObjectIdentity} (never
|
* @return the {@link Acl} for the requested {@link ObjectIdentity} (never
|
||||||
* <tt>null</tt>)
|
* <tt>null</tt>)
|
||||||
*
|
|
||||||
* @throws NotFoundException if an {@link Acl} was not found for the requested
|
* @throws NotFoundException if an {@link Acl} was not found for the requested
|
||||||
* {@link ObjectIdentity}
|
* {@link ObjectIdentity}
|
||||||
*/
|
*/
|
||||||
@@ -57,14 +51,11 @@ public interface AclService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link #readAclsById(List, List)} except it returns only a single Acl.
|
* Same as {@link #readAclsById(List, List)} except it returns only a single Acl.
|
||||||
*
|
|
||||||
* @param object to locate an {@link Acl} for
|
* @param object to locate an {@link Acl} for
|
||||||
* @param sids the security identities for which {@link Acl} information is required
|
* @param sids the security identities for which {@link Acl} information is required
|
||||||
* (may be <tt>null</tt> to denote all entries)
|
* (may be <tt>null</tt> to denote all entries)
|
||||||
*
|
|
||||||
* @return the {@link Acl} for the requested {@link ObjectIdentity} (never
|
* @return the {@link Acl} for the requested {@link ObjectIdentity} (never
|
||||||
* <tt>null</tt>)
|
* <tt>null</tt>)
|
||||||
*
|
|
||||||
* @throws NotFoundException if an {@link Acl} was not found for the requested
|
* @throws NotFoundException if an {@link Acl} was not found for the requested
|
||||||
* {@link ObjectIdentity}
|
* {@link ObjectIdentity}
|
||||||
*/
|
*/
|
||||||
@@ -76,17 +67,13 @@ public interface AclService {
|
|||||||
* The returned map is keyed on the passed objects, with the values being the
|
* The returned map is keyed on the passed objects, with the values being the
|
||||||
* <tt>Acl</tt> instances. Any unknown objects will not have a map key.
|
* <tt>Acl</tt> instances. Any unknown objects will not have a map key.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
|
||||||
* @param objects the objects to find {@link Acl} information for
|
* @param objects the objects to find {@link Acl} information for
|
||||||
*
|
|
||||||
* @return a map with exactly one element for each {@link ObjectIdentity} passed as an
|
* @return a map with exactly one element for each {@link ObjectIdentity} passed as an
|
||||||
* argument (never <tt>null</tt>)
|
* argument (never <tt>null</tt>)
|
||||||
*
|
|
||||||
* @throws NotFoundException if an {@link Acl} was not found for each requested
|
* @throws NotFoundException if an {@link Acl} was not found for each requested
|
||||||
* {@link ObjectIdentity}
|
* {@link ObjectIdentity}
|
||||||
*/
|
*/
|
||||||
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects)
|
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects) throws NotFoundException;
|
||||||
throws NotFoundException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains all the <tt>Acl</tt>s that apply for the passed <tt>Object</tt>s, but only
|
* Obtains all the <tt>Acl</tt>s that apply for the passed <tt>Object</tt>s, but only
|
||||||
@@ -103,17 +90,14 @@ public interface AclService {
|
|||||||
* <tt>Acl</tt> instances. Any unknown objects (or objects for which the interested
|
* <tt>Acl</tt> instances. Any unknown objects (or objects for which the interested
|
||||||
* <tt>Sid</tt>s do not have entries) will not have a map key.
|
* <tt>Sid</tt>s do not have entries) will not have a map key.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
|
||||||
* @param objects the objects to find {@link Acl} information for
|
* @param objects the objects to find {@link Acl} information for
|
||||||
* @param sids the security identities for which {@link Acl} information is required
|
* @param sids the security identities for which {@link Acl} information is required
|
||||||
* (may be <tt>null</tt> to denote all entries)
|
* (may be <tt>null</tt> to denote all entries)
|
||||||
*
|
|
||||||
* @return a map with exactly one element for each {@link ObjectIdentity} passed as an
|
* @return a map with exactly one element for each {@link ObjectIdentity} passed as an
|
||||||
* argument (never <tt>null</tt>)
|
* argument (never <tt>null</tt>)
|
||||||
*
|
|
||||||
* @throws NotFoundException if an {@link Acl} was not found for each requested
|
* @throws NotFoundException if an {@link Acl} was not found for each requested
|
||||||
* {@link ObjectIdentity}
|
* {@link ObjectIdentity}
|
||||||
*/
|
*/
|
||||||
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids)
|
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids) throws NotFoundException;
|
||||||
throws NotFoundException;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-7
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,12 +22,9 @@ package org.springframework.security.acls.model;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class AlreadyExistsException extends AclDataAccessException {
|
public class AlreadyExistsException extends AclDataAccessException {
|
||||||
// ~ Constructors
|
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an <code>AlreadyExistsException</code> with the specified message.
|
* Constructs an <code>AlreadyExistsException</code> with the specified message.
|
||||||
*
|
|
||||||
* @param msg the detail message
|
* @param msg the detail message
|
||||||
*/
|
*/
|
||||||
public AlreadyExistsException(String msg) {
|
public AlreadyExistsException(String msg) {
|
||||||
@@ -36,11 +34,11 @@ public class AlreadyExistsException extends AclDataAccessException {
|
|||||||
/**
|
/**
|
||||||
* Constructs an <code>AlreadyExistsException</code> with the specified message and
|
* Constructs an <code>AlreadyExistsException</code> with the specified message and
|
||||||
* root cause.
|
* root cause.
|
||||||
*
|
|
||||||
* @param msg the detail message
|
* @param msg the detail message
|
||||||
* @param t root cause
|
* @param cause root cause
|
||||||
*/
|
*/
|
||||||
public AlreadyExistsException(String msg, Throwable t) {
|
public AlreadyExistsException(String msg, Throwable cause) {
|
||||||
super(msg, t);
|
super(msg, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -13,19 +13,18 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an ACE that provides auditing information.
|
* Represents an ACE that provides auditing information.
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface AuditableAccessControlEntry extends AccessControlEntry {
|
public interface AuditableAccessControlEntry extends AccessControlEntry {
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
boolean isAuditFailure();
|
boolean isAuditFailure();
|
||||||
|
|
||||||
boolean isAuditSuccess();
|
boolean isAuditSuccess();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,17 +13,16 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mutable ACL that provides audit capabilities.
|
* A mutable ACL that provides audit capabilities.
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface AuditableAcl extends MutableAcl {
|
public interface AuditableAcl extends MutableAcl {
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure);
|
void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-7
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,12 +22,9 @@ package org.springframework.security.acls.model;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class ChildrenExistException extends AclDataAccessException {
|
public class ChildrenExistException extends AclDataAccessException {
|
||||||
// ~ Constructors
|
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an <code>ChildrenExistException</code> with the specified message.
|
* Constructs an <code>ChildrenExistException</code> with the specified message.
|
||||||
*
|
|
||||||
* @param msg the detail message
|
* @param msg the detail message
|
||||||
*/
|
*/
|
||||||
public ChildrenExistException(String msg) {
|
public ChildrenExistException(String msg) {
|
||||||
@@ -36,11 +34,11 @@ public class ChildrenExistException extends AclDataAccessException {
|
|||||||
/**
|
/**
|
||||||
* Constructs an <code>ChildrenExistException</code> with the specified message and
|
* Constructs an <code>ChildrenExistException</code> with the specified message and
|
||||||
* root cause.
|
* root cause.
|
||||||
*
|
|
||||||
* @param msg the detail message
|
* @param msg the detail message
|
||||||
* @param t root cause
|
* @param cause root cause
|
||||||
*/
|
*/
|
||||||
public ChildrenExistException(String msg, Throwable t) {
|
public ChildrenExistException(String msg, Throwable cause) {
|
||||||
super(msg, t);
|
super(msg, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -26,41 +27,35 @@ import java.io.Serializable;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public interface MutableAcl extends Acl {
|
public interface MutableAcl extends Acl {
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
void deleteAce(int aceIndex) throws NotFoundException;
|
void deleteAce(int aceIndex) throws NotFoundException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains an identifier that represents this <tt>MutableAcl</tt>.
|
* Obtains an identifier that represents this <tt>MutableAcl</tt>.
|
||||||
*
|
|
||||||
* @return the identifier, or <tt>null</tt> if unsaved
|
* @return the identifier, or <tt>null</tt> if unsaved
|
||||||
*/
|
*/
|
||||||
Serializable getId();
|
Serializable getId();
|
||||||
|
|
||||||
void insertAce(int atIndexLocation, Permission permission, Sid sid, boolean granting)
|
void insertAce(int atIndexLocation, Permission permission, Sid sid, boolean granting) throws NotFoundException;
|
||||||
throws NotFoundException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the present owner to a different owner.
|
* Changes the present owner to a different owner.
|
||||||
*
|
|
||||||
* @param newOwner the new owner (mandatory; cannot be null)
|
* @param newOwner the new owner (mandatory; cannot be null)
|
||||||
*/
|
*/
|
||||||
void setOwner(Sid newOwner);
|
void setOwner(Sid newOwner);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the value returned by {@link Acl#isEntriesInheriting()}.
|
* Change the value returned by {@link Acl#isEntriesInheriting()}.
|
||||||
*
|
|
||||||
* @param entriesInheriting the new value
|
* @param entriesInheriting the new value
|
||||||
*/
|
*/
|
||||||
void setEntriesInheriting(boolean entriesInheriting);
|
void setEntriesInheriting(boolean entriesInheriting);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the parent of this ACL.
|
* Changes the parent of this ACL.
|
||||||
*
|
|
||||||
* @param newParent the new parent
|
* @param newParent the new parent
|
||||||
*/
|
*/
|
||||||
void setParent(Acl newParent);
|
void setParent(Acl newParent);
|
||||||
|
|
||||||
void updateAce(int aceIndex, Permission permission) throws NotFoundException;
|
void updateAce(int aceIndex, Permission permission) throws NotFoundException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,41 +22,32 @@ package org.springframework.security.acls.model;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public interface MutableAclService extends AclService {
|
public interface MutableAclService extends AclService {
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an empty <code>Acl</code> object in the database. It will have no entries.
|
* Creates an empty <code>Acl</code> object in the database. It will have no entries.
|
||||||
* The returned object will then be used to add entries.
|
* The returned object will then be used to add entries.
|
||||||
*
|
|
||||||
* @param objectIdentity the object identity to create
|
* @param objectIdentity the object identity to create
|
||||||
*
|
|
||||||
* @return an ACL object with its ID set
|
* @return an ACL object with its ID set
|
||||||
*
|
|
||||||
* @throws AlreadyExistsException if the passed object identity already has a record
|
* @throws AlreadyExistsException if the passed object identity already has a record
|
||||||
*/
|
*/
|
||||||
MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException;
|
MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the specified entry from the database.
|
* Removes the specified entry from the database.
|
||||||
*
|
|
||||||
* @param objectIdentity the object identity to remove
|
* @param objectIdentity the object identity to remove
|
||||||
* @param deleteChildren whether to cascade the delete to children
|
* @param deleteChildren whether to cascade the delete to children
|
||||||
*
|
|
||||||
* @throws ChildrenExistException if the deleteChildren argument was
|
* @throws ChildrenExistException if the deleteChildren argument was
|
||||||
* <code>false</code> but children exist
|
* <code>false</code> but children exist
|
||||||
*/
|
*/
|
||||||
void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren)
|
void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException;
|
||||||
throws ChildrenExistException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes an existing <code>Acl</code> in the database.
|
* Changes an existing <code>Acl</code> in the database.
|
||||||
*
|
|
||||||
* @param acl to modify
|
* @param acl to modify
|
||||||
*
|
|
||||||
* @throws NotFoundException if the relevant record could not be found (did you
|
* @throws NotFoundException if the relevant record could not be found (did you
|
||||||
* remember to use {@link #createAcl(ObjectIdentity)} to create the object, rather
|
* remember to use {@link #createAcl(ObjectIdentity)} to create the object, rather
|
||||||
* than creating it with the <code>new</code> keyword?)
|
* than creating it with the <code>new</code> keyword?)
|
||||||
*/
|
*/
|
||||||
MutableAcl updateAcl(MutableAcl acl) throws NotFoundException;
|
MutableAcl updateAcl(MutableAcl acl) throws NotFoundException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,12 +22,9 @@ package org.springframework.security.acls.model;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class NotFoundException extends AclDataAccessException {
|
public class NotFoundException extends AclDataAccessException {
|
||||||
// ~ Constructors
|
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an <code>NotFoundException</code> with the specified message.
|
* Constructs an <code>NotFoundException</code> with the specified message.
|
||||||
*
|
|
||||||
* @param msg the detail message
|
* @param msg the detail message
|
||||||
*/
|
*/
|
||||||
public NotFoundException(String msg) {
|
public NotFoundException(String msg) {
|
||||||
@@ -36,11 +34,11 @@ public class NotFoundException extends AclDataAccessException {
|
|||||||
/**
|
/**
|
||||||
* Constructs an <code>NotFoundException</code> with the specified message and root
|
* Constructs an <code>NotFoundException</code> with the specified message and root
|
||||||
* cause.
|
* cause.
|
||||||
*
|
|
||||||
* @param msg the detail message
|
* @param msg the detail message
|
||||||
* @param t root cause
|
* @param cause root cause
|
||||||
*/
|
*/
|
||||||
public NotFoundException(String msg, Throwable t) {
|
public NotFoundException(String msg, Throwable cause) {
|
||||||
super(msg, t);
|
super(msg, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -32,15 +33,13 @@ import java.io.Serializable;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public interface ObjectIdentity extends Serializable {
|
public interface ObjectIdentity extends Serializable {
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param obj to be compared
|
* @param obj to be compared
|
||||||
*
|
|
||||||
* @return <tt>true</tt> if the objects are equal, <tt>false</tt> otherwise
|
* @return <tt>true</tt> if the objects are equal, <tt>false</tt> otherwise
|
||||||
* @see Object#equals(Object)
|
* @see Object#equals(Object)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
boolean equals(Object obj);
|
boolean equals(Object obj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,7 +52,6 @@ public interface ObjectIdentity extends Serializable {
|
|||||||
* identifier with business meaning, as that business meaning may change in the future
|
* identifier with business meaning, as that business meaning may change in the future
|
||||||
* such change will cascade to the ACL subsystem data.
|
* such change will cascade to the ACL subsystem data.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
|
||||||
* @return the identifier (unique within this <tt>type</tt>; never <tt>null</tt>)
|
* @return the identifier (unique within this <tt>type</tt>; never <tt>null</tt>)
|
||||||
*/
|
*/
|
||||||
Serializable getIdentifier();
|
Serializable getIdentifier();
|
||||||
@@ -62,7 +60,6 @@ public interface ObjectIdentity extends Serializable {
|
|||||||
* Obtains the "type" metadata for the domain object. This will often be a Java type
|
* Obtains the "type" metadata for the domain object. This will often be a Java type
|
||||||
* name (an interface or a class) – traditionally it is the name of the domain
|
* name (an interface or a class) – traditionally it is the name of the domain
|
||||||
* object implementation class.
|
* object implementation class.
|
||||||
*
|
|
||||||
* @return the "type" of the domain object (never <tt>null</tt>).
|
* @return the "type" of the domain object (never <tt>null</tt>).
|
||||||
*/
|
*/
|
||||||
String getType();
|
String getType();
|
||||||
@@ -71,5 +68,7 @@ public interface ObjectIdentity extends Serializable {
|
|||||||
* @return a hash code representation of the <tt>ObjectIdentity</tt>
|
* @return a hash code representation of the <tt>ObjectIdentity</tt>
|
||||||
* @see Object#hashCode()
|
* @see Object#hashCode()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
int hashCode();
|
int hashCode();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -30,7 +31,6 @@ import java.io.Serializable;
|
|||||||
public interface ObjectIdentityGenerator {
|
public interface ObjectIdentityGenerator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param id the identifier of the domain object, not null
|
* @param id the identifier of the domain object, not null
|
||||||
* @param type the type of the object (often a class name), not null
|
* @param type the type of the object (often a class name), not null
|
||||||
* @return the identity constructed using the supplied identifier and type
|
* @return the identity constructed using the supplied identifier and type
|
||||||
|
|||||||
+1
-3
@@ -21,11 +21,9 @@ package org.springframework.security.acls.model;
|
|||||||
* will be returned for a particular domain object
|
* will be returned for a particular domain object
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface ObjectIdentityRetrievalStrategy {
|
public interface ObjectIdentityRetrievalStrategy {
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
ObjectIdentity getObjectIdentity(Object domainObject);
|
ObjectIdentity getObjectIdentity(Object domainObject);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,8 +26,8 @@ package org.springframework.security.acls.model;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public interface OwnershipAcl extends MutableAcl {
|
public interface OwnershipAcl extends MutableAcl {
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
|
@Override
|
||||||
void setOwner(Sid newOwner);
|
void setOwner(Sid newOwner);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -23,19 +24,15 @@ import java.io.Serializable;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public interface Permission extends Serializable {
|
public interface Permission extends Serializable {
|
||||||
// ~ Static fields/initializers
|
|
||||||
// =====================================================================================
|
|
||||||
|
|
||||||
char RESERVED_ON = '~';
|
char RESERVED_ON = '~';
|
||||||
char RESERVED_OFF = '.';
|
|
||||||
String THIRTY_TWO_RESERVED_OFF = "................................";
|
|
||||||
|
|
||||||
// ~ Methods
|
char RESERVED_OFF = '.';
|
||||||
// ========================================================================================================
|
|
||||||
|
String THIRTY_TWO_RESERVED_OFF = "................................";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the bits that represents the permission.
|
* Returns the bits that represents the permission.
|
||||||
*
|
|
||||||
* @return the bits that represent the permission
|
* @return the bits that represent the permission
|
||||||
*/
|
*/
|
||||||
int getMask();
|
int getMask();
|
||||||
@@ -56,8 +53,8 @@ public interface Permission extends Serializable {
|
|||||||
* This method is only used for user interface and logging purposes. It is not used in
|
* This method is only used for user interface and logging purposes. It is not used in
|
||||||
* any permission calculations. Therefore, duplication of characters within the output
|
* any permission calculations. Therefore, duplication of characters within the output
|
||||||
* is permitted.
|
* is permitted.
|
||||||
*
|
|
||||||
* @return a 32-character bit pattern
|
* @return a 32-character bit pattern
|
||||||
*/
|
*/
|
||||||
String getPattern();
|
String getPattern();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -27,10 +28,9 @@ import java.util.List;
|
|||||||
public interface PermissionGrantingStrategy {
|
public interface PermissionGrantingStrategy {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the supplied strategy decides that the supplied {@code Acl}
|
* Returns true if the supplied strategy decides that the supplied {@code Acl} grants
|
||||||
* grants access based on the supplied list of permissions and sids.
|
* access based on the supplied list of permissions and sids.
|
||||||
*/
|
*/
|
||||||
boolean isGranted(Acl acl, List<Permission> permission, List<Sid> sids,
|
boolean isGranted(Acl acl, List<Permission> permission, List<Sid> sids, boolean administrativeMode);
|
||||||
boolean administrativeMode);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -31,24 +32,22 @@ import java.io.Serializable;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public interface Sid extends Serializable {
|
public interface Sid extends Serializable {
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refer to the <code>java.lang.Object</code> documentation for the interface
|
* Refer to the <code>java.lang.Object</code> documentation for the interface
|
||||||
* contract.
|
* contract.
|
||||||
*
|
|
||||||
* @param obj to be compared
|
* @param obj to be compared
|
||||||
*
|
|
||||||
* @return <code>true</code> if the objects are equal, <code>false</code> otherwise
|
* @return <code>true</code> if the objects are equal, <code>false</code> otherwise
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
boolean equals(Object obj);
|
boolean equals(Object obj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refer to the <code>java.lang.Object</code> documentation for the interface
|
* Refer to the <code>java.lang.Object</code> documentation for the interface
|
||||||
* contract.
|
* contract.
|
||||||
*
|
|
||||||
* @return a hash code representation of this object
|
* @return a hash code representation of this object
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
int hashCode();
|
int hashCode();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,7 @@ import org.springframework.security.core.Authentication;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public interface SidRetrievalStrategy {
|
public interface SidRetrievalStrategy {
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
List<Sid> getSids(Authentication authentication);
|
List<Sid> getSids(Authentication authentication);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,12 +24,9 @@ package org.springframework.security.acls.model;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class UnloadedSidException extends AclDataAccessException {
|
public class UnloadedSidException extends AclDataAccessException {
|
||||||
// ~ Constructors
|
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an <code>NotFoundException</code> with the specified message.
|
* Constructs an <code>NotFoundException</code> with the specified message.
|
||||||
*
|
|
||||||
* @param msg the detail message
|
* @param msg the detail message
|
||||||
*/
|
*/
|
||||||
public UnloadedSidException(String msg) {
|
public UnloadedSidException(String msg) {
|
||||||
@@ -38,11 +36,11 @@ public class UnloadedSidException extends AclDataAccessException {
|
|||||||
/**
|
/**
|
||||||
* Constructs an <code>NotFoundException</code> with the specified message and root
|
* Constructs an <code>NotFoundException</code> with the specified message and root
|
||||||
* cause.
|
* cause.
|
||||||
*
|
|
||||||
* @param msg the detail message
|
* @param msg the detail message
|
||||||
* @param t root cause
|
* @param cause root cause
|
||||||
*/
|
*/
|
||||||
public UnloadedSidException(String msg, Throwable t) {
|
public UnloadedSidException(String msg, Throwable cause) {
|
||||||
super(msg, t);
|
super(msg, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,9 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interfaces and shared classes to manage access control lists (ACLs) for domain object instances.
|
* Interfaces and shared classes to manage access control lists (ACLs) for domain object
|
||||||
|
* instances.
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
|
|||||||
@@ -13,12 +13,15 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Spring Security ACL package which implements instance-based security for domain objects.
|
* The Spring Security ACL package which implements instance-based security for domain
|
||||||
|
* objects.
|
||||||
* <p>
|
* <p>
|
||||||
* Consider using the annotation based approach ({@code @PreAuthorize}, {@code @PostFilter} annotations) combined
|
* Consider using the annotation based approach ({@code @PreAuthorize},
|
||||||
* with a {@link org.springframework.security.acls.AclPermissionEvaluator} in preference to the older and more verbose
|
* {@code @PostFilter} annotations) combined with a
|
||||||
* attribute/voter/after-invocation approach from versions before Spring Security 3.0.
|
* {@link org.springframework.security.acls.AclPermissionEvaluator} in preference to the
|
||||||
|
* older and more verbose attribute/voter/after-invocation approach from versions before
|
||||||
|
* Spring Security 3.0.
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.acls;
|
package org.springframework.security.acls;
|
||||||
|
|
||||||
|
|||||||
@@ -13,15 +13,17 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls;
|
package org.springframework.security.acls;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.security.acls.domain.AclFormattingUtils;
|
||||||
|
import org.springframework.security.acls.model.Permission;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.fail;
|
import static org.assertj.core.api.Assertions.fail;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.springframework.security.acls.domain.AclFormattingUtils;
|
|
||||||
import org.springframework.security.acls.model.Permission;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link AclFormattingUtils}.
|
* Tests for {@link AclFormattingUtils}.
|
||||||
*
|
*
|
||||||
@@ -29,8 +31,6 @@ import org.springframework.security.acls.model.Permission;
|
|||||||
*/
|
*/
|
||||||
public class AclFormattingUtilsTests {
|
public class AclFormattingUtilsTests {
|
||||||
|
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
@Test
|
@Test
|
||||||
public final void testDemergePatternsParametersConstraints() {
|
public final void testDemergePatternsParametersConstraints() {
|
||||||
try {
|
try {
|
||||||
@@ -39,21 +39,18 @@ public class AclFormattingUtilsTests {
|
|||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
AclFormattingUtils.demergePatterns("SOME STRING", null);
|
AclFormattingUtils.demergePatterns("SOME STRING", null);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
AclFormattingUtils.demergePatterns("SOME STRING", "LONGER SOME STRING");
|
AclFormattingUtils.demergePatterns("SOME STRING", "LONGER SOME STRING");
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
AclFormattingUtils.demergePatterns("SOME STRING", "SAME LENGTH");
|
AclFormattingUtils.demergePatterns("SOME STRING", "SAME LENGTH");
|
||||||
}
|
}
|
||||||
@@ -66,13 +63,10 @@ public class AclFormattingUtilsTests {
|
|||||||
public final void testDemergePatterns() {
|
public final void testDemergePatterns() {
|
||||||
String original = "...........................A...R";
|
String original = "...........................A...R";
|
||||||
String removeBits = "...............................R";
|
String removeBits = "...............................R";
|
||||||
assertThat(AclFormattingUtils.demergePatterns(original, removeBits)).isEqualTo(
|
assertThat(AclFormattingUtils.demergePatterns(original, removeBits))
|
||||||
"...........................A....");
|
.isEqualTo("...........................A....");
|
||||||
|
assertThat(AclFormattingUtils.demergePatterns("ABCDEF", "......")).isEqualTo("ABCDEF");
|
||||||
assertThat(AclFormattingUtils.demergePatterns("ABCDEF", "......")).isEqualTo(
|
assertThat(AclFormattingUtils.demergePatterns("ABCDEF", "GHIJKL")).isEqualTo("......");
|
||||||
"ABCDEF");
|
|
||||||
assertThat(AclFormattingUtils.demergePatterns("ABCDEF", "GHIJKL")).isEqualTo(
|
|
||||||
"......");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -83,21 +77,18 @@ public class AclFormattingUtilsTests {
|
|||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
AclFormattingUtils.mergePatterns("SOME STRING", null);
|
AclFormattingUtils.mergePatterns("SOME STRING", null);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
AclFormattingUtils.mergePatterns("SOME STRING", "LONGER SOME STRING");
|
AclFormattingUtils.mergePatterns("SOME STRING", "LONGER SOME STRING");
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
AclFormattingUtils.mergePatterns("SOME STRING", "SAME LENGTH");
|
AclFormattingUtils.mergePatterns("SOME STRING", "SAME LENGTH");
|
||||||
}
|
}
|
||||||
@@ -109,47 +100,37 @@ public class AclFormattingUtilsTests {
|
|||||||
public final void testMergePatterns() {
|
public final void testMergePatterns() {
|
||||||
String original = "...............................R";
|
String original = "...............................R";
|
||||||
String extraBits = "...........................A....";
|
String extraBits = "...........................A....";
|
||||||
assertThat(AclFormattingUtils.mergePatterns(original, extraBits)).isEqualTo(
|
assertThat(AclFormattingUtils.mergePatterns(original, extraBits)).isEqualTo("...........................A...R");
|
||||||
"...........................A...R");
|
assertThat(AclFormattingUtils.mergePatterns("ABCDEF", "......")).isEqualTo("ABCDEF");
|
||||||
|
assertThat(AclFormattingUtils.mergePatterns("ABCDEF", "GHIJKL")).isEqualTo("GHIJKL");
|
||||||
assertThat(AclFormattingUtils.mergePatterns("ABCDEF", "......")).isEqualTo(
|
|
||||||
"ABCDEF");
|
|
||||||
assertThat(AclFormattingUtils.mergePatterns("ABCDEF", "GHIJKL")).isEqualTo(
|
|
||||||
"GHIJKL");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public final void testBinaryPrints() {
|
public final void testBinaryPrints() {
|
||||||
assertThat(AclFormattingUtils.printBinary(15)).isEqualTo(
|
assertThat(AclFormattingUtils.printBinary(15)).isEqualTo("............................****");
|
||||||
"............................****");
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
AclFormattingUtils.printBinary(15, Permission.RESERVED_ON);
|
AclFormattingUtils.printBinary(15, Permission.RESERVED_ON);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException notExpected) {
|
catch (IllegalArgumentException notExpected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
AclFormattingUtils.printBinary(15, Permission.RESERVED_OFF);
|
AclFormattingUtils.printBinary(15, Permission.RESERVED_OFF);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException notExpected) {
|
catch (IllegalArgumentException notExpected) {
|
||||||
}
|
}
|
||||||
|
assertThat(AclFormattingUtils.printBinary(15, 'x')).isEqualTo("............................xxxx");
|
||||||
assertThat(AclFormattingUtils.printBinary(15, 'x')).isEqualTo(
|
|
||||||
"............................xxxx");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPrintBinaryNegative() {
|
public void testPrintBinaryNegative() {
|
||||||
assertThat(AclFormattingUtils.printBinary(0x80000000)).isEqualTo(
|
assertThat(AclFormattingUtils.printBinary(0x80000000)).isEqualTo("*...............................");
|
||||||
"*...............................");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPrintBinaryMinusOne() {
|
public void testPrintBinaryMinusOne() {
|
||||||
assertThat(AclFormattingUtils.printBinary(0xffffffff)).isEqualTo(
|
assertThat(AclFormattingUtils.printBinary(0xffffffff)).isEqualTo("********************************");
|
||||||
"********************************");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-12
@@ -13,11 +13,15 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls;
|
package org.springframework.security.acls;
|
||||||
|
|
||||||
import static org.mockito.Mockito.*;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||||
import org.springframework.security.acls.model.AclService;
|
import org.springframework.security.acls.model.AclService;
|
||||||
import org.springframework.security.acls.model.ObjectIdentity;
|
import org.springframework.security.acls.model.ObjectIdentity;
|
||||||
@@ -25,9 +29,12 @@ import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
|
|||||||
import org.springframework.security.acls.model.SidRetrievalStrategy;
|
import org.springframework.security.acls.model.SidRetrievalStrategy;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import java.util.Collections;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import java.util.List;
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
@@ -44,13 +51,10 @@ public class AclPermissionCacheOptimizerTests {
|
|||||||
pco.setObjectIdentityRetrievalStrategy(oidStrat);
|
pco.setObjectIdentityRetrievalStrategy(oidStrat);
|
||||||
pco.setSidRetrievalStrategy(sidStrat);
|
pco.setSidRetrievalStrategy(sidStrat);
|
||||||
Object[] dos = { new Object(), null, new Object() };
|
Object[] dos = { new Object(), null, new Object() };
|
||||||
ObjectIdentity[] oids = { new ObjectIdentityImpl("A", "1"),
|
ObjectIdentity[] oids = { new ObjectIdentityImpl("A", "1"), new ObjectIdentityImpl("A", "2") };
|
||||||
new ObjectIdentityImpl("A", "2") };
|
given(oidStrat.getObjectIdentity(dos[0])).willReturn(oids[0]);
|
||||||
when(oidStrat.getObjectIdentity(dos[0])).thenReturn(oids[0]);
|
given(oidStrat.getObjectIdentity(dos[2])).willReturn(oids[1]);
|
||||||
when(oidStrat.getObjectIdentity(dos[2])).thenReturn(oids[1]);
|
|
||||||
|
|
||||||
pco.cachePermissionsFor(mock(Authentication.class), Arrays.asList(dos));
|
pco.cachePermissionsFor(mock(Authentication.class), Arrays.asList(dos));
|
||||||
|
|
||||||
// AclService should be invoked with the list of required Oids
|
// AclService should be invoked with the list of required Oids
|
||||||
verify(service).readAclsById(eq(Arrays.asList(oids)), any(List.class));
|
verify(service).readAclsById(eq(Arrays.asList(oids)), any(List.class));
|
||||||
}
|
}
|
||||||
@@ -63,9 +67,7 @@ public class AclPermissionCacheOptimizerTests {
|
|||||||
SidRetrievalStrategy sids = mock(SidRetrievalStrategy.class);
|
SidRetrievalStrategy sids = mock(SidRetrievalStrategy.class);
|
||||||
pco.setObjectIdentityRetrievalStrategy(oids);
|
pco.setObjectIdentityRetrievalStrategy(oids);
|
||||||
pco.setSidRetrievalStrategy(sids);
|
pco.setSidRetrievalStrategy(sids);
|
||||||
|
|
||||||
pco.cachePermissionsFor(mock(Authentication.class), Collections.emptyList());
|
pco.cachePermissionsFor(mock(Authentication.class), Collections.emptyList());
|
||||||
|
|
||||||
verifyZeroInteractions(service, sids, oids);
|
verifyZeroInteractions(service, sids, oids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-17
@@ -13,15 +13,13 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls;
|
package org.springframework.security.acls;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
|
||||||
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.Acl;
|
import org.springframework.security.acls.model.Acl;
|
||||||
import org.springframework.security.acls.model.AclService;
|
import org.springframework.security.acls.model.AclService;
|
||||||
import org.springframework.security.acls.model.ObjectIdentity;
|
import org.springframework.security.acls.model.ObjectIdentity;
|
||||||
@@ -29,8 +27,14 @@ import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
|
|||||||
import org.springframework.security.acls.model.SidRetrievalStrategy;
|
import org.springframework.security.acls.model.SidRetrievalStrategy;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyList;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
@@ -42,14 +46,12 @@ public class AclPermissionEvaluatorTests {
|
|||||||
AclPermissionEvaluator pe = new AclPermissionEvaluator(service);
|
AclPermissionEvaluator pe = new AclPermissionEvaluator(service);
|
||||||
ObjectIdentity oid = mock(ObjectIdentity.class);
|
ObjectIdentity oid = mock(ObjectIdentity.class);
|
||||||
ObjectIdentityRetrievalStrategy oidStrategy = mock(ObjectIdentityRetrievalStrategy.class);
|
ObjectIdentityRetrievalStrategy oidStrategy = mock(ObjectIdentityRetrievalStrategy.class);
|
||||||
when(oidStrategy.getObjectIdentity(any(Object.class))).thenReturn(oid);
|
given(oidStrategy.getObjectIdentity(any(Object.class))).willReturn(oid);
|
||||||
pe.setObjectIdentityRetrievalStrategy(oidStrategy);
|
pe.setObjectIdentityRetrievalStrategy(oidStrategy);
|
||||||
pe.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
|
pe.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
|
||||||
Acl acl = mock(Acl.class);
|
Acl acl = mock(Acl.class);
|
||||||
|
given(service.readAclById(any(ObjectIdentity.class), anyList())).willReturn(acl);
|
||||||
when(service.readAclById(any(ObjectIdentity.class), anyList())).thenReturn(acl);
|
given(acl.isGranted(anyList(), anyList(), eq(false))).willReturn(true);
|
||||||
when(acl.isGranted(anyList(), anyList(), eq(false))).thenReturn(true);
|
|
||||||
|
|
||||||
assertThat(pe.hasPermission(mock(Authentication.class), new Object(), "READ")).isTrue();
|
assertThat(pe.hasPermission(mock(Authentication.class), new Object(), "READ")).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,21 +59,18 @@ public class AclPermissionEvaluatorTests {
|
|||||||
public void resolvePermissionNonEnglishLocale() {
|
public void resolvePermissionNonEnglishLocale() {
|
||||||
Locale systemLocale = Locale.getDefault();
|
Locale systemLocale = Locale.getDefault();
|
||||||
Locale.setDefault(new Locale("tr"));
|
Locale.setDefault(new Locale("tr"));
|
||||||
|
|
||||||
AclService service = mock(AclService.class);
|
AclService service = mock(AclService.class);
|
||||||
AclPermissionEvaluator pe = new AclPermissionEvaluator(service);
|
AclPermissionEvaluator pe = new AclPermissionEvaluator(service);
|
||||||
ObjectIdentity oid = mock(ObjectIdentity.class);
|
ObjectIdentity oid = mock(ObjectIdentity.class);
|
||||||
ObjectIdentityRetrievalStrategy oidStrategy = mock(ObjectIdentityRetrievalStrategy.class);
|
ObjectIdentityRetrievalStrategy oidStrategy = mock(ObjectIdentityRetrievalStrategy.class);
|
||||||
when(oidStrategy.getObjectIdentity(any(Object.class))).thenReturn(oid);
|
given(oidStrategy.getObjectIdentity(any(Object.class))).willReturn(oid);
|
||||||
pe.setObjectIdentityRetrievalStrategy(oidStrategy);
|
pe.setObjectIdentityRetrievalStrategy(oidStrategy);
|
||||||
pe.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
|
pe.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
|
||||||
Acl acl = mock(Acl.class);
|
Acl acl = mock(Acl.class);
|
||||||
|
given(service.readAclById(any(ObjectIdentity.class), anyList())).willReturn(acl);
|
||||||
when(service.readAclById(any(ObjectIdentity.class), anyList())).thenReturn(acl);
|
given(acl.isGranted(anyList(), anyList(), eq(false))).willReturn(true);
|
||||||
when(acl.isGranted(anyList(), anyList(), eq(false))).thenReturn(true);
|
|
||||||
|
|
||||||
assertThat(pe.hasPermission(mock(Authentication.class), new Object(), "write")).isTrue();
|
assertThat(pe.hasPermission(mock(Authentication.class), new Object(), "write")).isTrue();
|
||||||
|
|
||||||
Locale.setDefault(systemLocale);
|
Locale.setDefault(systemLocale);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls;
|
package org.springframework.security.acls;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls;
|
package org.springframework.security.acls;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -27,10 +28,11 @@ public final class TargetObjectWithUUID {
|
|||||||
private UUID id;
|
private UUID id;
|
||||||
|
|
||||||
public UUID getId() {
|
public UUID getId() {
|
||||||
return id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(UUID id) {
|
public void setId(UUID id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-26
@@ -13,46 +13,54 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.afterinvocation;
|
package org.springframework.security.acls.afterinvocation;
|
||||||
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
|
||||||
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.springframework.security.access.ConfigAttribute;
|
|
||||||
import org.springframework.security.access.SecurityConfig;
|
|
||||||
import org.springframework.security.acls.model.*;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.security.access.ConfigAttribute;
|
||||||
|
import org.springframework.security.access.SecurityConfig;
|
||||||
|
import org.springframework.security.acls.model.Acl;
|
||||||
|
import org.springframework.security.acls.model.AclService;
|
||||||
|
import org.springframework.security.acls.model.ObjectIdentity;
|
||||||
|
import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
|
||||||
|
import org.springframework.security.acls.model.Permission;
|
||||||
|
import org.springframework.security.acls.model.SidRetrievalStrategy;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "unchecked" })
|
@SuppressWarnings({ "unchecked" })
|
||||||
public class AclEntryAfterInvocationCollectionFilteringProviderTests {
|
public class AclEntryAfterInvocationCollectionFilteringProviderTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void objectsAreRemovedIfPermissionDenied() {
|
public void objectsAreRemovedIfPermissionDenied() {
|
||||||
AclService service = mock(AclService.class);
|
AclService service = mock(AclService.class);
|
||||||
Acl acl = mock(Acl.class);
|
Acl acl = mock(Acl.class);
|
||||||
when(acl.isGranted(any(), any(), anyBoolean())).thenReturn(
|
given(acl.isGranted(any(), any(), anyBoolean())).willReturn(false);
|
||||||
false);
|
given(service.readAclById(any(), any())).willReturn(acl);
|
||||||
when(service.readAclById(any(), any())).thenReturn(
|
|
||||||
acl);
|
|
||||||
AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider(
|
AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider(
|
||||||
service, Arrays.asList(mock(Permission.class)));
|
service, Arrays.asList(mock(Permission.class)));
|
||||||
provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class));
|
provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class));
|
||||||
provider.setProcessDomainObjectClass(Object.class);
|
provider.setProcessDomainObjectClass(Object.class);
|
||||||
provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
|
provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
|
||||||
|
|
||||||
Object returned = provider.decide(mock(Authentication.class), new Object(),
|
Object returned = provider.decide(mock(Authentication.class), new Object(),
|
||||||
SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), new ArrayList(
|
SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"),
|
||||||
Arrays.asList(new Object(), new Object())));
|
new ArrayList(Arrays.asList(new Object(), new Object())));
|
||||||
assertThat(returned).isInstanceOf(List.class);
|
assertThat(returned).isInstanceOf(List.class);
|
||||||
assertThat(((List) returned)).isEmpty();
|
assertThat(((List) returned)).isEmpty();
|
||||||
returned = provider.decide(mock(Authentication.class), new Object(),
|
returned = provider.decide(mock(Authentication.class), new Object(),
|
||||||
@@ -67,11 +75,8 @@ public class AclEntryAfterInvocationCollectionFilteringProviderTests {
|
|||||||
AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider(
|
AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider(
|
||||||
mock(AclService.class), Arrays.asList(mock(Permission.class)));
|
mock(AclService.class), Arrays.asList(mock(Permission.class)));
|
||||||
Object returned = new Object();
|
Object returned = new Object();
|
||||||
|
assertThat(returned).isSameAs(provider.decide(mock(Authentication.class), new Object(),
|
||||||
assertThat(returned)
|
Collections.<ConfigAttribute>emptyList(), returned));
|
||||||
.isSameAs(
|
|
||||||
provider.decide(mock(Authentication.class), new Object(),
|
|
||||||
Collections.<ConfigAttribute> emptyList(), returned));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -79,10 +84,8 @@ public class AclEntryAfterInvocationCollectionFilteringProviderTests {
|
|||||||
AclService service = mock(AclService.class);
|
AclService service = mock(AclService.class);
|
||||||
AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider(
|
AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider(
|
||||||
service, Arrays.asList(mock(Permission.class)));
|
service, Arrays.asList(mock(Permission.class)));
|
||||||
|
|
||||||
assertThat(provider.decide(mock(Authentication.class), new Object(),
|
assertThat(provider.decide(mock(Authentication.class), new Object(),
|
||||||
SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null))
|
SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null)).isNull();
|
||||||
.isNull();
|
|
||||||
verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class));
|
verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+50
-56
@@ -13,23 +13,37 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.afterinvocation;
|
package org.springframework.security.acls.afterinvocation;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.springframework.security.access.AccessDeniedException;
|
|
||||||
import org.springframework.security.access.ConfigAttribute;
|
|
||||||
import org.springframework.security.access.SecurityConfig;
|
|
||||||
import org.springframework.security.acls.model.*;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
|
import org.springframework.security.access.ConfigAttribute;
|
||||||
|
import org.springframework.security.access.SecurityConfig;
|
||||||
|
import org.springframework.security.acls.model.Acl;
|
||||||
|
import org.springframework.security.acls.model.AclService;
|
||||||
|
import org.springframework.security.acls.model.NotFoundException;
|
||||||
|
import org.springframework.security.acls.model.ObjectIdentity;
|
||||||
|
import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
|
||||||
|
import org.springframework.security.acls.model.Permission;
|
||||||
|
import org.springframework.security.acls.model.SidRetrievalStrategy;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.fail;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
*/
|
*/
|
||||||
@@ -44,74 +58,56 @@ public class AclEntryAfterInvocationProviderTests {
|
|||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
new AclEntryAfterInvocationProvider(mock(AclService.class),
|
new AclEntryAfterInvocationProvider(mock(AclService.class), Collections.<Permission>emptyList());
|
||||||
Collections.<Permission> emptyList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void accessIsAllowedIfPermissionIsGranted() {
|
public void accessIsAllowedIfPermissionIsGranted() {
|
||||||
AclService service = mock(AclService.class);
|
AclService service = mock(AclService.class);
|
||||||
Acl acl = mock(Acl.class);
|
Acl acl = mock(Acl.class);
|
||||||
when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn(
|
given(acl.isGranted(any(List.class), any(List.class), anyBoolean())).willReturn(true);
|
||||||
true);
|
given(service.readAclById(any(), any())).willReturn(acl);
|
||||||
when(service.readAclById(any(), any())).thenReturn(
|
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(service,
|
||||||
acl);
|
Arrays.asList(mock(Permission.class)));
|
||||||
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(
|
|
||||||
service, Arrays.asList(mock(Permission.class)));
|
|
||||||
provider.setMessageSource(new SpringSecurityMessageSource());
|
provider.setMessageSource(new SpringSecurityMessageSource());
|
||||||
provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class));
|
provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class));
|
||||||
provider.setProcessDomainObjectClass(Object.class);
|
provider.setProcessDomainObjectClass(Object.class);
|
||||||
provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
|
provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
|
||||||
Object returned = new Object();
|
Object returned = new Object();
|
||||||
|
assertThat(returned).isSameAs(provider.decide(mock(Authentication.class), new Object(),
|
||||||
assertThat(
|
SecurityConfig.createList("AFTER_ACL_READ"), returned));
|
||||||
returned)
|
|
||||||
.isSameAs(
|
|
||||||
provider.decide(mock(Authentication.class), new Object(),
|
|
||||||
SecurityConfig.createList("AFTER_ACL_READ"), returned));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void accessIsGrantedIfNoAttributesDefined() {
|
public void accessIsGrantedIfNoAttributesDefined() {
|
||||||
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(
|
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(mock(AclService.class),
|
||||||
mock(AclService.class), Arrays.asList(mock(Permission.class)));
|
Arrays.asList(mock(Permission.class)));
|
||||||
Object returned = new Object();
|
Object returned = new Object();
|
||||||
|
assertThat(returned).isSameAs(provider.decide(mock(Authentication.class), new Object(),
|
||||||
assertThat(
|
Collections.<ConfigAttribute>emptyList(), returned));
|
||||||
returned)
|
|
||||||
.isSameAs(
|
|
||||||
provider.decide(mock(Authentication.class), new Object(),
|
|
||||||
Collections.<ConfigAttribute> emptyList(), returned));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void accessIsGrantedIfObjectTypeNotSupported() {
|
public void accessIsGrantedIfObjectTypeNotSupported() {
|
||||||
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(
|
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(mock(AclService.class),
|
||||||
mock(AclService.class), Arrays.asList(mock(Permission.class)));
|
Arrays.asList(mock(Permission.class)));
|
||||||
provider.setProcessDomainObjectClass(String.class);
|
provider.setProcessDomainObjectClass(String.class);
|
||||||
// Not a String
|
// Not a String
|
||||||
Object returned = new Object();
|
Object returned = new Object();
|
||||||
|
assertThat(returned).isSameAs(provider.decide(mock(Authentication.class), new Object(),
|
||||||
assertThat(
|
SecurityConfig.createList("AFTER_ACL_READ"), returned));
|
||||||
returned)
|
|
||||||
.isSameAs(
|
|
||||||
provider.decide(mock(Authentication.class), new Object(),
|
|
||||||
SecurityConfig.createList("AFTER_ACL_READ"), returned));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = AccessDeniedException.class)
|
@Test(expected = AccessDeniedException.class)
|
||||||
public void accessIsDeniedIfPermissionIsNotGranted() {
|
public void accessIsDeniedIfPermissionIsNotGranted() {
|
||||||
AclService service = mock(AclService.class);
|
AclService service = mock(AclService.class);
|
||||||
Acl acl = mock(Acl.class);
|
Acl acl = mock(Acl.class);
|
||||||
when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn(
|
given(acl.isGranted(any(List.class), any(List.class), anyBoolean())).willReturn(false);
|
||||||
false);
|
|
||||||
// Try a second time with no permissions found
|
// Try a second time with no permissions found
|
||||||
when(acl.isGranted(any(), any(List.class), anyBoolean())).thenThrow(
|
given(acl.isGranted(any(), any(List.class), anyBoolean())).willThrow(new NotFoundException(""));
|
||||||
new NotFoundException(""));
|
given(service.readAclById(any(), any())).willReturn(acl);
|
||||||
when(service.readAclById(any(), any())).thenReturn(
|
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(service,
|
||||||
acl);
|
Arrays.asList(mock(Permission.class)));
|
||||||
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(
|
|
||||||
service, Arrays.asList(mock(Permission.class)));
|
|
||||||
provider.setProcessConfigAttribute("MY_ATTRIBUTE");
|
provider.setProcessConfigAttribute("MY_ATTRIBUTE");
|
||||||
provider.setMessageSource(new SpringSecurityMessageSource());
|
provider.setMessageSource(new SpringSecurityMessageSource());
|
||||||
provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class));
|
provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class));
|
||||||
@@ -119,8 +115,7 @@ public class AclEntryAfterInvocationProviderTests {
|
|||||||
provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
|
provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
|
||||||
try {
|
try {
|
||||||
provider.decide(mock(Authentication.class), new Object(),
|
provider.decide(mock(Authentication.class), new Object(),
|
||||||
SecurityConfig.createList("UNSUPPORTED", "MY_ATTRIBUTE"),
|
SecurityConfig.createList("UNSUPPORTED", "MY_ATTRIBUTE"), new Object());
|
||||||
new Object());
|
|
||||||
fail("Expected Exception");
|
fail("Expected Exception");
|
||||||
}
|
}
|
||||||
catch (AccessDeniedException expected) {
|
catch (AccessDeniedException expected) {
|
||||||
@@ -133,12 +128,11 @@ public class AclEntryAfterInvocationProviderTests {
|
|||||||
@Test
|
@Test
|
||||||
public void nullReturnObjectIsIgnored() {
|
public void nullReturnObjectIsIgnored() {
|
||||||
AclService service = mock(AclService.class);
|
AclService service = mock(AclService.class);
|
||||||
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(
|
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(service,
|
||||||
service, Arrays.asList(mock(Permission.class)));
|
Arrays.asList(mock(Permission.class)));
|
||||||
|
|
||||||
assertThat(provider.decide(mock(Authentication.class), new Object(),
|
assertThat(provider.decide(mock(Authentication.class), new Object(),
|
||||||
SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null))
|
SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null)).isNull();
|
||||||
.isNull();
|
|
||||||
verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class));
|
verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-38
@@ -13,18 +13,22 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.AccessControlEntry;
|
import org.springframework.security.acls.model.AccessControlEntry;
|
||||||
import org.springframework.security.acls.model.Acl;
|
import org.springframework.security.acls.model.Acl;
|
||||||
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
||||||
import org.springframework.security.acls.model.ObjectIdentity;
|
import org.springframework.security.acls.model.ObjectIdentity;
|
||||||
import org.springframework.security.acls.model.Sid;
|
import org.springframework.security.acls.model.Sid;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.fail;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link AccessControlEntryImpl}.
|
* Tests for {@link AccessControlEntryImpl}.
|
||||||
*
|
*
|
||||||
@@ -32,33 +36,26 @@ import org.springframework.security.acls.model.Sid;
|
|||||||
*/
|
*/
|
||||||
public class AccessControlImplEntryTests {
|
public class AccessControlImplEntryTests {
|
||||||
|
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConstructorRequiredFields() {
|
public void testConstructorRequiredFields() {
|
||||||
// Check Acl field is present
|
// Check Acl field is present
|
||||||
try {
|
try {
|
||||||
new AccessControlEntryImpl(null, null, new PrincipalSid("johndoe"),
|
new AccessControlEntryImpl(null, null, new PrincipalSid("johndoe"), BasePermission.ADMINISTRATION, true,
|
||||||
BasePermission.ADMINISTRATION, true, true, true);
|
true, true);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check Sid field is present
|
// Check Sid field is present
|
||||||
try {
|
try {
|
||||||
new AccessControlEntryImpl(null, mock(Acl.class), null,
|
new AccessControlEntryImpl(null, mock(Acl.class), null, BasePermission.ADMINISTRATION, true, true, true);
|
||||||
BasePermission.ADMINISTRATION, true, true, true);
|
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check Permission field is present
|
// Check Permission field is present
|
||||||
try {
|
try {
|
||||||
new AccessControlEntryImpl(null, mock(Acl.class),
|
new AccessControlEntryImpl(null, mock(Acl.class), new PrincipalSid("johndoe"), null, true, true, true);
|
||||||
new PrincipalSid("johndoe"), null, true, true, true);
|
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
@@ -69,11 +66,9 @@ public class AccessControlImplEntryTests {
|
|||||||
public void testAccessControlEntryImplGetters() {
|
public void testAccessControlEntryImplGetters() {
|
||||||
Acl mockAcl = mock(Acl.class);
|
Acl mockAcl = mock(Acl.class);
|
||||||
Sid sid = new PrincipalSid("johndoe");
|
Sid sid = new PrincipalSid("johndoe");
|
||||||
|
|
||||||
// Create a sample entry
|
// Create a sample entry
|
||||||
AccessControlEntry ace = new AccessControlEntryImpl(1L, mockAcl,
|
AccessControlEntry ace = new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, true, true,
|
||||||
sid, BasePermission.ADMINISTRATION, true, true, true);
|
true);
|
||||||
|
|
||||||
// and check every get() method
|
// and check every get() method
|
||||||
assertThat(ace.getId()).isEqualTo(1L);
|
assertThat(ace.getId()).isEqualTo(1L);
|
||||||
assertThat(ace.getAcl()).isEqualTo(mockAcl);
|
assertThat(ace.getAcl()).isEqualTo(mockAcl);
|
||||||
@@ -88,30 +83,27 @@ public class AccessControlImplEntryTests {
|
|||||||
public void testEquals() {
|
public void testEquals() {
|
||||||
final Acl mockAcl = mock(Acl.class);
|
final Acl mockAcl = mock(Acl.class);
|
||||||
final ObjectIdentity oid = mock(ObjectIdentity.class);
|
final ObjectIdentity oid = mock(ObjectIdentity.class);
|
||||||
|
given(mockAcl.getObjectIdentity()).willReturn(oid);
|
||||||
when(mockAcl.getObjectIdentity()).thenReturn(oid);
|
|
||||||
Sid sid = new PrincipalSid("johndoe");
|
Sid sid = new PrincipalSid("johndoe");
|
||||||
|
AccessControlEntry ace = new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, true, true,
|
||||||
AccessControlEntry ace = new AccessControlEntryImpl(1L, mockAcl,
|
true);
|
||||||
sid, BasePermission.ADMINISTRATION, true, true, true);
|
|
||||||
|
|
||||||
assertThat(ace).isNotNull();
|
assertThat(ace).isNotNull();
|
||||||
assertThat(ace).isNotEqualTo(100L);
|
assertThat(ace).isNotEqualTo(100L);
|
||||||
assertThat(ace).isEqualTo(ace);
|
assertThat(ace).isEqualTo(ace);
|
||||||
assertThat(ace).isEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid,
|
assertThat(ace).isEqualTo(
|
||||||
|
new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, true, true, true));
|
||||||
|
assertThat(ace).isNotEqualTo(
|
||||||
|
new AccessControlEntryImpl(2L, mockAcl, sid, BasePermission.ADMINISTRATION, true, true, true));
|
||||||
|
assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, new PrincipalSid("scott"),
|
||||||
BasePermission.ADMINISTRATION, true, true, true));
|
BasePermission.ADMINISTRATION, true, true, true));
|
||||||
assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(2L, mockAcl, sid,
|
assertThat(ace)
|
||||||
BasePermission.ADMINISTRATION, true, true, true));
|
.isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.WRITE, true, true, true));
|
||||||
assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl,
|
assertThat(ace).isNotEqualTo(
|
||||||
new PrincipalSid("scott"), BasePermission.ADMINISTRATION, true, true,
|
new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, false, true, true));
|
||||||
true));
|
assertThat(ace).isNotEqualTo(
|
||||||
assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid,
|
new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, true, false, true));
|
||||||
BasePermission.WRITE, true, true, true));
|
assertThat(ace).isNotEqualTo(
|
||||||
assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid,
|
new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, true, true, false));
|
||||||
BasePermission.ADMINISTRATION, false, true, true));
|
|
||||||
assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid,
|
|
||||||
BasePermission.ADMINISTRATION, true, false, true));
|
|
||||||
assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid,
|
|
||||||
BasePermission.ADMINISTRATION, true, true, false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-7
@@ -13,8 +13,8 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.acls.domain;
|
|
||||||
|
|
||||||
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@@ -24,6 +24,7 @@ import org.junit.Test;
|
|||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.Acl;
|
import org.springframework.security.acls.model.Acl;
|
||||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
@@ -31,21 +32,24 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class AclAuthorizationStrategyImplTests {
|
public class AclAuthorizationStrategyImplTests {
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
Acl acl;
|
Acl acl;
|
||||||
|
|
||||||
GrantedAuthority authority;
|
GrantedAuthority authority;
|
||||||
|
|
||||||
AclAuthorizationStrategyImpl strategy;
|
AclAuthorizationStrategyImpl strategy;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
authority = new SimpleGrantedAuthority("ROLE_AUTH");
|
this.authority = new SimpleGrantedAuthority("ROLE_AUTH");
|
||||||
TestingAuthenticationToken authentication = new TestingAuthenticationToken("foo", "bar", Arrays.asList(authority));
|
TestingAuthenticationToken authentication = new TestingAuthenticationToken("foo", "bar",
|
||||||
|
Arrays.asList(this.authority));
|
||||||
authentication.setAuthenticated(true);
|
authentication.setAuthenticated(true);
|
||||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||||
}
|
}
|
||||||
@@ -58,15 +62,18 @@ public class AclAuthorizationStrategyImplTests {
|
|||||||
// gh-4085
|
// gh-4085
|
||||||
@Test
|
@Test
|
||||||
public void securityCheckWhenCustomAuthorityThenNameIsUsed() {
|
public void securityCheckWhenCustomAuthorityThenNameIsUsed() {
|
||||||
strategy = new AclAuthorizationStrategyImpl(new CustomAuthority());
|
this.strategy = new AclAuthorizationStrategyImpl(new CustomAuthority());
|
||||||
strategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_GENERAL);
|
this.strategy.securityCheck(this.acl, AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
class CustomAuthority implements GrantedAuthority {
|
class CustomAuthority implements GrantedAuthority {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAuthority() {
|
public String getAuthority() {
|
||||||
return authority.getAuthority();
|
return AclAuthorizationStrategyImplTests.this.authority.getAuthority();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,21 +13,41 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
import java.lang.reflect.Field;
|
||||||
import static org.mockito.Mockito.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.After;
|
||||||
import org.springframework.security.acls.model.*;
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.security.acls.model.AccessControlEntry;
|
||||||
|
import org.springframework.security.acls.model.Acl;
|
||||||
|
import org.springframework.security.acls.model.AlreadyExistsException;
|
||||||
|
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
||||||
|
import org.springframework.security.acls.model.AuditableAcl;
|
||||||
|
import org.springframework.security.acls.model.ChildrenExistException;
|
||||||
|
import org.springframework.security.acls.model.MutableAcl;
|
||||||
|
import org.springframework.security.acls.model.MutableAclService;
|
||||||
|
import org.springframework.security.acls.model.NotFoundException;
|
||||||
|
import org.springframework.security.acls.model.ObjectIdentity;
|
||||||
|
import org.springframework.security.acls.model.Permission;
|
||||||
|
import org.springframework.security.acls.model.PermissionGrantingStrategy;
|
||||||
|
import org.springframework.security.acls.model.Sid;
|
||||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.util.FieldUtils;
|
import org.springframework.security.util.FieldUtils;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import java.util.*;
|
import static org.assertj.core.api.Assertions.fail;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link AclImpl}.
|
* Tests for {@link AclImpl}.
|
||||||
@@ -35,33 +55,41 @@ import java.util.*;
|
|||||||
* @author Andrei Stefan
|
* @author Andrei Stefan
|
||||||
*/
|
*/
|
||||||
public class AclImplTests {
|
public class AclImplTests {
|
||||||
|
|
||||||
private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject";
|
private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject";
|
||||||
|
|
||||||
private static final List<Permission> READ = Arrays.asList(BasePermission.READ);
|
private static final List<Permission> READ = Arrays.asList(BasePermission.READ);
|
||||||
|
|
||||||
private static final List<Permission> WRITE = Arrays.asList(BasePermission.WRITE);
|
private static final List<Permission> WRITE = Arrays.asList(BasePermission.WRITE);
|
||||||
|
|
||||||
private static final List<Permission> CREATE = Arrays.asList(BasePermission.CREATE);
|
private static final List<Permission> CREATE = Arrays.asList(BasePermission.CREATE);
|
||||||
|
|
||||||
private static final List<Permission> DELETE = Arrays.asList(BasePermission.DELETE);
|
private static final List<Permission> DELETE = Arrays.asList(BasePermission.DELETE);
|
||||||
|
|
||||||
private static final List<Sid> SCOTT = Arrays.asList((Sid) new PrincipalSid("scott"));
|
private static final List<Sid> SCOTT = Arrays.asList((Sid) new PrincipalSid("scott"));
|
||||||
|
|
||||||
private static final List<Sid> BEN = Arrays.asList((Sid) new PrincipalSid("ben"));
|
private static final List<Sid> BEN = Arrays.asList((Sid) new PrincipalSid("ben"));
|
||||||
|
|
||||||
Authentication auth = new TestingAuthenticationToken("joe", "ignored",
|
Authentication auth = new TestingAuthenticationToken("joe", "ignored", "ROLE_ADMINISTRATOR");
|
||||||
"ROLE_ADMINISTRATOR");
|
|
||||||
AclAuthorizationStrategy authzStrategy;
|
|
||||||
PermissionGrantingStrategy pgs;
|
|
||||||
AuditLogger mockAuditLogger;
|
|
||||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(TARGET_CLASS, 100);
|
|
||||||
private DefaultPermissionFactory permissionFactory;
|
|
||||||
|
|
||||||
// ~ Methods
|
AclAuthorizationStrategy authzStrategy;
|
||||||
// ========================================================================================================
|
|
||||||
|
PermissionGrantingStrategy pgs;
|
||||||
|
|
||||||
|
AuditLogger mockAuditLogger;
|
||||||
|
|
||||||
|
ObjectIdentity objectIdentity = new ObjectIdentityImpl(TARGET_CLASS, 100);
|
||||||
|
|
||||||
|
private DefaultPermissionFactory permissionFactory;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(this.auth);
|
||||||
authzStrategy = mock(AclAuthorizationStrategy.class);
|
this.authzStrategy = mock(AclAuthorizationStrategy.class);
|
||||||
mockAuditLogger = mock(AuditLogger.class);
|
this.mockAuditLogger = mock(AuditLogger.class);
|
||||||
pgs = new DefaultPermissionGrantingStrategy(mockAuditLogger);
|
this.pgs = new DefaultPermissionGrantingStrategy(this.mockAuditLogger);
|
||||||
auth.setAuthenticated(true);
|
this.auth.setAuthenticated(true);
|
||||||
permissionFactory = new DefaultPermissionFactory();
|
this.permissionFactory = new DefaultPermissionFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@@ -72,44 +100,43 @@ public class AclImplTests {
|
|||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void constructorsRejectNullObjectIdentity() {
|
public void constructorsRejectNullObjectIdentity() {
|
||||||
try {
|
try {
|
||||||
new AclImpl(null, 1, authzStrategy, pgs, null, null, true, new PrincipalSid(
|
new AclImpl(null, 1, this.authzStrategy, this.pgs, null, null, true, new PrincipalSid("joe"));
|
||||||
"joe"));
|
|
||||||
fail("Should have thrown IllegalArgumentException");
|
fail("Should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
new AclImpl(null, 1, authzStrategy, mockAuditLogger);
|
new AclImpl(null, 1, this.authzStrategy, this.mockAuditLogger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void constructorsRejectNullId() {
|
public void constructorsRejectNullId() {
|
||||||
try {
|
try {
|
||||||
new AclImpl(objectIdentity, null, authzStrategy, pgs, null, null, true,
|
new AclImpl(this.objectIdentity, null, this.authzStrategy, this.pgs, null, null, true,
|
||||||
new PrincipalSid("joe"));
|
new PrincipalSid("joe"));
|
||||||
fail("Should have thrown IllegalArgumentException");
|
fail("Should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
new AclImpl(objectIdentity, null, authzStrategy, mockAuditLogger);
|
new AclImpl(this.objectIdentity, null, this.authzStrategy, this.mockAuditLogger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void constructorsRejectNullAclAuthzStrategy() {
|
public void constructorsRejectNullAclAuthzStrategy() {
|
||||||
try {
|
try {
|
||||||
new AclImpl(objectIdentity, 1, null, new DefaultPermissionGrantingStrategy(
|
new AclImpl(this.objectIdentity, 1, null, new DefaultPermissionGrantingStrategy(this.mockAuditLogger), null,
|
||||||
mockAuditLogger), null, null, true, new PrincipalSid("joe"));
|
null, true, new PrincipalSid("joe"));
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
new AclImpl(objectIdentity, 1, null, mockAuditLogger);
|
new AclImpl(this.objectIdentity, 1, null, this.mockAuditLogger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void insertAceRejectsNullParameters() {
|
public void insertAceRejectsNullParameters() {
|
||||||
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null,
|
MutableAcl acl = new AclImpl(this.objectIdentity, 1, this.authzStrategy, this.pgs, null, null, true,
|
||||||
true, new PrincipalSid("joe"));
|
new PrincipalSid("joe"));
|
||||||
try {
|
try {
|
||||||
acl.insertAce(0, null, new GrantedAuthoritySid("ROLE_IGNORED"), true);
|
acl.insertAce(0, null, new GrantedAuthoritySid("ROLE_IGNORED"), true);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
@@ -126,10 +153,9 @@ public class AclImplTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void insertAceAddsElementAtCorrectIndex() {
|
public void insertAceAddsElementAtCorrectIndex() {
|
||||||
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null,
|
MutableAcl acl = new AclImpl(this.objectIdentity, 1, this.authzStrategy, this.pgs, null, null, true,
|
||||||
true, new PrincipalSid("joe"));
|
new PrincipalSid("joe"));
|
||||||
MockAclService service = new MockAclService();
|
MockAclService service = new MockAclService();
|
||||||
|
|
||||||
// Insert one permission
|
// Insert one permission
|
||||||
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST1"), true);
|
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST1"), true);
|
||||||
service.updateAcl(acl);
|
service.updateAcl(acl);
|
||||||
@@ -137,9 +163,7 @@ public class AclImplTests {
|
|||||||
assertThat(acl.getEntries()).hasSize(1);
|
assertThat(acl.getEntries()).hasSize(1);
|
||||||
assertThat(acl).isEqualTo(acl.getEntries().get(0).getAcl());
|
assertThat(acl).isEqualTo(acl.getEntries().get(0).getAcl());
|
||||||
assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(0).getPermission());
|
assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(0).getPermission());
|
||||||
assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid(
|
assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST1"));
|
||||||
"ROLE_TEST1"));
|
|
||||||
|
|
||||||
// Add a second permission
|
// Add a second permission
|
||||||
acl.insertAce(1, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), true);
|
acl.insertAce(1, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), true);
|
||||||
service.updateAcl(acl);
|
service.updateAcl(acl);
|
||||||
@@ -147,71 +171,54 @@ public class AclImplTests {
|
|||||||
assertThat(acl.getEntries()).hasSize(2);
|
assertThat(acl.getEntries()).hasSize(2);
|
||||||
assertThat(acl).isEqualTo(acl.getEntries().get(1).getAcl());
|
assertThat(acl).isEqualTo(acl.getEntries().get(1).getAcl());
|
||||||
assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(1).getPermission());
|
assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(1).getPermission());
|
||||||
assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid(
|
assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST2"));
|
||||||
"ROLE_TEST2"));
|
|
||||||
|
|
||||||
// Add a third permission, after the first one
|
// Add a third permission, after the first one
|
||||||
acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_TEST3"),
|
acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_TEST3"), false);
|
||||||
false);
|
|
||||||
service.updateAcl(acl);
|
service.updateAcl(acl);
|
||||||
assertThat(acl.getEntries()).hasSize(3);
|
assertThat(acl.getEntries()).hasSize(3);
|
||||||
// Check the third entry was added between the two existent ones
|
// Check the third entry was added between the two existent ones
|
||||||
assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(0).getPermission());
|
assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(0).getPermission());
|
||||||
assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid(
|
assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST1"));
|
||||||
"ROLE_TEST1"));
|
|
||||||
assertThat(BasePermission.WRITE).isEqualTo(acl.getEntries().get(1).getPermission());
|
assertThat(BasePermission.WRITE).isEqualTo(acl.getEntries().get(1).getPermission());
|
||||||
assertThat(acl.getEntries().get(1).getSid()).isEqualTo( new GrantedAuthoritySid(
|
assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST3"));
|
||||||
"ROLE_TEST3"));
|
|
||||||
assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(2).getPermission());
|
assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(2).getPermission());
|
||||||
assertThat(acl.getEntries().get(2).getSid()).isEqualTo(new GrantedAuthoritySid(
|
assertThat(acl.getEntries().get(2).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST2"));
|
||||||
"ROLE_TEST2"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = NotFoundException.class)
|
@Test(expected = NotFoundException.class)
|
||||||
public void insertAceFailsForNonExistentElement() {
|
public void insertAceFailsForNonExistentElement() {
|
||||||
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null,
|
MutableAcl acl = new AclImpl(this.objectIdentity, 1, this.authzStrategy, this.pgs, null, null, true,
|
||||||
true, new PrincipalSid("joe"));
|
new PrincipalSid("joe"));
|
||||||
MockAclService service = new MockAclService();
|
MockAclService service = new MockAclService();
|
||||||
|
|
||||||
// Insert one permission
|
// Insert one permission
|
||||||
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST1"), true);
|
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST1"), true);
|
||||||
service.updateAcl(acl);
|
service.updateAcl(acl);
|
||||||
|
acl.insertAce(55, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), true);
|
||||||
acl.insertAce(55, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"),
|
|
||||||
true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void deleteAceKeepsInitialOrdering() {
|
public void deleteAceKeepsInitialOrdering() {
|
||||||
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null,
|
MutableAcl acl = new AclImpl(this.objectIdentity, 1, this.authzStrategy, this.pgs, null, null, true,
|
||||||
true, new PrincipalSid("joe"));
|
new PrincipalSid("joe"));
|
||||||
MockAclService service = new MockAclService();
|
MockAclService service = new MockAclService();
|
||||||
|
|
||||||
// Add several permissions
|
// Add several permissions
|
||||||
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST1"), true);
|
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST1"), true);
|
||||||
acl.insertAce(1, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), true);
|
acl.insertAce(1, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), true);
|
||||||
acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST3"), true);
|
acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST3"), true);
|
||||||
service.updateAcl(acl);
|
service.updateAcl(acl);
|
||||||
|
|
||||||
// Delete first permission and check the order of the remaining permissions is
|
// Delete first permission and check the order of the remaining permissions is
|
||||||
// kept
|
// kept
|
||||||
acl.deleteAce(0);
|
acl.deleteAce(0);
|
||||||
assertThat(acl.getEntries()).hasSize(2);
|
assertThat(acl.getEntries()).hasSize(2);
|
||||||
assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid(
|
assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST2"));
|
||||||
"ROLE_TEST2"));
|
assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST3"));
|
||||||
assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid(
|
|
||||||
"ROLE_TEST3"));
|
|
||||||
|
|
||||||
// Add one more permission and remove the permission in the middle
|
// Add one more permission and remove the permission in the middle
|
||||||
acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST4"), true);
|
acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST4"), true);
|
||||||
service.updateAcl(acl);
|
service.updateAcl(acl);
|
||||||
acl.deleteAce(1);
|
acl.deleteAce(1);
|
||||||
assertThat(acl.getEntries()).hasSize(2);
|
assertThat(acl.getEntries()).hasSize(2);
|
||||||
assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid(
|
assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST2"));
|
||||||
"ROLE_TEST2"));
|
assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST4"));
|
||||||
assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid(
|
|
||||||
"ROLE_TEST4"));
|
|
||||||
|
|
||||||
// Remove remaining permissions
|
// Remove remaining permissions
|
||||||
acl.deleteAce(1);
|
acl.deleteAce(1);
|
||||||
acl.deleteAce(0);
|
acl.deleteAce(0);
|
||||||
@@ -221,10 +228,10 @@ public class AclImplTests {
|
|||||||
@Test
|
@Test
|
||||||
public void deleteAceFailsForNonExistentElement() {
|
public void deleteAceFailsForNonExistentElement() {
|
||||||
AclAuthorizationStrategyImpl strategy = new AclAuthorizationStrategyImpl(
|
AclAuthorizationStrategyImpl strategy = new AclAuthorizationStrategyImpl(
|
||||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority(
|
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||||
"ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL"));
|
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||||
MutableAcl acl = new AclImpl(objectIdentity, (1), strategy, pgs, null, null,
|
MutableAcl acl = new AclImpl(this.objectIdentity, (1), strategy, this.pgs, null, null, true,
|
||||||
true, new PrincipalSid("joe"));
|
new PrincipalSid("joe"));
|
||||||
try {
|
try {
|
||||||
acl.deleteAce(99);
|
acl.deleteAce(99);
|
||||||
fail("It should have thrown NotFoundException");
|
fail("It should have thrown NotFoundException");
|
||||||
@@ -235,8 +242,8 @@ public class AclImplTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isGrantingRejectsEmptyParameters() {
|
public void isGrantingRejectsEmptyParameters() {
|
||||||
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null,
|
MutableAcl acl = new AclImpl(this.objectIdentity, 1, this.authzStrategy, this.pgs, null, null, true,
|
||||||
true, new PrincipalSid("joe"));
|
new PrincipalSid("joe"));
|
||||||
Sid ben = new PrincipalSid("ben");
|
Sid ben = new PrincipalSid("ben");
|
||||||
try {
|
try {
|
||||||
acl.isGranted(new ArrayList<>(0), Arrays.asList(ben), false);
|
acl.isGranted(new ArrayList<>(0), Arrays.asList(ben), false);
|
||||||
@@ -254,28 +261,21 @@ public class AclImplTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isGrantingGrantsAccessForAclWithNoParent() {
|
public void isGrantingGrantsAccessForAclWithNoParent() {
|
||||||
Authentication auth = new TestingAuthenticationToken("ben", "ignored",
|
Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_GENERAL", "ROLE_GUEST");
|
||||||
"ROLE_GENERAL", "ROLE_GUEST");
|
|
||||||
auth.setAuthenticated(true);
|
auth.setAuthenticated(true);
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
ObjectIdentity rootOid = new ObjectIdentityImpl(TARGET_CLASS, 100);
|
ObjectIdentity rootOid = new ObjectIdentityImpl(TARGET_CLASS, 100);
|
||||||
|
|
||||||
// Create an ACL which owner is not the authenticated principal
|
// Create an ACL which owner is not the authenticated principal
|
||||||
MutableAcl rootAcl = new AclImpl(rootOid, 1, authzStrategy, pgs, null, null,
|
MutableAcl rootAcl = new AclImpl(rootOid, 1, this.authzStrategy, this.pgs, null, null, false,
|
||||||
false, new PrincipalSid("joe"));
|
new PrincipalSid("joe"));
|
||||||
|
|
||||||
// Grant some permissions
|
// Grant some permissions
|
||||||
rootAcl.insertAce(0, BasePermission.READ, new PrincipalSid("ben"), false);
|
rootAcl.insertAce(0, BasePermission.READ, new PrincipalSid("ben"), false);
|
||||||
rootAcl.insertAce(1, BasePermission.WRITE, new PrincipalSid("scott"), true);
|
rootAcl.insertAce(1, BasePermission.WRITE, new PrincipalSid("scott"), true);
|
||||||
rootAcl.insertAce(2, BasePermission.WRITE, new PrincipalSid("rod"), false);
|
rootAcl.insertAce(2, BasePermission.WRITE, new PrincipalSid("rod"), false);
|
||||||
rootAcl.insertAce(3, BasePermission.WRITE, new GrantedAuthoritySid(
|
rootAcl.insertAce(3, BasePermission.WRITE, new GrantedAuthoritySid("WRITE_ACCESS_ROLE"), true);
|
||||||
"WRITE_ACCESS_ROLE"), true);
|
|
||||||
|
|
||||||
// Check permissions granting
|
// Check permissions granting
|
||||||
List<Permission> permissions = Arrays.asList(BasePermission.READ,
|
List<Permission> permissions = Arrays.asList(BasePermission.READ, BasePermission.CREATE);
|
||||||
BasePermission.CREATE);
|
List<Sid> sids = Arrays.asList(new PrincipalSid("ben"), new GrantedAuthoritySid("ROLE_GUEST"));
|
||||||
List<Sid> sids = Arrays.asList(new PrincipalSid("ben"), new GrantedAuthoritySid(
|
|
||||||
"ROLE_GUEST"));
|
|
||||||
assertThat(rootAcl.isGranted(permissions, sids, false)).isFalse();
|
assertThat(rootAcl.isGranted(permissions, sids, false)).isFalse();
|
||||||
try {
|
try {
|
||||||
rootAcl.isGranted(permissions, SCOTT, false);
|
rootAcl.isGranted(permissions, SCOTT, false);
|
||||||
@@ -284,14 +284,14 @@ public class AclImplTests {
|
|||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
}
|
}
|
||||||
assertThat(rootAcl.isGranted(WRITE, SCOTT, false)).isTrue();
|
assertThat(rootAcl.isGranted(WRITE, SCOTT, false)).isTrue();
|
||||||
assertThat(rootAcl.isGranted(WRITE, Arrays.asList(new PrincipalSid("rod"),
|
assertThat(rootAcl.isGranted(WRITE,
|
||||||
new GrantedAuthoritySid("WRITE_ACCESS_ROLE")), false)).isFalse();
|
Arrays.asList(new PrincipalSid("rod"), new GrantedAuthoritySid("WRITE_ACCESS_ROLE")), false)).isFalse();
|
||||||
assertThat(rootAcl.isGranted(WRITE, Arrays.asList(new GrantedAuthoritySid(
|
assertThat(rootAcl.isGranted(WRITE,
|
||||||
"WRITE_ACCESS_ROLE"), new PrincipalSid("rod")), false)).isTrue();
|
Arrays.asList(new GrantedAuthoritySid("WRITE_ACCESS_ROLE"), new PrincipalSid("rod")), false)).isTrue();
|
||||||
try {
|
try {
|
||||||
// Change the type of the Sid and check the granting process
|
// Change the type of the Sid and check the granting process
|
||||||
rootAcl.isGranted(WRITE, Arrays.asList(new GrantedAuthoritySid("rod"),
|
rootAcl.isGranted(WRITE,
|
||||||
new PrincipalSid("WRITE_ACCESS_ROLE")), false);
|
Arrays.asList(new GrantedAuthoritySid("rod"), new PrincipalSid("WRITE_ACCESS_ROLE")), false);
|
||||||
fail("It should have thrown NotFoundException");
|
fail("It should have thrown NotFoundException");
|
||||||
}
|
}
|
||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
@@ -300,8 +300,7 @@ public class AclImplTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isGrantingGrantsAccessForInheritableAcls() {
|
public void isGrantingGrantsAccessForInheritableAcls() {
|
||||||
Authentication auth = new TestingAuthenticationToken("ben", "ignored",
|
Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_GENERAL");
|
||||||
"ROLE_GENERAL");
|
|
||||||
auth.setAuthenticated(true);
|
auth.setAuthenticated(true);
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, 100);
|
ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, 100);
|
||||||
@@ -309,60 +308,44 @@ public class AclImplTests {
|
|||||||
ObjectIdentity parentOid2 = new ObjectIdentityImpl(TARGET_CLASS, 102);
|
ObjectIdentity parentOid2 = new ObjectIdentityImpl(TARGET_CLASS, 102);
|
||||||
ObjectIdentity childOid1 = new ObjectIdentityImpl(TARGET_CLASS, 103);
|
ObjectIdentity childOid1 = new ObjectIdentityImpl(TARGET_CLASS, 103);
|
||||||
ObjectIdentity childOid2 = new ObjectIdentityImpl(TARGET_CLASS, 104);
|
ObjectIdentity childOid2 = new ObjectIdentityImpl(TARGET_CLASS, 104);
|
||||||
|
|
||||||
// Create ACLs
|
// Create ACLs
|
||||||
PrincipalSid joe = new PrincipalSid("joe");
|
PrincipalSid joe = new PrincipalSid("joe");
|
||||||
MutableAcl grandParentAcl = new AclImpl(grandParentOid, 1, authzStrategy, pgs,
|
MutableAcl grandParentAcl = new AclImpl(grandParentOid, 1, this.authzStrategy, this.pgs, null, null, false,
|
||||||
null, null, false, joe);
|
joe);
|
||||||
MutableAcl parentAcl1 = new AclImpl(parentOid1, 2, authzStrategy, pgs, null,
|
MutableAcl parentAcl1 = new AclImpl(parentOid1, 2, this.authzStrategy, this.pgs, null, null, true, joe);
|
||||||
null, true, joe);
|
MutableAcl parentAcl2 = new AclImpl(parentOid2, 3, this.authzStrategy, this.pgs, null, null, true, joe);
|
||||||
MutableAcl parentAcl2 = new AclImpl(parentOid2, 3, authzStrategy, pgs, null,
|
MutableAcl childAcl1 = new AclImpl(childOid1, 4, this.authzStrategy, this.pgs, null, null, true, joe);
|
||||||
null, true, joe);
|
MutableAcl childAcl2 = new AclImpl(childOid2, 4, this.authzStrategy, this.pgs, null, null, false, joe);
|
||||||
MutableAcl childAcl1 = new AclImpl(childOid1, 4, authzStrategy, pgs, null, null,
|
|
||||||
true, joe);
|
|
||||||
MutableAcl childAcl2 = new AclImpl(childOid2, 4, authzStrategy, pgs, null, null,
|
|
||||||
false, joe);
|
|
||||||
|
|
||||||
// Create hierarchies
|
// Create hierarchies
|
||||||
childAcl2.setParent(childAcl1);
|
childAcl2.setParent(childAcl1);
|
||||||
childAcl1.setParent(parentAcl1);
|
childAcl1.setParent(parentAcl1);
|
||||||
parentAcl2.setParent(grandParentAcl);
|
parentAcl2.setParent(grandParentAcl);
|
||||||
parentAcl1.setParent(grandParentAcl);
|
parentAcl1.setParent(grandParentAcl);
|
||||||
|
|
||||||
// Add some permissions
|
// Add some permissions
|
||||||
grandParentAcl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid(
|
grandParentAcl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true);
|
||||||
"ROLE_USER_READ"), true);
|
|
||||||
grandParentAcl.insertAce(1, BasePermission.WRITE, new PrincipalSid("ben"), true);
|
grandParentAcl.insertAce(1, BasePermission.WRITE, new PrincipalSid("ben"), true);
|
||||||
grandParentAcl
|
grandParentAcl.insertAce(2, BasePermission.DELETE, new PrincipalSid("ben"), false);
|
||||||
.insertAce(2, BasePermission.DELETE, new PrincipalSid("ben"), false);
|
grandParentAcl.insertAce(3, BasePermission.DELETE, new PrincipalSid("scott"), true);
|
||||||
grandParentAcl.insertAce(3, BasePermission.DELETE, new PrincipalSid("scott"),
|
|
||||||
true);
|
|
||||||
parentAcl1.insertAce(0, BasePermission.READ, new PrincipalSid("scott"), true);
|
parentAcl1.insertAce(0, BasePermission.READ, new PrincipalSid("scott"), true);
|
||||||
parentAcl1.insertAce(1, BasePermission.DELETE, new PrincipalSid("scott"), false);
|
parentAcl1.insertAce(1, BasePermission.DELETE, new PrincipalSid("scott"), false);
|
||||||
parentAcl2.insertAce(0, BasePermission.CREATE, new PrincipalSid("ben"), true);
|
parentAcl2.insertAce(0, BasePermission.CREATE, new PrincipalSid("ben"), true);
|
||||||
childAcl1.insertAce(0, BasePermission.CREATE, new PrincipalSid("scott"), true);
|
childAcl1.insertAce(0, BasePermission.CREATE, new PrincipalSid("scott"), true);
|
||||||
|
|
||||||
// Check granting process for parent1
|
// Check granting process for parent1
|
||||||
assertThat(parentAcl1.isGranted(READ, SCOTT, false)).isTrue();
|
assertThat(parentAcl1.isGranted(READ, SCOTT, false)).isTrue();
|
||||||
assertThat(parentAcl1.isGranted(READ,
|
assertThat(parentAcl1.isGranted(READ, Arrays.asList((Sid) new GrantedAuthoritySid("ROLE_USER_READ")), false))
|
||||||
Arrays.asList((Sid) new GrantedAuthoritySid("ROLE_USER_READ")), false))
|
|
||||||
.isTrue();
|
.isTrue();
|
||||||
assertThat(parentAcl1.isGranted(WRITE, BEN, false)).isTrue();
|
assertThat(parentAcl1.isGranted(WRITE, BEN, false)).isTrue();
|
||||||
assertThat(parentAcl1.isGranted(DELETE, BEN, false)).isFalse();
|
assertThat(parentAcl1.isGranted(DELETE, BEN, false)).isFalse();
|
||||||
assertThat(parentAcl1.isGranted(DELETE, SCOTT, false)).isFalse();
|
assertThat(parentAcl1.isGranted(DELETE, SCOTT, false)).isFalse();
|
||||||
|
|
||||||
// Check granting process for parent2
|
// Check granting process for parent2
|
||||||
assertThat(parentAcl2.isGranted(CREATE, BEN, false)).isTrue();
|
assertThat(parentAcl2.isGranted(CREATE, BEN, false)).isTrue();
|
||||||
assertThat(parentAcl2.isGranted(WRITE, BEN, false)).isTrue();
|
assertThat(parentAcl2.isGranted(WRITE, BEN, false)).isTrue();
|
||||||
assertThat(parentAcl2.isGranted(DELETE, BEN, false)).isFalse();
|
assertThat(parentAcl2.isGranted(DELETE, BEN, false)).isFalse();
|
||||||
|
|
||||||
// Check granting process for child1
|
// Check granting process for child1
|
||||||
assertThat(childAcl1.isGranted(CREATE, SCOTT, false)).isTrue();
|
assertThat(childAcl1.isGranted(CREATE, SCOTT, false)).isTrue();
|
||||||
assertThat(childAcl1.isGranted(READ,
|
assertThat(childAcl1.isGranted(READ, Arrays.asList((Sid) new GrantedAuthoritySid("ROLE_USER_READ")), false))
|
||||||
Arrays.asList((Sid) new GrantedAuthoritySid("ROLE_USER_READ")), false))
|
|
||||||
.isTrue();
|
.isTrue();
|
||||||
assertThat(childAcl1.isGranted(DELETE, BEN, false)).isFalse();
|
assertThat(childAcl1.isGranted(DELETE, BEN, false)).isFalse();
|
||||||
|
|
||||||
// Check granting process for child2 (doesn't inherit the permissions from its
|
// Check granting process for child2 (doesn't inherit the permissions from its
|
||||||
// parent)
|
// parent)
|
||||||
try {
|
try {
|
||||||
@@ -372,8 +355,7 @@ public class AclImplTests {
|
|||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
childAcl2.isGranted(CREATE,
|
childAcl2.isGranted(CREATE, Arrays.asList((Sid) new PrincipalSid("joe")), false);
|
||||||
Arrays.asList((Sid) new PrincipalSid("joe")), false);
|
|
||||||
fail("It should have thrown NotFoundException");
|
fail("It should have thrown NotFoundException");
|
||||||
}
|
}
|
||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
@@ -382,30 +364,23 @@ public class AclImplTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void updatedAceValuesAreCorrectlyReflectedInAcl() {
|
public void updatedAceValuesAreCorrectlyReflectedInAcl() {
|
||||||
Authentication auth = new TestingAuthenticationToken("ben", "ignored",
|
Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_GENERAL");
|
||||||
"ROLE_GENERAL");
|
|
||||||
auth.setAuthenticated(true);
|
auth.setAuthenticated(true);
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null,
|
MutableAcl acl = new AclImpl(this.objectIdentity, 1, this.authzStrategy, this.pgs, null, null, false,
|
||||||
false, new PrincipalSid("joe"));
|
new PrincipalSid("joe"));
|
||||||
MockAclService service = new MockAclService();
|
MockAclService service = new MockAclService();
|
||||||
|
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true);
|
||||||
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"),
|
acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), true);
|
||||||
true);
|
|
||||||
acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"),
|
|
||||||
true);
|
|
||||||
acl.insertAce(2, BasePermission.CREATE, new PrincipalSid("ben"), true);
|
acl.insertAce(2, BasePermission.CREATE, new PrincipalSid("ben"), true);
|
||||||
service.updateAcl(acl);
|
service.updateAcl(acl);
|
||||||
|
|
||||||
assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(0).getPermission());
|
assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(0).getPermission());
|
||||||
assertThat(BasePermission.WRITE).isEqualTo(acl.getEntries().get(1).getPermission());
|
assertThat(BasePermission.WRITE).isEqualTo(acl.getEntries().get(1).getPermission());
|
||||||
assertThat(BasePermission.CREATE).isEqualTo(acl.getEntries().get(2).getPermission());
|
assertThat(BasePermission.CREATE).isEqualTo(acl.getEntries().get(2).getPermission());
|
||||||
|
|
||||||
// Change each permission
|
// Change each permission
|
||||||
acl.updateAce(0, BasePermission.CREATE);
|
acl.updateAce(0, BasePermission.CREATE);
|
||||||
acl.updateAce(1, BasePermission.DELETE);
|
acl.updateAce(1, BasePermission.DELETE);
|
||||||
acl.updateAce(2, BasePermission.READ);
|
acl.updateAce(2, BasePermission.READ);
|
||||||
|
|
||||||
// Check the change was successfully made
|
// Check the change was successfully made
|
||||||
assertThat(BasePermission.CREATE).isEqualTo(acl.getEntries().get(0).getPermission());
|
assertThat(BasePermission.CREATE).isEqualTo(acl.getEntries().get(0).getPermission());
|
||||||
assertThat(BasePermission.DELETE).isEqualTo(acl.getEntries().get(1).getPermission());
|
assertThat(BasePermission.DELETE).isEqualTo(acl.getEntries().get(1).getPermission());
|
||||||
@@ -414,37 +389,22 @@ public class AclImplTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void auditableEntryFlagsAreUpdatedCorrectly() {
|
public void auditableEntryFlagsAreUpdatedCorrectly() {
|
||||||
Authentication auth = new TestingAuthenticationToken("ben", "ignored",
|
Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_AUDITING", "ROLE_GENERAL");
|
||||||
"ROLE_AUDITING", "ROLE_GENERAL");
|
|
||||||
auth.setAuthenticated(true);
|
auth.setAuthenticated(true);
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null,
|
MutableAcl acl = new AclImpl(this.objectIdentity, 1, this.authzStrategy, this.pgs, null, null, false,
|
||||||
false, new PrincipalSid("joe"));
|
new PrincipalSid("joe"));
|
||||||
MockAclService service = new MockAclService();
|
MockAclService service = new MockAclService();
|
||||||
|
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true);
|
||||||
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"),
|
acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), true);
|
||||||
true);
|
|
||||||
acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"),
|
|
||||||
true);
|
|
||||||
service.updateAcl(acl);
|
service.updateAcl(acl);
|
||||||
|
assertThat(((AuditableAccessControlEntry) acl.getEntries().get(0)).isAuditFailure()).isFalse();
|
||||||
assertThat(((AuditableAccessControlEntry) acl.getEntries().get(0))
|
assertThat(((AuditableAccessControlEntry) acl.getEntries().get(1)).isAuditFailure()).isFalse();
|
||||||
.isAuditFailure())
|
assertThat(((AuditableAccessControlEntry) acl.getEntries().get(0)).isAuditSuccess()).isFalse();
|
||||||
.isFalse();
|
assertThat(((AuditableAccessControlEntry) acl.getEntries().get(1)).isAuditSuccess()).isFalse();
|
||||||
assertThat(((AuditableAccessControlEntry) acl.getEntries().get(1))
|
|
||||||
.isAuditFailure())
|
|
||||||
.isFalse();
|
|
||||||
assertThat(((AuditableAccessControlEntry) acl.getEntries().get(0))
|
|
||||||
.isAuditSuccess())
|
|
||||||
.isFalse();
|
|
||||||
assertThat(((AuditableAccessControlEntry) acl.getEntries().get(1))
|
|
||||||
.isAuditSuccess())
|
|
||||||
.isFalse();
|
|
||||||
|
|
||||||
// Change each permission
|
// Change each permission
|
||||||
((AuditableAcl) acl).updateAuditing(0, true, true);
|
((AuditableAcl) acl).updateAuditing(0, true, true);
|
||||||
((AuditableAcl) acl).updateAuditing(1, true, true);
|
((AuditableAcl) acl).updateAuditing(1, true, true);
|
||||||
|
|
||||||
// Check the change was successfuly made
|
// Check the change was successfuly made
|
||||||
assertThat(acl.getEntries()).extracting("auditSuccess").containsOnly(true, true);
|
assertThat(acl.getEntries()).extracting("auditSuccess").containsOnly(true, true);
|
||||||
assertThat(acl.getEntries()).extracting("auditFailure").containsOnly(true, true);
|
assertThat(acl.getEntries()).extracting("auditFailure").containsOnly(true, true);
|
||||||
@@ -452,86 +412,74 @@ public class AclImplTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void gettersAndSettersAreConsistent() {
|
public void gettersAndSettersAreConsistent() {
|
||||||
Authentication auth = new TestingAuthenticationToken("ben", "ignored",
|
Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_GENERAL");
|
||||||
"ROLE_GENERAL");
|
|
||||||
auth.setAuthenticated(true);
|
auth.setAuthenticated(true);
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, (100));
|
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, (100));
|
||||||
ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, (101));
|
ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, (101));
|
||||||
MutableAcl acl = new AclImpl(identity, 1, authzStrategy, pgs, null, null, true,
|
MutableAcl acl = new AclImpl(identity, 1, this.authzStrategy, this.pgs, null, null, true,
|
||||||
|
new PrincipalSid("joe"));
|
||||||
|
MutableAcl parentAcl = new AclImpl(identity2, 2, this.authzStrategy, this.pgs, null, null, true,
|
||||||
new PrincipalSid("joe"));
|
new PrincipalSid("joe"));
|
||||||
MutableAcl parentAcl = new AclImpl(identity2, 2, authzStrategy, pgs, null, null,
|
|
||||||
true, new PrincipalSid("joe"));
|
|
||||||
MockAclService service = new MockAclService();
|
MockAclService service = new MockAclService();
|
||||||
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"),
|
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true);
|
||||||
true);
|
acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), true);
|
||||||
acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"),
|
|
||||||
true);
|
|
||||||
service.updateAcl(acl);
|
service.updateAcl(acl);
|
||||||
|
|
||||||
assertThat(1).isEqualTo(acl.getId());
|
assertThat(1).isEqualTo(acl.getId());
|
||||||
assertThat(identity).isEqualTo(acl.getObjectIdentity());
|
assertThat(identity).isEqualTo(acl.getObjectIdentity());
|
||||||
assertThat(new PrincipalSid("joe")).isEqualTo(acl.getOwner());
|
assertThat(new PrincipalSid("joe")).isEqualTo(acl.getOwner());
|
||||||
assertThat(acl.getParentAcl()).isNull();
|
assertThat(acl.getParentAcl()).isNull();
|
||||||
assertThat(acl.isEntriesInheriting()).isTrue();
|
assertThat(acl.isEntriesInheriting()).isTrue();
|
||||||
assertThat(acl.getEntries()).hasSize(2);
|
assertThat(acl.getEntries()).hasSize(2);
|
||||||
|
|
||||||
acl.setParent(parentAcl);
|
acl.setParent(parentAcl);
|
||||||
assertThat(parentAcl).isEqualTo(acl.getParentAcl());
|
assertThat(parentAcl).isEqualTo(acl.getParentAcl());
|
||||||
|
|
||||||
acl.setEntriesInheriting(false);
|
acl.setEntriesInheriting(false);
|
||||||
assertThat(acl.isEntriesInheriting()).isFalse();
|
assertThat(acl.isEntriesInheriting()).isFalse();
|
||||||
|
|
||||||
acl.setOwner(new PrincipalSid("ben"));
|
acl.setOwner(new PrincipalSid("ben"));
|
||||||
assertThat(new PrincipalSid("ben")).isEqualTo(acl.getOwner());
|
assertThat(new PrincipalSid("ben")).isEqualTo(acl.getOwner());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isSidLoadedBehavesAsExpected() {
|
public void isSidLoadedBehavesAsExpected() {
|
||||||
List<Sid> loadedSids = Arrays.asList(new PrincipalSid("ben"),
|
List<Sid> loadedSids = Arrays.asList(new PrincipalSid("ben"), new GrantedAuthoritySid("ROLE_IGNORED"));
|
||||||
new GrantedAuthoritySid("ROLE_IGNORED"));
|
MutableAcl acl = new AclImpl(this.objectIdentity, 1, this.authzStrategy, this.pgs, null, loadedSids, true,
|
||||||
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null,
|
new PrincipalSid("joe"));
|
||||||
loadedSids, true, new PrincipalSid("joe"));
|
|
||||||
|
|
||||||
assertThat(acl.isSidLoaded(loadedSids)).isTrue();
|
assertThat(acl.isSidLoaded(loadedSids)).isTrue();
|
||||||
assertThat(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid("ROLE_IGNORED"),
|
assertThat(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid("ROLE_IGNORED"), new PrincipalSid("ben"))))
|
||||||
new PrincipalSid("ben"))))
|
.isTrue();
|
||||||
.isTrue();
|
assertThat(acl.isSidLoaded(Arrays.asList((Sid) new GrantedAuthoritySid("ROLE_IGNORED")))).isTrue();
|
||||||
assertThat(acl.isSidLoaded(Arrays.asList((Sid) new GrantedAuthoritySid(
|
|
||||||
"ROLE_IGNORED"))))
|
|
||||||
.isTrue();
|
|
||||||
assertThat(acl.isSidLoaded(BEN)).isTrue();
|
assertThat(acl.isSidLoaded(BEN)).isTrue();
|
||||||
assertThat(acl.isSidLoaded(null)).isTrue();
|
assertThat(acl.isSidLoaded(null)).isTrue();
|
||||||
assertThat(acl.isSidLoaded(new ArrayList<>(0))).isTrue();
|
assertThat(acl.isSidLoaded(new ArrayList<>(0))).isTrue();
|
||||||
assertThat(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid(
|
assertThat(acl.isSidLoaded(
|
||||||
"ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_IGNORED"))))
|
Arrays.asList(new GrantedAuthoritySid("ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_IGNORED"))))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
assertThat(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid(
|
assertThat(acl.isSidLoaded(
|
||||||
"ROLE_GENERAL"), new GrantedAuthoritySid("ROLE_IGNORED"))))
|
Arrays.asList(new GrantedAuthoritySid("ROLE_GENERAL"), new GrantedAuthoritySid("ROLE_IGNORED"))))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
assertThat(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid(
|
assertThat(acl.isSidLoaded(
|
||||||
"ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_GENERAL"))))
|
Arrays.asList(new GrantedAuthoritySid("ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_GENERAL"))))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = NotFoundException.class)
|
@Test(expected = NotFoundException.class)
|
||||||
public void insertAceRaisesNotFoundExceptionForIndexLessThanZero() {
|
public void insertAceRaisesNotFoundExceptionForIndexLessThanZero() {
|
||||||
AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null,
|
AclImpl acl = new AclImpl(this.objectIdentity, 1, this.authzStrategy, this.pgs, null, null, true,
|
||||||
true, new PrincipalSid("joe"));
|
new PrincipalSid("joe"));
|
||||||
acl.insertAce(-1, mock(Permission.class), mock(Sid.class), true);
|
acl.insertAce(-1, mock(Permission.class), mock(Sid.class), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = NotFoundException.class)
|
@Test(expected = NotFoundException.class)
|
||||||
public void deleteAceRaisesNotFoundExceptionForIndexLessThanZero() {
|
public void deleteAceRaisesNotFoundExceptionForIndexLessThanZero() {
|
||||||
AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null,
|
AclImpl acl = new AclImpl(this.objectIdentity, 1, this.authzStrategy, this.pgs, null, null, true,
|
||||||
true, new PrincipalSid("joe"));
|
new PrincipalSid("joe"));
|
||||||
acl.deleteAce(-1);
|
acl.deleteAce(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = NotFoundException.class)
|
@Test(expected = NotFoundException.class)
|
||||||
public void insertAceRaisesNotFoundExceptionForIndexGreaterThanSize() {
|
public void insertAceRaisesNotFoundExceptionForIndexGreaterThanSize() {
|
||||||
AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null,
|
AclImpl acl = new AclImpl(this.objectIdentity, 1, this.authzStrategy, this.pgs, null, null, true,
|
||||||
true, new PrincipalSid("joe"));
|
new PrincipalSid("joe"));
|
||||||
// Insert at zero, OK.
|
// Insert at zero, OK.
|
||||||
acl.insertAce(0, mock(Permission.class), mock(Sid.class), true);
|
acl.insertAce(0, mock(Permission.class), mock(Sid.class), true);
|
||||||
// Size is now 1
|
// Size is now 1
|
||||||
@@ -541,8 +489,8 @@ public class AclImplTests {
|
|||||||
// SEC-1151
|
// SEC-1151
|
||||||
@Test(expected = NotFoundException.class)
|
@Test(expected = NotFoundException.class)
|
||||||
public void deleteAceRaisesNotFoundExceptionForIndexEqualToSize() {
|
public void deleteAceRaisesNotFoundExceptionForIndexEqualToSize() {
|
||||||
AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null,
|
AclImpl acl = new AclImpl(this.objectIdentity, 1, this.authzStrategy, this.pgs, null, null, true,
|
||||||
true, new PrincipalSid("joe"));
|
new PrincipalSid("joe"));
|
||||||
acl.insertAce(0, mock(Permission.class), mock(Sid.class), true);
|
acl.insertAce(0, mock(Permission.class), mock(Sid.class), true);
|
||||||
// Size is now 1
|
// Size is now 1
|
||||||
acl.deleteAce(1);
|
acl.deleteAce(1);
|
||||||
@@ -551,12 +499,9 @@ public class AclImplTests {
|
|||||||
// SEC-1795
|
// SEC-1795
|
||||||
@Test
|
@Test
|
||||||
public void changingParentIsSuccessful() {
|
public void changingParentIsSuccessful() {
|
||||||
AclImpl parentAcl = new AclImpl(objectIdentity, 1L, authzStrategy,
|
AclImpl parentAcl = new AclImpl(this.objectIdentity, 1L, this.authzStrategy, this.mockAuditLogger);
|
||||||
mockAuditLogger);
|
AclImpl childAcl = new AclImpl(this.objectIdentity, 2L, this.authzStrategy, this.mockAuditLogger);
|
||||||
AclImpl childAcl = new AclImpl(objectIdentity, 2L, authzStrategy, mockAuditLogger);
|
AclImpl changeParentAcl = new AclImpl(this.objectIdentity, 3L, this.authzStrategy, this.mockAuditLogger);
|
||||||
AclImpl changeParentAcl = new AclImpl(objectIdentity, 3L, authzStrategy,
|
|
||||||
mockAuditLogger);
|
|
||||||
|
|
||||||
childAcl.setParent(parentAcl);
|
childAcl.setParent(parentAcl);
|
||||||
childAcl.setParent(changeParentAcl);
|
childAcl.setParent(changeParentAcl);
|
||||||
}
|
}
|
||||||
@@ -564,11 +509,12 @@ public class AclImplTests {
|
|||||||
// SEC-2342
|
// SEC-2342
|
||||||
@Test
|
@Test
|
||||||
public void maskPermissionGrantingStrategy() {
|
public void maskPermissionGrantingStrategy() {
|
||||||
DefaultPermissionGrantingStrategy maskPgs = new MaskPermissionGrantingStrategy(mockAuditLogger);
|
DefaultPermissionGrantingStrategy maskPgs = new MaskPermissionGrantingStrategy(this.mockAuditLogger);
|
||||||
MockAclService service = new MockAclService();
|
MockAclService service = new MockAclService();
|
||||||
AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, maskPgs, null, null,
|
AclImpl acl = new AclImpl(this.objectIdentity, 1, this.authzStrategy, maskPgs, null, null, true,
|
||||||
true, new PrincipalSid("joe"));
|
new PrincipalSid("joe"));
|
||||||
Permission permission = permissionFactory.buildFromMask(BasePermission.READ.getMask() | BasePermission.WRITE.getMask());
|
Permission permission = this.permissionFactory
|
||||||
|
.buildFromMask(BasePermission.READ.getMask() | BasePermission.WRITE.getMask());
|
||||||
Sid sid = new PrincipalSid("ben");
|
Sid sid = new PrincipalSid("ben");
|
||||||
acl.insertAce(0, permission, sid, true);
|
acl.insertAce(0, permission, sid, true);
|
||||||
service.updateAcl(acl);
|
service.updateAcl(acl);
|
||||||
@@ -579,27 +525,21 @@ public class AclImplTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void hashCodeWithoutStackOverFlow() throws Exception {
|
public void hashCodeWithoutStackOverFlow() throws Exception {
|
||||||
//given
|
|
||||||
Sid sid = new PrincipalSid("pSid");
|
Sid sid = new PrincipalSid("pSid");
|
||||||
ObjectIdentity oid = new ObjectIdentityImpl("type", 1);
|
ObjectIdentity oid = new ObjectIdentityImpl("type", 1);
|
||||||
AclAuthorizationStrategy authStrategy = new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("role"));
|
AclAuthorizationStrategy authStrategy = new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("role"));
|
||||||
PermissionGrantingStrategy grantingStrategy = new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger());
|
PermissionGrantingStrategy grantingStrategy = new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger());
|
||||||
|
AclImpl acl = new AclImpl(oid, 1L, authStrategy, grantingStrategy, null, null, false, sid);
|
||||||
AclImpl acl = new AclImpl(oid, 1L, authStrategy, grantingStrategy, null, null, false, sid);
|
|
||||||
AccessControlEntryImpl ace = new AccessControlEntryImpl(1L, acl, sid, BasePermission.READ, true, true, true);
|
AccessControlEntryImpl ace = new AccessControlEntryImpl(1L, acl, sid, BasePermission.READ, true, true, true);
|
||||||
|
Field fieldAces = FieldUtils.getField(AclImpl.class, "aces");
|
||||||
Field fieldAces = FieldUtils.getField(AclImpl.class, "aces");
|
|
||||||
fieldAces.setAccessible(true);
|
fieldAces.setAccessible(true);
|
||||||
List<AccessControlEntryImpl> aces = (List<AccessControlEntryImpl>) fieldAces.get(acl);
|
List<AccessControlEntryImpl> aces = (List<AccessControlEntryImpl>) fieldAces.get(acl);
|
||||||
aces.add(ace);
|
aces.add(ace);
|
||||||
//when - then none StackOverFlowError been raised
|
|
||||||
ace.hashCode();
|
ace.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Inner Classes
|
|
||||||
// ==================================================================================================
|
|
||||||
|
|
||||||
private static class MaskPermissionGrantingStrategy extends DefaultPermissionGrantingStrategy {
|
private static class MaskPermissionGrantingStrategy extends DefaultPermissionGrantingStrategy {
|
||||||
|
|
||||||
MaskPermissionGrantingStrategy(AuditLogger auditLogger) {
|
MaskPermissionGrantingStrategy(AuditLogger auditLogger) {
|
||||||
super(auditLogger);
|
super(auditLogger);
|
||||||
}
|
}
|
||||||
@@ -611,26 +551,28 @@ public class AclImplTests {
|
|||||||
}
|
}
|
||||||
return super.isGranted(ace, p);
|
return super.isGranted(ace, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MockAclService implements MutableAclService {
|
private class MockAclService implements MutableAclService {
|
||||||
public MutableAcl createAcl(ObjectIdentity objectIdentity)
|
|
||||||
throws AlreadyExistsException {
|
@Override
|
||||||
|
public MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren)
|
@Override
|
||||||
throws ChildrenExistException {
|
public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mock implementation that populates the aces list with fully initialized
|
* Mock implementation that populates the aces list with fully initialized
|
||||||
* AccessControlEntries
|
* AccessControlEntries
|
||||||
*
|
*
|
||||||
* @see
|
* @see org.springframework.security.acls.MutableAclService#updateAcl(org.
|
||||||
* org.springframework.security.acls.MutableAclService#updateAcl(org.springframework
|
* springframework .security.acls.MutableAcl)
|
||||||
* .security.acls.MutableAcl)
|
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException {
|
public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException {
|
||||||
List<AccessControlEntry> oldAces = acl.getEntries();
|
List<AccessControlEntry> oldAces = acl.getEntries();
|
||||||
@@ -640,45 +582,47 @@ public class AclImplTests {
|
|||||||
try {
|
try {
|
||||||
newAces = (List) acesField.get(acl);
|
newAces = (List) acesField.get(acl);
|
||||||
newAces.clear();
|
newAces.clear();
|
||||||
|
|
||||||
for (int i = 0; i < oldAces.size(); i++) {
|
for (int i = 0; i < oldAces.size(); i++) {
|
||||||
AccessControlEntry ac = oldAces.get(i);
|
AccessControlEntry ac = oldAces.get(i);
|
||||||
// Just give an ID to all this acl's aces, rest of the fields are just
|
// Just give an ID to all this acl's aces, rest of the fields are just
|
||||||
// copied
|
// copied
|
||||||
newAces.add(new AccessControlEntryImpl((i + 1), ac.getAcl(), ac
|
newAces.add(new AccessControlEntryImpl((i + 1), ac.getAcl(), ac.getSid(), ac.getPermission(),
|
||||||
.getSid(), ac.getPermission(), ac.isGranting(),
|
ac.isGranting(), ((AuditableAccessControlEntry) ac).isAuditSuccess(),
|
||||||
((AuditableAccessControlEntry) ac).isAuditSuccess(),
|
|
||||||
((AuditableAccessControlEntry) ac).isAuditFailure()));
|
((AuditableAccessControlEntry) ac).isAuditFailure()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IllegalAccessException e) {
|
catch (IllegalAccessException ex) {
|
||||||
e.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return acl;
|
return acl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
|
public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Acl readAclById(ObjectIdentity object) throws NotFoundException {
|
public Acl readAclById(ObjectIdentity object) throws NotFoundException {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Acl readAclById(ObjectIdentity object, List<Sid> sids)
|
@Override
|
||||||
|
public Acl readAclById(ObjectIdentity object, List<Sid> sids) throws NotFoundException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects) throws NotFoundException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids)
|
||||||
throws NotFoundException {
|
throws NotFoundException {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects)
|
|
||||||
throws NotFoundException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects,
|
|
||||||
List<Sid> sids) throws NotFoundException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+60
-122
@@ -13,11 +13,13 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.junit.*;
|
|
||||||
import org.springframework.security.access.AccessDeniedException;
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
import org.springframework.security.acls.model.Acl;
|
import org.springframework.security.acls.model.Acl;
|
||||||
import org.springframework.security.acls.model.MutableAcl;
|
import org.springframework.security.acls.model.MutableAcl;
|
||||||
@@ -28,6 +30,8 @@ import org.springframework.security.core.Authentication;
|
|||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test class for {@link AclAuthorizationStrategyImpl} and {@link AclImpl} security
|
* Test class for {@link AclAuthorizationStrategyImpl} and {@link AclImpl} security
|
||||||
* checks.
|
* checks.
|
||||||
@@ -35,10 +39,8 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
|||||||
* @author Andrei Stefan
|
* @author Andrei Stefan
|
||||||
*/
|
*/
|
||||||
public class AclImplementationSecurityCheckTests {
|
public class AclImplementationSecurityCheckTests {
|
||||||
private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject";
|
|
||||||
|
|
||||||
// ~ Methods
|
private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject";
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
@@ -52,50 +54,38 @@ public class AclImplementationSecurityCheckTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSecurityCheckNoACEs() {
|
public void testSecurityCheckNoACEs() {
|
||||||
Authentication auth = new TestingAuthenticationToken("user", "password",
|
Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL", "ROLE_AUDITING",
|
||||||
"ROLE_GENERAL", "ROLE_AUDITING", "ROLE_OWNERSHIP");
|
"ROLE_OWNERSHIP");
|
||||||
auth.setAuthenticated(true);
|
auth.setAuthenticated(true);
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
|
|
||||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
||||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority(
|
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||||
"ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL"));
|
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||||
|
Acl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||||
Acl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy,
|
aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||||
new ConsoleAuditLogger());
|
aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_AUDITING);
|
||||||
|
aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
||||||
aclAuthorizationStrategy.securityCheck(acl,
|
|
||||||
AclAuthorizationStrategy.CHANGE_GENERAL);
|
|
||||||
aclAuthorizationStrategy.securityCheck(acl,
|
|
||||||
AclAuthorizationStrategy.CHANGE_AUDITING);
|
|
||||||
aclAuthorizationStrategy.securityCheck(acl,
|
|
||||||
AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
|
||||||
|
|
||||||
// Create another authorization strategy
|
// Create another authorization strategy
|
||||||
AclAuthorizationStrategy aclAuthorizationStrategy2 = new AclAuthorizationStrategyImpl(
|
AclAuthorizationStrategy aclAuthorizationStrategy2 = new AclAuthorizationStrategyImpl(
|
||||||
new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority(
|
new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority("ROLE_TWO"),
|
||||||
"ROLE_TWO"), new SimpleGrantedAuthority("ROLE_THREE"));
|
new SimpleGrantedAuthority("ROLE_THREE"));
|
||||||
Acl acl2 = new AclImpl(identity, 1L, aclAuthorizationStrategy2,
|
Acl acl2 = new AclImpl(identity, 1L, aclAuthorizationStrategy2, new ConsoleAuditLogger());
|
||||||
new ConsoleAuditLogger());
|
|
||||||
// Check access in case the principal has no authorization rights
|
// Check access in case the principal has no authorization rights
|
||||||
try {
|
try {
|
||||||
aclAuthorizationStrategy2.securityCheck(acl2,
|
aclAuthorizationStrategy2.securityCheck(acl2, AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||||
AclAuthorizationStrategy.CHANGE_GENERAL);
|
|
||||||
fail("It should have thrown NotFoundException");
|
fail("It should have thrown NotFoundException");
|
||||||
}
|
}
|
||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
aclAuthorizationStrategy2.securityCheck(acl2,
|
aclAuthorizationStrategy2.securityCheck(acl2, AclAuthorizationStrategy.CHANGE_AUDITING);
|
||||||
AclAuthorizationStrategy.CHANGE_AUDITING);
|
|
||||||
fail("It should have thrown NotFoundException");
|
fail("It should have thrown NotFoundException");
|
||||||
}
|
}
|
||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
aclAuthorizationStrategy2.securityCheck(acl2,
|
aclAuthorizationStrategy2.securityCheck(acl2, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
||||||
AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
|
||||||
fail("It should have thrown NotFoundException");
|
fail("It should have thrown NotFoundException");
|
||||||
}
|
}
|
||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
@@ -105,100 +95,71 @@ public class AclImplementationSecurityCheckTests {
|
|||||||
@Test
|
@Test
|
||||||
public void testSecurityCheckWithMultipleACEs() {
|
public void testSecurityCheckWithMultipleACEs() {
|
||||||
// Create a simple authentication with ROLE_GENERAL
|
// Create a simple authentication with ROLE_GENERAL
|
||||||
Authentication auth = new TestingAuthenticationToken("user", "password",
|
Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL");
|
||||||
"ROLE_GENERAL");
|
|
||||||
auth.setAuthenticated(true);
|
auth.setAuthenticated(true);
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
|
|
||||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
||||||
// Authorization strategy will require a different role for each access
|
// Authorization strategy will require a different role for each access
|
||||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority(
|
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||||
"ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL"));
|
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||||
|
|
||||||
// Let's give the principal the ADMINISTRATION permission, without
|
// Let's give the principal the ADMINISTRATION permission, without
|
||||||
// granting access
|
// granting access
|
||||||
MutableAcl aclFirstDeny = new AclImpl(identity, 1L,
|
MutableAcl aclFirstDeny = new AclImpl(identity, 1L, aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||||
aclAuthorizationStrategy, new ConsoleAuditLogger());
|
aclFirstDeny.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), false);
|
||||||
aclFirstDeny.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth),
|
|
||||||
false);
|
|
||||||
|
|
||||||
// The CHANGE_GENERAL test should pass as the principal has ROLE_GENERAL
|
// The CHANGE_GENERAL test should pass as the principal has ROLE_GENERAL
|
||||||
aclAuthorizationStrategy.securityCheck(aclFirstDeny,
|
aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||||
AclAuthorizationStrategy.CHANGE_GENERAL);
|
|
||||||
|
|
||||||
// The CHANGE_AUDITING and CHANGE_OWNERSHIP should fail since the
|
// The CHANGE_AUDITING and CHANGE_OWNERSHIP should fail since the
|
||||||
// principal doesn't have these authorities,
|
// principal doesn't have these authorities,
|
||||||
// nor granting access
|
// nor granting access
|
||||||
try {
|
try {
|
||||||
aclAuthorizationStrategy.securityCheck(aclFirstDeny,
|
aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_AUDITING);
|
||||||
AclAuthorizationStrategy.CHANGE_AUDITING);
|
|
||||||
fail("It should have thrown AccessDeniedException");
|
fail("It should have thrown AccessDeniedException");
|
||||||
}
|
}
|
||||||
catch (AccessDeniedException expected) {
|
catch (AccessDeniedException expected) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
aclAuthorizationStrategy.securityCheck(aclFirstDeny,
|
aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
||||||
AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
|
||||||
fail("It should have thrown AccessDeniedException");
|
fail("It should have thrown AccessDeniedException");
|
||||||
}
|
}
|
||||||
catch (AccessDeniedException expected) {
|
catch (AccessDeniedException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add granting access to this principal
|
// Add granting access to this principal
|
||||||
aclFirstDeny.insertAce(1, BasePermission.ADMINISTRATION, new PrincipalSid(auth),
|
aclFirstDeny.insertAce(1, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true);
|
||||||
true);
|
|
||||||
// and try again for CHANGE_AUDITING - the first ACE's granting flag
|
// and try again for CHANGE_AUDITING - the first ACE's granting flag
|
||||||
// (false) will deny this access
|
// (false) will deny this access
|
||||||
try {
|
try {
|
||||||
aclAuthorizationStrategy.securityCheck(aclFirstDeny,
|
aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_AUDITING);
|
||||||
AclAuthorizationStrategy.CHANGE_AUDITING);
|
|
||||||
fail("It should have thrown AccessDeniedException");
|
fail("It should have thrown AccessDeniedException");
|
||||||
}
|
}
|
||||||
catch (AccessDeniedException expected) {
|
catch (AccessDeniedException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create another ACL and give the principal the ADMINISTRATION
|
// Create another ACL and give the principal the ADMINISTRATION
|
||||||
// permission, with granting access
|
// permission, with granting access
|
||||||
MutableAcl aclFirstAllow = new AclImpl(identity, 1L,
|
MutableAcl aclFirstAllow = new AclImpl(identity, 1L, aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||||
aclAuthorizationStrategy, new ConsoleAuditLogger());
|
aclFirstAllow.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true);
|
||||||
aclFirstAllow.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth),
|
|
||||||
true);
|
|
||||||
|
|
||||||
// The CHANGE_AUDITING test should pass as there is one ACE with
|
// The CHANGE_AUDITING test should pass as there is one ACE with
|
||||||
// granting access
|
// granting access
|
||||||
|
aclAuthorizationStrategy.securityCheck(aclFirstAllow, AclAuthorizationStrategy.CHANGE_AUDITING);
|
||||||
aclAuthorizationStrategy.securityCheck(aclFirstAllow,
|
|
||||||
AclAuthorizationStrategy.CHANGE_AUDITING);
|
|
||||||
|
|
||||||
// Add a deny ACE and test again for CHANGE_AUDITING
|
// Add a deny ACE and test again for CHANGE_AUDITING
|
||||||
aclFirstAllow.insertAce(1, BasePermission.ADMINISTRATION, new PrincipalSid(auth),
|
aclFirstAllow.insertAce(1, BasePermission.ADMINISTRATION, new PrincipalSid(auth), false);
|
||||||
false);
|
|
||||||
try {
|
try {
|
||||||
aclAuthorizationStrategy.securityCheck(aclFirstAllow,
|
aclAuthorizationStrategy.securityCheck(aclFirstAllow, AclAuthorizationStrategy.CHANGE_AUDITING);
|
||||||
AclAuthorizationStrategy.CHANGE_AUDITING);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (AccessDeniedException notExpected) {
|
catch (AccessDeniedException notExpected) {
|
||||||
fail("It shouldn't have thrown AccessDeniedException");
|
fail("It shouldn't have thrown AccessDeniedException");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an ACL with no ACE
|
// Create an ACL with no ACE
|
||||||
MutableAcl aclNoACE = new AclImpl(identity, 1L,
|
MutableAcl aclNoACE = new AclImpl(identity, 1L, aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||||
aclAuthorizationStrategy, new ConsoleAuditLogger());
|
|
||||||
try {
|
try {
|
||||||
aclAuthorizationStrategy.securityCheck(aclNoACE,
|
aclAuthorizationStrategy.securityCheck(aclNoACE, AclAuthorizationStrategy.CHANGE_AUDITING);
|
||||||
AclAuthorizationStrategy.CHANGE_AUDITING);
|
|
||||||
fail("It should have thrown NotFoundException");
|
fail("It should have thrown NotFoundException");
|
||||||
}
|
}
|
||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
|
|
||||||
}
|
}
|
||||||
// and still grant access for CHANGE_GENERAL
|
// and still grant access for CHANGE_GENERAL
|
||||||
try {
|
try {
|
||||||
aclAuthorizationStrategy.securityCheck(aclNoACE,
|
aclAuthorizationStrategy.securityCheck(aclNoACE, AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||||
AclAuthorizationStrategy.CHANGE_GENERAL);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
fail("It shouldn't have thrown NotFoundException");
|
fail("It shouldn't have thrown NotFoundException");
|
||||||
@@ -208,64 +169,46 @@ public class AclImplementationSecurityCheckTests {
|
|||||||
@Test
|
@Test
|
||||||
public void testSecurityCheckWithInheritableACEs() {
|
public void testSecurityCheckWithInheritableACEs() {
|
||||||
// Create a simple authentication with ROLE_GENERAL
|
// Create a simple authentication with ROLE_GENERAL
|
||||||
Authentication auth = new TestingAuthenticationToken("user", "password",
|
Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL");
|
||||||
"ROLE_GENERAL");
|
|
||||||
auth.setAuthenticated(true);
|
auth.setAuthenticated(true);
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
|
|
||||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100);
|
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100);
|
||||||
// Authorization strategy will require a different role for each access
|
// Authorization strategy will require a different role for each access
|
||||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||||
new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority(
|
new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority("ROLE_TWO"),
|
||||||
"ROLE_TWO"), new SimpleGrantedAuthority("ROLE_GENERAL"));
|
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||||
|
|
||||||
// Let's give the principal an ADMINISTRATION permission, with granting
|
// Let's give the principal an ADMINISTRATION permission, with granting
|
||||||
// access
|
// access
|
||||||
MutableAcl parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy,
|
MutableAcl parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||||
new ConsoleAuditLogger());
|
parentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true);
|
||||||
parentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth),
|
MutableAcl childAcl = new AclImpl(identity, 2, aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||||
true);
|
|
||||||
MutableAcl childAcl = new AclImpl(identity, 2, aclAuthorizationStrategy,
|
|
||||||
new ConsoleAuditLogger());
|
|
||||||
|
|
||||||
// Check against the 'child' acl, which doesn't offer any authorization
|
// Check against the 'child' acl, which doesn't offer any authorization
|
||||||
// rights on CHANGE_OWNERSHIP
|
// rights on CHANGE_OWNERSHIP
|
||||||
try {
|
try {
|
||||||
aclAuthorizationStrategy.securityCheck(childAcl,
|
aclAuthorizationStrategy.securityCheck(childAcl, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
||||||
AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
|
||||||
fail("It should have thrown NotFoundException");
|
fail("It should have thrown NotFoundException");
|
||||||
}
|
}
|
||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link the child with its parent and test again against the
|
// Link the child with its parent and test again against the
|
||||||
// CHANGE_OWNERSHIP right
|
// CHANGE_OWNERSHIP right
|
||||||
childAcl.setParent(parentAcl);
|
childAcl.setParent(parentAcl);
|
||||||
childAcl.setEntriesInheriting(true);
|
childAcl.setEntriesInheriting(true);
|
||||||
try {
|
try {
|
||||||
aclAuthorizationStrategy.securityCheck(childAcl,
|
aclAuthorizationStrategy.securityCheck(childAcl, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
||||||
AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
fail("It shouldn't have thrown NotFoundException");
|
fail("It shouldn't have thrown NotFoundException");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a root parent and link it to the middle parent
|
// Create a root parent and link it to the middle parent
|
||||||
MutableAcl rootParentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy,
|
MutableAcl rootParentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||||
new ConsoleAuditLogger());
|
parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||||
parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy,
|
rootParentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true);
|
||||||
new ConsoleAuditLogger());
|
|
||||||
rootParentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth),
|
|
||||||
true);
|
|
||||||
parentAcl.setEntriesInheriting(true);
|
parentAcl.setEntriesInheriting(true);
|
||||||
parentAcl.setParent(rootParentAcl);
|
parentAcl.setParent(rootParentAcl);
|
||||||
childAcl.setParent(parentAcl);
|
childAcl.setParent(parentAcl);
|
||||||
try {
|
try {
|
||||||
aclAuthorizationStrategy.securityCheck(childAcl,
|
aclAuthorizationStrategy.securityCheck(childAcl, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
||||||
AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
fail("It shouldn't have thrown NotFoundException");
|
fail("It shouldn't have thrown NotFoundException");
|
||||||
@@ -274,39 +217,34 @@ public class AclImplementationSecurityCheckTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSecurityCheckPrincipalOwner() {
|
public void testSecurityCheckPrincipalOwner() {
|
||||||
Authentication auth = new TestingAuthenticationToken("user", "password",
|
Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_ONE");
|
||||||
"ROLE_ONE");
|
|
||||||
auth.setAuthenticated(true);
|
auth.setAuthenticated(true);
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
|
|
||||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100);
|
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100);
|
||||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority(
|
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||||
"ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL"));
|
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||||
|
|
||||||
Acl acl = new AclImpl(identity, 1, aclAuthorizationStrategy,
|
Acl acl = new AclImpl(identity, 1, aclAuthorizationStrategy,
|
||||||
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), null,
|
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), null, null, false,
|
||||||
null, false, new PrincipalSid(auth));
|
new PrincipalSid(auth));
|
||||||
try {
|
try {
|
||||||
aclAuthorizationStrategy.securityCheck(acl,
|
aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||||
AclAuthorizationStrategy.CHANGE_GENERAL);
|
|
||||||
}
|
}
|
||||||
catch (AccessDeniedException notExpected) {
|
catch (AccessDeniedException notExpected) {
|
||||||
fail("It shouldn't have thrown AccessDeniedException");
|
fail("It shouldn't have thrown AccessDeniedException");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
aclAuthorizationStrategy.securityCheck(acl,
|
aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_AUDITING);
|
||||||
AclAuthorizationStrategy.CHANGE_AUDITING);
|
|
||||||
fail("It shouldn't have thrown AccessDeniedException");
|
fail("It shouldn't have thrown AccessDeniedException");
|
||||||
}
|
}
|
||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
aclAuthorizationStrategy.securityCheck(acl,
|
aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
||||||
AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
|
||||||
}
|
}
|
||||||
catch (AccessDeniedException notExpected) {
|
catch (AccessDeniedException notExpected) {
|
||||||
fail("It shouldn't have thrown AccessDeniedException");
|
fail("It shouldn't have thrown AccessDeniedException");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,10 +13,8 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.acls.domain;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
package org.springframework.security.acls.domain;
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
@@ -24,72 +22,76 @@ import java.io.PrintStream;
|
|||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.AccessControlEntry;
|
import org.springframework.security.acls.model.AccessControlEntry;
|
||||||
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test class for {@link ConsoleAuditLogger}.
|
* Test class for {@link ConsoleAuditLogger}.
|
||||||
*
|
*
|
||||||
* @author Andrei Stefan
|
* @author Andrei Stefan
|
||||||
*/
|
*/
|
||||||
public class AuditLoggerTests {
|
public class AuditLoggerTests {
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
private PrintStream console;
|
|
||||||
private ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
|
||||||
private ConsoleAuditLogger logger;
|
|
||||||
private AuditableAccessControlEntry ace;
|
|
||||||
|
|
||||||
// ~ Methods
|
private PrintStream console;
|
||||||
// ========================================================================================================
|
|
||||||
|
private ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
private ConsoleAuditLogger logger;
|
||||||
|
|
||||||
|
private AuditableAccessControlEntry ace;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
logger = new ConsoleAuditLogger();
|
this.logger = new ConsoleAuditLogger();
|
||||||
ace = mock(AuditableAccessControlEntry.class);
|
this.ace = mock(AuditableAccessControlEntry.class);
|
||||||
console = System.out;
|
this.console = System.out;
|
||||||
System.setOut(new PrintStream(bytes));
|
System.setOut(new PrintStream(this.bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
System.setOut(console);
|
System.setOut(this.console);
|
||||||
bytes.reset();
|
this.bytes.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void nonAuditableAceIsIgnored() {
|
public void nonAuditableAceIsIgnored() {
|
||||||
AccessControlEntry ace = mock(AccessControlEntry.class);
|
AccessControlEntry ace = mock(AccessControlEntry.class);
|
||||||
logger.logIfNeeded(true, ace);
|
this.logger.logIfNeeded(true, ace);
|
||||||
assertThat(bytes.size()).isZero();
|
assertThat(this.bytes.size()).isZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void successIsNotLoggedIfAceDoesntRequireSuccessAudit() {
|
public void successIsNotLoggedIfAceDoesntRequireSuccessAudit() {
|
||||||
when(ace.isAuditSuccess()).thenReturn(false);
|
given(this.ace.isAuditSuccess()).willReturn(false);
|
||||||
logger.logIfNeeded(true, ace);
|
this.logger.logIfNeeded(true, this.ace);
|
||||||
assertThat(bytes.size()).isZero();
|
assertThat(this.bytes.size()).isZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void successIsLoggedIfAceRequiresSuccessAudit() {
|
public void successIsLoggedIfAceRequiresSuccessAudit() {
|
||||||
when(ace.isAuditSuccess()).thenReturn(true);
|
given(this.ace.isAuditSuccess()).willReturn(true);
|
||||||
|
this.logger.logIfNeeded(true, this.ace);
|
||||||
logger.logIfNeeded(true, ace);
|
assertThat(this.bytes.toString()).startsWith("GRANTED due to ACE");
|
||||||
assertThat(bytes.toString()).startsWith("GRANTED due to ACE");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void failureIsntLoggedIfAceDoesntRequireFailureAudit() {
|
public void failureIsntLoggedIfAceDoesntRequireFailureAudit() {
|
||||||
when(ace.isAuditFailure()).thenReturn(false);
|
given(this.ace.isAuditFailure()).willReturn(false);
|
||||||
logger.logIfNeeded(false, ace);
|
this.logger.logIfNeeded(false, this.ace);
|
||||||
assertThat(bytes.size()).isZero();
|
assertThat(this.bytes.size()).isZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void failureIsLoggedIfAceRequiresFailureAudit() {
|
public void failureIsLoggedIfAceRequiresFailureAudit() {
|
||||||
when(ace.isAuditFailure()).thenReturn(true);
|
given(this.ace.isAuditFailure()).willReturn(true);
|
||||||
logger.logIfNeeded(false, ace);
|
this.logger.logIfNeeded(false, this.ace);
|
||||||
assertThat(bytes.toString()).startsWith("DENIED due to ACE");
|
assertThat(this.bytes.toString()).startsWith("DENIED due to ACE");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-25
@@ -13,15 +13,16 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.security.acls.domain.IdentityUnavailableException;
|
|
||||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
|
||||||
import org.springframework.security.acls.model.ObjectIdentity;
|
import org.springframework.security.acls.model.ObjectIdentity;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link ObjectIdentityImpl}.
|
* Tests for {@link ObjectIdentityImpl}.
|
||||||
*
|
*
|
||||||
@@ -32,9 +33,6 @@ public class ObjectIdentityImplTests {
|
|||||||
|
|
||||||
private static final String DOMAIN_CLASS = "org.springframework.security.acls.domain.ObjectIdentityImplTests$MockIdDomainObject";
|
private static final String DOMAIN_CLASS = "org.springframework.security.acls.domain.ObjectIdentityImplTests$MockIdDomainObject";
|
||||||
|
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void constructorsRespectRequiredFields() {
|
public void constructorsRespectRequiredFields() {
|
||||||
// Check one-argument constructor required field
|
// Check one-argument constructor required field
|
||||||
@@ -44,7 +42,6 @@ public class ObjectIdentityImplTests {
|
|||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check String-Serializable constructor required field
|
// Check String-Serializable constructor required field
|
||||||
try {
|
try {
|
||||||
new ObjectIdentityImpl("", 1L);
|
new ObjectIdentityImpl("", 1L);
|
||||||
@@ -52,7 +49,6 @@ public class ObjectIdentityImplTests {
|
|||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check Serializable parameter is not null
|
// Check Serializable parameter is not null
|
||||||
try {
|
try {
|
||||||
new ObjectIdentityImpl(DOMAIN_CLASS, null);
|
new ObjectIdentityImpl(DOMAIN_CLASS, null);
|
||||||
@@ -60,7 +56,6 @@ public class ObjectIdentityImplTests {
|
|||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The correct way of using String-Serializable constructor
|
// The correct way of using String-Serializable constructor
|
||||||
try {
|
try {
|
||||||
new ObjectIdentityImpl(DOMAIN_CLASS, 1L);
|
new ObjectIdentityImpl(DOMAIN_CLASS, 1L);
|
||||||
@@ -68,7 +63,6 @@ public class ObjectIdentityImplTests {
|
|||||||
catch (IllegalArgumentException notExpected) {
|
catch (IllegalArgumentException notExpected) {
|
||||||
fail("It shouldn't have thrown IllegalArgumentException");
|
fail("It shouldn't have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the Class-Serializable constructor
|
// Check the Class-Serializable constructor
|
||||||
try {
|
try {
|
||||||
new ObjectIdentityImpl(MockIdDomainObject.class, null);
|
new ObjectIdentityImpl(MockIdDomainObject.class, null);
|
||||||
@@ -93,9 +87,7 @@ public class ObjectIdentityImplTests {
|
|||||||
fail("It should have thrown IdentityUnavailableException");
|
fail("It should have thrown IdentityUnavailableException");
|
||||||
}
|
}
|
||||||
catch (IdentityUnavailableException expected) {
|
catch (IdentityUnavailableException expected) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getId() should return a non-null value
|
// getId() should return a non-null value
|
||||||
MockIdDomainObject mockId = new MockIdDomainObject();
|
MockIdDomainObject mockId = new MockIdDomainObject();
|
||||||
try {
|
try {
|
||||||
@@ -103,9 +95,7 @@ public class ObjectIdentityImplTests {
|
|||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getId() should return a Serializable object
|
// getId() should return a Serializable object
|
||||||
mockId.setId(new MockIdDomainObject());
|
mockId.setId(new MockIdDomainObject());
|
||||||
try {
|
try {
|
||||||
@@ -114,7 +104,6 @@ public class ObjectIdentityImplTests {
|
|||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// getId() should return a Serializable object
|
// getId() should return a Serializable object
|
||||||
mockId.setId(100L);
|
mockId.setId(100L);
|
||||||
try {
|
try {
|
||||||
@@ -134,15 +123,13 @@ public class ObjectIdentityImplTests {
|
|||||||
ObjectIdentity obj = new ObjectIdentityImpl(DOMAIN_CLASS, 1L);
|
ObjectIdentity obj = new ObjectIdentityImpl(DOMAIN_CLASS, 1L);
|
||||||
MockIdDomainObject mockObj = new MockIdDomainObject();
|
MockIdDomainObject mockObj = new MockIdDomainObject();
|
||||||
mockObj.setId(1L);
|
mockObj.setId(1L);
|
||||||
|
|
||||||
String string = "SOME_STRING";
|
String string = "SOME_STRING";
|
||||||
assertThat(string).isNotSameAs(obj);
|
assertThat(string).isNotSameAs(obj);
|
||||||
assertThat(obj).isNotNull();
|
assertThat(obj).isNotNull();
|
||||||
assertThat(obj).isNotEqualTo("DIFFERENT_OBJECT_TYPE");
|
assertThat(obj).isNotEqualTo("DIFFERENT_OBJECT_TYPE");
|
||||||
assertThat(obj).isNotEqualTo(new ObjectIdentityImpl(DOMAIN_CLASS, 2L));
|
assertThat(obj).isNotEqualTo(new ObjectIdentityImpl(DOMAIN_CLASS, 2L));
|
||||||
assertThat(obj).isNotEqualTo(new ObjectIdentityImpl(
|
assertThat(obj).isNotEqualTo(new ObjectIdentityImpl(
|
||||||
"org.springframework.security.acls.domain.ObjectIdentityImplTests$MockOtherIdDomainObject",
|
"org.springframework.security.acls.domain.ObjectIdentityImplTests$MockOtherIdDomainObject", 1L));
|
||||||
1L));
|
|
||||||
assertThat(new ObjectIdentityImpl(DOMAIN_CLASS, 1L)).isEqualTo(obj);
|
assertThat(new ObjectIdentityImpl(DOMAIN_CLASS, 1L)).isEqualTo(obj);
|
||||||
assertThat(new ObjectIdentityImpl(mockObj)).isEqualTo(obj);
|
assertThat(new ObjectIdentityImpl(mockObj)).isEqualTo(obj);
|
||||||
}
|
}
|
||||||
@@ -158,7 +145,6 @@ public class ObjectIdentityImplTests {
|
|||||||
public void longAndIntegerIdsWithSameValueAreEqualAndHaveSameHashcode() {
|
public void longAndIntegerIdsWithSameValueAreEqualAndHaveSameHashcode() {
|
||||||
ObjectIdentity obj = new ObjectIdentityImpl(Object.class, 5L);
|
ObjectIdentity obj = new ObjectIdentityImpl(Object.class, 5L);
|
||||||
ObjectIdentity obj2 = new ObjectIdentityImpl(Object.class, 5);
|
ObjectIdentity obj2 = new ObjectIdentityImpl(Object.class, 5);
|
||||||
|
|
||||||
assertThat(obj2).isEqualTo(obj);
|
assertThat(obj2).isEqualTo(obj);
|
||||||
assertThat(obj2.hashCode()).isEqualTo(obj.hashCode());
|
assertThat(obj2.hashCode()).isEqualTo(obj.hashCode());
|
||||||
}
|
}
|
||||||
@@ -178,30 +164,32 @@ public class ObjectIdentityImplTests {
|
|||||||
assertThat(obj).isNotEqualTo(obj2);
|
assertThat(obj).isNotEqualTo(obj2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Inner Classes
|
|
||||||
// ==================================================================================================
|
|
||||||
|
|
||||||
private class MockIdDomainObject {
|
private class MockIdDomainObject {
|
||||||
|
|
||||||
private Object id;
|
private Object id;
|
||||||
|
|
||||||
public Object getId() {
|
public Object getId() {
|
||||||
return id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(Object id) {
|
public void setId(Object id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MockOtherIdDomainObject {
|
private class MockOtherIdDomainObject {
|
||||||
|
|
||||||
private Object id;
|
private Object id;
|
||||||
|
|
||||||
public Object getId() {
|
public Object getId() {
|
||||||
return id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(Object id) {
|
public void setId(Object id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-9
@@ -13,14 +13,16 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.ObjectIdentity;
|
import org.springframework.security.acls.model.ObjectIdentity;
|
||||||
import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
|
import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link ObjectIdentityRetrievalStrategyImpl}
|
* Tests for {@link ObjectIdentityRetrievalStrategyImpl}
|
||||||
*
|
*
|
||||||
@@ -28,33 +30,29 @@ import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
|
|||||||
*/
|
*/
|
||||||
public class ObjectIdentityRetrievalStrategyImplTests {
|
public class ObjectIdentityRetrievalStrategyImplTests {
|
||||||
|
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
@Test
|
@Test
|
||||||
public void testObjectIdentityCreation() {
|
public void testObjectIdentityCreation() {
|
||||||
MockIdDomainObject domain = new MockIdDomainObject();
|
MockIdDomainObject domain = new MockIdDomainObject();
|
||||||
domain.setId(1);
|
domain.setId(1);
|
||||||
|
|
||||||
ObjectIdentityRetrievalStrategy retStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
ObjectIdentityRetrievalStrategy retStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
||||||
ObjectIdentity identity = retStrategy.getObjectIdentity(domain);
|
ObjectIdentity identity = retStrategy.getObjectIdentity(domain);
|
||||||
|
|
||||||
assertThat(identity).isNotNull();
|
assertThat(identity).isNotNull();
|
||||||
assertThat(new ObjectIdentityImpl(domain)).isEqualTo(identity);
|
assertThat(new ObjectIdentityImpl(domain)).isEqualTo(identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Inner Classes
|
|
||||||
// ==================================================================================================
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private class MockIdDomainObject {
|
private class MockIdDomainObject {
|
||||||
|
|
||||||
private Object id;
|
private Object id;
|
||||||
|
|
||||||
public Object getId() {
|
public Object getId() {
|
||||||
return id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(Object id) {
|
public void setId(Object id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,14 +13,16 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.acls.domain;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.Permission;
|
import org.springframework.security.acls.model.Permission;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests classes associated with Permission.
|
* Tests classes associated with Permission.
|
||||||
*
|
*
|
||||||
@@ -32,12 +34,12 @@ public class PermissionTests {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void createPermissionfactory() {
|
public void createPermissionfactory() {
|
||||||
permissionFactory = new DefaultPermissionFactory();
|
this.permissionFactory = new DefaultPermissionFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void basePermissionTest() {
|
public void basePermissionTest() {
|
||||||
Permission p = permissionFactory.buildFromName("WRITE");
|
Permission p = this.permissionFactory.buildFromName("WRITE");
|
||||||
assertThat(p).isNotNull();
|
assertThat(p).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,53 +47,37 @@ public class PermissionTests {
|
|||||||
public void expectedIntegerValues() {
|
public void expectedIntegerValues() {
|
||||||
assertThat(BasePermission.READ.getMask()).isEqualTo(1);
|
assertThat(BasePermission.READ.getMask()).isEqualTo(1);
|
||||||
assertThat(BasePermission.ADMINISTRATION.getMask()).isEqualTo(16);
|
assertThat(BasePermission.ADMINISTRATION.getMask()).isEqualTo(16);
|
||||||
assertThat(
|
assertThat(new CumulativePermission().set(BasePermission.READ).set(BasePermission.WRITE)
|
||||||
new CumulativePermission().set(BasePermission.READ)
|
.set(BasePermission.CREATE).getMask()).isEqualTo(7);
|
||||||
.set(BasePermission.WRITE).set(BasePermission.CREATE).getMask())
|
assertThat(new CumulativePermission().set(BasePermission.READ).set(BasePermission.ADMINISTRATION).getMask())
|
||||||
.isEqualTo(7);
|
.isEqualTo(17);
|
||||||
assertThat(
|
|
||||||
new CumulativePermission().set(BasePermission.READ)
|
|
||||||
.set(BasePermission.ADMINISTRATION).getMask())
|
|
||||||
.isEqualTo(17);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void fromInteger() {
|
public void fromInteger() {
|
||||||
Permission permission = permissionFactory.buildFromMask(7);
|
Permission permission = this.permissionFactory.buildFromMask(7);
|
||||||
permission = permissionFactory.buildFromMask(4);
|
permission = this.permissionFactory.buildFromMask(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void stringConversion() {
|
public void stringConversion() {
|
||||||
permissionFactory.registerPublicPermissions(SpecialPermission.class);
|
this.permissionFactory.registerPublicPermissions(SpecialPermission.class);
|
||||||
|
assertThat(BasePermission.READ.toString()).isEqualTo("BasePermission[...............................R=1]");
|
||||||
assertThat(BasePermission.READ.toString())
|
assertThat(BasePermission.ADMINISTRATION.toString())
|
||||||
.isEqualTo("BasePermission[...............................R=1]");
|
.isEqualTo("BasePermission[...........................A....=16]");
|
||||||
|
assertThat(new CumulativePermission().set(BasePermission.READ).toString())
|
||||||
|
.isEqualTo("CumulativePermission[...............................R=1]");
|
||||||
assertThat(
|
assertThat(
|
||||||
BasePermission.ADMINISTRATION.toString())
|
new CumulativePermission().set(SpecialPermission.ENTER).set(BasePermission.ADMINISTRATION).toString())
|
||||||
.isEqualTo("BasePermission[...........................A....=16]");
|
.isEqualTo("CumulativePermission[..........................EA....=48]");
|
||||||
|
assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ).toString())
|
||||||
assertThat(
|
.isEqualTo("CumulativePermission[...........................A...R=17]");
|
||||||
new CumulativePermission().set(BasePermission.READ).toString())
|
assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ)
|
||||||
.isEqualTo("CumulativePermission[...............................R=1]");
|
.clear(BasePermission.ADMINISTRATION).toString())
|
||||||
|
.isEqualTo("CumulativePermission[...............................R=1]");
|
||||||
assertThat(new CumulativePermission().set(SpecialPermission.ENTER)
|
assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ)
|
||||||
.set(BasePermission.ADMINISTRATION).toString())
|
.clear(BasePermission.ADMINISTRATION).clear(BasePermission.READ).toString())
|
||||||
.isEqualTo("CumulativePermission[..........................EA....=48]");
|
.isEqualTo("CumulativePermission[................................=0]");
|
||||||
|
|
||||||
assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION)
|
|
||||||
.set(BasePermission.READ).toString())
|
|
||||||
.isEqualTo("CumulativePermission[...........................A...R=17]");
|
|
||||||
|
|
||||||
assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION)
|
|
||||||
.set(BasePermission.READ).clear(BasePermission.ADMINISTRATION)
|
|
||||||
.toString())
|
|
||||||
.isEqualTo("CumulativePermission[...............................R=1]");
|
|
||||||
|
|
||||||
assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION)
|
|
||||||
.set(BasePermission.READ).clear(BasePermission.ADMINISTRATION)
|
|
||||||
.clear(BasePermission.READ).toString())
|
|
||||||
.isEqualTo("CumulativePermission[................................=0]");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.Permission;
|
import org.springframework.security.acls.model.Permission;
|
||||||
@@ -23,10 +24,13 @@ import org.springframework.security.acls.model.Permission;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class SpecialPermission extends BasePermission {
|
public class SpecialPermission extends BasePermission {
|
||||||
|
|
||||||
public static final Permission ENTER = new SpecialPermission(1 << 5, 'E'); // 32
|
public static final Permission ENTER = new SpecialPermission(1 << 5, 'E'); // 32
|
||||||
|
|
||||||
public static final Permission LEAVE = new SpecialPermission(1 << 6, 'L');
|
public static final Permission LEAVE = new SpecialPermission(1 << 6, 'L');
|
||||||
|
|
||||||
protected SpecialPermission(int mask, char code) {
|
protected SpecialPermission(int mask, char code) {
|
||||||
super(mask, code);
|
super(mask, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+65
-80
@@ -13,19 +13,38 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.jdbc;
|
package org.springframework.security.acls.jdbc;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import net.sf.ehcache.Cache;
|
import net.sf.ehcache.Cache;
|
||||||
import net.sf.ehcache.CacheManager;
|
import net.sf.ehcache.CacheManager;
|
||||||
import net.sf.ehcache.Ehcache;
|
import net.sf.ehcache.Ehcache;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.junit.*;
|
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
import org.springframework.security.acls.TargetObject;
|
import org.springframework.security.acls.TargetObject;
|
||||||
import org.springframework.security.acls.TargetObjectWithUUID;
|
import org.springframework.security.acls.TargetObjectWithUUID;
|
||||||
import org.springframework.security.acls.domain.*;
|
import org.springframework.security.acls.domain.AclAuthorizationStrategy;
|
||||||
|
import org.springframework.security.acls.domain.AclAuthorizationStrategyImpl;
|
||||||
|
import org.springframework.security.acls.domain.BasePermission;
|
||||||
|
import org.springframework.security.acls.domain.ConsoleAuditLogger;
|
||||||
|
import org.springframework.security.acls.domain.DefaultPermissionFactory;
|
||||||
|
import org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy;
|
||||||
|
import org.springframework.security.acls.domain.EhCacheBasedAclCache;
|
||||||
|
import org.springframework.security.acls.domain.GrantedAuthoritySid;
|
||||||
|
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||||
|
import org.springframework.security.acls.domain.PrincipalSid;
|
||||||
import org.springframework.security.acls.model.Acl;
|
import org.springframework.security.acls.model.Acl;
|
||||||
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
||||||
import org.springframework.security.acls.model.MutableAcl;
|
import org.springframework.security.acls.model.MutableAcl;
|
||||||
@@ -35,9 +54,8 @@ import org.springframework.security.acls.model.Permission;
|
|||||||
import org.springframework.security.acls.model.Sid;
|
import org.springframework.security.acls.model.Sid;
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
|
||||||
import java.util.*;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.fail;
|
||||||
import javax.sql.DataSource;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link BasicLookupStrategy}
|
* Tests {@link BasicLookupStrategy}
|
||||||
@@ -47,19 +65,18 @@ import javax.sql.DataSource;
|
|||||||
public abstract class AbstractBasicLookupStrategyTests {
|
public abstract class AbstractBasicLookupStrategyTests {
|
||||||
|
|
||||||
protected static final Sid BEN_SID = new PrincipalSid("ben");
|
protected static final Sid BEN_SID = new PrincipalSid("ben");
|
||||||
|
|
||||||
protected static final String TARGET_CLASS = TargetObject.class.getName();
|
protected static final String TARGET_CLASS = TargetObject.class.getName();
|
||||||
|
|
||||||
protected static final String TARGET_CLASS_WITH_UUID = TargetObjectWithUUID.class.getName();
|
protected static final String TARGET_CLASS_WITH_UUID = TargetObjectWithUUID.class.getName();
|
||||||
|
|
||||||
protected static final UUID OBJECT_IDENTITY_UUID = UUID.randomUUID();
|
protected static final UUID OBJECT_IDENTITY_UUID = UUID.randomUUID();
|
||||||
|
|
||||||
protected static final Long OBJECT_IDENTITY_LONG_AS_UUID = 110L;
|
protected static final Long OBJECT_IDENTITY_LONG_AS_UUID = 110L;
|
||||||
|
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
private BasicLookupStrategy strategy;
|
private BasicLookupStrategy strategy;
|
||||||
private static CacheManager cacheManager;
|
|
||||||
|
|
||||||
// ~ Methods
|
private static CacheManager cacheManager;
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
public abstract JdbcTemplate getJdbcTemplate();
|
public abstract JdbcTemplate getJdbcTemplate();
|
||||||
|
|
||||||
@@ -80,44 +97,41 @@ public abstract class AbstractBasicLookupStrategyTests {
|
|||||||
@Before
|
@Before
|
||||||
public void populateDatabase() {
|
public void populateDatabase() {
|
||||||
String query = "INSERT INTO acl_sid(ID,PRINCIPAL,SID) VALUES (1,1,'ben');"
|
String query = "INSERT INTO acl_sid(ID,PRINCIPAL,SID) VALUES (1,1,'ben');"
|
||||||
+ "INSERT INTO acl_class(ID,CLASS) VALUES (2,'" + TARGET_CLASS + "');"
|
+ "INSERT INTO acl_class(ID,CLASS) VALUES (2,'" + TARGET_CLASS + "');"
|
||||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (1,2,100,null,1,1);"
|
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (1,2,100,null,1,1);"
|
||||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (2,2,101,1,1,1);"
|
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (2,2,101,1,1,1);"
|
||||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (3,2,102,2,1,1);"
|
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (3,2,102,2,1,1);"
|
||||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (1,1,0,1,1,1,0,0);"
|
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (1,1,0,1,1,1,0,0);"
|
||||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (2,1,1,1,2,0,0,0);"
|
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (2,1,1,1,2,0,0,0);"
|
||||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (3,2,0,1,8,1,0,0);"
|
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (3,2,0,1,8,1,0,0);"
|
||||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (4,3,0,1,8,0,0,0);";
|
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (4,3,0,1,8,0,0,0);";
|
||||||
getJdbcTemplate().execute(query);
|
getJdbcTemplate().execute(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void initializeBeans() {
|
public void initializeBeans() {
|
||||||
strategy = new BasicLookupStrategy(getDataSource(), aclCache(), aclAuthStrategy(),
|
this.strategy = new BasicLookupStrategy(getDataSource(), aclCache(), aclAuthStrategy(),
|
||||||
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()));
|
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()));
|
||||||
strategy.setPermissionFactory(new DefaultPermissionFactory());
|
this.strategy.setPermissionFactory(new DefaultPermissionFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AclAuthorizationStrategy aclAuthStrategy() {
|
protected AclAuthorizationStrategy aclAuthStrategy() {
|
||||||
return new AclAuthorizationStrategyImpl(
|
return new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_ADMINISTRATOR"));
|
||||||
new SimpleGrantedAuthority("ROLE_ADMINISTRATOR"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EhCacheBasedAclCache aclCache() {
|
protected EhCacheBasedAclCache aclCache() {
|
||||||
return new EhCacheBasedAclCache(getCache(),
|
return new EhCacheBasedAclCache(getCache(), new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()),
|
||||||
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()),
|
new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER")));
|
||||||
new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void emptyDatabase() {
|
public void emptyDatabase() {
|
||||||
String query = "DELETE FROM acl_entry;" + "DELETE FROM acl_object_identity WHERE ID = 9;"
|
String query = "DELETE FROM acl_entry;" + "DELETE FROM acl_object_identity WHERE ID = 9;"
|
||||||
+ "DELETE FROM acl_object_identity WHERE ID = 8;" + "DELETE FROM acl_object_identity WHERE ID = 7;"
|
+ "DELETE FROM acl_object_identity WHERE ID = 8;" + "DELETE FROM acl_object_identity WHERE ID = 7;"
|
||||||
+ "DELETE FROM acl_object_identity WHERE ID = 6;" + "DELETE FROM acl_object_identity WHERE ID = 5;"
|
+ "DELETE FROM acl_object_identity WHERE ID = 6;" + "DELETE FROM acl_object_identity WHERE ID = 5;"
|
||||||
+ "DELETE FROM acl_object_identity WHERE ID = 4;" + "DELETE FROM acl_object_identity WHERE ID = 3;"
|
+ "DELETE FROM acl_object_identity WHERE ID = 4;" + "DELETE FROM acl_object_identity WHERE ID = 3;"
|
||||||
+ "DELETE FROM acl_object_identity WHERE ID = 2;" + "DELETE FROM acl_object_identity WHERE ID = 1;"
|
+ "DELETE FROM acl_object_identity WHERE ID = 2;" + "DELETE FROM acl_object_identity WHERE ID = 1;"
|
||||||
+ "DELETE FROM acl_class;" + "DELETE FROM acl_sid;";
|
+ "DELETE FROM acl_class;" + "DELETE FROM acl_sid;";
|
||||||
getJdbcTemplate().execute(query);
|
getJdbcTemplate().execute(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,9 +147,8 @@ public abstract class AbstractBasicLookupStrategyTests {
|
|||||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, 101L);
|
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, 101L);
|
||||||
// Deliberately use an integer for the child, to reproduce bug report in SEC-819
|
// Deliberately use an integer for the child, to reproduce bug report in SEC-819
|
||||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 102);
|
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 102);
|
||||||
|
|
||||||
Map<ObjectIdentity, Acl> map = this.strategy
|
Map<ObjectIdentity, Acl> map = this.strategy
|
||||||
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
||||||
checkEntries(topParentOid, middleParentOid, childOid, map);
|
checkEntries(topParentOid, middleParentOid, childOid, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,15 +157,12 @@ public abstract class AbstractBasicLookupStrategyTests {
|
|||||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, 100);
|
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, 100);
|
||||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, 101L);
|
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, 101L);
|
||||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 102L);
|
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 102L);
|
||||||
|
|
||||||
// Objects were put in cache
|
// Objects were put in cache
|
||||||
strategy.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
this.strategy.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
||||||
|
|
||||||
// Let's empty the database to force acls retrieval from cache
|
// Let's empty the database to force acls retrieval from cache
|
||||||
emptyDatabase();
|
emptyDatabase();
|
||||||
Map<ObjectIdentity, Acl> map = this.strategy
|
Map<ObjectIdentity, Acl> map = this.strategy
|
||||||
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
||||||
|
|
||||||
checkEntries(topParentOid, middleParentOid, childOid, map);
|
checkEntries(topParentOid, middleParentOid, childOid, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,43 +171,36 @@ public abstract class AbstractBasicLookupStrategyTests {
|
|||||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
||||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, 101);
|
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, 101);
|
||||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 102L);
|
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 102L);
|
||||||
|
|
||||||
// Set a batch size to allow multiple database queries in order to retrieve all
|
// Set a batch size to allow multiple database queries in order to retrieve all
|
||||||
// acls
|
// acls
|
||||||
this.strategy.setBatchSize(1);
|
this.strategy.setBatchSize(1);
|
||||||
Map<ObjectIdentity, Acl> map = this.strategy
|
Map<ObjectIdentity, Acl> map = this.strategy
|
||||||
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
||||||
checkEntries(topParentOid, middleParentOid, childOid, map);
|
checkEntries(topParentOid, middleParentOid, childOid, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkEntries(ObjectIdentity topParentOid, ObjectIdentity middleParentOid, ObjectIdentity childOid,
|
private void checkEntries(ObjectIdentity topParentOid, ObjectIdentity middleParentOid, ObjectIdentity childOid,
|
||||||
Map<ObjectIdentity, Acl> map) {
|
Map<ObjectIdentity, Acl> map) {
|
||||||
assertThat(map).hasSize(3);
|
assertThat(map).hasSize(3);
|
||||||
|
|
||||||
MutableAcl topParent = (MutableAcl) map.get(topParentOid);
|
MutableAcl topParent = (MutableAcl) map.get(topParentOid);
|
||||||
MutableAcl middleParent = (MutableAcl) map.get(middleParentOid);
|
MutableAcl middleParent = (MutableAcl) map.get(middleParentOid);
|
||||||
MutableAcl child = (MutableAcl) map.get(childOid);
|
MutableAcl child = (MutableAcl) map.get(childOid);
|
||||||
|
|
||||||
// Check the retrieved versions has IDs
|
// Check the retrieved versions has IDs
|
||||||
assertThat(topParent.getId()).isNotNull();
|
assertThat(topParent.getId()).isNotNull();
|
||||||
assertThat(middleParent.getId()).isNotNull();
|
assertThat(middleParent.getId()).isNotNull();
|
||||||
assertThat(child.getId()).isNotNull();
|
assertThat(child.getId()).isNotNull();
|
||||||
|
|
||||||
// Check their parents were correctly retrieved
|
// Check their parents were correctly retrieved
|
||||||
assertThat(topParent.getParentAcl()).isNull();
|
assertThat(topParent.getParentAcl()).isNull();
|
||||||
assertThat(middleParent.getParentAcl().getObjectIdentity()).isEqualTo(topParentOid);
|
assertThat(middleParent.getParentAcl().getObjectIdentity()).isEqualTo(topParentOid);
|
||||||
assertThat(child.getParentAcl().getObjectIdentity()).isEqualTo(middleParentOid);
|
assertThat(child.getParentAcl().getObjectIdentity()).isEqualTo(middleParentOid);
|
||||||
|
|
||||||
// Check their ACEs were correctly retrieved
|
// Check their ACEs were correctly retrieved
|
||||||
assertThat(topParent.getEntries()).hasSize(2);
|
assertThat(topParent.getEntries()).hasSize(2);
|
||||||
assertThat(middleParent.getEntries()).hasSize(1);
|
assertThat(middleParent.getEntries()).hasSize(1);
|
||||||
assertThat(child.getEntries()).hasSize(1);
|
assertThat(child.getEntries()).hasSize(1);
|
||||||
|
|
||||||
// Check object identities were correctly retrieved
|
// Check object identities were correctly retrieved
|
||||||
assertThat(topParent.getObjectIdentity()).isEqualTo(topParentOid);
|
assertThat(topParent.getObjectIdentity()).isEqualTo(topParentOid);
|
||||||
assertThat(middleParent.getObjectIdentity()).isEqualTo(middleParentOid);
|
assertThat(middleParent.getObjectIdentity()).isEqualTo(middleParentOid);
|
||||||
assertThat(child.getObjectIdentity()).isEqualTo(childOid);
|
assertThat(child.getObjectIdentity()).isEqualTo(childOid);
|
||||||
|
|
||||||
// Check each entry
|
// Check each entry
|
||||||
assertThat(topParent.isEntriesInheriting()).isTrue();
|
assertThat(topParent.isEntriesInheriting()).isTrue();
|
||||||
assertThat(Long.valueOf(1)).isEqualTo(topParent.getId());
|
assertThat(Long.valueOf(1)).isEqualTo(topParent.getId());
|
||||||
@@ -208,14 +211,12 @@ public abstract class AbstractBasicLookupStrategyTests {
|
|||||||
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isAuditFailure()).isFalse();
|
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isAuditFailure()).isFalse();
|
||||||
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isAuditSuccess()).isFalse();
|
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isAuditSuccess()).isFalse();
|
||||||
assertThat((topParent.getEntries().get(0)).isGranting()).isTrue();
|
assertThat((topParent.getEntries().get(0)).isGranting()).isTrue();
|
||||||
|
|
||||||
assertThat(Long.valueOf(2)).isEqualTo(topParent.getEntries().get(1).getId());
|
assertThat(Long.valueOf(2)).isEqualTo(topParent.getEntries().get(1).getId());
|
||||||
assertThat(topParent.getEntries().get(1).getPermission()).isEqualTo(BasePermission.WRITE);
|
assertThat(topParent.getEntries().get(1).getPermission()).isEqualTo(BasePermission.WRITE);
|
||||||
assertThat(topParent.getEntries().get(1).getSid()).isEqualTo(new PrincipalSid("ben"));
|
assertThat(topParent.getEntries().get(1).getSid()).isEqualTo(new PrincipalSid("ben"));
|
||||||
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isAuditFailure()).isFalse();
|
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isAuditFailure()).isFalse();
|
||||||
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isAuditSuccess()).isFalse();
|
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isAuditSuccess()).isFalse();
|
||||||
assertThat(topParent.getEntries().get(1).isGranting()).isFalse();
|
assertThat(topParent.getEntries().get(1).isGranting()).isFalse();
|
||||||
|
|
||||||
assertThat(middleParent.isEntriesInheriting()).isTrue();
|
assertThat(middleParent.isEntriesInheriting()).isTrue();
|
||||||
assertThat(Long.valueOf(2)).isEqualTo(middleParent.getId());
|
assertThat(Long.valueOf(2)).isEqualTo(middleParent.getId());
|
||||||
assertThat(new PrincipalSid("ben")).isEqualTo(middleParent.getOwner());
|
assertThat(new PrincipalSid("ben")).isEqualTo(middleParent.getOwner());
|
||||||
@@ -225,7 +226,6 @@ public abstract class AbstractBasicLookupStrategyTests {
|
|||||||
assertThat(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isAuditFailure()).isFalse();
|
assertThat(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isAuditFailure()).isFalse();
|
||||||
assertThat(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isAuditSuccess()).isFalse();
|
assertThat(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isAuditSuccess()).isFalse();
|
||||||
assertThat(middleParent.getEntries().get(0).isGranting()).isTrue();
|
assertThat(middleParent.getEntries().get(0).isGranting()).isTrue();
|
||||||
|
|
||||||
assertThat(child.isEntriesInheriting()).isTrue();
|
assertThat(child.isEntriesInheriting()).isTrue();
|
||||||
assertThat(Long.valueOf(3)).isEqualTo(child.getId());
|
assertThat(Long.valueOf(3)).isEqualTo(child.getId());
|
||||||
assertThat(new PrincipalSid("ben")).isEqualTo(child.getOwner());
|
assertThat(new PrincipalSid("ben")).isEqualTo(child.getOwner());
|
||||||
@@ -241,15 +241,12 @@ public abstract class AbstractBasicLookupStrategyTests {
|
|||||||
public void testAllParentsAreRetrievedWhenChildIsLoaded() {
|
public void testAllParentsAreRetrievedWhenChildIsLoaded() {
|
||||||
String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (6,2,103,1,1,1);";
|
String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (6,2,103,1,1,1);";
|
||||||
getJdbcTemplate().execute(query);
|
getJdbcTemplate().execute(query);
|
||||||
|
|
||||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
||||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, 101L);
|
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, 101L);
|
||||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 102L);
|
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 102L);
|
||||||
ObjectIdentity middleParent2Oid = new ObjectIdentityImpl(TARGET_CLASS, 103L);
|
ObjectIdentity middleParent2Oid = new ObjectIdentityImpl(TARGET_CLASS, 103L);
|
||||||
|
|
||||||
// Retrieve the child
|
// Retrieve the child
|
||||||
Map<ObjectIdentity, Acl> map = this.strategy.readAclsById(Arrays.asList(childOid), null);
|
Map<ObjectIdentity, Acl> map = this.strategy.readAclsById(Arrays.asList(childOid), null);
|
||||||
|
|
||||||
// Check that the child and all its parents were retrieved
|
// Check that the child and all its parents were retrieved
|
||||||
assertThat(map.get(childOid)).isNotNull();
|
assertThat(map.get(childOid)).isNotNull();
|
||||||
assertThat(map.get(childOid).getObjectIdentity()).isEqualTo(childOid);
|
assertThat(map.get(childOid).getObjectIdentity()).isEqualTo(childOid);
|
||||||
@@ -257,7 +254,6 @@ public abstract class AbstractBasicLookupStrategyTests {
|
|||||||
assertThat(map.get(middleParentOid).getObjectIdentity()).isEqualTo(middleParentOid);
|
assertThat(map.get(middleParentOid).getObjectIdentity()).isEqualTo(middleParentOid);
|
||||||
assertThat(map.get(topParentOid)).isNotNull();
|
assertThat(map.get(topParentOid)).isNotNull();
|
||||||
assertThat(map.get(topParentOid).getObjectIdentity()).isEqualTo(topParentOid);
|
assertThat(map.get(topParentOid).getObjectIdentity()).isEqualTo(topParentOid);
|
||||||
|
|
||||||
// The second parent shouldn't have been retrieved
|
// The second parent shouldn't have been retrieved
|
||||||
assertThat(map.get(middleParent2Oid)).isNull();
|
assertThat(map.get(middleParent2Oid)).isNull();
|
||||||
}
|
}
|
||||||
@@ -268,31 +264,26 @@ public abstract class AbstractBasicLookupStrategyTests {
|
|||||||
@Test
|
@Test
|
||||||
public void testReadAllObjectIdentitiesWhenLastElementIsAlreadyCached() {
|
public void testReadAllObjectIdentitiesWhenLastElementIsAlreadyCached() {
|
||||||
String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (6,2,105,null,1,1);"
|
String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (6,2,105,null,1,1);"
|
||||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (7,2,106,6,1,1);"
|
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (7,2,106,6,1,1);"
|
||||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (8,2,107,6,1,1);"
|
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (8,2,107,6,1,1);"
|
||||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (9,2,108,7,1,1);"
|
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (9,2,108,7,1,1);"
|
||||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (7,6,0,1,1,1,0,0)";
|
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (7,6,0,1,1,1,0,0)";
|
||||||
getJdbcTemplate().execute(query);
|
getJdbcTemplate().execute(query);
|
||||||
|
|
||||||
ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, 104L);
|
ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, 104L);
|
||||||
ObjectIdentity parent1Oid = new ObjectIdentityImpl(TARGET_CLASS, 105L);
|
ObjectIdentity parent1Oid = new ObjectIdentityImpl(TARGET_CLASS, 105L);
|
||||||
ObjectIdentity parent2Oid = new ObjectIdentityImpl(TARGET_CLASS, 106);
|
ObjectIdentity parent2Oid = new ObjectIdentityImpl(TARGET_CLASS, 106);
|
||||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 107);
|
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 107);
|
||||||
|
|
||||||
// First lookup only child, thus populating the cache with grandParent,
|
// First lookup only child, thus populating the cache with grandParent,
|
||||||
// parent1
|
// parent1
|
||||||
// and child
|
// and child
|
||||||
List<Permission> checkPermission = Arrays.asList(BasePermission.READ);
|
List<Permission> checkPermission = Arrays.asList(BasePermission.READ);
|
||||||
List<Sid> sids = Arrays.asList(BEN_SID);
|
List<Sid> sids = Arrays.asList(BEN_SID);
|
||||||
List<ObjectIdentity> childOids = Arrays.asList(childOid);
|
List<ObjectIdentity> childOids = Arrays.asList(childOid);
|
||||||
|
this.strategy.setBatchSize(6);
|
||||||
strategy.setBatchSize(6);
|
Map<ObjectIdentity, Acl> foundAcls = this.strategy.readAclsById(childOids, sids);
|
||||||
Map<ObjectIdentity, Acl> foundAcls = strategy.readAclsById(childOids, sids);
|
|
||||||
|
|
||||||
Acl foundChildAcl = foundAcls.get(childOid);
|
Acl foundChildAcl = foundAcls.get(childOid);
|
||||||
assertThat(foundChildAcl).isNotNull();
|
assertThat(foundChildAcl).isNotNull();
|
||||||
assertThat(foundChildAcl.isGranted(checkPermission, sids, false)).isTrue();
|
assertThat(foundChildAcl.isGranted(checkPermission, sids, false)).isTrue();
|
||||||
|
|
||||||
// Search for object identities has to be done in the following order:
|
// Search for object identities has to be done in the following order:
|
||||||
// last
|
// last
|
||||||
// element have to be one which
|
// element have to be one which
|
||||||
@@ -300,12 +291,11 @@ public abstract class AbstractBasicLookupStrategyTests {
|
|||||||
// cache
|
// cache
|
||||||
List<ObjectIdentity> allOids = Arrays.asList(grandParentOid, parent1Oid, parent2Oid, childOid);
|
List<ObjectIdentity> allOids = Arrays.asList(grandParentOid, parent1Oid, parent2Oid, childOid);
|
||||||
try {
|
try {
|
||||||
foundAcls = strategy.readAclsById(allOids, sids);
|
foundAcls = this.strategy.readAclsById(allOids, sids);
|
||||||
|
}
|
||||||
} catch (NotFoundException notExpected) {
|
catch (NotFoundException notExpected) {
|
||||||
fail("It shouldn't have thrown NotFoundException");
|
fail("It shouldn't have thrown NotFoundException");
|
||||||
}
|
}
|
||||||
|
|
||||||
Acl foundParent2Acl = foundAcls.get(parent2Oid);
|
Acl foundParent2Acl = foundAcls.get(parent2Oid);
|
||||||
assertThat(foundParent2Acl).isNotNull();
|
assertThat(foundParent2Acl).isNotNull();
|
||||||
assertThat(foundParent2Acl.isGranted(checkPermission, sids, false)).isTrue();
|
assertThat(foundParent2Acl.isGranted(checkPermission, sids, false)).isTrue();
|
||||||
@@ -314,26 +304,21 @@ public abstract class AbstractBasicLookupStrategyTests {
|
|||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void nullOwnerIsNotSupported() {
|
public void nullOwnerIsNotSupported() {
|
||||||
String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (6,2,104,null,null,1);";
|
String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (6,2,104,null,null,1);";
|
||||||
|
|
||||||
getJdbcTemplate().execute(query);
|
getJdbcTemplate().execute(query);
|
||||||
|
|
||||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, 104L);
|
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, 104L);
|
||||||
|
this.strategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID));
|
||||||
strategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreatePrincipalSid() {
|
public void testCreatePrincipalSid() {
|
||||||
Sid result = strategy.createSid(true, "sid");
|
Sid result = this.strategy.createSid(true, "sid");
|
||||||
|
|
||||||
assertThat(result.getClass()).isEqualTo(PrincipalSid.class);
|
assertThat(result.getClass()).isEqualTo(PrincipalSid.class);
|
||||||
assertThat(((PrincipalSid) result).getPrincipal()).isEqualTo("sid");
|
assertThat(((PrincipalSid) result).getPrincipal()).isEqualTo("sid");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateGrantedAuthority() {
|
public void testCreateGrantedAuthority() {
|
||||||
Sid result = strategy.createSid(false, "sid");
|
Sid result = this.strategy.createSid(false, "sid");
|
||||||
|
|
||||||
assertThat(result.getClass()).isEqualTo(GrantedAuthoritySid.class);
|
assertThat(result.getClass()).isEqualTo(GrantedAuthoritySid.class);
|
||||||
assertThat(((GrantedAuthoritySid) result).getGrantedAuthority()).isEqualTo("sid");
|
assertThat(((GrantedAuthoritySid) result).getGrantedAuthority()).isEqualTo("sid");
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-72
@@ -13,38 +13,43 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.jdbc;
|
package org.springframework.security.acls.jdbc;
|
||||||
|
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.mockito.Mock;
|
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
|
||||||
import org.springframework.core.convert.ConversionService;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.ConversionService;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link AclClassIdUtils}.
|
* Tests for {@link AclClassIdUtils}.
|
||||||
|
*
|
||||||
* @author paulwheeler
|
* @author paulwheeler
|
||||||
*/
|
*/
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class AclClassIdUtilsTest {
|
public class AclClassIdUtilsTests {
|
||||||
|
|
||||||
private static final Long DEFAULT_IDENTIFIER = 999L;
|
private static final Long DEFAULT_IDENTIFIER = 999L;
|
||||||
|
|
||||||
private static final BigInteger BIGINT_IDENTIFIER = new BigInteger("999");
|
private static final BigInteger BIGINT_IDENTIFIER = new BigInteger("999");
|
||||||
|
|
||||||
private static final String DEFAULT_IDENTIFIER_AS_STRING = DEFAULT_IDENTIFIER.toString();
|
private static final String DEFAULT_IDENTIFIER_AS_STRING = DEFAULT_IDENTIFIER.toString();
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private ResultSet resultSet;
|
private ResultSet resultSet;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private ConversionService conversionService;
|
private ConversionService conversionService;
|
||||||
|
|
||||||
@@ -52,124 +57,82 @@ public class AclClassIdUtilsTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
aclClassIdUtils = new AclClassIdUtils();
|
this.aclClassIdUtils = new AclClassIdUtils();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldReturnLongIfIdentifierIsLong() throws SQLException {
|
public void shouldReturnLongIfIdentifierIsLong() throws SQLException {
|
||||||
// when
|
Serializable newIdentifier = this.aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER, this.resultSet);
|
||||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER, resultSet);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldReturnLongIfIdentifierIsBigInteger() throws SQLException {
|
public void shouldReturnLongIfIdentifierIsBigInteger() throws SQLException {
|
||||||
// when
|
Serializable newIdentifier = this.aclClassIdUtils.identifierFrom(BIGINT_IDENTIFIER, this.resultSet);
|
||||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(BIGINT_IDENTIFIER, resultSet);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldReturnLongIfClassIdTypeIsNull() throws SQLException {
|
public void shouldReturnLongIfClassIdTypeIsNull() throws SQLException {
|
||||||
// given
|
given(this.resultSet.getString("class_id_type")).willReturn(null);
|
||||||
given(resultSet.getString("class_id_type")).willReturn(null);
|
Serializable newIdentifier = this.aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, this.resultSet);
|
||||||
|
|
||||||
// when
|
|
||||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, resultSet);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldReturnLongIfNoClassIdTypeColumn() throws SQLException {
|
public void shouldReturnLongIfNoClassIdTypeColumn() throws SQLException {
|
||||||
// given
|
given(this.resultSet.getString("class_id_type")).willThrow(SQLException.class);
|
||||||
given(resultSet.getString("class_id_type")).willThrow(SQLException.class);
|
Serializable newIdentifier = this.aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, this.resultSet);
|
||||||
|
|
||||||
// when
|
|
||||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, resultSet);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldReturnLongIfTypeClassNotFound() throws SQLException {
|
public void shouldReturnLongIfTypeClassNotFound() throws SQLException {
|
||||||
// given
|
given(this.resultSet.getString("class_id_type")).willReturn("com.example.UnknownType");
|
||||||
given(resultSet.getString("class_id_type")).willReturn("com.example.UnknownType");
|
Serializable newIdentifier = this.aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, this.resultSet);
|
||||||
|
|
||||||
// when
|
|
||||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, resultSet);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldReturnLongEvenIfCustomConversionServiceDoesNotSupportLongConversion() throws SQLException {
|
public void shouldReturnLongEvenIfCustomConversionServiceDoesNotSupportLongConversion() throws SQLException {
|
||||||
// given
|
given(this.resultSet.getString("class_id_type")).willReturn("java.lang.Long");
|
||||||
given(resultSet.getString("class_id_type")).willReturn("java.lang.Long");
|
given(this.conversionService.canConvert(String.class, Long.class)).willReturn(false);
|
||||||
given(conversionService.canConvert(String.class, Long.class)).willReturn(false);
|
this.aclClassIdUtils.setConversionService(this.conversionService);
|
||||||
aclClassIdUtils.setConversionService(conversionService);
|
Serializable newIdentifier = this.aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, this.resultSet);
|
||||||
|
|
||||||
// when
|
|
||||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, resultSet);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldReturnLongWhenLongClassIdType() throws SQLException {
|
public void shouldReturnLongWhenLongClassIdType() throws SQLException {
|
||||||
// given
|
given(this.resultSet.getString("class_id_type")).willReturn("java.lang.Long");
|
||||||
given(resultSet.getString("class_id_type")).willReturn("java.lang.Long");
|
Serializable newIdentifier = this.aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, this.resultSet);
|
||||||
|
|
||||||
// when
|
|
||||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, resultSet);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldReturnUUIDWhenUUIDClassIdType() throws SQLException {
|
public void shouldReturnUUIDWhenUUIDClassIdType() throws SQLException {
|
||||||
// given
|
|
||||||
UUID identifier = UUID.randomUUID();
|
UUID identifier = UUID.randomUUID();
|
||||||
given(resultSet.getString("class_id_type")).willReturn("java.util.UUID");
|
given(this.resultSet.getString("class_id_type")).willReturn("java.util.UUID");
|
||||||
|
Serializable newIdentifier = this.aclClassIdUtils.identifierFrom(identifier.toString(), this.resultSet);
|
||||||
// when
|
|
||||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(identifier.toString(), resultSet);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(newIdentifier).isEqualTo(identifier);
|
assertThat(newIdentifier).isEqualTo(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldReturnStringWhenStringClassIdType() throws SQLException {
|
public void shouldReturnStringWhenStringClassIdType() throws SQLException {
|
||||||
// given
|
|
||||||
String identifier = "MY_STRING_IDENTIFIER";
|
String identifier = "MY_STRING_IDENTIFIER";
|
||||||
given(resultSet.getString("class_id_type")).willReturn("java.lang.String");
|
given(this.resultSet.getString("class_id_type")).willReturn("java.lang.String");
|
||||||
|
Serializable newIdentifier = this.aclClassIdUtils.identifierFrom(identifier, this.resultSet);
|
||||||
// when
|
|
||||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(identifier, resultSet);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(newIdentifier).isEqualTo(identifier);
|
assertThat(newIdentifier).isEqualTo(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void shouldNotAcceptNullConversionServiceInConstruction() {
|
public void shouldNotAcceptNullConversionServiceInConstruction() {
|
||||||
// when
|
|
||||||
new AclClassIdUtils(null);
|
new AclClassIdUtils(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void shouldNotAcceptNullConversionServiceInSetter() {
|
public void shouldNotAcceptNullConversionServiceInSetter() {
|
||||||
// when
|
this.aclClassIdUtils.setConversionService(null);
|
||||||
aclClassIdUtils.setConversionService(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+4
-1
@@ -13,12 +13,14 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.jdbc;
|
package org.springframework.security.acls.jdbc;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,8 +30,8 @@ import org.springframework.jdbc.core.JdbcTemplate;
|
|||||||
* @author Paul Wheeler
|
* @author Paul Wheeler
|
||||||
*/
|
*/
|
||||||
public class BasicLookupStrategyTests extends AbstractBasicLookupStrategyTests {
|
public class BasicLookupStrategyTests extends AbstractBasicLookupStrategyTests {
|
||||||
private static final BasicLookupStrategyTestsDbHelper DATABASE_HELPER = new BasicLookupStrategyTestsDbHelper();
|
|
||||||
|
|
||||||
|
private static final BasicLookupStrategyTestsDbHelper DATABASE_HELPER = new BasicLookupStrategyTestsDbHelper();
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void createDatabase() throws Exception {
|
public static void createDatabase() throws Exception {
|
||||||
@@ -50,4 +52,5 @@ public class BasicLookupStrategyTests extends AbstractBasicLookupStrategyTests {
|
|||||||
public DataSource getDataSource() {
|
public DataSource getDataSource() {
|
||||||
return DATABASE_HELPER.getDataSource();
|
return DATABASE_HELPER.getDataSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-10
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.jdbc;
|
package org.springframework.security.acls.jdbc;
|
||||||
|
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
@@ -23,15 +24,20 @@ import org.springframework.util.FileCopyUtils;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class to initialize the database for BasicLookupStrategyTests.
|
* Helper class to initialize the database for BasicLookupStrategyTests.
|
||||||
|
*
|
||||||
* @author Andrei Stefan
|
* @author Andrei Stefan
|
||||||
* @author Paul Wheeler
|
* @author Paul Wheeler
|
||||||
*/
|
*/
|
||||||
public class BasicLookupStrategyTestsDbHelper {
|
public class BasicLookupStrategyTestsDbHelper {
|
||||||
|
|
||||||
private static final String ACL_SCHEMA_SQL_FILE = "createAclSchema.sql";
|
private static final String ACL_SCHEMA_SQL_FILE = "createAclSchema.sql";
|
||||||
|
|
||||||
private static final String ACL_SCHEMA_SQL_FILE_WITH_ACL_CLASS_ID = "createAclSchemaWithAclClassIdType.sql";
|
private static final String ACL_SCHEMA_SQL_FILE_WITH_ACL_CLASS_ID = "createAclSchemaWithAclClassIdType.sql";
|
||||||
|
|
||||||
private SingleConnectionDataSource dataSource;
|
private SingleConnectionDataSource dataSource;
|
||||||
|
|
||||||
private JdbcTemplate jdbcTemplate;
|
private JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
private boolean withAclClassIdType;
|
private boolean withAclClassIdType;
|
||||||
|
|
||||||
public BasicLookupStrategyTestsDbHelper() {
|
public BasicLookupStrategyTestsDbHelper() {
|
||||||
@@ -45,28 +51,28 @@ public class BasicLookupStrategyTestsDbHelper {
|
|||||||
// Use a different connection url so the tests can run in parallel
|
// Use a different connection url so the tests can run in parallel
|
||||||
String connectionUrl;
|
String connectionUrl;
|
||||||
String sqlClassPathResource;
|
String sqlClassPathResource;
|
||||||
if (!withAclClassIdType) {
|
if (!this.withAclClassIdType) {
|
||||||
connectionUrl = "jdbc:hsqldb:mem:lookupstrategytest";
|
connectionUrl = "jdbc:hsqldb:mem:lookupstrategytest";
|
||||||
sqlClassPathResource = ACL_SCHEMA_SQL_FILE;
|
sqlClassPathResource = ACL_SCHEMA_SQL_FILE;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
connectionUrl = "jdbc:hsqldb:mem:lookupstrategytestWithAclClassIdType";
|
connectionUrl = "jdbc:hsqldb:mem:lookupstrategytestWithAclClassIdType";
|
||||||
sqlClassPathResource = ACL_SCHEMA_SQL_FILE_WITH_ACL_CLASS_ID;
|
sqlClassPathResource = ACL_SCHEMA_SQL_FILE_WITH_ACL_CLASS_ID;
|
||||||
|
|
||||||
}
|
}
|
||||||
dataSource = new SingleConnectionDataSource(connectionUrl, "sa", "", true);
|
this.dataSource = new SingleConnectionDataSource(connectionUrl, "sa", "", true);
|
||||||
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
|
this.dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
|
||||||
jdbcTemplate = new JdbcTemplate(dataSource);
|
this.jdbcTemplate = new JdbcTemplate(this.dataSource);
|
||||||
|
|
||||||
Resource resource = new ClassPathResource(sqlClassPathResource);
|
Resource resource = new ClassPathResource(sqlClassPathResource);
|
||||||
String sql = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
|
String sql = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
|
||||||
jdbcTemplate.execute(sql);
|
this.jdbcTemplate.execute(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JdbcTemplate getJdbcTemplate() {
|
public JdbcTemplate getJdbcTemplate() {
|
||||||
return jdbcTemplate;
|
return this.jdbcTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SingleConnectionDataSource getDataSource() {
|
public SingleConnectionDataSource getDataSource() {
|
||||||
return dataSource;
|
return this.dataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-19
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.jdbc;
|
package org.springframework.security.acls.jdbc;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -20,10 +21,12 @@ import java.util.Map;
|
|||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.core.convert.ConversionFailedException;
|
import org.springframework.core.convert.ConversionFailedException;
|
||||||
import org.springframework.core.convert.support.DefaultConversionService;
|
import org.springframework.core.convert.support.DefaultConversionService;
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
@@ -34,8 +37,6 @@ import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
|||||||
import org.springframework.security.acls.model.Acl;
|
import org.springframework.security.acls.model.Acl;
|
||||||
import org.springframework.security.acls.model.ObjectIdentity;
|
import org.springframework.security.acls.model.ObjectIdentity;
|
||||||
|
|
||||||
import junit.framework.Assert;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link BasicLookupStrategy} with Acl Class type id set to UUID.
|
* Tests {@link BasicLookupStrategy} with Acl Class type id set to UUID.
|
||||||
*
|
*
|
||||||
@@ -67,34 +68,35 @@ public class BasicLookupStrategyWithAclClassTypeTests extends AbstractBasicLooku
|
|||||||
DATABASE_HELPER.getDataSource().destroy();
|
DATABASE_HELPER.getDataSource().destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@Before
|
@Before
|
||||||
public void initializeBeans() {
|
public void initializeBeans() {
|
||||||
super.initializeBeans();
|
super.initializeBeans();
|
||||||
uuidEnabledStrategy = new BasicLookupStrategy(getDataSource(), aclCache(), aclAuthStrategy(),
|
this.uuidEnabledStrategy = new BasicLookupStrategy(getDataSource(), aclCache(), aclAuthStrategy(),
|
||||||
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()));
|
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()));
|
||||||
uuidEnabledStrategy.setPermissionFactory(new DefaultPermissionFactory());
|
this.uuidEnabledStrategy.setPermissionFactory(new DefaultPermissionFactory());
|
||||||
uuidEnabledStrategy.setAclClassIdSupported(true);
|
this.uuidEnabledStrategy.setAclClassIdSupported(true);
|
||||||
uuidEnabledStrategy.setConversionService(new DefaultConversionService());
|
this.uuidEnabledStrategy.setConversionService(new DefaultConversionService());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void populateDatabaseForAclClassTypeTests() {
|
public void populateDatabaseForAclClassTypeTests() {
|
||||||
String query = "INSERT INTO acl_class(ID,CLASS,CLASS_ID_TYPE) VALUES (3,'"
|
String query = "INSERT INTO acl_class(ID,CLASS,CLASS_ID_TYPE) VALUES (3,'" + TARGET_CLASS_WITH_UUID
|
||||||
+ TARGET_CLASS_WITH_UUID
|
+ "', 'java.util.UUID');"
|
||||||
+ "', 'java.util.UUID');"
|
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,3,'"
|
||||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,3,'"
|
+ OBJECT_IDENTITY_UUID.toString() + "',null,1,1);"
|
||||||
+ OBJECT_IDENTITY_UUID.toString() + "',null,1,1);"
|
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (5,3,'"
|
||||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (5,3,'"
|
+ OBJECT_IDENTITY_LONG_AS_UUID + "',null,1,1);"
|
||||||
+ OBJECT_IDENTITY_LONG_AS_UUID + "',null,1,1);"
|
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (5,4,0,1,8,0,0,0);"
|
||||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (5,4,0,1,8,0,0,0);"
|
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (6,5,0,1,8,0,0,0);";
|
||||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (6,5,0,1,8,0,0,0);";
|
|
||||||
DATABASE_HELPER.getJdbcTemplate().execute(query);
|
DATABASE_HELPER.getJdbcTemplate().execute(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadObjectIdentityUsingUuidType() {
|
public void testReadObjectIdentityUsingUuidType() {
|
||||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, OBJECT_IDENTITY_UUID);
|
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, OBJECT_IDENTITY_UUID);
|
||||||
Map<ObjectIdentity, Acl> foundAcls = uuidEnabledStrategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID));
|
Map<ObjectIdentity, Acl> foundAcls = this.uuidEnabledStrategy.readAclsById(Arrays.asList(oid),
|
||||||
|
Arrays.asList(BEN_SID));
|
||||||
Assert.assertEquals(1, foundAcls.size());
|
Assert.assertEquals(1, foundAcls.size());
|
||||||
Assert.assertNotNull(foundAcls.get(oid));
|
Assert.assertNotNull(foundAcls.get(oid));
|
||||||
}
|
}
|
||||||
@@ -102,7 +104,8 @@ public class BasicLookupStrategyWithAclClassTypeTests extends AbstractBasicLooku
|
|||||||
@Test
|
@Test
|
||||||
public void testReadObjectIdentityUsingLongTypeWithConversionServiceEnabled() {
|
public void testReadObjectIdentityUsingLongTypeWithConversionServiceEnabled() {
|
||||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
||||||
Map<ObjectIdentity, Acl> foundAcls = uuidEnabledStrategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID));
|
Map<ObjectIdentity, Acl> foundAcls = this.uuidEnabledStrategy.readAclsById(Arrays.asList(oid),
|
||||||
|
Arrays.asList(BEN_SID));
|
||||||
Assert.assertEquals(1, foundAcls.size());
|
Assert.assertEquals(1, foundAcls.size());
|
||||||
Assert.assertNotNull(foundAcls.get(oid));
|
Assert.assertNotNull(foundAcls.get(oid));
|
||||||
}
|
}
|
||||||
@@ -110,6 +113,7 @@ public class BasicLookupStrategyWithAclClassTypeTests extends AbstractBasicLooku
|
|||||||
@Test(expected = ConversionFailedException.class)
|
@Test(expected = ConversionFailedException.class)
|
||||||
public void testReadObjectIdentityUsingNonUuidInDatabase() {
|
public void testReadObjectIdentityUsingNonUuidInDatabase() {
|
||||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, OBJECT_IDENTITY_LONG_AS_UUID);
|
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, OBJECT_IDENTITY_LONG_AS_UUID);
|
||||||
uuidEnabledStrategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID));
|
this.uuidEnabledStrategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,34 +13,31 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.jdbc;
|
package org.springframework.security.acls.jdbc;
|
||||||
|
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
|
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.FileCopyUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.FileCopyUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Seeds the database for {@link JdbcMutableAclServiceTests}.
|
* Seeds the database for {@link JdbcMutableAclServiceTests}.
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class DatabaseSeeder {
|
public class DatabaseSeeder {
|
||||||
// ~ Constructors
|
|
||||||
// ===================================================================================================
|
|
||||||
|
|
||||||
public DatabaseSeeder(DataSource dataSource, Resource resource) throws IOException {
|
public DatabaseSeeder(DataSource dataSource, Resource resource) throws IOException {
|
||||||
Assert.notNull(dataSource, "dataSource required");
|
Assert.notNull(dataSource, "dataSource required");
|
||||||
Assert.notNull(resource, "resource required");
|
Assert.notNull(resource, "resource required");
|
||||||
|
|
||||||
JdbcTemplate template = new JdbcTemplate(dataSource);
|
JdbcTemplate template = new JdbcTemplate(dataSource);
|
||||||
String sql = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
|
String sql = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
|
||||||
template.execute(sql);
|
template.execute(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+82
-117
@@ -13,10 +13,8 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.acls.jdbc;
|
|
||||||
|
|
||||||
import static org.mockito.Mockito.*;
|
package org.springframework.security.acls.jdbc;
|
||||||
import static org.assertj.core.api.Assertions.*;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@@ -28,7 +26,6 @@ import java.util.List;
|
|||||||
|
|
||||||
import net.sf.ehcache.Ehcache;
|
import net.sf.ehcache.Ehcache;
|
||||||
import net.sf.ehcache.Element;
|
import net.sf.ehcache.Element;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -37,7 +34,14 @@ import org.mockito.ArgumentCaptor;
|
|||||||
import org.mockito.Captor;
|
import org.mockito.Captor;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
import org.springframework.security.acls.domain.*;
|
|
||||||
|
import org.springframework.security.acls.domain.AclAuthorizationStrategy;
|
||||||
|
import org.springframework.security.acls.domain.AclAuthorizationStrategyImpl;
|
||||||
|
import org.springframework.security.acls.domain.AclImpl;
|
||||||
|
import org.springframework.security.acls.domain.ConsoleAuditLogger;
|
||||||
|
import org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy;
|
||||||
|
import org.springframework.security.acls.domain.EhCacheBasedAclCache;
|
||||||
|
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||||
import org.springframework.security.acls.model.MutableAcl;
|
import org.springframework.security.acls.model.MutableAcl;
|
||||||
import org.springframework.security.acls.model.ObjectIdentity;
|
import org.springframework.security.acls.model.ObjectIdentity;
|
||||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
@@ -47,6 +51,12 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
|||||||
import org.springframework.security.util.FieldUtils;
|
import org.springframework.security.util.FieldUtils;
|
||||||
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.fail;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link EhCacheBasedAclCache}
|
* Tests {@link EhCacheBasedAclCache}
|
||||||
*
|
*
|
||||||
@@ -54,10 +64,12 @@ import org.springframework.test.util.ReflectionTestUtils;
|
|||||||
*/
|
*/
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class EhCacheBasedAclCacheTests {
|
public class EhCacheBasedAclCacheTests {
|
||||||
|
|
||||||
private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject";
|
private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject";
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private Ehcache cache;
|
private Ehcache cache;
|
||||||
|
|
||||||
@Captor
|
@Captor
|
||||||
private ArgumentCaptor<Element> element;
|
private ArgumentCaptor<Element> element;
|
||||||
|
|
||||||
@@ -67,17 +79,14 @@ public class EhCacheBasedAclCacheTests {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
myCache = new EhCacheBasedAclCache(cache, new DefaultPermissionGrantingStrategy(
|
this.myCache = new EhCacheBasedAclCache(this.cache,
|
||||||
new ConsoleAuditLogger()), new AclAuthorizationStrategyImpl(
|
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()),
|
||||||
new SimpleGrantedAuthority("ROLE_USER")));
|
new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER")));
|
||||||
|
|
||||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
||||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority(
|
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||||
"ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL"));
|
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||||
|
this.acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||||
acl = new AclImpl(identity, 1L, aclAuthorizationStrategy,
|
|
||||||
new ConsoleAuditLogger());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@@ -87,48 +96,43 @@ public class EhCacheBasedAclCacheTests {
|
|||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void constructorRejectsNullParameters() {
|
public void constructorRejectsNullParameters() {
|
||||||
new EhCacheBasedAclCache(null, new DefaultPermissionGrantingStrategy(
|
new EhCacheBasedAclCache(null, new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()),
|
||||||
new ConsoleAuditLogger()), new AclAuthorizationStrategyImpl(
|
new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER")));
|
||||||
new SimpleGrantedAuthority("ROLE_USER")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void methodsRejectNullParameters() {
|
public void methodsRejectNullParameters() {
|
||||||
try {
|
try {
|
||||||
Serializable id = null;
|
Serializable id = null;
|
||||||
myCache.evictFromCache(id);
|
this.myCache.evictFromCache(id);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ObjectIdentity obj = null;
|
ObjectIdentity obj = null;
|
||||||
myCache.evictFromCache(obj);
|
this.myCache.evictFromCache(obj);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Serializable id = null;
|
Serializable id = null;
|
||||||
myCache.getFromCache(id);
|
this.myCache.getFromCache(id);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ObjectIdentity obj = null;
|
ObjectIdentity obj = null;
|
||||||
myCache.getFromCache(obj);
|
this.myCache.getFromCache(obj);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
MutableAcl acl = null;
|
MutableAcl acl = null;
|
||||||
myCache.putInCache(acl);
|
this.myCache.putInCache(acl);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
@@ -142,146 +146,107 @@ public class EhCacheBasedAclCacheTests {
|
|||||||
File file = File.createTempFile("SEC_TEST", ".object");
|
File file = File.createTempFile("SEC_TEST", ".object");
|
||||||
FileOutputStream fos = new FileOutputStream(file);
|
FileOutputStream fos = new FileOutputStream(file);
|
||||||
ObjectOutputStream oos = new ObjectOutputStream(fos);
|
ObjectOutputStream oos = new ObjectOutputStream(fos);
|
||||||
oos.writeObject(acl);
|
oos.writeObject(this.acl);
|
||||||
oos.close();
|
oos.close();
|
||||||
|
|
||||||
FileInputStream fis = new FileInputStream(file);
|
FileInputStream fis = new FileInputStream(file);
|
||||||
ObjectInputStream ois = new ObjectInputStream(fis);
|
ObjectInputStream ois = new ObjectInputStream(fis);
|
||||||
MutableAcl retrieved = (MutableAcl) ois.readObject();
|
MutableAcl retrieved = (MutableAcl) ois.readObject();
|
||||||
ois.close();
|
ois.close();
|
||||||
|
assertThat(retrieved).isEqualTo(this.acl);
|
||||||
assertThat(retrieved).isEqualTo(acl);
|
Object retrieved1 = FieldUtils.getProtectedFieldValue("aclAuthorizationStrategy", retrieved);
|
||||||
|
|
||||||
Object retrieved1 = FieldUtils.getProtectedFieldValue("aclAuthorizationStrategy",
|
|
||||||
retrieved);
|
|
||||||
assertThat(retrieved1).isNull();
|
assertThat(retrieved1).isNull();
|
||||||
|
Object retrieved2 = FieldUtils.getProtectedFieldValue("permissionGrantingStrategy", retrieved);
|
||||||
Object retrieved2 = FieldUtils.getProtectedFieldValue(
|
|
||||||
"permissionGrantingStrategy", retrieved);
|
|
||||||
assertThat(retrieved2).isNull();
|
assertThat(retrieved2).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void clearCache() {
|
public void clearCache() {
|
||||||
myCache.clearCache();
|
this.myCache.clearCache();
|
||||||
|
verify(this.cache).removeAll();
|
||||||
verify(cache).removeAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void putInCache() {
|
public void putInCache() {
|
||||||
myCache.putInCache(acl);
|
this.myCache.putInCache(this.acl);
|
||||||
|
verify(this.cache, times(2)).put(this.element.capture());
|
||||||
verify(cache, times(2)).put(element.capture());
|
assertThat(this.element.getValue().getKey()).isEqualTo(this.acl.getId());
|
||||||
assertThat(element.getValue().getKey()).isEqualTo(acl.getId());
|
assertThat(this.element.getValue().getObjectValue()).isEqualTo(this.acl);
|
||||||
assertThat(element.getValue().getObjectValue()).isEqualTo(acl);
|
assertThat(this.element.getAllValues().get(0).getKey()).isEqualTo(this.acl.getObjectIdentity());
|
||||||
assertThat(element.getAllValues().get(0).getKey()).isEqualTo(
|
assertThat(this.element.getAllValues().get(0).getObjectValue()).isEqualTo(this.acl);
|
||||||
acl.getObjectIdentity());
|
|
||||||
assertThat(element.getAllValues().get(0).getObjectValue()).isEqualTo(acl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void putInCacheAclWithParent() {
|
public void putInCacheAclWithParent() {
|
||||||
Authentication auth = new TestingAuthenticationToken("user", "password",
|
Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL");
|
||||||
"ROLE_GENERAL");
|
|
||||||
auth.setAuthenticated(true);
|
auth.setAuthenticated(true);
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
|
ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS, 2L);
|
||||||
ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS,
|
|
||||||
2L);
|
|
||||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority(
|
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||||
"ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL"));
|
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||||
MutableAcl parentAcl = new AclImpl(identityParent, 2L,
|
MutableAcl parentAcl = new AclImpl(identityParent, 2L, aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||||
aclAuthorizationStrategy, new ConsoleAuditLogger());
|
this.acl.setParent(parentAcl);
|
||||||
acl.setParent(parentAcl);
|
this.myCache.putInCache(this.acl);
|
||||||
|
verify(this.cache, times(4)).put(this.element.capture());
|
||||||
myCache.putInCache(acl);
|
List<Element> allValues = this.element.getAllValues();
|
||||||
|
|
||||||
verify(cache, times(4)).put(element.capture());
|
|
||||||
|
|
||||||
List<Element> allValues = element.getAllValues();
|
|
||||||
|
|
||||||
assertThat(allValues.get(0).getKey()).isEqualTo(parentAcl.getObjectIdentity());
|
assertThat(allValues.get(0).getKey()).isEqualTo(parentAcl.getObjectIdentity());
|
||||||
assertThat(allValues.get(0).getObjectValue()).isEqualTo(parentAcl);
|
assertThat(allValues.get(0).getObjectValue()).isEqualTo(parentAcl);
|
||||||
|
|
||||||
assertThat(allValues.get(1).getKey()).isEqualTo(parentAcl.getId());
|
assertThat(allValues.get(1).getKey()).isEqualTo(parentAcl.getId());
|
||||||
assertThat(allValues.get(1).getObjectValue()).isEqualTo(parentAcl);
|
assertThat(allValues.get(1).getObjectValue()).isEqualTo(parentAcl);
|
||||||
|
assertThat(allValues.get(2).getKey()).isEqualTo(this.acl.getObjectIdentity());
|
||||||
assertThat(allValues.get(2).getKey()).isEqualTo(acl.getObjectIdentity());
|
assertThat(allValues.get(2).getObjectValue()).isEqualTo(this.acl);
|
||||||
assertThat(allValues.get(2).getObjectValue()).isEqualTo(acl);
|
assertThat(allValues.get(3).getKey()).isEqualTo(this.acl.getId());
|
||||||
|
assertThat(allValues.get(3).getObjectValue()).isEqualTo(this.acl);
|
||||||
assertThat(allValues.get(3).getKey()).isEqualTo(acl.getId());
|
|
||||||
assertThat(allValues.get(3).getObjectValue()).isEqualTo(acl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getFromCacheSerializable() {
|
public void getFromCacheSerializable() {
|
||||||
when(cache.get(acl.getId())).thenReturn(new Element(acl.getId(), acl));
|
given(this.cache.get(this.acl.getId())).willReturn(new Element(this.acl.getId(), this.acl));
|
||||||
|
assertThat(this.myCache.getFromCache(this.acl.getId())).isEqualTo(this.acl);
|
||||||
assertThat(myCache.getFromCache(acl.getId())).isEqualTo(acl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getFromCacheSerializablePopulatesTransient() {
|
public void getFromCacheSerializablePopulatesTransient() {
|
||||||
when(cache.get(acl.getId())).thenReturn(new Element(acl.getId(), acl));
|
given(this.cache.get(this.acl.getId())).willReturn(new Element(this.acl.getId(), this.acl));
|
||||||
|
this.myCache.putInCache(this.acl);
|
||||||
myCache.putInCache(acl);
|
ReflectionTestUtils.setField(this.acl, "permissionGrantingStrategy", null);
|
||||||
|
ReflectionTestUtils.setField(this.acl, "aclAuthorizationStrategy", null);
|
||||||
ReflectionTestUtils.setField(acl, "permissionGrantingStrategy", null);
|
MutableAcl fromCache = this.myCache.getFromCache(this.acl.getId());
|
||||||
ReflectionTestUtils.setField(acl, "aclAuthorizationStrategy", null);
|
assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy")).isNotNull();
|
||||||
|
assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy")).isNotNull();
|
||||||
MutableAcl fromCache = myCache.getFromCache(acl.getId());
|
|
||||||
|
|
||||||
assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy"))
|
|
||||||
.isNotNull();
|
|
||||||
assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy"))
|
|
||||||
.isNotNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getFromCacheObjectIdentity() {
|
public void getFromCacheObjectIdentity() {
|
||||||
when(cache.get(acl.getId())).thenReturn(new Element(acl.getId(), acl));
|
given(this.cache.get(this.acl.getId())).willReturn(new Element(this.acl.getId(), this.acl));
|
||||||
|
assertThat(this.myCache.getFromCache(this.acl.getId())).isEqualTo(this.acl);
|
||||||
assertThat(myCache.getFromCache(acl.getId())).isEqualTo(acl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getFromCacheObjectIdentityPopulatesTransient() {
|
public void getFromCacheObjectIdentityPopulatesTransient() {
|
||||||
when(cache.get(acl.getObjectIdentity()))
|
given(this.cache.get(this.acl.getObjectIdentity())).willReturn(new Element(this.acl.getId(), this.acl));
|
||||||
.thenReturn(new Element(acl.getId(), acl));
|
this.myCache.putInCache(this.acl);
|
||||||
|
ReflectionTestUtils.setField(this.acl, "permissionGrantingStrategy", null);
|
||||||
myCache.putInCache(acl);
|
ReflectionTestUtils.setField(this.acl, "aclAuthorizationStrategy", null);
|
||||||
|
MutableAcl fromCache = this.myCache.getFromCache(this.acl.getObjectIdentity());
|
||||||
ReflectionTestUtils.setField(acl, "permissionGrantingStrategy", null);
|
assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy")).isNotNull();
|
||||||
ReflectionTestUtils.setField(acl, "aclAuthorizationStrategy", null);
|
assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy")).isNotNull();
|
||||||
|
|
||||||
MutableAcl fromCache = myCache.getFromCache(acl.getObjectIdentity());
|
|
||||||
|
|
||||||
assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy"))
|
|
||||||
.isNotNull();
|
|
||||||
assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy"))
|
|
||||||
.isNotNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void evictCacheSerializable() {
|
public void evictCacheSerializable() {
|
||||||
when(cache.get(acl.getObjectIdentity()))
|
given(this.cache.get(this.acl.getObjectIdentity())).willReturn(new Element(this.acl.getId(), this.acl));
|
||||||
.thenReturn(new Element(acl.getId(), acl));
|
this.myCache.evictFromCache(this.acl.getObjectIdentity());
|
||||||
|
verify(this.cache).remove(this.acl.getId());
|
||||||
myCache.evictFromCache(acl.getObjectIdentity());
|
verify(this.cache).remove(this.acl.getObjectIdentity());
|
||||||
|
|
||||||
verify(cache).remove(acl.getId());
|
|
||||||
verify(cache).remove(acl.getObjectIdentity());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void evictCacheObjectIdentity() {
|
public void evictCacheObjectIdentity() {
|
||||||
when(cache.get(acl.getId())).thenReturn(new Element(acl.getId(), acl));
|
given(this.cache.get(this.acl.getId())).willReturn(new Element(this.acl.getId(), this.acl));
|
||||||
|
this.myCache.evictFromCache(this.acl.getId());
|
||||||
myCache.evictFromCache(acl.getId());
|
verify(this.cache).remove(this.acl.getId());
|
||||||
|
verify(this.cache).remove(this.acl.getObjectIdentity());
|
||||||
verify(cache).remove(acl.getId());
|
|
||||||
verify(cache).remove(acl.getObjectIdentity());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,14 +13,25 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.jdbc;
|
package org.springframework.security.acls.jdbc;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
import org.springframework.jdbc.core.JdbcOperations;
|
import org.springframework.jdbc.core.JdbcOperations;
|
||||||
import org.springframework.jdbc.core.RowMapper;
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
|
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
|
||||||
@@ -32,17 +43,15 @@ import org.springframework.security.acls.model.NotFoundException;
|
|||||||
import org.springframework.security.acls.model.ObjectIdentity;
|
import org.springframework.security.acls.model.ObjectIdentity;
|
||||||
import org.springframework.security.acls.model.Sid;
|
import org.springframework.security.acls.model.Sid;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.mockito.AdditionalMatchers.aryEq;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.*;
|
import static org.mockito.ArgumentMatchers.anyList;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit and Integration tests the ACL JdbcAclService using an
|
* Unit and Integration tests the ACL JdbcAclService using an in-memory database.
|
||||||
* in-memory database.
|
|
||||||
*
|
*
|
||||||
* @author Nena Raab
|
* @author Nena Raab
|
||||||
*/
|
*/
|
||||||
@@ -61,51 +70,48 @@ public class JdbcAclServiceTests {
|
|||||||
JdbcOperations jdbcOperations;
|
JdbcOperations jdbcOperations;
|
||||||
|
|
||||||
private JdbcAclService aclServiceIntegration;
|
private JdbcAclService aclServiceIntegration;
|
||||||
|
|
||||||
private JdbcAclService aclService;
|
private JdbcAclService aclService;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
aclService = new JdbcAclService(jdbcOperations, lookupStrategy);
|
this.aclService = new JdbcAclService(this.jdbcOperations, this.lookupStrategy);
|
||||||
aclServiceIntegration = new JdbcAclService(embeddedDatabase, lookupStrategy);
|
this.aclServiceIntegration = new JdbcAclService(this.embeddedDatabase, this.lookupStrategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUpEmbeddedDatabase() {
|
public void setUpEmbeddedDatabase() {
|
||||||
embeddedDatabase = new EmbeddedDatabaseBuilder()//
|
// @formatter:off
|
||||||
.addScript("createAclSchemaWithAclClassIdType.sql")
|
this.embeddedDatabase = new EmbeddedDatabaseBuilder()
|
||||||
.addScript("db/sql/test_data_hierarchy.sql")
|
.addScript("createAclSchemaWithAclClassIdType.sql")
|
||||||
.build();
|
.addScript("db/sql/test_data_hierarchy.sql")
|
||||||
|
.build();
|
||||||
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDownEmbeddedDatabase() {
|
public void tearDownEmbeddedDatabase() {
|
||||||
embeddedDatabase.shutdown();
|
this.embeddedDatabase.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
// SEC-1898
|
// SEC-1898
|
||||||
@Test(expected = NotFoundException.class)
|
@Test(expected = NotFoundException.class)
|
||||||
public void readAclByIdMissingAcl() {
|
public void readAclByIdMissingAcl() {
|
||||||
Map<ObjectIdentity, Acl> result = new HashMap<>();
|
Map<ObjectIdentity, Acl> result = new HashMap<>();
|
||||||
when(
|
given(this.lookupStrategy.readAclsById(anyList(), anyList())).willReturn(result);
|
||||||
lookupStrategy.readAclsById(anyList(),
|
|
||||||
anyList())).thenReturn(result);
|
|
||||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(Object.class, 1);
|
ObjectIdentity objectIdentity = new ObjectIdentityImpl(Object.class, 1);
|
||||||
List<Sid> sids = Arrays.<Sid>asList(new PrincipalSid("user"));
|
List<Sid> sids = Arrays.<Sid>asList(new PrincipalSid("user"));
|
||||||
|
this.aclService.readAclById(objectIdentity, sids);
|
||||||
aclService.readAclById(objectIdentity, sids);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void findOneChildren() {
|
public void findOneChildren() {
|
||||||
List<ObjectIdentity> result = new ArrayList<>();
|
List<ObjectIdentity> result = new ArrayList<>();
|
||||||
result.add(new ObjectIdentityImpl(Object.class, "5577"));
|
result.add(new ObjectIdentityImpl(Object.class, "5577"));
|
||||||
Object[] args = {"1", "org.springframework.security.acls.jdbc.JdbcAclServiceTests$MockLongIdDomainObject"};
|
Object[] args = { "1", "org.springframework.security.acls.jdbc.JdbcAclServiceTests$MockLongIdDomainObject" };
|
||||||
when(
|
given(this.jdbcOperations.query(anyString(), eq(args), any(RowMapper.class))).willReturn(result);
|
||||||
jdbcOperations.query(anyString(),
|
|
||||||
aryEq(args), any(RowMapper.class))).thenReturn(result);
|
|
||||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 1L);
|
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 1L);
|
||||||
|
List<ObjectIdentity> objectIdentities = this.aclService.findChildren(objectIdentity);
|
||||||
List<ObjectIdentity> objectIdentities = aclService.findChildren(objectIdentity);
|
|
||||||
assertThat(objectIdentities.size()).isEqualTo(1);
|
assertThat(objectIdentities.size()).isEqualTo(1);
|
||||||
assertThat(objectIdentities.get(0).getIdentifier()).isEqualTo("5577");
|
assertThat(objectIdentities.get(0).getIdentifier()).isEqualTo("5577");
|
||||||
}
|
}
|
||||||
@@ -113,19 +119,14 @@ public class JdbcAclServiceTests {
|
|||||||
@Test
|
@Test
|
||||||
public void findNoChildren() {
|
public void findNoChildren() {
|
||||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 1L);
|
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 1L);
|
||||||
|
List<ObjectIdentity> objectIdentities = this.aclService.findChildren(objectIdentity);
|
||||||
List<ObjectIdentity> objectIdentities = aclService.findChildren(objectIdentity);
|
|
||||||
assertThat(objectIdentities).isNull();
|
assertThat(objectIdentities).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Some integration tests
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void findChildrenWithoutIdType() {
|
public void findChildrenWithoutIdType() {
|
||||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 4711L);
|
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 4711L);
|
||||||
|
List<ObjectIdentity> objectIdentities = this.aclServiceIntegration.findChildren(objectIdentity);
|
||||||
List<ObjectIdentity> objectIdentities = aclServiceIntegration.findChildren(objectIdentity);
|
|
||||||
assertThat(objectIdentities.size()).isEqualTo(1);
|
assertThat(objectIdentities.size()).isEqualTo(1);
|
||||||
assertThat(objectIdentities.get(0).getType()).isEqualTo(MockUntypedIdDomainObject.class.getName());
|
assertThat(objectIdentities.get(0).getType()).isEqualTo(MockUntypedIdDomainObject.class.getName());
|
||||||
assertThat(objectIdentities.get(0).getIdentifier()).isEqualTo(5000L);
|
assertThat(objectIdentities.get(0).getIdentifier()).isEqualTo(5000L);
|
||||||
@@ -134,16 +135,14 @@ public class JdbcAclServiceTests {
|
|||||||
@Test
|
@Test
|
||||||
public void findChildrenForUnknownObject() {
|
public void findChildrenForUnknownObject() {
|
||||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(Object.class, 33);
|
ObjectIdentity objectIdentity = new ObjectIdentityImpl(Object.class, 33);
|
||||||
|
List<ObjectIdentity> objectIdentities = this.aclServiceIntegration.findChildren(objectIdentity);
|
||||||
List<ObjectIdentity> objectIdentities = aclServiceIntegration.findChildren(objectIdentity);
|
|
||||||
assertThat(objectIdentities).isNull();
|
assertThat(objectIdentities).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void findChildrenOfIdTypeLong() {
|
public void findChildrenOfIdTypeLong() {
|
||||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl("location", "US-PAL");
|
ObjectIdentity objectIdentity = new ObjectIdentityImpl("location", "US-PAL");
|
||||||
|
List<ObjectIdentity> objectIdentities = this.aclServiceIntegration.findChildren(objectIdentity);
|
||||||
List<ObjectIdentity> objectIdentities = aclServiceIntegration.findChildren(objectIdentity);
|
|
||||||
assertThat(objectIdentities.size()).isEqualTo(2);
|
assertThat(objectIdentities.size()).isEqualTo(2);
|
||||||
assertThat(objectIdentities.get(0).getType()).isEqualTo(MockLongIdDomainObject.class.getName());
|
assertThat(objectIdentities.get(0).getType()).isEqualTo(MockLongIdDomainObject.class.getName());
|
||||||
assertThat(objectIdentities.get(0).getIdentifier()).isEqualTo(4711L);
|
assertThat(objectIdentities.get(0).getIdentifier()).isEqualTo(4711L);
|
||||||
@@ -154,9 +153,8 @@ public class JdbcAclServiceTests {
|
|||||||
@Test
|
@Test
|
||||||
public void findChildrenOfIdTypeString() {
|
public void findChildrenOfIdTypeString() {
|
||||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl("location", "US");
|
ObjectIdentity objectIdentity = new ObjectIdentityImpl("location", "US");
|
||||||
|
this.aclServiceIntegration.setAclClassIdSupported(true);
|
||||||
aclServiceIntegration.setAclClassIdSupported(true);
|
List<ObjectIdentity> objectIdentities = this.aclServiceIntegration.findChildren(objectIdentity);
|
||||||
List<ObjectIdentity> objectIdentities = aclServiceIntegration.findChildren(objectIdentity);
|
|
||||||
assertThat(objectIdentities.size()).isEqualTo(1);
|
assertThat(objectIdentities.size()).isEqualTo(1);
|
||||||
assertThat(objectIdentities.get(0).getType()).isEqualTo("location");
|
assertThat(objectIdentities.get(0).getType()).isEqualTo("location");
|
||||||
assertThat(objectIdentities.get(0).getIdentifier()).isEqualTo("US-PAL");
|
assertThat(objectIdentities.get(0).getIdentifier()).isEqualTo("US-PAL");
|
||||||
@@ -165,35 +163,40 @@ public class JdbcAclServiceTests {
|
|||||||
@Test
|
@Test
|
||||||
public void findChildrenOfIdTypeUUID() {
|
public void findChildrenOfIdTypeUUID() {
|
||||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockUntypedIdDomainObject.class, 5000L);
|
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockUntypedIdDomainObject.class, 5000L);
|
||||||
|
this.aclServiceIntegration.setAclClassIdSupported(true);
|
||||||
aclServiceIntegration.setAclClassIdSupported(true);
|
List<ObjectIdentity> objectIdentities = this.aclServiceIntegration.findChildren(objectIdentity);
|
||||||
List<ObjectIdentity> objectIdentities = aclServiceIntegration.findChildren(objectIdentity);
|
|
||||||
assertThat(objectIdentities.size()).isEqualTo(1);
|
assertThat(objectIdentities.size()).isEqualTo(1);
|
||||||
assertThat(objectIdentities.get(0).getType()).isEqualTo("costcenter");
|
assertThat(objectIdentities.get(0).getType()).isEqualTo("costcenter");
|
||||||
assertThat(objectIdentities.get(0).getIdentifier()).isEqualTo(UUID.fromString("25d93b3f-c3aa-4814-9d5e-c7c96ced7762"));
|
assertThat(objectIdentities.get(0).getIdentifier())
|
||||||
|
.isEqualTo(UUID.fromString("25d93b3f-c3aa-4814-9d5e-c7c96ced7762"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MockLongIdDomainObject {
|
class MockLongIdDomainObject {
|
||||||
|
|
||||||
private Object id;
|
private Object id;
|
||||||
|
|
||||||
public Object getId() {
|
Object getId() {
|
||||||
return id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(Object id) {
|
void setId(Object id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MockUntypedIdDomainObject {
|
class MockUntypedIdDomainObject {
|
||||||
|
|
||||||
private Object id;
|
private Object id;
|
||||||
|
|
||||||
public Object getId() {
|
Object getId() {
|
||||||
return id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(Object id) {
|
void setId(Object id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+137
-218
@@ -13,10 +13,8 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.acls.jdbc;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
package org.springframework.security.acls.jdbc;
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -25,6 +23,7 @@ import java.util.Map;
|
|||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
@@ -55,6 +54,11 @@ import org.springframework.test.context.transaction.AfterTransaction;
|
|||||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.fail;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration tests the ACL system using an in-memory database.
|
* Integration tests the ACL system using an in-memory database.
|
||||||
*
|
*
|
||||||
@@ -62,56 +66,49 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
* @author Andrei Stefan
|
* @author Andrei Stefan
|
||||||
*/
|
*/
|
||||||
@ContextConfiguration(locations = { "/jdbcMutableAclServiceTests-context.xml" })
|
@ContextConfiguration(locations = { "/jdbcMutableAclServiceTests-context.xml" })
|
||||||
public class JdbcMutableAclServiceTests extends
|
public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4SpringContextTests {
|
||||||
AbstractTransactionalJUnit4SpringContextTests {
|
|
||||||
// ~ Constant fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
private static final String TARGET_CLASS = TargetObject.class.getName();
|
private static final String TARGET_CLASS = TargetObject.class.getName();
|
||||||
|
|
||||||
private final Authentication auth = new TestingAuthenticationToken("ben", "ignored",
|
private final Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_ADMINISTRATOR");
|
||||||
"ROLE_ADMINISTRATOR");
|
|
||||||
|
|
||||||
public static final String SELECT_ALL_CLASSES = "SELECT * FROM acl_class WHERE class = ?";
|
public static final String SELECT_ALL_CLASSES = "SELECT * FROM acl_class WHERE class = ?";
|
||||||
|
|
||||||
// ~ Instance fields
|
private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS,
|
private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, 101L);
|
||||||
100L);
|
|
||||||
private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS,
|
private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 102L);
|
||||||
101L);
|
|
||||||
private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS,
|
|
||||||
102L);
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private JdbcMutableAclService jdbcMutableAclService;
|
private JdbcMutableAclService jdbcMutableAclService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AclCache aclCache;
|
private AclCache aclCache;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private LookupStrategy lookupStrategy;
|
private LookupStrategy lookupStrategy;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private JdbcTemplate jdbcTemplate;
|
private JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
protected String getSqlClassPathResource() {
|
protected String getSqlClassPathResource() {
|
||||||
return "createAclSchema.sql";
|
return "createAclSchema.sql";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ObjectIdentity getTopParentOid() {
|
protected ObjectIdentity getTopParentOid() {
|
||||||
return topParentOid;
|
return this.topParentOid;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ObjectIdentity getMiddleParentOid() {
|
protected ObjectIdentity getMiddleParentOid() {
|
||||||
return middleParentOid;
|
return this.middleParentOid;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ObjectIdentity getChildOid() {
|
protected ObjectIdentity getChildOid() {
|
||||||
return childOid;
|
return this.childOid;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getTargetClass() {
|
protected String getTargetClass() {
|
||||||
@@ -121,162 +118,134 @@ public class JdbcMutableAclServiceTests extends
|
|||||||
@BeforeTransaction
|
@BeforeTransaction
|
||||||
public void createTables() throws Exception {
|
public void createTables() throws Exception {
|
||||||
try {
|
try {
|
||||||
new DatabaseSeeder(dataSource, new ClassPathResource(getSqlClassPathResource()));
|
new DatabaseSeeder(this.dataSource, new ClassPathResource(getSqlClassPathResource()));
|
||||||
// new DatabaseSeeder(dataSource, new
|
// new DatabaseSeeder(dataSource, new
|
||||||
// ClassPathResource("createAclSchemaPostgres.sql"));
|
// ClassPathResource("createAclSchemaPostgres.sql"));
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
e.printStackTrace();
|
ex.printStackTrace();
|
||||||
throw e;
|
throw ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterTransaction
|
@AfterTransaction
|
||||||
public void clearContextAndData() {
|
public void clearContextAndData() {
|
||||||
SecurityContextHolder.clearContext();
|
SecurityContextHolder.clearContext();
|
||||||
jdbcTemplate.execute("drop table acl_entry");
|
this.jdbcTemplate.execute("drop table acl_entry");
|
||||||
jdbcTemplate.execute("drop table acl_object_identity");
|
this.jdbcTemplate.execute("drop table acl_object_identity");
|
||||||
jdbcTemplate.execute("drop table acl_class");
|
this.jdbcTemplate.execute("drop table acl_class");
|
||||||
jdbcTemplate.execute("drop table acl_sid");
|
this.jdbcTemplate.execute("drop table acl_sid");
|
||||||
aclCache.clearCache();
|
this.aclCache.clearCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Transactional
|
@Transactional
|
||||||
public void testLifecycle() {
|
public void testLifecycle() {
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(this.auth);
|
||||||
|
MutableAcl topParent = this.jdbcMutableAclService.createAcl(getTopParentOid());
|
||||||
MutableAcl topParent = jdbcMutableAclService.createAcl(getTopParentOid());
|
MutableAcl middleParent = this.jdbcMutableAclService.createAcl(getMiddleParentOid());
|
||||||
MutableAcl middleParent = jdbcMutableAclService.createAcl(getMiddleParentOid());
|
MutableAcl child = this.jdbcMutableAclService.createAcl(getChildOid());
|
||||||
MutableAcl child = jdbcMutableAclService.createAcl(getChildOid());
|
|
||||||
|
|
||||||
// Specify the inheritance hierarchy
|
// Specify the inheritance hierarchy
|
||||||
middleParent.setParent(topParent);
|
middleParent.setParent(topParent);
|
||||||
child.setParent(middleParent);
|
child.setParent(middleParent);
|
||||||
|
|
||||||
// Now let's add a couple of permissions
|
// Now let's add a couple of permissions
|
||||||
topParent.insertAce(0, BasePermission.READ, new PrincipalSid(auth), true);
|
topParent.insertAce(0, BasePermission.READ, new PrincipalSid(this.auth), true);
|
||||||
topParent.insertAce(1, BasePermission.WRITE, new PrincipalSid(auth), false);
|
topParent.insertAce(1, BasePermission.WRITE, new PrincipalSid(this.auth), false);
|
||||||
middleParent.insertAce(0, BasePermission.DELETE, new PrincipalSid(auth), true);
|
middleParent.insertAce(0, BasePermission.DELETE, new PrincipalSid(this.auth), true);
|
||||||
child.insertAce(0, BasePermission.DELETE, new PrincipalSid(auth), false);
|
child.insertAce(0, BasePermission.DELETE, new PrincipalSid(this.auth), false);
|
||||||
|
|
||||||
// Explicitly save the changed ACL
|
// Explicitly save the changed ACL
|
||||||
jdbcMutableAclService.updateAcl(topParent);
|
this.jdbcMutableAclService.updateAcl(topParent);
|
||||||
jdbcMutableAclService.updateAcl(middleParent);
|
this.jdbcMutableAclService.updateAcl(middleParent);
|
||||||
jdbcMutableAclService.updateAcl(child);
|
this.jdbcMutableAclService.updateAcl(child);
|
||||||
|
|
||||||
// Let's check if we can read them back correctly
|
// Let's check if we can read them back correctly
|
||||||
Map<ObjectIdentity, Acl> map = jdbcMutableAclService.readAclsById(Arrays.asList(
|
Map<ObjectIdentity, Acl> map = this.jdbcMutableAclService
|
||||||
getTopParentOid(), getMiddleParentOid(), getChildOid()));
|
.readAclsById(Arrays.asList(getTopParentOid(), getMiddleParentOid(), getChildOid()));
|
||||||
assertThat(map).hasSize(3);
|
assertThat(map).hasSize(3);
|
||||||
|
|
||||||
// Replace our current objects with their retrieved versions
|
// Replace our current objects with their retrieved versions
|
||||||
topParent = (MutableAcl) map.get(getTopParentOid());
|
topParent = (MutableAcl) map.get(getTopParentOid());
|
||||||
middleParent = (MutableAcl) map.get(getMiddleParentOid());
|
middleParent = (MutableAcl) map.get(getMiddleParentOid());
|
||||||
child = (MutableAcl) map.get(getChildOid());
|
child = (MutableAcl) map.get(getChildOid());
|
||||||
|
|
||||||
// Check the retrieved versions has IDs
|
// Check the retrieved versions has IDs
|
||||||
assertThat(topParent.getId()).isNotNull();
|
assertThat(topParent.getId()).isNotNull();
|
||||||
assertThat(middleParent.getId()).isNotNull();
|
assertThat(middleParent.getId()).isNotNull();
|
||||||
assertThat(child.getId()).isNotNull();
|
assertThat(child.getId()).isNotNull();
|
||||||
|
|
||||||
// Check their parents were correctly persisted
|
// Check their parents were correctly persisted
|
||||||
assertThat(topParent.getParentAcl()).isNull();
|
assertThat(topParent.getParentAcl()).isNull();
|
||||||
assertThat(middleParent.getParentAcl().getObjectIdentity()).isEqualTo(getTopParentOid());
|
assertThat(middleParent.getParentAcl().getObjectIdentity()).isEqualTo(getTopParentOid());
|
||||||
assertThat(child.getParentAcl().getObjectIdentity()).isEqualTo(getMiddleParentOid());
|
assertThat(child.getParentAcl().getObjectIdentity()).isEqualTo(getMiddleParentOid());
|
||||||
|
|
||||||
// Check their ACEs were correctly persisted
|
// Check their ACEs were correctly persisted
|
||||||
assertThat(topParent.getEntries()).hasSize(2);
|
assertThat(topParent.getEntries()).hasSize(2);
|
||||||
assertThat(middleParent.getEntries()).hasSize(1);
|
assertThat(middleParent.getEntries()).hasSize(1);
|
||||||
assertThat(child.getEntries()).hasSize(1);
|
assertThat(child.getEntries()).hasSize(1);
|
||||||
|
|
||||||
// Check the retrieved rights are correct
|
// Check the retrieved rights are correct
|
||||||
List<Permission> read = Arrays.asList(BasePermission.READ);
|
List<Permission> read = Arrays.asList(BasePermission.READ);
|
||||||
List<Permission> write = Arrays.asList(BasePermission.WRITE);
|
List<Permission> write = Arrays.asList(BasePermission.WRITE);
|
||||||
List<Permission> delete = Arrays.asList(BasePermission.DELETE);
|
List<Permission> delete = Arrays.asList(BasePermission.DELETE);
|
||||||
List<Sid> pSid = Arrays.asList((Sid) new PrincipalSid(auth));
|
List<Sid> pSid = Arrays.asList((Sid) new PrincipalSid(this.auth));
|
||||||
|
|
||||||
assertThat(topParent.isGranted(read, pSid, false)).isTrue();
|
assertThat(topParent.isGranted(read, pSid, false)).isTrue();
|
||||||
assertThat(topParent.isGranted(write, pSid, false)).isFalse();
|
assertThat(topParent.isGranted(write, pSid, false)).isFalse();
|
||||||
assertThat(middleParent.isGranted(delete, pSid, false)).isTrue();
|
assertThat(middleParent.isGranted(delete, pSid, false)).isTrue();
|
||||||
assertThat(child.isGranted(delete, pSid, false)).isFalse();
|
assertThat(child.isGranted(delete, pSid, false)).isFalse();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
child.isGranted(Arrays.asList(BasePermission.ADMINISTRATION), pSid, false);
|
child.isGranted(Arrays.asList(BasePermission.ADMINISTRATION), pSid, false);
|
||||||
fail("Should have thrown NotFoundException");
|
fail("Should have thrown NotFoundException");
|
||||||
}
|
}
|
||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now check the inherited rights (when not explicitly overridden) also look OK
|
// Now check the inherited rights (when not explicitly overridden) also look OK
|
||||||
assertThat(child.isGranted(read, pSid, false)).isTrue();
|
assertThat(child.isGranted(read, pSid, false)).isTrue();
|
||||||
assertThat(child.isGranted(write, pSid, false)).isFalse();
|
assertThat(child.isGranted(write, pSid, false)).isFalse();
|
||||||
assertThat(child.isGranted(delete, pSid, false)).isFalse();
|
assertThat(child.isGranted(delete, pSid, false)).isFalse();
|
||||||
|
|
||||||
// Next change the child so it doesn't inherit permissions from above
|
// Next change the child so it doesn't inherit permissions from above
|
||||||
child.setEntriesInheriting(false);
|
child.setEntriesInheriting(false);
|
||||||
jdbcMutableAclService.updateAcl(child);
|
this.jdbcMutableAclService.updateAcl(child);
|
||||||
child = (MutableAcl) jdbcMutableAclService.readAclById(getChildOid());
|
child = (MutableAcl) this.jdbcMutableAclService.readAclById(getChildOid());
|
||||||
assertThat(child.isEntriesInheriting()).isFalse();
|
assertThat(child.isEntriesInheriting()).isFalse();
|
||||||
|
|
||||||
// Check the child permissions no longer inherit
|
// Check the child permissions no longer inherit
|
||||||
assertThat(child.isGranted(delete, pSid, true)).isFalse();
|
assertThat(child.isGranted(delete, pSid, true)).isFalse();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
child.isGranted(read, pSid, true);
|
child.isGranted(read, pSid, true);
|
||||||
fail("Should have thrown NotFoundException");
|
fail("Should have thrown NotFoundException");
|
||||||
}
|
}
|
||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
child.isGranted(write, pSid, true);
|
child.isGranted(write, pSid, true);
|
||||||
fail("Should have thrown NotFoundException");
|
fail("Should have thrown NotFoundException");
|
||||||
}
|
}
|
||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's add an identical permission to the child, but it'll appear AFTER the
|
// Let's add an identical permission to the child, but it'll appear AFTER the
|
||||||
// current permission, so has no impact
|
// current permission, so has no impact
|
||||||
child.insertAce(1, BasePermission.DELETE, new PrincipalSid(auth), true);
|
child.insertAce(1, BasePermission.DELETE, new PrincipalSid(this.auth), true);
|
||||||
|
|
||||||
// Let's also add another permission to the child
|
// Let's also add another permission to the child
|
||||||
child.insertAce(2, BasePermission.CREATE, new PrincipalSid(auth), true);
|
child.insertAce(2, BasePermission.CREATE, new PrincipalSid(this.auth), true);
|
||||||
|
|
||||||
// Save the changed child
|
// Save the changed child
|
||||||
jdbcMutableAclService.updateAcl(child);
|
this.jdbcMutableAclService.updateAcl(child);
|
||||||
child = (MutableAcl) jdbcMutableAclService.readAclById(getChildOid());
|
child = (MutableAcl) this.jdbcMutableAclService.readAclById(getChildOid());
|
||||||
assertThat(child.getEntries()).hasSize(3);
|
assertThat(child.getEntries()).hasSize(3);
|
||||||
|
|
||||||
// Output permissions
|
// Output permissions
|
||||||
for (int i = 0; i < child.getEntries().size(); i++) {
|
for (int i = 0; i < child.getEntries().size(); i++) {
|
||||||
System.out.println(child.getEntries().get(i));
|
System.out.println(child.getEntries().get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the permissions are as they should be
|
// Check the permissions are as they should be
|
||||||
assertThat(child.isGranted(delete, pSid, true)).isFalse(); // as earlier permission
|
assertThat(child.isGranted(delete, pSid, true)).isFalse(); // as earlier
|
||||||
// overrode
|
// permission
|
||||||
|
// overrode
|
||||||
assertThat(child.isGranted(Arrays.asList(BasePermission.CREATE), pSid, true)).isTrue();
|
assertThat(child.isGranted(Arrays.asList(BasePermission.CREATE), pSid, true)).isTrue();
|
||||||
|
|
||||||
// Now check the first ACE (index 0) really is DELETE for our Sid and is
|
// Now check the first ACE (index 0) really is DELETE for our Sid and is
|
||||||
// non-granting
|
// non-granting
|
||||||
AccessControlEntry entry = child.getEntries().get(0);
|
AccessControlEntry entry = child.getEntries().get(0);
|
||||||
assertThat(entry.getPermission().getMask()).isEqualTo(BasePermission.DELETE.getMask());
|
assertThat(entry.getPermission().getMask()).isEqualTo(BasePermission.DELETE.getMask());
|
||||||
assertThat(entry.getSid()).isEqualTo(new PrincipalSid(auth));
|
assertThat(entry.getSid()).isEqualTo(new PrincipalSid(this.auth));
|
||||||
assertThat(entry.isGranting()).isFalse();
|
assertThat(entry.isGranting()).isFalse();
|
||||||
assertThat(entry.getId()).isNotNull();
|
assertThat(entry.getId()).isNotNull();
|
||||||
|
|
||||||
// Now delete that first ACE
|
// Now delete that first ACE
|
||||||
child.deleteAce(0);
|
child.deleteAce(0);
|
||||||
|
|
||||||
// Save and check it worked
|
// Save and check it worked
|
||||||
child = jdbcMutableAclService.updateAcl(child);
|
child = this.jdbcMutableAclService.updateAcl(child);
|
||||||
assertThat(child.getEntries()).hasSize(2);
|
assertThat(child.getEntries()).hasSize(2);
|
||||||
assertThat(child.isGranted(delete, pSid, false)).isTrue();
|
assertThat(child.isGranted(delete, pSid, false)).isTrue();
|
||||||
|
|
||||||
SecurityContextHolder.clearContext();
|
SecurityContextHolder.clearContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,38 +255,31 @@ public class JdbcMutableAclServiceTests extends
|
|||||||
@Test
|
@Test
|
||||||
@Transactional
|
@Transactional
|
||||||
public void deleteAclAlsoDeletesChildren() {
|
public void deleteAclAlsoDeletesChildren() {
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(this.auth);
|
||||||
|
this.jdbcMutableAclService.createAcl(getTopParentOid());
|
||||||
jdbcMutableAclService.createAcl(getTopParentOid());
|
MutableAcl middleParent = this.jdbcMutableAclService.createAcl(getMiddleParentOid());
|
||||||
MutableAcl middleParent = jdbcMutableAclService.createAcl(getMiddleParentOid());
|
MutableAcl child = this.jdbcMutableAclService.createAcl(getChildOid());
|
||||||
MutableAcl child = jdbcMutableAclService.createAcl(getChildOid());
|
|
||||||
child.setParent(middleParent);
|
child.setParent(middleParent);
|
||||||
jdbcMutableAclService.updateAcl(middleParent);
|
this.jdbcMutableAclService.updateAcl(middleParent);
|
||||||
jdbcMutableAclService.updateAcl(child);
|
this.jdbcMutableAclService.updateAcl(child);
|
||||||
// Check the childOid really is a child of middleParentOid
|
// Check the childOid really is a child of middleParentOid
|
||||||
Acl childAcl = jdbcMutableAclService.readAclById(getChildOid());
|
Acl childAcl = this.jdbcMutableAclService.readAclById(getChildOid());
|
||||||
|
|
||||||
assertThat(childAcl.getParentAcl().getObjectIdentity()).isEqualTo(getMiddleParentOid());
|
assertThat(childAcl.getParentAcl().getObjectIdentity()).isEqualTo(getMiddleParentOid());
|
||||||
|
|
||||||
// Delete the mid-parent and test if the child was deleted, as well
|
// Delete the mid-parent and test if the child was deleted, as well
|
||||||
jdbcMutableAclService.deleteAcl(getMiddleParentOid(), true);
|
this.jdbcMutableAclService.deleteAcl(getMiddleParentOid(), true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
jdbcMutableAclService.readAclById(getMiddleParentOid());
|
this.jdbcMutableAclService.readAclById(getMiddleParentOid());
|
||||||
fail("It should have thrown NotFoundException");
|
fail("It should have thrown NotFoundException");
|
||||||
}
|
}
|
||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
jdbcMutableAclService.readAclById(getChildOid());
|
this.jdbcMutableAclService.readAclById(getChildOid());
|
||||||
fail("It should have thrown NotFoundException");
|
fail("It should have thrown NotFoundException");
|
||||||
}
|
}
|
||||||
catch (NotFoundException expected) {
|
catch (NotFoundException expected) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Acl acl = this.jdbcMutableAclService.readAclById(getTopParentOid());
|
||||||
Acl acl = jdbcMutableAclService.readAclById(getTopParentOid());
|
|
||||||
assertThat(acl).isNotNull();
|
assertThat(acl).isNotNull();
|
||||||
assertThat(getTopParentOid()).isEqualTo(acl.getObjectIdentity());
|
assertThat(getTopParentOid()).isEqualTo(acl.getObjectIdentity());
|
||||||
}
|
}
|
||||||
@@ -325,21 +287,19 @@ public class JdbcMutableAclServiceTests extends
|
|||||||
@Test
|
@Test
|
||||||
public void constructorRejectsNullParameters() {
|
public void constructorRejectsNullParameters() {
|
||||||
try {
|
try {
|
||||||
new JdbcMutableAclService(null, lookupStrategy, aclCache);
|
new JdbcMutableAclService(null, this.lookupStrategy, this.aclCache);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new JdbcMutableAclService(dataSource, null, aclCache);
|
new JdbcMutableAclService(this.dataSource, null, this.aclCache);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new JdbcMutableAclService(dataSource, lookupStrategy, null);
|
new JdbcMutableAclService(this.dataSource, this.lookupStrategy, null);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
@@ -349,7 +309,7 @@ public class JdbcMutableAclServiceTests extends
|
|||||||
@Test
|
@Test
|
||||||
public void createAclRejectsNullParameter() {
|
public void createAclRejectsNullParameter() {
|
||||||
try {
|
try {
|
||||||
jdbcMutableAclService.createAcl(null);
|
this.jdbcMutableAclService.createAcl(null);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
@@ -359,13 +319,12 @@ public class JdbcMutableAclServiceTests extends
|
|||||||
@Test
|
@Test
|
||||||
@Transactional
|
@Transactional
|
||||||
public void createAclForADuplicateDomainObject() {
|
public void createAclForADuplicateDomainObject() {
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(this.auth);
|
||||||
ObjectIdentity duplicateOid = new ObjectIdentityImpl(TARGET_CLASS,
|
ObjectIdentity duplicateOid = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
||||||
100L);
|
this.jdbcMutableAclService.createAcl(duplicateOid);
|
||||||
jdbcMutableAclService.createAcl(duplicateOid);
|
|
||||||
// Try to add the same object second time
|
// Try to add the same object second time
|
||||||
try {
|
try {
|
||||||
jdbcMutableAclService.createAcl(duplicateOid);
|
this.jdbcMutableAclService.createAcl(duplicateOid);
|
||||||
fail("It should have thrown AlreadyExistsException");
|
fail("It should have thrown AlreadyExistsException");
|
||||||
}
|
}
|
||||||
catch (AlreadyExistsException expected) {
|
catch (AlreadyExistsException expected) {
|
||||||
@@ -376,7 +335,7 @@ public class JdbcMutableAclServiceTests extends
|
|||||||
@Transactional
|
@Transactional
|
||||||
public void deleteAclRejectsNullParameters() {
|
public void deleteAclRejectsNullParameters() {
|
||||||
try {
|
try {
|
||||||
jdbcMutableAclService.deleteAcl(null, true);
|
this.jdbcMutableAclService.deleteAcl(null, true);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
@@ -386,61 +345,52 @@ public class JdbcMutableAclServiceTests extends
|
|||||||
@Test
|
@Test
|
||||||
@Transactional
|
@Transactional
|
||||||
public void deleteAclWithChildrenThrowsException() {
|
public void deleteAclWithChildrenThrowsException() {
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(this.auth);
|
||||||
MutableAcl parent = jdbcMutableAclService.createAcl(getTopParentOid());
|
MutableAcl parent = this.jdbcMutableAclService.createAcl(getTopParentOid());
|
||||||
MutableAcl child = jdbcMutableAclService.createAcl(getMiddleParentOid());
|
MutableAcl child = this.jdbcMutableAclService.createAcl(getMiddleParentOid());
|
||||||
|
|
||||||
// Specify the inheritance hierarchy
|
// Specify the inheritance hierarchy
|
||||||
child.setParent(parent);
|
child.setParent(parent);
|
||||||
jdbcMutableAclService.updateAcl(child);
|
this.jdbcMutableAclService.updateAcl(child);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
jdbcMutableAclService.setForeignKeysInDatabase(false); // switch on FK
|
this.jdbcMutableAclService.setForeignKeysInDatabase(false); // switch on FK
|
||||||
// checking in the
|
// checking in the
|
||||||
// class, not database
|
// class, not database
|
||||||
jdbcMutableAclService.deleteAcl(getTopParentOid(), false);
|
this.jdbcMutableAclService.deleteAcl(getTopParentOid(), false);
|
||||||
fail("It should have thrown ChildrenExistException");
|
fail("It should have thrown ChildrenExistException");
|
||||||
}
|
}
|
||||||
catch (ChildrenExistException expected) {
|
catch (ChildrenExistException expected) {
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
jdbcMutableAclService.setForeignKeysInDatabase(true); // restore to the
|
this.jdbcMutableAclService.setForeignKeysInDatabase(true); // restore to the
|
||||||
// default
|
// default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Transactional
|
@Transactional
|
||||||
public void deleteAclRemovesRowsFromDatabase() {
|
public void deleteAclRemovesRowsFromDatabase() {
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(this.auth);
|
||||||
MutableAcl child = jdbcMutableAclService.createAcl(getChildOid());
|
MutableAcl child = this.jdbcMutableAclService.createAcl(getChildOid());
|
||||||
child.insertAce(0, BasePermission.DELETE, new PrincipalSid(auth), false);
|
child.insertAce(0, BasePermission.DELETE, new PrincipalSid(this.auth), false);
|
||||||
jdbcMutableAclService.updateAcl(child);
|
this.jdbcMutableAclService.updateAcl(child);
|
||||||
|
|
||||||
// Remove the child and check all related database rows were removed accordingly
|
// Remove the child and check all related database rows were removed accordingly
|
||||||
jdbcMutableAclService.deleteAcl(getChildOid(), false);
|
this.jdbcMutableAclService.deleteAcl(getChildOid(), false);
|
||||||
assertThat(
|
assertThat(this.jdbcTemplate.queryForList(SELECT_ALL_CLASSES, new Object[] { getTargetClass() })).hasSize(1);
|
||||||
jdbcTemplate.queryForList(SELECT_ALL_CLASSES,
|
assertThat(this.jdbcTemplate.queryForList("select * from acl_object_identity")).isEmpty();
|
||||||
new Object[] { getTargetClass() })).hasSize(1);
|
assertThat(this.jdbcTemplate.queryForList("select * from acl_entry")).isEmpty();
|
||||||
assertThat(jdbcTemplate.queryForList("select * from acl_object_identity")
|
|
||||||
).isEmpty();
|
|
||||||
assertThat(jdbcTemplate.queryForList("select * from acl_entry")).isEmpty();
|
|
||||||
|
|
||||||
// Check the cache
|
// Check the cache
|
||||||
assertThat(aclCache.getFromCache(getChildOid())).isNull();
|
assertThat(this.aclCache.getFromCache(getChildOid())).isNull();
|
||||||
assertThat(aclCache.getFromCache(102L)).isNull();
|
assertThat(this.aclCache.getFromCache(102L)).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** SEC-1107 */
|
/** SEC-1107 */
|
||||||
@Test
|
@Test
|
||||||
@Transactional
|
@Transactional
|
||||||
public void identityWithIntegerIdIsSupportedByCreateAcl() {
|
public void identityWithIntegerIdIsSupportedByCreateAcl() {
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(this.auth);
|
||||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, 101);
|
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, 101);
|
||||||
jdbcMutableAclService.createAcl(oid);
|
this.jdbcMutableAclService.createAcl(oid);
|
||||||
|
assertThat(this.jdbcMutableAclService.readAclById(new ObjectIdentityImpl(TARGET_CLASS, 101L))).isNotNull();
|
||||||
assertThat(jdbcMutableAclService.readAclById(new ObjectIdentityImpl(
|
|
||||||
TARGET_CLASS, 101L))).isNotNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -449,32 +399,25 @@ public class JdbcMutableAclServiceTests extends
|
|||||||
@Test
|
@Test
|
||||||
@Transactional
|
@Transactional
|
||||||
public void childrenAreClearedFromCacheWhenParentIsUpdated() {
|
public void childrenAreClearedFromCacheWhenParentIsUpdated() {
|
||||||
Authentication auth = new TestingAuthenticationToken("ben", "ignored",
|
Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_ADMINISTRATOR");
|
||||||
"ROLE_ADMINISTRATOR");
|
|
||||||
auth.setAuthenticated(true);
|
auth.setAuthenticated(true);
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
|
|
||||||
ObjectIdentity parentOid = new ObjectIdentityImpl(TARGET_CLASS, 104L);
|
ObjectIdentity parentOid = new ObjectIdentityImpl(TARGET_CLASS, 104L);
|
||||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 105L);
|
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 105L);
|
||||||
|
MutableAcl parent = this.jdbcMutableAclService.createAcl(parentOid);
|
||||||
MutableAcl parent = jdbcMutableAclService.createAcl(parentOid);
|
MutableAcl child = this.jdbcMutableAclService.createAcl(childOid);
|
||||||
MutableAcl child = jdbcMutableAclService.createAcl(childOid);
|
|
||||||
|
|
||||||
child.setParent(parent);
|
child.setParent(parent);
|
||||||
jdbcMutableAclService.updateAcl(child);
|
this.jdbcMutableAclService.updateAcl(child);
|
||||||
|
parent = (AclImpl) this.jdbcMutableAclService.readAclById(parentOid);
|
||||||
parent = (AclImpl) jdbcMutableAclService.readAclById(parentOid);
|
|
||||||
parent.insertAce(0, BasePermission.READ, new PrincipalSid("ben"), true);
|
parent.insertAce(0, BasePermission.READ, new PrincipalSid("ben"), true);
|
||||||
jdbcMutableAclService.updateAcl(parent);
|
this.jdbcMutableAclService.updateAcl(parent);
|
||||||
|
parent = (AclImpl) this.jdbcMutableAclService.readAclById(parentOid);
|
||||||
parent = (AclImpl) jdbcMutableAclService.readAclById(parentOid);
|
|
||||||
parent.insertAce(1, BasePermission.READ, new PrincipalSid("scott"), true);
|
parent.insertAce(1, BasePermission.READ, new PrincipalSid("scott"), true);
|
||||||
jdbcMutableAclService.updateAcl(parent);
|
this.jdbcMutableAclService.updateAcl(parent);
|
||||||
|
child = (MutableAcl) this.jdbcMutableAclService.readAclById(childOid);
|
||||||
child = (MutableAcl) jdbcMutableAclService.readAclById(childOid);
|
|
||||||
parent = (MutableAcl) child.getParentAcl();
|
parent = (MutableAcl) child.getParentAcl();
|
||||||
|
assertThat(parent.getEntries()).hasSize(2)
|
||||||
assertThat(parent.getEntries()).hasSize(2).withFailMessage("Fails because child has a stale reference to its parent");
|
.withFailMessage("Fails because child has a stale reference to its parent");
|
||||||
assertThat(parent.getEntries().get(0).getPermission().getMask()).isEqualTo(1);
|
assertThat(parent.getEntries().get(0).getPermission().getMask()).isEqualTo(1);
|
||||||
assertThat(parent.getEntries().get(0).getSid()).isEqualTo(new PrincipalSid("ben"));
|
assertThat(parent.getEntries().get(0).getSid()).isEqualTo(new PrincipalSid("ben"));
|
||||||
assertThat(parent.getEntries().get(1).getPermission().getMask()).isEqualTo(1);
|
assertThat(parent.getEntries().get(1).getPermission().getMask()).isEqualTo(1);
|
||||||
@@ -487,34 +430,22 @@ public class JdbcMutableAclServiceTests extends
|
|||||||
@Test
|
@Test
|
||||||
@Transactional
|
@Transactional
|
||||||
public void childrenAreClearedFromCacheWhenParentisUpdated2() {
|
public void childrenAreClearedFromCacheWhenParentisUpdated2() {
|
||||||
Authentication auth = new TestingAuthenticationToken("system", "secret",
|
Authentication auth = new TestingAuthenticationToken("system", "secret", "ROLE_IGNORED");
|
||||||
"ROLE_IGNORED");
|
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
ObjectIdentityImpl rootObject = new ObjectIdentityImpl(TARGET_CLASS,
|
ObjectIdentityImpl rootObject = new ObjectIdentityImpl(TARGET_CLASS, 1L);
|
||||||
1L);
|
MutableAcl parent = this.jdbcMutableAclService.createAcl(rootObject);
|
||||||
|
MutableAcl child = this.jdbcMutableAclService.createAcl(new ObjectIdentityImpl(TARGET_CLASS, 2L));
|
||||||
MutableAcl parent = jdbcMutableAclService.createAcl(rootObject);
|
|
||||||
MutableAcl child = jdbcMutableAclService.createAcl(new ObjectIdentityImpl(
|
|
||||||
TARGET_CLASS, 2L));
|
|
||||||
child.setParent(parent);
|
child.setParent(parent);
|
||||||
jdbcMutableAclService.updateAcl(child);
|
this.jdbcMutableAclService.updateAcl(child);
|
||||||
|
parent.insertAce(0, BasePermission.ADMINISTRATION, new GrantedAuthoritySid("ROLE_ADMINISTRATOR"), true);
|
||||||
parent.insertAce(0, BasePermission.ADMINISTRATION, new GrantedAuthoritySid(
|
this.jdbcMutableAclService.updateAcl(parent);
|
||||||
"ROLE_ADMINISTRATOR"), true);
|
|
||||||
jdbcMutableAclService.updateAcl(parent);
|
|
||||||
|
|
||||||
parent.insertAce(1, BasePermission.DELETE, new PrincipalSid("terry"), true);
|
parent.insertAce(1, BasePermission.DELETE, new PrincipalSid("terry"), true);
|
||||||
jdbcMutableAclService.updateAcl(parent);
|
this.jdbcMutableAclService.updateAcl(parent);
|
||||||
|
child = (MutableAcl) this.jdbcMutableAclService.readAclById(new ObjectIdentityImpl(TARGET_CLASS, 2L));
|
||||||
child = (MutableAcl) jdbcMutableAclService.readAclById(new ObjectIdentityImpl(
|
|
||||||
TARGET_CLASS, 2L));
|
|
||||||
|
|
||||||
parent = (MutableAcl) child.getParentAcl();
|
parent = (MutableAcl) child.getParentAcl();
|
||||||
|
|
||||||
assertThat(parent.getEntries()).hasSize(2);
|
assertThat(parent.getEntries()).hasSize(2);
|
||||||
assertThat(parent.getEntries().get(0).getPermission().getMask()).isEqualTo(16);
|
assertThat(parent.getEntries().get(0).getPermission().getMask()).isEqualTo(16);
|
||||||
assertThat(parent.getEntries()
|
assertThat(parent.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_ADMINISTRATOR"));
|
||||||
.get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_ADMINISTRATOR"));
|
|
||||||
assertThat(parent.getEntries().get(1).getPermission().getMask()).isEqualTo(8);
|
assertThat(parent.getEntries().get(1).getPermission().getMask()).isEqualTo(8);
|
||||||
assertThat(parent.getEntries().get(1).getSid()).isEqualTo(new PrincipalSid("terry"));
|
assertThat(parent.getEntries().get(1).getSid()).isEqualTo(new PrincipalSid("terry"));
|
||||||
}
|
}
|
||||||
@@ -522,56 +453,50 @@ public class JdbcMutableAclServiceTests extends
|
|||||||
@Test
|
@Test
|
||||||
@Transactional
|
@Transactional
|
||||||
public void cumulativePermissions() {
|
public void cumulativePermissions() {
|
||||||
Authentication auth = new TestingAuthenticationToken("ben", "ignored",
|
Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_ADMINISTRATOR");
|
||||||
"ROLE_ADMINISTRATOR");
|
|
||||||
auth.setAuthenticated(true);
|
auth.setAuthenticated(true);
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
|
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, 110L);
|
||||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS,
|
MutableAcl topParent = this.jdbcMutableAclService.createAcl(topParentOid);
|
||||||
110L);
|
|
||||||
MutableAcl topParent = jdbcMutableAclService.createAcl(topParentOid);
|
|
||||||
|
|
||||||
// Add an ACE permission entry
|
// Add an ACE permission entry
|
||||||
Permission cm = new CumulativePermission().set(BasePermission.READ).set(
|
Permission cm = new CumulativePermission().set(BasePermission.READ).set(BasePermission.ADMINISTRATION);
|
||||||
BasePermission.ADMINISTRATION);
|
|
||||||
assertThat(cm.getMask()).isEqualTo(17);
|
assertThat(cm.getMask()).isEqualTo(17);
|
||||||
Sid benSid = new PrincipalSid(auth);
|
Sid benSid = new PrincipalSid(auth);
|
||||||
topParent.insertAce(0, cm, benSid, true);
|
topParent.insertAce(0, cm, benSid, true);
|
||||||
assertThat(topParent.getEntries()).hasSize(1);
|
assertThat(topParent.getEntries()).hasSize(1);
|
||||||
|
|
||||||
// Explicitly save the changed ACL
|
// Explicitly save the changed ACL
|
||||||
topParent = jdbcMutableAclService.updateAcl(topParent);
|
topParent = this.jdbcMutableAclService.updateAcl(topParent);
|
||||||
|
|
||||||
// Check the mask was retrieved correctly
|
// Check the mask was retrieved correctly
|
||||||
assertThat(topParent.getEntries().get(0).getPermission().getMask()).isEqualTo(17);
|
assertThat(topParent.getEntries().get(0).getPermission().getMask()).isEqualTo(17);
|
||||||
assertThat(topParent.isGranted(Arrays.asList(cm), Arrays.asList(benSid), true)).isTrue();
|
assertThat(topParent.isGranted(Arrays.asList(cm), Arrays.asList(benSid), true)).isTrue();
|
||||||
|
|
||||||
SecurityContextHolder.clearContext();
|
SecurityContextHolder.clearContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProcessingCustomSid() {
|
public void testProcessingCustomSid() {
|
||||||
CustomJdbcMutableAclService customJdbcMutableAclService = spy(new CustomJdbcMutableAclService(
|
CustomJdbcMutableAclService customJdbcMutableAclService = spy(
|
||||||
dataSource, lookupStrategy, aclCache));
|
new CustomJdbcMutableAclService(this.dataSource, this.lookupStrategy, this.aclCache));
|
||||||
CustomSid customSid = new CustomSid("Custom sid");
|
CustomSid customSid = new CustomSid("Custom sid");
|
||||||
when(
|
given(customJdbcMutableAclService.createOrRetrieveSidPrimaryKey("Custom sid", false, false)).willReturn(1L);
|
||||||
customJdbcMutableAclService.createOrRetrieveSidPrimaryKey("Custom sid",
|
Long result = customJdbcMutableAclService.createOrRetrieveSidPrimaryKey(customSid, false);
|
||||||
false, false)).thenReturn(1L);
|
|
||||||
|
|
||||||
Long result = customJdbcMutableAclService.createOrRetrieveSidPrimaryKey(
|
|
||||||
customSid, false);
|
|
||||||
|
|
||||||
assertThat(new Long(1L)).isEqualTo(result);
|
assertThat(new Long(1L)).isEqualTo(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Authentication getAuth() {
|
||||||
|
return this.auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JdbcMutableAclService getJdbcMutableAclService() {
|
||||||
|
return this.jdbcMutableAclService;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class needed to show how to extend {@link JdbcMutableAclService} for
|
* This class needed to show how to extend {@link JdbcMutableAclService} for
|
||||||
* processing custom {@link Sid} implementations
|
* processing custom {@link Sid} implementations
|
||||||
*/
|
*/
|
||||||
private class CustomJdbcMutableAclService extends JdbcMutableAclService {
|
private class CustomJdbcMutableAclService extends JdbcMutableAclService {
|
||||||
|
|
||||||
private CustomJdbcMutableAclService(DataSource dataSource,
|
CustomJdbcMutableAclService(DataSource dataSource, LookupStrategy lookupStrategy, AclCache aclCache) {
|
||||||
LookupStrategy lookupStrategy, AclCache aclCache) {
|
|
||||||
super(dataSource, lookupStrategy, aclCache);
|
super(dataSource, lookupStrategy, aclCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,13 +516,7 @@ public class JdbcMutableAclServiceTests extends
|
|||||||
}
|
}
|
||||||
return createOrRetrieveSidPrimaryKey(sidName, isPrincipal, allowCreate);
|
return createOrRetrieveSidPrimaryKey(sidName, isPrincipal, allowCreate);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Authentication getAuth() {
|
|
||||||
return auth;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected JdbcMutableAclService getJdbcMutableAclService() {
|
|
||||||
return jdbcMutableAclService;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-17
@@ -13,13 +13,13 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.acls.jdbc;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
package org.springframework.security.acls.jdbc;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.security.acls.TargetObjectWithUUID;
|
import org.springframework.security.acls.TargetObjectWithUUID;
|
||||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||||
import org.springframework.security.acls.model.ObjectIdentity;
|
import org.springframework.security.acls.model.ObjectIdentity;
|
||||||
@@ -27,21 +27,24 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
|||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration tests the ACL system using ACL class id type of UUID and using an in-memory database.
|
* Integration tests the ACL system using ACL class id type of UUID and using an in-memory
|
||||||
|
* database.
|
||||||
|
*
|
||||||
* @author Paul Wheeler
|
* @author Paul Wheeler
|
||||||
*/
|
*/
|
||||||
@ContextConfiguration(locations = {"/jdbcMutableAclServiceTestsWithAclClass-context.xml"})
|
@ContextConfiguration(locations = { "/jdbcMutableAclServiceTestsWithAclClass-context.xml" })
|
||||||
public class JdbcMutableAclServiceTestsWithAclClassId extends JdbcMutableAclServiceTests {
|
public class JdbcMutableAclServiceTestsWithAclClassId extends JdbcMutableAclServiceTests {
|
||||||
|
|
||||||
private static final String TARGET_CLASS_WITH_UUID = TargetObjectWithUUID.class.getName();
|
private static final String TARGET_CLASS_WITH_UUID = TargetObjectWithUUID.class.getName();
|
||||||
|
|
||||||
private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID,
|
private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, UUID.randomUUID());
|
||||||
UUID.randomUUID());
|
|
||||||
private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID,
|
private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, UUID.randomUUID());
|
||||||
UUID.randomUUID());
|
|
||||||
private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID,
|
private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, UUID.randomUUID());
|
||||||
UUID.randomUUID());
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getSqlClassPathResource() {
|
protected String getSqlClassPathResource() {
|
||||||
@@ -50,17 +53,17 @@ public class JdbcMutableAclServiceTestsWithAclClassId extends JdbcMutableAclServ
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ObjectIdentity getTopParentOid() {
|
protected ObjectIdentity getTopParentOid() {
|
||||||
return topParentOid;
|
return this.topParentOid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ObjectIdentity getMiddleParentOid() {
|
protected ObjectIdentity getMiddleParentOid() {
|
||||||
return middleParentOid;
|
return this.middleParentOid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ObjectIdentity getChildOid() {
|
protected ObjectIdentity getChildOid() {
|
||||||
return childOid;
|
return this.childOid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -72,12 +75,11 @@ public class JdbcMutableAclServiceTestsWithAclClassId extends JdbcMutableAclServ
|
|||||||
@Transactional
|
@Transactional
|
||||||
public void identityWithUuidIdIsSupportedByCreateAcl() {
|
public void identityWithUuidIdIsSupportedByCreateAcl() {
|
||||||
SecurityContextHolder.getContext().setAuthentication(getAuth());
|
SecurityContextHolder.getContext().setAuthentication(getAuth());
|
||||||
|
|
||||||
UUID id = UUID.randomUUID();
|
UUID id = UUID.randomUUID();
|
||||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, id);
|
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, id);
|
||||||
getJdbcMutableAclService().createAcl(oid);
|
getJdbcMutableAclService().createAcl(oid);
|
||||||
|
assertThat(getJdbcMutableAclService().readAclById(new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, id)))
|
||||||
assertThat(getJdbcMutableAclService().readAclById(new ObjectIdentityImpl(
|
.isNotNull();
|
||||||
TARGET_CLASS_WITH_UUID, id))).isNotNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-50
@@ -13,15 +13,26 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.jdbc;
|
package org.springframework.security.acls.jdbc;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
import org.springframework.cache.CacheManager;
|
import org.springframework.cache.CacheManager;
|
||||||
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||||
import org.springframework.security.acls.domain.*;
|
import org.springframework.security.acls.domain.AclAuthorizationStrategy;
|
||||||
|
import org.springframework.security.acls.domain.AclAuthorizationStrategyImpl;
|
||||||
|
import org.springframework.security.acls.domain.AclImpl;
|
||||||
|
import org.springframework.security.acls.domain.AuditLogger;
|
||||||
|
import org.springframework.security.acls.domain.ConsoleAuditLogger;
|
||||||
|
import org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy;
|
||||||
|
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||||
|
import org.springframework.security.acls.domain.SpringCacheBasedAclCache;
|
||||||
import org.springframework.security.acls.model.MutableAcl;
|
import org.springframework.security.acls.model.MutableAcl;
|
||||||
import org.springframework.security.acls.model.ObjectIdentity;
|
import org.springframework.security.acls.model.ObjectIdentity;
|
||||||
import org.springframework.security.acls.model.PermissionGrantingStrategy;
|
import org.springframework.security.acls.model.PermissionGrantingStrategy;
|
||||||
@@ -31,9 +42,7 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.util.FieldUtils;
|
import org.springframework.security.util.FieldUtils;
|
||||||
|
|
||||||
import java.util.Map;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link org.springframework.security.acls.domain.SpringCacheBasedAclCache}
|
* Tests {@link org.springframework.security.acls.domain.SpringCacheBasedAclCache}
|
||||||
@@ -41,6 +50,7 @@ import static org.assertj.core.api.Assertions.*;
|
|||||||
* @author Marten Deinum
|
* @author Marten Deinum
|
||||||
*/
|
*/
|
||||||
public class SpringCacheBasedAclCacheTests {
|
public class SpringCacheBasedAclCacheTests {
|
||||||
|
|
||||||
private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject";
|
private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject";
|
||||||
|
|
||||||
private static CacheManager cacheManager;
|
private static CacheManager cacheManager;
|
||||||
@@ -76,43 +86,31 @@ public class SpringCacheBasedAclCacheTests {
|
|||||||
Map realCache = (Map) cache.getNativeCache();
|
Map realCache = (Map) cache.getNativeCache();
|
||||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
||||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority(
|
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||||
"ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL"));
|
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||||
AuditLogger auditLogger = new ConsoleAuditLogger();
|
AuditLogger auditLogger = new ConsoleAuditLogger();
|
||||||
|
PermissionGrantingStrategy permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(auditLogger);
|
||||||
PermissionGrantingStrategy permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(
|
SpringCacheBasedAclCache myCache = new SpringCacheBasedAclCache(cache, permissionGrantingStrategy,
|
||||||
auditLogger);
|
aclAuthorizationStrategy);
|
||||||
SpringCacheBasedAclCache myCache = new SpringCacheBasedAclCache(cache,
|
MutableAcl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, auditLogger);
|
||||||
permissionGrantingStrategy, aclAuthorizationStrategy);
|
|
||||||
MutableAcl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy,
|
|
||||||
auditLogger);
|
|
||||||
|
|
||||||
assertThat(realCache).isEmpty();
|
assertThat(realCache).isEmpty();
|
||||||
myCache.putInCache(acl);
|
myCache.putInCache(acl);
|
||||||
|
|
||||||
// Check we can get from cache the same objects we put in
|
// Check we can get from cache the same objects we put in
|
||||||
assertThat(acl).isEqualTo(myCache.getFromCache(1L));
|
assertThat(acl).isEqualTo(myCache.getFromCache(1L));
|
||||||
assertThat(acl).isEqualTo(myCache.getFromCache(identity));
|
assertThat(acl).isEqualTo(myCache.getFromCache(identity));
|
||||||
|
|
||||||
// Put another object in cache
|
// Put another object in cache
|
||||||
ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, 101L);
|
ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, 101L);
|
||||||
MutableAcl acl2 = new AclImpl(identity2, 2L,
|
MutableAcl acl2 = new AclImpl(identity2, 2L, aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||||
aclAuthorizationStrategy, new ConsoleAuditLogger());
|
|
||||||
|
|
||||||
myCache.putInCache(acl2);
|
myCache.putInCache(acl2);
|
||||||
|
|
||||||
// Try to evict an entry that doesn't exist
|
// Try to evict an entry that doesn't exist
|
||||||
myCache.evictFromCache(3L);
|
myCache.evictFromCache(3L);
|
||||||
myCache.evictFromCache(new ObjectIdentityImpl(TARGET_CLASS, 102L));
|
myCache.evictFromCache(new ObjectIdentityImpl(TARGET_CLASS, 102L));
|
||||||
assertThat(realCache).hasSize(4);
|
assertThat(realCache).hasSize(4);
|
||||||
|
|
||||||
myCache.evictFromCache(1L);
|
myCache.evictFromCache(1L);
|
||||||
assertThat(realCache).hasSize(2);
|
assertThat(realCache).hasSize(2);
|
||||||
|
|
||||||
// Check the second object inserted
|
// Check the second object inserted
|
||||||
assertThat(acl2).isEqualTo(myCache.getFromCache(2L));
|
assertThat(acl2).isEqualTo(myCache.getFromCache(2L));
|
||||||
assertThat(acl2).isEqualTo(myCache.getFromCache(identity2));
|
assertThat(acl2).isEqualTo(myCache.getFromCache(identity2));
|
||||||
|
|
||||||
myCache.evictFromCache(identity2);
|
myCache.evictFromCache(identity2);
|
||||||
assertThat(realCache).isEmpty();
|
assertThat(realCache).isEmpty();
|
||||||
}
|
}
|
||||||
@@ -122,50 +120,36 @@ public class SpringCacheBasedAclCacheTests {
|
|||||||
public void cacheOperationsAclWithParent() throws Exception {
|
public void cacheOperationsAclWithParent() throws Exception {
|
||||||
Cache cache = getCache();
|
Cache cache = getCache();
|
||||||
Map realCache = (Map) cache.getNativeCache();
|
Map realCache = (Map) cache.getNativeCache();
|
||||||
|
Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL");
|
||||||
Authentication auth = new TestingAuthenticationToken("user", "password",
|
|
||||||
"ROLE_GENERAL");
|
|
||||||
auth.setAuthenticated(true);
|
auth.setAuthenticated(true);
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
|
|
||||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 1L);
|
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 1L);
|
||||||
ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS,
|
ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS, 2L);
|
||||||
2L);
|
|
||||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority(
|
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||||
"ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL"));
|
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||||
AuditLogger auditLogger = new ConsoleAuditLogger();
|
AuditLogger auditLogger = new ConsoleAuditLogger();
|
||||||
|
PermissionGrantingStrategy permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(auditLogger);
|
||||||
PermissionGrantingStrategy permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(
|
SpringCacheBasedAclCache myCache = new SpringCacheBasedAclCache(cache, permissionGrantingStrategy,
|
||||||
auditLogger);
|
aclAuthorizationStrategy);
|
||||||
SpringCacheBasedAclCache myCache = new SpringCacheBasedAclCache(cache,
|
MutableAcl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, auditLogger);
|
||||||
permissionGrantingStrategy, aclAuthorizationStrategy);
|
MutableAcl parentAcl = new AclImpl(identityParent, 2L, aclAuthorizationStrategy, auditLogger);
|
||||||
|
|
||||||
MutableAcl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy,
|
|
||||||
auditLogger);
|
|
||||||
MutableAcl parentAcl = new AclImpl(identityParent, 2L,
|
|
||||||
aclAuthorizationStrategy, auditLogger);
|
|
||||||
|
|
||||||
acl.setParent(parentAcl);
|
acl.setParent(parentAcl);
|
||||||
|
|
||||||
assertThat(realCache).isEmpty();
|
assertThat(realCache).isEmpty();
|
||||||
myCache.putInCache(acl);
|
myCache.putInCache(acl);
|
||||||
assertThat(4).isEqualTo(realCache.size());
|
assertThat(4).isEqualTo(realCache.size());
|
||||||
|
|
||||||
// Check we can get from cache the same objects we put in
|
// Check we can get from cache the same objects we put in
|
||||||
AclImpl aclFromCache = (AclImpl) myCache.getFromCache(1L);
|
AclImpl aclFromCache = (AclImpl) myCache.getFromCache(1L);
|
||||||
assertThat(aclFromCache).isEqualTo(acl);
|
assertThat(aclFromCache).isEqualTo(acl);
|
||||||
// SEC-951 check transient fields are set on parent
|
// SEC-951 check transient fields are set on parent
|
||||||
assertThat(FieldUtils.getFieldValue(aclFromCache.getParentAcl(),
|
assertThat(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), "aclAuthorizationStrategy")).isNotNull();
|
||||||
"aclAuthorizationStrategy")).isNotNull();
|
assertThat(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), "permissionGrantingStrategy")).isNotNull();
|
||||||
assertThat(FieldUtils.getFieldValue(aclFromCache.getParentAcl(),
|
|
||||||
"permissionGrantingStrategy")).isNotNull();
|
|
||||||
assertThat(myCache.getFromCache(identity)).isEqualTo(acl);
|
assertThat(myCache.getFromCache(identity)).isEqualTo(acl);
|
||||||
assertThat(FieldUtils.getFieldValue(aclFromCache, "aclAuthorizationStrategy")).isNotNull();
|
assertThat(FieldUtils.getFieldValue(aclFromCache, "aclAuthorizationStrategy")).isNotNull();
|
||||||
AclImpl parentAclFromCache = (AclImpl) myCache.getFromCache(2L);
|
AclImpl parentAclFromCache = (AclImpl) myCache.getFromCache(2L);
|
||||||
assertThat(parentAclFromCache).isEqualTo(parentAcl);
|
assertThat(parentAclFromCache).isEqualTo(parentAcl);
|
||||||
assertThat(FieldUtils.getFieldValue(parentAclFromCache,
|
assertThat(FieldUtils.getFieldValue(parentAclFromCache, "aclAuthorizationStrategy")).isNotNull();
|
||||||
"aclAuthorizationStrategy")).isNotNull();
|
|
||||||
assertThat(myCache.getFromCache(identityParent)).isEqualTo(parentAcl);
|
assertThat(myCache.getFromCache(identityParent)).isEqualTo(parentAcl);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,12 +13,14 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.sid;
|
package org.springframework.security.acls.sid;
|
||||||
|
|
||||||
import org.springframework.security.acls.model.Sid;
|
import org.springframework.security.acls.model.Sid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is example of custom {@link Sid} implementation
|
* This class is example of custom {@link Sid} implementation
|
||||||
|
*
|
||||||
* @author Mikhail Stryzhonok
|
* @author Mikhail Stryzhonok
|
||||||
*/
|
*/
|
||||||
public class CustomSid implements Sid {
|
public class CustomSid implements Sid {
|
||||||
@@ -30,10 +32,11 @@ public class CustomSid implements Sid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getSid() {
|
public String getSid() {
|
||||||
return sid;
|
return this.sid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSid(String sid) {
|
public void setSid(String sid) {
|
||||||
this.sid = sid;
|
this.sid = sid;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-15
@@ -13,14 +13,13 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.acls.sid;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
package org.springframework.security.acls.sid;
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||||
import org.springframework.security.acls.domain.GrantedAuthoritySid;
|
import org.springframework.security.acls.domain.GrantedAuthoritySid;
|
||||||
import org.springframework.security.acls.domain.PrincipalSid;
|
import org.springframework.security.acls.domain.PrincipalSid;
|
||||||
@@ -31,6 +30,11 @@ import org.springframework.security.authentication.TestingAuthenticationToken;
|
|||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.authority.AuthorityUtils;
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyCollection;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link SidRetrievalStrategyImpl}
|
* Tests for {@link SidRetrievalStrategyImpl}
|
||||||
*
|
*
|
||||||
@@ -39,26 +43,20 @@ import org.springframework.security.core.authority.AuthorityUtils;
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class SidRetrievalStrategyTests {
|
public class SidRetrievalStrategyTests {
|
||||||
Authentication authentication = new TestingAuthenticationToken("scott", "password",
|
|
||||||
"A", "B", "C");
|
|
||||||
|
|
||||||
// ~ Methods
|
Authentication authentication = new TestingAuthenticationToken("scott", "password", "A", "B", "C");
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void correctSidsAreRetrieved() {
|
public void correctSidsAreRetrieved() {
|
||||||
SidRetrievalStrategy retrStrategy = new SidRetrievalStrategyImpl();
|
SidRetrievalStrategy retrStrategy = new SidRetrievalStrategyImpl();
|
||||||
List<Sid> sids = retrStrategy.getSids(authentication);
|
List<Sid> sids = retrStrategy.getSids(this.authentication);
|
||||||
|
|
||||||
assertThat(sids).isNotNull();
|
assertThat(sids).isNotNull();
|
||||||
assertThat(sids).hasSize(4);
|
assertThat(sids).hasSize(4);
|
||||||
assertThat(sids.get(0)).isNotNull();
|
assertThat(sids.get(0)).isNotNull();
|
||||||
assertThat(sids.get(0) instanceof PrincipalSid).isTrue();
|
assertThat(sids.get(0) instanceof PrincipalSid).isTrue();
|
||||||
|
|
||||||
for (int i = 1; i < sids.size(); i++) {
|
for (int i = 1; i < sids.size(); i++) {
|
||||||
assertThat(sids.get(i) instanceof GrantedAuthoritySid).isTrue();
|
assertThat(sids.get(i) instanceof GrantedAuthoritySid).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
assertThat(((PrincipalSid) sids.get(0)).getPrincipal()).isEqualTo("scott");
|
assertThat(((PrincipalSid) sids.get(0)).getPrincipal()).isEqualTo("scott");
|
||||||
assertThat(((GrantedAuthoritySid) sids.get(1)).getGrantedAuthority()).isEqualTo("A");
|
assertThat(((GrantedAuthoritySid) sids.get(1)).getGrantedAuthority()).isEqualTo("A");
|
||||||
assertThat(((GrantedAuthoritySid) sids.get(2)).getGrantedAuthority()).isEqualTo("B");
|
assertThat(((GrantedAuthoritySid) sids.get(2)).getGrantedAuthority()).isEqualTo("B");
|
||||||
@@ -69,14 +67,13 @@ public class SidRetrievalStrategyTests {
|
|||||||
public void roleHierarchyIsUsedWhenSet() {
|
public void roleHierarchyIsUsedWhenSet() {
|
||||||
RoleHierarchy rh = mock(RoleHierarchy.class);
|
RoleHierarchy rh = mock(RoleHierarchy.class);
|
||||||
List rhAuthorities = AuthorityUtils.createAuthorityList("D");
|
List rhAuthorities = AuthorityUtils.createAuthorityList("D");
|
||||||
when(rh.getReachableGrantedAuthorities(anyCollection()))
|
given(rh.getReachableGrantedAuthorities(anyCollection())).willReturn(rhAuthorities);
|
||||||
.thenReturn(rhAuthorities);
|
|
||||||
SidRetrievalStrategy strat = new SidRetrievalStrategyImpl(rh);
|
SidRetrievalStrategy strat = new SidRetrievalStrategyImpl(rh);
|
||||||
|
List<Sid> sids = strat.getSids(this.authentication);
|
||||||
List<Sid> sids = strat.getSids(authentication);
|
|
||||||
assertThat(sids).hasSize(2);
|
assertThat(sids).hasSize(2);
|
||||||
assertThat(sids.get(0)).isNotNull();
|
assertThat(sids.get(0)).isNotNull();
|
||||||
assertThat(sids.get(0) instanceof PrincipalSid).isTrue();
|
assertThat(sids.get(0) instanceof PrincipalSid).isTrue();
|
||||||
assertThat(((GrantedAuthoritySid) sids.get(1)).getGrantedAuthority()).isEqualTo("D");
|
assertThat(((GrantedAuthoritySid) sids.get(1)).getGrantedAuthority()).isEqualTo("D");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,12 +13,14 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.acls.sid;
|
package org.springframework.security.acls.sid;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import java.util.Collection;
|
||||||
import static org.assertj.core.api.Assertions.fail;
|
import java.util.Collections;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.security.acls.domain.GrantedAuthoritySid;
|
import org.springframework.security.acls.domain.GrantedAuthoritySid;
|
||||||
import org.springframework.security.acls.domain.PrincipalSid;
|
import org.springframework.security.acls.domain.PrincipalSid;
|
||||||
import org.springframework.security.acls.model.Sid;
|
import org.springframework.security.acls.model.Sid;
|
||||||
@@ -29,13 +31,11 @@ import org.springframework.security.core.GrantedAuthority;
|
|||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.core.userdetails.User;
|
import org.springframework.security.core.userdetails.User;
|
||||||
|
|
||||||
import java.util.Collection;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import java.util.Collections;
|
import static org.assertj.core.api.Assertions.fail;
|
||||||
|
|
||||||
public class SidTests {
|
public class SidTests {
|
||||||
|
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
@Test
|
@Test
|
||||||
public void testPrincipalSidConstructorsRequiredFields() {
|
public void testPrincipalSidConstructorsRequiredFields() {
|
||||||
// Check one String-argument constructor
|
// Check one String-argument constructor
|
||||||
@@ -46,17 +46,14 @@ public class SidTests {
|
|||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new PrincipalSid("");
|
new PrincipalSid("");
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
new PrincipalSid("johndoe");
|
new PrincipalSid("johndoe");
|
||||||
// throws no exception
|
// throws no exception
|
||||||
|
|
||||||
// Check one Authentication-argument constructor
|
// Check one Authentication-argument constructor
|
||||||
try {
|
try {
|
||||||
Authentication authentication = null;
|
Authentication authentication = null;
|
||||||
@@ -65,18 +62,14 @@ public class SidTests {
|
|||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Authentication authentication = new TestingAuthenticationToken(null,
|
Authentication authentication = new TestingAuthenticationToken(null, "password");
|
||||||
"password");
|
|
||||||
new PrincipalSid(authentication);
|
new PrincipalSid(authentication);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
|
Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
|
||||||
Authentication authentication = new TestingAuthenticationToken("johndoe",
|
|
||||||
"password");
|
|
||||||
new PrincipalSid(authentication);
|
new PrincipalSid(authentication);
|
||||||
// throws no exception
|
// throws no exception
|
||||||
}
|
}
|
||||||
@@ -90,25 +83,19 @@ public class SidTests {
|
|||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new GrantedAuthoritySid("");
|
new GrantedAuthoritySid("");
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new GrantedAuthoritySid("ROLE_TEST");
|
new GrantedAuthoritySid("ROLE_TEST");
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException notExpected) {
|
catch (IllegalArgumentException notExpected) {
|
||||||
fail("It shouldn't have thrown IllegalArgumentException");
|
fail("It shouldn't have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check one GrantedAuthority-argument constructor
|
// Check one GrantedAuthority-argument constructor
|
||||||
try {
|
try {
|
||||||
GrantedAuthority ga = null;
|
GrantedAuthority ga = null;
|
||||||
@@ -116,22 +103,17 @@ public class SidTests {
|
|||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
GrantedAuthority ga = new SimpleGrantedAuthority(null);
|
GrantedAuthority ga = new SimpleGrantedAuthority(null);
|
||||||
new GrantedAuthoritySid(ga);
|
new GrantedAuthoritySid(ga);
|
||||||
fail("It should have thrown IllegalArgumentException");
|
fail("It should have thrown IllegalArgumentException");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST");
|
GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST");
|
||||||
new GrantedAuthoritySid(ga);
|
new GrantedAuthoritySid(ga);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException notExpected) {
|
catch (IllegalArgumentException notExpected) {
|
||||||
fail("It shouldn't have thrown IllegalArgumentException");
|
fail("It shouldn't have thrown IllegalArgumentException");
|
||||||
@@ -140,18 +122,14 @@ public class SidTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPrincipalSidEquals() {
|
public void testPrincipalSidEquals() {
|
||||||
Authentication authentication = new TestingAuthenticationToken("johndoe",
|
Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
|
||||||
"password");
|
|
||||||
Sid principalSid = new PrincipalSid(authentication);
|
Sid principalSid = new PrincipalSid(authentication);
|
||||||
|
|
||||||
assertThat(principalSid.equals(null)).isFalse();
|
assertThat(principalSid.equals(null)).isFalse();
|
||||||
assertThat(principalSid.equals("DIFFERENT_TYPE_OBJECT")).isFalse();
|
assertThat(principalSid.equals("DIFFERENT_TYPE_OBJECT")).isFalse();
|
||||||
assertThat(principalSid.equals(principalSid)).isTrue();
|
assertThat(principalSid.equals(principalSid)).isTrue();
|
||||||
assertThat(principalSid.equals(new PrincipalSid(authentication))).isTrue();
|
assertThat(principalSid.equals(new PrincipalSid(authentication))).isTrue();
|
||||||
assertThat(principalSid.equals(new PrincipalSid(
|
assertThat(principalSid.equals(new PrincipalSid(new TestingAuthenticationToken("johndoe", null)))).isTrue();
|
||||||
new TestingAuthenticationToken("johndoe", null)))).isTrue();
|
assertThat(principalSid.equals(new PrincipalSid(new TestingAuthenticationToken("scott", null)))).isFalse();
|
||||||
assertThat(principalSid.equals(new PrincipalSid(
|
|
||||||
new TestingAuthenticationToken("scott", null)))).isFalse();
|
|
||||||
assertThat(principalSid.equals(new PrincipalSid("johndoe"))).isTrue();
|
assertThat(principalSid.equals(new PrincipalSid("johndoe"))).isTrue();
|
||||||
assertThat(principalSid.equals(new PrincipalSid("scott"))).isFalse();
|
assertThat(principalSid.equals(new PrincipalSid("scott"))).isFalse();
|
||||||
}
|
}
|
||||||
@@ -160,59 +138,46 @@ public class SidTests {
|
|||||||
public void testGrantedAuthoritySidEquals() {
|
public void testGrantedAuthoritySidEquals() {
|
||||||
GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST");
|
GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST");
|
||||||
Sid gaSid = new GrantedAuthoritySid(ga);
|
Sid gaSid = new GrantedAuthoritySid(ga);
|
||||||
|
|
||||||
assertThat(gaSid.equals(null)).isFalse();
|
assertThat(gaSid.equals(null)).isFalse();
|
||||||
assertThat(gaSid.equals("DIFFERENT_TYPE_OBJECT")).isFalse();
|
assertThat(gaSid.equals("DIFFERENT_TYPE_OBJECT")).isFalse();
|
||||||
assertThat(gaSid.equals(gaSid)).isTrue();
|
assertThat(gaSid.equals(gaSid)).isTrue();
|
||||||
assertThat(gaSid.equals(new GrantedAuthoritySid(ga))).isTrue();
|
assertThat(gaSid.equals(new GrantedAuthoritySid(ga))).isTrue();
|
||||||
assertThat(gaSid.equals(new GrantedAuthoritySid(
|
assertThat(gaSid.equals(new GrantedAuthoritySid(new SimpleGrantedAuthority("ROLE_TEST")))).isTrue();
|
||||||
new SimpleGrantedAuthority("ROLE_TEST")))).isTrue();
|
assertThat(gaSid.equals(new GrantedAuthoritySid(new SimpleGrantedAuthority("ROLE_NOT_EQUAL")))).isFalse();
|
||||||
assertThat(gaSid.equals(new GrantedAuthoritySid(
|
|
||||||
new SimpleGrantedAuthority("ROLE_NOT_EQUAL")))).isFalse();
|
|
||||||
assertThat(gaSid.equals(new GrantedAuthoritySid("ROLE_TEST"))).isTrue();
|
assertThat(gaSid.equals(new GrantedAuthoritySid("ROLE_TEST"))).isTrue();
|
||||||
assertThat(gaSid.equals(new GrantedAuthoritySid("ROLE_NOT_EQUAL"))).isFalse();
|
assertThat(gaSid.equals(new GrantedAuthoritySid("ROLE_NOT_EQUAL"))).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPrincipalSidHashCode() {
|
public void testPrincipalSidHashCode() {
|
||||||
Authentication authentication = new TestingAuthenticationToken("johndoe",
|
Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
|
||||||
"password");
|
|
||||||
Sid principalSid = new PrincipalSid(authentication);
|
Sid principalSid = new PrincipalSid(authentication);
|
||||||
|
|
||||||
assertThat(principalSid.hashCode()).isEqualTo("johndoe".hashCode());
|
assertThat(principalSid.hashCode()).isEqualTo("johndoe".hashCode());
|
||||||
assertThat(principalSid.hashCode()).isEqualTo(
|
assertThat(principalSid.hashCode()).isEqualTo(new PrincipalSid("johndoe").hashCode());
|
||||||
new PrincipalSid("johndoe").hashCode());
|
assertThat(principalSid.hashCode()).isNotEqualTo(new PrincipalSid("scott").hashCode());
|
||||||
assertThat(principalSid.hashCode()).isNotEqualTo(
|
assertThat(principalSid.hashCode())
|
||||||
new PrincipalSid("scott").hashCode());
|
.isNotEqualTo(new PrincipalSid(new TestingAuthenticationToken("scott", "password")).hashCode());
|
||||||
assertThat(principalSid.hashCode()).isNotEqualTo(new PrincipalSid(
|
|
||||||
new TestingAuthenticationToken("scott", "password")).hashCode());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGrantedAuthoritySidHashCode() {
|
public void testGrantedAuthoritySidHashCode() {
|
||||||
GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST");
|
GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST");
|
||||||
Sid gaSid = new GrantedAuthoritySid(ga);
|
Sid gaSid = new GrantedAuthoritySid(ga);
|
||||||
|
|
||||||
assertThat(gaSid.hashCode()).isEqualTo("ROLE_TEST".hashCode());
|
assertThat(gaSid.hashCode()).isEqualTo("ROLE_TEST".hashCode());
|
||||||
assertThat(gaSid.hashCode()).isEqualTo(
|
assertThat(gaSid.hashCode()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST").hashCode());
|
||||||
new GrantedAuthoritySid("ROLE_TEST").hashCode());
|
assertThat(gaSid.hashCode()).isNotEqualTo(new GrantedAuthoritySid("ROLE_TEST_2").hashCode());
|
||||||
assertThat(gaSid.hashCode()).isNotEqualTo(
|
assertThat(gaSid.hashCode())
|
||||||
new GrantedAuthoritySid("ROLE_TEST_2").hashCode());
|
.isNotEqualTo(new GrantedAuthoritySid(new SimpleGrantedAuthority("ROLE_TEST_2")).hashCode());
|
||||||
assertThat(gaSid.hashCode()).isNotEqualTo(new GrantedAuthoritySid(
|
|
||||||
new SimpleGrantedAuthority("ROLE_TEST_2")).hashCode());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetters() {
|
public void testGetters() {
|
||||||
Authentication authentication = new TestingAuthenticationToken("johndoe",
|
Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
|
||||||
"password");
|
|
||||||
PrincipalSid principalSid = new PrincipalSid(authentication);
|
PrincipalSid principalSid = new PrincipalSid(authentication);
|
||||||
GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST");
|
GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST");
|
||||||
GrantedAuthoritySid gaSid = new GrantedAuthoritySid(ga);
|
GrantedAuthoritySid gaSid = new GrantedAuthoritySid(ga);
|
||||||
|
|
||||||
assertThat("johndoe".equals(principalSid.getPrincipal())).isTrue();
|
assertThat("johndoe".equals(principalSid.getPrincipal())).isTrue();
|
||||||
assertThat("scott".equals(principalSid.getPrincipal())).isFalse();
|
assertThat("scott".equals(principalSid.getPrincipal())).isFalse();
|
||||||
|
|
||||||
assertThat("ROLE_TEST".equals(gaSid.getGrantedAuthority())).isTrue();
|
assertThat("ROLE_TEST".equals(gaSid.getGrantedAuthority())).isTrue();
|
||||||
assertThat("ROLE_TEST2".equals(gaSid.getGrantedAuthority())).isFalse();
|
assertThat("ROLE_TEST2".equals(gaSid.getGrantedAuthority())).isFalse();
|
||||||
}
|
}
|
||||||
@@ -222,7 +187,6 @@ public class SidTests {
|
|||||||
User user = new User("user", "password", Collections.singletonList(new SimpleGrantedAuthority("ROLE_TEST")));
|
User user = new User("user", "password", Collections.singletonList(new SimpleGrantedAuthority("ROLE_TEST")));
|
||||||
Authentication authentication = new TestingAuthenticationToken(user, "password");
|
Authentication authentication = new TestingAuthenticationToken(user, "password");
|
||||||
PrincipalSid principalSid = new PrincipalSid(authentication);
|
PrincipalSid principalSid = new PrincipalSid(authentication);
|
||||||
|
|
||||||
assertThat("user").isEqualTo(principalSid.getPrincipal());
|
assertThat("user").isEqualTo(principalSid.getPrincipal());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +194,6 @@ public class SidTests {
|
|||||||
public void getPrincipalWhenPrincipalNotInstanceOfUserDetailsThenReturnsPrincipalName() {
|
public void getPrincipalWhenPrincipalNotInstanceOfUserDetailsThenReturnsPrincipalName() {
|
||||||
Authentication authentication = new TestingAuthenticationToken("token", "password");
|
Authentication authentication = new TestingAuthenticationToken("token", "password");
|
||||||
PrincipalSid principalSid = new PrincipalSid(authentication);
|
PrincipalSid principalSid = new PrincipalSid(authentication);
|
||||||
|
|
||||||
assertThat("token").isEqualTo(principalSid.getPrincipal());
|
assertThat("token").isEqualTo(principalSid.getPrincipal());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,11 +201,11 @@ public class SidTests {
|
|||||||
public void getPrincipalWhenCustomAuthenticationPrincipalThenReturnsPrincipalName() {
|
public void getPrincipalWhenCustomAuthenticationPrincipalThenReturnsPrincipalName() {
|
||||||
Authentication authentication = new CustomAuthenticationToken(new CustomToken("token"), null);
|
Authentication authentication = new CustomAuthenticationToken(new CustomToken("token"), null);
|
||||||
PrincipalSid principalSid = new PrincipalSid(authentication);
|
PrincipalSid principalSid = new PrincipalSid(authentication);
|
||||||
|
|
||||||
assertThat("token").isEqualTo(principalSid.getPrincipal());
|
assertThat("token").isEqualTo(principalSid.getPrincipal());
|
||||||
}
|
}
|
||||||
|
|
||||||
static class CustomAuthenticationToken extends AbstractAuthenticationToken {
|
static class CustomAuthenticationToken extends AbstractAuthenticationToken {
|
||||||
|
|
||||||
private CustomToken principal;
|
private CustomToken principal;
|
||||||
|
|
||||||
CustomAuthenticationToken(CustomToken principal, Collection<GrantedAuthority> authorities) {
|
CustomAuthenticationToken(CustomToken principal, Collection<GrantedAuthority> authorities) {
|
||||||
@@ -262,11 +225,13 @@ public class SidTests {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return principal.getName();
|
return this.principal.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class CustomToken {
|
static class CustomToken {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
CustomToken(String name) {
|
CustomToken(String name) {
|
||||||
@@ -274,7 +239,9 @@ public class SidTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String getName() {
|
String getName() {
|
||||||
return name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+103
-92
@@ -13,9 +13,8 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.access.intercept.aspectj.aspect;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
package org.springframework.security.access.intercept.aspectj.aspect;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -49,39 +48,44 @@ import org.springframework.security.authentication.AuthenticationManager;
|
|||||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @since 3.0.3
|
* @since 3.0.3
|
||||||
*/
|
*/
|
||||||
public class AnnotationSecurityAspectTests {
|
public class AnnotationSecurityAspectTests {
|
||||||
|
|
||||||
private AffirmativeBased adm;
|
private AffirmativeBased adm;
|
||||||
private @Mock AuthenticationManager authman;
|
|
||||||
private TestingAuthenticationToken anne = new TestingAuthenticationToken("anne", "",
|
@Mock
|
||||||
"ROLE_A");
|
private AuthenticationManager authman;
|
||||||
|
|
||||||
|
private TestingAuthenticationToken anne = new TestingAuthenticationToken("anne", "", "ROLE_A");
|
||||||
|
|
||||||
// private TestingAuthenticationToken bob = new TestingAuthenticationToken("bob", "",
|
// private TestingAuthenticationToken bob = new TestingAuthenticationToken("bob", "",
|
||||||
// "ROLE_B");
|
// "ROLE_B");
|
||||||
private AspectJMethodSecurityInterceptor interceptor;
|
private AspectJMethodSecurityInterceptor interceptor;
|
||||||
|
|
||||||
private SecuredImpl secured = new SecuredImpl();
|
private SecuredImpl secured = new SecuredImpl();
|
||||||
|
|
||||||
private SecuredImplSubclass securedSub = new SecuredImplSubclass();
|
private SecuredImplSubclass securedSub = new SecuredImplSubclass();
|
||||||
|
|
||||||
private PrePostSecured prePostSecured = new PrePostSecured();
|
private PrePostSecured prePostSecured = new PrePostSecured();
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public final void setUp() {
|
public final void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
interceptor = new AspectJMethodSecurityInterceptor();
|
this.interceptor = new AspectJMethodSecurityInterceptor();
|
||||||
AccessDecisionVoter[] voters = new AccessDecisionVoter[] {
|
AccessDecisionVoter[] voters = new AccessDecisionVoter[] { new RoleVoter(),
|
||||||
new RoleVoter(),
|
new PreInvocationAuthorizationAdviceVoter(new ExpressionBasedPreInvocationAdvice()) };
|
||||||
new PreInvocationAuthorizationAdviceVoter(
|
this.adm = new AffirmativeBased(Arrays.<AccessDecisionVoter<? extends Object>>asList(voters));
|
||||||
new ExpressionBasedPreInvocationAdvice()) };
|
this.interceptor.setAccessDecisionManager(this.adm);
|
||||||
adm = new AffirmativeBased(
|
this.interceptor.setAuthenticationManager(this.authman);
|
||||||
Arrays.<AccessDecisionVoter<? extends Object>> asList(voters));
|
this.interceptor.setSecurityMetadataSource(new SecuredAnnotationSecurityMetadataSource());
|
||||||
interceptor.setAccessDecisionManager(adm);
|
|
||||||
interceptor.setAuthenticationManager(authman);
|
|
||||||
interceptor
|
|
||||||
.setSecurityMetadataSource(new SecuredAnnotationSecurityMetadataSource());
|
|
||||||
AnnotationSecurityAspect secAspect = AnnotationSecurityAspect.aspectOf();
|
AnnotationSecurityAspect secAspect = AnnotationSecurityAspect.aspectOf();
|
||||||
secAspect.setSecurityInterceptor(interceptor);
|
secAspect.setSecurityInterceptor(this.interceptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@@ -91,59 +95,57 @@ public class AnnotationSecurityAspectTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void securedInterfaceMethodAllowsAllAccess() {
|
public void securedInterfaceMethodAllowsAllAccess() {
|
||||||
secured.securedMethod();
|
this.secured.securedMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = AuthenticationCredentialsNotFoundException.class)
|
@Test(expected = AuthenticationCredentialsNotFoundException.class)
|
||||||
public void securedClassMethodDeniesUnauthenticatedAccess() {
|
public void securedClassMethodDeniesUnauthenticatedAccess() {
|
||||||
secured.securedClassMethod();
|
this.secured.securedClassMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void securedClassMethodAllowsAccessToRoleA() {
|
public void securedClassMethodAllowsAccessToRoleA() {
|
||||||
SecurityContextHolder.getContext().setAuthentication(anne);
|
SecurityContextHolder.getContext().setAuthentication(this.anne);
|
||||||
secured.securedClassMethod();
|
this.secured.securedClassMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = AccessDeniedException.class)
|
@Test(expected = AccessDeniedException.class)
|
||||||
public void internalPrivateCallIsIntercepted() {
|
public void internalPrivateCallIsIntercepted() {
|
||||||
SecurityContextHolder.getContext().setAuthentication(anne);
|
SecurityContextHolder.getContext().setAuthentication(this.anne);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
secured.publicCallsPrivate();
|
this.secured.publicCallsPrivate();
|
||||||
fail("Expected AccessDeniedException");
|
fail("Expected AccessDeniedException");
|
||||||
}
|
}
|
||||||
catch (AccessDeniedException expected) {
|
catch (AccessDeniedException expected) {
|
||||||
}
|
}
|
||||||
securedSub.publicCallsPrivate();
|
this.securedSub.publicCallsPrivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = AccessDeniedException.class)
|
@Test(expected = AccessDeniedException.class)
|
||||||
public void protectedMethodIsIntercepted() {
|
public void protectedMethodIsIntercepted() {
|
||||||
SecurityContextHolder.getContext().setAuthentication(anne);
|
SecurityContextHolder.getContext().setAuthentication(this.anne);
|
||||||
|
this.secured.protectedMethod();
|
||||||
secured.protectedMethod();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void overriddenProtectedMethodIsNotIntercepted() {
|
public void overriddenProtectedMethodIsNotIntercepted() {
|
||||||
// AspectJ doesn't inherit annotations
|
// AspectJ doesn't inherit annotations
|
||||||
securedSub.protectedMethod();
|
this.securedSub.protectedMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
// SEC-1262
|
// SEC-1262
|
||||||
@Test(expected = AccessDeniedException.class)
|
@Test(expected = AccessDeniedException.class)
|
||||||
public void denyAllPreAuthorizeDeniesAccess() {
|
public void denyAllPreAuthorizeDeniesAccess() {
|
||||||
configureForElAnnotations();
|
configureForElAnnotations();
|
||||||
SecurityContextHolder.getContext().setAuthentication(anne);
|
SecurityContextHolder.getContext().setAuthentication(this.anne);
|
||||||
prePostSecured.denyAllMethod();
|
this.prePostSecured.denyAllMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void postFilterIsApplied() {
|
public void postFilterIsApplied() {
|
||||||
configureForElAnnotations();
|
configureForElAnnotations();
|
||||||
SecurityContextHolder.getContext().setAuthentication(anne);
|
SecurityContextHolder.getContext().setAuthentication(this.anne);
|
||||||
List<String> objects = prePostSecured.postFilterMethod();
|
List<String> objects = this.prePostSecured.postFilterMethod();
|
||||||
assertThat(objects).hasSize(2);
|
assertThat(objects).hasSize(2);
|
||||||
assertThat(objects.contains("apple")).isTrue();
|
assertThat(objects.contains("apple")).isTrue();
|
||||||
assertThat(objects.contains("aubergine")).isTrue();
|
assertThat(objects.contains("aubergine")).isTrue();
|
||||||
@@ -151,64 +153,73 @@ public class AnnotationSecurityAspectTests {
|
|||||||
|
|
||||||
private void configureForElAnnotations() {
|
private void configureForElAnnotations() {
|
||||||
DefaultMethodSecurityExpressionHandler eh = new DefaultMethodSecurityExpressionHandler();
|
DefaultMethodSecurityExpressionHandler eh = new DefaultMethodSecurityExpressionHandler();
|
||||||
interceptor
|
this.interceptor.setSecurityMetadataSource(
|
||||||
.setSecurityMetadataSource(new PrePostAnnotationSecurityMetadataSource(
|
new PrePostAnnotationSecurityMetadataSource(new ExpressionBasedAnnotationAttributeFactory(eh)));
|
||||||
new ExpressionBasedAnnotationAttributeFactory(eh)));
|
this.interceptor.setAccessDecisionManager(this.adm);
|
||||||
interceptor.setAccessDecisionManager(adm);
|
|
||||||
AfterInvocationProviderManager aim = new AfterInvocationProviderManager();
|
AfterInvocationProviderManager aim = new AfterInvocationProviderManager();
|
||||||
aim.setProviders(Arrays.asList(new PostInvocationAdviceProvider(
|
aim.setProviders(Arrays.asList(new PostInvocationAdviceProvider(new ExpressionBasedPostInvocationAdvice(eh))));
|
||||||
new ExpressionBasedPostInvocationAdvice(eh))));
|
this.interceptor.setAfterInvocationManager(aim);
|
||||||
interceptor.setAfterInvocationManager(aim);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SecuredInterface {
|
|
||||||
@Secured("ROLE_X")
|
|
||||||
void securedMethod();
|
|
||||||
}
|
|
||||||
|
|
||||||
class SecuredImpl implements SecuredInterface {
|
|
||||||
// Not really secured because AspectJ doesn't inherit annotations from interfaces
|
|
||||||
public void securedMethod() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Secured("ROLE_A")
|
|
||||||
public void securedClassMethod() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Secured("ROLE_X")
|
|
||||||
private void privateMethod() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Secured("ROLE_X")
|
|
||||||
protected void protectedMethod() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Secured("ROLE_X")
|
|
||||||
public void publicCallsPrivate() {
|
|
||||||
privateMethod();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SecuredImplSubclass extends SecuredImpl {
|
|
||||||
protected void protectedMethod() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void publicCallsPrivate() {
|
|
||||||
super.publicCallsPrivate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class PrePostSecured {
|
|
||||||
@PreAuthorize("denyAll")
|
|
||||||
public void denyAllMethod() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostFilter("filterObject.startsWith('a')")
|
|
||||||
public List<String> postFilterMethod() {
|
|
||||||
ArrayList<String> objects = new ArrayList<>();
|
|
||||||
objects.addAll(Arrays.asList(new String[] { "apple", "banana", "aubergine",
|
|
||||||
"orange" }));
|
|
||||||
return objects;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface SecuredInterface {
|
||||||
|
|
||||||
|
@Secured("ROLE_X")
|
||||||
|
void securedMethod();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SecuredImpl implements SecuredInterface {
|
||||||
|
|
||||||
|
// Not really secured because AspectJ doesn't inherit annotations from interfaces
|
||||||
|
@Override
|
||||||
|
public void securedMethod() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Secured("ROLE_A")
|
||||||
|
public void securedClassMethod() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Secured("ROLE_X")
|
||||||
|
private void privateMethod() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Secured("ROLE_X")
|
||||||
|
protected void protectedMethod() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Secured("ROLE_X")
|
||||||
|
public void publicCallsPrivate() {
|
||||||
|
privateMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SecuredImplSubclass extends SecuredImpl {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void protectedMethod() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void publicCallsPrivate() {
|
||||||
|
super.publicCallsPrivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class PrePostSecured {
|
||||||
|
|
||||||
|
@PreAuthorize("denyAll")
|
||||||
|
public void denyAllMethod() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostFilter("filterObject.startsWith('a')")
|
||||||
|
public List<String> postFilterMethod() {
|
||||||
|
ArrayList<String> objects = new ArrayList<>();
|
||||||
|
objects.addAll(Arrays.asList(new String[] { "apple", "banana", "aubergine", "orange" }));
|
||||||
|
return objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-1
@@ -1,6 +1,7 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'io.spring.gradle:spring-build-conventions:0.0.33.RELEASE'
|
classpath 'io.spring.gradle:spring-build-conventions:0.0.33.RELEASE'
|
||||||
|
classpath "io.spring.javaformat:spring-javaformat-gradle-plugin:$springJavaformatVersion"
|
||||||
classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
|
classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
|
||||||
classpath 'io.spring.nohttp:nohttp-gradle:0.0.5.RELEASE'
|
classpath 'io.spring.nohttp:nohttp-gradle:0.0.5.RELEASE'
|
||||||
classpath "io.freefair.gradle:aspectj-plugin:5.0.1"
|
classpath "io.freefair.gradle:aspectj-plugin:5.0.1"
|
||||||
@@ -34,12 +35,35 @@ subprojects {
|
|||||||
plugins.withType(JavaPlugin) {
|
plugins.withType(JavaPlugin) {
|
||||||
project.sourceCompatibility='1.8'
|
project.sourceCompatibility='1.8'
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
tasks.withType(JavaCompile) {
|
||||||
options.encoding = "UTF-8"
|
options.encoding = "UTF-8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
apply plugin: 'io.spring.javaformat'
|
||||||
|
apply plugin: 'checkstyle'
|
||||||
|
|
||||||
|
pluginManager.withPlugin("io.spring.convention.checkstyle", { plugin ->
|
||||||
|
configure(plugin) {
|
||||||
|
dependencies {
|
||||||
|
checkstyle "io.spring.javaformat:spring-javaformat-checkstyle:$springJavaformatVersion"
|
||||||
|
}
|
||||||
|
checkstyle {
|
||||||
|
toolVersion = '8.34'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (project.name.contains('sample')) {
|
||||||
|
tasks.whenTaskAdded { task ->
|
||||||
|
if (task.name.contains('format') || task.name.contains('checkFormat') || task.name.contains("checkstyle")) {
|
||||||
|
task.enabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nohttp {
|
nohttp {
|
||||||
allowlistFile = project.file("etc/nohttp/allowlist.lines")
|
allowlistFile = project.file("etc/nohttp/allowlist.lines")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import org.gradle.api.Project;
|
|||||||
public class GlobalLockPlugin implements Plugin<Project> {
|
public class GlobalLockPlugin implements Plugin<Project> {
|
||||||
@Override
|
@Override
|
||||||
public void apply(Project project) {
|
public void apply(Project project) {
|
||||||
project.getTasks().register("writeLocks", GlobalLockTask.class, writeAll -> {
|
project.getTasks().register("writeLocks", GlobalLockTask.class, (writeAll) -> {
|
||||||
writeAll.setDescription("Writes the locks for all projects");
|
writeAll.setDescription("Writes the locks for all projects");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import org.gradle.api.Project;
|
|||||||
public class TrangPlugin implements Plugin<Project> {
|
public class TrangPlugin implements Plugin<Project> {
|
||||||
@Override
|
@Override
|
||||||
public void apply(Project project) {
|
public void apply(Project project) {
|
||||||
project.getTasks().register("rncToXsd", RncToXsd.class, rncToXsd -> {
|
project.getTasks().register("rncToXsd", RncToXsd.class, (rncToXsd) -> {
|
||||||
rncToXsd.setDescription("Converts .rnc to .xsd");
|
rncToXsd.setDescription("Converts .rnc to .xsd");
|
||||||
rncToXsd.setGroup("Build");
|
rncToXsd.setGroup("Build");
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.cas;
|
package org.springframework.security.cas;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,4 +33,5 @@ public final class SamlServiceProperties extends ServiceProperties {
|
|||||||
super.setArtifactParameter(DEFAULT_SAML_ARTIFACT_PARAMETER);
|
super.setArtifactParameter(DEFAULT_SAML_ARTIFACT_PARAMETER);
|
||||||
super.setServiceParameter(DEFAULT_SAML_SERVICE_PARAMETER);
|
super.setServiceParameter(DEFAULT_SAML_SERVICE_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,9 +34,6 @@ public class ServiceProperties implements InitializingBean {
|
|||||||
|
|
||||||
public static final String DEFAULT_CAS_SERVICE_PARAMETER = "service";
|
public static final String DEFAULT_CAS_SERVICE_PARAMETER = "service";
|
||||||
|
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
private String service;
|
private String service;
|
||||||
|
|
||||||
private boolean authenticateAllArtifacts;
|
private boolean authenticateAllArtifacts;
|
||||||
@@ -47,9 +44,7 @@ public class ServiceProperties implements InitializingBean {
|
|||||||
|
|
||||||
private String serviceParameter = DEFAULT_CAS_SERVICE_PARAMETER;
|
private String serviceParameter = DEFAULT_CAS_SERVICE_PARAMETER;
|
||||||
|
|
||||||
// ~ Methods
|
@Override
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
public void afterPropertiesSet() {
|
public void afterPropertiesSet() {
|
||||||
Assert.hasLength(this.service, "service cannot be empty.");
|
Assert.hasLength(this.service, "service cannot be empty.");
|
||||||
Assert.hasLength(this.artifactParameter, "artifactParameter cannot be empty.");
|
Assert.hasLength(this.artifactParameter, "artifactParameter cannot be empty.");
|
||||||
@@ -65,7 +60,6 @@ public class ServiceProperties implements InitializingBean {
|
|||||||
* <pre>
|
* <pre>
|
||||||
* https://www.mycompany.com/application/login/cas
|
* https://www.mycompany.com/application/login/cas
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
|
||||||
* @return the URL of the service the user is authenticating to
|
* @return the URL of the service the user is authenticating to
|
||||||
*/
|
*/
|
||||||
public final String getService() {
|
public final String getService() {
|
||||||
@@ -81,7 +75,6 @@ public class ServiceProperties implements InitializingBean {
|
|||||||
* ticket was generated as a consequence of an explicit login. High security
|
* ticket was generated as a consequence of an explicit login. High security
|
||||||
* applications would probably set this to <code>true</code>. Defaults to
|
* applications would probably set this to <code>true</code>. Defaults to
|
||||||
* <code>false</code>, providing automated single sign on.
|
* <code>false</code>, providing automated single sign on.
|
||||||
*
|
|
||||||
* @return whether to send the <code>renew</code> parameter to CAS
|
* @return whether to send the <code>renew</code> parameter to CAS
|
||||||
*/
|
*/
|
||||||
public final boolean isSendRenew() {
|
public final boolean isSendRenew() {
|
||||||
@@ -103,7 +96,6 @@ public class ServiceProperties implements InitializingBean {
|
|||||||
/**
|
/**
|
||||||
* Configures the Request Parameter to look for when attempting to see if a CAS ticket
|
* Configures the Request Parameter to look for when attempting to see if a CAS ticket
|
||||||
* was sent from the server.
|
* was sent from the server.
|
||||||
*
|
|
||||||
* @param artifactParameter the id to use. Default is "ticket".
|
* @param artifactParameter the id to use. Default is "ticket".
|
||||||
*/
|
*/
|
||||||
public final void setArtifactParameter(final String artifactParameter) {
|
public final void setArtifactParameter(final String artifactParameter) {
|
||||||
@@ -113,7 +105,6 @@ public class ServiceProperties implements InitializingBean {
|
|||||||
/**
|
/**
|
||||||
* Configures the Request parameter to look for when attempting to send a request to
|
* Configures the Request parameter to look for when attempting to send a request to
|
||||||
* CAS.
|
* CAS.
|
||||||
*
|
|
||||||
* @return the service parameter to use. Default is "service".
|
* @return the service parameter to use. Default is "service".
|
||||||
*/
|
*/
|
||||||
public final String getServiceParameter() {
|
public final String getServiceParameter() {
|
||||||
@@ -132,11 +123,10 @@ public class ServiceProperties implements InitializingBean {
|
|||||||
* If true, then any non-null artifact (ticket) should be authenticated. Additionally,
|
* If true, then any non-null artifact (ticket) should be authenticated. Additionally,
|
||||||
* the service will be determined dynamically in order to ensure the service matches
|
* the service will be determined dynamically in order to ensure the service matches
|
||||||
* the expected value for this artifact.
|
* the expected value for this artifact.
|
||||||
*
|
|
||||||
* @param authenticateAllArtifacts
|
* @param authenticateAllArtifacts
|
||||||
*/
|
*/
|
||||||
public final void setAuthenticateAllArtifacts(
|
public final void setAuthenticateAllArtifacts(final boolean authenticateAllArtifacts) {
|
||||||
final boolean authenticateAllArtifacts) {
|
|
||||||
this.authenticateAllArtifacts = authenticateAllArtifacts;
|
this.authenticateAllArtifacts = authenticateAllArtifacts;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -13,11 +13,13 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.cas.authentication;
|
package org.springframework.security.cas.authentication;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import org.jasig.cas.client.validation.Assertion;
|
import org.jasig.cas.client.validation.Assertion;
|
||||||
|
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||||
|
|
||||||
@@ -37,15 +39,16 @@ public final class CasAssertionAuthenticationToken extends AbstractAuthenticatio
|
|||||||
|
|
||||||
public CasAssertionAuthenticationToken(final Assertion assertion, final String ticket) {
|
public CasAssertionAuthenticationToken(final Assertion assertion, final String ticket) {
|
||||||
super(new ArrayList<>());
|
super(new ArrayList<>());
|
||||||
|
|
||||||
this.assertion = assertion;
|
this.assertion = assertion;
|
||||||
this.ticket = ticket;
|
this.ticket = ticket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Object getPrincipal() {
|
public Object getPrincipal() {
|
||||||
return this.assertion.getPrincipal().getName();
|
return this.assertion.getPrincipal().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Object getCredentials() {
|
public Object getCredentials() {
|
||||||
return this.ticket;
|
return this.ticket;
|
||||||
}
|
}
|
||||||
@@ -53,4 +56,5 @@ public final class CasAssertionAuthenticationToken extends AbstractAuthenticatio
|
|||||||
public Assertion getAssertion() {
|
public Assertion getAssertion() {
|
||||||
return this.assertion;
|
return this.assertion;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+58
-89
@@ -21,10 +21,12 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
import org.jasig.cas.client.validation.Assertion;
|
import org.jasig.cas.client.validation.Assertion;
|
||||||
import org.jasig.cas.client.validation.TicketValidationException;
|
import org.jasig.cas.client.validation.TicketValidationException;
|
||||||
import org.jasig.cas.client.validation.TicketValidator;
|
import org.jasig.cas.client.validation.TicketValidator;
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.MessageSource;
|
||||||
import org.springframework.context.MessageSourceAware;
|
import org.springframework.context.MessageSourceAware;
|
||||||
import org.springframework.context.support.MessageSourceAccessor;
|
import org.springframework.context.support.MessageSourceAccessor;
|
||||||
|
import org.springframework.core.log.LogMessage;
|
||||||
import org.springframework.security.authentication.AccountStatusUserDetailsChecker;
|
import org.springframework.security.authentication.AccountStatusUserDetailsChecker;
|
||||||
import org.springframework.security.authentication.AuthenticationProvider;
|
import org.springframework.security.authentication.AuthenticationProvider;
|
||||||
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
@@ -37,7 +39,11 @@ import org.springframework.security.core.AuthenticationException;
|
|||||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||||
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
|
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
|
||||||
import org.springframework.security.core.userdetails.*;
|
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsChecker;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,118 +60,93 @@ import org.springframework.util.Assert;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
* @author Scott Battaglia
|
* @author Scott Battaglia
|
||||||
*/
|
*/
|
||||||
public class CasAuthenticationProvider implements AuthenticationProvider,
|
public class CasAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
|
||||||
InitializingBean, MessageSourceAware {
|
|
||||||
// ~ Static fields/initializers
|
|
||||||
// =====================================================================================
|
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class);
|
private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class);
|
||||||
|
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
|
|
||||||
private AuthenticationUserDetailsService<CasAssertionAuthenticationToken> authenticationUserDetailsService;
|
private AuthenticationUserDetailsService<CasAssertionAuthenticationToken> authenticationUserDetailsService;
|
||||||
|
|
||||||
private final UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
|
private final UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
|
||||||
|
|
||||||
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
|
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
|
||||||
|
|
||||||
private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache();
|
private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache();
|
||||||
|
|
||||||
private String key;
|
private String key;
|
||||||
|
|
||||||
private TicketValidator ticketValidator;
|
private TicketValidator ticketValidator;
|
||||||
|
|
||||||
private ServiceProperties serviceProperties;
|
private ServiceProperties serviceProperties;
|
||||||
|
|
||||||
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
|
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
|
||||||
|
|
||||||
// ~ Methods
|
@Override
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
public void afterPropertiesSet() {
|
public void afterPropertiesSet() {
|
||||||
Assert.notNull(this.authenticationUserDetailsService,
|
Assert.notNull(this.authenticationUserDetailsService, "An authenticationUserDetailsService must be set");
|
||||||
"An authenticationUserDetailsService must be set");
|
|
||||||
Assert.notNull(this.ticketValidator, "A ticketValidator must be set");
|
Assert.notNull(this.ticketValidator, "A ticketValidator must be set");
|
||||||
Assert.notNull(this.statelessTicketCache, "A statelessTicketCache must be set");
|
Assert.notNull(this.statelessTicketCache, "A statelessTicketCache must be set");
|
||||||
Assert.hasText(
|
Assert.hasText(this.key,
|
||||||
this.key,
|
|
||||||
"A Key is required so CasAuthenticationProvider can identify tokens it previously authenticated");
|
"A Key is required so CasAuthenticationProvider can identify tokens it previously authenticated");
|
||||||
Assert.notNull(this.messages, "A message source must be set");
|
Assert.notNull(this.messages, "A message source must be set");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Authentication authenticate(Authentication authentication)
|
@Override
|
||||||
throws AuthenticationException {
|
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||||
if (!supports(authentication.getClass())) {
|
if (!supports(authentication.getClass())) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (authentication instanceof UsernamePasswordAuthenticationToken
|
if (authentication instanceof UsernamePasswordAuthenticationToken
|
||||||
&& (!CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER
|
&& (!CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER.equals(authentication.getPrincipal().toString())
|
||||||
.equals(authentication.getPrincipal().toString()) && !CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER
|
&& !CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER
|
||||||
.equals(authentication.getPrincipal().toString()))) {
|
.equals(authentication.getPrincipal().toString()))) {
|
||||||
// UsernamePasswordAuthenticationToken not CAS related
|
// UsernamePasswordAuthenticationToken not CAS related
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If an existing CasAuthenticationToken, just check we created it
|
// If an existing CasAuthenticationToken, just check we created it
|
||||||
if (authentication instanceof CasAuthenticationToken) {
|
if (authentication instanceof CasAuthenticationToken) {
|
||||||
if (this.key.hashCode() == ((CasAuthenticationToken) authentication)
|
if (this.key.hashCode() != ((CasAuthenticationToken) authentication).getKeyHash()) {
|
||||||
.getKeyHash()) {
|
throw new BadCredentialsException(this.messages.getMessage("CasAuthenticationProvider.incorrectKey",
|
||||||
return authentication;
|
"The presented CasAuthenticationToken does not contain the expected key"));
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new BadCredentialsException(
|
|
||||||
messages.getMessage("CasAuthenticationProvider.incorrectKey",
|
|
||||||
"The presented CasAuthenticationToken does not contain the expected key"));
|
|
||||||
}
|
}
|
||||||
|
return authentication;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure credentials are presented
|
// Ensure credentials are presented
|
||||||
if ((authentication.getCredentials() == null)
|
if ((authentication.getCredentials() == null) || "".equals(authentication.getCredentials())) {
|
||||||
|| "".equals(authentication.getCredentials())) {
|
throw new BadCredentialsException(this.messages.getMessage("CasAuthenticationProvider.noServiceTicket",
|
||||||
throw new BadCredentialsException(messages.getMessage(
|
|
||||||
"CasAuthenticationProvider.noServiceTicket",
|
|
||||||
"Failed to provide a CAS service ticket to validate"));
|
"Failed to provide a CAS service ticket to validate"));
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean stateless = false;
|
boolean stateless = (authentication instanceof UsernamePasswordAuthenticationToken
|
||||||
|
&& CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER.equals(authentication.getPrincipal()));
|
||||||
if (authentication instanceof UsernamePasswordAuthenticationToken
|
|
||||||
&& CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER.equals(authentication
|
|
||||||
.getPrincipal())) {
|
|
||||||
stateless = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CasAuthenticationToken result = null;
|
CasAuthenticationToken result = null;
|
||||||
|
|
||||||
if (stateless) {
|
if (stateless) {
|
||||||
// Try to obtain from cache
|
// Try to obtain from cache
|
||||||
result = statelessTicketCache.getByTicketId(authentication.getCredentials()
|
result = this.statelessTicketCache.getByTicketId(authentication.getCredentials().toString());
|
||||||
.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
result = this.authenticateNow(authentication);
|
result = this.authenticateNow(authentication);
|
||||||
result.setDetails(authentication.getDetails());
|
result.setDetails(authentication.getDetails());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stateless) {
|
if (stateless) {
|
||||||
// Add to cache
|
// Add to cache
|
||||||
statelessTicketCache.putTicketInCache(result);
|
this.statelessTicketCache.putTicketInCache(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CasAuthenticationToken authenticateNow(final Authentication authentication)
|
private CasAuthenticationToken authenticateNow(final Authentication authentication) throws AuthenticationException {
|
||||||
throws AuthenticationException {
|
|
||||||
try {
|
try {
|
||||||
final Assertion assertion = this.ticketValidator.validate(authentication
|
Assertion assertion = this.ticketValidator.validate(authentication.getCredentials().toString(),
|
||||||
.getCredentials().toString(), getServiceUrl(authentication));
|
getServiceUrl(authentication));
|
||||||
final UserDetails userDetails = loadUserByAssertion(assertion);
|
UserDetails userDetails = loadUserByAssertion(assertion);
|
||||||
userDetailsChecker.check(userDetails);
|
this.userDetailsChecker.check(userDetails);
|
||||||
return new CasAuthenticationToken(this.key, userDetails,
|
return new CasAuthenticationToken(this.key, userDetails, authentication.getCredentials(),
|
||||||
authentication.getCredentials(),
|
this.authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), userDetails, assertion);
|
||||||
authoritiesMapper.mapAuthorities(userDetails.getAuthorities()),
|
|
||||||
userDetails, assertion);
|
|
||||||
}
|
}
|
||||||
catch (final TicketValidationException e) {
|
catch (TicketValidationException ex) {
|
||||||
throw new BadCredentialsException(e.getMessage(), e);
|
throw new BadCredentialsException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,30 +155,20 @@ public class CasAuthenticationProvider implements AuthenticationProvider,
|
|||||||
* {@link ServiceAuthenticationDetails}, then
|
* {@link ServiceAuthenticationDetails}, then
|
||||||
* {@link ServiceAuthenticationDetails#getServiceUrl()} is used. Otherwise, the
|
* {@link ServiceAuthenticationDetails#getServiceUrl()} is used. Otherwise, the
|
||||||
* {@link ServiceProperties#getService()} is used.
|
* {@link ServiceProperties#getService()} is used.
|
||||||
*
|
|
||||||
* @param authentication
|
* @param authentication
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private String getServiceUrl(Authentication authentication) {
|
private String getServiceUrl(Authentication authentication) {
|
||||||
String serviceUrl;
|
String serviceUrl;
|
||||||
if (authentication.getDetails() instanceof ServiceAuthenticationDetails) {
|
if (authentication.getDetails() instanceof ServiceAuthenticationDetails) {
|
||||||
serviceUrl = ((ServiceAuthenticationDetails) authentication.getDetails())
|
return ((ServiceAuthenticationDetails) authentication.getDetails()).getServiceUrl();
|
||||||
.getServiceUrl();
|
|
||||||
}
|
|
||||||
else if (serviceProperties == null) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"serviceProperties cannot be null unless Authentication.getDetails() implements ServiceAuthenticationDetails.");
|
|
||||||
}
|
|
||||||
else if (serviceProperties.getService() == null) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"serviceProperties.getService() cannot be null unless Authentication.getDetails() implements ServiceAuthenticationDetails.");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
serviceUrl = serviceProperties.getService();
|
|
||||||
}
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("serviceUrl = " + serviceUrl);
|
|
||||||
}
|
}
|
||||||
|
Assert.state(this.serviceProperties != null,
|
||||||
|
"serviceProperties cannot be null unless Authentication.getDetails() implements ServiceAuthenticationDetails.");
|
||||||
|
Assert.state(this.serviceProperties.getService() != null,
|
||||||
|
"serviceProperties.getService() cannot be null unless Authentication.getDetails() implements ServiceAuthenticationDetails.");
|
||||||
|
serviceUrl = this.serviceProperties.getService();
|
||||||
|
logger.debug(LogMessage.format("serviceUrl = %s", serviceUrl));
|
||||||
return serviceUrl;
|
return serviceUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,13 +176,11 @@ public class CasAuthenticationProvider implements AuthenticationProvider,
|
|||||||
* Template method for retrieving the UserDetails based on the assertion. Default is
|
* Template method for retrieving the UserDetails based on the assertion. Default is
|
||||||
* to call configured userDetailsService and pass the username. Deployers can override
|
* to call configured userDetailsService and pass the username. Deployers can override
|
||||||
* this method and retrieve the user based on any criteria they desire.
|
* this method and retrieve the user based on any criteria they desire.
|
||||||
*
|
|
||||||
* @param assertion The CAS Assertion.
|
* @param assertion The CAS Assertion.
|
||||||
* @return the UserDetails.
|
* @return the UserDetails.
|
||||||
*/
|
*/
|
||||||
protected UserDetails loadUserByAssertion(final Assertion assertion) {
|
protected UserDetails loadUserByAssertion(final Assertion assertion) {
|
||||||
final CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken(
|
final CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken(assertion, "");
|
||||||
assertion, "");
|
|
||||||
return this.authenticationUserDetailsService.loadUserDetails(token);
|
return this.authenticationUserDetailsService.loadUserDetails(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,8 +189,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider,
|
|||||||
* Sets the UserDetailsService to use. This is a convenience method to invoke
|
* Sets the UserDetailsService to use. This is a convenience method to invoke
|
||||||
*/
|
*/
|
||||||
public void setUserDetailsService(final UserDetailsService userDetailsService) {
|
public void setUserDetailsService(final UserDetailsService userDetailsService) {
|
||||||
this.authenticationUserDetailsService = new UserDetailsByNameServiceWrapper(
|
this.authenticationUserDetailsService = new UserDetailsByNameServiceWrapper(userDetailsService);
|
||||||
userDetailsService);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAuthenticationUserDetailsService(
|
public void setAuthenticationUserDetailsService(
|
||||||
@@ -234,7 +202,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider,
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected String getKey() {
|
protected String getKey() {
|
||||||
return key;
|
return this.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKey(String key) {
|
public void setKey(String key) {
|
||||||
@@ -242,13 +210,14 @@ public class CasAuthenticationProvider implements AuthenticationProvider,
|
|||||||
}
|
}
|
||||||
|
|
||||||
public StatelessTicketCache getStatelessTicketCache() {
|
public StatelessTicketCache getStatelessTicketCache() {
|
||||||
return statelessTicketCache;
|
return this.statelessTicketCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TicketValidator getTicketValidator() {
|
protected TicketValidator getTicketValidator() {
|
||||||
return ticketValidator;
|
return this.ticketValidator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setMessageSource(final MessageSource messageSource) {
|
public void setMessageSource(final MessageSource messageSource) {
|
||||||
this.messages = new MessageSourceAccessor(messageSource);
|
this.messages = new MessageSourceAccessor(messageSource);
|
||||||
}
|
}
|
||||||
@@ -265,11 +234,11 @@ public class CasAuthenticationProvider implements AuthenticationProvider,
|
|||||||
this.authoritiesMapper = authoritiesMapper;
|
this.authoritiesMapper = authoritiesMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean supports(final Class<?> authentication) {
|
public boolean supports(final Class<?> authentication) {
|
||||||
return (UsernamePasswordAuthenticationToken.class
|
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication))
|
||||||
.isAssignableFrom(authentication))
|
|
||||||
|| (CasAuthenticationToken.class.isAssignableFrom(authentication))
|
|| (CasAuthenticationToken.class.isAssignableFrom(authentication))
|
||||||
|| (CasAssertionAuthenticationToken.class
|
|| (CasAssertionAuthenticationToken.class.isAssignableFrom(authentication));
|
||||||
.isAssignableFrom(authentication));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+42
-59
@@ -20,11 +20,13 @@ import java.io.Serializable;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.jasig.cas.client.validation.Assertion;
|
import org.jasig.cas.client.validation.Assertion;
|
||||||
|
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a successful CAS <code>Authentication</code>.
|
* Represents a successful CAS <code>Authentication</code>.
|
||||||
@@ -32,80 +34,69 @@ import org.springframework.util.Assert;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
* @author Scott Battaglia
|
* @author Scott Battaglia
|
||||||
*/
|
*/
|
||||||
public class CasAuthenticationToken extends AbstractAuthenticationToken implements
|
public class CasAuthenticationToken extends AbstractAuthenticationToken implements Serializable {
|
||||||
Serializable {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||||
|
|
||||||
// ~ Instance fields
|
|
||||||
// ================================================================================================
|
|
||||||
private final Object credentials;
|
private final Object credentials;
|
||||||
private final Object principal;
|
|
||||||
private final UserDetails userDetails;
|
|
||||||
private final int keyHash;
|
|
||||||
private final Assertion assertion;
|
|
||||||
|
|
||||||
// ~ Constructors
|
private final Object principal;
|
||||||
// ===================================================================================================
|
|
||||||
|
private final UserDetails userDetails;
|
||||||
|
|
||||||
|
private final int keyHash;
|
||||||
|
|
||||||
|
private final Assertion assertion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
* @param key to identify if this object made by a given
|
||||||
* @param key to identify if this object made by a given
|
* {@link CasAuthenticationProvider}
|
||||||
* {@link CasAuthenticationProvider}
|
* @param principal typically the UserDetails object (cannot be <code>null</code>)
|
||||||
* @param principal typically the UserDetails object (cannot be <code>null</code>)
|
|
||||||
* @param credentials the service/proxy ticket ID from CAS (cannot be
|
* @param credentials the service/proxy ticket ID from CAS (cannot be
|
||||||
* <code>null</code>)
|
* <code>null</code>)
|
||||||
* @param authorities the authorities granted to the user (from the
|
* @param authorities the authorities granted to the user (from the
|
||||||
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
|
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
|
||||||
* be <code>null</code>)
|
* be <code>null</code>)
|
||||||
* @param userDetails the user details (from the
|
* @param userDetails the user details (from the
|
||||||
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
|
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
|
||||||
* be <code>null</code>)
|
* be <code>null</code>)
|
||||||
* @param assertion the assertion returned from the CAS servers. It contains the
|
* @param assertion the assertion returned from the CAS servers. It contains the
|
||||||
* principal and how to obtain a proxy ticket for the user.
|
* principal and how to obtain a proxy ticket for the user.
|
||||||
* @throws IllegalArgumentException if a <code>null</code> was passed
|
* @throws IllegalArgumentException if a <code>null</code> was passed
|
||||||
*/
|
*/
|
||||||
public CasAuthenticationToken(final String key, final Object principal,
|
public CasAuthenticationToken(final String key, final Object principal, final Object credentials,
|
||||||
final Object credentials,
|
final Collection<? extends GrantedAuthority> authorities, final UserDetails userDetails,
|
||||||
final Collection<? extends GrantedAuthority> authorities,
|
final Assertion assertion) {
|
||||||
final UserDetails userDetails, final Assertion assertion) {
|
|
||||||
this(extractKeyHash(key), principal, credentials, authorities, userDetails, assertion);
|
this(extractKeyHash(key), principal, credentials, authorities, userDetails, assertion);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private constructor for Jackson Deserialization support
|
* Private constructor for Jackson Deserialization support
|
||||||
*
|
* @param keyHash hashCode of provided key to identify if this object made by a given
|
||||||
* @param keyHash hashCode of provided key to identify if this object made by a given
|
* {@link CasAuthenticationProvider}
|
||||||
* {@link CasAuthenticationProvider}
|
* @param principal typically the UserDetails object (cannot be <code>null</code>)
|
||||||
* @param principal typically the UserDetails object (cannot be <code>null</code>)
|
|
||||||
* @param credentials the service/proxy ticket ID from CAS (cannot be
|
* @param credentials the service/proxy ticket ID from CAS (cannot be
|
||||||
* <code>null</code>)
|
* <code>null</code>)
|
||||||
* @param authorities the authorities granted to the user (from the
|
* @param authorities the authorities granted to the user (from the
|
||||||
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
|
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
|
||||||
* be <code>null</code>)
|
* be <code>null</code>)
|
||||||
* @param userDetails the user details (from the
|
* @param userDetails the user details (from the
|
||||||
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
|
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
|
||||||
* be <code>null</code>)
|
* be <code>null</code>)
|
||||||
* @param assertion the assertion returned from the CAS servers. It contains the
|
* @param assertion the assertion returned from the CAS servers. It contains the
|
||||||
* principal and how to obtain a proxy ticket for the user.
|
* principal and how to obtain a proxy ticket for the user.
|
||||||
* @throws IllegalArgumentException if a <code>null</code> was passed
|
* @throws IllegalArgumentException if a <code>null</code> was passed
|
||||||
* @since 4.2
|
* @since 4.2
|
||||||
*/
|
*/
|
||||||
private CasAuthenticationToken(final Integer keyHash, final Object principal,
|
private CasAuthenticationToken(final Integer keyHash, final Object principal, final Object credentials,
|
||||||
final Object credentials,
|
final Collection<? extends GrantedAuthority> authorities, final UserDetails userDetails,
|
||||||
final Collection<? extends GrantedAuthority> authorities,
|
final Assertion assertion) {
|
||||||
final UserDetails userDetails, final Assertion assertion) {
|
|
||||||
super(authorities);
|
super(authorities);
|
||||||
|
if ((principal == null) || "".equals(principal) || (credentials == null) || "".equals(credentials)
|
||||||
if ((principal == null)
|
|| (authorities == null) || (userDetails == null) || (assertion == null)) {
|
||||||
|| "".equals(principal) || (credentials == null)
|
throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
|
||||||
|| "".equals(credentials) || (authorities == null)
|
|
||||||
|| (userDetails == null) || (assertion == null)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Cannot pass null or empty values to constructor");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.keyHash = keyHash;
|
this.keyHash = keyHash;
|
||||||
this.principal = principal;
|
this.principal = principal;
|
||||||
this.credentials = credentials;
|
this.credentials = credentials;
|
||||||
@@ -114,9 +105,6 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
|
|||||||
setAuthenticated(true);
|
setAuthenticated(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~ Methods
|
|
||||||
// ========================================================================================================
|
|
||||||
|
|
||||||
private static Integer extractKeyHash(String key) {
|
private static Integer extractKeyHash(String key) {
|
||||||
Assert.hasLength(key, "key cannot be null or empty");
|
Assert.hasLength(key, "key cannot be null or empty");
|
||||||
return key.hashCode();
|
return key.hashCode();
|
||||||
@@ -127,21 +115,16 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
|
|||||||
if (!super.equals(obj)) {
|
if (!super.equals(obj)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj instanceof CasAuthenticationToken) {
|
if (obj instanceof CasAuthenticationToken) {
|
||||||
CasAuthenticationToken test = (CasAuthenticationToken) obj;
|
CasAuthenticationToken test = (CasAuthenticationToken) obj;
|
||||||
|
|
||||||
if (!this.assertion.equals(test.getAssertion())) {
|
if (!this.assertion.equals(test.getAssertion())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.getKeyHash() != test.getKeyHash()) {
|
if (this.getKeyHash() != test.getKeyHash()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +135,7 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
|
|||||||
result = 31 * result + this.principal.hashCode();
|
result = 31 * result + this.principal.hashCode();
|
||||||
result = 31 * result + this.userDetails.hashCode();
|
result = 31 * result + this.userDetails.hashCode();
|
||||||
result = 31 * result + this.keyHash;
|
result = 31 * result + this.keyHash;
|
||||||
result = 31 * result + (this.assertion != null ? this.assertion.hashCode() : 0);
|
result = 31 * result + ObjectUtils.nullSafeHashCode(this.assertion);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +158,7 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
public UserDetails getUserDetails() {
|
public UserDetails getUserDetails() {
|
||||||
return userDetails;
|
return this.userDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -184,7 +167,7 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
|
|||||||
sb.append(super.toString());
|
sb.append(super.toString());
|
||||||
sb.append(" Assertion: ").append(this.assertion);
|
sb.append(" Assertion: ").append(this.assertion);
|
||||||
sb.append(" Credentials (Service/Proxy Ticket): ").append(this.credentials);
|
sb.append(" Credentials (Service/Proxy Ticket): ").append(this.credentials);
|
||||||
|
|
||||||
return (sb.toString());
|
return (sb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user