diff --git a/api/src/main/java/io/kafbat/ui/config/ReadOnlyModeFilter.java b/api/src/main/java/io/kafbat/ui/config/ReadOnlyModeFilter.java index 184eb8725..81165e988 100644 --- a/api/src/main/java/io/kafbat/ui/config/ReadOnlyModeFilter.java +++ b/api/src/main/java/io/kafbat/ui/config/ReadOnlyModeFilter.java @@ -5,6 +5,7 @@ import io.kafbat.ui.service.ClustersStorage; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; +import java.util.Set; import java.util.regex.Pattern; import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; @@ -23,6 +24,10 @@ public class ReadOnlyModeFilter implements WebFilter { private static final Pattern CLUSTER_NAME_REGEX = Pattern.compile("/api/clusters/(?[^/]++)"); + private static final Set SAFE_ENDPOINTS = Set.of( + Pattern.compile("/api/clusters/[^/]+/topics/[^/]+/(smartfilters)$") + ); + private final ClustersStorage clustersStorage; @NotNull @@ -35,10 +40,12 @@ public Mono filter(ServerWebExchange exchange, @NotNull WebFilterChain cha var path = exchange.getRequest().getPath().pathWithinApplication().value(); var decodedPath = URLDecoder.decode(path, StandardCharsets.UTF_8); + var matcher = CLUSTER_NAME_REGEX.matcher(decodedPath); if (!matcher.find()) { return chain.filter(exchange); } + var clusterName = matcher.group("clusterName"); var kafkaCluster = clustersStorage.getClusterByName(clusterName) .orElseThrow( @@ -49,6 +56,15 @@ public Mono filter(ServerWebExchange exchange, @NotNull WebFilterChain cha return chain.filter(exchange); } + var isSafeEndpoint = SAFE_ENDPOINTS + .stream() + .parallel() + .anyMatch(endpoint -> endpoint.matcher(decodedPath).matches()); + + if (isSafeEndpoint) { + return chain.filter(exchange); + } + return Mono.error(ReadOnlyModeException::new); } }