Skip to content

Commit 4011ce6

Browse files
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
1 parent 03f9659 commit 4011ce6

File tree

5 files changed

+36
-34
lines changed

5 files changed

+36
-34
lines changed

plugin-acl/plugin/grails-app/services/grails/plugin/springsecurity/acl/AclObjectIdentityGormService.groovy

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ package grails.plugin.springsecurity.acl
2121

2222
import grails.gorm.DetachedCriteria
2323
import grails.gorm.transactions.ReadOnly
24-
import groovy.transform.CompileDynamic
2524
import groovy.transform.CompileStatic
2625
import org.springframework.security.acls.model.ObjectIdentity
2726

@@ -42,14 +41,9 @@ class AclObjectIdentityGormService {
4241
AclObjectIdentity.get(id)
4342
}
4443

45-
@CompileDynamic
4644
@ReadOnly
4745
List<AclObjectIdentity> findAllByParentObjectIdAndParentAclClassName(Long objectId, String aclClassName) {
48-
//findQueryByParentObjectIdAndParentAclClassName(objectId, aclClassName).list()
49-
List<AclObjectIdentity> aclObjectIdentityList = findAll()
50-
aclObjectIdentityList.findAll { AclObjectIdentity oid ->
51-
(oid?.parent?.aclClass?.className == aclClassName) && ( oid?.parent?.objectId == objectId)
52-
}
46+
findQueryByParentObjectIdAndParentAclClassName(objectId, aclClassName).list()
5347
}
5448

5549
@ReadOnly

plugin-acl/plugin/grails-app/services/grails/plugin/springsecurity/acl/AclService.groovy

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import grails.gorm.transactions.ReadOnly
2222
import groovy.transform.CompileDynamic
2323
import groovy.transform.CompileStatic
2424
import groovy.util.logging.Slf4j
25+
import org.grails.datastore.gorm.GormEntity
2526
import org.springframework.context.MessageSource
2627
import org.springframework.security.acls.domain.AccessControlEntryImpl
2728
import org.springframework.security.acls.domain.GrantedAuthoritySid
@@ -97,10 +98,7 @@ class AclService implements MutableAclService, WarnErros {
9798
objectId: object.identifier as Long,
9899
owner: ownerSid,
99100
entriesInheriting: true)
100-
if ( !aclObjectIdentity.save() ) {
101-
log.error '{}', errorsBeanBeingSaved(messageSource, aclObjectIdentity)
102-
}
103-
aclObjectIdentity
101+
save(aclObjectIdentity)
104102
}
105103

106104
@Transactional
@@ -124,9 +122,7 @@ class AclService implements MutableAclService, WarnErros {
124122
AclSid aclSid = aclSidGormService.findBySidAndPrincipal(sidName, principal)
125123
if (!aclSid && allowCreate) {
126124
aclSid = new AclSid(sid: sidName, principal: principal)
127-
if ( !aclSid.save() ) {
128-
log.error '{}', errorsBeanBeingSaved(messageSource, aclSid)
129-
}
125+
save(aclSid)
130126
}
131127
aclSid
132128
}
@@ -136,9 +132,7 @@ class AclService implements MutableAclService, WarnErros {
136132
AclClass aclClass = aclClassGormService.findByClassName(className)
137133
if (!aclClass && allowCreate) {
138134
aclClass = new AclClass(className: className)
139-
if ( !aclClass.save() ) {
140-
log.error '{}', errorsBeanBeingSaved(messageSource, aclClass)
141-
}
135+
save(aclClass)
142136
}
143137
aclClass
144138
}
@@ -209,23 +203,25 @@ class AclService implements MutableAclService, WarnErros {
209203
log.trace 'Checking ace for delete: {}', ace
210204
!acl.entries.find { AccessControlEntry entry ->
211205
log.trace 'Checking entry for delete: {}', entry
212-
entry.permission.mask == ace.mask && entry.sid == ace.sid.sid
206+
entryEqual(ace, entry)
213207
}
214208
}
215209

216210
List<AccessControlEntry> toCreate = acl.entries.findAll { AccessControlEntry entry ->
217211
log.trace 'Checking entry for create: {}', entry
218212
!existingAces.find { AclEntry ace ->
219213
log.trace 'Checking ace for create: {}', ace
220-
entry.permission.mask == ace.mask && entry.sid == ace.sid.sid
214+
entryEqual(ace, entry)
221215
}
222216
}
223217

218+
Integer maxAceOrder = existingAces.max { it.aceOrder }?.aceOrder
219+
224220
// Delete this ACL's ACEs in the acl_entry table
225221
deleteEntries toDelete
226222

227223
// Create this ACL's ACEs in the acl_entry table
228-
createEntries(acl, toCreate as List<AuditableAccessControlEntry>)
224+
createEntries(acl, maxAceOrder, toCreate as List<AuditableAccessControlEntry>)
229225

230226
// Change the mutable columns in acl_object_identity
231227
updateObjectIdentity acl
@@ -237,10 +233,9 @@ class AclService implements MutableAclService, WarnErros {
237233
}
238234

