fix(recipe): add server-side image size limit and use .matches() for type check
- @Size(max=7_000_000) on heroImageUrl enforces ~5 MB cap at bean validation - ALLOWED_IMAGE_PATTERN uses .matches() for unambiguous full-string check - Tests: oversized image → 400, empty ingredients list → 400 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -161,6 +161,33 @@ class RecipeControllerTest {
|
||||
verify(recipeService).deleteRecipe(HOUSEHOLD_ID, RECIPE_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createRecipeWithOversizedHeroImageShouldReturn400() throws Exception {
|
||||
String heroImageUrl = "data:image/jpeg;base64," + "A".repeat(7_000_000);
|
||||
String body = "{\"name\":\"Test\",\"effort\":\"easy\",\"tagIds\":[\"" + UUID.randomUUID() + "\"]," +
|
||||
"\"ingredients\":[{\"quantity\":1,\"unit\":\"g\",\"newIngredientName\":\"x\",\"sortOrder\":0}]," +
|
||||
"\"heroImageUrl\":\"" + heroImageUrl + "\"}";
|
||||
|
||||
mockMvc.perform(post("/v1/recipes")
|
||||
.principal(() -> "sarah@example.com")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(body))
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createRecipeWithEmptyIngredientsListShouldReturn400() throws Exception {
|
||||
var body = """
|
||||
{"name":"Test","effort":"easy","tagIds":["%s"],"ingredients":[]}
|
||||
""".formatted(UUID.randomUUID());
|
||||
|
||||
mockMvc.perform(post("/v1/recipes")
|
||||
.principal(() -> "sarah@example.com")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(body))
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createRecipeWithCapitalisedEffortShouldReturn400() throws Exception {
|
||||
var body = """
|
||||
|
||||
Reference in New Issue
Block a user