Browse Source
Prior to this commit, the ObjectIdentity id had to be a number. This commit allows for domain objects to use UUIDs as their identifier. The fully qualified class name of the identifier type can be specified in the acl_object_identity table and a ConversionService can be provided to BasicLookupStrategy to convert from String to the actual identifier type. There are the following other changes: - BasicLookupStrategy has a new property, aclClassIdSupported, which is used to retrieve the new column from the database. This preserves backwards-compatibility, as it is false by default. - JdbcMutableAclService has the same property, aclClassIdSupported, which is needed to modify the insert statement to write to the new column. Defaults to false for backwards-compatibility. - Tests have been updated to verify both the existing functionality for backwards-compatibility and the new functionality. Fixes gh-1224pull/4424/merge
22 changed files with 1200 additions and 368 deletions
@ -0,0 +1,125 @@
@@ -0,0 +1,125 @@
|
||||
/* |
||||
* Copyright 2002-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.security.acls.jdbc; |
||||
|
||||
import java.io.Serializable; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import org.springframework.core.convert.ConversionService; |
||||
import org.springframework.security.acls.model.ObjectIdentity; |
||||
|
||||
/** |
||||
* Utility class for helping convert database representations of {@link ObjectIdentity#getIdentifier()} into |
||||
* the correct Java type as specified by <code>acl_class.class_id_type</code>. |
||||
* @author paulwheeler |
||||
*/ |
||||
class AclClassIdUtils { |
||||
private static final String DEFAULT_CLASS_ID_TYPE_COLUMN_NAME = "class_id_type"; |
||||
private static final Log log = LogFactory.getLog(AclClassIdUtils.class); |
||||
|
||||
private ConversionService conversionService; |
||||
|
||||
public 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 |
||||
* it could be String. |
||||
* @param identifier The identifier from the database |
||||
* @param resultSet Result set of the query |
||||
* @return The identifier in the appropriate target Java type. Typically Long or UUID. |
||||
* @throws SQLException |
||||
*/ |
||||
Serializable identifierFrom(Serializable identifier, ResultSet resultSet) throws SQLException { |
||||
if (isString(identifier) && hasValidClassIdType(resultSet) |
||||
&& canConvertFromStringTo(classIdTypeFrom(resultSet))) { |
||||
|
||||
identifier = convertFromStringTo((String) identifier, classIdTypeFrom(resultSet)); |
||||
} else { |
||||
// Assume it should be a Long type
|
||||
identifier = convertToLong(identifier); |
||||
} |
||||
|
||||
return identifier; |
||||
} |
||||
|
||||
private boolean hasValidClassIdType(ResultSet resultSet) throws SQLException { |
||||
boolean hasClassIdType = false; |
||||
try { |
||||
hasClassIdType = classIdTypeFrom(resultSet) != null; |
||||
} catch (SQLException e) { |
||||
log.debug("Unable to obtain the class id type", e); |
||||
} |
||||
return hasClassIdType; |
||||
} |
||||
|
||||
private <T extends Serializable> Class<T> classIdTypeFrom(ResultSet resultSet) throws SQLException { |
||||
return classIdTypeFrom(resultSet.getString(DEFAULT_CLASS_ID_TYPE_COLUMN_NAME)); |
||||
} |
||||
|
||||
private <T extends Serializable> Class<T> classIdTypeFrom(String className) { |
||||
Class targetType = null; |
||||
if (className != null) { |
||||
try { |
||||
targetType = Class.forName(className); |
||||
} catch (ClassNotFoundException e) { |
||||
log.debug("Unable to find class id type on classpath", e); |
||||
} |
||||
} |
||||
return targetType; |
||||
} |
||||
|
||||
private <T> boolean canConvertFromStringTo(Class<T> targetType) { |
||||
return hasConversionService() && conversionService.canConvert(String.class, targetType); |
||||
} |
||||
|
||||
private <T extends Serializable> T convertFromStringTo(String identifier, Class<T> targetType) { |
||||
return conversionService.convert(identifier, targetType); |
||||
} |
||||
|
||||
private boolean hasConversionService() { |
||||
return conversionService != null; |
||||
} |
||||
|
||||
/** |
||||
* Converts to a {@link Long}, attempting to use the {@link ConversionService} if available. |
||||
* @param identifier The identifier |
||||
* @return Long version of the identifier |
||||
* @throws NumberFormatException if the string cannot be parsed to a long. |
||||
* @throws org.springframework.core.convert.ConversionException if a conversion exception occurred |
||||
* @throws IllegalArgumentException if targetType is null |
||||
*/ |
||||
private Long convertToLong(Serializable identifier) { |
||||
Long idAsLong; |
||||
if (hasConversionService()) { |
||||
idAsLong = conversionService.convert(identifier, Long.class); |
||||
} else { |
||||
idAsLong = Long.valueOf(identifier.toString()); |
||||
} |
||||
return idAsLong; |
||||
} |
||||
|
||||
private boolean isString(Serializable object) { |
||||
return object.getClass().isAssignableFrom(String.class); |
||||
} |
||||
|
||||
public void setConversionService(ConversionService conversionService) { |
||||
this.conversionService = conversionService; |
||||
} |
||||
} |
||||
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
-- ACL schema sql used in HSQLDB |
||||
|
||||
-- drop table acl_entry; |
||||
-- drop table acl_object_identity; |
||||
-- drop table acl_class; |
||||
-- drop table acl_sid; |
||||
|
||||
create table acl_sid( |
||||
id bigint generated by default as identity(start with 100) not null primary key, |
||||
principal boolean not null, |
||||
sid varchar_ignorecase(100) not null, |
||||
constraint unique_uk_1 unique(sid,principal) |
||||
); |
||||
|
||||
create table acl_class( |
||||
id bigint generated by default as identity(start with 100) not null primary key, |
||||
class varchar_ignorecase(100) not null, |
||||
class_id_type varchar_ignorecase(100), |
||||
constraint unique_uk_2 unique(class) |
||||
); |
||||
|
||||
create table acl_object_identity( |
||||
id bigint generated by default as identity(start with 100) not null primary key, |
||||
object_id_class bigint not null, |
||||
object_id_identity varchar_ignorecase(36) not null, |
||||
parent_object bigint, |
||||
owner_sid bigint, |
||||
entries_inheriting boolean not null, |
||||
constraint unique_uk_3 unique(object_id_class,object_id_identity), |
||||
constraint foreign_fk_1 foreign key(parent_object)references acl_object_identity(id), |
||||
constraint foreign_fk_2 foreign key(object_id_class)references acl_class(id), |
||||
constraint foreign_fk_3 foreign key(owner_sid)references acl_sid(id) |
||||
); |
||||
|
||||
create table acl_entry( |
||||
id bigint generated by default as identity(start with 100) not null primary key, |
||||
acl_object_identity bigint not null, |
||||
ace_order int not null, |
||||
sid bigint not null, |
||||
mask integer not null, |
||||
granting boolean not null, |
||||
audit_success boolean not null, |
||||
audit_failure boolean not null, |
||||
constraint unique_uk_4 unique(acl_object_identity,ace_order), |
||||
constraint foreign_fk_4 foreign key(acl_object_identity) references acl_object_identity(id), |
||||
constraint foreign_fk_5 foreign key(sid) references acl_sid(id) |
||||
); |
||||
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
/* |
||||
* Copyright 2002-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.security.acls; |
||||
|
||||
import java.util.UUID; |
||||
|
||||
/** |
||||
* Dummy domain object class with a {@link UUID} for the Id. |
||||
* |
||||
* @author Luke Taylor |
||||
*/ |
||||
public final class TargetObjectWithUUID { |
||||
|
||||
private UUID id; |
||||
|
||||
public UUID getId() { |
||||
return id; |
||||
} |
||||
|
||||
public void setId(UUID id) { |
||||
this.id = id; |
||||
} |
||||
} |
||||
@ -0,0 +1,341 @@
@@ -0,0 +1,341 @@
|
||||
/* |
||||
* Copyright 2002-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.security.acls.jdbc; |
||||
|
||||
import static org.assertj.core.api.Assertions.*; |
||||
|
||||
import net.sf.ehcache.Cache; |
||||
import net.sf.ehcache.CacheManager; |
||||
import net.sf.ehcache.Ehcache; |
||||
|
||||
import org.junit.*; |
||||
import org.springframework.jdbc.core.JdbcTemplate; |
||||
import org.springframework.security.acls.TargetObject; |
||||
import org.springframework.security.acls.TargetObjectWithUUID; |
||||
import org.springframework.security.acls.domain.*; |
||||
import org.springframework.security.acls.model.Acl; |
||||
import org.springframework.security.acls.model.AuditableAccessControlEntry; |
||||
import org.springframework.security.acls.model.MutableAcl; |
||||
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.Sid; |
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority; |
||||
|
||||
import java.util.*; |
||||
|
||||
import javax.sql.DataSource; |
||||
|
||||
/** |
||||
* Tests {@link BasicLookupStrategy} |
||||
* |
||||
* @author Andrei Stefan |
||||
*/ |
||||
public abstract class AbstractBasicLookupStrategyTests { |
||||
|
||||
protected static final Sid BEN_SID = new PrincipalSid("ben"); |
||||
protected static final String TARGET_CLASS = TargetObject.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 Long OBJECT_IDENTITY_LONG_AS_UUID = 110L; |
||||
|
||||
// ~ Instance fields
|
||||
// ================================================================================================
|
||||
|
||||
private BasicLookupStrategy strategy; |
||||
private static CacheManager cacheManager; |
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
public abstract JdbcTemplate getJdbcTemplate(); |
||||
|
||||
public abstract DataSource getDataSource(); |
||||
|
||||
@BeforeClass |
||||
public static void initCacheManaer() { |
||||
cacheManager = CacheManager.create(); |
||||
cacheManager.addCache(new Cache("basiclookuptestcache", 500, false, false, 30, 30)); |
||||
} |
||||
|
||||
@AfterClass |
||||
public static void shutdownCacheManager() { |
||||
cacheManager.removalAll(); |
||||
cacheManager.shutdown(); |
||||
} |
||||
|
||||
@Before |
||||
public void populateDatabase() { |
||||
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_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 (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 (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 (4,3,0,1,8,0,0,0);"; |
||||
getJdbcTemplate().execute(query); |
||||
} |
||||
|
||||
@Before |
||||
public void initializeBeans() { |
||||
strategy = new BasicLookupStrategy(getDataSource(), aclCache(), aclAuthStrategy(), |
||||
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger())); |
||||
strategy.setPermissionFactory(new DefaultPermissionFactory()); |
||||
} |
||||
|
||||
protected AclAuthorizationStrategy aclAuthStrategy() { |
||||
return new AclAuthorizationStrategyImpl( |
||||
new SimpleGrantedAuthority("ROLE_ADMINISTRATOR")); |
||||
} |
||||
|
||||
protected EhCacheBasedAclCache aclCache() { |
||||
return new EhCacheBasedAclCache(getCache(), |
||||
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), |
||||
new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER"))); |
||||
} |
||||
|
||||
|
||||
@After |
||||
public void emptyDatabase() { |
||||
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 = 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 = 2;" + "DELETE FROM acl_object_identity WHERE ID = 1;" |
||||
+ "DELETE FROM acl_class;" + "DELETE FROM acl_sid;"; |
||||
getJdbcTemplate().execute(query); |
||||
} |
||||
|
||||
protected Ehcache getCache() { |
||||
Ehcache cache = cacheManager.getCache("basiclookuptestcache"); |
||||
cache.removeAll(); |
||||
return cache; |
||||
} |
||||
|
||||
@Test |
||||
public void testAclsRetrievalWithDefaultBatchSize() throws Exception { |
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(100)); |
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(101)); |
||||
// Deliberately use an integer for the child, to reproduce bug report in SEC-819
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(102)); |
||||
|
||||
Map<ObjectIdentity, Acl> map = this.strategy |
||||
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null); |
||||
checkEntries(topParentOid, middleParentOid, childOid, map); |
||||
} |
||||
|
||||
@Test |
||||
public void testAclsRetrievalFromCacheOnly() throws Exception { |
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(100)); |
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(101)); |
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(102)); |
||||
|
||||
// Objects were put in cache
|
||||
strategy.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null); |
||||
|
||||
// Let's empty the database to force acls retrieval from cache
|
||||
emptyDatabase(); |
||||
Map<ObjectIdentity, Acl> map = this.strategy |
||||
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null); |
||||
|
||||
checkEntries(topParentOid, middleParentOid, childOid, map); |
||||
} |
||||
|
||||
@Test |
||||
public void testAclsRetrievalWithCustomBatchSize() throws Exception { |
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(100)); |
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(101)); |
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(102)); |
||||
|
||||
// Set a batch size to allow multiple database queries in order to retrieve all
|
||||
// acls
|
||||
this.strategy.setBatchSize(1); |
||||
Map<ObjectIdentity, Acl> map = this.strategy |
||||
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null); |
||||
checkEntries(topParentOid, middleParentOid, childOid, map); |
||||
} |
||||
|
||||
private void checkEntries(ObjectIdentity topParentOid, ObjectIdentity middleParentOid, ObjectIdentity childOid, |
||||
Map<ObjectIdentity, Acl> map) throws Exception { |
||||
assertThat(map).hasSize(3); |
||||
|
||||
MutableAcl topParent = (MutableAcl) map.get(topParentOid); |
||||
MutableAcl middleParent = (MutableAcl) map.get(middleParentOid); |
||||
MutableAcl child = (MutableAcl) map.get(childOid); |
||||
|
||||
// Check the retrieved versions has IDs
|
||||
assertThat(topParent.getId()).isNotNull(); |
||||
assertThat(middleParent.getId()).isNotNull(); |
||||
assertThat(child.getId()).isNotNull(); |
||||
|
||||
// Check their parents were correctly retrieved
|
||||
assertThat(topParent.getParentAcl()).isNull(); |
||||
assertThat(middleParent.getParentAcl().getObjectIdentity()).isEqualTo(topParentOid); |
||||
assertThat(child.getParentAcl().getObjectIdentity()).isEqualTo(middleParentOid); |
||||
|
||||
// Check their ACEs were correctly retrieved
|
||||
assertThat(topParent.getEntries()).hasSize(2); |
||||
assertThat(middleParent.getEntries()).hasSize(1); |
||||
assertThat(child.getEntries()).hasSize(1); |
||||
|
||||
// Check object identities were correctly retrieved
|
||||
assertThat(topParent.getObjectIdentity()).isEqualTo(topParentOid); |
||||
assertThat(middleParent.getObjectIdentity()).isEqualTo(middleParentOid); |
||||
assertThat(child.getObjectIdentity()).isEqualTo(childOid); |
||||
|
||||
// Check each entry
|
||||
assertThat(topParent.isEntriesInheriting()).isTrue(); |
||||
assertThat(Long.valueOf(1)).isEqualTo(topParent.getId()); |
||||
assertThat(new PrincipalSid("ben")).isEqualTo(topParent.getOwner()); |
||||
assertThat(Long.valueOf(1)).isEqualTo(topParent.getEntries().get(0).getId()); |
||||
assertThat(topParent.getEntries().get(0).getPermission()).isEqualTo(BasePermission.READ); |
||||
assertThat(topParent.getEntries().get(0).getSid()).isEqualTo(new PrincipalSid("ben")); |
||||
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isAuditFailure()).isFalse(); |
||||
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isAuditSuccess()).isFalse(); |
||||
assertThat((topParent.getEntries().get(0)).isGranting()).isTrue(); |
||||
|
||||
assertThat(Long.valueOf(2)).isEqualTo(topParent.getEntries().get(1).getId()); |
||||
assertThat(topParent.getEntries().get(1).getPermission()).isEqualTo(BasePermission.WRITE); |
||||
assertThat(topParent.getEntries().get(1).getSid()).isEqualTo(new PrincipalSid("ben")); |
||||
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isAuditFailure()).isFalse(); |
||||
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isAuditSuccess()).isFalse(); |
||||
assertThat(topParent.getEntries().get(1).isGranting()).isFalse(); |
||||
|
||||
assertThat(middleParent.isEntriesInheriting()).isTrue(); |
||||
assertThat(Long.valueOf(2)).isEqualTo(middleParent.getId()); |
||||
assertThat(new PrincipalSid("ben")).isEqualTo(middleParent.getOwner()); |
||||
assertThat(Long.valueOf(3)).isEqualTo(middleParent.getEntries().get(0).getId()); |
||||
assertThat(middleParent.getEntries().get(0).getPermission()).isEqualTo(BasePermission.DELETE); |
||||
assertThat(middleParent.getEntries().get(0).getSid()).isEqualTo(new PrincipalSid("ben")); |
||||
assertThat(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isAuditFailure()).isFalse(); |
||||
assertThat(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isAuditSuccess()).isFalse(); |
||||
assertThat(middleParent.getEntries().get(0).isGranting()).isTrue(); |
||||
|
||||
assertThat(child.isEntriesInheriting()).isTrue(); |
||||
assertThat(Long.valueOf(3)).isEqualTo(child.getId()); |
||||
assertThat(new PrincipalSid("ben")).isEqualTo(child.getOwner()); |
||||
assertThat(Long.valueOf(4)).isEqualTo(child.getEntries().get(0).getId()); |
||||
assertThat(child.getEntries().get(0).getPermission()).isEqualTo(BasePermission.DELETE); |
||||
assertThat(new PrincipalSid("ben")).isEqualTo(child.getEntries().get(0).getSid()); |
||||
assertThat(((AuditableAccessControlEntry) child.getEntries().get(0)).isAuditFailure()).isFalse(); |
||||
assertThat(((AuditableAccessControlEntry) child.getEntries().get(0)).isAuditSuccess()).isFalse(); |
||||
assertThat((child.getEntries().get(0)).isGranting()).isFalse(); |
||||
} |
||||
|
||||
@Test |
||||
public void testAllParentsAreRetrievedWhenChildIsLoaded() throws Exception { |
||||
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); |
||||
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100)); |
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(101)); |
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(102)); |
||||
ObjectIdentity middleParent2Oid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(103)); |
||||
|
||||
// Retrieve the child
|
||||
Map<ObjectIdentity, Acl> map = this.strategy.readAclsById(Arrays.asList(childOid), null); |
||||
|
||||
// Check that the child and all its parents were retrieved
|
||||
assertThat(map.get(childOid)).isNotNull(); |
||||
assertThat(map.get(childOid).getObjectIdentity()).isEqualTo(childOid); |
||||
assertThat(map.get(middleParentOid)).isNotNull(); |
||||
assertThat(map.get(middleParentOid).getObjectIdentity()).isEqualTo(middleParentOid); |
||||
assertThat(map.get(topParentOid)).isNotNull(); |
||||
assertThat(map.get(topParentOid).getObjectIdentity()).isEqualTo(topParentOid); |
||||
|
||||
// The second parent shouldn't have been retrieved
|
||||
assertThat(map.get(middleParent2Oid)).isNull(); |
||||
} |
||||
|
||||
/** |
||||
* Test created from SEC-590. |
||||
*/ |
||||
@Test |
||||
public void testReadAllObjectIdentitiesWhenLastElementIsAlreadyCached() throws Exception { |
||||
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 (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_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); |
||||
|
||||
ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(104)); |
||||
ObjectIdentity parent1Oid = new ObjectIdentityImpl(TARGET_CLASS, new Long(105)); |
||||
ObjectIdentity parent2Oid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(106)); |
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(107)); |
||||
|
||||
// First lookup only child, thus populating the cache with grandParent,
|
||||
// parent1
|
||||
// and child
|
||||
List<Permission> checkPermission = Arrays.asList(BasePermission.READ); |
||||
List<Sid> sids = Arrays.asList(BEN_SID); |
||||
List<ObjectIdentity> childOids = Arrays.asList(childOid); |
||||
|
||||
strategy.setBatchSize(6); |
||||
Map<ObjectIdentity, Acl> foundAcls = strategy.readAclsById(childOids, sids); |
||||
|
||||
Acl foundChildAcl = foundAcls.get(childOid); |
||||
assertThat(foundChildAcl).isNotNull(); |
||||
assertThat(foundChildAcl.isGranted(checkPermission, sids, false)).isTrue(); |
||||
|
||||
// Search for object identities has to be done in the following order:
|
||||
// last
|
||||
// element have to be one which
|
||||
// is already in cache and the element before it must not be stored in
|
||||
// cache
|
||||
List<ObjectIdentity> allOids = Arrays.asList(grandParentOid, parent1Oid, parent2Oid, childOid); |
||||
try { |
||||
foundAcls = strategy.readAclsById(allOids, sids); |
||||
|
||||
} catch (NotFoundException notExpected) { |
||||
fail("It shouldn't have thrown NotFoundException"); |
||||
} |
||||
|
||||
Acl foundParent2Acl = foundAcls.get(parent2Oid); |
||||
assertThat(foundParent2Acl).isNotNull(); |
||||
assertThat(foundParent2Acl.isGranted(checkPermission, sids, false)).isTrue(); |
||||
} |
||||
|
||||
@Test(expected = IllegalArgumentException.class) |
||||
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);"; |
||||
|
||||
getJdbcTemplate().execute(query); |
||||
|
||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, new Long(104)); |
||||
|
||||
strategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID)); |
||||
} |
||||
|
||||
@Test |
||||
public void testCreatePrincipalSid() { |
||||
Sid result = strategy.createSid(true, "sid"); |
||||
|
||||
assertThat(result.getClass()).isEqualTo(PrincipalSid.class); |
||||
assertThat(((PrincipalSid) result).getPrincipal()).isEqualTo("sid"); |
||||
} |
||||
|
||||
@Test |
||||
public void testCreateGrantedAuthority() { |
||||
Sid result = strategy.createSid(false, "sid"); |
||||
|
||||
assertThat(result.getClass()).isEqualTo(GrantedAuthoritySid.class); |
||||
assertThat(((GrantedAuthoritySid) result).getGrantedAuthority()).isEqualTo("sid"); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,160 @@
@@ -0,0 +1,160 @@
|
||||
/* |
||||
* Copyright 2002-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.security.acls.jdbc; |
||||
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.mockito.BDDMockito.given; |
||||
|
||||
import java.io.Serializable; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.util.UUID; |
||||
|
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.mockito.InjectMocks; |
||||
import org.mockito.Mock; |
||||
import org.mockito.runners.MockitoJUnitRunner; |
||||
import org.springframework.core.convert.ConversionService; |
||||
|
||||
/** |
||||
* Tests for {@link AclClassIdUtils}. |
||||
* @author paulwheeler |
||||
*/ |
||||
@RunWith(MockitoJUnitRunner.class) |
||||
public class AclClassIdUtilsTest { |
||||
|
||||
private static final Long DEFAULT_IDENTIFIER = 999L; |
||||
private static final String DEFAULT_IDENTIFIER_AS_STRING = DEFAULT_IDENTIFIER.toString(); |
||||
|
||||
@Mock |
||||
private ResultSet resultSet; |
||||
@Mock |
||||
private ConversionService conversionService; |
||||
@InjectMocks |
||||
private AclClassIdUtils aclClassIdUtils; |
||||
|
||||
@Before |
||||
public void setUp() throws Exception { |
||||
given(conversionService.canConvert(String.class, Long.class)).willReturn(true); |
||||
given(conversionService.convert(DEFAULT_IDENTIFIER, Long.class)).willReturn(new Long(DEFAULT_IDENTIFIER)); |
||||
given(conversionService.convert(DEFAULT_IDENTIFIER_AS_STRING, Long.class)).willReturn(new Long(DEFAULT_IDENTIFIER)); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldReturnLongIfIdentifierIsNotStringAndNoConversionService() throws SQLException { |
||||
// given
|
||||
AclClassIdUtils aclClassIdUtilsWithoutConversionSvc = new AclClassIdUtils(); |
||||
|
||||
// when
|
||||
Serializable newIdentifier = aclClassIdUtilsWithoutConversionSvc.identifierFrom(DEFAULT_IDENTIFIER, resultSet); |
||||
|
||||
// then
|
||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldReturnLongIfIdentifierIsNotString() throws SQLException { |
||||
// given
|
||||
Long prevIdentifier = 999L; |
||||
|
||||
// when
|
||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(prevIdentifier, resultSet); |
||||
|
||||
// then
|
||||
assertThat(newIdentifier).isEqualTo(prevIdentifier); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldReturnLongIfClassIdTypeIsNull() throws SQLException { |
||||
// given
|
||||
given(resultSet.getString("class_id_type")).willReturn(null); |
||||
|
||||
// when
|
||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, resultSet); |
||||
|
||||
// then
|
||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldReturnLongIfNoClassIdTypeColumn() throws SQLException { |
||||
// given
|
||||
given(resultSet.getString("class_id_type")).willThrow(SQLException.class); |
||||
|
||||
// when
|
||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, resultSet); |
||||
|
||||
// then
|
||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldReturnLongIfTypeClassNotFound() throws SQLException { |
||||
// given
|
||||
given(resultSet.getString("class_id_type")).willReturn("com.example.UnknownType"); |
||||
|
||||
// when
|
||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, resultSet); |
||||
|
||||
// then
|
||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldReturnLongIfTypeClassCannotBeConverted() throws SQLException { |
||||
// given
|
||||
given(resultSet.getString("class_id_type")).willReturn("java.lang.Long"); |
||||
given(conversionService.canConvert(String.class, Long.class)).willReturn(false); |
||||
|
||||
// when
|
||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, resultSet); |
||||
|
||||
// then
|
||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldReturnLongWhenLongClassIdType() throws SQLException { |
||||
// given
|
||||
given(resultSet.getString("class_id_type")).willReturn("java.lang.Long"); |
||||
|
||||
// when
|
||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, resultSet); |
||||
|
||||
// then
|
||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldReturnUUIDWhenUUIDClassIdType() throws SQLException { |
||||
// given
|
||||
UUID identifier = UUID.randomUUID(); |
||||
String identifierAsString = identifier.toString(); |
||||
given(resultSet.getString("class_id_type")).willReturn("java.util.UUID"); |
||||
given(conversionService.canConvert(String.class, UUID.class)).willReturn(true); |
||||
given(conversionService.convert(identifierAsString, UUID.class)).willReturn(UUID.fromString(identifierAsString)); |
||||
|
||||
// when
|
||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(identifier.toString(), resultSet); |
||||
|
||||
// then
|
||||
assertThat(newIdentifier).isEqualTo(identifier); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,72 @@
@@ -0,0 +1,72 @@
|
||||
/* |
||||
* Copyright 2002-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.security.acls.jdbc; |
||||
|
||||
import org.springframework.core.io.ClassPathResource; |
||||
import org.springframework.core.io.Resource; |
||||
import org.springframework.jdbc.core.JdbcTemplate; |
||||
import org.springframework.jdbc.datasource.SingleConnectionDataSource; |
||||
import org.springframework.util.FileCopyUtils; |
||||
|
||||
/** |
||||
* Helper class to initialize the database for BasicLookupStrategyTests. |
||||
* @author Andrei Stefan |
||||
* @author Paul Wheeler |
||||
*/ |
||||
public class BasicLookupStrategyTestsDbHelper { |
||||
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 SingleConnectionDataSource dataSource; |
||||
private JdbcTemplate jdbcTemplate; |
||||
private boolean withAclClassIdType; |
||||
|
||||
public BasicLookupStrategyTestsDbHelper() { |
||||
} |
||||
|
||||
public BasicLookupStrategyTestsDbHelper(boolean withAclClassIdType) { |
||||
this.withAclClassIdType = withAclClassIdType; |
||||
} |
||||
|
||||
public void createDatabase() throws Exception { |
||||
// Use a different connection url so the tests can run in parallel
|
||||
String connectionUrl; |
||||
String sqlClassPathResource; |
||||
if (!withAclClassIdType) { |
||||
connectionUrl = "jdbc:hsqldb:mem:lookupstrategytest"; |
||||
sqlClassPathResource = ACL_SCHEMA_SQL_FILE; |
||||
} else { |
||||
connectionUrl = "jdbc:hsqldb:mem:lookupstrategytestWithAclClassIdType"; |
||||
sqlClassPathResource = ACL_SCHEMA_SQL_FILE_WITH_ACL_CLASS_ID; |
||||
|
||||
} |
||||
dataSource = new SingleConnectionDataSource(connectionUrl, "sa", "", true); |
||||
dataSource.setDriverClassName("org.hsqldb.jdbcDriver"); |
||||
jdbcTemplate = new JdbcTemplate(dataSource); |
||||
|
||||
Resource resource = new ClassPathResource(sqlClassPathResource); |
||||
String sql = new String(FileCopyUtils.copyToByteArray(resource.getInputStream())); |
||||
jdbcTemplate.execute(sql); |
||||
} |
||||
|
||||
public JdbcTemplate getJdbcTemplate() { |
||||
return jdbcTemplate; |
||||
} |
||||
|
||||
public SingleConnectionDataSource getDataSource() { |
||||
return dataSource; |
||||
} |
||||
} |
||||
@ -0,0 +1,117 @@
@@ -0,0 +1,117 @@
|
||||
/* |
||||
* Copyright 2002-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.security.acls.jdbc; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.Map; |
||||
|
||||
import javax.sql.DataSource; |
||||
|
||||
import org.junit.AfterClass; |
||||
import org.junit.Before; |
||||
import org.junit.BeforeClass; |
||||
import org.junit.Test; |
||||
import org.springframework.core.convert.ConversionFailedException; |
||||
import org.springframework.core.convert.support.DefaultConversionService; |
||||
import org.springframework.jdbc.core.JdbcTemplate; |
||||
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.ObjectIdentityImpl; |
||||
import org.springframework.security.acls.model.Acl; |
||||
import org.springframework.security.acls.model.ObjectIdentity; |
||||
|
||||
import junit.framework.Assert; |
||||
|
||||
/** |
||||
* Tests {@link BasicLookupStrategy} with Acl Class type id set to UUID. |
||||
* |
||||
* @author Paul Wheeler |
||||
*/ |
||||
public class BasicLookupStrategyWithAclClassTypeTests extends AbstractBasicLookupStrategyTests { |
||||
|
||||
private static final BasicLookupStrategyTestsDbHelper DATABASE_HELPER = new BasicLookupStrategyTestsDbHelper(true); |
||||
|
||||
private BasicLookupStrategy uuidEnabledStrategy; |
||||
|
||||
@Override |
||||
public JdbcTemplate getJdbcTemplate() { |
||||
return DATABASE_HELPER.getJdbcTemplate(); |
||||
} |
||||
|
||||
@Override |
||||
public DataSource getDataSource() { |
||||
return DATABASE_HELPER.getDataSource(); |
||||
} |
||||
|
||||
@BeforeClass |
||||
public static void createDatabase() throws Exception { |
||||
DATABASE_HELPER.createDatabase(); |
||||
} |
||||
|
||||
@AfterClass |
||||
public static void dropDatabase() throws Exception { |
||||
DATABASE_HELPER.getDataSource().destroy(); |
||||
} |
||||
|
||||
@Before |
||||
public void initializeBeans() { |
||||
super.initializeBeans(); |
||||
AclClassIdUtils aclClassIdUtils = new AclClassIdUtils(); |
||||
aclClassIdUtils.setConversionService(new DefaultConversionService()); |
||||
uuidEnabledStrategy = new BasicLookupStrategy(getDataSource(), aclCache(), aclAuthStrategy(), |
||||
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger())); |
||||
uuidEnabledStrategy.setPermissionFactory(new DefaultPermissionFactory()); |
||||
uuidEnabledStrategy.setAclClassIdSupported(true); |
||||
uuidEnabledStrategy.setAclClassIdUtils(aclClassIdUtils); |
||||
} |
||||
|
||||
@Before |
||||
public void populateDatabaseForAclClassTypeTests() { |
||||
String query = "INSERT INTO acl_class(ID,CLASS,CLASS_ID_TYPE) VALUES (3,'" |
||||
+ TARGET_CLASS_WITH_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,'" |
||||
+ 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,'" |
||||
+ 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 (6,5,0,1,8,0,0,0);"; |
||||
DATABASE_HELPER.getJdbcTemplate().execute(query); |
||||
} |
||||
|
||||
@Test |
||||
public void testReadObjectIdentityUsingUuidType() { |
||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, OBJECT_IDENTITY_UUID); |
||||
Map<ObjectIdentity, Acl> foundAcls = uuidEnabledStrategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID)); |
||||
Assert.assertEquals(1, foundAcls.size()); |
||||
Assert.assertNotNull(foundAcls.get(oid)); |
||||
} |
||||
|
||||
@Test |
||||
public void testReadObjectIdentityUsingLongTypeWithConversionServiceEnabled() { |
||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, new Long(100)); |
||||
Map<ObjectIdentity, Acl> foundAcls = uuidEnabledStrategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID)); |
||||
Assert.assertEquals(1, foundAcls.size()); |
||||
Assert.assertNotNull(foundAcls.get(oid)); |
||||
} |
||||
|
||||
@Test(expected = ConversionFailedException.class) |
||||
public void testReadObjectIdentityUsingNonUuidInDatabase() { |
||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, OBJECT_IDENTITY_LONG_AS_UUID); |
||||
uuidEnabledStrategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID)); |
||||
} |
||||
} |
||||
@ -0,0 +1,83 @@
@@ -0,0 +1,83 @@
|
||||
/* |
||||
* Copyright 2002-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.security.acls.jdbc; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
import java.util.UUID; |
||||
|
||||
import org.junit.Test; |
||||
import org.springframework.security.acls.TargetObjectWithUUID; |
||||
import org.springframework.security.acls.domain.ObjectIdentityImpl; |
||||
import org.springframework.security.acls.model.ObjectIdentity; |
||||
import org.springframework.security.core.context.SecurityContextHolder; |
||||
import org.springframework.test.context.ContextConfiguration; |
||||
import org.springframework.transaction.annotation.Transactional; |
||||
|
||||
/** |
||||
* Integration tests the ACL system using ACL class id type of UUID and using an in-memory database. |
||||
* @author Paul Wheeler |
||||
*/ |
||||
@ContextConfiguration(locations = {"/jdbcMutableAclServiceTestsWithAclClass-context.xml"}) |
||||
public class JdbcMutableAclServiceTestsWithAclClassId extends JdbcMutableAclServiceTests { |
||||
|
||||
private static final String TARGET_CLASS_WITH_UUID = TargetObjectWithUUID.class.getName(); |
||||
|
||||
private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, |
||||
UUID.randomUUID()); |
||||
private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, |
||||
UUID.randomUUID()); |
||||
private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, |
||||
UUID.randomUUID()); |
||||
|
||||
@Override |
||||
protected String getSqlClassPathResource() { |
||||
return "createAclSchemaWithAclClassIdType.sql"; |
||||
} |
||||
|
||||
@Override |
||||
protected ObjectIdentity getTopParentOid() { |
||||
return topParentOid; |
||||
} |
||||
|
||||
@Override |
||||
protected ObjectIdentity getMiddleParentOid() { |
||||
return middleParentOid; |
||||
} |
||||
|
||||
@Override |
||||
protected ObjectIdentity getChildOid() { |
||||
return childOid; |
||||
} |
||||
|
||||
@Override |
||||
protected String getTargetClass() { |
||||
return TARGET_CLASS_WITH_UUID; |
||||
} |
||||
|
||||
@Test |
||||
@Transactional |
||||
public void identityWithUuidIdIsSupportedByCreateAcl() throws Exception { |
||||
SecurityContextHolder.getContext().setAuthentication(getAuth()); |
||||
|
||||
UUID id = UUID.randomUUID(); |
||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, id); |
||||
getJdbcMutableAclService().createAcl(oid); |
||||
|
||||
assertThat(getJdbcMutableAclService().readAclById(new ObjectIdentityImpl( |
||||
TARGET_CLASS_WITH_UUID, id))).isNotNull(); |
||||
} |
||||
} |
||||
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<beans xmlns="http://www.springframework.org/schema/beans" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> |
||||
|
||||
<import resource="jdbcMutableAclServiceTests-context.xml"/> |
||||
|
||||
<bean id="aclClassIdUtils" class="org.springframework.security.acls.jdbc.AclClassIdUtils"> |
||||
<property name="conversionService"> |
||||
<bean class="org.springframework.core.convert.support.DefaultConversionService"/> |
||||
</property> |
||||
</bean> |
||||
<!-- Overridden bean definitions --> |
||||
|
||||
<bean id="aclService" class="org.springframework.security.acls.jdbc.JdbcMutableAclService"> |
||||
<constructor-arg ref="dataSource"/> |
||||
<constructor-arg ref="lookupStrategy"/> |
||||
<constructor-arg ref="aclCache"/> |
||||
<property name="aclClassIdSupported" value="true"/> |
||||
<property name="aclClassIdUtils" ref="aclClassIdUtils"/> |
||||
</bean> |
||||
|
||||
<bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy"> |
||||
<constructor-arg ref="dataSource"/> |
||||
<constructor-arg ref="aclCache"/> |
||||
<constructor-arg ref="aclAuthorizationStrategy"/> |
||||
<constructor-arg> |
||||
<bean class="org.springframework.security.acls.domain.ConsoleAuditLogger"/> |
||||
</constructor-arg> |
||||
<property name="aclClassIdSupported" value="true"/> |
||||
<property name="aclClassIdUtils" ref="aclClassIdUtils"/> |
||||
</bean> |
||||
</beans> |
||||
Loading…
Reference in new issue