diff --git a/.sdkmanrc b/.sdkmanrc index 18edc690..64345a4b 100644 --- a/.sdkmanrc +++ b/.sdkmanrc @@ -3,4 +3,4 @@ # See https://sdkman.io/usage#config # A summary is to add the following to ~/.sdkman/etc/config # sdkman_auto_env=true -java=8.0.332-tem +java=17.0.3-tem diff --git a/build.gradle b/build.gradle index 5dbad1e7..43bbff3f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'org.springframework.boot' version '2.2.1.RELEASE' + id 'org.springframework.boot' version '3.2.5' id "com.gorylenko.gradle-git-properties" version "2.4.1" } @@ -7,17 +7,9 @@ apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' -apply from: "gradle/test.gradle" version = '0.0.1-SNAPSHOT' -jar { - baseName = 'pivotal-github-cla' -} - -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - repositories { mavenCentral() } @@ -47,19 +39,21 @@ dependencies { implementation('nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect') implementation('org.springframework.boot:spring-boot-starter-security') implementation('org.springframework.boot:spring-boot-starter-actuator') - implementation('org.springframework.cloud:spring-cloud-spring-service-connector') - implementation('org.springframework.cloud:spring-cloud-cloudfoundry-connector') + implementation('org.springframework.boot:spring-boot-starter-validation') implementation('org.springframework.session:spring-session-data-redis') implementation('org.eclipse.mylyn.github:org.eclipse.egit.github.core:2.1.5') implementation('org.webjars:webjars-locator-core') implementation('org.webjars:bootstrap:3.3.6') implementation('org.webjars:jquery:1.11.3') implementation('org.webjars.bower:select2:4.0.3') - implementation('com.h2database:h2') implementation('net.sourceforge.nekohtml:nekohtml') implementation('org.flywaydb:flyway-core') - implementation('mysql:mysql-connector-java:5.1.49') + implementation('org.flywaydb:flyway-mysql') + implementation('mysql:mysql-connector-java:8.0.33') developmentOnly("org.springframework.boot:spring-boot-devtools") + testImplementation('org.springframework.boot:spring-boot-testcontainers') + testImplementation('org.testcontainers:junit-jupiter') + testImplementation('org.testcontainers:mysql') testImplementation('org.springframework.boot:spring-boot-configuration-processor') testImplementation('org.springframework.boot:spring-boot-devtools') testImplementation('org.springframework.security:spring-security-test') @@ -71,10 +65,15 @@ dependencies { testImplementation('org.seleniumhq.selenium:selenium-support') testImplementation('org.assertj:assertj-core') testImplementation('com.squareup.okhttp3:mockwebserver') - testImplementation('org.testcontainers:selenium:1.12.4') + testImplementation('org.testcontainers:selenium') } + +test { + useJUnitPlatform() +} + eclipse { classpath { containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER') diff --git a/ci/scripts/docker/docker-mysql.sh b/ci/scripts/docker/docker-mysql.sh index ba7f8301..0bd14a71 100755 --- a/ci/scripts/docker/docker-mysql.sh +++ b/ci/scripts/docker/docker-mysql.sh @@ -1,4 +1,4 @@ #!/bin/sh # https://hub.docker.com/_/mysql DIR="$( cd "$(dirname "$0")" ; pwd -P )" -docker run --rm --name pcla-mysql -e MYSQL_ROOT_PASSWORD=password -p 3306:3306 -v "$DIR/mysql-init.sh:/docker-entrypoint-initdb.d/mysql-init.sh" mysql:5.7.37 \ No newline at end of file +docker run --rm --name pcla-mysql -e MYSQL_ROOT_PASSWORD=password -p 3306:3306 -v "$DIR/mysql-init.sh:/docker-entrypoint-initdb.d/mysql-init.sh" mysql:8.0.36 \ No newline at end of file diff --git a/gradle/test.gradle b/gradle/test.gradle deleted file mode 100644 index 239d5afd..00000000 --- a/gradle/test.gradle +++ /dev/null @@ -1,9 +0,0 @@ -task testWithMySQL(type: Test) { - systemProperty 'spring.active.profiles.data', 'local-mysql' - classpath = test.classpath - useJUnit { - includeCategories 'io.pivotal.cla.junit.JpaTests' - } -} - -check.dependsOn testWithMySQL \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf0..41d9927a 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 aa991fce..48c0a02c 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.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 83f2acfd..1b6c7873 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,78 +17,113 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -105,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 24467a14..ac1b06f9 100755 --- a/gradlew.bat +++ b/gradlew.bat @@ -29,6 +29,9 @@ 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" @@ -37,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :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 %CMD_LINE_ARGS% +"%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 diff --git a/src/main/java/io/pivotal/cla/config/DatabaseConfig.java b/src/main/java/io/pivotal/cla/config/DatabaseConfig.java deleted file mode 100644 index c3ce5096..00000000 --- a/src/main/java/io/pivotal/cla/config/DatabaseConfig.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed 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 - * - * http://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 io.pivotal.cla.config; - -import com.zaxxer.hikari.HikariDataSource; -import org.springframework.cloud.Cloud; -import org.springframework.cloud.CloudFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; - -import javax.sql.DataSource; - -/** - * @author Mark Paluch - * @author Rob Winch - */ - -@Configuration -@Profile(GitHubClaProfiles.LOCAL) -class LocalDatabaseConfig { - - @Bean - public DataSource dataSource() { - HikariDataSource dataSource = new HikariDataSource(); - dataSource.setDriverClassName("org.h2.Driver"); - dataSource.setJdbcUrl("jdbc:h2:mem:pivotalcla;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"); - dataSource.setUsername("sa"); - dataSource.setPassword(""); - return dataSource; - } -} - -@Configuration -@Profile(GitHubClaProfiles.LOCAL_MYSQL) -class LocalMysqlDatabaseConfig { - - @Bean - public DataSource dataSource() { - HikariDataSource dataSource = new HikariDataSource(); - - dataSource.setDriverClassName("com.mysql.jdbc.Driver"); - dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/pivotalcla"); - dataSource.setUsername("spring"); - dataSource.setPassword("password"); - return dataSource; - } -} - -@Configuration -@Profile(GitHubClaProfiles.CLOUDFOUNDRY) -class CloudFoundryDatabaseConfig { - - @Bean - public Cloud cloud() { - return new CloudFactory().getCloud(); - } - - @Bean - public DataSource dataSource() { - return cloud().getSingletonServiceConnector(DataSource.class, null); - } -} diff --git a/src/main/java/io/pivotal/cla/config/SecurityConfig.java b/src/main/java/io/pivotal/cla/config/SecurityConfig.java index b7a5ef2e..edcc761d 100644 --- a/src/main/java/io/pivotal/cla/config/SecurityConfig.java +++ b/src/main/java/io/pivotal/cla/config/SecurityConfig.java @@ -17,20 +17,24 @@ import java.io.IOException; import java.util.LinkedHashMap; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.InsufficientAuthenticationException; +import org.springframework.security.authorization.AuthorizationDecision; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.DefaultSecurityFilterChain; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.access.AccessDeniedHandlerImpl; import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint; @@ -43,41 +47,49 @@ import io.pivotal.cla.data.User; import io.pivotal.cla.security.GitHubAuthenticationEntryPoint; +@Configuration(proxyBeanMethods = false) @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) -public class SecurityConfig extends WebSecurityConfigurerAdapter { - @Autowired - private ClaOAuthConfig oauthConfig; +public class SecurityConfig { - @Override - protected void configure(HttpSecurity http) throws Exception { + private final ClaOAuthConfig oauthConfig; + + public SecurityConfig(ClaOAuthConfig oauthConfig) { + this.oauthConfig = oauthConfig; + } + + @Bean + DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception { AuthenticationEntryPoint entryPoint = entryPoint(); AdminRequestedAccessDeniedHandler accessDeniedHandler = new AdminRequestedAccessDeniedHandler(entryPoint); // @formatter:off http - .requiresChannel() + .requiresChannel(channel -> channel .requestMatchers(request -> request.getHeader("x-forwarded-port") != null).requiresSecure() - .and() - .exceptionHandling() + ) + .exceptionHandling(exceptions -> exceptions .authenticationEntryPoint(entryPoint) .accessDeniedHandler(accessDeniedHandler) - .and() - .csrf() - .ignoringAntMatchers("/github/hooks/**") - .and() - .authorizeRequests() + ) + .csrf(csrf -> csrf + .ignoringRequestMatchers("/github/hooks/**") + ) + .authorizeHttpRequests(requests -> requests + .requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole("CLA_AUTHOR") .requestMatchers(CorsUtils::isPreFlightRequest).permitAll() - .mvcMatchers("/login/**", "/", "/about", "/faq").permitAll() - .mvcMatchers("/view/**").permitAll() - .mvcMatchers("/webjars/**", "/assets/**").permitAll() - .mvcMatchers("/github/hooks/**").permitAll() - .mvcMatchers("/admin", "/admin/lookup/**", "/admin/cla/link/**", "/admin/help/**").hasRole("ADMIN") - .mvcMatchers("/admin/**", "/manage/**").hasRole("CLA_AUTHOR") + .requestMatchers("/login/**", "/", "/about", "/faq").permitAll() + .requestMatchers("/view/**").permitAll() + .requestMatchers("/webjars/**", "/assets/**").permitAll() + .requestMatchers("/github/hooks/**").permitAll() + .requestMatchers("/admin", "/admin/lookup/**", "/admin/cla/link/**", "/admin/help/**").hasRole("ADMIN") + .requestMatchers("/admin/**", "/manage/**").hasRole("CLA_AUTHOR") .anyRequest().authenticated() - .and() - .logout() - .logoutSuccessUrl("/?logout"); + ) + .logout(logout -> logout + .logoutSuccessUrl("/?logout") + ); // @formatter:on + return http.build(); } diff --git a/src/main/java/io/pivotal/cla/config/SessionConfig.java b/src/main/java/io/pivotal/cla/config/SessionConfig.java deleted file mode 100644 index a423ca77..00000000 --- a/src/main/java/io/pivotal/cla/config/SessionConfig.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed 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 - * - * http://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 io.pivotal.cla.config; - -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.data.redis.RedisProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.Cloud; -import org.springframework.cloud.CloudFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; -import org.springframework.session.data.redis.config.ConfigureRedisAction; - -/** - * @author Mark Paluch - */ -@Configuration -@EnableConfigurationProperties(RedisProperties.class) -public class SessionConfig { - - @Profile(GitHubClaProfiles.CLOUDFOUNDRY) - @Bean - public RedisConnectionFactory cloudRedisConnectionFactory() { - CloudFactory cloudFactory = new CloudFactory(); - Cloud cloud = cloudFactory.getCloud(); - RedisConnectionFactory connectionFactory = cloud.getSingletonServiceConnector(RedisConnectionFactory.class, null); - return connectionFactory; - } - - @Bean - @ConditionalOnMissingBean(RedisConnectionFactory.class) - public RedisConnectionFactory redisConnectionFactory(RedisProperties redisProperties) { - - LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(); - connectionFactory.setPort(redisProperties.getPort()); - connectionFactory.setHostName(redisProperties.getHost()); - connectionFactory.setPassword(redisProperties.getPassword()); - connectionFactory.setShutdownTimeout(0); - - return connectionFactory; - } - - @Bean - ConfigureRedisAction configureRedisAction() { - return ConfigureRedisAction.NO_OP; - } -} diff --git a/src/main/java/io/pivotal/cla/config/WebMvcConfig.java b/src/main/java/io/pivotal/cla/config/WebMvcConfig.java index a886e9de..bd2d84be 100644 --- a/src/main/java/io/pivotal/cla/config/WebMvcConfig.java +++ b/src/main/java/io/pivotal/cla/config/WebMvcConfig.java @@ -20,7 +20,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import io.pivotal.cla.mvc.support.ImportedSignaturesSessionAttrResolver; @@ -29,7 +29,7 @@ * */ @Configuration -public class WebMvcConfig extends WebMvcConfigurerAdapter { +public class WebMvcConfig implements WebMvcConfigurer { /* (non-Javadoc) * @see org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter#addArgumentResolvers(java.util.List) diff --git a/src/main/java/io/pivotal/cla/data/AccessToken.java b/src/main/java/io/pivotal/cla/data/AccessToken.java index 28f9b22c..61897316 100644 --- a/src/main/java/io/pivotal/cla/data/AccessToken.java +++ b/src/main/java/io/pivotal/cla/data/AccessToken.java @@ -15,8 +15,8 @@ */ package io.pivotal.cla.data; -import javax.persistence.Entity; -import javax.persistence.Id; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; @Entity public class AccessToken { diff --git a/src/main/java/io/pivotal/cla/data/ContributorLicenseAgreement.java b/src/main/java/io/pivotal/cla/data/ContributorLicenseAgreement.java index a9a031c3..4d0a1340 100644 --- a/src/main/java/io/pivotal/cla/data/ContributorLicenseAgreement.java +++ b/src/main/java/io/pivotal/cla/data/ContributorLicenseAgreement.java @@ -16,23 +16,25 @@ package io.pivotal.cla.data; import java.util.Date; -import javax.persistence.AttributeOverride; -import javax.persistence.AttributeOverrides; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Lob; -import javax.persistence.OneToOne; -import javax.persistence.Version; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; + +import jakarta.persistence.AttributeOverride; +import jakarta.persistence.AttributeOverrides; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Lob; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Version; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; import org.hibernate.validator.constraints.NotEmpty; @Entity public class ContributorLicenseAgreement { @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @NotEmpty(message = "This is required") private String name; @@ -62,12 +64,12 @@ public class ContributorLicenseAgreement { @Lob @NotNull(message = "This is required") @Valid - @AttributeOverrides({@AttributeOverride(name = "markdown", column = @Column(name = "individual_markdown")), @AttributeOverride(name = "html", column = @Column(name = "individual_html"))}) + @AttributeOverrides({@AttributeOverride(name = "markdown", column = @Column(name = "individual_markdown", columnDefinition = "longtext")), @AttributeOverride(name = "html", column = @Column(name = "individual_html", columnDefinition = "longtext"))}) private MarkdownContent individualContent; @Lob @Valid @NotNull(message = "This is required") - @AttributeOverrides({@AttributeOverride(name = "markdown", column = @Column(name = "corporate_markdown")), @AttributeOverride(name = "html", column = @Column(name = "corporate_html"))}) + @AttributeOverrides({@AttributeOverride(name = "markdown", column = @Column(name = "corporate_markdown", columnDefinition = "longtext")), @AttributeOverride(name = "html", column = @Column(name = "corporate_html", columnDefinition = "longtext"))}) private MarkdownContent corporateContent; public ContributorLicenseAgreement() { diff --git a/src/main/java/io/pivotal/cla/data/CorporateSignature.java b/src/main/java/io/pivotal/cla/data/CorporateSignature.java index 19f33deb..a1e3e0c9 100644 --- a/src/main/java/io/pivotal/cla/data/CorporateSignature.java +++ b/src/main/java/io/pivotal/cla/data/CorporateSignature.java @@ -16,17 +16,19 @@ package io.pivotal.cla.data; import java.util.Date; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.ManyToOne; -import javax.persistence.Version; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Version; @Entity public class CorporateSignature { @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne private ContributorLicenseAgreement cla; diff --git a/src/main/java/io/pivotal/cla/data/IndividualSignature.java b/src/main/java/io/pivotal/cla/data/IndividualSignature.java index f5b3d51f..887e36fb 100644 --- a/src/main/java/io/pivotal/cla/data/IndividualSignature.java +++ b/src/main/java/io/pivotal/cla/data/IndividualSignature.java @@ -16,17 +16,19 @@ package io.pivotal.cla.data; import java.util.Date; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.ManyToOne; -import javax.persistence.Version; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Version; @Entity public class IndividualSignature { @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne private ContributorLicenseAgreement cla; diff --git a/src/main/java/io/pivotal/cla/data/MarkdownContent.java b/src/main/java/io/pivotal/cla/data/MarkdownContent.java index 42e2200e..732d630f 100644 --- a/src/main/java/io/pivotal/cla/data/MarkdownContent.java +++ b/src/main/java/io/pivotal/cla/data/MarkdownContent.java @@ -15,8 +15,8 @@ */ package io.pivotal.cla.data; -import javax.persistence.Embeddable; -import javax.persistence.Lob; +import jakarta.persistence.Embeddable; +import jakarta.persistence.Lob; import org.hibernate.validator.constraints.NotEmpty; /** diff --git a/src/main/java/io/pivotal/cla/data/User.java b/src/main/java/io/pivotal/cla/data/User.java index 514e3d5b..dc036697 100644 --- a/src/main/java/io/pivotal/cla/data/User.java +++ b/src/main/java/io/pivotal/cla/data/User.java @@ -17,13 +17,13 @@ import java.io.Serializable; import java.util.Set; -import javax.persistence.CollectionTable; -import javax.persistence.Column; -import javax.persistence.ElementCollection; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.Transient; +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Transient; import com.fasterxml.jackson.annotation.JsonProperty; @Entity diff --git a/src/main/java/io/pivotal/cla/data/repository/ContributorLicenseAgreementRepository.java b/src/main/java/io/pivotal/cla/data/repository/ContributorLicenseAgreementRepository.java index 00ccf119..b28d3314 100644 --- a/src/main/java/io/pivotal/cla/data/repository/ContributorLicenseAgreementRepository.java +++ b/src/main/java/io/pivotal/cla/data/repository/ContributorLicenseAgreementRepository.java @@ -17,12 +17,13 @@ import java.util.List; +import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; import io.pivotal.cla.data.ContributorLicenseAgreement; public interface ContributorLicenseAgreementRepository - extends PagingAndSortingRepository { + extends PagingAndSortingRepository, CrudRepository { default ContributorLicenseAgreement findOne(Long id) { return findById(id).orElse(null); diff --git a/src/main/java/io/pivotal/cla/mvc/CclaController.java b/src/main/java/io/pivotal/cla/mvc/CclaController.java index 4c1fd5a5..ba37b65c 100644 --- a/src/main/java/io/pivotal/cla/mvc/CclaController.java +++ b/src/main/java/io/pivotal/cla/mvc/CclaController.java @@ -33,7 +33,7 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.mvc.support.RedirectAttributes; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.util.Date; import java.util.List; import java.util.Map; diff --git a/src/main/java/io/pivotal/cla/mvc/ClaRequest.java b/src/main/java/io/pivotal/cla/mvc/ClaRequest.java index f37392ef..110cdf7f 100644 --- a/src/main/java/io/pivotal/cla/mvc/ClaRequest.java +++ b/src/main/java/io/pivotal/cla/mvc/ClaRequest.java @@ -15,7 +15,7 @@ */ package io.pivotal.cla.mvc; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import io.pivotal.cla.mvc.util.UrlBuilder; diff --git a/src/main/java/io/pivotal/cla/mvc/IclaController.java b/src/main/java/io/pivotal/cla/mvc/IclaController.java index 76484f56..4fc08faf 100644 --- a/src/main/java/io/pivotal/cla/mvc/IclaController.java +++ b/src/main/java/io/pivotal/cla/mvc/IclaController.java @@ -31,7 +31,7 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.servlet.mvc.support.RedirectAttributes; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.util.Date; import java.util.Map; diff --git a/src/main/java/io/pivotal/cla/mvc/SignClaForm.java b/src/main/java/io/pivotal/cla/mvc/SignClaForm.java index 9b4aab32..a8af8b3d 100644 --- a/src/main/java/io/pivotal/cla/mvc/SignClaForm.java +++ b/src/main/java/io/pivotal/cla/mvc/SignClaForm.java @@ -15,8 +15,8 @@ */ package io.pivotal.cla.mvc; -import javax.validation.constraints.AssertTrue; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.NotNull; import org.hibernate.validator.constraints.NotEmpty; public class SignClaForm extends ClaRequest { diff --git a/src/main/java/io/pivotal/cla/mvc/admin/AdminClaController.java b/src/main/java/io/pivotal/cla/mvc/admin/AdminClaController.java index f232246d..5a4c812e 100644 --- a/src/main/java/io/pivotal/cla/mvc/admin/AdminClaController.java +++ b/src/main/java/io/pivotal/cla/mvc/admin/AdminClaController.java @@ -19,6 +19,7 @@ import java.util.Collections; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Sort; import org.springframework.security.access.prepost.PreAuthorize; import io.pivotal.cla.data.ContributorLicenseAgreement; import io.pivotal.cla.data.repository.AccessTokenRepository; diff --git a/src/main/java/io/pivotal/cla/mvc/admin/AdminCrudClaController.java b/src/main/java/io/pivotal/cla/mvc/admin/AdminCrudClaController.java index cf389f69..82b52b46 100644 --- a/src/main/java/io/pivotal/cla/mvc/admin/AdminCrudClaController.java +++ b/src/main/java/io/pivotal/cla/mvc/admin/AdminCrudClaController.java @@ -28,7 +28,7 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.util.Map; /** diff --git a/src/main/java/io/pivotal/cla/mvc/admin/AdminLinkClaController.java b/src/main/java/io/pivotal/cla/mvc/admin/AdminLinkClaController.java index 06a3bbb6..91a69f4d 100644 --- a/src/main/java/io/pivotal/cla/mvc/admin/AdminLinkClaController.java +++ b/src/main/java/io/pivotal/cla/mvc/admin/AdminLinkClaController.java @@ -30,8 +30,8 @@ import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.servlet.mvc.support.RedirectAttributes; -import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; import java.net.URLEncoder; import java.util.List; import java.util.Map; diff --git a/src/main/java/io/pivotal/cla/mvc/admin/AdminLookupSignatureController.java b/src/main/java/io/pivotal/cla/mvc/admin/AdminLookupSignatureController.java index ef1613fb..550c4a4f 100644 --- a/src/main/java/io/pivotal/cla/mvc/admin/AdminLookupSignatureController.java +++ b/src/main/java/io/pivotal/cla/mvc/admin/AdminLookupSignatureController.java @@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestParam; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.util.Map; /** @@ -24,7 +24,7 @@ public AdminLookupSignatureController(ClaService clas) { this.clas = clas; } - @GetMapping("/admin/lookup") + @GetMapping("/admin/lookup/") String index(@ModelAttribute LookupForm lookupForm) { lookupForm.setClaName("pivotal"); // default value return "admin/lookup/index"; diff --git a/src/main/java/io/pivotal/cla/mvc/admin/ClaForm.java b/src/main/java/io/pivotal/cla/mvc/admin/ClaForm.java index f8b684c2..607921a9 100644 --- a/src/main/java/io/pivotal/cla/mvc/admin/ClaForm.java +++ b/src/main/java/io/pivotal/cla/mvc/admin/ClaForm.java @@ -15,8 +15,8 @@ */ package io.pivotal.cla.mvc.admin; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; import org.hibernate.validator.constraints.NotEmpty; import org.springframework.util.StringUtils; import io.pivotal.cla.data.ContributorLicenseAgreement; diff --git a/src/main/java/io/pivotal/cla/mvc/admin/LookupForm.java b/src/main/java/io/pivotal/cla/mvc/admin/LookupForm.java index bc464a2b..05b1a277 100644 --- a/src/main/java/io/pivotal/cla/mvc/admin/LookupForm.java +++ b/src/main/java/io/pivotal/cla/mvc/admin/LookupForm.java @@ -1,6 +1,6 @@ package io.pivotal.cla.mvc.admin; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotEmpty; /** * @author Rob Winch diff --git a/src/main/java/io/pivotal/cla/mvc/admin/SignIClaForm.java b/src/main/java/io/pivotal/cla/mvc/admin/SignIClaForm.java index 701659d7..f2e113b0 100644 --- a/src/main/java/io/pivotal/cla/mvc/admin/SignIClaForm.java +++ b/src/main/java/io/pivotal/cla/mvc/admin/SignIClaForm.java @@ -18,8 +18,8 @@ import io.pivotal.cla.mvc.ClaRequest; import org.hibernate.validator.constraints.NotEmpty; -import javax.validation.constraints.AssertTrue; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.NotNull; public class SignIClaForm extends ClaRequest { @NotEmpty(message = "This is required") diff --git a/src/main/java/io/pivotal/cla/mvc/github/GitHubHooksController.java b/src/main/java/io/pivotal/cla/mvc/github/GitHubHooksController.java index 82b28ca7..a2e8313a 100644 --- a/src/main/java/io/pivotal/cla/mvc/github/GitHubHooksController.java +++ b/src/main/java/io/pivotal/cla/mvc/github/GitHubHooksController.java @@ -21,7 +21,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.eclipse.egit.github.core.Issue; import org.eclipse.egit.github.core.PullRequest; import org.eclipse.egit.github.core.Repository; diff --git a/src/main/java/io/pivotal/cla/mvc/security/OAuthController.java b/src/main/java/io/pivotal/cla/mvc/security/OAuthController.java index d5ab98a5..abf991f0 100644 --- a/src/main/java/io/pivotal/cla/mvc/security/OAuthController.java +++ b/src/main/java/io/pivotal/cla/mvc/security/OAuthController.java @@ -31,20 +31,24 @@ import org.springframework.data.domain.PageRequest; import org.springframework.http.HttpStatus; import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextImpl; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; +import org.springframework.security.web.context.HttpSessionSecurityContextRepository; +import org.springframework.security.web.context.SecurityContextRepository; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.util.List; @Controller public class OAuthController { + private SecurityContextRepository securityContextRepository = new HttpSessionSecurityContextRepository(); private AuthenticationSuccessHandler success = new SavedRequestAwareAuthenticationSuccessHandler(); @Autowired private GitHubApi gitHub; @@ -74,6 +78,7 @@ public void oauth(ImportedSignaturesSessionAttr importedSignaturesAttr, HttpServ boolean isNewUser = existingUser == null; users.save(user); Authentication authentication = Login.loginAs(user); + securityContextRepository.saveContext(new SecurityContextImpl(authentication), request, response); if (isNewUser) { List individualSignatures = individual.findSignaturesFor(PageRequest.of(0, 1), user); boolean signed = !individualSignatures.isEmpty(); diff --git a/src/main/java/io/pivotal/cla/mvc/util/UrlBuilder.java b/src/main/java/io/pivotal/cla/mvc/util/UrlBuilder.java index e34ace9f..378d3725 100644 --- a/src/main/java/io/pivotal/cla/mvc/util/UrlBuilder.java +++ b/src/main/java/io/pivotal/cla/mvc/util/UrlBuilder.java @@ -17,7 +17,7 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; diff --git a/src/main/java/io/pivotal/cla/security/GitHubAuthenticationEntryPoint.java b/src/main/java/io/pivotal/cla/security/GitHubAuthenticationEntryPoint.java index 0f07f847..682fd00b 100644 --- a/src/main/java/io/pivotal/cla/security/GitHubAuthenticationEntryPoint.java +++ b/src/main/java/io/pivotal/cla/security/GitHubAuthenticationEntryPoint.java @@ -17,9 +17,9 @@ import java.io.IOException; import java.util.UUID; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.web.util.UriComponentsBuilder; diff --git a/src/main/java/io/pivotal/cla/security/GitHubSignature.java b/src/main/java/io/pivotal/cla/security/GitHubSignature.java index 4841fafa..aa4e2c70 100644 --- a/src/main/java/io/pivotal/cla/security/GitHubSignature.java +++ b/src/main/java/io/pivotal/cla/security/GitHubSignature.java @@ -29,7 +29,7 @@ /** * @author Rob Winch */ -@Component +@Component("gitHubSignature") public class GitHubSignature { private static final String SIGNATURE_PREFIX = "sha1="; private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1"; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index b8930589..98edfd95 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,15 +1,17 @@ -spring.thymeleaf.mode=LEGACYHTML5 +spring.thymeleaf.mode=HTML spring.mvc.hiddenmethod.filter.enabled=true spring.flyway.table=schema_version spring.profiles.active=local -spring.resources.chain.strategy.content.enabled=true -spring.resources.chain.enabled=true +spring.web.resources.chain.strategy.content.enabled=true +spring.web.resources.chain.enabled=true management.endpoints.web.base-path=/manage management.endpoints.web.exposure.include=* management.info.git.mode=full spring.jpa.generate-ddl=false spring.jpa.hibernate.ddl-auto=validate -spring.jpa.hibernate.use-new-id-generator-mappings=false spring.session.store-type=redis +# https://stackoverflow.com/questions/74929193/revinfo-table-is-missing-the-sequence-revinfo-seq +# https://thorben-janssen.com/sequence-naming-strategies-in-hibernate-6/ +spring.jpa.properties.hibernate.id.db_structure_naming_strategy=legacy diff --git a/src/main/resources/templates/about.html b/src/main/resources/templates/about.html index 269758cd..5500608c 100644 --- a/src/main/resources/templates/about.html +++ b/src/main/resources/templates/about.html @@ -1,4 +1,4 @@ - + About @@ -16,7 +16,7 @@

