This is an automated email from the ASF dual-hosted git repository.

matrei pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/grails-spring-security.git


The following commit(s) were added to refs/heads/7.0.x by this push:
     new 4011ce69 ACL Plugin 7.0.x fixes (#1154)
4011ce69 is described below

commit 4011ce6993fef0392f8f23292787060365c8bcfb
Author: Eugene Kamenev <eugene.kame...@gmail.com>
AuthorDate: Wed Aug 20 18:26:15 2025 +0500

    ACL Plugin 7.0.x fixes (#1154)
    
    * fix: add dirty check to acl identity
    
    * fix: do not fetch all records from db
    
    * fix: sid matching, maxOrder, common save
    
    * fix: review comments
    
    * fix: test cases
    
    * fix: remove return
    
    * fix: move method to AclService & test cases
    
    * fix: remove redundant condition
---
 .../acl/AclObjectIdentityGormService.groovy        |  8 +---
 .../plugin/springsecurity/acl/AclService.groovy    | 50 ++++++++++++----------
 .../acl/AbstractAclObjectIdentity.groovy           |  2 +
 .../springsecurity/acl/AclObjectIdentity.groovy    |  2 +
 .../groovy/spec/AclEntrySpec.groovy                |  8 ++--
 5 files changed, 36 insertions(+), 34 deletions(-)

diff --git 
a/plugin-acl/plugin/grails-app/services/grails/plugin/springsecurity/acl/AclObjectIdentityGormService.groovy
 
b/plugin-acl/plugin/grails-app/services/grails/plugin/springsecurity/acl/AclObjectIdentityGormService.groovy
index c72de8c7..a8a42390 100644
--- 
a/plugin-acl/plugin/grails-app/services/grails/plugin/springsecurity/acl/AclObjectIdentityGormService.groovy
+++ 
b/plugin-acl/plugin/grails-app/services/grails/plugin/springsecurity/acl/AclObjectIdentityGormService.groovy
@@ -21,7 +21,6 @@ package grails.plugin.springsecurity.acl
 
 import grails.gorm.DetachedCriteria
 import grails.gorm.transactions.ReadOnly
-import groovy.transform.CompileDynamic
 import groovy.transform.CompileStatic
 import org.springframework.security.acls.model.ObjectIdentity
 
@@ -42,14 +41,9 @@ class AclObjectIdentityGormService {
         AclObjectIdentity.get(id)
     }
 
-    @CompileDynamic
     @ReadOnly
     List<AclObjectIdentity> findAllByParentObjectIdAndParentAclClassName(Long 
objectId, String aclClassName) {
-        //findQueryByParentObjectIdAndParentAclClassName(objectId, 
aclClassName).list()
-        List<AclObjectIdentity> aclObjectIdentityList = findAll()
-        aclObjectIdentityList.findAll { AclObjectIdentity oid ->
-            (oid?.parent?.aclClass?.className == aclClassName) &&  ( 
oid?.parent?.objectId == objectId)
-        }
+        findQueryByParentObjectIdAndParentAclClassName(objectId, 
aclClassName).list()
     }
 
     @ReadOnly
diff --git 
a/plugin-acl/plugin/grails-app/services/grails/plugin/springsecurity/acl/AclService.groovy
 
b/plugin-acl/plugin/grails-app/services/grails/plugin/springsecurity/acl/AclService.groovy
index 91961a4c..602fe74b 100644
--- 
a/plugin-acl/plugin/grails-app/services/grails/plugin/springsecurity/acl/AclService.groovy
+++ 
b/plugin-acl/plugin/grails-app/services/grails/plugin/springsecurity/acl/AclService.groovy
@@ -22,6 +22,7 @@ import grails.gorm.transactions.ReadOnly
 import groovy.transform.CompileDynamic
 import groovy.transform.CompileStatic
 import groovy.util.logging.Slf4j
+import org.grails.datastore.gorm.GormEntity
 import org.springframework.context.MessageSource
 import org.springframework.security.acls.domain.AccessControlEntryImpl
 import org.springframework.security.acls.domain.GrantedAuthoritySid
@@ -97,10 +98,7 @@ class AclService implements MutableAclService, WarnErros {
                                objectId: object.identifier as Long,
                                owner: ownerSid,
                                entriesInheriting: true)
-               if ( !aclObjectIdentity.save() ) {
-                       log.error '{}', errorsBeanBeingSaved(messageSource, 
aclObjectIdentity)
-               }
-               aclObjectIdentity
+               save(aclObjectIdentity)
        }
 
        @Transactional
