diff --git a/mauro-api/src/main/groovy/org/maurodata/controller/ErrorSanitisingFilter.groovy b/mauro-api/src/main/groovy/org/maurodata/controller/ErrorSanitisingFilter.groovy new file mode 100644 index 000000000..0d34277f9 --- /dev/null +++ b/mauro-api/src/main/groovy/org/maurodata/controller/ErrorSanitisingFilter.groovy @@ -0,0 +1,57 @@ +package org.maurodata.controller + +import groovy.transform.CompileStatic +import io.micronaut.core.async.publisher.Publishers +import io.micronaut.core.order.Ordered +import io.micronaut.http.HttpRequest +import io.micronaut.http.HttpStatus +import io.micronaut.http.MutableHttpResponse +import io.micronaut.http.annotation.Filter +import io.micronaut.http.filter.HttpServerFilter +import io.micronaut.http.filter.ServerFilterChain +import io.micronaut.http.hateoas.JsonError +import io.micronaut.http.hateoas.Resource +import org.reactivestreams.Publisher + +@CompileStatic +@Filter("/**") +class ErrorSanitisingFilter implements HttpServerFilter { + + @Override + int getOrder() { + return Ordered.LOWEST_PRECEDENCE + } + + @Override + Publisher> doFilter(HttpRequest request, + ServerFilterChain chain) { + + return Publishers.map(chain.proceed(request)) {response -> + + if (response.status == HttpStatus.INTERNAL_SERVER_ERROR) { + response.body.ifPresent {body -> + + if (body instanceof JsonError) { + sanitiseJsonError(body as JsonError, "Internal Server Error") + } + } + } + + return response + } as Publisher> + } + + private static void sanitiseJsonError(JsonError error, String message) { + if (error.getMessage() && HttpStatusExceptionHandler.toTrap(error.getMessage())) { + error.setMessage(message) + } + + error.getEmbedded().values().forEach {List resources -> + resources.each {resource -> + if (resource instanceof JsonError) { + sanitiseJsonError(resource as JsonError, 'No details') + } + } + } + } +} \ No newline at end of file diff --git a/mauro-api/src/main/groovy/org/maurodata/controller/HttpStatusExceptionHandler.groovy b/mauro-api/src/main/groovy/org/maurodata/controller/HttpStatusExceptionHandler.groovy index c6ba658d7..fbcbd81de 100644 --- a/mauro-api/src/main/groovy/org/maurodata/controller/HttpStatusExceptionHandler.groovy +++ b/mauro-api/src/main/groovy/org/maurodata/controller/HttpStatusExceptionHandler.groovy @@ -9,12 +9,20 @@ import io.micronaut.http.HttpResponse import jakarta.inject.Singleton import io.micronaut.http.HttpStatus import io.micronaut.http.exceptions.HttpStatusException +import java.util.regex.Pattern @CompileStatic @Replaces(HttpStatusHandler.class) @Singleton class HttpStatusExceptionHandler implements ExceptionHandler>> { + static String[] trap = ['select', 'insert', 'update', 'delete', 'sql', 'query', 'jdbc', 'table'] + static Pattern trapPattern = ~/(?i)\b(${trap.join('|')})\b/ + + static boolean toTrap(final String message) { + message && (message =~ trapPattern) + } + @Override HttpResponse> handle(HttpRequest request, HttpStatusException exception) { HttpStatus status = exception.getStatus() @@ -31,6 +39,11 @@ class HttpStatusExceptionHandler implements ExceptionHandler errorMessage = Collections.singletonMap("message", message) Map embedded = new HashMap<>()