From 258fb7581b37e1f6c876d4061aec722cf34000d8 Mon Sep 17 00:00:00 2001 From: Devon Hillard Date: Sun, 22 Feb 2026 10:04:34 -0700 Subject: [PATCH 1/2] refactor(config): migrate @ConfigurationProperties from @Component to @EnableConfigurationProperties Remove @Component and @PropertySource from DevLoginConfigProperties and WebAuthnConfigProperties so they are passive data holders per Spring Boot convention. Registration is now handled by dedicated @Configuration classes with @EnableConfigurationProperties: - DevLoginAutoConfiguration: guards with @Profile("local") and @ConditionalOnProperty, owns @PropertySource - WebAuthnAutoConfiguration: always active (WebSecurityConfig requires the properties), owns @PropertySource Closes #263 --- .../user/dev/DevLoginAutoConfiguration.java | 24 +++++++++++++++++++ .../user/dev/DevLoginConfigProperties.java | 4 ---- .../security/WebAuthnAutoConfiguration.java | 20 ++++++++++++++++ .../security/WebAuthnConfigProperties.java | 4 ---- 4 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/digitalsanctuary/spring/user/dev/DevLoginAutoConfiguration.java create mode 100644 src/main/java/com/digitalsanctuary/spring/user/security/WebAuthnAutoConfiguration.java diff --git a/src/main/java/com/digitalsanctuary/spring/user/dev/DevLoginAutoConfiguration.java b/src/main/java/com/digitalsanctuary/spring/user/dev/DevLoginAutoConfiguration.java new file mode 100644 index 0000000..c3cbde7 --- /dev/null +++ b/src/main/java/com/digitalsanctuary/spring/user/dev/DevLoginAutoConfiguration.java @@ -0,0 +1,24 @@ +package com.digitalsanctuary.spring.user.dev; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.context.annotation.PropertySource; + +/** + * Auto-configuration for the dev login feature. + *

+ * Activates only when the {@code local} profile is active and + * {@code user.dev.auto-login-enabled=true}. Individual dev-login components + * ({@link DevLoginController}, {@link DevLoginStartupWarning}) carry their own + * guards for defense-in-depth. + *

