diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index bc9d5f8..d80d5ef 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -13,11 +13,12 @@ jobs: MAVEN_CENTRAL_PGP_KEY: ${{ secrets.MAVEN_CENTRAL_PGP_KEY }} steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v3 - uses: gradle/wrapper-validation-action@v1 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 + - name: Set up JDK 11 + uses: actions/setup-java@v3 with: - java-version: '8.0.282' + java-version: '11' + distribution: 'corretto' - name: build test and publish run: ./gradlew assemble && ./gradlew check --info && ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository -x check --info --stacktrace diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 13a366a..48c7e45 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -11,11 +11,12 @@ jobs: buildAndTest: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v3 - uses: gradle/wrapper-validation-action@v1 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 + - name: Set up JDK 11 + uses: actions/setup-java@v3 with: - java-version: '8.0.282' + java-version: '11' + distribution: 'corretto' - name: build and test run: ./gradlew assemble && ./gradlew check --info --stacktrace diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b61d755..6de60e8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,11 +17,12 @@ jobs: RELEASE_VERSION: ${{ github.event.inputs.version }} steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v3 - uses: gradle/wrapper-validation-action@v1 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 + - name: Set up JDK 11 + uses: actions/setup-java@v3 with: - java-version: '8.0.282' + java-version: '11' + distribution: 'corretto' - name: build test and publish run: ./gradlew assemble && ./gradlew check --info && ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository -x check --info --stacktrace diff --git a/README.md b/README.md index f03fd25..cbe7c3d 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ This library provides extended validation of fields and field arguments for [gra ``` ```groovy -compile 'com.graphql-java:graphql-java-extended-validation:20.0' +implementation 'com.graphql-java:graphql-java-extended-validation:20.0' ``` > Note: diff --git a/build.gradle b/build.gradle index 5ba7df2..da5f461 100644 --- a/build.gradle +++ b/build.gradle @@ -20,33 +20,28 @@ def getDevelopmentVersion() { println "git hash is empty: error: ${error.toString()}" throw new IllegalStateException("git hash could not be determined") } - new SimpleDateFormat('yyyy-MM-dd\'T\'HH-mm-ss').format(new Date()) + "-" + gitHash + "0.0.0-" + new SimpleDateFormat('yyyy-MM-dd\'T\'HH-mm-ss').format(new Date()) + "-" + gitHash } - def releaseVersion = System.env.RELEASE_VERSION version = releaseVersion ? releaseVersion : getDevelopmentVersion() println "Building version = " + version group = 'com.graphql-java' -if (JavaVersion.current() != JavaVersion.VERSION_1_8) { - def msg = String.format("This build must be run with java 1.8 - you are running %s - gradle finds the JDK via JAVA_HOME=%s", - JavaVersion.current(), System.getenv("JAVA_HOME")) - throw new GradleException(msg) +java { + toolchain { + languageVersion = JavaLanguageVersion.of(11) + } } -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - repositories { mavenCentral() mavenLocal() } - dependencies { - api "com.graphql-java:graphql-java:20.0" - api "com.graphql-java:graphql-java-extended-scalars:20.0" + api "com.graphql-java:graphql-java:21.0" + api "com.graphql-java:graphql-java-extended-scalars:21.0" api "org.hibernate.validator:hibernate-validator:7.0.1.Final" api "org.glassfish:jakarta.el:4.0.2" @@ -91,7 +86,7 @@ publishing { asNode().children().last() + { resolveStrategy = Closure.DELEGATE_FIRST name 'graphql-java-extended-validation' - description 'A library fo extended validation for graphql-java' + description 'A library of extended validation for graphql-java' url 'https://github.com/graphql-java/graphql-java-extended-validation' inceptionYear '2019' @@ -137,9 +132,7 @@ signing { sign publishing.publications } - // all publish tasks depend on the build task tasks.withType(PublishToMavenRepository) { dependsOn build } - diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c..7454180 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 05679dc..db9a6b8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 4f906e0..744e882 100755 --- a/gradlew +++ b/gradlew @@ -72,7 +72,7 @@ case "`uname`" in Darwin* ) darwin=true ;; - MINGW* ) + MSYS* | MINGW* ) msys=true ;; NONSTOP* ) diff --git a/gradlew.bat b/gradlew.bat index 107acd3..ac1b06f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,89 +1,89 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/main/java/graphql/validation/locale/LocaleUtil.java b/src/main/java/graphql/validation/locale/LocaleUtil.java index 13fffdb..11eabcd 100644 --- a/src/main/java/graphql/validation/locale/LocaleUtil.java +++ b/src/main/java/graphql/validation/locale/LocaleUtil.java @@ -23,9 +23,9 @@ public class LocaleUtil { */ public static Locale determineLocale(DataFetchingEnvironment environment, Locale defaultLocale) { // - // in a future version of graphql java the DFE will have the Locale but in the mean time - Locale locale; - locale = extractLocale(environment); + // The DFE has a locale now, but we retain the old look-ups for backwards compat reasons + // + Locale locale = environment.getLocale(); if (locale == null) { locale = extractLocale(environment.getContext()); if (locale == null) { diff --git a/src/main/java/graphql/validation/rules/ValidationEnvironment.java b/src/main/java/graphql/validation/rules/ValidationEnvironment.java index 903b5bb..ae3c4b1 100644 --- a/src/main/java/graphql/validation/rules/ValidationEnvironment.java +++ b/src/main/java/graphql/validation/rules/ValidationEnvironment.java @@ -1,5 +1,6 @@ package graphql.validation.rules; +import graphql.GraphQLContext; import graphql.PublicApi; import graphql.execution.ResultPath; import graphql.language.SourceLocation; @@ -55,6 +56,8 @@ public enum ValidatedElement { private final Object validatedValue; private final GraphQLInputType validatedType; private final ValidatedElement validatedElement; + + private final GraphQLContext graphQLContext; private final List directives; private ValidationEnvironment(Builder builder) { @@ -71,6 +74,7 @@ private ValidationEnvironment(Builder builder) { this.location = builder.location; this.validatedValue = builder.validatedValue; this.validatedElement = builder.validatedElement; + this.graphQLContext = builder.graphQLContext; this.directives = builder.directives; } @@ -135,6 +139,10 @@ public List getDirectives() { return directives; } + public GraphQLContext getGraphQLContext() { + return graphQLContext; + } + public ValidationEnvironment transform(Consumer builderConsumer) { Builder builder = newValidationEnvironment().validationEnvironment(this); builderConsumer.accept(builder); @@ -156,6 +164,7 @@ public static class Builder { private GraphQLInputType validatedType; private ValidatedElement validatedElement; private List directives = Collections.emptyList(); + private GraphQLContext graphQLContext = GraphQLContext.getDefault(); public Builder validationEnvironment(ValidationEnvironment validationEnvironment) { this.argument = validationEnvironment.argument; @@ -172,6 +181,7 @@ public Builder validationEnvironment(ValidationEnvironment validationEnvironment this.validatedValue = validationEnvironment.validatedValue; this.validatedElement = validationEnvironment.validatedElement; this.directives = validationEnvironment.directives; + this.graphQLContext = validationEnvironment.graphQLContext; return this; } @@ -184,6 +194,7 @@ public Builder dataFetchingEnvironment(DataFetchingEnvironment dataFetchingEnvir location(dataFetchingEnvironment.getField().getSourceLocation()); argumentValues(dataFetchingEnvironment.getArguments()); validatedElement(ValidatedElement.FIELD); + graphQLContext(dataFetchingEnvironment.getGraphQlContext()); return this; } @@ -252,6 +263,11 @@ public Builder locale(Locale locale) { return this; } + public Builder graphQLContext(GraphQLContext graphQLContext) { + this.graphQLContext = graphQLContext; + return this; + } + public Builder directives(List directives) { this.directives = directives; return this; diff --git a/src/main/java/graphql/validation/schemawiring/TrivialFieldValidatorDataFetcher.java b/src/main/java/graphql/validation/schemawiring/TrivialFieldValidatorDataFetcher.java new file mode 100644 index 0000000..1a6a98c --- /dev/null +++ b/src/main/java/graphql/validation/schemawiring/TrivialFieldValidatorDataFetcher.java @@ -0,0 +1,15 @@ +package graphql.validation.schemawiring; + +import graphql.TrivialDataFetcher; +import graphql.schema.DataFetcher; +import graphql.validation.interpolation.MessageInterpolator; +import graphql.validation.rules.OnValidationErrorStrategy; +import graphql.validation.rules.ValidationRules; + +import java.util.Locale; + +public class TrivialFieldValidatorDataFetcher extends FieldValidatorDataFetcher implements TrivialDataFetcher { + public TrivialFieldValidatorDataFetcher(OnValidationErrorStrategy errorStrategy, MessageInterpolator messageInterpolator, DataFetcher defaultDataFetcher, Locale defaultLocale, ValidationRules validationRules) { + super(errorStrategy, messageInterpolator, defaultDataFetcher, defaultLocale, validationRules); + } +} diff --git a/src/main/java/graphql/validation/schemawiring/ValidationSchemaWiring.java b/src/main/java/graphql/validation/schemawiring/ValidationSchemaWiring.java index 36cf6ba..30867b9 100644 --- a/src/main/java/graphql/validation/schemawiring/ValidationSchemaWiring.java +++ b/src/main/java/graphql/validation/schemawiring/ValidationSchemaWiring.java @@ -1,6 +1,7 @@ package graphql.validation.schemawiring; import graphql.PublicApi; +import graphql.TrivialDataFetcher; import graphql.schema.DataFetcher; import graphql.schema.GraphQLFieldDefinition; import graphql.schema.GraphQLFieldsContainer; @@ -8,7 +9,6 @@ import graphql.schema.idl.SchemaDirectiveWiringEnvironment; import graphql.validation.interpolation.MessageInterpolator; import graphql.validation.rules.OnValidationErrorStrategy; -import graphql.validation.rules.TargetedValidationRules; import graphql.validation.rules.ValidationRules; import java.util.Locale; @@ -51,6 +51,16 @@ private DataFetcher buildValidatingDataFetcher(OnValidationErrorStrategy MessageInterpolator messageInterpolator, DataFetcher currentDF, final Locale defaultLocale) { + if (currentDF instanceof TrivialDataFetcher) { + return new TrivialFieldValidatorDataFetcher( + errorStrategy, + messageInterpolator, + currentDF, + defaultLocale, + ruleCandidates + ); + } + return new FieldValidatorDataFetcher( errorStrategy, messageInterpolator, diff --git a/src/test/groovy/graphql/validation/locale/LocaleUtilTest.groovy b/src/test/groovy/graphql/validation/locale/LocaleUtilTest.groovy index b01b5eb..cda044b 100644 --- a/src/test/groovy/graphql/validation/locale/LocaleUtilTest.groovy +++ b/src/test/groovy/graphql/validation/locale/LocaleUtilTest.groovy @@ -1,7 +1,7 @@ package graphql.validation.locale +import graphql.GraphQLContext import graphql.GraphQLError -import graphql.GraphqlErrorBuilder import graphql.execution.ExecutionStepInfo import graphql.execution.MergedField import graphql.schema.DataFetchingEnvironment @@ -18,6 +18,8 @@ import graphql.validation.rules.ValidationEnvironment import graphql.validation.rules.ValidationRule import spock.lang.Specification +import static graphql.GraphqlErrorBuilder.newError + class LocaleUtilTest extends Specification { def directiveRules = DirectiveConstraints.newDirectiveConstraints().build() @@ -99,7 +101,10 @@ class LocaleUtilTest extends Specification { @Override List runValidation(ValidationEnvironment validationEnvironment) { - return [GraphqlErrorBuilder.newError().message("Locale=" + validationEnvironment.getLocale().getCountry()).build()] + return [ + newError().message("Locale=" + validationEnvironment.getLocale().getCountry()).build(), + newError().message("Context=" + (validationEnvironment.getGraphQLContext() != null)).build() + ] } } @@ -176,5 +181,31 @@ class LocaleUtilTest extends Specification { errors = targetedValidationRules.runValidationRules(dfe, new ResourceBundleMessageInterpolator(), Locale.CHINA) then: errors[0].message == "Locale=GB" + + // use DFE direct + when: + + dfe = DataFetchingEnvironmentImpl.newDataFetchingEnvironment(dfe) + .locale(Locale.UK) + .build() + + errors = targetedValidationRules.runValidationRules(dfe, new ResourceBundleMessageInterpolator(), Locale.CHINA) + then: + errors[0].message == "Locale=GB" + errors[1].message == "Context=false" + + // sneaking in a test that graphql context gets picked up here + // cheeky I know but the setup of a clean test in the exact right place is not worth it + when: + + dfe = DataFetchingEnvironmentImpl.newDataFetchingEnvironment(dfe) + .locale(Locale.UK) + .graphQLContext(GraphQLContext.of([x: "present"])) + .build() + + errors = targetedValidationRules.runValidationRules(dfe, new ResourceBundleMessageInterpolator(), Locale.CHINA) + then: + errors[0].message == "Locale=GB" + errors[1].message == "Context=true" } }