diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/AclClassIdUtils.java b/acl/src/main/java/org/springframework/security/acls/jdbc/AclClassIdUtils.java
new file mode 100644
index 00000000000..76d47c6f5fd
--- /dev/null
+++ b/acl/src/main/java/org/springframework/security/acls/jdbc/AclClassIdUtils.java
@@ -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 acl_class.class_id_type
.
+ * @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 Class classIdTypeFrom(ResultSet resultSet) throws SQLException {
+ return classIdTypeFrom(resultSet.getString(DEFAULT_CLASS_ID_TYPE_COLUMN_NAME));
+ }
+
+ private Class 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 boolean canConvertFromStringTo(Class targetType) {
+ return hasConversionService() && conversionService.canConvert(String.class, targetType);
+ }
+
+ private T convertFromStringTo(String identifier, Class 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;
+ }
+}
diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java b/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java
index 0bd358e6115..5b81b36d5b2 100644
--- a/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java
+++ b/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ * Copyright 2004, 2005, 2006, 2017 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,6 +30,9 @@
import javax.sql.DataSource;
+import org.springframework.core.convert.ConversionException;
+import org.springframework.core.convert.ConversionService;
+import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.ResultSetExtractor;
@@ -78,7 +81,7 @@
*/
public class BasicLookupStrategy implements LookupStrategy {
- public final static String DEFAULT_SELECT_CLAUSE = "select acl_object_identity.object_id_identity, "
+ private final static String DEFAULT_SELECT_CLAUSE_COLUMNS = "select acl_object_identity.object_id_identity, "
+ "acl_entry.ace_order, "
+ "acl_object_identity.id as acl_id, "
+ "acl_object_identity.parent_object, "
@@ -92,13 +95,19 @@ public class BasicLookupStrategy implements LookupStrategy {
+ "acl_sid.sid as ace_sid, "
+ "acli_sid.principal as acl_principal, "
+ "acli_sid.sid as acl_sid, "
- + "acl_class.class "
- + "from acl_object_identity "
+ + "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_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_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 final static String DEFAULT_ACL_CLASS_ID_SELECT_CLAUSE = DEFAULT_SELECT_CLAUSE_COLUMNS +
+ 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 final static String DEFAULT_LOOKUP_IDENTITIES_WHERE_CLAUSE = "(acl_object_identity.object_id_identity = ? and acl_class.class = ?)";
@@ -126,6 +135,8 @@ public class BasicLookupStrategy implements LookupStrategy {
private String lookupObjectIdentitiesWhereClause = DEFAULT_LOOKUP_IDENTITIES_WHERE_CLAUSE;
private String orderByClause = DEFAULT_ORDER_BY_CLAUSE;
+ private AclClassIdUtils aclClassIdUtils;
+
// ~ Constructors
// ===================================================================================================
@@ -161,9 +172,9 @@ public BasicLookupStrategy(DataSource dataSource, AclCache aclCache,
this.aclCache = aclCache;
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
this.grantingStrategy = grantingStrategy;
+ this.aclClassIdUtils = new AclClassIdUtils();
fieldAces.setAccessible(true);
fieldAcl.setAccessible(true);
-
}
// ~ Methods
@@ -383,10 +394,9 @@ public void setValues(PreparedStatement ps) throws SQLException {
// No need to check for nulls, as guaranteed non-null by
// ObjectIdentity.getIdentifier() interface contract
String identifier = oid.getIdentifier().toString();
- long id = (Long.valueOf(identifier)).longValue();
// Inject values
- ps.setLong((2 * i) + 1, id);
+ ps.setString((2 * i) + 1, identifier);
ps.setString((2 * i) + 2, type);
i++;
}
@@ -537,6 +547,18 @@ public final void setOrderByClause(String orderByClause) {
this.orderByClause = orderByClause;
}
+ public final void setAclClassIdSupported(boolean aclClassIdSupported) {
+ if (aclClassIdSupported) {
+ Assert.isTrue(this.selectClause.equals(DEFAULT_SELECT_CLAUSE), "Cannot set aclClassIdSupported and override the select clause; "
+ + "just override the select clause");
+ this.selectClause = DEFAULT_ACL_CLASS_ID_SELECT_CLAUSE;
+ }
+ }
+
+ public final void setAclClassIdUtils(AclClassIdUtils aclClassIdUtils) {
+ this.aclClassIdUtils = aclClassIdUtils;
+ }
+
// ~ Inner Classes
// ==================================================================================================
@@ -602,6 +624,7 @@ public Set extractData(ResultSet rs) throws SQLException {
* @param rs the ResultSet focused on a current row
*
* @throws SQLException if something goes wrong converting values
+ * @throws ConversionException if can't convert to the desired Java type
*/
private void convertCurrentResultIntoObject(Map acls,
ResultSet rs) throws SQLException {
@@ -612,9 +635,12 @@ private void convertCurrentResultIntoObject(Map acls,
if (acl == null) {
// 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.
+ Serializable identifier = (Serializable) rs.getObject("object_id_identity");
+ identifier = aclClassIdUtils.identifierFrom(identifier, rs);
ObjectIdentity objectIdentity = new ObjectIdentityImpl(
- rs.getString("class"), Long.valueOf(rs
- .getLong("object_id_identity")));
+ rs.getString("class"), identifier);
Acl parentAcl = null;
long parentAclId = rs.getLong("parent_object");
diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcAclService.java b/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcAclService.java
index e9e8ed49c74..1032e6da9f5 100644
--- a/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcAclService.java
+++ b/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcAclService.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ * Copyright 2004, 2005, 2006, 2017 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
*/
package org.springframework.security.acls.jdbc;
+import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
@@ -49,8 +50,15 @@ public class JdbcAclService implements AclService {
// =====================================================================================
protected static final Log log = LogFactory.getLog(JdbcAclService.class);
- private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL = "select obj.object_id_identity as obj_id, class.class as class "
- + "from acl_object_identity obj, acl_object_identity parent, acl_class 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
+ + " 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 = ?)";
+ 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 = ?)";
@@ -60,7 +68,9 @@ public class JdbcAclService implements AclService {
protected final JdbcTemplate jdbcTemplate;
private final LookupStrategy lookupStrategy;
+ private boolean aclClassIdSupported;
private String findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL;
+ private AclClassIdUtils aclClassIdUtils;
// ~ Constructors
// ===================================================================================================
@@ -70,6 +80,7 @@ public JdbcAclService(DataSource dataSource, LookupStrategy lookupStrategy) {
Assert.notNull(lookupStrategy, "LookupStrategy required");
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.lookupStrategy = lookupStrategy;
+ this.aclClassIdUtils = new AclClassIdUtils();
}
// ~ Methods
@@ -82,7 +93,8 @@ public List findChildren(ObjectIdentity parentIdentity) {
public ObjectIdentity mapRow(ResultSet rs, int rowNum)
throws SQLException {
String javaType = rs.getString("class");
- Long identifier = new Long(rs.getLong("obj_id"));
+ Serializable identifier = (Serializable) rs.getObject("obj_id");
+ identifier = aclClassIdUtils.identifierFrom(identifier, rs);
return new ObjectIdentityImpl(javaType, identifier);
}
@@ -138,4 +150,24 @@ public Map readAclsById(List objects,
public void setFindChildrenQuery(String findChildrenSql) {
this.findChildrenSql = findChildrenSql;
}
+
+ public void setAclClassIdSupported(boolean aclClassIdSupported) {
+ this.aclClassIdSupported = aclClassIdSupported;
+ if (aclClassIdSupported) {
+ // Change the default insert if it hasn't been overridden
+ if (this.findChildrenSql.equals(DEFAULT_SELECT_ACL_WITH_PARENT_SQL)) {
+ this.findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE;
+ } else {
+ log.debug("Find children statement has already been overridden, so not overridding the default");
+ }
+ }
+ }
+
+ public void setAclClassIdUtils(AclClassIdUtils aclClassIdUtils) {
+ this.aclClassIdUtils = aclClassIdUtils;
+ }
+
+ protected boolean isAclClassIdSupported() {
+ return aclClassIdSupported;
+ }
}
diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcMutableAclService.java b/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcMutableAclService.java
index 8c990af9acc..6100fe1074b 100644
--- a/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcMutableAclService.java
+++ b/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcMutableAclService.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ * Copyright 2004, 2005, 2006, 2017 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -58,6 +58,8 @@
* @author Johannes Zlattinger
*/
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_WITH_ID = "insert into acl_class (class, class_id_type) values (?, ?)";
// ~ Instance fields
// ================================================================================================
@@ -67,7 +69,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
private String deleteObjectIdentityByPrimaryKey = "delete from acl_object_identity where id=?";
private String classIdentityQuery = "call identity()";
private String sidIdentityQuery = "call identity()";
- private String insertClass = "insert into acl_class (class) values (?)";
+ private String insertClass = DEFAULT_INSERT_INTO_ACL_CLASS;
private String insertEntry = "insert into acl_entry "
+ "(acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure)"
+ "values (?, ?, ?, ?, ?, ?, ?)";
@@ -167,7 +169,7 @@ public void setValues(PreparedStatement stmt, int i) throws SQLException {
*/
protected void createObjectIdentity(ObjectIdentity object, Sid owner) {
Long sidId = createOrRetrieveSidPrimaryKey(owner, true);
- Long classId = createOrRetrieveClassPrimaryKey(object.getType(), true);
+ Long classId = createOrRetrieveClassPrimaryKey(object.getType(), true, object.getIdentifier().getClass());
jdbcTemplate.update(insertObjectIdentity, classId, object.getIdentifier(), sidId,
Boolean.TRUE);
}
@@ -181,7 +183,7 @@ protected void createObjectIdentity(ObjectIdentity object, Sid owner) {
*
* @return the primary key or null if not found
*/
- protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate) {
+ protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate, Class idType) {
List classIds = jdbcTemplate.queryForList(selectClassPrimaryKey,
new Object[] { type }, Long.class);
@@ -190,7 +192,11 @@ protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate)
}
if (allowCreate) {
- jdbcTemplate.update(insertClass, type);
+ if (!isAclClassIdSupported()) {
+ jdbcTemplate.update(insertClass, type);
+ } else {
+ jdbcTemplate.update(insertClass, type, idType.getCanonicalName());
+ }
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(),
"Transaction must be running");
return jdbcTemplate.queryForObject(classIdentityQuery, Long.class);
@@ -485,4 +491,17 @@ public void setUpdateObjectIdentity(String updateObjectIdentity) {
public void setForeignKeysInDatabase(boolean foreignKeysInDatabase) {
this.foreignKeysInDatabase = foreignKeysInDatabase;
}
+
+ @Override
+ public void setAclClassIdSupported(boolean aclClassIdSupported) {
+ super.setAclClassIdSupported(aclClassIdSupported);
+ if (aclClassIdSupported) {
+ // Change the default insert if it hasn't been overridden
+ if (this.insertClass.equals(DEFAULT_INSERT_INTO_ACL_CLASS)) {
+ this.insertClass = DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID;
+ } else {
+ log.debug("Insert class statement has already been overridden, so not overridding the default");
+ }
+ }
+ }
}
diff --git a/acl/src/main/resources/createAclSchemaMySQL.sql b/acl/src/main/resources/createAclSchemaMySQL.sql
index 5eb32f4ff23..d50120e2fc0 100644
--- a/acl/src/main/resources/createAclSchemaMySQL.sql
+++ b/acl/src/main/resources/createAclSchemaMySQL.sql
@@ -21,7 +21,7 @@ CREATE TABLE acl_class (
CREATE TABLE acl_object_identity (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
object_id_class BIGINT UNSIGNED NOT NULL,
- object_id_identity BIGINT NOT NULL,
+ object_id_identity VARCHAR(36) NOT NULL,
parent_object BIGINT UNSIGNED,
owner_sid BIGINT UNSIGNED,
entries_inheriting BOOLEAN NOT NULL,
diff --git a/acl/src/main/resources/createAclSchemaOracle.sql b/acl/src/main/resources/createAclSchemaOracle.sql
index 9d3fcecebd3..c3fb609bfea 100644
--- a/acl/src/main/resources/createAclSchemaOracle.sql
+++ b/acl/src/main/resources/createAclSchemaOracle.sql
@@ -43,7 +43,7 @@ END;
CREATE TABLE acl_object_identity (
id NUMBER(38) NOT NULL PRIMARY KEY,
object_id_class NUMBER(38) NOT NULL,
- object_id_identity NUMBER(38) NOT NULL,
+ object_id_identity NVARCHAR2(36) NOT NULL,
parent_object NUMBER(38),
owner_sid NUMBER(38),
entries_inheriting NUMBER(1) NOT NULL CHECK (entries_inheriting in (0, 1)),
diff --git a/acl/src/main/resources/createAclSchemaPostgres.sql b/acl/src/main/resources/createAclSchemaPostgres.sql
index 364ebf92d22..ef346ed195b 100644
--- a/acl/src/main/resources/createAclSchemaPostgres.sql
+++ b/acl/src/main/resources/createAclSchemaPostgres.sql
@@ -15,13 +15,14 @@ create table acl_sid(
create table acl_class(
id bigserial not null primary key,
class varchar(100) not null,
+ class_id_type varchar(100),
constraint unique_uk_2 unique(class)
);
create table acl_object_identity(
id bigserial primary key,
object_id_class bigint not null,
- object_id_identity bigint not null,
+ object_id_identity varchar(36) not null,
parent_object bigint,
owner_sid bigint,
entries_inheriting boolean not null,
diff --git a/acl/src/main/resources/createAclSchemaSqlServer.sql b/acl/src/main/resources/createAclSchemaSqlServer.sql
index 0c0ded8c827..b7f5ff23fe9 100644
--- a/acl/src/main/resources/createAclSchemaSqlServer.sql
+++ b/acl/src/main/resources/createAclSchemaSqlServer.sql
@@ -21,7 +21,7 @@ CREATE TABLE acl_class (
CREATE TABLE acl_object_identity (
id BIGINT NOT NULL IDENTITY PRIMARY KEY,
object_id_class BIGINT NOT NULL,
- object_id_identity BIGINT NOT NULL,
+ object_id_identity VARCHAR(36) NOT NULL,
parent_object BIGINT,
owner_sid BIGINT,
entries_inheriting BIT NOT NULL,
diff --git a/acl/src/main/resources/createAclSchemaWithAclClassIdType.sql b/acl/src/main/resources/createAclSchemaWithAclClassIdType.sql
new file mode 100644
index 00000000000..40594f1d148
--- /dev/null
+++ b/acl/src/main/resources/createAclSchemaWithAclClassIdType.sql
@@ -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)
+);
diff --git a/acl/src/test/java/org/springframework/security/acls/TargetObjectWithUUID.java b/acl/src/test/java/org/springframework/security/acls/TargetObjectWithUUID.java
new file mode 100644
index 00000000000..c3148699c44
--- /dev/null
+++ b/acl/src/test/java/org/springframework/security/acls/TargetObjectWithUUID.java
@@ -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;
+ }
+}
diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/AbstractBasicLookupStrategyTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/AbstractBasicLookupStrategyTests.java
new file mode 100644
index 00000000000..2e564535629
--- /dev/null
+++ b/acl/src/test/java/org/springframework/security/acls/jdbc/AbstractBasicLookupStrategyTests.java
@@ -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 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 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 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 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 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 checkPermission = Arrays.asList(BasePermission.READ);
+ List sids = Arrays.asList(BEN_SID);
+ List childOids = Arrays.asList(childOid);
+
+ strategy.setBatchSize(6);
+ Map 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 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");
+ }
+
+}
diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/AclClassIdUtilsTest.java b/acl/src/test/java/org/springframework/security/acls/jdbc/AclClassIdUtilsTest.java
new file mode 100644
index 00000000000..59bb3ea4006
--- /dev/null
+++ b/acl/src/test/java/org/springframework/security/acls/jdbc/AclClassIdUtilsTest.java
@@ -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);
+ }
+
+}
diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTests.java
index 069f999b8d2..8557177dc64 100644
--- a/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTests.java
+++ b/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * 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.
@@ -15,330 +15,39 @@
*/
package org.springframework.security.acls.jdbc;
-import static org.assertj.core.api.Assertions.*;
+import javax.sql.DataSource;
-import net.sf.ehcache.Cache;
-import net.sf.ehcache.CacheManager;
-import net.sf.ehcache.Ehcache;
-import org.junit.*;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.jdbc.datasource.SingleConnectionDataSource;
-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 org.springframework.util.FileCopyUtils;
-
-import java.util.*;
/**
- * Tests {@link BasicLookupStrategy}
+ * Tests {@link BasicLookupStrategy} with Acl Class type id not specified.
*
* @author Andrei Stefan
+ * @author Paul Wheeler
*/
-public class BasicLookupStrategyTests {
-
- private static final Sid BEN_SID = new PrincipalSid("ben");
- private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject";
-
- // ~ Instance fields
- // ================================================================================================
-
- private static JdbcTemplate jdbcTemplate;
- private BasicLookupStrategy strategy;
- private static SingleConnectionDataSource dataSource;
- private static CacheManager cacheManager;
+public class BasicLookupStrategyTests extends AbstractBasicLookupStrategyTests {
+ private static final BasicLookupStrategyTestsDbHelper DATABASE_HELPER = new BasicLookupStrategyTestsDbHelper();
- // ~ Methods
- // ========================================================================================================
- @BeforeClass
- public static void initCacheManaer() {
- cacheManager = CacheManager.create();
- cacheManager.addCache(new Cache("basiclookuptestcache", 500, false, false, 30, 30));
- }
@BeforeClass
public static void createDatabase() throws Exception {
- dataSource = new SingleConnectionDataSource("jdbc:hsqldb:mem:lookupstrategytest", "sa", "", true);
- dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
- jdbcTemplate = new JdbcTemplate(dataSource);
-
- Resource resource = new ClassPathResource("createAclSchema.sql");
- String sql = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
- jdbcTemplate.execute(sql);
+ DATABASE_HELPER.createDatabase();
}
@AfterClass
public static void dropDatabase() throws Exception {
- dataSource.destroy();
- }
-
- @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);";
- jdbcTemplate.execute(query);
- }
-
- @Before
- public void initializeBeans() {
- EhCacheBasedAclCache cache = new EhCacheBasedAclCache(getCache(),
- new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()),
- new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER")));
- AclAuthorizationStrategy authorizationStrategy = new AclAuthorizationStrategyImpl(
- new SimpleGrantedAuthority("ROLE_ADMINISTRATOR"));
- strategy = new BasicLookupStrategy(dataSource, cache, authorizationStrategy,
- new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()));
- strategy.setPermissionFactory(new DefaultPermissionFactory());
- }
-
- @After
- public void emptyDatabase() {
- String query = "DELETE FROM acl_entry;" + "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;";
- jdbcTemplate.execute(query);
+ DATABASE_HELPER.getDataSource().destroy();
}
- private Ehcache getCache() {
- Ehcache cache = cacheManager.getCache("basiclookuptestcache");
- cache.removeAll();
- return cache;
+ @Override
+ public JdbcTemplate getJdbcTemplate() {
+ return DATABASE_HELPER.getJdbcTemplate();
}
- @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 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 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 map = this.strategy
- .readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
- checkEntries(topParentOid, middleParentOid, childOid, map);
+ @Override
+ public DataSource getDataSource() {
+ return DATABASE_HELPER.getDataSource();
}
-
- private void checkEntries(ObjectIdentity topParentOid, ObjectIdentity middleParentOid, ObjectIdentity childOid,
- Map 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 (4,2,103,1,1,1);";
- jdbcTemplate.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 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 (4,2,104,null,1,1);"
- + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (5,2,105,4,1,1);"
- + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (6,2,106,4,1,1);"
- + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (7,2,107,5,1,1);"
- + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (5,4,0,1,1,1,0,0)";
- jdbcTemplate.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 checkPermission = Arrays.asList(BasePermission.READ);
- List sids = Arrays.asList(BEN_SID);
- List childOids = Arrays.asList(childOid);
-
- strategy.setBatchSize(6);
- Map 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 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 (4,2,104,null,null,1);";
-
- jdbcTemplate.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");
- }
-
}
diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTestsDbHelper.java b/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTestsDbHelper.java
new file mode 100644
index 00000000000..5615c71c04f
--- /dev/null
+++ b/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTestsDbHelper.java
@@ -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;
+ }
+}
diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyWithAclClassTypeTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyWithAclClassTypeTests.java
new file mode 100644
index 00000000000..b84d606c222
--- /dev/null
+++ b/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyWithAclClassTypeTests.java
@@ -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 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 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));
+ }
+}
diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTests.java
index fcc6f8098bd..0f47daa5c60 100644
--- a/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTests.java
+++ b/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ * Copyright 2004, 2005, 2006, 2017 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -98,10 +98,30 @@ public class JdbcMutableAclServiceTests extends
// ~ Methods
// ========================================================================================================
+ protected String getSqlClassPathResource() {
+ return "createAclSchema.sql";
+ }
+
+ protected ObjectIdentity getTopParentOid() {
+ return topParentOid;
+ }
+
+ protected ObjectIdentity getMiddleParentOid() {
+ return middleParentOid;
+ }
+
+ protected ObjectIdentity getChildOid() {
+ return childOid;
+ }
+
+ protected String getTargetClass() {
+ return TARGET_CLASS;
+ }
+
@BeforeTransaction
public void createTables() throws Exception {
try {
- new DatabaseSeeder(dataSource, new ClassPathResource("createAclSchema.sql"));
+ new DatabaseSeeder(dataSource, new ClassPathResource(getSqlClassPathResource()));
// new DatabaseSeeder(dataSource, new
// ClassPathResource("createAclSchemaPostgres.sql"));
}
@@ -126,9 +146,9 @@ public void clearContextAndData() throws Exception {
public void testLifecycle() {
SecurityContextHolder.getContext().setAuthentication(auth);
- MutableAcl topParent = jdbcMutableAclService.createAcl(topParentOid);
- MutableAcl middleParent = jdbcMutableAclService.createAcl(middleParentOid);
- MutableAcl child = jdbcMutableAclService.createAcl(childOid);
+ MutableAcl topParent = jdbcMutableAclService.createAcl(getTopParentOid());
+ MutableAcl middleParent = jdbcMutableAclService.createAcl(getMiddleParentOid());
+ MutableAcl child = jdbcMutableAclService.createAcl(getChildOid());
// Specify the inheritance hierarchy
middleParent.setParent(topParent);
@@ -147,13 +167,13 @@ public void testLifecycle() {
// Let's check if we can read them back correctly
Map map = jdbcMutableAclService.readAclsById(Arrays.asList(
- topParentOid, middleParentOid, childOid));
+ getTopParentOid(), getMiddleParentOid(), getChildOid()));
assertThat(map).hasSize(3);
// Replace our current objects with their retrieved versions
- topParent = (MutableAcl) map.get(topParentOid);
- middleParent = (MutableAcl) map.get(middleParentOid);
- child = (MutableAcl) map.get(childOid);
+ topParent = (MutableAcl) map.get(getTopParentOid());
+ middleParent = (MutableAcl) map.get(getMiddleParentOid());
+ child = (MutableAcl) map.get(getChildOid());
// Check the retrieved versions has IDs
assertThat(topParent.getId()).isNotNull();
@@ -162,8 +182,8 @@ public void testLifecycle() {
// Check their parents were correctly persisted
assertThat(topParent.getParentAcl()).isNull();
- assertThat(middleParent.getParentAcl().getObjectIdentity()).isEqualTo(topParentOid);
- assertThat(child.getParentAcl().getObjectIdentity()).isEqualTo(middleParentOid);
+ assertThat(middleParent.getParentAcl().getObjectIdentity()).isEqualTo(getTopParentOid());
+ assertThat(child.getParentAcl().getObjectIdentity()).isEqualTo(getMiddleParentOid());
// Check their ACEs were correctly persisted
assertThat(topParent.getEntries()).hasSize(2);
@@ -197,7 +217,7 @@ public void testLifecycle() {
// Next change the child so it doesn't inherit permissions from above
child.setEntriesInheriting(false);
jdbcMutableAclService.updateAcl(child);
- child = (MutableAcl) jdbcMutableAclService.readAclById(childOid);
+ child = (MutableAcl) jdbcMutableAclService.readAclById(getChildOid());
assertThat(child.isEntriesInheriting()).isFalse();
// Check the child permissions no longer inherit
@@ -228,7 +248,7 @@ public void testLifecycle() {
// Save the changed child
jdbcMutableAclService.updateAcl(child);
- child = (MutableAcl) jdbcMutableAclService.readAclById(childOid);
+ child = (MutableAcl) jdbcMutableAclService.readAclById(getChildOid());
assertThat(child.getEntries()).hasSize(3);
// Output permissions
@@ -268,38 +288,38 @@ public void testLifecycle() {
public void deleteAclAlsoDeletesChildren() throws Exception {
SecurityContextHolder.getContext().setAuthentication(auth);
- jdbcMutableAclService.createAcl(topParentOid);
- MutableAcl middleParent = jdbcMutableAclService.createAcl(middleParentOid);
- MutableAcl child = jdbcMutableAclService.createAcl(childOid);
+ jdbcMutableAclService.createAcl(getTopParentOid());
+ MutableAcl middleParent = jdbcMutableAclService.createAcl(getMiddleParentOid());
+ MutableAcl child = jdbcMutableAclService.createAcl(getChildOid());
child.setParent(middleParent);
jdbcMutableAclService.updateAcl(middleParent);
jdbcMutableAclService.updateAcl(child);
// Check the childOid really is a child of middleParentOid
- Acl childAcl = jdbcMutableAclService.readAclById(childOid);
+ Acl childAcl = jdbcMutableAclService.readAclById(getChildOid());
- assertThat(childAcl.getParentAcl().getObjectIdentity()).isEqualTo(middleParentOid);
+ assertThat(childAcl.getParentAcl().getObjectIdentity()).isEqualTo(getMiddleParentOid());
// Delete the mid-parent and test if the child was deleted, as well
- jdbcMutableAclService.deleteAcl(middleParentOid, true);
+ jdbcMutableAclService.deleteAcl(getMiddleParentOid(), true);
try {
- jdbcMutableAclService.readAclById(middleParentOid);
+ jdbcMutableAclService.readAclById(getMiddleParentOid());
fail("It should have thrown NotFoundException");
}
catch (NotFoundException expected) {
}
try {
- jdbcMutableAclService.readAclById(childOid);
+ jdbcMutableAclService.readAclById(getChildOid());
fail("It should have thrown NotFoundException");
}
catch (NotFoundException expected) {
}
- Acl acl = jdbcMutableAclService.readAclById(topParentOid);
+ Acl acl = jdbcMutableAclService.readAclById(getTopParentOid());
assertThat(acl).isNotNull();
- assertThat(topParentOid).isEqualTo(((MutableAcl) acl).getObjectIdentity());
+ assertThat(getTopParentOid()).isEqualTo(((MutableAcl) acl).getObjectIdentity());
}
@Test
@@ -367,8 +387,8 @@ public void deleteAclRejectsNullParameters() throws Exception {
@Transactional
public void deleteAclWithChildrenThrowsException() throws Exception {
SecurityContextHolder.getContext().setAuthentication(auth);
- MutableAcl parent = jdbcMutableAclService.createAcl(topParentOid);
- MutableAcl child = jdbcMutableAclService.createAcl(middleParentOid);
+ MutableAcl parent = jdbcMutableAclService.createAcl(getTopParentOid());
+ MutableAcl child = jdbcMutableAclService.createAcl(getMiddleParentOid());
// Specify the inheritance hierarchy
child.setParent(parent);
@@ -378,7 +398,7 @@ public void deleteAclWithChildrenThrowsException() throws Exception {
jdbcMutableAclService.setForeignKeysInDatabase(false); // switch on FK
// checking in the
// class, not database
- jdbcMutableAclService.deleteAcl(topParentOid, false);
+ jdbcMutableAclService.deleteAcl(getTopParentOid(), false);
fail("It should have thrown ChildrenExistException");
}
catch (ChildrenExistException expected) {
@@ -393,21 +413,21 @@ public void deleteAclWithChildrenThrowsException() throws Exception {
@Transactional
public void deleteAclRemovesRowsFromDatabase() throws Exception {
SecurityContextHolder.getContext().setAuthentication(auth);
- MutableAcl child = jdbcMutableAclService.createAcl(childOid);
+ MutableAcl child = jdbcMutableAclService.createAcl(getChildOid());
child.insertAce(0, BasePermission.DELETE, new PrincipalSid(auth), false);
jdbcMutableAclService.updateAcl(child);
// Remove the child and check all related database rows were removed accordingly
- jdbcMutableAclService.deleteAcl(childOid, false);
+ jdbcMutableAclService.deleteAcl(getChildOid(), false);
assertThat(
jdbcTemplate.queryForList(SELECT_ALL_CLASSES,
- new Object[] { TARGET_CLASS })).hasSize(1);
+ new Object[] { getTargetClass() })).hasSize(1);
assertThat(jdbcTemplate.queryForList("select * from acl_object_identity")
).isEmpty();
assertThat(jdbcTemplate.queryForList("select * from acl_entry")).isEmpty();
// Check the cache
- assertThat(aclCache.getFromCache(childOid)).isNull();
+ assertThat(aclCache.getFromCache(getChildOid())).isNull();
assertThat(aclCache.getFromCache(Long.valueOf(102))).isNull();
}
@@ -573,4 +593,11 @@ else if (sid instanceof GrantedAuthoritySid) {
}
}
+ protected Authentication getAuth() {
+ return auth;
+ }
+
+ protected JdbcMutableAclService getJdbcMutableAclService() {
+ return jdbcMutableAclService;
+ }
}
diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTestsWithAclClassId.java b/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTestsWithAclClassId.java
new file mode 100644
index 00000000000..21ca2a4e6b5
--- /dev/null
+++ b/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTestsWithAclClassId.java
@@ -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();
+ }
+}
diff --git a/acl/src/test/resources/jdbcMutableAclServiceTests-context.xml b/acl/src/test/resources/jdbcMutableAclServiceTests-context.xml
index 4c1802536a6..e748cb7d925 100644
--- a/acl/src/test/resources/jdbcMutableAclServiceTests-context.xml
+++ b/acl/src/test/resources/jdbcMutableAclServiceTests-context.xml
@@ -17,7 +17,10 @@
-
+
+
+
+
diff --git a/acl/src/test/resources/jdbcMutableAclServiceTestsWithAclClass-context.xml b/acl/src/test/resources/jdbcMutableAclServiceTestsWithAclClass-context.xml
new file mode 100644
index 00000000000..e0baeede48a
--- /dev/null
+++ b/acl/src/test/resources/jdbcMutableAclServiceTestsWithAclClass-context.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/manual/src/docs/asciidoc/index.adoc b/docs/manual/src/docs/asciidoc/index.adoc
index 21cba98a0a7..7464b9238d3 100644
--- a/docs/manual/src/docs/asciidoc/index.adoc
+++ b/docs/manual/src/docs/asciidoc/index.adoc
@@ -7279,7 +7279,7 @@ create table acl_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 bigint not null,
+ object_id_identity varchar_ignorecase(36) not null,
parent_object bigint,
owner_sid bigint,
entries_inheriting boolean not null,
@@ -7323,7 +7323,7 @@ create table acl_class(
create table acl_object_identity(
id bigserial primary key,
object_id_class bigint not null,
- object_id_identity bigint not null,
+ object_id_identity varchar(36) not null,
parent_object bigint,
owner_sid bigint,
entries_inheriting boolean not null,
@@ -7372,7 +7372,7 @@ CREATE TABLE acl_class (
CREATE TABLE acl_object_identity (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
object_id_class BIGINT UNSIGNED NOT NULL,
- object_id_identity BIGINT NOT NULL,
+ object_id_identity VARCHAR(36) NOT NULL,
parent_object BIGINT UNSIGNED,
owner_sid BIGINT UNSIGNED,
entries_inheriting BOOLEAN NOT NULL,
@@ -7416,7 +7416,7 @@ CREATE TABLE acl_class (
CREATE TABLE acl_object_identity (
id BIGINT NOT NULL IDENTITY PRIMARY KEY,
object_id_class BIGINT NOT NULL,
- object_id_identity BIGINT NOT NULL,
+ object_id_identity VARCHAR(36) NOT NULL,
parent_object BIGINT,
owner_sid BIGINT,
entries_inheriting BIT NOT NULL,
@@ -7474,7 +7474,7 @@ END;
CREATE TABLE acl_object_identity (
id NUMBER(38) NOT NULL PRIMARY KEY,
object_id_class NUMBER(38) NOT NULL,
- object_id_identity NUMBER(38) NOT NULL,
+ object_id_identity NVARCHAR2(36) NOT NULL,
parent_object NUMBER(38),
owner_sid NUMBER(38),
entries_inheriting NUMBER(1) NOT NULL CHECK (entries_inheriting in (0, 1)),
diff --git a/samples/xml/contacts/src/main/java/sample/contact/DataSourcePopulator.java b/samples/xml/contacts/src/main/java/sample/contact/DataSourcePopulator.java
index dce00eff5d2..559e564c2d4 100644
--- a/samples/xml/contacts/src/main/java/sample/contact/DataSourcePopulator.java
+++ b/samples/xml/contacts/src/main/java/sample/contact/DataSourcePopulator.java
@@ -95,11 +95,12 @@ public void afterPropertiesSet() throws Exception {
template.execute("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));");
template.execute("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 BIGINT NOT NULL,"
+ + "OBJECT_ID_IDENTITY VARCHAR_IGNORECASE(36) NOT NULL,"
+ "PARENT_OBJECT BIGINT,"
+ "OWNER_SID BIGINT,"
+ "ENTRIES_INHERITING BOOLEAN NOT NULL,"
diff --git a/samples/xml/dms/src/main/java/sample/dms/DataSourcePopulator.java b/samples/xml/dms/src/main/java/sample/dms/DataSourcePopulator.java
index 9da9b052e99..fa355d96d0c 100755
--- a/samples/xml/dms/src/main/java/sample/dms/DataSourcePopulator.java
+++ b/samples/xml/dms/src/main/java/sample/dms/DataSourcePopulator.java
@@ -48,8 +48,8 @@ public DataSourcePopulator(DataSource dataSource, DocumentDao documentDao) {
public void afterPropertiesSet() throws Exception {
// ACL tables
template.execute("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));");
- template.execute("CREATE TABLE ACL_CLASS(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,CLASS VARCHAR_IGNORECASE(100) NOT NULL,CONSTRAINT UNIQUE_UK_2 UNIQUE(CLASS));");
- template.execute("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 BIGINT 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));");
+ template.execute("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));");
+ template.execute("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));");
template.execute("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));");
// Normal authentication tables