Refactor ACL database tables.

This commit is contained in:
Ben Alex 2004-07-31 03:42:18 +00:00
parent 437c89892c
commit 13d5a2dbca
7 changed files with 390 additions and 126 deletions

View File

@ -33,7 +33,6 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
@ -46,12 +45,11 @@ import javax.sql.DataSource;
* </p>
*
* <p>
* A default database structure is assumed (see {@link
* #DEF_ACLS_BY_OBJECT_IDENTITY_QUERY}). This may be overridden by setting the
* default query strings to use. If this does not provide enough flexibility,
* another strategy would be to subclass this class and override the {@link
* MappingSqlQuery} instance used, via the {@link #initMappingSqlQueries()}
* extension point.
* A default database structure is assumed. This may be overridden by setting
* the default query strings to use. If this does not provide enough
* flexibility, another strategy would be to subclass this class and override
* the {@link MappingSqlQuery} instance used, via the {@link
* #initMappingSqlQueries()} extension point.
* </p>
*
* @author Ben Alex
@ -60,18 +58,23 @@ import javax.sql.DataSource;
public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
//~ Static fields/initializers =============================================
public static final String DEF_ACLS_BY_OBJECT_IDENTITY_QUERY = "SELECT OBJECT_IDENTITY, RECIPIENT, PARENT_OBJECT_IDENTITY, MASK, ACL_CLASS FROM acls WHERE object_identity = ?";
public static final String RECIPIENT_USED_FOR_INHERITENCE_MARKER = "___INHERITENCE_MARKER_ONLY___";
public static final String DEF_ACLS_BY_OBJECT_IDENTITY_QUERY = "SELECT RECIPIENT, MASK FROM acl_permission WHERE acl_object_identity = ?";
public static final String DEF_OBJECT_PROPERTIES_QUERY = "SELECT ID, OBJECT_IDENTITY, ACL_CLASS, PARENT.OBJECT_IDENTITY as PARENT_OBJECT_IDENTITY FROM acl_object_identity LEFT OUTER JOIN acl_object_identity as PARENT ON acl_object_identity.parent_object=parent.id WHERE parent.id=acl_object_identity.parent_object and object_identity = ?";
private static final Log logger = LogFactory.getLog(JdbcDaoSupport.class);
//~ Instance fields ========================================================
private MappingSqlQuery aclsByObjectIdentity;
private MappingSqlQuery objectProperties;
private String aclsByObjectIdentityQuery;
private String objectPropertiesQuery;
//~ Constructors ===========================================================
public JdbcDaoImpl() {
aclsByObjectIdentityQuery = DEF_ACLS_BY_OBJECT_IDENTITY_QUERY;
objectPropertiesQuery = DEF_OBJECT_PROPERTIES_QUERY;
}
//~ Methods ================================================================
@ -114,26 +117,36 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
String aclObjectIdentityString = neoi.getClassname() + ":"
+ neoi.getId();
// Lookup the BasicAclEntrys from RDBMS (may include null responses)
List acls = aclsByObjectIdentity.execute(aclObjectIdentityString);
// Lookup the object's main properties from the RDBMS (guaranteed no nulls)
List objects = objectProperties.execute(aclObjectIdentityString);
// Now prune list of null responses (to meet interface contract)
List toReturnAcls = new Vector();
Iterator iter = acls.iterator();
while (iter.hasNext()) {
Object object = iter.next();
if (object != null) {
toReturnAcls.add(object);
}
if (objects.size() == 0) {
// this is an unknown object identity string
return null;
}
// Return null if nothing of use found (to meet interface contract)
if (toReturnAcls.size() > 0) {
return (BasicAclEntry[]) toReturnAcls.toArray(new BasicAclEntry[] {});
// Cast to an object properties holder (there should only be one record)
AclDetailsHolder propertiesInformation = (AclDetailsHolder) objects.get(0);
// Lookup the object's ACLs from RDBMS (guaranteed no nulls)
List acls = aclsByObjectIdentity.execute(propertiesInformation
.getForeignKeyId());
if (acls.size() == 0) {
// return merely an inheritence marker (as we know about the object but it has no related ACLs)
return new BasicAclEntry[] {createBasicAclEntry(propertiesInformation,
null)};
} else {
return null;
// return the individual ACL instances
AclDetailsHolder[] aclHolders = (AclDetailsHolder[]) acls.toArray(new AclDetailsHolder[] {});
List toReturnAcls = new Vector();
for (int i = 0; i < aclHolders.length; i++) {
toReturnAcls.add(createBasicAclEntry(propertiesInformation,
aclHolders[i]));
}
return (BasicAclEntry[]) toReturnAcls.toArray(new BasicAclEntry[] {});
}
}
@ -164,6 +177,18 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
return aclsByObjectIdentityQuery;
}
public void setObjectProperties(MappingSqlQuery objectPropertiesQuery) {
this.objectProperties = objectPropertiesQuery;
}
public void setObjectPropertiesQuery(String queryString) {
objectPropertiesQuery = queryString;
}
public String getObjectPropertiesQuery() {
return objectPropertiesQuery;
}
protected void initDao() throws ApplicationContextException {
initMappingSqlQueries();
}
@ -174,70 +199,151 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
*/
protected void initMappingSqlQueries() {
setAclsByObjectIdentity(new AclsByObjectIdentityMapping(getDataSource()));
setObjectProperties(new ObjectPropertiesMapping(getDataSource()));
}
/**
* Constructs an individual <code>BasicAclEntry</code> from the passed
* <code>AclDetailsHolder</code>s.
*
* <P>
* Guarantees to never return <code>null</code> (exceptions are thrown in
* the event of any issues).
* </p>
*
* @param propertiesInformation mandatory information about which instance
* to create, the object identity, and the parent object identity
* (<code>null</code> or empty <code>String</code>s prohibited for
* <code>aclClass</code> and <code>aclObjectIdentity</code>
* @param aclInformation optional information about the individual ACL
* record (if <code>null</code> only an "inheritence marker"
* instance is returned; if not <code>null</code>, it is prohibited
* to present <code>null</code> or an empty <code>String</code> for
* <code>recipient</code>)
*
* @return a fully populated instance suitable for use by external objects
*
* @throws IllegalArgumentException if the indicated ACL class could not be
* created
*/
private BasicAclEntry createBasicAclEntry(
AclDetailsHolder propertiesInformation, AclDetailsHolder aclInformation) {
BasicAclEntry entry;
try {
entry = (BasicAclEntry) propertiesInformation.getAclClass()
.newInstance();
} catch (InstantiationException ie) {
throw new IllegalArgumentException(ie.getMessage());
} catch (IllegalAccessException iae) {
throw new IllegalArgumentException(iae.getMessage());
}
entry.setAclObjectIdentity(propertiesInformation.getAclObjectIdentity());
entry.setAclObjectParentIdentity(propertiesInformation
.getAclObjectParentIdentity());
if (aclInformation == null) {
// this is an inheritence marker instance only
entry.setMask(0);
entry.setRecipient(RECIPIENT_USED_FOR_INHERITENCE_MARKER);
} else {
// this is an individual ACL entry
entry.setMask(aclInformation.getMask());
entry.setRecipient(aclInformation.getRecipient());
}
return entry;
}
//~ Inner Classes ==========================================================
/**
* Query object to look up ACL entries.
* Query object to look up individual ACL entries.
*
* <P>
* Returns the generic <code>AclDetailsHolder</code> object.
* </p>
*
* <P>
* Guarantees to never return <code>null</code> (exceptions are thrown in
* the event of any issues).
* </p>
*
* <P>
* The executed SQL requires the following information be made available
* from the indicated placeholders: 1. OBJECT_IDENTITY, 2. RECIPIENT, 3.
* PARENT_OBJECT_IDENTITY, 4. MASK, and 5. ACL_CLASS
* from the indicated placeholders: 1. RECIPIENT, 2. MASK.
* </p>
*/
protected class AclsByObjectIdentityMapping extends MappingSqlQuery {
protected AclsByObjectIdentityMapping(DataSource ds) {
super(ds, aclsByObjectIdentityQuery);
declareParameter(new SqlParameter(Types.INTEGER));
compile();
}
protected Object mapRow(ResultSet rs, int rownum)
throws SQLException {
String recipient = rs.getString(1);
int mask = rs.getInt(2);
if ((recipient == null) || "".equals(recipient)) {
throw new IllegalArgumentException("recipient required");
}
return new AclDetailsHolder(recipient, mask);
}
}
/**
* Query object to look up properties for an object identity.
*
* <P>
* Returns the generic <code>AclDetailsHolder</code> object.
* </p>
*
* <P>
* Guarantees to never return <code>null</code> (exceptions are thrown in
* the event of any issues).
* </p>
*
* <P>
* The executed SQL requires the following information be made available
* from the indicated placeholders: 1. ID, 2. OBJECT_IDENTITY, 3.
* ACL_CLASS and 4. PARENT_OBJECT_IDENTITY.
* </p>
*/
protected class ObjectPropertiesMapping extends MappingSqlQuery {
protected ObjectPropertiesMapping(DataSource ds) {
super(ds, objectPropertiesQuery);
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
protected Object mapRow(ResultSet rs, int rownum)
throws SQLException {
String objectIdentity = rs.getString(1);
String recipient = rs.getString(2);
String parentObjectIdentity = rs.getString(3);
int mask = rs.getInt(4);
String aclClass = rs.getString(5);
int id = rs.getInt(1); // required
String objectIdentity = rs.getString(2); // required
String aclClass = rs.getString(3); // required
String parentObjectIdentity = rs.getString(4); // optional
// Try to create the indicated BasicAclEntry class
BasicAclEntry entry;
if ((objectIdentity == null) || "".equals(objectIdentity)
|| (aclClass == null) || "".equals(aclClass)) {
// shouldn't happen if DB schema defined NOT NULL columns
throw new IllegalArgumentException(
"required DEF_OBJECT_PROPERTIES_QUERY value returned null or empty");
}
Class aclClazz;
try {
Class aclClazz = this.getClass().getClassLoader().loadClass(aclClass);
entry = (BasicAclEntry) aclClazz.newInstance();
aclClazz = this.getClass().getClassLoader().loadClass(aclClass);
} catch (ClassNotFoundException cnf) {
logger.error(cnf);
return null;
} catch (InstantiationException ie) {
logger.error(ie);
return null;
} catch (IllegalAccessException iae) {
logger.error(iae);
return null;
throw new IllegalArgumentException(cnf.getMessage());
}
// Now set each of the ACL's properties
entry.setAclObjectIdentity(buildIdentity(objectIdentity));
entry.setAclObjectParentIdentity(buildIdentity(parentObjectIdentity));
entry.setRecipient(recipient);
entry.setMask(mask);
if ((entry.getRecipient() == null)
|| (entry.getAclObjectIdentity() == null)) {
// Problem with retrieval of ACL
// (shouldn't happen if DB schema defined NOT NULL columns)
logger.error("recipient or aclObjectIdentity is null");
return null;
}
return entry;
return new AclDetailsHolder(id, buildIdentity(objectIdentity),
buildIdentity(parentObjectIdentity), aclClazz);
}
private AclObjectIdentity buildIdentity(String identity) {
@ -253,4 +359,88 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
return new NamedEntityObjectIdentity(classname, id);
}
}
/**
* Used to hold details of a domain object instance's properties, or an
* individual ACL entry.
*
* <P>
* Not all properties will be set. The actual properties set will depend on
* which <code>MappingSqlQuery</code> creates the object.
* </p>
*
* <P>
* Does not enforce <code>null</code>s or empty <code>String</code>s as
* this is performed by the <code>MappingSqlQuery</code> objects (or
* preferably the backend RDBMS via schema constraints).
* </p>
*/
private class AclDetailsHolder {
private AclObjectIdentity aclObjectIdentity;
private AclObjectIdentity aclObjectParentIdentity;
private Class aclClass;
private Object recipient;
private int foreignKeyId;
private int mask;
/**
* Record details of an individual ACL entry (usually from the
* ACL_PERMISSION table)
*
* @param recipient the recipient
* @param mask the integer to be masked
*/
public AclDetailsHolder(Object recipient, int mask) {
this.recipient = recipient;
this.mask = mask;
}
/**
* Record details of a domain object instance's properties (usually
* from the ACL_OBJECT_IDENTITY table)
*
* @param foreignKeyId used by the
* <code>AclsByObjectIdentityMapping</code> to locate the
* individual ACL entries
* @param aclObjectIdentity the object identity of the domain object
* instance
* @param aclObjectParentIdentity the object identity of the domain
* object instance's parent
* @param aclClass the class of which a new instance which should be
* created for each individual ACL entry (or an inheritence
* "holder" class if there are no ACL entries)
*/
public AclDetailsHolder(int foreignKeyId,
AclObjectIdentity aclObjectIdentity,
AclObjectIdentity aclObjectParentIdentity, Class aclClass) {
this.foreignKeyId = foreignKeyId;
this.aclObjectIdentity = aclObjectIdentity;
this.aclObjectParentIdentity = aclObjectParentIdentity;
this.aclClass = aclClass;
}
public Class getAclClass() {
return aclClass;
}
public AclObjectIdentity getAclObjectIdentity() {
return aclObjectIdentity;
}
public AclObjectIdentity getAclObjectParentIdentity() {
return aclObjectParentIdentity;
}
public int getForeignKeyId() {
return foreignKeyId;
}
public int getMask() {
return mask;
}
public Object getRecipient() {
return recipient;
}
}
}

View File

@ -63,7 +63,9 @@ public class PopulatedDatabase {
template.execute(
"CREATE UNIQUE INDEX IX_AUTH_USERNAME ON AUTHORITIES(USERNAME,AUTHORITY)");
template.execute(
"CREATE TABLE ACLS(OBJECT_IDENTITY VARCHAR_IGNORECASE(250) NOT NULL,RECIPIENT VARCHAR_IGNORECASE(100) NOT NULL,PARENT_OBJECT_IDENTITY VARCHAR_IGNORECASE(250),MASK INTEGER NOT NULL,ACL_CLASS VARCHAR_IGNORECASE(250) NOT NULL,CONSTRAINT PK_ACLS PRIMARY KEY(OBJECT_IDENTITY,RECIPIENT))");
"CREATE TABLE ACL_OBJECT_IDENTITY(ID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,OBJECT_IDENTITY VARCHAR_IGNORECASE(250) NOT NULL,PARENT_OBJECT INTEGER,ACL_CLASS VARCHAR_IGNORECASE(250) NOT NULL,CONSTRAINT UNIQUE_OBJECT_IDENTITY UNIQUE(OBJECT_IDENTITY),CONSTRAINT SYS_FK_3 FOREIGN KEY(PARENT_OBJECT) REFERENCES ACL_OBJECT_IDENTITY(ID))");
template.execute(
"CREATE TABLE ACL_PERMISSION(ID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,ACL_OBJECT_IDENTITY INTEGER NOT NULL,RECIPIENT VARCHAR_IGNORECASE(100) NOT NULL,MASK INTEGER NOT NULL,CONSTRAINT UNIQUE_RECIPIENT UNIQUE(ACL_OBJECT_IDENTITY,RECIPIENT),CONSTRAINT SYS_FK_7 FOREIGN KEY(ACL_OBJECT_IDENTITY) REFERENCES ACL_OBJECT_IDENTITY(ID))");
template.execute("SET IGNORECASE TRUE");
template.execute("INSERT INTO USERS VALUES('dianne','emu',TRUE)");
template.execute("INSERT INTO USERS VALUES('marissa','koala',TRUE)");
@ -81,22 +83,30 @@ public class PopulatedDatabase {
template.execute(
"INSERT INTO AUTHORITIES VALUES('peter','ROLE_TELLER')");
template.execute(
"INSERT INTO ACLS VALUES('net.sf.acegisecurity.acl.DomainObject:1','ROLE_SUPERVISOR',NULL,1,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')");
"INSERT INTO acl_object_identity VALUES (1, 'net.sf.acegisecurity.acl.DomainObject:1', null, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');");
template.execute(
"INSERT INTO ACLS VALUES('net.sf.acegisecurity.acl.DomainObject:2','marissa','net.sf.acegisecurity.acl.DomainObject:1',2,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')");
"INSERT INTO acl_object_identity VALUES (2, 'net.sf.acegisecurity.acl.DomainObject:2', 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');");
template.execute(
"INSERT INTO ACLS VALUES('net.sf.acegisecurity.acl.DomainObject:2','ROLE_SUPERVISOR','net.sf.acegisecurity.acl.DomainObject:1',0,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')");
"INSERT INTO acl_object_identity VALUES (3, 'net.sf.acegisecurity.acl.DomainObject:3', 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');");
template.execute(
"INSERT INTO ACLS VALUES('net.sf.acegisecurity.acl.DomainObject:3','scott','net.sf.acegisecurity.acl.DomainObject:1',14,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')");
"INSERT INTO acl_object_identity VALUES (4, 'net.sf.acegisecurity.acl.DomainObject:4', 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');");
template.execute(
"INSERT INTO ACLS VALUES('net.sf.acegisecurity.acl.DomainObject:4','inheritance_marker_only','net.sf.acegisecurity.acl.DomainObject:1',0,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')");
"INSERT INTO acl_object_identity VALUES (5, 'net.sf.acegisecurity.acl.DomainObject:5', 3, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');");
template.execute(
"INSERT INTO ACLS VALUES('net.sf.acegisecurity.acl.DomainObject:5','inheritance_marker_only','net.sf.acegisecurity.acl.DomainObject:3',0,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')");
"INSERT INTO acl_object_identity VALUES (6, 'net.sf.acegisecurity.acl.DomainObject:6', 3, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');");
// ----- BEGIN deviation from normal sample data load script -----
template.execute(
"INSERT INTO ACLS VALUES('net.sf.acegisecurity.acl.DomainObject:6','scott','net.sf.acegisecurity.acl.DomainObject:3',1,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')");
"INSERT INTO acl_object_identity VALUES (7, 'net.sf.acegisecurity.acl.DomainObject:7', 3, 'some.invalid.acl.entry.class');");
// ----- FINISH deviation from normal sample data load script -----
template.execute(
"INSERT INTO ACLS VALUES('net.sf.acegisecurity.acl.DomainObject:7','scott','some.invalid.parent:1',2,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')");
"INSERT INTO acl_permission VALUES (null, 1, 'ROLE_SUPERVISOR', 1);");
template.execute(
"INSERT INTO ACLS VALUES('net.sf.acegisecurity.acl.DomainObject:8','scott','net.sf.acegisecurity.acl.DomainObject:3',1,'some.invalid.basic.acl.entry.class.name')");
"INSERT INTO acl_permission VALUES (null, 2, 'ROLE_SUPERVISOR', 0);");
template.execute(
"INSERT INTO acl_permission VALUES (null, 2, 'marissa', 2);");
template.execute(
"INSERT INTO acl_permission VALUES (null, 3, 'scott', 14);");
template.execute(
"INSERT INTO acl_permission VALUES (null, 6, 'scott', 1);");
}
}

