diff --git a/servlet/java-configuration/data/build.gradle b/servlet/java-configuration/data/build.gradle new file mode 100644 index 0000000..830b409 --- /dev/null +++ b/servlet/java-configuration/data/build.gradle @@ -0,0 +1,38 @@ +plugins { + id "java" + id "nebula.integtest" version "7.0.9" + id "org.gretty" version "3.0.3" +} + +repositories { + mavenCentral() + maven { url "https://repo.spring.io/libs-snapshot" } +} + +dependencies { + implementation platform("org.springframework:spring-framework-bom:5.2.8.RELEASE") + implementation platform("org.springframework.data:spring-data-releasetrain:Neumann-SR3") + implementation platform("org.springframework.security:spring-security-bom:5.4.0-SNAPSHOT") + implementation platform("org.junit:junit-bom:5.6.2") + + implementation "org.springframework.security:spring-security-config" + implementation "org.springframework.security:spring-security-data" + implementation "org.springframework.security:spring-security-web" + implementation 'jakarta.validation:jakarta.validation-api:2.0.2' + implementation 'javax.persistence:javax.persistence-api:2.2' + implementation 'org.hibernate:hibernate-entitymanager:5.4.20.Final' + implementation 'org.hibernate.validator:hibernate-validator:6.1.5.Final' + implementation 'org.hsqldb:hsqldb:2.5.1' + implementation 'org.springframework.data:spring-data-jpa' + + testImplementation "org.assertj:assertj-core:3.15.0" + testImplementation "org.springframework:spring-test" + testImplementation "org.springframework.security:spring-security-test" + testImplementation("org.junit.jupiter:junit-jupiter-api") + + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") +} + +tasks.withType(Test).configureEach { + useJUnitPlatform() +} diff --git a/servlet/java-configuration/data/gradle.properties b/servlet/java-configuration/data/gradle.properties new file mode 100644 index 0000000..fe89f6a --- /dev/null +++ b/servlet/java-configuration/data/gradle.properties @@ -0,0 +1 @@ +tomcat85Version=8.5.54 diff --git a/servlet/java-configuration/data/gradle/wrapper/gradle-wrapper.jar b/servlet/java-configuration/data/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..62d4c05 Binary files /dev/null and b/servlet/java-configuration/data/gradle/wrapper/gradle-wrapper.jar differ diff --git a/servlet/java-configuration/data/gradle/wrapper/gradle-wrapper.properties b/servlet/java-configuration/data/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..bb8b2fc --- /dev/null +++ b/servlet/java-configuration/data/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/servlet/java-configuration/data/gradlew b/servlet/java-configuration/data/gradlew new file mode 100755 index 0000000..fbd7c51 --- /dev/null +++ b/servlet/java-configuration/data/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 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 +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# 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 +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$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" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# 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 + ;; +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" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + 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 +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 +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 + +# 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 + # 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\"" + fi + i=`expr $i + 1` + 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, 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" + +exec "$JAVACMD" "$@" diff --git a/servlet/java-configuration/data/gradlew.bat b/servlet/java-configuration/data/gradlew.bat new file mode 100644 index 0000000..a9f778a --- /dev/null +++ b/servlet/java-configuration/data/gradlew.bat @@ -0,0 +1,104 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +: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% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/servlet/java-configuration/data/settings.gradle b/servlet/java-configuration/data/settings.gradle new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/servlet/java-configuration/data/settings.gradle @@ -0,0 +1 @@ + diff --git a/servlet/java-configuration/data/src/main/java/example/DataConfiguration.java b/servlet/java-configuration/data/src/main/java/example/DataConfiguration.java new file mode 100644 index 0000000..2050e0d --- /dev/null +++ b/servlet/java-configuration/data/src/main/java/example/DataConfiguration.java @@ -0,0 +1,86 @@ +/* + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package example; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; +import org.springframework.core.io.ClassPathResource; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.Database; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.security.data.repository.query.SecurityEvaluationContextExtension; +import org.springframework.transaction.PlatformTransactionManager; + +import javax.sql.DataSource; + +/** + * @author Rob Winch + */ +@Configuration +@ComponentScan +@EnableJpaRepositories +public class DataConfiguration { + + @Bean + public SecurityEvaluationContextExtension expressionEvaluationContextProvider() { + return new SecurityEvaluationContextExtension(); + } + + @Bean + public DataSource dataSource() { + EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); + return builder.setType(EmbeddedDatabaseType.HSQL).build(); + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + vendorAdapter.setDatabase(Database.HSQL); + vendorAdapter.setGenerateDdl(true); + + LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); + factory.setJpaVendorAdapter(vendorAdapter); + factory.setPackagesToScan(Message.class.getPackage().getName()); + factory.setDataSource(dataSource()); + + return factory; + } + + @Bean + @DependsOn("entityManagerFactory") + public ResourceDatabasePopulator initDatabase(DataSource dataSource) throws Exception { + ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); + populator.addScript(new ClassPathResource("data.sql")); + populator.populate(dataSource.getConnection()); + return populator; + } + + @Bean + public PlatformTransactionManager transactionManager() { + JpaTransactionManager txManager = new JpaTransactionManager(); + txManager.setEntityManagerFactory(entityManagerFactory().getObject()); + return txManager; + } + +} diff --git a/servlet/java-configuration/data/src/main/java/example/Message.java b/servlet/java-configuration/data/src/main/java/example/Message.java new file mode 100644 index 0000000..69346e7 --- /dev/null +++ b/servlet/java-configuration/data/src/main/java/example/Message.java @@ -0,0 +1,83 @@ +/* + * Copyright 2020 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package example; + +import java.util.Calendar; + +import javax.persistence.*; + +import org.hibernate.validator.constraints.NotEmpty; + +@Entity +public class Message { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @NotEmpty(message = "Message is required.") + private String text; + + @NotEmpty(message = "Summary is required.") + private String summary; + + private Calendar created = Calendar.getInstance(); + + @OneToOne + private User to; + + public User getTo() { + return to; + } + + public void setTo(User to) { + this.to = to; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Calendar getCreated() { + return created; + } + + public void setCreated(Calendar created) { + this.created = created; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public String getSummary() { + return summary; + } + + public void setSummary(String summary) { + this.summary = summary; + } + +} diff --git a/servlet/java-configuration/data/src/main/java/example/MessageRepository.java b/servlet/java-configuration/data/src/main/java/example/MessageRepository.java new file mode 100644 index 0000000..8ca1b2a --- /dev/null +++ b/servlet/java-configuration/data/src/main/java/example/MessageRepository.java @@ -0,0 +1,28 @@ +/* + * Copyright 2020 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package example; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +/** + * @author Rob Winch + */ +@Repository +public interface MessageRepository extends JpaRepository { + +} diff --git a/servlet/java-configuration/data/src/main/java/example/SecurityMessageRepository.java b/servlet/java-configuration/data/src/main/java/example/SecurityMessageRepository.java new file mode 100644 index 0000000..4bbbf79 --- /dev/null +++ b/servlet/java-configuration/data/src/main/java/example/SecurityMessageRepository.java @@ -0,0 +1,33 @@ +/* + * Copyright 2020 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package example; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * @author Rob Winch + */ +@Repository +public interface SecurityMessageRepository extends MessageRepository { + + @Query("select m from Message m where m.to.id = ?#{ principal?.id }") + List findAll(); + +} \ No newline at end of file diff --git a/servlet/java-configuration/data/src/main/java/example/User.java b/servlet/java-configuration/data/src/main/java/example/User.java new file mode 100644 index 0000000..fb840d1 --- /dev/null +++ b/servlet/java-configuration/data/src/main/java/example/User.java @@ -0,0 +1,82 @@ +/* + * Copyright 2020 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package example; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +/** + * @author Rob Winch + */ +@Entity +public class User { + + @GeneratedValue(strategy = GenerationType.AUTO) + @Id + private Long id; + + private String firstName; + + private String lastName; + + private String email; + + private String password; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + +} \ No newline at end of file diff --git a/servlet/java-configuration/data/src/test/java/example/SecurityMessageRepositoryTests.java b/servlet/java-configuration/data/src/test/java/example/SecurityMessageRepositoryTests.java new file mode 100644 index 0000000..3f96b82 --- /dev/null +++ b/servlet/java-configuration/data/src/test/java/example/SecurityMessageRepositoryTests.java @@ -0,0 +1,55 @@ +/* + * Copyright 2020 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package example; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.util.ReflectionUtils; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Rob Winch + */ +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = DataConfiguration.class) +public class SecurityMessageRepositoryTests { + + @Autowired + SecurityMessageRepository repository; + + @Test + @WithMockCustomUser + void findAllOnlyToCurrentUser() { + Method method = ReflectionUtils.findMethod(SecurityMessageRepositoryTests.class, "findAllOnlyToCurrentUser"); + WithMockCustomUser withMockCustomUser = AnnotationUtils.findAnnotation(method, WithMockCustomUser.class); + List messages = repository.findAll(); + assertThat(messages).hasSize(3); + for (Message m : messages) { + assertThat(m.getTo().getId()).isEqualTo(withMockCustomUser.id()); + } + } + +} diff --git a/servlet/java-configuration/data/src/test/java/example/WithMockCustomUser.java b/servlet/java-configuration/data/src/test/java/example/WithMockCustomUser.java new file mode 100644 index 0000000..b6634d2 --- /dev/null +++ b/servlet/java-configuration/data/src/test/java/example/WithMockCustomUser.java @@ -0,0 +1,32 @@ +/* + * Copyright 2020 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package example; + +import org.springframework.security.test.context.support.WithSecurityContext; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +@WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class) +public @interface WithMockCustomUser { + + String email() default "user@example.com"; + + long id() default 0L; + +} diff --git a/servlet/java-configuration/data/src/test/java/example/WithMockCustomUserSecurityContextFactory.java b/servlet/java-configuration/data/src/test/java/example/WithMockCustomUserSecurityContextFactory.java new file mode 100644 index 0000000..1d80f48 --- /dev/null +++ b/servlet/java-configuration/data/src/test/java/example/WithMockCustomUserSecurityContextFactory.java @@ -0,0 +1,41 @@ +/* + * Copyright 2020 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package example; + +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.test.context.support.WithSecurityContextFactory; + +public class WithMockCustomUserSecurityContextFactory implements WithSecurityContextFactory { + + @Override + public SecurityContext createSecurityContext(WithMockCustomUser customUser) { + SecurityContext context = SecurityContextHolder.createEmptyContext(); + + User principal = new User(); + principal.setId(customUser.id()); + principal.setEmail(customUser.email()); + Authentication auth = new UsernamePasswordAuthenticationToken(principal, "password", + AuthorityUtils.createAuthorityList("ROLE_USER")); + context.setAuthentication(auth); + return context; + } + +} diff --git a/servlet/java-configuration/data/src/test/resources/data.sql b/servlet/java-configuration/data/src/test/resources/data.sql new file mode 100644 index 0000000..97c60b1 --- /dev/null +++ b/servlet/java-configuration/data/src/test/resources/data.sql @@ -0,0 +1,10 @@ +insert into user(id,email,password,firstName,lastName) values (0,'rob@example.com','password','Rob','Winch'); +insert into user(id,email,password,firstName,lastName) values (1,'luke@example.com','password','Luke','Taylor'); + +insert into message(id,created,to_id,summary,text) values (100,'2014-07-10 10:00:00',0,'Hello Rob','This message is for Rob'); +insert into message(id,created,to_id,summary,text) values (101,'2014-07-10 14:00:00',0,'How are you Rob?','This message is for Rob'); +insert into message(id,created,to_id,summary,text) values (102,'2014-07-11 22:00:00',0,'Is this secure?','This message is for Rob'); + +insert into message(id,created,to_id,summary,text) values (110,'2014-07-12 10:00:00',1,'Hello Luke','This message is for Luke'); +insert into message(id,created,to_id,summary,text) values (111,'2014-07-12 10:00:00',1,'Greetings Luke','This message is for Luke'); +insert into message(id,created,to_id,summary,text) values (112,'2014-07-12 10:00:00',1,'Is this secure?','This message is for Luke'); \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 555c531..adae1db 100644 --- a/settings.gradle +++ b/settings.gradle @@ -28,6 +28,7 @@ include ":reactive:webflux:java:oauth2:webclient" include ":reactive:webflux:kotlin:hello-security" include ":servlet:java-configuration:hello-security" include ":servlet:java-configuration:hello-security-explicit" +include ":servlet:java-configuration:data" include ":servlet:java-configuration:max-sessions" include ":servlet:spring-boot:java:hello" include ":servlet:spring-boot:java:hello-security"