@@ -124,9 +122,7 @@ class AclService implements MutableAclService, WarnErros {
                AclSid aclSid = 
aclSidGormService.findBySidAndPrincipal(sidName, principal)
                if (!aclSid && allowCreate) {
                        aclSid = new AclSid(sid: sidName, principal: principal)
-                       if ( !aclSid.save() ) {
-                               log.error '{}', 
errorsBeanBeingSaved(messageSource, aclSid)
-                       }
+                       save(aclSid)
                }
                aclSid
        }
@@ -136,9 +132,7 @@ class AclService implements MutableAclService, WarnErros {
                AclClass aclClass = 
aclClassGormService.findByClassName(className)
                if (!aclClass && allowCreate) {
                        aclClass = new AclClass(className: className)
-                       if ( !aclClass.save() ) {
-                               log.error '{}', 
errorsBeanBeingSaved(messageSource, aclClass)
-                       }
+                       save(aclClass)
                }
                aclClass
        }
@@ -209,7 +203,7 @@ class AclService implements MutableAclService, WarnErros {
                        log.trace 'Checking ace for delete: {}', ace
                        !acl.entries.find { AccessControlEntry entry ->
                                log.trace 'Checking entry for delete: {}', entry
-                               entry.permission.mask == ace.mask && entry.sid 
== ace.sid.sid
+                               entryEqual(ace, entry)
                        }
                }
 
@@ -217,15 +211,17 @@ class AclService implements MutableAclService, WarnErros {
                        log.trace 'Checking entry for create: {}', entry
                        !existingAces.find { AclEntry ace ->
                                log.trace 'Checking ace for create: {}', ace
-                               entry.permission.mask == ace.mask && entry.sid 
== ace.sid.sid
+                               entryEqual(ace, entry)
                        }
                }
 
+               Integer maxAceOrder = existingAces.max { it.aceOrder }?.aceOrder
+
                // Delete this ACL's ACEs in the acl_entry table
                deleteEntries toDelete
 
                // Create this ACL's ACEs in the acl_entry table
-               createEntries(acl, toCreate as 
List<AuditableAccessControlEntry>)
+               createEntries(acl, maxAceOrder, toCreate as 
List<AuditableAccessControlEntry>)
 
                // Change the mutable columns in acl_object_identity
                updateObjectIdentity acl
@@ -237,10 +233,9 @@ class AclService implements MutableAclService, WarnErros {
        }
 
        @Transactional
