|
|
|
|
@@ -0,0 +1,68 @@
|
|
|
|
|
package org.raddatz.familienarchiv.user;
|
|
|
|
|
|
|
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
|
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
|
|
|
|
|
import org.springframework.boot.context.properties.bind.Binder;
|
|
|
|
|
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
|
|
|
|
import org.springframework.core.env.PropertiesPropertySource;
|
|
|
|
|
import org.springframework.core.io.ClassPathResource;
|
|
|
|
|
|
|
|
|
|
import java.util.Properties;
|
|
|
|
|
|
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Pins the admin-seed property key contract. {@code UserDataInitializer} reads
|
|
|
|
|
* {@code @Value("${app.admin.email:...}")} and {@code @Value("${app.admin.password:...}")}.
|
|
|
|
|
* The yaml MUST expose those exact keys, not e.g. {@code app.admin.username}, or
|
|
|
|
|
* the env vars {@code APP_ADMIN_USERNAME} / {@code APP_ADMIN_PASSWORD} are
|
|
|
|
|
* silently ignored and the admin user gets seeded with the hardcoded defaults.
|
|
|
|
|
*
|
|
|
|
|
* <p>Discovered as a HIGH bug during the production-deploy bootstrap (#513): on
|
|
|
|
|
* first deploy the prod admin password is permanently locked to whatever ends
|
|
|
|
|
* up in the database, so a key-name mismatch would lock prod to the dev defaults
|
|
|
|
|
* {@code admin@familyarchive.local} / {@code admin123}.
|
|
|
|
|
*
|
|
|
|
|
* <p>No Spring context — Binder reads application.yaml directly.
|
|
|
|
|
*/
|
|
|
|
|
class AdminSeedPropertyKeyTest {
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void admin_email_key_binds_from_yaml() {
|
|
|
|
|
Binder binder = binderFromApplicationYaml();
|
|
|
|
|
|
|
|
|
|
String email = binder.bind("app.admin.email", String.class)
|
|
|
|
|
.orElseThrow(() -> new AssertionError(
|
|
|
|
|
"app.admin.email is missing from application.yaml. "
|
|
|
|
|
+ "UserDataInitializer reads this exact key; if the yaml uses "
|
|
|
|
|
+ "a different name (e.g. 'username'), the env var "
|
|
|
|
|
+ "APP_ADMIN_USERNAME is silently ignored."));
|
|
|
|
|
|
|
|
|
|
assertThat(email)
|
|
|
|
|
.as("app.admin.email must resolve from APP_ADMIN_USERNAME or its default")
|
|
|
|
|
.isNotBlank();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void admin_password_key_binds_from_yaml() {
|
|
|
|
|
Binder binder = binderFromApplicationYaml();
|
|
|
|
|
|
|
|
|
|
String password = binder.bind("app.admin.password", String.class)
|
|
|
|
|
.orElseThrow(() -> new AssertionError(
|
|
|
|
|
"app.admin.password is missing from application.yaml. "
|
|
|
|
|
+ "UserDataInitializer reads this exact key."));
|
|
|
|
|
|
|
|
|
|
assertThat(password)
|
|
|
|
|
.as("app.admin.password must resolve from APP_ADMIN_PASSWORD or its default")
|
|
|
|
|
.isNotBlank();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Binder binderFromApplicationYaml() {
|
|
|
|
|
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
|
|
|
|
|
yaml.setResources(new ClassPathResource("application.yaml"));
|
|
|
|
|
Properties props = yaml.getObject();
|
|
|
|
|
assertThat(props).as("application.yaml must be on the classpath").isNotNull();
|
|
|
|
|
return new Binder(ConfigurationPropertySources.from(
|
|
|
|
|
new PropertiesPropertySource("application", props)));
|
|
|
|
|
}
|
|
|
|
|
}
|