Production must not ship test users, demo orders, or test1234. Dev and CI still need seeded users for e2e. Prod creates one admin from deploy secrets. - Move V2/V4/V6 seed migrations to db/dev-migration - Add application-prod.yml with schema-only Flyway and ignore-missing for moved seeds - Add AdminBootstrap to create admin from ADMIN_EMAIL and ADMIN_PASSWORD - Wire docker,prod profile, deploy secrets, and localhost:5433 for SSH DB access - Add hashPassword Gradle task for optional manual bcrypt generation
72 lines
2.6 KiB
Java
72 lines
2.6 KiB
Java
package se.bilhalsning.config;
|
|
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
import static org.mockito.Mockito.never;
|
|
import static org.mockito.Mockito.verify;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.junit.jupiter.api.extension.ExtendWith;
|
|
import org.mockito.ArgumentCaptor;
|
|
import org.mockito.InjectMocks;
|
|
import org.mockito.Mock;
|
|
import org.mockito.junit.jupiter.MockitoExtension;
|
|
import org.springframework.boot.DefaultApplicationArguments;
|
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
import org.springframework.test.util.ReflectionTestUtils;
|
|
import se.bilhalsning.entity.User;
|
|
import se.bilhalsning.repository.UserRepository;
|
|
|
|
@ExtendWith(MockitoExtension.class)
|
|
class AdminBootstrapTest {
|
|
|
|
@Mock
|
|
private UserRepository userRepository;
|
|
|
|
@Mock
|
|
private PasswordEncoder passwordEncoder;
|
|
|
|
@InjectMocks
|
|
private AdminBootstrap adminBootstrap;
|
|
|
|
@BeforeEach
|
|
void setUp() {
|
|
ReflectionTestUtils.setField(adminBootstrap, "adminEmail", "admin@bilhej.se");
|
|
ReflectionTestUtils.setField(adminBootstrap, "adminPassword", "secure-production-password");
|
|
}
|
|
|
|
@Test
|
|
void shouldSkipBootstrapWhenAdminAlreadyExists() {
|
|
when(userRepository.existsByRole("admin")).thenReturn(true);
|
|
|
|
adminBootstrap.run(new DefaultApplicationArguments(new String[] {}));
|
|
|
|
verify(userRepository, never()).save(any(User.class));
|
|
}
|
|
|
|
@Test
|
|
void shouldCreateAdminWhenMissing() {
|
|
when(userRepository.existsByRole("admin")).thenReturn(false);
|
|
when(passwordEncoder.encode("secure-production-password")).thenReturn("encoded-hash");
|
|
|
|
adminBootstrap.run(new DefaultApplicationArguments(new String[] {}));
|
|
|
|
ArgumentCaptor<User> captor = ArgumentCaptor.forClass(User.class);
|
|
verify(userRepository).save(captor.capture());
|
|
User saved = captor.getValue();
|
|
org.junit.jupiter.api.Assertions.assertEquals("admin@bilhej.se", saved.getEmail());
|
|
org.junit.jupiter.api.Assertions.assertEquals("encoded-hash", saved.getPasswordHash());
|
|
org.junit.jupiter.api.Assertions.assertEquals("admin", saved.getRole());
|
|
}
|
|
|
|
@Test
|
|
void shouldFailWhenCredentialsMissingAndNoAdmin() {
|
|
ReflectionTestUtils.setField(adminBootstrap, "adminPassword", "");
|
|
when(userRepository.existsByRole("admin")).thenReturn(false);
|
|
|
|
org.junit.jupiter.api.Assertions.assertThrows(
|
|
IllegalStateException.class,
|
|
() -> adminBootstrap.run(new DefaultApplicationArguments(new String[] {})));
|
|
}
|
|
}
|