feat(backend): make invite share URL base configurable via app.base-url

Replaces hardcoded \"https://yourapp.com\" with a Spring property.

- application.yml: app.base-url defaults to http://localhost:5173
- application-docker.yml: reads APP_BASE_URL env var, same default
- HouseholdService: injects @Value("${app.base-url}") and uses it in
  toInviteResponse() to build shareUrl
- HouseholdServiceTest: sets field via ReflectionTestUtils in @BeforeEach;
  adds test asserting shareUrl starts with configured base URL

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-10 20:07:53 +02:00
parent 05476ecaab
commit eb5699577b
4 changed files with 33 additions and 1 deletions

View File

@@ -17,6 +17,7 @@ import com.recipeapp.recipe.TagRepository;
import com.recipeapp.recipe.entity.Ingredient;
import com.recipeapp.recipe.entity.IngredientCategory;
import com.recipeapp.recipe.entity.Tag;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -38,6 +39,9 @@ public class HouseholdService {
private final TagRepository tagRepository;
private final VarietyScoreConfigRepository varietyScoreConfigRepository;
@Value("${app.base-url}")
private String baseUrl;
private static final SecureRandom RANDOM = new SecureRandom();
private static final String CODE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
@@ -262,7 +266,7 @@ public class HouseholdService {
private InviteResponse toInviteResponse(HouseholdInvite invite) {
return new InviteResponse(
invite.getInviteCode(),
"https://yourapp.com/join/" + invite.getInviteCode(),
baseUrl + "/join/" + invite.getInviteCode(),
invite.getExpiresAt());
}
}

View File

@@ -2,3 +2,6 @@ spring:
flyway:
locations: classpath:db/migration,classpath:db/seed
out-of-order: true
app:
base-url: ${APP_BASE_URL:http://localhost:5173}

View File

@@ -30,3 +30,6 @@ spring:
server:
port: 8080
app:
base-url: http://localhost:5173

View File

@@ -17,7 +17,9 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.junit.jupiter.api.BeforeEach;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;
import java.time.Instant;
import java.util.List;
@@ -43,6 +45,11 @@ class HouseholdServiceTest {
@InjectMocks
private HouseholdService householdService;
@BeforeEach
void setUp() {
ReflectionTestUtils.setField(householdService, "baseUrl", "http://localhost:5173");
}
private UserAccount testUser() {
return new UserAccount("sarah@example.com", "Sarah", "hashed");
}
@@ -132,6 +139,21 @@ class HouseholdServiceTest {
verify(householdInviteRepository).save(any(HouseholdInvite.class));
}
@Test
void createInviteShouldBuildShareUrlWithConfiguredBaseUrl() {
var user = testUser();
var household = new Household("Smith family", user);
var member = new HouseholdMember(household, user, "planner");
when(householdMemberRepository.findByUserEmailIgnoreCase("sarah@example.com")).thenReturn(Optional.of(member));
when(householdInviteRepository.save(any(HouseholdInvite.class))).thenAnswer(i -> i.getArgument(0));
InviteResponse result = householdService.createInvite("sarah@example.com");
assertThat(result.shareUrl()).startsWith("http://localhost:5173/join/");
assertThat(result.shareUrl()).endsWith(result.inviteCode());
}
@Test
void acceptInviteShouldAddUserAsMember() {
var user = new UserAccount("tom@example.com", "Tom", "hashed");