View File

@ -59,7 +59,22 @@ public class JdbcDaoImplTests extends TestCase {
junit.textui.TestRunner.run(JdbcDaoImplTests.class);
}
public void testGetsAclsWhichExistInDatabase() throws Exception {
public void testExceptionThrownIfBasicAclEntryClassNotFound()
throws Exception {
JdbcDaoImpl dao = makePopulatedJdbcDao();
AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY,
"7");
try {
dao.getAcls(identity);
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertTrue(true);
}
}
public void testGetsEntriesWhichExistInDatabaseAndHaveAcls()
throws Exception {
JdbcDaoImpl dao = makePopulatedJdbcDao();
AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY,
"2");
@ -67,6 +82,26 @@ public class JdbcDaoImplTests extends TestCase {
assertEquals(2, acls.length);
}
public void testGetsEntriesWhichExistInDatabaseButHaveNoAcls()
throws Exception {
JdbcDaoImpl dao = makePopulatedJdbcDao();
AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY,
"5");
BasicAclEntry[] acls = dao.getAcls(identity);
assertEquals(1, acls.length);
assertEquals(JdbcDaoImpl.RECIPIENT_USED_FOR_INHERITENCE_MARKER,
acls[0].getRecipient());
}
public void testGetsEntriesWhichHaveNoParent() throws Exception {
JdbcDaoImpl dao = makePopulatedJdbcDao();
AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY,
"1");
BasicAclEntry[] acls = dao.getAcls(identity);
assertEquals(1, acls.length);
assertNull(acls[0].getAclObjectParentIdentity());
}
public void testGettersSetters() throws Exception {
JdbcDaoImpl dao = makePopulatedJdbcDao();
dao.setAclsByObjectIdentity(new MockMappingSqlQuery());
@ -74,15 +109,9 @@ public class JdbcDaoImplTests extends TestCase {
dao.setAclsByObjectIdentityQuery("foo");
assertEquals("foo", dao.getAclsByObjectIdentityQuery());
}
public void testNullReturnedIfBasicAclEntryClassNotFound()
throws Exception {
JdbcDaoImpl dao = makePopulatedJdbcDao();
AclObjectIdentity identity = new NamedEntityObjectIdentity(OBJECT_IDENTITY,
"8");
BasicAclEntry[] result = dao.getAcls(identity);
assertNull(result);
dao.setObjectPropertiesQuery("foobar");
assertEquals("foobar", dao.getObjectPropertiesQuery());
}
public void testNullReturnedIfEntityNotFound() throws Exception {
@ -93,7 +122,7 @@ public class JdbcDaoImplTests extends TestCase {
assertNull(result);
}
public void testRejectsNonNamedEntityObjectIdentity()
public void testReturnsNullForUnNamedEntityObjectIdentity()
throws Exception {
JdbcDaoImpl dao = new JdbcDaoImpl();
AclObjectIdentity identity = new AclObjectIdentity() {}

View File

@ -3208,23 +3208,41 @@ public java.lang.Object getRecipient();</programlisting></para>
default database schema and some sample data will aid in understanding
its function:</para>
<para><programlisting>CREATE TABLE acls (
object_identity VARCHAR_IGNORECASE(250) NOT NULL,
recipient VARCHAR_IGNORECASE(100) NOT NULL,
parent_object_identity VARCHAR_IGNORECASE(250),
mask INTEGER NOT NULL,
acl_class VARCHAR_IGNORECASE(250) NOT NULL,
CONSTRAINT pk_acls PRIMARY KEY(object_identity, recipient)
<para><programlisting>CREATE TABLE acl_object_identity (
id IDENTITY NOT NULL,
object_identity VARCHAR_IGNORECASE(250) NOT NULL,
parent_object INTEGER,
acl_class VARCHAR_IGNORECASE(250) NOT NULL,
CONSTRAINT unique_object_identity UNIQUE(object_identity),
FOREIGN KEY (parent_object) REFERENCES acl_object_identity(id)
);
INSERT INTO acls VALUES ('corp.DomainObject:1', 'ROLE_SUPERVISOR', null, 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acls VALUES ('corp.DomainObject:2', 'ROLE_SUPERVISOR', 'corp.DomainObject:1', 0, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acls VALUES ('corp.DomainObject:2', 'marissa', 'corp.DomainObject:1', 2, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acls VALUES ('corp.DomainObject:3', 'scott', 'corp.DomainObject:1', 14, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acls VALUES ('corp.DomainObject:4', 'inheritance_marker_only', 'corp.DomainObject:1', 0, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acls VALUES ('corp.DomainObject:5', 'inheritance_marker_only', 'corp.DomainObject:3', 0, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acls VALUES ('corp.DomainObject:6', 'scott', 'corp.DomainObject:3', 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acls VALUES ('corp.DomainObject:7', 'scott', 'some.invalid.parent:1', 2, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');</programlisting></para>
CREATE TABLE acl_permission (
id IDENTITY NOT NULL,
acl_object_identity INTEGER NOT NULL,
recipient VARCHAR_IGNORECASE(100) NOT NULL,
mask INTEGER NOT NULL,
CONSTRAINT unique_recipient UNIQUE(acl_object_identity, recipient),
FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity(id)
);
INSERT INTO acl_object_identity VALUES (1, 'corp.DomainObject:1', null, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acl_object_identity VALUES (2, 'corp.DomainObject:2', 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acl_object_identity VALUES (3, 'corp.DomainObject:3', 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acl_object_identity VALUES (4, 'corp.DomainObject:4', 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acl_object_identity VALUES (5, 'corp.DomainObject:5', 3, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acl_object_identity VALUES (6, 'corp.DomainObject:6', 3, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acl_permission VALUES (null, 1, 'ROLE_SUPERVISOR', 1);
INSERT INTO acl_permission VALUES (null, 2, 'ROLE_SUPERVISOR', 0);
INSERT INTO acl_permission VALUES (null, 2, 'marissa', 2);
INSERT INTO acl_permission VALUES (null, 3, 'scott', 14);
INSERT INTO acl_permission VALUES (null, 6, 'scott', 1);</programlisting></para>
<para>As can be seen, database-specific constraints are used
extensively to ensure the integrity of the ACL information. If you
need to use a different database (Hypersonic SQL statements are shown
above), you should try to implement equivalent constraints.</para>
<para>The <literal>JdbcDaoImpl</literal> will only respond to requests
for <literal>NamedEntityObjectIdentity</literal>s. It converts such
@ -3312,8 +3330,7 @@ INSERT INTO acls VALUES ('corp.DomainObject:7', 'scott', 'some.invalid.parent:1'
--- 5 ROLE_SUPERVISOR Administer (from parent #3)
--- scott Read, Write, Create (from parent #3)
--- 6 ROLE_SUPERVISOR Administer (from parent #3)
--- scott Administer (overrides parent #3)
--- 7 scott Read (invalid parent ignored)</programlisting></para>
--- scott Administer (overrides parent #3)</programlisting></para>
<para>So the above explains how a domain object instance has its
<literal>AclObjectIdentity</literal> discovered, and the

View File

@ -1,5 +1,5 @@
#HSQL database
#Wed Jul 28 02:20:39 GMT 2004
#Sat Jul 31 02:59:13 GMT 2004
hsqldb.script_format=0
runtime.gc_interval=0
sql.enforce_strict_size=false

View File

@ -1,7 +1,8 @@
CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(50) NOT NULL,ENABLED BOOLEAN NOT NULL)
CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME))
CREATE UNIQUE INDEX IX_AUTH_USERNAME ON AUTHORITIES(USERNAME,AUTHORITY)
CREATE TABLE ACLS(OBJECT_IDENTITY VARCHAR_IGNORECASE(250) NOT NULL,RECIPIENT VARCHAR_IGNORECASE(100) NOT NULL,PARENT_OBJECT_IDENTITY VARCHAR_IGNORECASE(250),MASK INTEGER NOT NULL,ACL_CLASS VARCHAR_IGNORECASE(250) NOT NULL,CONSTRAINT PK_ACLS PRIMARY KEY(OBJECT_IDENTITY,RECIPIENT))
CREATE TABLE ACL_OBJECT_IDENTITY(ID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,OBJECT_IDENTITY VARCHAR_IGNORECASE(250) NOT NULL,PARENT_OBJECT INTEGER,ACL_CLASS VARCHAR_IGNORECASE(250) NOT NULL,CONSTRAINT UNIQUE_OBJECT_IDENTITY UNIQUE(OBJECT_IDENTITY),CONSTRAINT SYS_FK_3 FOREIGN KEY(PARENT_OBJECT) REFERENCES ACL_OBJECT_IDENTITY(ID))
CREATE TABLE ACL_PERMISSION(ID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,ACL_OBJECT_IDENTITY INTEGER NOT NULL,RECIPIENT VARCHAR_IGNORECASE(100) NOT NULL,MASK INTEGER NOT NULL,CONSTRAINT UNIQUE_RECIPIENT UNIQUE(ACL_OBJECT_IDENTITY,RECIPIENT),CONSTRAINT SYS_FK_7 FOREIGN KEY(ACL_OBJECT_IDENTITY) REFERENCES ACL_OBJECT_IDENTITY(ID))
SET IGNORECASE TRUE
CREATE USER SA PASSWORD "" ADMIN
INSERT INTO USERS VALUES('dianne','emu',TRUE)
@ -13,11 +14,14 @@ INSERT INTO AUTHORITIES VALUES('marissa','ROLE_SUPERVISOR')
INSERT INTO AUTHORITIES VALUES('dianne','ROLE_TELLER')
INSERT INTO AUTHORITIES VALUES('scott','ROLE_TELLER')
INSERT INTO AUTHORITIES VALUES('peter','ROLE_TELLER')
INSERT INTO ACLS VALUES('net.sf.acegisecurity.acl.DomainObject:1','ROLE_SUPERVISOR',NULL,1,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')
INSERT INTO ACLS VALUES('net.sf.acegisecurity.acl.DomainObject:2','marissa','net.sf.acegisecurity.acl.DomainObject:1',2,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')
INSERT INTO ACLS VALUES('net.sf.acegisecurity.acl.DomainObject:2','ROLE_SUPERVISOR','net.sf.acegisecurity.acl.DomainObject:1',0,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')
INSERT INTO ACLS VALUES('net.sf.acegisecurity.acl.DomainObject:3','scott','net.sf.acegisecurity.acl.DomainObject:1',14,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')
INSERT INTO ACLS VALUES('net.sf.acegisecurity.acl.DomainObject:4','inheritance_marker_only','net.sf.acegisecurity.acl.DomainObject:1',0,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')
INSERT INTO ACLS VALUES('net.sf.acegisecurity.acl.DomainObject:5','inheritance_marker_only','net.sf.acegisecurity.acl.DomainObject:3',0,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')
INSERT INTO ACLS VALUES('net.sf.acegisecurity.acl.DomainObject:6','scott','net.sf.acegisecurity.acl.DomainObject:3',1,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')
INSERT INTO ACLS VALUES('net.sf.acegisecurity.acl.DomainObject:7','scott','some.invalid.parent:1',2,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')
INSERT INTO ACL_OBJECT_IDENTITY VALUES(1,'net.sf.acegisecurity.acl.DomainObject:1',NULL,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')
INSERT INTO ACL_OBJECT_IDENTITY VALUES(2,'net.sf.acegisecurity.acl.DomainObject:2',1,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')
INSERT INTO ACL_OBJECT_IDENTITY VALUES(3,'net.sf.acegisecurity.acl.DomainObject:3',1,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')
INSERT INTO ACL_OBJECT_IDENTITY VALUES(4,'net.sf.acegisecurity.acl.DomainObject:4',1,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')
INSERT INTO ACL_OBJECT_IDENTITY VALUES(5,'net.sf.acegisecurity.acl.DomainObject:5',3,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')
INSERT INTO ACL_OBJECT_IDENTITY VALUES(6,'net.sf.acegisecurity.acl.DomainObject:6',3,'net.sf.acegisecurity.acl.basic.SimpleAclEntry')
INSERT INTO ACL_PERMISSION VALUES(0,1,'ROLE_SUPERVISOR',1)
INSERT INTO ACL_PERMISSION VALUES(1,2,'ROLE_SUPERVISOR',0)
INSERT INTO ACL_PERMISSION VALUES(2,2,'marissa',2)
INSERT INTO ACL_PERMISSION VALUES(3,3,'scott',14)
INSERT INTO ACL_PERMISSION VALUES(4,6,'scott',1)

View File

@ -27,13 +27,24 @@ INSERT INTO authorities VALUES ('dianne', 'ROLE_TELLER');
INSERT INTO authorities VALUES ('scott', 'ROLE_TELLER');
INSERT INTO authorities VALUES ('peter', 'ROLE_TELLER');
CREATE TABLE acls (
object_identity VARCHAR_IGNORECASE(250) NOT NULL,
recipient VARCHAR_IGNORECASE(100) NOT NULL,
parent_object_identity VARCHAR_IGNORECASE(250),
mask INTEGER NOT NULL,
acl_class VARCHAR_IGNORECASE(250) NOT NULL,
CONSTRAINT pk_acls PRIMARY KEY(object_identity, recipient)
--- Indexes auto created in HSQLDB for primary keys and unique columns
CREATE TABLE acl_object_identity (
id IDENTITY NOT NULL,
object_identity VARCHAR_IGNORECASE(250) NOT NULL,
parent_object INTEGER,
acl_class VARCHAR_IGNORECASE(250) NOT NULL,
CONSTRAINT unique_object_identity UNIQUE(object_identity),
FOREIGN KEY (parent_object) REFERENCES acl_object_identity(id)
);
CREATE TABLE acl_permission (
id IDENTITY NOT NULL,
acl_object_identity INTEGER NOT NULL,
recipient VARCHAR_IGNORECASE(100) NOT NULL,
mask INTEGER NOT NULL,
CONSTRAINT unique_recipient UNIQUE(acl_object_identity, recipient),
FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity(id)
);
--- Mask integer 0 = no permissions
@ -56,16 +67,19 @@ CREATE TABLE acls (
--- scott Read, Write, Create (from parent #3)
--- 6 ROLE_SUPERVISOR Administer (from parent #3)
--- scott Administer (overrides parent #3)
--- 7 scott Read (invalid parent ignored)
---------------------------------------------------------------------
INSERT INTO acls VALUES ('net.sf.acegisecurity.acl.DomainObject:1', 'ROLE_SUPERVISOR', null, 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acls VALUES ('net.sf.acegisecurity.acl.DomainObject:2', 'ROLE_SUPERVISOR', 'net.sf.acegisecurity.acl.DomainObject:1', 0, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acls VALUES ('net.sf.acegisecurity.acl.DomainObject:2', 'marissa', 'net.sf.acegisecurity.acl.DomainObject:1', 2, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acls VALUES ('net.sf.acegisecurity.acl.DomainObject:3', 'scott', 'net.sf.acegisecurity.acl.DomainObject:1', 14, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acls VALUES ('net.sf.acegisecurity.acl.DomainObject:4', 'inheritance_marker_only', 'net.sf.acegisecurity.acl.DomainObject:1', 0, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acls VALUES ('net.sf.acegisecurity.acl.DomainObject:5', 'inheritance_marker_only', 'net.sf.acegisecurity.acl.DomainObject:3', 0, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acls VALUES ('net.sf.acegisecurity.acl.DomainObject:6', 'scott', 'net.sf.acegisecurity.acl.DomainObject:3', 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acls VALUES ('net.sf.acegisecurity.acl.DomainObject:7', 'scott', 'some.invalid.parent:1', 2, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acl_object_identity VALUES (1, 'net.sf.acegisecurity.acl.DomainObject:1', null, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acl_object_identity VALUES (2, 'net.sf.acegisecurity.acl.DomainObject:2', 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acl_object_identity VALUES (3, 'net.sf.acegisecurity.acl.DomainObject:3', 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acl_object_identity VALUES (4, 'net.sf.acegisecurity.acl.DomainObject:4', 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acl_object_identity VALUES (5, 'net.sf.acegisecurity.acl.DomainObject:5', 3, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acl_object_identity VALUES (6, 'net.sf.acegisecurity.acl.DomainObject:6', 3, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
INSERT INTO acl_permission VALUES (null, 1, 'ROLE_SUPERVISOR', 1);
INSERT INTO acl_permission VALUES (null, 2, 'ROLE_SUPERVISOR', 0);
INSERT INTO acl_permission VALUES (null, 2, 'marissa', 2);
INSERT INTO acl_permission VALUES (null, 3, 'scott', 14);
INSERT INTO acl_permission VALUES (null, 6, 'scott', 1);