Skip to content
Snippets Groups Projects
Commit adb065ec authored by Jan Zickermann's avatar Jan Zickermann
Browse files

OZG-4799 Handle other Exceptions

parent 16c5e5e8
No related merge requests found
......@@ -21,12 +21,19 @@
*/
package de.ozgcloud.admin.web.error;
import java.net.URI;
import org.springframework.http.HttpStatus;
public class ErrorConstants {
import lombok.AllArgsConstructor;
import lombok.Getter;
private ErrorConstants() {}
@AllArgsConstructor
@Getter
public enum ErrorType {
UNKNOWN(HttpStatus.INTERNAL_SERVER_ERROR),
AUTHORIZATION(HttpStatus.UNAUTHORIZED),
FUNCTIONAL(HttpStatus.BAD_REQUEST),
TECHNICAL(HttpStatus.INTERNAL_SERVER_ERROR),
;
private static final String PROBLEM_BASE_URL = "https://administration.ozg-sh.de/problem";
public static final URI NOT_AUTHORIZED_PROBLEM = URI.create(PROBLEM_BASE_URL + "/not-authorized");
private final HttpStatus status;
}
......@@ -21,39 +21,26 @@
*/
package de.ozgcloud.admin.web.error;
import static de.ozgcloud.admin.web.error.ErrorConstants.*;
import java.nio.file.AccessDeniedException;
import java.util.Map;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ProblemDetail;
import org.springframework.http.ResponseEntity;
import org.springframework.web.ErrorResponse;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import lombok.extern.slf4j.Slf4j;
import de.ozgcloud.common.errorhandling.TechnicalException;
@RestControllerAdvice
@Slf4j
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
public class ExceptionTranslator extends ResponseEntityExceptionHandler {
@ExceptionHandler({ AccessDeniedException.class })
public ResponseEntity<ProblemDetail> handleAccessDeniedException(AccessDeniedException ex) {
log.error(ex.getMessage(), ex);
return handleErrorResponse(ErrorResponse
.builder(ex, HttpStatus.FORBIDDEN, ex.getLocalizedMessage())
.type(NOT_AUTHORIZED_PROBLEM)
.build());
}
@ExceptionHandler({ RuntimeException.class, AccessDeniedException.class, TechnicalException.class })
public ErrorResponse handleAccessDeniedException(Exception ex) {
var errorType = Map.of(
AccessDeniedException.class, ErrorType.AUTHORIZATION,
TechnicalException.class, ErrorType.TECHNICAL
).getOrDefault(ex.getClass(), ErrorType.UNKNOWN);
private ResponseEntity<ProblemDetail> handleErrorResponse(ErrorResponse errorResponse) {
var body = errorResponse.updateAndGetBody(this.getMessageSource(), LocaleContextHolder.getLocale());
var headers = new HttpHeaders();
return new ResponseEntity<>(body, headers, errorResponse.getStatusCode());
return ErrorResponse.builder(ex, errorType.getStatus(), ex.getLocalizedMessage()).build();
}
}
......@@ -21,7 +21,6 @@
*/
package de.ozgcloud.admin.web.error;
import static org.hamcrest.Matchers.*;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
......@@ -41,9 +40,10 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import de.ozgcloud.admin.service.BasicAppInfoService;
import de.ozgcloud.admin.web.controller.BasicAppInfoController;
import de.ozgcloud.common.errorhandling.TechnicalException;
@SpringBootTest
class RestResponseEntityExceptionHandlerTest {
class ExceptionTranslatorITCase {
@Spy
@InjectMocks
......@@ -58,7 +58,7 @@ class RestResponseEntityExceptionHandlerTest {
void mock() {
mockMvc = MockMvcBuilders
.standaloneSetup(basicAppInfoController)
.setControllerAdvice(new RestResponseEntityExceptionHandler())
.setControllerAdvice(new ExceptionTranslator())
.build();
}
......@@ -66,16 +66,35 @@ class RestResponseEntityExceptionHandlerTest {
@Nested
class TestErrorHandler {
@Test
void shouldHandleAccessDenied() throws Exception {
private void throwWhenApiCalled(Exception ex) {
when(basicAppInfoService.getJavaVersion())
.thenAnswer(invocation -> {
throw new AccessDeniedException("test no access");
throw ex;
});
}
@Test
void shouldHandleAccessDenied() throws Exception {
throwWhenApiCalled(new AccessDeniedException("test no access"));
mockMvc.perform(get("/api"))
.andExpect(status().is(ErrorType.AUTHORIZATION.getStatus().value()));
}
@Test
void shouldHandleTechnicalError() throws Exception {
throwWhenApiCalled(new TechnicalException("test technical error"));
mockMvc.perform(get("/api"))
.andExpect(status().is(ErrorType.TECHNICAL.getStatus().value()));
}
@Test
void shouldRuntimeError() throws Exception {
throwWhenApiCalled(new RuntimeException("test unknown error"));
mockMvc.perform(get("/api"))
.andExpect(status().is4xxClientError())
.andExpect(jsonPath("$.type", equalTo(ErrorConstants.NOT_AUTHORIZED_PROBLEM.toString())));
.andExpect(status().is(ErrorType.UNKNOWN.getStatus().value()));
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment