JdbcAclService: fixes PostgreSql issue
When setup the acl tables as specified in the Spring.io documentation
I have faced the following error on a PostgreSql database:
org.postgresql.util.PSQLException: ERROR: operator does not exist:
bigint = character varying.
This is because the acl_object_identity.object_id_identity column is
of type varchar(36) but it is not necessarily accessed with a value
of type String.
- JdbcAclService / JdbcMutableAclService: SQL query must match
object_id_identity column specification
- JdbcAclService: changed JdbcTemplate to JdbcOperations for testability
- JdbcAclServiceTest: Increased test coverage,
the integration tests using embedded db relates to this commit
cd8d2079ed
Fixes gh-5508
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 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,21 +15,16 @@
|
||||
*/
|
||||
package org.springframework.security.acls.jdbc;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyList;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
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.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.domain.PrincipalSid;
|
||||
import org.springframework.security.acls.model.Acl;
|
||||
@@ -37,19 +32,54 @@ import org.springframework.security.acls.model.NotFoundException;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.*;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.AdditionalMatchers.aryEq;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Unit and Integration tests the ACL JdbcAclService using an
|
||||
* in-memory database.
|
||||
*
|
||||
* @author Nena Raab
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JdbcAclServiceTests {
|
||||
|
||||
private EmbeddedDatabase embeddedDatabase;
|
||||
|
||||
@Mock
|
||||
private DataSource dataSource;
|
||||
|
||||
@Mock
|
||||
private LookupStrategy lookupStrategy;
|
||||
|
||||
@Mock
|
||||
JdbcOperations jdbcOperations;
|
||||
|
||||
private JdbcAclService aclServiceIntegration;
|
||||
private JdbcAclService aclService;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
aclService = new JdbcAclService(dataSource, lookupStrategy);
|
||||
aclService = new JdbcAclService(jdbcOperations, lookupStrategy);
|
||||
aclServiceIntegration = new JdbcAclService(embeddedDatabase, lookupStrategy);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUpEmbeddedDatabase() {
|
||||
embeddedDatabase = new EmbeddedDatabaseBuilder()//
|
||||
.addScript("createAclSchemaWithAclClassIdType.sql")
|
||||
.addScript("db/sql/test_data_hierarchy.sql")
|
||||
.build();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDownEmbeddedDatabase() {
|
||||
embeddedDatabase.shutdown();
|
||||
}
|
||||
|
||||
// SEC-1898
|
||||
@@ -60,8 +90,110 @@ public class JdbcAclServiceTests {
|
||||
lookupStrategy.readAclsById(anyList(),
|
||||
anyList())).thenReturn(result);
|
||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(Object.class, 1);
|
||||
List<Sid> sids = Arrays.<Sid> asList(new PrincipalSid("user"));
|
||||
List<Sid> sids = Arrays.<Sid>asList(new PrincipalSid("user"));
|
||||
|
||||
aclService.readAclById(objectIdentity, sids);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneChildren() {
|
||||
List<ObjectIdentity> result = new ArrayList<>();
|
||||
result.add(new ObjectIdentityImpl(Object.class, "5577"));
|
||||
Object[] args = {"1", "org.springframework.security.acls.jdbc.JdbcAclServiceTests$MockLongIdDomainObject"};
|
||||
when(
|
||||
jdbcOperations.query(anyString(),
|
||||
aryEq(args), any(RowMapper.class))).thenReturn(result);
|
||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 1L);
|
||||
|
||||
List<ObjectIdentity> objectIdentities = aclService.findChildren(objectIdentity);
|
||||
assertThat(objectIdentities.size()).isEqualTo(1);
|
||||
assertThat(objectIdentities.get(0).getIdentifier()).isEqualTo("5577");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findNoChildren() {
|
||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 1L);
|
||||
|
||||
List<ObjectIdentity> objectIdentities = aclService.findChildren(objectIdentity);
|
||||
assertThat(objectIdentities).isNull();
|
||||
}
|
||||
|
||||
// ~ Some integration tests
|
||||
// ========================================================================================================
|
||||
|
||||
@Test
|
||||
public void findChildrenWithoutIdType() {
|
||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 4711L);
|
||||
|
||||
List<ObjectIdentity> objectIdentities = aclServiceIntegration.findChildren(objectIdentity);
|
||||
assertThat(objectIdentities.size()).isEqualTo(1);
|
||||
assertThat(objectIdentities.get(0).getType()).isEqualTo(MockUntypedIdDomainObject.class.getName());
|
||||
assertThat(objectIdentities.get(0).getIdentifier()).isEqualTo(5000L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findChildrenForUnknownObject() {
|
||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(Object.class, 33);
|
||||
|
||||
List<ObjectIdentity> objectIdentities = aclServiceIntegration.findChildren(objectIdentity);
|
||||
assertThat(objectIdentities).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findChildrenOfIdTypeLong() {
|
||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl("location", "US-PAL");
|
||||
|
||||
List<ObjectIdentity> objectIdentities = aclServiceIntegration.findChildren(objectIdentity);
|
||||
assertThat(objectIdentities.size()).isEqualTo(2);
|
||||
assertThat(objectIdentities.get(0).getType()).isEqualTo(MockLongIdDomainObject.class.getName());
|
||||
assertThat(objectIdentities.get(0).getIdentifier()).isEqualTo(4711L);
|
||||
assertThat(objectIdentities.get(1).getType()).isEqualTo(MockLongIdDomainObject.class.getName());
|
||||
assertThat(objectIdentities.get(1).getIdentifier()).isEqualTo(4712L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findChildrenOfIdTypeString() {
|
||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl("location", "US");
|
||||
|
||||
aclServiceIntegration.setAclClassIdSupported(true);
|
||||
List<ObjectIdentity> objectIdentities = aclServiceIntegration.findChildren(objectIdentity);
|
||||
assertThat(objectIdentities.size()).isEqualTo(1);
|
||||
assertThat(objectIdentities.get(0).getType()).isEqualTo("location");
|
||||
assertThat(objectIdentities.get(0).getIdentifier()).isEqualTo("US-PAL");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findChildrenOfIdTypeUUID() {
|
||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockUntypedIdDomainObject.class, 5000L);
|
||||
|
||||
aclServiceIntegration.setAclClassIdSupported(true);
|
||||
List<ObjectIdentity> objectIdentities = aclServiceIntegration.findChildren(objectIdentity);
|
||||
assertThat(objectIdentities.size()).isEqualTo(1);
|
||||
assertThat(objectIdentities.get(0).getType()).isEqualTo("costcenter");
|
||||
assertThat(objectIdentities.get(0).getIdentifier()).isEqualTo(UUID.fromString("25d93b3f-c3aa-4814-9d5e-c7c96ced7762"));
|
||||
}
|
||||
|
||||
private class MockLongIdDomainObject {
|
||||
private Object id;
|
||||
|
||||
public Object getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Object id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
private class MockUntypedIdDomainObject {
|
||||
private Object id;
|
||||
|
||||
public Object getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Object id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
17
acl/src/test/resources/db/sql/test_data_hierarchy.sql
Normal file
17
acl/src/test/resources/db/sql/test_data_hierarchy.sql
Normal file
@@ -0,0 +1,17 @@
|
||||
--- insert ACL data
|
||||
INSERT INTO ACL_SID (ID, PRINCIPAL, SID) VALUES
|
||||
(10, true, 'user');
|
||||
|
||||
INSERT INTO acl_class (id, class, class_id_type) VALUES
|
||||
(20,'location','java.lang.String'),
|
||||
(21,'org.springframework.security.acls.jdbc.JdbcAclServiceTests$MockLongIdDomainObject','java.lang.Long'),
|
||||
(22,'org.springframework.security.acls.jdbc.JdbcAclServiceTests$MockUntypedIdDomainObject',''),
|
||||
(23,'costcenter','java.util.UUID');
|
||||
|
||||
INSERT INTO acl_object_identity (id, object_id_class, object_id_identity, parent_object, owner_sid, entries_inheriting) VALUES
|
||||
(1,20,'US',NULL,10,false),
|
||||
(2,20,'US-PAL',1,10,true),
|
||||
(3,21,'4711',2,10,true),
|
||||
(4,21,'4712',2,10,true),
|
||||
(5,22,'5000',3,10,true),
|
||||
(6,23,'25d93b3f-c3aa-4814-9d5e-c7c96ced7762',5,10,true);
|
||||
Reference in New Issue
Block a user