Skip to content

Commit c2cdc05

Browse files
authored
Merge pull request #302 from San-43/fix-287-hide-technical-error-details
Fix #287 hide technical exception messages in API error responses (SQL / Hibernate details)
2 parents 34eff33 + 296edb5 commit c2cdc05

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

src/main/java/org/springframework/samples/petclinic/rest/advice/ExceptionControllerAdvice.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,11 @@ public ResponseEntity<ProblemDetail> handleGeneralException(Exception e, HttpSer
8686
@ResponseBody
8787
public ResponseEntity<ProblemDetail> handleDataIntegrityViolationException(DataIntegrityViolationException ex, HttpServletRequest request) {
8888
HttpStatus status = HttpStatus.NOT_FOUND;
89-
ProblemDetail detail = this.detailBuild(ex, status, request.getRequestURL());
89+
ProblemDetail detail = ProblemDetail.forStatus(status);
90+
detail.setType(URI.create(request.getRequestURL().toString()));
91+
detail.setTitle(ex.getClass().getSimpleName());
92+
detail.setDetail("Request could not be processed");
93+
detail.setProperty("timestamp", Instant.now());
9094
return ResponseEntity.status(status).body(detail);
9195
}
9296

src/main/java/org/springframework/samples/petclinic/rest/controller/OwnerRestController.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,12 @@ public ResponseEntity<OwnerDto> deleteOwner(Integer ownerId) {
134134
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
135135
@Override
136136
public ResponseEntity<PetDto> addPetToOwner(Integer ownerId, PetFieldsDto petFieldsDto) {
137+
Owner owner = this.clinicService.findOwnerById(ownerId);
138+
if (owner == null) {
139+
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
140+
}
137141
HttpHeaders headers = new HttpHeaders();
138142
Pet pet = petMapper.toPet(petFieldsDto);
139-
Owner owner = new Owner();
140143
owner.setId(ownerId);
141144
pet.setOwner(owner);
142145
pet.getType().setName(null);

src/test/java/org/springframework/samples/petclinic/rest/controller/OwnerRestControllerTests.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.samples.petclinic.rest.controller;
1818

19+
import org.springframework.dao.DataIntegrityViolationException;
1920
import tools.jackson.databind.ObjectMapper;
2021
import org.junit.jupiter.api.BeforeEach;
2122
import org.junit.jupiter.api.Test;
@@ -47,7 +48,9 @@
4748
import java.util.ArrayList;
4849
import java.util.List;
4950

51+
import static org.mockito.ArgumentMatchers.any;
5052
import static org.mockito.BDDMockito.given;
53+
import static org.mockito.Mockito.doThrow;
5154
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
5255
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
5356

@@ -341,6 +344,8 @@ void testDeleteOwnerError() throws Exception {
341344
@Test
342345
@WithMockUser(roles = "OWNER_ADMIN")
343346
void testCreatePetSuccess() throws Exception {
347+
final Owner owner = ownerMapper.toOwner(owners.get(0));
348+
given(this.clinicService.findOwnerById(1)).willReturn(owner);
344349
PetDto newPet = pets.get(0);
345350
newPet.setId(999);
346351
ObjectMapper mapper = JsonMapper.builder()
@@ -368,6 +373,40 @@ void testCreatePetError() throws Exception {
368373
.andExpect(status().isBadRequest()).andDo(MockMvcResultHandlers.print());
369374
}
370375

376+
@Test
377+
@WithMockUser(roles = "OWNER_ADMIN")
378+
void testCreatePetShouldNotExposeTechnicalDetails() throws Exception {
379+
PetDto newPet = pets.get(0);
380+
newPet.setId(null);
381+
ObjectMapper mapper = JsonMapper.builder()
382+
.defaultDateFormat(new SimpleDateFormat("dd/MM/yyyy"))
383+
.build();
384+
String newPetAsJSON = mapper.writeValueAsString(newPet);
385+
String technicalMessage = "could not execute statement; SQL [insert into pets ...]; constraint [fk_pet_owner]";
386+
given(this.clinicService.findOwnerById(1)).willReturn(ownerMapper.toOwner(owners.get(0)));
387+
doThrow(new DataIntegrityViolationException(technicalMessage)).when(this.clinicService).savePet(any());
388+
this.mockMvc.perform(post("/api/owners/1/pets")
389+
.content(newPetAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
390+
.andDo(MockMvcResultHandlers.print())
391+
.andExpect(status().isNotFound())
392+
.andExpect(jsonPath("$.detail").value("Request could not be processed"));
393+
}
394+
395+
@Test
396+
@WithMockUser(roles = "OWNER_ADMIN")
397+
void testCreatePetWithUnknownOwnerShouldReturnNotFound() throws Exception {
398+
PetDto newPet = pets.get(0);
399+
newPet.setId(null);
400+
ObjectMapper mapper = JsonMapper.builder()
401+
.defaultDateFormat(new SimpleDateFormat("dd/MM/yyyy"))
402+
.build();
403+
String newPetAsJSON = mapper.writeValueAsString(newPet);
404+
given(this.clinicService.findOwnerById(1000000)).willReturn(null);
405+
this.mockMvc.perform(post("/api/owners/1000000/pets")
406+
.content(newPetAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
407+
.andExpect(status().isNotFound());
408+
}
409+
371410
@Test
372411
@WithMockUser(roles = "OWNER_ADMIN")
373412
void testCreateVisitSuccess() throws Exception {

0 commit comments

Comments
 (0)