From 72fc38ae4ad517a2f532f29e5771610548a5918a Mon Sep 17 00:00:00 2001 From: sdelamo Date: Wed, 2 Jan 2019 08:49:47 +0100 Subject: [PATCH 01/11] Bump up Groovy to 2.5.5 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index df8f58de..bdb5ed8f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ projectVersion=3.0.0.BUILD-SNAPSHOT #projectVersion=2.2.7 grailsVersion=4.0.0.BUILD-SNAPSHOT scaffoldingVersion=2.0.0.BUILD-SNAPSHOT -groovyVersion=2.5.4 +groovyVersion=2.5.5 cglibNodepVersion=3.2.9 joddWotVersion=3.3.8 asciidoc=true From 7bb8442bbebbc12c38d07127a10ceb8e3d7a0a96 Mon Sep 17 00:00:00 2001 From: sdelamo Date: Wed, 2 Jan 2019 17:48:36 +0100 Subject: [PATCH 02/11] Bump up serverlet api version to 4.0.1 --- build.gradle | 2 +- gradle.properties | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9d4ac1f8..ff1a2781 100644 --- a/build.gradle +++ b/build.gradle @@ -40,7 +40,7 @@ dependencies { provided "org.grails:grails-web-boot" provided "org.grails:grails-dependencies" - provided 'javax.servlet:javax.servlet-api:3.1.0' + provided "javax.servlet:javax.servlet-api:$servletApiVersion" compile "org.grails:scaffolding-core:$scaffoldingVersion" diff --git a/gradle.properties b/gradle.properties index bdb5ed8f..ae955324 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,6 +5,7 @@ scaffoldingVersion=2.0.0.BUILD-SNAPSHOT groovyVersion=2.5.5 cglibNodepVersion=3.2.9 joddWotVersion=3.3.8 +servletApiVersion=4.0.1 asciidoc=true githubSlug=grails-fields-plugin/grails-fields githubBranch=master From b7b7de214161d4cd2b00a1532e803d001138bc17 Mon Sep 17 00:00:00 2001 From: graemerocher Date: Tue, 19 Feb 2019 12:19:01 +0100 Subject: [PATCH 03/11] Update dependencies --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index ae955324..93758ee2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,8 @@ projectVersion=3.0.0.BUILD-SNAPSHOT #projectVersion=2.2.7 -grailsVersion=4.0.0.BUILD-SNAPSHOT +grailsVersion=4.0.0.M1 scaffoldingVersion=2.0.0.BUILD-SNAPSHOT -groovyVersion=2.5.5 +groovyVersion=2.5.6 cglibNodepVersion=3.2.9 joddWotVersion=3.3.8 servletApiVersion=4.0.1 From d0f0b1acf3f8dc36aa0949cb3246f9496024dc9f Mon Sep 17 00:00:00 2001 From: jameskleeh Date: Tue, 19 Feb 2019 09:13:24 -0500 Subject: [PATCH 04/11] Use release versions of dependencies --- build.gradle | 4 ++-- gradle.properties | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 9d4ac1f8..41254599 100644 --- a/build.gradle +++ b/build.gradle @@ -46,8 +46,8 @@ dependencies { //testCompile "org.grails:grails-plugin-testing" - testCompile "org.grails:grails-web-testing-support:2.0.0.BUILD-SNAPSHOT" - testCompile "org.grails:grails-gorm-testing-support:2.0.0.BUILD-SNAPSHOT" + testCompile "org.grails:grails-web-testing-support:2.0.0.RC1" + testCompile "org.grails:grails-gorm-testing-support:2.0.0.RC1" console "org.grails:grails-console" diff --git a/gradle.properties b/gradle.properties index df8f58de..3234da52 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ projectVersion=3.0.0.BUILD-SNAPSHOT #projectVersion=2.2.7 -grailsVersion=4.0.0.BUILD-SNAPSHOT -scaffoldingVersion=2.0.0.BUILD-SNAPSHOT +grailsVersion=4.0.0.M1 +scaffoldingVersion=2.0.0.RC1 groovyVersion=2.5.4 cglibNodepVersion=3.2.9 joddWotVersion=3.3.8 From 13d22ec7679498e64221347429d382e3c969392a Mon Sep 17 00:00:00 2001 From: jameskleeh Date: Tue, 19 Feb 2019 09:30:42 -0500 Subject: [PATCH 05/11] Release 3.0.0.RC1 --- build.gradle | 4 +--- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 9dee5065..7e6cc077 100644 --- a/build.gradle +++ b/build.gradle @@ -43,9 +43,7 @@ dependencies { provided "javax.servlet:javax.servlet-api:$servletApiVersion" compile "org.grails:scaffolding-core:$scaffoldingVersion" - - //testCompile "org.grails:grails-plugin-testing" - + testCompile "org.grails:grails-web-testing-support:2.0.0.RC1" testCompile "org.grails:grails-gorm-testing-support:2.0.0.RC1" diff --git a/gradle.properties b/gradle.properties index f8ac7512..7a83b80a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -projectVersion=3.0.0.BUILD-SNAPSHOT +projectVersion=3.0.0.RC1 #projectVersion=2.2.7 grailsVersion=4.0.0.M1 scaffoldingVersion=2.0.0.RC1 From da4ac74028896504a7bc7615edc52532bf47e854 Mon Sep 17 00:00:00 2001 From: jameskleeh Date: Tue, 19 Feb 2019 09:46:30 -0500 Subject: [PATCH 06/11] Back to snapshot --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7a83b80a..f8ac7512 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -projectVersion=3.0.0.RC1 +projectVersion=3.0.0.BUILD-SNAPSHOT #projectVersion=2.2.7 grailsVersion=4.0.0.M1 scaffoldingVersion=2.0.0.RC1 From 5a80d3d51868a1606365d5208d4694e1e31d7ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Berg=20Glasius?= Date: Mon, 15 Feb 2021 16:10:34 +0100 Subject: [PATCH 07/11] Added Action: Stale issues and pr's --- .github/workflows/stale.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/workflows/stale.yml diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000..969de1fe --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,20 @@ +name: Mark stale issues and pull requests + +on: + schedule: + - cron: "30 1 * * *" + +jobs: + stale: + + runs-on: ubuntu-latest + + steps: + - uses: actions/stale@v3 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: 'Stale issue. Marked automatically' + stale-pr-message: 'Stale pull request. Marked automatically' + stale-issue-label: 'no-issue-activity' + stale-pr-label: 'no-pr-activity' + days-before-stale: 120 From 3c0f15a43eacfc1bbdf8b618e1144d97e368923c Mon Sep 17 00:00:00 2001 From: David Kron Date: Fri, 3 Sep 2021 21:55:47 +0200 Subject: [PATCH 08/11] fix warning "Accessing config through dot notation is deprecated" --- .../grails/plugin/formfields/FormFieldsTemplateService.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/groovy/grails/plugin/formfields/FormFieldsTemplateService.groovy b/src/main/groovy/grails/plugin/formfields/FormFieldsTemplateService.groovy index 8325afb0..50055d75 100644 --- a/src/main/groovy/grails/plugin/formfields/FormFieldsTemplateService.groovy +++ b/src/main/groovy/grails/plugin/formfields/FormFieldsTemplateService.groovy @@ -231,8 +231,8 @@ class FormFieldsTemplateService { private boolean shouldCache() { // If not explicitly specified, there is no template caching - Boolean cacheDisabled = grailsApplication?.config?.grails?.plugin?.fields?.disableLookupCache + Boolean cacheDisabled = grailsApplication?.config?.getProperty('grails.plugin.fields.disableLookupCache', Boolean) return !cacheDisabled } -} \ No newline at end of file +} From de08017bcc56878441c4c40cf8608bac736dcc51 Mon Sep 17 00:00:00 2001 From: David Kron Date: Wed, 17 Aug 2022 18:10:57 +0200 Subject: [PATCH 09/11] respect defaultNullable() of Validateable classes (issue #218) --- .../BeanPropertyAccessorFactory.groovy | 5 ++- .../CommandPropertyAccessorSpec.groovy | 36 +++++++++++++++++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/main/groovy/grails/plugin/formfields/BeanPropertyAccessorFactory.groovy b/src/main/groovy/grails/plugin/formfields/BeanPropertyAccessorFactory.groovy index cad061e3..128233d7 100644 --- a/src/main/groovy/grails/plugin/formfields/BeanPropertyAccessorFactory.groovy +++ b/src/main/groovy/grails/plugin/formfields/BeanPropertyAccessorFactory.groovy @@ -18,6 +18,7 @@ package grails.plugin.formfields import grails.core.GrailsApplication import grails.gorm.validation.DefaultConstrainedProperty +import grails.validation.Validateable import groovy.transform.PackageScope import grails.core.support.GrailsApplicationAware import grails.core.support.proxy.ProxyHandler @@ -110,7 +111,9 @@ class BeanPropertyAccessorFactory implements GrailsApplicationAware { } private Constrained resolveConstraints(BeanWrapper beanWrapper, String propertyName) { - grails.gorm.validation.Constrained constraint = constraintsEvaluator.evaluate(beanWrapper.wrappedClass)[propertyName] + Class type = beanWrapper.wrappedClass + boolean defaultNullable = Validateable.class.isAssignableFrom(type) ? type.metaClass.invokeStaticMethod(type, 'defaultNullable') : false + grails.gorm.validation.Constrained constraint = constraintsEvaluator.evaluate(type, defaultNullable)[propertyName] if (!constraint) { constraint = createDefaultConstraint(beanWrapper, propertyName) } diff --git a/src/test/groovy/grails/plugin/formfields/CommandPropertyAccessorSpec.groovy b/src/test/groovy/grails/plugin/formfields/CommandPropertyAccessorSpec.groovy index 9437396e..6d4a5026 100644 --- a/src/test/groovy/grails/plugin/formfields/CommandPropertyAccessorSpec.groovy +++ b/src/test/groovy/grails/plugin/formfields/CommandPropertyAccessorSpec.groovy @@ -1,7 +1,11 @@ package grails.plugin.formfields -import grails.plugin.formfields.mock.* -import spock.lang.* + +import grails.plugin.formfields.mock.Gender +import grails.plugin.formfields.mock.Person +import grails.validation.Validateable +import spock.lang.Issue +import spock.lang.Unroll @Unroll class CommandPropertyAccessorSpec extends BuildsAccessorFactory { @@ -256,6 +260,20 @@ class CommandPropertyAccessorSpec extends BuildsAccessorFactory { propertyAccessor.constraints.blank } + @Issue('https://github.com/grails-fields-plugin/grails-fields/issues/218') + void 'respect defaultNullable() when evaluating constraints of a Validateable'() { + given: + ValidateableCommand command = new ValidateableCommand() + DefaultNullableValidateableCommand command2 = new DefaultNullableValidateableCommand() + + and: + def propertyAccessor = factory.accessorFor(command, 'myNullableProperty') + def propertyAccessor2 = factory.accessorFor(command2, 'myNullableProperty') + + expect: + !propertyAccessor.constraints.nullable + propertyAccessor2.constraints.nullable + } } class TestCommand { @@ -278,4 +296,16 @@ class TestCommand { class UnconstrainedCommand { String stringProperty -} \ No newline at end of file +} + +class ValidateableCommand implements Validateable { + String myNullableProperty +} + +class DefaultNullableValidateableCommand implements Validateable { + String myNullableProperty + + static boolean defaultNullable() { + return true + } +} From 80c0bdffa1284986fcb94b4781bf06d46fa29398 Mon Sep 17 00:00:00 2001 From: Mattias Reichel Date: Wed, 16 Nov 2022 15:49:16 +0100 Subject: [PATCH 10/11] Update readme.md Removed the link to the bean-fields plugin as it is gone. --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index ba6c88d7..ef024f5f 100644 --- a/readme.md +++ b/readme.md @@ -4,7 +4,7 @@ - `2.2.x` y `2.1.x` for Grails 3. - `grails2.x` for Grails 2. -A spiritual successor to the [bean-fields plugin](http://grails.org/plugin/bean-fields) that attempts to provide a configurable way to render forms with appropriate inputs for different properties without having to copy and paste lots of boilerplate code. It should be possible to change the rendering for a field with the minimum of impact on any other code. This plugin attempts to achieve that by using GSP templates looked up by convention. Developers can then create templates for rendering particular properties or types of properties with the former overriding the latter. +A spiritual successor to the bean-fields plugin that attempts to provide a configurable way to render forms with appropriate inputs for different properties without having to copy and paste lots of boilerplate code. It should be possible to change the rendering for a field with the minimum of impact on any other code. This plugin attempts to achieve that by using GSP templates looked up by convention. Developers can then create templates for rendering particular properties or types of properties with the former overriding the latter. For further information please see the full documentation. From ba00ce8ccebe1f2e07aea7586ea6b635cfc11733 Mon Sep 17 00:00:00 2001 From: Brian Koehmstedt Date: Mon, 6 Feb 2023 20:18:49 -0800 Subject: [PATCH 11/11] If field validation error codes are unresolved and fallback to the defaultMessage on the error, this defaultMessage must be escaped due to the possibility of user input being in the error message. Fixes issue #323. --- .../plugin/formfields/FormFieldsTagLib.groovy | 17 ++++++- .../taglib/FieldTagWithBodySpec.groovy | 44 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/grails-app/taglib/grails/plugin/formfields/FormFieldsTagLib.groovy b/grails-app/taglib/grails/plugin/formfields/FormFieldsTagLib.groovy index 9e1cfdd8..20f8e260 100644 --- a/grails-app/taglib/grails/plugin/formfields/FormFieldsTagLib.groovy +++ b/grails-app/taglib/grails/plugin/formfields/FormFieldsTagLib.groovy @@ -33,6 +33,9 @@ import org.grails.scaffolding.model.property.DomainPropertyFactory import org.grails.web.servlet.mvc.GrailsWebRequest import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Value +import org.springframework.context.MessageSource +import org.springframework.context.MessageSourceResolvable +import org.springframework.context.NoSuchMessageException import org.springframework.web.servlet.LocaleResolver import javax.servlet.http.HttpServletRequest @@ -68,6 +71,7 @@ class FormFieldsTagLib { DomainModelService domainModelService LocaleResolver localeResolver CodecLookup codecLookup + MessageSource messageSource static defaultEncodeAs = [taglib: 'raw'] @@ -458,7 +462,18 @@ class FormFieldsTagLib { value : (value instanceof Number || value instanceof Boolean || value) ? value : valueDefault, constraints : propertyAccessor.constraints, persistentProperty: propertyAccessor.domainProperty, - errors : propertyAccessor.errors.collect { message(error: it) }, + errors : propertyAccessor.errors.collect { error -> + String errorMsg = null + try { + errorMsg = error instanceof MessageSourceResolvable ? messageSource.getMessage(error, locale) : messageSource.getMessage(error.toString(), null, locale) + } + catch (NoSuchMessageException ignored) { + // no-op + } + // unresolved message codes fallback to the defaultMessage and this should + // be escaped as it could be an error message with user input + errorMsg && errorMsg == error.defaultMessage ? message(error: error, encodeAs: "HTML") : message(error: error) + }, required : attrs.containsKey("required") ? Boolean.valueOf(attrs.remove('required')) : propertyAccessor.required, invalid : attrs.containsKey("invalid") ? Boolean.valueOf(attrs.remove('invalid')) : propertyAccessor.invalid, prefix : resolvePrefix(attrs.remove('prefix')), diff --git a/src/test/groovy/grails/plugin/formfields/taglib/FieldTagWithBodySpec.groovy b/src/test/groovy/grails/plugin/formfields/taglib/FieldTagWithBodySpec.groovy index 40f072c4..f8ce2ce4 100644 --- a/src/test/groovy/grails/plugin/formfields/taglib/FieldTagWithBodySpec.groovy +++ b/src/test/groovy/grails/plugin/formfields/taglib/FieldTagWithBodySpec.groovy @@ -1,7 +1,11 @@ package grails.plugin.formfields.taglib +import grails.plugin.formfields.mock.Gender import grails.plugin.formfields.mock.Person import grails.testing.web.taglib.TagLibUnitTest +import grails.validation.ValidationErrors +import org.grails.plugins.web.taglib.FormatTagLib +import org.springframework.context.support.StaticMessageSource import spock.lang.Issue import grails.plugin.formfields.* @@ -56,4 +60,44 @@ class FieldTagWithBodySpec extends AbstractFormFieldsTagLibSpec implements TagLi expect: applyTemplate('${attrs.foo}', [personInstance: personInstance]) == 'bar' } + + @Issue("https://github.com/grails-fields-plugin/grails-fields/issues/323") + void 'validation defaultMessage strings are escaped'() { + given: + views['/_fields/default/_wrapper.gsp'] = '${widget}' + + and: + def person = new Person(name: 'Not Allowed', gender: Gender.Male, password: 'XYZ').with { + errors = new ValidationErrors(it) + errors.rejectValue('name', 'unresolved.code', 'custom error with special chars & < > \' "') + it + } + + when: + def result = applyTemplate('${errors[0]}', [personInstance: person]) + + then: + result == 'custom error with special chars & < > ' "' + } + + void 'resolved error codes are not escaped'() { + given: + views['/_fields/default/_wrapper.gsp'] = '${widget}' + + and: + ((StaticMessageSource) messageSource).addMessage('name.invalid', FormatTagLib.resolveLocale(null), '
Name is invalid
') + + and: + def person = new Person(name: 'Not Allowed', gender: Gender.Male, password: 'XYZ').with { + errors = new ValidationErrors(it) + errors.rejectValue('name', 'name.invalid', 'default error message') + it + } + + when: + def result = applyTemplate('${errors[0]}', [personInstance: person]) + + then: + result == '
Name is invalid
' + } } \ No newline at end of file