diff --git a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/DatabaseAdminController.java b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/DatabaseAdminController.java index 3bd0affd..ed5a9753 100644 --- a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/DatabaseAdminController.java +++ b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/DatabaseAdminController.java @@ -72,13 +72,14 @@ public class DatabaseAdminController { @Operation(summary = "Get table sizes and row counts") public ResponseEntity> getTables() { var tables = jdbc.query(""" - SELECT schemaname || '.' || relname AS table_name, + SELECT relname AS table_name, n_live_tup AS row_count, pg_size_pretty(pg_total_relation_size(relid)) AS data_size, pg_total_relation_size(relid) AS data_size_bytes, pg_size_pretty(pg_indexes_size(relid)) AS index_size, pg_indexes_size(relid) AS index_size_bytes FROM pg_stat_user_tables + WHERE schemaname = current_schema() ORDER BY pg_total_relation_size(relid) DESC """, (rs, row) -> new TableSizeResponse( rs.getString("table_name"), rs.getLong("row_count"), @@ -94,7 +95,7 @@ public class DatabaseAdminController { SELECT pid, EXTRACT(EPOCH FROM (now() - query_start)) AS duration_seconds, state, query FROM pg_stat_activity - WHERE state != 'idle' AND pid != pg_backend_pid() + WHERE state != 'idle' AND pid != pg_backend_pid() AND datname = current_database() ORDER BY query_start ASC """, (rs, row) -> new ActiveQueryResponse( rs.getInt("pid"), rs.getDouble("duration_seconds"), diff --git a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/OpenSearchAdminController.java b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/OpenSearchAdminController.java index f4f13ff4..a7ff7fc2 100644 --- a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/OpenSearchAdminController.java +++ b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/OpenSearchAdminController.java @@ -48,17 +48,20 @@ public class OpenSearchAdminController { private final AuditService auditService; private final ObjectMapper objectMapper; private final String opensearchUrl; + private final String indexPrefix; public OpenSearchAdminController(OpenSearchClient client, RestClient restClient, SearchIndexerStats indexerStats, AuditService auditService, ObjectMapper objectMapper, - @Value("${opensearch.url:http://localhost:9200}") String opensearchUrl) { + @Value("${opensearch.url:http://localhost:9200}") String opensearchUrl, + @Value("${opensearch.index-prefix:executions-}") String indexPrefix) { this.client = client; this.restClient = restClient; this.indexerStats = indexerStats; this.auditService = auditService; this.objectMapper = objectMapper; this.opensearchUrl = opensearchUrl; + this.indexPrefix = indexPrefix; } @GetMapping("/status") @@ -109,6 +112,9 @@ public class OpenSearchAdminController { List allIndices = new ArrayList<>(); for (JsonNode idx : indices) { String name = idx.path("index").asText(""); + if (!name.startsWith(indexPrefix)) { + continue; + } if (!search.isEmpty() && !name.contains(search)) { continue; } @@ -146,6 +152,9 @@ public class OpenSearchAdminController { @Operation(summary = "Delete an OpenSearch index") public ResponseEntity deleteIndex(@PathVariable String name, HttpServletRequest request) { try { + if (!name.startsWith(indexPrefix)) { + throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Cannot delete index outside application scope"); + } boolean exists = client.indices().exists(r -> r.index(name)).value(); if (!exists) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Index not found: " + name);