Why Does Pivotal Require a CLA?

Our CLA is based on the Apache Software Foundation’s CLA and in it, contributors state that the contributions are their original work and grant Pivotal a copyright and patent license to include their contributions in the project. In return, Pivotal and the open source communities we serve are able to distribute and build upon such contributions. This means that if any legal issues arise in the future about our rights to distribute the code, we can show them these forms. - It also ensures that the contributors cannot withdraw permission to the contributions at some point in the future. + It also ensures that the contributors cannot withdraw permission to the contributions at some point in the future.

Both individuals and large enterprises use code from our open source projects, and in our experience, they need to be sure about the origins and rights to use the code. diff --git a/src/main/resources/templates/admin/cla/form.html b/src/main/resources/templates/admin/cla/form.html index 52002526..fc379619 100644 --- a/src/main/resources/templates/admin/cla/form.html +++ b/src/main/resources/templates/admin/cla/form.html @@ -1,6 +1,6 @@ + layout:decorate="layouts/main" th:with="isEditCla=${claForm.id != null}"> Create CLA diff --git a/src/main/resources/templates/admin/cla/index.html b/src/main/resources/templates/admin/cla/index.html index af33cfb2..d91eb0a2 100644 --- a/src/main/resources/templates/admin/cla/index.html +++ b/src/main/resources/templates/admin/cla/index.html @@ -1,6 +1,6 @@ + layout:decorate="layouts/main"> Manage CLAs diff --git a/src/main/resources/templates/admin/cla/link.html b/src/main/resources/templates/admin/cla/link.html index a98e99c7..d7e3c71e 100644 --- a/src/main/resources/templates/admin/cla/link.html +++ b/src/main/resources/templates/admin/cla/link.html @@ -1,5 +1,5 @@ - + Link to CLA diff --git a/src/main/resources/templates/admin/cla/sign/icla.html b/src/main/resources/templates/admin/cla/sign/icla.html index 178c3fb8..2734dea5 100644 --- a/src/main/resources/templates/admin/cla/sign/icla.html +++ b/src/main/resources/templates/admin/cla/sign/icla.html @@ -1,6 +1,6 @@ + layout:decorate="layouts/main"> Sign ICLA diff --git a/src/main/resources/templates/admin/help/index.html b/src/main/resources/templates/admin/help/index.html index fdeb6634..d68a6b9b 100644 --- a/src/main/resources/templates/admin/help/index.html +++ b/src/main/resources/templates/admin/help/index.html @@ -1,6 +1,6 @@ + layout:decorate="layouts/main"> Admin Help diff --git a/src/main/resources/templates/admin/help/migrate.html b/src/main/resources/templates/admin/help/migrate.html index 4c213cb4..15ed3698 100644 --- a/src/main/resources/templates/admin/help/migrate.html +++ b/src/main/resources/templates/admin/help/migrate.html @@ -1,6 +1,6 @@ + layout:decorate="layouts/main"> Migrating diff --git a/src/main/resources/templates/admin/lookup/index.html b/src/main/resources/templates/admin/lookup/index.html index a56ff6c7..c56dd20d 100644 --- a/src/main/resources/templates/admin/lookup/index.html +++ b/src/main/resources/templates/admin/lookup/index.html @@ -1,6 +1,6 @@ + layout:decorate="layouts/main"> Lookup Signature diff --git a/src/main/resources/templates/cla/ccla/sign.html b/src/main/resources/templates/cla/ccla/sign.html index 936808c3..68dcbaaa 100644 --- a/src/main/resources/templates/cla/ccla/sign.html +++ b/src/main/resources/templates/cla/ccla/sign.html @@ -1,6 +1,6 @@ + layout:decorate="layouts/main"> Sign CCLA diff --git a/src/main/resources/templates/cla/ccla/view.html b/src/main/resources/templates/cla/ccla/view.html index e229ee4c..b7e47a79 100644 --- a/src/main/resources/templates/cla/ccla/view.html +++ b/src/main/resources/templates/cla/ccla/view.html @@ -1,6 +1,6 @@ + layout:decorate="layouts/main"> Sign CCLA diff --git a/src/main/resources/templates/cla/icla/sign.html b/src/main/resources/templates/cla/icla/sign.html index f77795ea..35685eac 100644 --- a/src/main/resources/templates/cla/icla/sign.html +++ b/src/main/resources/templates/cla/icla/sign.html @@ -1,6 +1,6 @@ + layout:decorate="layouts/main"> Sign ICLA diff --git a/src/main/resources/templates/cla/icla/view.html b/src/main/resources/templates/cla/icla/view.html index 726e810c..46a868b7 100644 --- a/src/main/resources/templates/cla/icla/view.html +++ b/src/main/resources/templates/cla/icla/view.html @@ -1,6 +1,6 @@ + layout:decorate="layouts/main"> View ICLA diff --git a/src/main/resources/templates/error.html b/src/main/resources/templates/error.html index df9a2fd5..705814ca 100644 --- a/src/main/resources/templates/error.html +++ b/src/main/resources/templates/error.html @@ -1,4 +1,4 @@ - + Error diff --git a/src/main/resources/templates/error/403.html b/src/main/resources/templates/error/403.html index 303434cc..f79f9764 100644 --- a/src/main/resources/templates/error/403.html +++ b/src/main/resources/templates/error/403.html @@ -1,4 +1,4 @@ - + Access Denied diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 8593c2e8..280fdad6 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -1,4 +1,4 @@ - + Home diff --git a/src/main/resources/templates/layouts/main.html b/src/main/resources/templates/layouts/main.html index 2209c1b6..bc28fdfb 100644 --- a/src/main/resources/templates/layouts/main.html +++ b/src/main/resources/templates/layouts/main.html @@ -8,7 +8,7 @@ - Pivotal CLA + Pivotal CLA diff --git a/src/main/resources/templates/sync/form.html b/src/main/resources/templates/sync/form.html index 044df3b0..68b2d3db 100644 --- a/src/main/resources/templates/sync/form.html +++ b/src/main/resources/templates/sync/form.html @@ -1,6 +1,6 @@ + layout:decorate="layouts/main"> Sync Pull Request diff --git a/src/test/java/io/pivotal/cla/MocksConfig.java b/src/test/java/io/pivotal/cla/MocksConfig.java index 3a2487cf..9f98497c 100644 --- a/src/test/java/io/pivotal/cla/MocksConfig.java +++ b/src/test/java/io/pivotal/cla/MocksConfig.java @@ -15,14 +15,14 @@ */ package io.pivotal.cla; +import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; -@Configuration -@Profile("test") +@TestConfiguration public class MocksConfig { @Controller diff --git a/src/test/java/io/pivotal/cla/TestPivotalClaApplication.java b/src/test/java/io/pivotal/cla/TestPivotalClaApplication.java new file mode 100644 index 00000000..a962d1f6 --- /dev/null +++ b/src/test/java/io/pivotal/cla/TestPivotalClaApplication.java @@ -0,0 +1,31 @@ +/* + * Copyright 2002-2024 the original author or authors. + * + * Licensed 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 + * + * http://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 io.pivotal.cla; + +import io.pivotal.cla.data.repository.MysqlConfiguration; +import org.springframework.boot.SpringApplication; +import org.springframework.test.context.ActiveProfiles; + +@ActiveProfiles("local") +public class TestPivotalClaApplication { + + public static void main(String[] args) { + SpringApplication.from(PivotalClaApplication::main) + .with(MysqlConfiguration.class) + .run(args); + } +} \ No newline at end of file diff --git a/src/test/java/io/pivotal/cla/config/ClaOAuthConfigTests.java b/src/test/java/io/pivotal/cla/config/ClaOAuthConfigTests.java index d00f3bca..2288f286 100644 --- a/src/test/java/io/pivotal/cla/config/ClaOAuthConfigTests.java +++ b/src/test/java/io/pivotal/cla/config/ClaOAuthConfigTests.java @@ -17,10 +17,8 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.lang.reflect.Modifier; - -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; /** @@ -30,7 +28,7 @@ public class ClaOAuthConfigTests { ClaOAuthConfig config; - @Before + @BeforeEach public void setup() { config = new ClaOAuthConfig(); } diff --git a/src/test/java/io/pivotal/cla/data/repository/CorporateSignatureRepositoryTests.java b/src/test/java/io/pivotal/cla/data/repository/CorporateSignatureRepositoryTests.java index 77d0b829..487e89f4 100644 --- a/src/test/java/io/pivotal/cla/data/repository/CorporateSignatureRepositoryTests.java +++ b/src/test/java/io/pivotal/cla/data/repository/CorporateSignatureRepositoryTests.java @@ -19,17 +19,20 @@ import io.pivotal.cla.data.CorporateSignature; import io.pivotal.cla.data.DataUtils; import io.pivotal.cla.data.User; -import io.pivotal.cla.junit.JpaTests; -import io.pivotal.cla.test.context.SystemDataActiveProfiles; -import org.junit.Before; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; import org.springframework.data.domain.PageRequest; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.testcontainers.containers.MySQLContainer; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; import java.util.Arrays; import java.util.Collections; @@ -40,11 +43,11 @@ * @author Rob Winch * */ -@RunWith(SpringJUnit4ClassRunner.class) @DataJpaTest +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @TestPropertySource(locations="/application-test.properties") -@SystemDataActiveProfiles -@Category(JpaTests.class) +@Testcontainers +@Import(MysqlConfiguration.class) public class CorporateSignatureRepositoryTests { @Autowired @@ -61,7 +64,7 @@ public class CorporateSignatureRepositoryTests { User user; - @Before + @BeforeEach public void setup() { user = DataUtils.createUser(); @@ -227,4 +230,5 @@ private static CorporateSignature createSignature(ContributorLicenseAgreement cl signature.setEmail(user.getEmails().iterator().next()); return signature; } + } diff --git a/src/test/java/io/pivotal/cla/data/repository/IndividualSignatureRepositoryTests.java b/src/test/java/io/pivotal/cla/data/repository/IndividualSignatureRepositoryTests.java index b3faca5f..2b95605c 100644 --- a/src/test/java/io/pivotal/cla/data/repository/IndividualSignatureRepositoryTests.java +++ b/src/test/java/io/pivotal/cla/data/repository/IndividualSignatureRepositoryTests.java @@ -19,18 +19,18 @@ import io.pivotal.cla.data.DataUtils; import io.pivotal.cla.data.IndividualSignature; import io.pivotal.cla.data.User; -import io.pivotal.cla.junit.JpaTests; import io.pivotal.cla.service.ClaService; -import io.pivotal.cla.test.context.SystemDataActiveProfiles; -import org.junit.Before; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.runner.RunWith; +import io.pivotal.cla.service.github.GitHubApi; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; import org.springframework.data.domain.PageRequest; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.testcontainers.junit.jupiter.Testcontainers; import java.util.Collections; @@ -40,11 +40,11 @@ * @author Rob Winch * */ -@RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest +@DataJpaTest +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @TestPropertySource(locations="/application-test.properties") -@SystemDataActiveProfiles -@Category(JpaTests.class) +@Testcontainers +@Import({MysqlConfiguration.class, ClaService.class}) public class IndividualSignatureRepositoryTests { @Autowired @@ -56,6 +56,9 @@ public class IndividualSignatureRepositoryTests { @Autowired ClaService claService; + @MockBean + GitHubApi gitHubApi; + ContributorLicenseAgreement cla; ContributorLicenseAgreement springCla; @@ -64,7 +67,7 @@ public class IndividualSignatureRepositoryTests { User user; - @Before + @BeforeEach public void setup() { user = DataUtils.createUser(); diff --git a/src/test/java/io/pivotal/cla/data/repository/MysqlConfiguration.java b/src/test/java/io/pivotal/cla/data/repository/MysqlConfiguration.java new file mode 100644 index 00000000..1fd8ba01 --- /dev/null +++ b/src/test/java/io/pivotal/cla/data/repository/MysqlConfiguration.java @@ -0,0 +1,33 @@ +/* + * Copyright 2002-2024 the original author or authors. + * + * Licensed 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 + * + * http://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 io.pivotal.cla.data.repository; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.context.annotation.Bean; +import org.testcontainers.containers.MySQLContainer; +import org.testcontainers.utility.DockerImageName; + +@TestConfiguration(proxyBeanMethods = false) +public class MysqlConfiguration { + + @Bean + @ServiceConnection + static MySQLContainer mysqlContainer() { + return new MySQLContainer(DockerImageName.parse("mysql:8.0.36")); + } +} diff --git a/src/test/java/io/pivotal/cla/mvc/admin/AdminUserControllerTests.java b/src/test/java/io/pivotal/cla/mvc/admin/AdminUserControllerTests.java index eeccf44b..06118869 100644 --- a/src/test/java/io/pivotal/cla/mvc/admin/AdminUserControllerTests.java +++ b/src/test/java/io/pivotal/cla/mvc/admin/AdminUserControllerTests.java @@ -3,19 +3,16 @@ import io.pivotal.cla.data.User; import io.pivotal.cla.data.repository.UserRepository; +import io.pivotal.cla.security.ImportSecurity; import io.pivotal.cla.security.WithAdminUser; import io.pivotal.cla.security.WithClaAuthorUser; import io.pivotal.cla.security.WithSigningUser; -import io.pivotal.cla.webdriver.WebDriverContext; +import io.pivotal.cla.service.ClaService; import org.hamcrest.CoreMatchers; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; @@ -25,12 +22,15 @@ import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; -@WebDriverContext -@RunWith(SpringRunner.class) +@WebMvcTest(AdminUserController.class) +@ImportSecurity public class AdminUserControllerTests { @MockBean UserRepository users; + @MockBean + ClaService claService; + @Autowired MockMvc mockMvc; diff --git a/src/test/java/io/pivotal/cla/mvc/github/GitHubHooksControllerTests.java b/src/test/java/io/pivotal/cla/mvc/github/GitHubHooksControllerTests.java index 633334f4..4d2cc701 100644 --- a/src/test/java/io/pivotal/cla/mvc/github/GitHubHooksControllerTests.java +++ b/src/test/java/io/pivotal/cla/mvc/github/GitHubHooksControllerTests.java @@ -25,10 +25,13 @@ import java.io.UnsupportedEncodingException; import java.util.Arrays; -import org.junit.Before; -import org.junit.Test; +import io.pivotal.cla.security.GitHubSignature; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.request.RequestPostProcessor; @@ -38,23 +41,23 @@ import io.pivotal.cla.data.User; import io.pivotal.cla.egit.github.core.PullRequestId; import io.pivotal.cla.egit.github.core.event.GithubEvents; -import io.pivotal.cla.security.GitHubSignature; import io.pivotal.cla.security.WithSigningUserFactory; import io.pivotal.cla.service.github.GitHubApi; import io.pivotal.cla.service.github.PullRequestStatus; import io.pivotal.cla.webdriver.BaseWebDriverTests; +@Import(GitHubSignature.class) public class GitHubHooksControllerTests extends BaseWebDriverTests { AccessToken accessToken; @Autowired - GitHubSignature oauth; + GitHubApi gitHubApiMock; @Autowired - GitHubApi gitHubApiMock; + GitHubSignature oauth; - @Before + @BeforeEach public void setupAccessToken() { accessToken = new AccessToken(AccessToken.CLA_ACCESS_TOKEN_ID, "GitHubHooksControllerTests_access_token"); when(mockTokenRepo.findOne(AccessToken.CLA_ACCESS_TOKEN_ID)).thenReturn(accessToken); diff --git a/src/test/java/io/pivotal/cla/mvc/support/ImportedSignaturesSessionAttrResolverTests.java b/src/test/java/io/pivotal/cla/mvc/support/ImportedSignaturesSessionAttrResolverTests.java index c626bd73..70f03bf0 100644 --- a/src/test/java/io/pivotal/cla/mvc/support/ImportedSignaturesSessionAttrResolverTests.java +++ b/src/test/java/io/pivotal/cla/mvc/support/ImportedSignaturesSessionAttrResolverTests.java @@ -15,8 +15,8 @@ */ package io.pivotal.cla.mvc.support; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.core.MethodParameter; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.util.ReflectionUtils; @@ -37,7 +37,7 @@ public class ImportedSignaturesSessionAttrResolverTests { ImportedSignaturesSessionAttrResolver resolver; - @Before + @BeforeEach public void setup() { resolver = new ImportedSignaturesSessionAttrResolver(); method = ReflectionUtils.findMethod(ImportedSignaturesSessionAttrResolverTests.class, "methodParameter", ImportedSignaturesSessionAttr.class, Object.class); diff --git a/src/test/java/io/pivotal/cla/mvc/support/ImportedSignaturesSessionAttrTests.java b/src/test/java/io/pivotal/cla/mvc/support/ImportedSignaturesSessionAttrTests.java index a4dd0d05..8f425494 100644 --- a/src/test/java/io/pivotal/cla/mvc/support/ImportedSignaturesSessionAttrTests.java +++ b/src/test/java/io/pivotal/cla/mvc/support/ImportedSignaturesSessionAttrTests.java @@ -17,8 +17,8 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.web.context.request.ServletWebRequest; @@ -31,7 +31,7 @@ public class ImportedSignaturesSessionAttrTests { MockHttpServletRequest request; - @Before + @BeforeEach public void setup() { request = new MockHttpServletRequest(); attr = new ImportedSignaturesSessionAttr(new ServletWebRequest(request)); diff --git a/src/test/java/io/pivotal/cla/security/GitHubSignatureTests.java b/src/test/java/io/pivotal/cla/security/GitHubSignatureTests.java index ce2e8cb8..241b5afd 100644 --- a/src/test/java/io/pivotal/cla/security/GitHubSignatureTests.java +++ b/src/test/java/io/pivotal/cla/security/GitHubSignatureTests.java @@ -16,14 +16,14 @@ package io.pivotal.cla.security; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.when; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import io.pivotal.cla.data.AccessToken; import io.pivotal.cla.data.repository.AccessTokenRepository; @@ -32,7 +32,7 @@ * @author Rob Winch * */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class GitHubSignatureTests { @Mock AccessTokenRepository mockAccessTokens; @@ -41,7 +41,7 @@ public class GitHubSignatureTests { AccessToken token; - @Before + @BeforeEach public void setup() { gitHubSignature = new GitHubSignature(mockAccessTokens); token = new AccessToken(); diff --git a/src/test/java/io/pivotal/cla/security/ImportSecurity.java b/src/test/java/io/pivotal/cla/security/ImportSecurity.java new file mode 100644 index 00000000..9aca8ad2 --- /dev/null +++ b/src/test/java/io/pivotal/cla/security/ImportSecurity.java @@ -0,0 +1,29 @@ +/* + * Copyright 2002-2024 the original author or authors. + * + * Licensed 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 + * + * http://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 io.pivotal.cla.security; + +import io.pivotal.cla.config.ClaOAuthConfig; +import io.pivotal.cla.config.SecurityConfig; +import org.springframework.context.annotation.Import; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +@Import({SecurityConfig.class, ClaOAuthConfig.class}) +public @interface ImportSecurity { +} diff --git a/src/test/java/io/pivotal/cla/service/github/MylynGitHubApiITests.java b/src/test/java/io/pivotal/cla/service/github/MylynGitHubApiITests.java index b2235aff..dcdb8133 100644 --- a/src/test/java/io/pivotal/cla/service/github/MylynGitHubApiITests.java +++ b/src/test/java/io/pivotal/cla/service/github/MylynGitHubApiITests.java @@ -15,42 +15,40 @@ */ package io.pivotal.cla.service.github; -import static org.assertj.core.api.Assertions.*; - -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.runners.MockitoJUnitRunner; -import org.springframework.core.serializer.support.SerializingConverter; - import io.pivotal.cla.config.ClaOAuthConfig; import io.pivotal.cla.config.OAuthClientCredentials; import io.pivotal.cla.data.User; import okhttp3.mockwebserver.EnqueueRequests; +import okhttp3.mockwebserver.EnqueueRequestsExtension; import okhttp3.mockwebserver.EnqueueResourcesMockWebServer; import okhttp3.mockwebserver.RecordedRequest; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.core.serializer.support.SerializingConverter; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; /** * @author Rob Winch * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith({ MockitoExtension.class, EnqueueRequestsExtension.class }) public class MylynGitHubApiITests { - @Rule public final EnqueueResourcesMockWebServer server = new EnqueueResourcesMockWebServer(); ClaOAuthConfig oauthConfig; MylynGitHubApi service; - @Before + @BeforeEach public void setup() throws IOException { OAuthClientCredentials credentials = new OAuthClientCredentials(); @@ -1247,7 +1245,7 @@ public void saveFailureNoComments() throws Exception { "getStatusNone", "saveStatus" }) - @Ignore + @Disabled public void saveFailureNoCommentsPullRequestClosed() throws Exception { String accessToken = "access-token-123"; @@ -1273,7 +1271,7 @@ public void saveFailureNoCommentsPullRequestClosed() throws Exception { "getStatusNone", "saveStatus" }) - @Ignore + @Disabled public void saveFailureNoCommentsPullRequestUnknownState() throws Exception { String accessToken = "access-token-123"; diff --git a/src/test/java/io/pivotal/cla/test/context/SystemActiveProfilesResolverTests.java b/src/test/java/io/pivotal/cla/test/context/SystemActiveProfilesResolverTests.java index 6f094678..ea79ce0a 100644 --- a/src/test/java/io/pivotal/cla/test/context/SystemActiveProfilesResolverTests.java +++ b/src/test/java/io/pivotal/cla/test/context/SystemActiveProfilesResolverTests.java @@ -17,8 +17,8 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.test.context.ActiveProfiles; /** @@ -28,7 +28,7 @@ public class SystemActiveProfilesResolverTests { SystemActiveProfilesResolver resolver; - @Before + @BeforeEach public void setup() { resolver = new SystemActiveProfilesResolver(); } diff --git a/src/test/java/io/pivotal/cla/webdriver/AboutControllerTests.java b/src/test/java/io/pivotal/cla/webdriver/AboutControllerTests.java index 5b23dafa..ca76f498 100644 --- a/src/test/java/io/pivotal/cla/webdriver/AboutControllerTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/AboutControllerTests.java @@ -18,7 +18,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class AboutControllerTests extends BaseWebDriverTests { diff --git a/src/test/java/io/pivotal/cla/webdriver/AccessDeniedTests.java b/src/test/java/io/pivotal/cla/webdriver/AccessDeniedTests.java index 60749321..e7429885 100644 --- a/src/test/java/io/pivotal/cla/webdriver/AccessDeniedTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/AccessDeniedTests.java @@ -15,12 +15,12 @@ */ package io.pivotal.cla.webdriver; -import static org.mockito.Matchers.any; +import static org.mockito.Mockito.any; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import org.junit.Test; +import org.junit.jupiter.api.Test; import io.pivotal.cla.data.User; import io.pivotal.cla.security.WithSigningUser; diff --git a/src/test/java/io/pivotal/cla/webdriver/ActuatorSecurityTests.java b/src/test/java/io/pivotal/cla/webdriver/ActuatorSecurityTests.java index 59908ddd..26266752 100644 --- a/src/test/java/io/pivotal/cla/webdriver/ActuatorSecurityTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/ActuatorSecurityTests.java @@ -18,7 +18,19 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.springframework.boot.actuate.autoconfigure.beans.BeansEndpointAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.endpoint.web.ServletEndpointManagementContextConfiguration; +import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.endpoint.web.servlet.WebMvcEndpointManagementContextConfiguration; +import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; +import org.springframework.boot.autoconfigure.*; +import org.springframework.boot.context.TypeExcludeFilter; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.context.annotation.Import; +import org.springframework.core.Ordered; import org.springframework.http.MediaType; import io.pivotal.cla.security.WithAdminUser; @@ -29,6 +41,7 @@ * @author Rob Winch * */ +@ImportAutoConfiguration({EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, BeansEndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class}) public class ActuatorSecurityTests extends BaseWebDriverTests { @Test diff --git a/src/test/java/io/pivotal/cla/webdriver/AuthenticationTests.java b/src/test/java/io/pivotal/cla/webdriver/AuthenticationTests.java index 7b730e65..e29f4372 100644 --- a/src/test/java/io/pivotal/cla/webdriver/AuthenticationTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/AuthenticationTests.java @@ -16,9 +16,9 @@ package io.pivotal.cla.webdriver; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anySet; -import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anySet; +import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -28,11 +28,14 @@ import java.util.Arrays; import java.util.Collections; -import org.junit.Test; +import io.pivotal.cla.MocksConfig; +import io.pivotal.cla.security.ImportSecurity; +import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Import; import org.springframework.mock.web.MockHttpSession; import org.springframework.security.test.context.TestSecurityContextHolder; import org.springframework.util.MultiValueMap; @@ -49,6 +52,7 @@ import io.pivotal.cla.webdriver.pages.SignClaPage; import io.pivotal.cla.webdriver.pages.admin.AdminLinkClaPage; +@Import(MocksConfig.class) public class AuthenticationTests extends BaseWebDriverTests { @Autowired @@ -133,6 +137,7 @@ public void authenticateAdmin() throws Exception { when(mockGitHub.getCurrentUser(any(CurrentUserRequest.class))).thenReturn(user); AdminLinkClaPage admin = AdminLinkClaPage.to(driver); + System.out.println(driver.getCurrentUrl()); admin.assertAt(); ArgumentCaptor userCaptor = ArgumentCaptor.forClass(CurrentUserRequest.class); diff --git a/src/test/java/io/pivotal/cla/webdriver/BaseWebDriverTests.java b/src/test/java/io/pivotal/cla/webdriver/BaseWebDriverTests.java index 059884d1..aa9a0190 100644 --- a/src/test/java/io/pivotal/cla/webdriver/BaseWebDriverTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/BaseWebDriverTests.java @@ -19,14 +19,17 @@ import java.net.URLDecoder; import java.util.concurrent.Executors; -import org.junit.Before; -import org.junit.runner.RunWith; +import io.pivotal.cla.security.GitHubSignature; +import io.pivotal.cla.security.ImportSecurity; +import io.pivotal.cla.service.ClaService; +import org.junit.jupiter.api.BeforeEach; import org.openqa.selenium.WebDriver; import org.openqa.selenium.htmlunit.HtmlUnitDriver; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; import org.springframework.security.concurrent.DelegatingSecurityContextExecutor; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDriverBuilder; import org.springframework.web.context.WebApplicationContext; @@ -42,8 +45,9 @@ import io.pivotal.cla.data.repository.UserRepository; import io.pivotal.cla.service.github.GitHubApi; -@RunWith(SpringJUnit4ClassRunner.class) -@WebDriverContext +@WebMvcTest +@ImportSecurity +@Import(ClaService.class) public abstract class BaseWebDriverTests { @Autowired protected WebApplicationContext wac; @@ -70,7 +74,7 @@ public abstract class BaseWebDriverTests { protected IndividualSignature individualSignature; protected CorporateSignature corporateSignature; - @Before + @BeforeEach public void setup() { HtmlUnitDriver driver = MockMvcHtmlUnitDriverBuilder .mockMvcSetup(mockMvc) diff --git a/src/test/java/io/pivotal/cla/webdriver/CclaControllerTests.java b/src/test/java/io/pivotal/cla/webdriver/CclaControllerTests.java index 4219e7a1..51c7bb5e 100644 --- a/src/test/java/io/pivotal/cla/webdriver/CclaControllerTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/CclaControllerTests.java @@ -16,9 +16,9 @@ package io.pivotal.cla.webdriver; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyCollectionOf; -import static org.mockito.Matchers.anyString; +import static org.mockito.ArgumentMatchers.anyCollection; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -31,7 +31,7 @@ import java.util.concurrent.TimeUnit; import io.pivotal.cla.webdriver.pages.ViewCclaPage; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import io.pivotal.cla.data.AccessToken; @@ -455,7 +455,7 @@ public void signWithRepositoryIdWithPullRequestId() throws Exception { when(mockClaRepository.findOne(cla.getId())).thenReturn(cla); when(mockGitHub.getOrganizations(anyString())).thenReturn(Arrays.asList("spring","pivotal")); when(mockGitHub.getShaForPullRequest(any(PullRequestStatus.class))).thenReturn("abc123"); - when(mockCorporateSignatureRepository.findSignature(anyString(), anyCollectionOf(String.class), anyCollectionOf(String.class))).thenReturn(null,corporateSignature); + when(mockCorporateSignatureRepository.findSignature(anyString(), anyCollection(), anyCollection())).thenReturn(null,corporateSignature); when(mockTokenRepo.findOne(repositoryId)).thenReturn(new AccessToken(repositoryId, "access-token-123")); int pullRequestId = 2; diff --git a/src/test/java/io/pivotal/cla/webdriver/ClaControllerTests.java b/src/test/java/io/pivotal/cla/webdriver/ClaControllerTests.java index a86ccc9e..8757911e 100644 --- a/src/test/java/io/pivotal/cla/webdriver/ClaControllerTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/ClaControllerTests.java @@ -16,8 +16,8 @@ package io.pivotal.cla.webdriver; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -27,9 +27,12 @@ import java.util.Arrays; import java.util.List; -import org.junit.Before; -import org.junit.Test; +import io.pivotal.cla.MocksConfig; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; +import org.springframework.context.annotation.Import; +import org.springframework.security.test.context.TestSecurityContextHolder; import org.springframework.security.test.context.support.WithAnonymousUser; import io.pivotal.cla.data.AccessToken; @@ -43,9 +46,10 @@ import io.pivotal.cla.webdriver.pages.SignIclaPage; @WithSigningUser +@Import(MocksConfig.class) public class ClaControllerTests extends BaseWebDriverTests { - @Before + @BeforeEach public void setup() { super.setup(); when(mockClaRepository.findByNameAndPrimaryTrue(cla.getName())).thenReturn(cla); @@ -54,6 +58,7 @@ public void setup() { @Test @WithAnonymousUser public void viewSignedWithRepositoryIdAndPullRequestIdNewUser() throws Exception { + TestSecurityContextHolder.clearContext(); // FIXME: This is a work around for bug with AnonymousAuthenticationToken in test security context clears out any new values. String repositoryId = "spring-projects/spring-security"; User signingUser = WithSigningUserFactory.create(); when(mockGitHub.getCurrentUser(any())).thenReturn(signingUser); diff --git a/src/test/java/io/pivotal/cla/webdriver/FaqControllerTests.java b/src/test/java/io/pivotal/cla/webdriver/FaqControllerTests.java index c8e8628d..3f9541f7 100644 --- a/src/test/java/io/pivotal/cla/webdriver/FaqControllerTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/FaqControllerTests.java @@ -15,7 +15,7 @@ */ package io.pivotal.cla.webdriver; -import org.junit.Test; +import org.junit.jupiter.api.Test; import io.pivotal.cla.webdriver.pages.FaqPage; diff --git a/src/test/java/io/pivotal/cla/webdriver/HomeControllerTests.java b/src/test/java/io/pivotal/cla/webdriver/HomeControllerTests.java index 9d300859..55e1e7ee 100644 --- a/src/test/java/io/pivotal/cla/webdriver/HomeControllerTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/HomeControllerTests.java @@ -19,7 +19,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import org.junit.Test; +import org.junit.jupiter.api.Test; import io.pivotal.cla.security.WithSigningUser; import io.pivotal.cla.webdriver.pages.AboutPage; diff --git a/src/test/java/io/pivotal/cla/webdriver/IclaControllerTests.java b/src/test/java/io/pivotal/cla/webdriver/IclaControllerTests.java index 043cc2ba..b3ece3a2 100644 --- a/src/test/java/io/pivotal/cla/webdriver/IclaControllerTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/IclaControllerTests.java @@ -16,10 +16,10 @@ package io.pivotal.cla.webdriver; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.eq; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -30,7 +30,7 @@ import java.util.concurrent.TimeUnit; import io.pivotal.cla.webdriver.pages.ViewIclaPage; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import io.pivotal.cla.data.AccessToken; @@ -274,7 +274,7 @@ public void signNoRepositoryIdAndNoPullRequestId() { .sign(SignIclaPage.class); signPage.assertAt(); - verifyZeroInteractions(mockGitHub); + verifyNoInteractions(mockGitHub); } @Test @@ -309,7 +309,7 @@ private void assertThatClaIsSigned(SignClaForm form) { assertThat(signature.getTelephone()).isEqualTo(form.getTelephone()); assertThat(signature.getDateOfSignature()).isCloseTo(new Date(), TimeUnit.SECONDS.toMillis(5)); - verifyZeroInteractions(mockGitHub); + verifyNoInteractions(mockGitHub); } @Test diff --git a/src/test/java/io/pivotal/cla/webdriver/RequiresChannelTests.java b/src/test/java/io/pivotal/cla/webdriver/RequiresChannelTests.java index 9770b637..e78d40d3 100644 --- a/src/test/java/io/pivotal/cla/webdriver/RequiresChannelTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/RequiresChannelTests.java @@ -19,7 +19,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class RequiresChannelTests extends BaseWebDriverTests { diff --git a/src/test/java/io/pivotal/cla/webdriver/WebDriverContext.java b/src/test/java/io/pivotal/cla/webdriver/WebDriverContext.java deleted file mode 100644 index 2660fc9d..00000000 --- a/src/test/java/io/pivotal/cla/webdriver/WebDriverContext.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed 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 - * - * http://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 io.pivotal.cla.webdriver; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.springframework.boot.test.autoconfigure.orm.jpa.AutoConfigureDataJpa; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.test.context.ActiveProfiles; - -@Documented -@Inherited -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -@AutoConfigureMockMvc -@ActiveProfiles("test") -@SpringBootTest(webEnvironment = WebEnvironment.MOCK) -public @interface WebDriverContext { -} diff --git a/src/test/java/io/pivotal/cla/webdriver/admin/AdminCreateClaTests.java b/src/test/java/io/pivotal/cla/webdriver/admin/AdminCreateClaTests.java index 03137fca..9ab765c7 100644 --- a/src/test/java/io/pivotal/cla/webdriver/admin/AdminCreateClaTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/admin/AdminCreateClaTests.java @@ -21,7 +21,7 @@ import java.util.Arrays; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import io.pivotal.cla.data.ContributorLicenseAgreement; diff --git a/src/test/java/io/pivotal/cla/webdriver/admin/AdminHelpTests.java b/src/test/java/io/pivotal/cla/webdriver/admin/AdminHelpTests.java index 24a1c7f8..0b1407d0 100644 --- a/src/test/java/io/pivotal/cla/webdriver/admin/AdminHelpTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/admin/AdminHelpTests.java @@ -15,7 +15,7 @@ */ package io.pivotal.cla.webdriver.admin; -import org.junit.Test; +import org.junit.jupiter.api.Test; import io.pivotal.cla.security.WithAdminUser; import io.pivotal.cla.webdriver.BaseWebDriverTests; diff --git a/src/test/java/io/pivotal/cla/webdriver/admin/AdminHomeTests.java b/src/test/java/io/pivotal/cla/webdriver/admin/AdminHomeTests.java index 9a7d6d26..2b0f890e 100644 --- a/src/test/java/io/pivotal/cla/webdriver/admin/AdminHomeTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/admin/AdminHomeTests.java @@ -19,7 +19,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import org.junit.Test; +import org.junit.jupiter.api.Test; import io.pivotal.cla.security.WithAdminUser; import io.pivotal.cla.security.WithClaAuthorUser; diff --git a/src/test/java/io/pivotal/cla/webdriver/admin/AdminLinkClaTests.java b/src/test/java/io/pivotal/cla/webdriver/admin/AdminLinkClaTests.java index cba4a771..7d36a899 100644 --- a/src/test/java/io/pivotal/cla/webdriver/admin/AdminLinkClaTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/admin/AdminLinkClaTests.java @@ -17,19 +17,18 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyList; -import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyList; +import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.Arrays; import java.util.concurrent.Executors; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; -import org.openqa.selenium.WebDriver; import org.openqa.selenium.htmlunit.HtmlUnitDriver; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.concurrent.DelegatingSecurityContextExecutor; @@ -50,7 +49,7 @@ @WithAdminUser public class AdminLinkClaTests extends BaseWebDriverTests { - @Before + @BeforeEach public void claFormData() throws Exception { when(mockClaRepository.findByPrimaryTrue()).thenReturn(Arrays.asList(cla,cla)); when(mockGitHub.findRepositoryNamesWithAdminPermission(anyString())).thenReturn(Arrays.asList("test/this")); diff --git a/src/test/java/io/pivotal/cla/webdriver/admin/AdminListClaTests.java b/src/test/java/io/pivotal/cla/webdriver/admin/AdminListClaTests.java index f0c604e8..d28c95fc 100644 --- a/src/test/java/io/pivotal/cla/webdriver/admin/AdminListClaTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/admin/AdminListClaTests.java @@ -21,7 +21,7 @@ import java.util.Arrays; -import org.junit.Test; +import org.junit.jupiter.api.Test; import io.pivotal.cla.security.WithClaAuthorUser; import io.pivotal.cla.webdriver.BaseWebDriverTests; diff --git a/src/test/java/io/pivotal/cla/webdriver/admin/AdminLookupSignatureTests.java b/src/test/java/io/pivotal/cla/webdriver/admin/AdminLookupSignatureTests.java index b247a485..862682a1 100644 --- a/src/test/java/io/pivotal/cla/webdriver/admin/AdminLookupSignatureTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/admin/AdminLookupSignatureTests.java @@ -20,7 +20,7 @@ import io.pivotal.cla.webdriver.BaseWebDriverTests; import io.pivotal.cla.webdriver.pages.admin.AdminLookupSignaturePage; import io.pivotal.cla.webdriver.pages.admin.AdminLookupSignaturePage.FindSignatureForm; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import static org.assertj.core.api.Assertions.assertThat; diff --git a/src/test/java/io/pivotal/cla/webdriver/admin/EditAdminClaTests.java b/src/test/java/io/pivotal/cla/webdriver/admin/EditAdminClaTests.java index 06d66178..5b907587 100644 --- a/src/test/java/io/pivotal/cla/webdriver/admin/EditAdminClaTests.java +++ b/src/test/java/io/pivotal/cla/webdriver/admin/EditAdminClaTests.java @@ -6,7 +6,7 @@ import java.util.Arrays; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import io.pivotal.cla.data.ContributorLicenseAgreement; @@ -200,7 +200,7 @@ public void editClaSuccessPrimary() { @Test public void editClaSuccessPrimaryExistingButSameId() { - cla.setId(new Long(1L)); + cla.setId(Long.valueOf(1L)); when(mockClaRepository.findByNameAndPrimaryTrue(cla.getName())).thenReturn(cla); when(mockClaRepository.findAll()).thenReturn(Arrays.asList(cla)); when(mockClaRepository.findOne(cla.getId())).thenReturn(cla); diff --git a/src/test/java/io/pivotal/cla/webdriver/pages/BasePage.java b/src/test/java/io/pivotal/cla/webdriver/pages/BasePage.java index 3443f2f4..4dcbcc49 100644 --- a/src/test/java/io/pivotal/cla/webdriver/pages/BasePage.java +++ b/src/test/java/io/pivotal/cla/webdriver/pages/BasePage.java @@ -33,6 +33,8 @@ import io.pivotal.cla.webdriver.pages.admin.AdminLinkClaPage; import io.pivotal.cla.webdriver.pages.admin.AdminListClasPage; +import java.time.Duration; + public abstract class BasePage { public static final String WEBDRIVER_BASE_URL = "webdriver.baseUrl"; @@ -157,7 +159,7 @@ public void assertNotSelected() { } public void waitUntilAt(Runnable assertAt) { - new WebDriverWait(getDriver(), 6).until(input -> at(assertAt)); + new WebDriverWait(getDriver(), Duration.ofSeconds(6)).until(input -> at(assertAt)); } private boolean at(Runnable assertAt) { @@ -187,13 +189,13 @@ public AdminLookupSignaturePage lookup() { protected void userMenu() { userMenu.click(); - WebDriverWait wait = new WebDriverWait(driver, 5); + WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5)); wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(signout.getAttribute("id")))); } protected void adminMenu() { adminMenu.click(); - WebDriverWait wait = new WebDriverWait(driver, 5); + WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5)); wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(link.getAttribute("id")))); } diff --git a/src/test/java/io/pivotal/cla/webdriver/pages/SignCclaPage.java b/src/test/java/io/pivotal/cla/webdriver/pages/SignCclaPage.java index 1a461539..1ebeb3a1 100644 --- a/src/test/java/io/pivotal/cla/webdriver/pages/SignCclaPage.java +++ b/src/test/java/io/pivotal/cla/webdriver/pages/SignCclaPage.java @@ -81,7 +81,7 @@ public static SignCclaPage go(WebDriver driver, String cla) { } public static SignCclaPage go(WebDriver driver, String cla, String repositoryId, long pullRequestId) { - get(driver, url(cla) + "/?repositoryId="+repositoryId+"&pullRequestId="+pullRequestId); + get(driver, url(cla) + "?repositoryId="+repositoryId+"&pullRequestId="+pullRequestId); return PageFactory.initElements(driver, SignCclaPage.class); } diff --git a/src/test/java/io/pivotal/cla/webdriver/pages/github/GitHubAuthorizePage.java b/src/test/java/io/pivotal/cla/webdriver/pages/github/GitHubAuthorizePage.java index 2714f248..c3b0a3e1 100644 --- a/src/test/java/io/pivotal/cla/webdriver/pages/github/GitHubAuthorizePage.java +++ b/src/test/java/io/pivotal/cla/webdriver/pages/github/GitHubAuthorizePage.java @@ -7,6 +7,8 @@ import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; +import java.time.Duration; + public class GitHubAuthorizePage { final WebDriver driver; @@ -24,7 +26,7 @@ public void authorizeIfNecessary() { } private void waitToBeClickable(By selector) { - WebDriverWait wait = new WebDriverWait(driver, 60); + WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(60)); wait.until(ExpectedConditions.elementToBeClickable(selector)); } diff --git a/src/test/java/io/pivotal/cla/webdriver/pages/github/GitHubPullRequestPage.java b/src/test/java/io/pivotal/cla/webdriver/pages/github/GitHubPullRequestPage.java index 103a2778..4cfc70d5 100644 --- a/src/test/java/io/pivotal/cla/webdriver/pages/github/GitHubPullRequestPage.java +++ b/src/test/java/io/pivotal/cla/webdriver/pages/github/GitHubPullRequestPage.java @@ -12,6 +12,8 @@ import io.pivotal.cla.webdriver.pages.SignClaPage; +import java.time.Duration; + /** * Represents a Pull Request Page. For example: * @@ -66,7 +68,7 @@ public SignClaPage details() { } private void waitForText(String text) { - new WebDriverWait(driver, 60).until(input -> getBodyText(input).contains(text)); + new WebDriverWait(driver, Duration.ofSeconds(60)).until(input -> getBodyText(input).contains(text)); } private String getBodyText(WebDriver driver) { diff --git a/src/test/java/okhttp3/mockwebserver/EnqueueRequestsExtension.java b/src/test/java/okhttp3/mockwebserver/EnqueueRequestsExtension.java new file mode 100644 index 00000000..7ae321da --- /dev/null +++ b/src/test/java/okhttp3/mockwebserver/EnqueueRequestsExtension.java @@ -0,0 +1,146 @@ +/* + * Copyright 2002-2016 the original author or authors. + * + * Licensed 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 + * + * http://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 okhttp3.mockwebserver; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.stream.Stream; + +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +/** + * Allows externalizing queued responses using classpath resources. This is + * useful when dealing with larger responses from the server that may be + * difficult to read inline within a test. An example test can be seen below: + * + *

+ * package okhttp3.mockwebserver;
+ *
+ * public class EnqueueResourcesMockWebServerITest {
+ * 	@Rule
+ * 	public EnqueueResourcesMockWebServer server = new EnqueueResourcesMockWebServer();
+ *
+ * 	@Test
+ * 	public void multipleRequests() throws IOException {
+ * 		OkHttpClient client = new OkHttpClient.Builder().build();
+ * 		HttpUrl url = server.getServer().url("/");
+ *
+ * 		Request request = new Request.Builder().get().url(url).build();
+ *
+ * 		Response response = client.newCall(request).execute();
+ *
+ * 		assertEquals(200, response.code());
+ * 		assertEquals("Hi", response.body().string());
+ *
+ * 		response = client.newCall(request).execute();
+ *
+ * 		assertEquals(500, response.code());
+ * 		assertEquals("Fail", response.body().string());
+ * 	}
+ * }
+ * 
+ * + *

+ * For this to work the following classpath resources are present: + *

+ * + * okhttp3.mockwebserver.EnqueueResourcesMockWebServerITest_okhttp3. + * multipleRequests/1 + * + *
+ * HTTP/1.1 200 OK
+ *
+ * Hi
+ * 
+ * + * okhttp3.mockwebserver.EnqueueResourcesMockWebServerITest_okhttp3. + * multipleRequests/2 + * + *
+ * HTTP/1.1 500 Internal Server Error
+ *
+ * Fail
+ * 
+ * + * In addition the following special headers can be used: + * + *
    + *
  • OkHttp-ThrottleBody - Sets the MockResponse's throttleBody. Takes the + * format of <long bytesPerPeriod>;<long period>;<TimeUnit + * unit>
  • + *
  • OkHttp-ChunkedBody - Sets the MockResponse's chunked body value. Takes + * the format of <int maxChunkSize>
  • + *
  • OkHttp-BodyDelay - Sets the MockResponse's bodyDelay. Takes the format of + * <long delay>TimeUnit unit>
  • + *
+ * + * If additional customizations are necessary, the MockResponse can be accessed + * using {@link #peek()}. + * + * @author Rob Winch + */ +public final class EnqueueRequestsExtension implements BeforeEachCallback, AfterEachCallback { + + @Override + public void beforeEach(ExtensionContext extensionContext) throws Exception { + Class testClass = extensionContext.getRequiredTestClass(); + Object testInstance = extensionContext.getRequiredTestInstance(); + + findEnqueueResourcesMockWebServerMembers(testClass, testInstance) + .forEach(server -> { + try { + server.getServer().start(); + } catch (IOException e) { + throw new RuntimeException(e); + } + Method method = extensionContext.getRequiredTestMethod(); + server.enqueue(testClass, method); + }); + + + } + + @Override + public void afterEach(ExtensionContext extensionContext) throws Exception { + Class testClass = extensionContext.getRequiredTestClass(); + Object testInstance = extensionContext.getRequiredTestInstance(); + + findEnqueueResourcesMockWebServerMembers(testClass, testInstance) + .forEach(server -> { + try { + server.getServer().shutdown(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } + + private static Stream findEnqueueResourcesMockWebServerMembers(Class testClass, Object testInstance) { + return Arrays.stream(testClass.getDeclaredFields()) + .filter(f -> f.getType().equals(EnqueueResourcesMockWebServer.class)) + .map(f -> { + try { + f.setAccessible(true); + return (EnqueueResourcesMockWebServer) f.get(testInstance); + } catch (IllegalArgumentException | IllegalAccessException e) { + throw new RuntimeException(e); + } + }); + } +} \ No newline at end of file diff --git a/src/test/java/okhttp3/mockwebserver/EnqueueResourcesMockWebServer.java b/src/test/java/okhttp3/mockwebserver/EnqueueResourcesMockWebServer.java index 77da0867..c8328edb 100644 --- a/src/test/java/okhttp3/mockwebserver/EnqueueResourcesMockWebServer.java +++ b/src/test/java/okhttp3/mockwebserver/EnqueueResourcesMockWebServer.java @@ -17,7 +17,11 @@ import java.io.IOException; import java.io.InputStream; +import java.lang.reflect.Method; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; @@ -93,7 +97,7 @@ * * @author Rob Winch */ -public final class EnqueueResourcesMockWebServer implements TestRule { +public final class EnqueueResourcesMockWebServer { final QueueDispatcher dispatcher; final MockWebServer server; @@ -118,24 +122,12 @@ public String getServerUrl() { return "http://" + server.getHostName()+ ":" + server.getPort(); } - @Override - public Statement apply(Statement base, final Description description) { - final Statement serverStatement = server.apply(base, description); - return new Statement() { - @Override - public void evaluate() throws Throwable { - enqueue(description); - serverStatement.evaluate(); - } - }; - } - - private void enqueue(Description description) { - EnqueueRequests toEnqueue = description.getAnnotation(EnqueueRequests.class); - if(toEnqueue == null) { - enqueueDefault(description); + void enqueue(Class testClass, Method testMethod) { + EnqueueRequests toEnqueue = testMethod.getAnnotation(EnqueueRequests.class); + if(toEnqueue != null) { + enqueue(testClass, toEnqueue); } else { - enqueue(description.getTestClass(), toEnqueue); + enqueueDefault(testClass, testMethod); } } @@ -153,8 +145,8 @@ private void enqueue(Class testClass, EnqueueRequests toEnqueue) { } } - private void enqueueDefault(Description description) { - String resourceBaseName = getResourceBaseName(description); + private void enqueueDefault(Class testClass, Method testMethod) { + String resourceBaseName = getResourceBaseName(testClass, testMethod); for (int i = 1; i < Integer.MAX_VALUE; i++) { String resourceName = resourceBaseName + i; @@ -191,8 +183,8 @@ private InputStream input(String name) { return getClass().getResourceAsStream(name); } - private String getResourceBaseName(Description description) { - return "/"+(description.getTestClass().getName() + "_okhttp3/" + description.getMethodName() + "/") + private String getResourceBaseName(Class testClass, Method testMethod) { + return "/"+(testClass.getName() + "_okhttp3/" + testMethod.getName() + "/") .replaceAll("\\.", "/"); } } \ No newline at end of file diff --git a/src/test/java/okhttp3/mockwebserver/EnqueueResourcesMockWebServerITest.java b/src/test/java/okhttp3/mockwebserver/EnqueueResourcesMockWebServerITest.java index 8311d2f8..68f70f30 100644 --- a/src/test/java/okhttp3/mockwebserver/EnqueueResourcesMockWebServerITest.java +++ b/src/test/java/okhttp3/mockwebserver/EnqueueResourcesMockWebServerITest.java @@ -15,24 +15,24 @@ */ package okhttp3.mockwebserver; -import static org.junit.Assert.assertEquals; - -import java.io.IOException; - -import org.junit.Rule; -import org.junit.Test; - import okhttp3.HttpUrl; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import java.io.IOException; + +import static org.junit.Assert.assertEquals; /** * @author Rob Winch * */ +@ExtendWith(EnqueueRequestsExtension.class) public class EnqueueResourcesMockWebServerITest { - @Rule + public EnqueueResourcesMockWebServer server = new EnqueueResourcesMockWebServer(); @Test diff --git a/src/test/java/okhttp3/mockwebserver/MockResponseParserTest.java b/src/test/java/okhttp3/mockwebserver/MockResponseParserTest.java index bd768e6f..f350d3a7 100644 --- a/src/test/java/okhttp3/mockwebserver/MockResponseParserTest.java +++ b/src/test/java/okhttp3/mockwebserver/MockResponseParserTest.java @@ -15,30 +15,27 @@ */ package okhttp3.mockwebserver; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; /** * @author Rob Winch * */ public class MockResponseParserTest { - @Rule - public ExpectedException thrown= ExpectedException.none(); - MockResponseParser parser; - @Before + @BeforeEach public void setup() { parser = new MockResponseParser(); } @@ -66,24 +63,27 @@ public void headerContentType() throws IOException { assertEquals("application/json", response.getHeaders().get("Content-Type")); } - @Test(expected=IllegalArgumentException.class) + @Test public void nullInputStream() throws IOException { - parser.createResponse(null); + assertThatIllegalArgumentException().isThrownBy(() -> parser.createResponse(null)); } - @Test(expected=EOFException.class) + @Test public void empty() throws IOException { - parser.createResponse(input("empty")); + assertThatExceptionOfType(EOFException.class) + .isThrownBy(() -> parser.createResponse(input("empty"))); } - @Test(expected=EOFException.class) + @Test public void onlyStatus() throws IOException { - parser.createResponse(input("onlyStatus")); + assertThatExceptionOfType(EOFException.class) + .isThrownBy(() -> parser.createResponse(input("onlyStatus"))); } - @Test(expected=EOFException.class) + @Test public void noEmptyLine() throws IOException { - parser.createResponse(input("noEmptyLine")); + assertThatExceptionOfType(EOFException.class) + .isThrownBy(() -> parser.createResponse(input("noEmptyLine"))); } @Test @@ -137,34 +137,38 @@ public void throttleBodyWithWhiteSpace() throws IOException { @Test public void throttleBodyInvalidFormatMissingPart() throws IOException { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("OkHttp-ThrottleBody expected to be in format ;; but got '12345;67890'"); + String expectedMessage = "OkHttp-ThrottleBody expected to be in format ;; but got '12345;67890'"; - parser.createResponse(input("throttleBodyInvalidFormatMissingPart")); + assertThatIllegalArgumentException() + .isThrownBy(() -> parser.createResponse(input("throttleBodyInvalidFormatMissingPart"))) + .withMessage(expectedMessage); } @Test public void throttleBodyInvalidFormatBytesPerPeriodNotLong() throws IOException { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("OkHttp-ThrottleBody expected to be in format ;; but got 'invalid;67890;SECONDS'"); + String expectedMessage = "OkHttp-ThrottleBody expected to be in format ;; but got 'invalid;67890;SECONDS'"; - parser.createResponse(input("throttleBodyInvalidFormatBytesPerPeriodNotLong")); + assertThatIllegalArgumentException() + .isThrownBy(() -> parser.createResponse(input("throttleBodyInvalidFormatBytesPerPeriodNotLong"))) + .withMessage(expectedMessage); } @Test public void throttleBodyInvalidFormatPeriodNotLong() throws IOException { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("OkHttp-ThrottleBody expected to be in format ;; but got '12345;invalid;SECONDS'"); + String expectedMesssage = "OkHttp-ThrottleBody expected to be in format ;; but got '12345;invalid;SECONDS'"; - parser.createResponse(input("throttleBodyInvalidFormatPeriodNotLong")); + assertThatIllegalArgumentException() + .isThrownBy(() -> parser.createResponse(input("throttleBodyInvalidFormatPeriodNotLong"))) + .withMessageContaining(expectedMesssage); } @Test public void throttleBodyInvalidFormatInvalidUnit() throws IOException { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("OkHttp-ThrottleBody expected to be in format ;; but got '12345;67890;invalid'"); + String expectedMessage = "OkHttp-ThrottleBody expected to be in format ;; but got '12345;67890;invalid'"; - parser.createResponse(input("throttleBodyInvalidFormatInvalidUnit")); + assertThatIllegalArgumentException() + .isThrownBy(() -> parser.createResponse(input("throttleBodyInvalidFormatInvalidUnit"))) + .withMessage(expectedMessage); } @Test @@ -179,10 +183,11 @@ public void chunkedBody() throws IOException { @Test public void chunkedBodyInvalidFormatNotInt() throws IOException { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("OkHttp-ChunkedBody expected to be in format but got 'invalid'"); + String expectedMessage = "OkHttp-ChunkedBody expected to be in format but got 'invalid'"; - parser.createResponse(input("chunkedBodyInvalidFormatNotInt")); + assertThatIllegalArgumentException() + .isThrownBy(() -> parser.createResponse(input("chunkedBodyInvalidFormatNotInt"))) + .withMessage(expectedMessage); } @Test @@ -203,18 +208,20 @@ public void bodyDelayWithWhiteSpace() throws IOException { @Test public void bodyDelayInvalidFormatInvalidUnit() throws IOException { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("OkHttp-BodyDelay expected to be in format ; but got '123;invalid'"); + String expectedMessage = "OkHttp-BodyDelay expected to be in format ; but got '123;invalid'"; - parser.createResponse(input("bodyDelayInvalidFormatInvalidUnit")); + assertThatIllegalArgumentException() + .isThrownBy(() -> parser.createResponse(input("bodyDelayInvalidFormatInvalidUnit"))) + .withMessage(expectedMessage); } @Test public void bodyDelayInvalidFormatInvalidDelay() throws IOException { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("OkHttp-BodyDelay expected to be in format ; but got 'invalid;SECONDS'"); + String expectedMessage = "OkHttp-BodyDelay expected to be in format ; but got 'invalid;SECONDS'"; - parser.createResponse(input("bodyDelayInvalidFormatInvalidDelay")); + assertThatIllegalArgumentException() + .isThrownBy(() -> parser.createResponse(input("bodyDelayInvalidFormatInvalidDelay"))) + .withMessage(expectedMessage); } private InputStream input(String name) {