diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/ApplicationConfig.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/ApplicationConfig.java new file mode 100644 index 0000000000..e422f71940 --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/ApplicationConfig.java @@ -0,0 +1,68 @@ +/* + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.config.annotation.method.configuration.issue14637; + +import javax.sql.DataSource; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +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.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.config.annotation.method.configuration.issue14637.domain.Entry; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +/** + * @author Josh Cummings + */ +@Configuration +@EnableJpaRepositories("org.springframework.security.config.annotation.method.configuration.issue14637.repo") +@EnableTransactionManagement +public class ApplicationConfig { + + @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); + vendorAdapter.setShowSql(true); + LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); + factory.setJpaVendorAdapter(vendorAdapter); + factory.setPackagesToScan(Entry.class.getPackage().getName()); + factory.setDataSource(dataSource()); + return factory; + } + + @Bean + public PlatformTransactionManager transactionManager() { + JpaTransactionManager txManager = new JpaTransactionManager(); + txManager.setEntityManagerFactory(entityManagerFactory().getObject()); + return txManager; + } + +} diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/Issue14637Tests.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/Issue14637Tests.java new file mode 100644 index 0000000000..1993e8d484 --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/Issue14637Tests.java @@ -0,0 +1,50 @@ +/* + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.config.annotation.method.configuration.issue14637; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.config.annotation.method.configuration.issue14637.domain.Entry; +import org.springframework.security.config.annotation.method.configuration.issue14637.repo.EntryRepository; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +/** + * @author Josh Cummings + */ +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { ApplicationConfig.class, SecurityConfig.class }) +public class Issue14637Tests { + + @Autowired + private EntryRepository entries; + + @Test + @WithMockUser + public void authenticateWhenInvalidPasswordThenBadCredentialsException() { + Entry entry = new Entry(); + entry.setId(123L); + assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(() -> this.entries.save(entry)); + } + +} diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/SecurityConfig.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/SecurityConfig.java new file mode 100644 index 0000000000..5795e9c44d --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/SecurityConfig.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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.config.annotation.method.configuration.issue14637; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; + +/** + * @author Josh Cummings + */ +@Configuration +@EnableMethodSecurity +public class SecurityConfig { + +} diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/domain/Entry.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/domain/Entry.java new file mode 100644 index 0000000000..5bd054ce01 --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/domain/Entry.java @@ -0,0 +1,42 @@ +/* + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.config.annotation.method.configuration.issue14637.domain; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +/** + * @author Josh Cummings + */ +@Entity +public class Entry { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + +} diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/repo/EntryRepository.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/repo/EntryRepository.java new file mode 100644 index 0000000000..e23bb2669b --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/issue14637/repo/EntryRepository.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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.config.annotation.method.configuration.issue14637.repo; + +import org.springframework.data.repository.CrudRepository; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.config.annotation.method.configuration.issue14637.domain.Entry; + +/** + * @author Josh Cummings + */ +public interface EntryRepository extends CrudRepository { + + @PreAuthorize("#entry.id == null") + Entry save(Entry entry); + +}