This is an automated email from the ASF dual-hosted git repository. jamesfredley pushed a commit to branch test/databinding-codegen-contract in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit 23f7c46a4e8a98d23aebb8a04983ef4adecd422f Author: James Fredley <[email protected]> AuthorDate: Fri Jul 17 17:42:07 2026 -0400 Characterize data-binding allowlist through public binding API Assisted-by: opencode:gpt-5.6-sol --- .../DefaultDatabindingWhitelistBehaviorSpec.groovy | 117 +++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/grails-test-suite-web/src/test/groovy/org/grails/web/binding/DefaultDatabindingWhitelistBehaviorSpec.groovy b/grails-test-suite-web/src/test/groovy/org/grails/web/binding/DefaultDatabindingWhitelistBehaviorSpec.groovy new file mode 100644 index 0000000000..10b437ec31 --- /dev/null +++ b/grails-test-suite-web/src/test/groovy/org/grails/web/binding/DefaultDatabindingWhitelistBehaviorSpec.groovy @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.grails.web.binding + +import grails.artefact.Artefact +import grails.persistence.Entity +import grails.testing.web.controllers.ControllerUnitTest +import grails.validation.Validateable +import grails.web.databinding.DataBindingUtils +import spock.lang.Specification + +class DefaultDatabindingWhitelistBehaviorSpec extends Specification implements ControllerUnitTest<WhitelistBehaviorController> { + + void 'domain binding includes simple and association properties but excludes special and unlisted properties'() { + given: + Date dateCreated = new Date() + Date lastUpdated = new Date() + Map source = [ + name: 'Ada', + address: [street: 'Analytical Engine Way'], + id: 99L, + version: 7L, + dateCreated: dateCreated, + lastUpdated: lastUpdated, + ignored: 'not bindable' + ] + + when: + WhitelistDomain domain = new WhitelistDomain() + DataBindingUtils.bindObjectToInstance(domain, source) + + then: + domain.name == 'Ada' + domain.address.street == 'Analytical Engine Way' + domain.id == null + domain.version == null + domain.dateCreated == null + domain.lastUpdated == null + domain.ignored == null + } + + void 'Validateable command binding includes declared special properties but excludes unlisted properties'() { + given: + Date dateCreated = new Date() + Date lastUpdated = new Date() + params.name = 'Grace' + params.'address.street' = 'Compiler Lane' + params.id = '99' + params.version = '7' + params.dateCreated = dateCreated + params.lastUpdated = lastUpdated + params.ignored = 'not bindable' + + when: + WhitelistCommand command = controller.bindCommand().command + + then: + command.name == 'Grace' + command.address.street == 'Compiler Lane' + command.id == 99L + command.version == 7L + command.dateCreated == dateCreated + command.lastUpdated == lastUpdated + command.ignored == null + } +} + +@Entity +class WhitelistDomain { + String name + WhitelistAddress address = new WhitelistAddress() + Long id + Long version + Date dateCreated + Date lastUpdated + Object ignored + + static hasOne = [address: WhitelistAddress] +} + +@Entity +class WhitelistAddress { + String street +} + +@Artefact('Controller') +class WhitelistBehaviorController { + def bindCommand(WhitelistCommand command) { + [command: command] + } +} + +class WhitelistCommand implements Validateable { + String name + WhitelistAddress address = new WhitelistAddress() + Long id + Long version + Date dateCreated + Date lastUpdated + Object ignored +}
