SEC-1038: Changed JdbcMutableAclServiceTests to facilitate testing with PostgreSQL and updated JdbcMutableAclService to use a the id obtained from the ObjectIdentity directly rather than calling toString() on it before passing to the JDBC call.
This commit is contained in:
parent
29fafbbf18
commit
c6dfee69d4
|
@ -47,6 +47,13 @@
|
|||
<artifactId>hsqldb</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>8.3-603.jdbc3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -42,7 +42,14 @@ import org.springframework.util.Assert;
|
|||
|
||||
|
||||
/**
|
||||
* Provides a base implementation of {@link MutableAclService}.
|
||||
* Provides a base JDBC implementation of {@link MutableAclService}.
|
||||
* <p>
|
||||
* The default settings are for HSQLDB. If you are using a different database you
|
||||
* will probably need to set the {@link #setSidIdentityQuery(String) sidIdentityQuery} and
|
||||
* {@link #setClassIdentityQuery(String) classIdentityQuery} properties appropriately.
|
||||
* <p>
|
||||
* See the appendix of the Spring Security reference manual for more information on the expected schema
|
||||
* and how it is used. Information on using PostgreSQL is also included.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Johannes Zlattinger
|
||||
|
@ -55,8 +62,8 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||
private AclCache aclCache;
|
||||
private String deleteEntryByObjectIdentityForeignKey = "delete from acl_entry where acl_object_identity=?";
|
||||
private String deleteObjectIdentityByPrimaryKey = "delete from acl_object_identity where id=?";
|
||||
private String classIdentityQuery = "call identity()"; // should be overridden for postgres : select currval('acl_class_seq')
|
||||
private String sidIdentityQuery = "call identity()"; // should be overridden for postgres : select currval('acl_siq_seq')
|
||||
private String classIdentityQuery = "call identity()";
|
||||
private String sidIdentityQuery = "call identity()";
|
||||
private String insertClass = "insert into acl_class (class) values (?)";
|
||||
private String insertEntry = "insert into acl_entry "
|
||||
+ "(acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure)"
|
||||
|
@ -142,7 +149,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||
protected void createObjectIdentity(ObjectIdentity object, Sid owner) {
|
||||
Long sidId = createOrRetrieveSidPrimaryKey(owner, true);
|
||||
Long classId = createOrRetrieveClassPrimaryKey(object.getJavaType(), true);
|
||||
jdbcTemplate.update(insertObjectIdentity, classId, object.getIdentifier().toString(), sidId, Boolean.TRUE);
|
||||
jdbcTemplate.update(insertObjectIdentity, classId, object.getIdentifier(), sidId, Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -354,14 +361,26 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||
}
|
||||
}
|
||||
|
||||
public void setClassIdentityQuery(String identityQuery) {
|
||||
Assert.hasText(identityQuery, "New identity query is required");
|
||||
this.classIdentityQuery = identityQuery;
|
||||
/**
|
||||
* Sets the query that will be used to retrieve the identity of a newly created row in the <tt>acl_class</tt>
|
||||
* table.
|
||||
*
|
||||
* @param classIdentityQuery the query, which should return the identifier. Defaults to <tt>call identity()</tt>
|
||||
*/
|
||||
public void setClassIdentityQuery(String classIdentityQuery) {
|
||||
Assert.hasText(classIdentityQuery, "New classIdentityQuery query is required");
|
||||
this.classIdentityQuery = classIdentityQuery;
|
||||
}
|
||||
|
||||
public void setSidIdentityQuery(String identityQuery) {
|
||||
Assert.hasText(identityQuery, "New identity query is required");
|
||||
this.sidIdentityQuery = identityQuery;
|
||||
/**
|
||||
* Sets the query that will be used to retrieve the identity of a newly created row in the <tt>acl_sid</tt>
|
||||
* table.
|
||||
*
|
||||
* @param sidIdentityQuery the query, which should return the identifier. Defaults to <tt>call identity()</tt>
|
||||
*/
|
||||
public void setSidIdentityQuery(String sidIdentityQuery) {
|
||||
Assert.hasText(sidIdentityQuery, "New sidIdentityQuery query is required");
|
||||
this.sidIdentityQuery = sidIdentityQuery;
|
||||
}
|
||||
/**
|
||||
* @param foreignKeysInDatabase if false this class will perform additional FK constrain checking, which may
|
||||
|
|
|
@ -1,43 +1,46 @@
|
|||
-- ACL Schema SQL
|
||||
-- ACL schema sql used in HSQLDB
|
||||
|
||||
-- DROP TABLE ACL_ENTRY;
|
||||
-- DROP TABLE ACL_OBJECT_IDENTITY;
|
||||
-- DROP TABLE ACL_CLASS;
|
||||
-- DROP TABLE ACL_SID;
|
||||
-- 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_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,
|
||||
CONSTRAINT UNIQUE_UK_2 UNIQUE(CLASS));
|
||||
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)
|
||||
);
|
||||
|
||||
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));
|
||||
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)
|
||||
);
|
||||
|
||||
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));
|
||||
create table acl_entry(
|
||||
id bigint generated by default as identity(start with 100) not null primary key,
|
||||
acl_object_identity bigint not null,
|
||||
ace_order int not null,
|
||||
sid bigint not null,
|
||||
mask integer not null,
|
||||
granting boolean not null,
|
||||
audit_success boolean not null,
|
||||
audit_failure boolean not null,
|
||||
constraint unique_uk_4 unique(acl_object_identity,ace_order),
|
||||
constraint foreign_fk_4 foreign key(acl_object_identity) references acl_object_identity(id),
|
||||
constraint foreign_fk_5 foreign key(sid) references acl_sid(id)
|
||||
);
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
-- ACL Schema SQL for PostgreSQL
|
||||
|
||||
-- drop table acl_entry;
|
||||
-- drop table acl_object_identity;
|
||||
-- drop table acl_class;
|
||||
-- drop table acl_sid;
|
||||
|
||||
create table acl_sid(
|
||||
id bigserial not null primary key,
|
||||
principal boolean not null,
|
||||
sid varchar(100) not null,
|
||||
constraint unique_uk_1 unique(sid,principal)
|
||||
);
|
||||
|
||||
create table acl_class(
|
||||
id bigserial not null primary key,
|
||||
class varchar(100) not null,
|
||||
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,
|
||||
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 bigserial 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)
|
||||
);
|
|
@ -1,27 +1,39 @@
|
|||
-- Not required. Just shows the sort of queries being sent to DB.
|
||||
|
||||
|
||||
select ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY, ACL_ENTRY.ACE_ORDER,
|
||||
ACL_OBJECT_IDENTITY.ID as ACL_ID,
|
||||
ACL_OBJECT_IDENTITY.PARENT_OBJECT,
|
||||
ACL_OBJECT_IDENTITY,ENTRIES_INHERITING,
|
||||
ACL_ENTRY.ID as ACE_ID, ACL_ENTRY.MASK, ACL_ENTRY.GRANTING, ACL_ENTRY.AUDIT_SUCCESS, ACL_ENTRY.AUDIT_FAILURE,
|
||||
ACL_SID.PRINCIPAL as ACE_PRINCIPAL, ACL_SID.SID as ACE_SID,
|
||||
ACLI_SID.PRINCIPAL as ACL_PRINCIPAL, ACLI_SID.SID as ACL_SID,
|
||||
ACL_CLASS.CLASS
|
||||
select acl_object_identity.object_id_identity,
|
||||
acl_entry.ace_order,
|
||||
acl_object_identity.id as acl_id,
|
||||
acl_object_identity.parent_object,
|
||||
acl_object_identity,
|
||||
entries_inheriting,
|
||||
acl_entry.id as ace_id,
|
||||
acl_entry.mask,
|
||||
acl_entry.granting,
|
||||
acl_entry.audit_success,
|
||||
acl_entry.audit_failure,
|
||||
acl_sid.principal as ace_principal,
|
||||
acl_sid.sid as ace_sid,
|
||||
acli_sid.principal as acl_principal,
|
||||
acli_sid.sid as acl_sid,
|
||||
acl_class.class
|
||||
|
||||
from ACL_OBJECT_IDENTITY, ACL_SID ACLI_SID, ACL_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
|
||||
from acl_object_identity,
|
||||
acl_sid acli_sid,
|
||||
acl_class
|
||||
|
||||
where
|
||||
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
|
||||
acli_sid.id = acl_object_identity.owner_sid
|
||||
|
||||
and acl_class.id = acl_object_identity.object_id_class
|
||||
|
||||
ACLI_SID.ID = ACL_OBJECT_IDENTITY.OWNER_SID
|
||||
and ACL_CLASS.ID = ACL_OBJECT_IDENTITY.OBJECT_ID_CLASS
|
||||
and (
|
||||
(ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY = 1
|
||||
and ACL_CLASS.CLASS = 'sample.contact.Contact')
|
||||
or
|
||||
(ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY = 2000
|
||||
and ACL_CLASS.CLASS = 'sample.contact.Contact')
|
||||
) order by ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY asc, ACL_ENTRY.ACE_ORDER asc
|
||||
|
||||
(acl_object_identity.object_id_identity = 1 and acl_class.class = 'sample.contact.contact')
|
||||
or
|
||||
(acl_object_identity.object_id_identity = 2000 and acl_class.class = 'sample.contact.contact')
|
||||
|
||||
) order by acl_object_identity.object_id_identity asc, acl_entry.ace_order asc
|
||||
|
|
|
@ -1,208 +0,0 @@
|
|||
package org.springframework.security.acls.jdbc;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.Ehcache;
|
||||
|
||||
import org.springframework.cache.ehcache.EhCacheFactoryBean;
|
||||
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
import org.springframework.security.acls.MutableAcl;
|
||||
import org.springframework.security.acls.domain.AclAuthorizationStrategyImpl;
|
||||
import org.springframework.security.acls.domain.AclImpl;
|
||||
import org.springframework.security.acls.domain.BasePermission;
|
||||
import org.springframework.security.acls.domain.ConsoleAuditLogger;
|
||||
import org.springframework.security.acls.objectidentity.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.sid.GrantedAuthoritySid;
|
||||
import org.springframework.security.acls.sid.PrincipalSid;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.authority.GrantedAuthorityImpl;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
|
||||
public class AclPermissionInheritanceTests extends TestCase {
|
||||
|
||||
private JdbcMutableAclService aclService;
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
private DriverManagerDataSource dataSource;
|
||||
private DataSourceTransactionManager txManager;
|
||||
private TransactionStatus txStatus;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
|
||||
dataSource = new DriverManagerDataSource();
|
||||
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
|
||||
dataSource.setUrl("jdbc:hsqldb:mem:permissiontest");
|
||||
dataSource.setUsername("sa");
|
||||
dataSource.setPassword("");
|
||||
|
||||
jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
|
||||
txManager = new DataSourceTransactionManager();
|
||||
txManager.setDataSource(dataSource);
|
||||
|
||||
txStatus = txManager.getTransaction(new DefaultTransactionDefinition());
|
||||
|
||||
aclService = createAclService(dataSource);
|
||||
|
||||
Authentication auth = new UsernamePasswordAuthenticationToken("system", "secret",
|
||||
AuthorityUtils.createAuthorityList("ROLE_IGNORED"));
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
txManager.rollback(txStatus);
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
public void test1() throws Exception {
|
||||
|
||||
createAclSchema(jdbcTemplate);
|
||||
|
||||
ObjectIdentityImpl rootObject =
|
||||
new ObjectIdentityImpl(TestDomainObject.class, new Long(1));
|
||||
|
||||
MutableAcl parent = aclService.createAcl(rootObject);
|
||||
MutableAcl child = aclService.createAcl(new ObjectIdentityImpl(TestDomainObject.class, new Long(2)));
|
||||
child.setParent(parent);
|
||||
aclService.updateAcl(child);
|
||||
|
||||
parent = (AclImpl) aclService.readAclById(rootObject);
|
||||
parent.insertAce(0, BasePermission.READ,
|
||||
new PrincipalSid("john"), true);
|
||||
aclService.updateAcl(parent);
|
||||
|
||||
parent = (AclImpl) aclService.readAclById(rootObject);
|
||||
parent.insertAce(1, BasePermission.READ,
|
||||
new PrincipalSid("joe"), true);
|
||||
aclService.updateAcl(parent);
|
||||
|
||||
child = (MutableAcl) aclService.readAclById(
|
||||
new ObjectIdentityImpl(TestDomainObject.class, new Long(2)));
|
||||
|
||||
parent = (MutableAcl) child.getParentAcl();
|
||||
|
||||
assertEquals("Fails because child has a stale reference to its parent", 2, parent.getEntries().size());
|
||||
assertEquals(1, parent.getEntries().get(0).getPermission().getMask());
|
||||
assertEquals(new PrincipalSid("john"), parent.getEntries().get(0).getSid());
|
||||
assertEquals(1, parent.getEntries().get(1).getPermission().getMask());
|
||||
assertEquals(new PrincipalSid("joe"), parent.getEntries().get(1).getSid());
|
||||
|
||||
}
|
||||
public void test2() throws Exception {
|
||||
|
||||
createAclSchema(jdbcTemplate);
|
||||
|
||||
ObjectIdentityImpl rootObject =
|
||||
new ObjectIdentityImpl(TestDomainObject.class, new Long(1));
|
||||
|
||||
MutableAcl parent = aclService.createAcl(rootObject);
|
||||
MutableAcl child = aclService.createAcl(new ObjectIdentityImpl(TestDomainObject.class, new Long(2)));
|
||||
child.setParent(parent);
|
||||
aclService.updateAcl(child);
|
||||
|
||||
parent.insertAce(0, BasePermission.ADMINISTRATION,
|
||||
new GrantedAuthoritySid("ROLE_ADMINISTRATOR"), true);
|
||||
aclService.updateAcl(parent);
|
||||
|
||||
parent.insertAce(1, BasePermission.DELETE, new PrincipalSid("terry"), true);
|
||||
aclService.updateAcl(parent);
|
||||
|
||||
child = (MutableAcl) aclService.readAclById(
|
||||
new ObjectIdentityImpl(TestDomainObject.class, new Long(2)));
|
||||
|
||||
parent = (MutableAcl) child.getParentAcl();
|
||||
|
||||
assertEquals(2, parent.getEntries().size());
|
||||
assertEquals(16, parent.getEntries().get(0).getPermission().getMask());
|
||||
assertEquals(new GrantedAuthoritySid("ROLE_ADMINISTRATOR"), parent.getEntries().get(0).getSid());
|
||||
assertEquals(8, parent.getEntries().get(1).getPermission().getMask());
|
||||
assertEquals(new PrincipalSid("terry"), parent.getEntries().get(1).getSid());
|
||||
|
||||
}
|
||||
|
||||
private JdbcMutableAclService createAclService(DriverManagerDataSource ds)
|
||||
throws IOException {
|
||||
|
||||
GrantedAuthorityImpl adminAuthority = new GrantedAuthorityImpl("ROLE_ADMINISTRATOR");
|
||||
AclAuthorizationStrategyImpl authStrategy = new AclAuthorizationStrategyImpl(
|
||||
new GrantedAuthorityImpl[]{adminAuthority,adminAuthority,adminAuthority});
|
||||
|
||||
EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
|
||||
ehCacheManagerFactoryBean.afterPropertiesSet();
|
||||
CacheManager cacheManager = (CacheManager) ehCacheManagerFactoryBean.getObject();
|
||||
|
||||
EhCacheFactoryBean ehCacheFactoryBean = new EhCacheFactoryBean();
|
||||
ehCacheFactoryBean.setCacheName("aclAche");
|
||||
ehCacheFactoryBean.setCacheManager(cacheManager);
|
||||
ehCacheFactoryBean.afterPropertiesSet();
|
||||
Ehcache ehCache = (Ehcache) ehCacheFactoryBean.getObject();
|
||||
|
||||
AclCache aclAche = new EhCacheBasedAclCache(ehCache);
|
||||
|
||||
BasicLookupStrategy lookupStrategy =
|
||||
new BasicLookupStrategy(ds, aclAche, authStrategy, new ConsoleAuditLogger());
|
||||
|
||||
return new JdbcMutableAclService(ds,lookupStrategy, aclAche);
|
||||
}
|
||||
|
||||
private void createAclSchema(JdbcTemplate jdbcTemplate) {
|
||||
|
||||
jdbcTemplate.execute("DROP TABLE ACL_ENTRY IF EXISTS;");
|
||||
jdbcTemplate.execute("DROP TABLE ACL_OBJECT_IDENTITY IF EXISTS;");
|
||||
jdbcTemplate.execute("DROP TABLE ACL_CLASS IF EXISTS");
|
||||
jdbcTemplate.execute("DROP TABLE ACL_SID IF EXISTS");
|
||||
|
||||
jdbcTemplate.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));");
|
||||
jdbcTemplate.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));");
|
||||
jdbcTemplate.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));");
|
||||
jdbcTemplate.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));");
|
||||
}
|
||||
|
||||
public static class TestDomainObject {
|
||||
|
||||
private Long id;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,15 +16,12 @@ package org.springframework.security.acls.jdbc;
|
|||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
@ -37,17 +34,21 @@ import org.springframework.security.acls.MutableAcl;
|
|||
import org.springframework.security.acls.NotFoundException;
|
||||
import org.springframework.security.acls.Permission;
|
||||
import org.springframework.security.acls.TargetObject;
|
||||
import org.springframework.security.acls.domain.AclImpl;
|
||||
import org.springframework.security.acls.domain.BasePermission;
|
||||
import org.springframework.security.acls.domain.CumulativePermission;
|
||||
import org.springframework.security.acls.objectidentity.ObjectIdentity;
|
||||
import org.springframework.security.acls.objectidentity.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.sid.GrantedAuthoritySid;
|
||||
import org.springframework.security.acls.sid.PrincipalSid;
|
||||
import org.springframework.security.acls.sid.Sid;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.test.annotation.Rollback;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
|
||||
import org.springframework.test.context.transaction.AfterTransaction;
|
||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
|
@ -69,9 +70,9 @@ public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4Sprin
|
|||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(100));
|
||||
private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(101));
|
||||
private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(102));
|
||||
private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100));
|
||||
private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(101));
|
||||
private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(102));
|
||||
|
||||
@Autowired
|
||||
private JdbcMutableAclService jdbcMutableAclService;
|
||||
|
@ -86,12 +87,18 @@ public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4Sprin
|
|||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@Before
|
||||
public void createTables() throws IOException {
|
||||
new DatabaseSeeder(dataSource, new ClassPathResource("createAclSchema.sql"));
|
||||
@BeforeTransaction
|
||||
public void createTables() throws Exception {
|
||||
try {
|
||||
new DatabaseSeeder(dataSource, new ClassPathResource("createAclSchema.sql"));
|
||||
// new DatabaseSeeder(dataSource, new ClassPathResource("createAclSchemaPostgres.sql"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
@AfterTransaction
|
||||
public void clearContextAndData() throws Exception {
|
||||
SecurityContextHolder.clearContext();
|
||||
jdbcTemplate.execute("drop table acl_entry");
|
||||
|
@ -102,7 +109,6 @@ public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4Sprin
|
|||
|
||||
@Test
|
||||
@Transactional
|
||||
@Rollback
|
||||
public void testLifecycle() {
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
|
@ -239,8 +245,7 @@ public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4Sprin
|
|||
*/
|
||||
@Test
|
||||
@Transactional
|
||||
@Rollback
|
||||
public void testDeleteAclAlsoDeletesChildren() throws Exception {
|
||||
public void deleteAclAlsoDeletesChildren() throws Exception {
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
jdbcMutableAclService.createAcl(topParentOid);
|
||||
|
@ -313,10 +318,9 @@ public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4Sprin
|
|||
|
||||
@Test
|
||||
@Transactional
|
||||
@Rollback
|
||||
public void testCreateAclForADuplicateDomainObject() throws Exception {
|
||||
public void createAclForADuplicateDomainObject() throws Exception {
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
ObjectIdentity duplicateOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(100));
|
||||
ObjectIdentity duplicateOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100));
|
||||
jdbcMutableAclService.createAcl(duplicateOid);
|
||||
// Try to add the same object second time
|
||||
try {
|
||||
|
@ -329,8 +333,7 @@ public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4Sprin
|
|||
|
||||
@Test
|
||||
@Transactional
|
||||
@Rollback
|
||||
public void testDeleteAclRejectsNullParameters() throws Exception {
|
||||
public void deleteAclRejectsNullParameters() throws Exception {
|
||||
try {
|
||||
jdbcMutableAclService.deleteAcl(null, true);
|
||||
fail("It should have thrown IllegalArgumentException");
|
||||
|
@ -341,8 +344,7 @@ public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4Sprin
|
|||
|
||||
@Test
|
||||
@Transactional
|
||||
@Rollback
|
||||
public void testDeleteAclWithChildrenThrowsException() throws Exception {
|
||||
public void deleteAclWithChildrenThrowsException() throws Exception {
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
MutableAcl parent = jdbcMutableAclService.createAcl(topParentOid);
|
||||
MutableAcl child = jdbcMutableAclService.createAcl(middleParentOid);
|
||||
|
@ -364,8 +366,7 @@ public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4Sprin
|
|||
|
||||
@Test
|
||||
@Transactional
|
||||
@Rollback
|
||||
public void testDeleteAclRemovesRowsFromDatabase() throws Exception {
|
||||
public void deleteAclRemovesRowsFromDatabase() throws Exception {
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
MutableAcl child = jdbcMutableAclService.createAcl(childOid);
|
||||
child.insertAce(0, BasePermission.DELETE, new PrincipalSid(auth), false);
|
||||
|
@ -379,13 +380,12 @@ public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4Sprin
|
|||
|
||||
// Check the cache
|
||||
assertNull(aclCache.getFromCache(childOid));
|
||||
assertNull(aclCache.getFromCache(new Long(102)));
|
||||
assertNull(aclCache.getFromCache(Long.valueOf(102)));
|
||||
}
|
||||
|
||||
/** SEC-1107 */
|
||||
@Test
|
||||
@Transactional
|
||||
@Rollback
|
||||
public void identityWithIntegerIdIsSupportedByCreateAcl() throws Exception {
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(101));
|
||||
|
@ -397,14 +397,15 @@ public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4Sprin
|
|||
/**
|
||||
* SEC-655
|
||||
*/
|
||||
/* public void testClearChildrenFromCacheWhenParentIsUpdated() throws Exception {
|
||||
Authentication auth = new TestingAuthenticationToken("ben", "ignored",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ADMINISTRATOR")});
|
||||
@Test
|
||||
@Transactional
|
||||
public void childrenAreClearedFromCacheWhenParentIsUpdated() throws Exception {
|
||||
Authentication auth = new TestingAuthenticationToken("ben", "ignored","ROLE_ADMINISTRATOR");
|
||||
auth.setAuthenticated(true);
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
ObjectIdentity parentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(104));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(105));
|
||||
ObjectIdentity parentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(104));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(105));
|
||||
|
||||
MutableAcl parent = jdbcMutableAclService.createAcl(parentOid);
|
||||
MutableAcl child = jdbcMutableAclService.createAcl(childOid);
|
||||
|
@ -413,46 +414,80 @@ public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4Sprin
|
|||
jdbcMutableAclService.updateAcl(child);
|
||||
|
||||
parent = (AclImpl) jdbcMutableAclService.readAclById(parentOid);
|
||||
parent.insertAce(null, BasePermission.READ, new PrincipalSid("ben"), true);
|
||||
parent.insertAce(0, BasePermission.READ, new PrincipalSid("ben"), true);
|
||||
jdbcMutableAclService.updateAcl(parent);
|
||||
|
||||
parent = (AclImpl) jdbcMutableAclService.readAclById(parentOid);
|
||||
parent.insertAce(null, BasePermission.READ, new PrincipalSid("scott"), true);
|
||||
parent.insertAce(1, BasePermission.READ, new PrincipalSid("scott"), true);
|
||||
jdbcMutableAclService.updateAcl(parent);
|
||||
|
||||
child = (MutableAcl) jdbcMutableAclService.readAclById(childOid);
|
||||
parent = (MutableAcl) child.getParentAcl();
|
||||
|
||||
assertEquals("Fails because child has a stale reference to its parent", 2, parent.getEntries().size());
|
||||
assertEquals(1, parent.getEntries()[0].getPermission().getMask());
|
||||
assertEquals(new PrincipalSid("ben"), parent.getEntries()[0].getSid());
|
||||
assertEquals(1, parent.getEntries()[1].getPermission().getMask());
|
||||
assertEquals(new PrincipalSid("scott"), parent.getEntries()[1].getSid());
|
||||
}*/
|
||||
assertEquals(1, parent.getEntries().get(0).getPermission().getMask());
|
||||
assertEquals(new PrincipalSid("ben"), parent.getEntries().get(0).getSid());
|
||||
assertEquals(1, parent.getEntries().get(1).getPermission().getMask());
|
||||
assertEquals(new PrincipalSid("scott"), parent.getEntries().get(1).getSid());
|
||||
}
|
||||
|
||||
/* public void testCumulativePermissions() {
|
||||
setComplete();
|
||||
Authentication auth = new TestingAuthenticationToken("ben", "ignored", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ADMINISTRATOR")});
|
||||
auth.setAuthenticated(true);
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
/**
|
||||
* SEC-655
|
||||
*/
|
||||
@Test
|
||||
@Transactional
|
||||
public void childrenAreClearedFromCacheWhenParentisUpdated2() throws Exception {
|
||||
Authentication auth = new TestingAuthenticationToken("system", "secret","ROLE_IGNORED");
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
ObjectIdentityImpl rootObject = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(1));
|
||||
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(110));
|
||||
MutableAcl topParent = jdbcMutableAclService.createAcl(topParentOid);
|
||||
MutableAcl parent = jdbcMutableAclService.createAcl(rootObject);
|
||||
MutableAcl child = jdbcMutableAclService.createAcl(new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(2)));
|
||||
child.setParent(parent);
|
||||
jdbcMutableAclService.updateAcl(child);
|
||||
|
||||
// Add an ACE permission entry
|
||||
CumulativePermission cm = new CumulativePermission().set(BasePermission.READ).set(BasePermission.ADMINISTRATION);
|
||||
assertEquals(17, cm.getMask());
|
||||
topParent.insertAce(null, cm, new PrincipalSid(auth), true);
|
||||
parent.insertAce(0, BasePermission.ADMINISTRATION, new GrantedAuthoritySid("ROLE_ADMINISTRATOR"), true);
|
||||
jdbcMutableAclService.updateAcl(parent);
|
||||
|
||||
parent.insertAce(1, BasePermission.DELETE, new PrincipalSid("terry"), true);
|
||||
jdbcMutableAclService.updateAcl(parent);
|
||||
|
||||
child = (MutableAcl) jdbcMutableAclService.readAclById(new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(2)));
|
||||
|
||||
parent = (MutableAcl) child.getParentAcl();
|
||||
|
||||
assertEquals(2, parent.getEntries().size());
|
||||
assertEquals(16, parent.getEntries().get(0).getPermission().getMask());
|
||||
assertEquals(new GrantedAuthoritySid("ROLE_ADMINISTRATOR"), parent.getEntries().get(0).getSid());
|
||||
assertEquals(8, parent.getEntries().get(1).getPermission().getMask());
|
||||
assertEquals(new PrincipalSid("terry"), parent.getEntries().get(1).getSid());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void cumulativePermissions() {
|
||||
Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_ADMINISTRATOR");
|
||||
auth.setAuthenticated(true);
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(110));
|
||||
MutableAcl topParent = jdbcMutableAclService.createAcl(topParentOid);
|
||||
|
||||
// Add an ACE permission entry
|
||||
Permission cm = new CumulativePermission().set(BasePermission.READ).set(BasePermission.ADMINISTRATION);
|
||||
assertEquals(17, cm.getMask());
|
||||
Sid benSid = new PrincipalSid(auth);
|
||||
topParent.insertAce(0, cm, benSid, true);
|
||||
assertEquals(1, topParent.getEntries().size());
|
||||
|
||||
// Explictly save the changed ACL
|
||||
// Explicitly save the changed ACL
|
||||
topParent = jdbcMutableAclService.updateAcl(topParent);
|
||||
|
||||
// Check the mask was retrieved correctly
|
||||
assertEquals(17, topParent.getEntries()[0].getPermission().getMask());
|
||||
assertTrue(topParent.isGranted(new Permission[] {cm}, pSid, true));
|
||||
assertEquals(17, topParent.getEntries().get(0).getPermission().getMask());
|
||||
assertTrue(topParent.isGranted(Arrays.asList(cm), Arrays.asList(benSid), true));
|
||||
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
|
|
@ -54,8 +54,22 @@
|
|||
<constructor-arg ref="dataSource"/>
|
||||
<constructor-arg ref="lookupStrategy"/>
|
||||
<constructor-arg ref="aclCache"/>
|
||||
|
||||
<!-- Uncomment to use PostgreSQL
|
||||
<property name="classIdentityQuery" value="select currval(pg_get_serial_sequence('acl_class', 'id'))"/>
|
||||
<property name="sidIdentityQuery" value="select currval(pg_get_serial_sequence('acl_sid', 'id'))"/>
|
||||
-->
|
||||
</bean>
|
||||
|
||||
<!-- PostgreSQL DataSource configuration
|
||||
|
||||
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
|
||||
<property name="driverClassName" value="org.postgresql.Driver"/>
|
||||
<property name="url" value="jdbc:postgresql://localhost:5432/acltest"/>
|
||||
<property name="username" value="acltest"/>
|
||||
<property name="password" value="acltest"/>
|
||||
</bean>
|
||||
-->
|
||||
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
|
||||
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
|
||||
<property name="url" value="jdbc:hsqldb:mem:acltest"/>
|
Loading…
Reference in New Issue