239235
@Transactional
240-
protected void createEntries(MutableAcl acl, List<AuditableAccessControlEntry> entries = null) {
241-
List<AuditableAccessControlEntry> entryList = entries ?: acl.entries as List<AuditableAccessControlEntry>
242-
int i = 0
243-
for (AuditableAccessControlEntry entry in entryList) {
236+
protected void createEntries(MutableAcl acl, Integer maxOrder, List<AuditableAccessControlEntry> entries) {
237+
int i = maxOrder != null ? maxOrder + 1 : 0
238+
for (AuditableAccessControlEntry entry in entries) {
244239
Assert.isInstanceOf AccessControlEntryImpl, entry, 'Unknown ACE class'
245240
AclEntry aclEntryInstance = new AclEntry(
246241
aclObjectIdentity: AclObjectIdentity.load(acl.id),
@@ -250,9 +245,7 @@ class AclService implements MutableAclService, WarnErros {
250245
granting: entry.isGranting(),
251246
auditSuccess: entry.isAuditSuccess(),
252247
auditFailure: entry.isAuditFailure())
253-
if ( !aclEntryInstance.save() ) {
254-
log.error "{}", errorsBeanBeingSaved(messageSource, aclEntryInstance)
255-
}
248+
save(aclEntryInstance)
256249
}
257250
}
258251

@@ -272,9 +265,7 @@ class AclService implements MutableAclService, WarnErros {
272265
aclObjectIdentity.parent = parent
273266
aclObjectIdentity.owner = createOrRetrieveSid(acl.owner, true)
274267
aclObjectIdentity.entriesInheriting = acl.isEntriesInheriting()
275-
if ( !aclObjectIdentity.save() ) {
276-
log.error "{}", errorsBeanBeingSaved(messageSource, aclObjectIdentity)
277-
}
268+
save(aclObjectIdentity)
278269
AclObjectIdentity.withSession { it.flush() }
279270
}
280271

@@ -335,4 +326,17 @@ class AclService implements MutableAclService, WarnErros {
335326
}
336327
return result
337328
}
329+
330+
@Transactional
331+
protected <T extends GormEntity<T>> T save(T bean) {
332+
if (!bean.save()) {
333+
log.warn errorsBeanBeingSaved(messageSource, bean)
334+
}
335+
bean
336+
}
337+
338+
private static boolean entryEqual(AclEntry ace, AccessControlEntry entry) {
339+
Sid sid = ace.sid.principal ? new PrincipalSid(ace.sid.sid) : new GrantedAuthoritySid(ace.sid.sid)
340+
return entry.permission.mask == ace.mask && entry.sid == sid && entry.granting == ace.granting
341+
}
338342
}

plugin-acl/plugin/src/main/groovy/grails/plugin/springsecurity/acl/AbstractAclObjectIdentity.groovy

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package grails.plugin.springsecurity.acl
2020

21+
import grails.gorm.dirty.checking.DirtyCheck
2122
import groovy.transform.EqualsAndHashCode
2223
import groovy.transform.ToString
2324

@@ -29,6 +30,7 @@ import groovy.transform.ToString
2930
*/
3031
@EqualsAndHashCode(includes=['aclClass', 'parent', 'owner', 'entriesInheriting'])
3132
@ToString(includeNames=true)
33+
@DirtyCheck
3234
abstract class AbstractAclObjectIdentity implements Serializable {
3335

3436
AclClass aclClass

plugin-ui/examples/extended/grails-app/domain/grails/plugin/springsecurity/acl/AclObjectIdentity.groovy

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@
1818
*/
1919
package grails.plugin.springsecurity.acl
2020

21+
import grails.gorm.dirty.checking.DirtyCheck
2122
import groovy.transform.ToString
2223

2324
/**
2425
* @author <a href='mailto:[email protected]'>Burt Beckwith</a>
2526
*/
2627
@ToString(excludes='version', includeNames=true)
28+
@DirtyCheck
2729
class AclObjectIdentity {
2830

2931
private static final long serialVersionUID = 1

plugin-ui/examples/extended/src/integration-test/groovy/spec/AclEntrySpec.groovy

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ class AclEntrySpec extends AbstractSecuritySpec {
5454
aclEntrySearchPage.assertResults(1, 3, 3)
5555

5656
assertContentContains('60')
57-
assertContentContains('398')
58-
assertContentContains('399')
59-
assertContentContains('400')
57+
assertContentContains('62')
58+
assertContentContains('194')
59+
assertContentContains('195')
6060
assertContentContains('user1')
6161
assertContentContains('admin')
6262
assertContentDoesNotContain('>user2</a>')
@@ -74,7 +74,7 @@ class AclEntrySpec extends AbstractSecuritySpec {
7474
then:
7575
browser.at(AclEntrySearchPage)
7676
aclEntrySearchPage.assertResults(1, 10, 67)
77-
['104', '111', '119', '126', '131', '136', '141', '146', '152', '159'].each {
77+
['75', '76', '78', '80', '82', '87', '89', '91', '93', '95'].each {
7878
assertContentContains it
7979
}
8080
}

0 commit comments

Comments
 (0)