+ */ +@Configuration +@Profile("local") +@ConditionalOnProperty(name = "user.dev.auto-login-enabled", havingValue = "true", matchIfMissing = false) +@PropertySource("classpath:config/dsspringuserconfig.properties") +@EnableConfigurationProperties(DevLoginConfigProperties.class) +public class DevLoginAutoConfiguration { +} diff --git a/src/main/java/com/digitalsanctuary/spring/user/dev/DevLoginConfigProperties.java b/src/main/java/com/digitalsanctuary/spring/user/dev/DevLoginConfigProperties.java index 1b1bf5b..d58b624 100644 --- a/src/main/java/com/digitalsanctuary/spring/user/dev/DevLoginConfigProperties.java +++ b/src/main/java/com/digitalsanctuary/spring/user/dev/DevLoginConfigProperties.java @@ -1,8 +1,6 @@ package com.digitalsanctuary.spring.user.dev; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.PropertySource; -import org.springframework.stereotype.Component; import lombok.Data; /** @@ -17,8 +15,6 @@ *

*/ @Data -@Component -@PropertySource("classpath:config/dsspringuserconfig.properties") @ConfigurationProperties(prefix = "user.dev") public class DevLoginConfigProperties { diff --git a/src/main/java/com/digitalsanctuary/spring/user/security/WebAuthnAutoConfiguration.java b/src/main/java/com/digitalsanctuary/spring/user/security/WebAuthnAutoConfiguration.java new file mode 100644 index 0000000..87fa2cd --- /dev/null +++ b/src/main/java/com/digitalsanctuary/spring/user/security/WebAuthnAutoConfiguration.java @@ -0,0 +1,20 @@ +package com.digitalsanctuary.spring.user.security; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +/** + * Auto-configuration that registers {@link WebAuthnConfigProperties}. + *

+ * This configuration is always active because {@code WebSecurityConfig} requires + * {@link WebAuthnConfigProperties} regardless of whether WebAuthn is enabled. + * Individual WebAuthn components carry their own + * {@code @ConditionalOnProperty(name = "user.webauthn.enabled")} guards. + *

+ */ +@Configuration +@PropertySource("classpath:config/dsspringuserconfig.properties") +@EnableConfigurationProperties(WebAuthnConfigProperties.class) +public class WebAuthnAutoConfiguration { +} diff --git a/src/main/java/com/digitalsanctuary/spring/user/security/WebAuthnConfigProperties.java b/src/main/java/com/digitalsanctuary/spring/user/security/WebAuthnConfigProperties.java index 72c277b..e30a978 100644 --- a/src/main/java/com/digitalsanctuary/spring/user/security/WebAuthnConfigProperties.java +++ b/src/main/java/com/digitalsanctuary/spring/user/security/WebAuthnConfigProperties.java @@ -2,16 +2,12 @@ import java.util.Set; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.PropertySource; -import org.springframework.stereotype.Component; import lombok.Data; /** * Configuration properties for WebAuthn (Passkey) authentication. */ @Data -@Component -@PropertySource("classpath:config/dsspringuserconfig.properties") @ConfigurationProperties(prefix = "user.webauthn") public class WebAuthnConfigProperties { From 23047ca3e5c6faa9fc3f04751a299db61619bba9 Mon Sep 17 00:00:00 2001 From: Devon Hillard Date: Sun, 22 Feb 2026 12:28:13 -0700 Subject: [PATCH 2/2] fix(review): address PR #264 review feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename DevLoginAutoConfiguration → DevLoginConfiguration and WebAuthnAutoConfiguration → WebAuthnConfiguration to avoid implying Spring Boot SPI semantics (these are component-scanned, not SPI-registered via AutoConfiguration.imports) - Remove @PropertySource from DevLoginConfiguration: the annotation cannot influence its own @ConditionalOnProperty evaluation (condition is checked before @PropertySource is processed), and defaults are already available via WebAuthnConfiguration which unconditionally loads dsspringuserconfig.properties --- ...oConfiguration.java => DevLoginConfiguration.java} | 11 +++++++---- ...oConfiguration.java => WebAuthnConfiguration.java} | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) rename src/main/java/com/digitalsanctuary/spring/user/dev/{DevLoginAutoConfiguration.java => DevLoginConfiguration.java} (69%) rename src/main/java/com/digitalsanctuary/spring/user/security/{WebAuthnAutoConfiguration.java => WebAuthnConfiguration.java} (86%) diff --git a/src/main/java/com/digitalsanctuary/spring/user/dev/DevLoginAutoConfiguration.java b/src/main/java/com/digitalsanctuary/spring/user/dev/DevLoginConfiguration.java similarity index 69% rename from src/main/java/com/digitalsanctuary/spring/user/dev/DevLoginAutoConfiguration.java rename to src/main/java/com/digitalsanctuary/spring/user/dev/DevLoginConfiguration.java index c3cbde7..5d7e8b8 100644 --- a/src/main/java/com/digitalsanctuary/spring/user/dev/DevLoginAutoConfiguration.java +++ b/src/main/java/com/digitalsanctuary/spring/user/dev/DevLoginConfiguration.java @@ -4,21 +4,24 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; -import org.springframework.context.annotation.PropertySource; /** - * Auto-configuration for the dev login feature. + * Configuration that registers {@link DevLoginConfigProperties}. *

* Activates only when the {@code local} profile is active and * {@code user.dev.auto-login-enabled=true}. Individual dev-login components * ({@link DevLoginController}, {@link DevLoginStartupWarning}) carry their own * guards for defense-in-depth. *

+ *

+ * Note: this class is registered via component scan (not Spring Boot SPI), so + * default property values are provided by {@code WebAuthnConfiguration}, which + * unconditionally loads {@code classpath:config/dsspringuserconfig.properties}. + *

*/ @Configuration @Profile("local") @ConditionalOnProperty(name = "user.dev.auto-login-enabled", havingValue = "true", matchIfMissing = false) -@PropertySource("classpath:config/dsspringuserconfig.properties") @EnableConfigurationProperties(DevLoginConfigProperties.class) -public class DevLoginAutoConfiguration { +public class DevLoginConfiguration { } diff --git a/src/main/java/com/digitalsanctuary/spring/user/security/WebAuthnAutoConfiguration.java b/src/main/java/com/digitalsanctuary/spring/user/security/WebAuthnConfiguration.java similarity index 86% rename from src/main/java/com/digitalsanctuary/spring/user/security/WebAuthnAutoConfiguration.java rename to src/main/java/com/digitalsanctuary/spring/user/security/WebAuthnConfiguration.java index 87fa2cd..c9513f7 100644 --- a/src/main/java/com/digitalsanctuary/spring/user/security/WebAuthnAutoConfiguration.java +++ b/src/main/java/com/digitalsanctuary/spring/user/security/WebAuthnConfiguration.java @@ -5,7 +5,7 @@ import org.springframework.context.annotation.PropertySource; /** - * Auto-configuration that registers {@link WebAuthnConfigProperties}. + * Configuration that registers {@link WebAuthnConfigProperties}. *

* This configuration is always active because {@code WebSecurityConfig} requires * {@link WebAuthnConfigProperties} regardless of whether WebAuthn is enabled. @@ -16,5 +16,5 @@ @Configuration @PropertySource("classpath:config/dsspringuserconfig.properties") @EnableConfigurationProperties(WebAuthnConfigProperties.class) -public class WebAuthnAutoConfiguration { +public class WebAuthnConfiguration { }