-       protected void createEntries(MutableAcl acl, 
List<AuditableAccessControlEntry> entries = null) {
-               List<AuditableAccessControlEntry> entryList = entries ?: 
acl.entries as List<AuditableAccessControlEntry>
-               int i = 0
-               for (AuditableAccessControlEntry entry in entryList) {
+       protected void createEntries(MutableAcl acl, Integer maxOrder, 
List<AuditableAccessControlEntry> entries) {
+               int i = maxOrder != null ? maxOrder + 1 : 0
+               for (AuditableAccessControlEntry entry in entries) {
                        Assert.isInstanceOf AccessControlEntryImpl, entry, 
'Unknown ACE class'
                        AclEntry aclEntryInstance = new AclEntry(
                                        aclObjectIdentity: 
AclObjectIdentity.load(acl.id),
@@ -250,9 +245,7 @@ class AclService implements MutableAclService, WarnErros {
                                        granting: entry.isGranting(),
                                        auditSuccess: entry.isAuditSuccess(),
                                        auditFailure: entry.isAuditFailure())
-                       if ( !aclEntryInstance.save() ) {
-                               log.error "{}", 
errorsBeanBeingSaved(messageSource, aclEntryInstance)
-                       }
+                       save(aclEntryInstance)
                }
        }
 
@@ -272,9 +265,7 @@ class AclService implements MutableAclService, WarnErros {
                aclObjectIdentity.parent = parent
                aclObjectIdentity.owner = createOrRetrieveSid(acl.owner, true)
                aclObjectIdentity.entriesInheriting = acl.isEntriesInheriting()
-               if ( !aclObjectIdentity.save() ) {
-                       log.error "{}", errorsBeanBeingSaved(messageSource, 
aclObjectIdentity)
-               }
+               save(aclObjectIdentity)
                AclObjectIdentity.withSession { it.flush() }
        }
 
@@ -335,4 +326,17 @@ class AclService implements MutableAclService, WarnErros {
                }
                return result
        }
+
+    @Transactional
+       protected <T extends GormEntity<T>> T save(T bean) {
+               if (!bean.save()) {
+            log.warn errorsBeanBeingSaved(messageSource, bean)
+               }
+               bean
+       }
+
+    private static boolean entryEqual(AclEntry ace, AccessControlEntry entry) {
+        Sid sid = ace.sid.principal ? new PrincipalSid(ace.sid.sid) : new 
GrantedAuthoritySid(ace.sid.sid)
+        return entry.permission.mask == ace.mask && entry.sid == sid && 
entry.granting == ace.granting
+    }
 }
diff --git 
a/plugin-acl/plugin/src/main/groovy/grails/plugin/springsecurity/acl/AbstractAclObjectIdentity.groovy
 
b/plugin-acl/plugin/src/main/groovy/grails/plugin/springsecurity/acl/AbstractAclObjectIdentity.groovy
index ec5d1275..bb717fb5 100644
--- 
a/plugin-acl/plugin/src/main/groovy/grails/plugin/springsecurity/acl/AbstractAclObjectIdentity.groovy
+++ 
b/plugin-acl/plugin/src/main/groovy/grails/plugin/springsecurity/acl/AbstractAclObjectIdentity.groovy
@@ -18,6 +18,7 @@
  */
 package grails.plugin.springsecurity.acl
 
+import grails.gorm.dirty.checking.DirtyCheck
 import groovy.transform.EqualsAndHashCode
 import groovy.transform.ToString
 
@@ -29,6 +30,7 @@ import groovy.transform.ToString
  */
 @EqualsAndHashCode(includes=['aclClass', 'parent', 'owner', 
'entriesInheriting'])
 @ToString(includeNames=true)
+@DirtyCheck
 abstract class AbstractAclObjectIdentity implements Serializable {
 
        AclClass aclClass
diff --git 
a/plugin-ui/examples/extended/grails-app/domain/grails/plugin/springsecurity/acl/AclObjectIdentity.groovy
 
b/plugin-ui/examples/extended/grails-app/domain/grails/plugin/springsecurity/acl/AclObjectIdentity.groovy
index 306f43a1..061bc98c 100644
--- 
a/plugin-ui/examples/extended/grails-app/domain/grails/plugin/springsecurity/acl/AclObjectIdentity.groovy
+++ 
b/plugin-ui/examples/extended/grails-app/domain/grails/plugin/springsecurity/acl/AclObjectIdentity.groovy
@@ -18,12 +18,14 @@
  */
 package grails.plugin.springsecurity.acl
 
+import grails.gorm.dirty.checking.DirtyCheck
 import groovy.transform.ToString
 
 /**
  * @author <a href='mailto:b...@burtbeckwith.com'>Burt Beckwith</a>
  */
 @ToString(excludes='version', includeNames=true)
+@DirtyCheck
 class AclObjectIdentity {
 
        private static final long serialVersionUID = 1
diff --git 
a/plugin-ui/examples/extended/src/integration-test/groovy/spec/AclEntrySpec.groovy
 
b/plugin-ui/examples/extended/src/integration-test/groovy/spec/AclEntrySpec.groovy
index 630874ac..c01313db 100644
--- 
a/plugin-ui/examples/extended/src/integration-test/groovy/spec/AclEntrySpec.groovy
+++ 
b/plugin-ui/examples/extended/src/integration-test/groovy/spec/AclEntrySpec.groovy
@@ -54,9 +54,9 @@ class AclEntrySpec extends AbstractSecuritySpec {
                aclEntrySearchPage.assertResults(1, 3, 3)
 
                assertContentContains('60')
-               assertContentContains('398')
-               assertContentContains('399')
-               assertContentContains('400')
+               assertContentContains('62')
+               assertContentContains('194')
+               assertContentContains('195')
                assertContentContains('user1')
                assertContentContains('admin')
                assertContentDoesNotContain('>user2</a>')
@@ -74,7 +74,7 @@ class AclEntrySpec extends AbstractSecuritySpec {
                then:
                browser.at(AclEntrySearchPage)
                aclEntrySearchPage.assertResults(1, 10, 67)
-               ['104', '111', '119', '126', '131', '136', '141', '146', '152', 
'159'].each {
+               ['75', '76', '78', '80', '82', '87', '89', '91', '93', 
'95'].each {
                        assertContentContains it
                }
        }

Reply via email to