spring-projects / spring-security

Spring Security
http://spring.io/projects/spring-security
Apache License 2.0
8.78k stars 5.89k forks source link

Fail to insert into acl_entry when build acl twice with reset between the two execution #14934

Closed leoporcelli closed 5 months ago

leoporcelli commented 6 months ago

Describe the bug Hi. First of all, a little disclaimer. Is the first time I open an issue in Github, so please be patient is I do something wrong and, indeed, I'm open to any suggestion on how to do this better.

Back to us: I've tried to integrate ACLs into my project. When I first execute the init of the data (with sample data to test the APIs) everything goes well. The data are insered and secured correcly. But, if I execute a DB reset (also resetting the ACLs tables) and then I execute the data init again I get the following error (Note: without ant stack trace, I don't kwon why) PreparedStatementCallback; SQL [insert into acl_entry (acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure)values (?, ?, ?, ?, ?, ?, ?)]; Batch entry 0 insert into acl_entry (acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure)values (('1'::int8), ('0'::int4), ('1'::int8), ('16'::int4), ('TRUE'), ('FALSE'), ('FALSE')) was aborted: ERROR: insert or update on table "acl_entry" violates foreign key constraint "foreign_fk_4" Details: Key (acl_object_identity)=(1) is not present in table "acl_object_identity". Call getNextException to see other errors in the batch.

To Reproduce This is the ACLs tables schema: `drop table if exists acl_entry; drop table if exists acl_object_identity; drop table if exists acl_class; drop table if exists acl_sid;

create table IF NOT EXISTS 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 IF NOT EXISTS acl_class( id bigserial not null primary key, class varchar(100) not null, constraint unique_uk_2 unique(class) );

create table IF NOT EXISTS acl_object_identity( id bigserial primary key, object_id_class bigint not null, object_id_identity varchar(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 IF NOT EXISTS 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) );`

The AclManagerService.java file (without imports) `@Component public class AclManagerService {

@Autowired private JdbcMutableAclService aclService; public void addUserPermission(User user, String principal) { ObjectIdentity oi = new ObjectIdentityImpl(User.class, user.getId()); log.info(user.getId().toString()); updateAcl(oi, principal, BasePermission.ADMINISTRATION, true);

}

private void updateAcl(ObjectIdentity oi, String principal, Permission p, boolean grantAccess) { Sid sid = new PrincipalSid(principal);

// Create or read the relevant ACL
MutableAcl acl = null;
try {
  acl = (MutableAcl) aclService.readAclById(oi, List.of(sid));
} catch (NotFoundException nfe) {
  acl = aclService.createAcl(oi);
}

for (int i = acl.getEntries().size() - 1; i > 0; i--) {
  acl.deleteAce(i);
}

if (grantAccess) {
  // Now grant some permissions via an access control entry (ACE)
  acl.insertAce(0, p, sid, true);
}
try {
  aclService.updateAcl(acl);
} catch (Exception ex) {
  System.out.println(ex.getMessage());
}

}

}`

The AclContext.java class `@Configuration @EnableWebSecurity public class AclContext {

@Autowired private DataSource dataSource; /**

Thank you

jzheaux commented 5 months ago

Thanks for getting in touch, @leoporcelli! It feels like this is a question that would be better suited to Stack Overflow. We prefer to use GitHub issues only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it) or add more detail if you feel this is a genuine bug.