This is an automated email from the ASF dual-hosted git repository.
lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git
The following commit(s) were added to refs/heads/rocketmq-studio by this push:
new 51a3424a fix: validate audit log date filters (#567)
51a3424a is described below
commit 51a3424aefab961488199b4eff6942a875c2b080
Author: yx9o <[email protected]>
AuthorDate: Tue Jul 28 20:27:28 2026 +0800
fix: validate audit log date filters (#567)
* fix: align frontend API success response handling (#429)
* ci: add build workflow and PR review skill (#430)
* fix: connect K8s certificate page to APIs (#440)
* feat: extend translation keys & add useLanguage compatible alias in
LangContext (#433)
* fix: validate audit query and cleanup parameters (#442)
* chore: fix Dockerfile missing style/ copy and standardize pr-review skill
(#444)
- Add COPY style ./style to server/Dockerfile so Maven checkstyle can
find style/rmq_checkstyle.xml during docker compose build
- Rewrite pr-review SKILL.md with an 8-stage pipeline checklist,
Dockerfile pre-flight fix step, and [Studio] title format spec
* feat: add centralized ThemeContext and useTheme hook for dark mode
management (#435)
* fix: preserve SSE framing for AI chat (#438)
* feat: add Prometheus range query adapter (#432)
Add a real Prometheus /api/v1/query_range adapter as the foundation for
observability (#431): configurable base URL, timeouts, Basic/Bearer auth, error
mapping, and tests.
* feat: implement login page, auth & AI modules, simplify theme management
(#473)
Add login page with full auth workflow, Auth/AI API modules, Zustand state,
and simplified theme management.
* feat: add Ops page (NameServer management, VIPChannel, TLS) (#474)
Add Ops management page for NameServer address management, VIP channel
toggle, and TLS switch.
* feat: add Producer page (#475)
Add a page to query producer client connections by Topic and Producer Group.
* feat: add AlertManagement page for alert rule operations (#476)
Add alert rule management page: parse/render Prometheus AlertManager YAML
rules with search, toggle, and CRUD.
* feat: add SslSettings page for SSL/TLS configuration management (#477)
Add SSL/TLS configuration page: SSL toggle, TLS version,
KeyStore/TrustStore, client auth mode.
* feat: add broker cluster overview page (#479)
Add Broker Cluster overview page with tab-based NameServer/Broker/Proxy
management and cluster stats.
* feat: add consumer group management page (#480)
Add consumer group management page.
* feat: add lite topic management page (#481)
Add lite topic management page.
* feat: add Proxy management page (#482)
Add Proxy management page (address list, status, TPS, memory, CPU, uptime).
* feat: add LLM Settings configuration page (#483)
Add LLM settings configuration page (provider, apiKey, model, temperature,
etc.).
* feat: connect frontend pages to backend APIs and align contracts (#445)
Consolidated API-integration work
(#445,#446,#447,#448,#449,#450,#451,#452,#453,#454,#458,#459,#460,#461,#463).
* feat: add service capabilities and interaction enhancements (#462)
Consolidated service/interaction work
(#462,#468,#469,#464,#470,#471,#472,#488).
* feat: add preferences persistence, accessibility and env config (#465)
Consolidated preferences/a11y/config work (#465,#466,#485,#486,#487,#484).
* fix: include remaining consolidated frontend changes (#490)
topicService topic API contract, authStore persisted session, vite env
config.
* fix: align login response contract (#492)
Align frontend LoginResponse type with backend LoginVO contract: change
flat username/role to nested user.username/admin structure.
* fix: use runtime DNS resolver for Nginx API proxy (#494)
Fix Nginx API proxy failure caused by hardcoded DNS resolver by switching
to container runtime dynamic resolution.
* feat: enhance i18n support with labelKey-based translations (#495)
Migrate hardcoded Chinese UI text to i18n labelKey pattern, add ~280
translation entries (zh+en), fix duplicate key compilation errors.
* test: fix frontend baseline assertions (#498)
Fix test assertions to align with backend PageResult contract and current
i18n labels.
* fix: initialize deploy helpers before validation (#499)
Move logging/error helper initialization before config validation in
deploy.sh to fix err() undefined when REMOTE_HOST is missing.
* ci: build frontend Docker image (#500)
Add frontend Docker image build to CI workflow to validate Dockerfile/nginx
deployment path.
* fix: load producer topics from Studio API response (#501)
Fix Producer page topic list to read from Studio API new format
(data[].name) with backward compatibility for legacy topicList format.
* fix: generate data source keys on creation (#509)
Fix ConcurrentHashMap NPE when creating data sources with null key by
auto-generating UUID in service layer.
* feat: add producer connection endpoint (#510)
Add producer connection query endpoint with topic/producerGroup filtering,
returning backward-compatible connectionSet format.
* fix: avoid returning General Settings API key (#512)
Fix security issue where General Settings endpoint returned API key in
plaintext. Replace with apiKeyConfigured boolean flag and support explicit key
clearing.
* feat: add catalog-driven read-only tools (#514)
Introduce versioned YAML tool catalog with JSON Schema validation, SHA-256
digest, deep immutability, and two read-only L1 tool handlers (rmq.cluster.list
/ rmq.capabilities).
* feat: add LiteTopic backend endpoints (#502)
Add backend stub endpoints for LiteTopic page: list, session details, TTL
extension, quota, and capability check.
* feat: add ops backend endpoints (#504)
Add ops page backend endpoints: NameServer address management, VIP Channel,
and TLS switches.
* feat: add proxy address endpoints (#505)
Add proxy address list and add-address endpoints supporting Studio frontend
form submission.
* feat: add LLM settings endpoints (#506)
Add LLM settings backend endpoints: config read/write, connectivity test,
and model listing.
* feat: add alert rules YAML endpoint (#507)
Add alert rules Prometheus YAML export endpoint with default RocketMQ alert
template fallback.
* fix: ACL page API integration (#516)
Wire ACL management page to backend API, add update endpoints for ACL rules
and users with proper validation.
* fix: sort queried messages by store time (#519)
Sort message query results by storeTime in descending order so latest
messages appear first.
* feat: add consumer stack diagnostics API (#521)
Add consumer thread stack diagnostics endpoint (GET
/api/groups/{name}/instances/{clientId}/stack) with Provider/Stub/Service
layering.
* fix: validate audit log date filters
---------
Co-authored-by: btlqql <[email protected]>
Co-authored-by: lizhimins <[email protected]>
Co-authored-by: zhaohai <[email protected]>
Co-authored-by: terrancesli <[email protected]>
Co-authored-by: wizcraft_kris
<[email protected]>
Co-authored-by: Loyal-Young <[email protected]>
Co-authored-by: majialong <[email protected]>
Co-authored-by: aias00 <[email protected]>
Co-authored-by: PiliLily <[email protected]>
---
docs/api-spec.md | 2 ++
.../rocketmq/studio/ops/audit/AuditService.java | 15 +++++++-----
.../studio/ops/audit/AuditServiceTest.java | 28 +++++++++++++++++-----
3 files changed, 33 insertions(+), 12 deletions(-)
diff --git a/docs/api-spec.md b/docs/api-spec.md
index e75158f9..2fa9602f 100644
--- a/docs/api-spec.md
+++ b/docs/api-spec.md
@@ -1424,6 +1424,8 @@ GET
/api/audit-logs?page={page}&pageSize={pageSize}&search={search}&operationTyp
| `endDate` | `string` | 否 | 结束日期 (YYYY-MM-DD) |
| `result` | `string` | 否 | 结果过滤: `success` / `failure` |
+`startDate` 或 `endDate` 格式错误,以及 `startDate` 晚于 `endDate` 时,接口返回 HTTP 400。
+
**Response `data`:**
| 字段 | 类型 | 说明 |
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/ops/audit/AuditService.java
b/server/src/main/java/org/apache/rocketmq/studio/ops/audit/AuditService.java
index 8972bbe7..27588437 100644
---
a/server/src/main/java/org/apache/rocketmq/studio/ops/audit/AuditService.java
+++
b/server/src/main/java/org/apache/rocketmq/studio/ops/audit/AuditService.java
@@ -26,6 +26,7 @@ import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
import java.util.List;
@Slf4j
@@ -43,8 +44,11 @@ public class AuditService {
log.info("Querying audit logs, page={}, pageSize={}, search={},
operationType={}, result={}",
page, pageSize, search, operationType, result);
- LocalDateTime start = parseDate(startDate, true);
- LocalDateTime end = parseDate(endDate, false);
+ LocalDateTime start = parseDate(startDate, true, "startDate");
+ LocalDateTime end = parseDate(endDate, false, "endDate");
+ if (start != null && end != null && start.isAfter(end)) {
+ throw new BusinessException(400, "startDate must not be after
endDate");
+ }
List<AuditRecordVO> allRecords = auditRepository.findAll(search,
operationType, start, end, result);
long total = allRecords.size();
@@ -76,16 +80,15 @@ public class AuditService {
}
}
- private LocalDateTime parseDate(String dateStr, boolean startOfDay) {
+ private LocalDateTime parseDate(String dateStr, boolean startOfDay, String
parameterName) {
if (dateStr == null || dateStr.isEmpty()) {
return null;
}
try {
LocalDate date = LocalDate.parse(dateStr,
DateTimeFormatter.ISO_LOCAL_DATE);
return startOfDay ? date.atStartOfDay() :
date.atTime(LocalTime.MAX);
- } catch (Exception e) {
- log.warn("Failed to parse date: {}", dateStr, e);
- return null;
+ } catch (DateTimeParseException e) {
+ throw new BusinessException(400, parameterName + " must use
YYYY-MM-DD");
}
}
}
diff --git
a/server/src/test/java/org/apache/rocketmq/studio/ops/audit/AuditServiceTest.java
b/server/src/test/java/org/apache/rocketmq/studio/ops/audit/AuditServiceTest.java
index e50eca77..fefb3651 100644
---
a/server/src/test/java/org/apache/rocketmq/studio/ops/audit/AuditServiceTest.java
+++
b/server/src/test/java/org/apache/rocketmq/studio/ops/audit/AuditServiceTest.java
@@ -188,14 +188,30 @@ class AuditServiceTest {
}
@Test
- void queryLogsShouldHandleInvalidDateFormat() {
- when(auditRepository.findAll(isNull(), isNull(), isNull(), isNull(),
isNull()))
- .thenReturn(Collections.emptyList());
+ void queryLogsShouldRejectInvalidStartDate() {
+ assertThatThrownBy(() -> auditService.queryLogs(
+ 1, 10, null, null, "invalid-date", null, null))
+ .isInstanceOf(BusinessException.class)
+ .hasMessage("startDate must use YYYY-MM-DD")
+ .satisfies(ex -> assertThat(((BusinessException)
ex).getCode()).isEqualTo(400));
+ }
- PageResult<AuditRecordVO> result = auditService.queryLogs(1, 10, null,
null, "invalid-date", null, null);
+ @Test
+ void queryLogsShouldRejectInvalidEndDate() {
+ assertThatThrownBy(() -> auditService.queryLogs(
+ 1, 10, null, null, null, "2025-02-30", null))
+ .isInstanceOf(BusinessException.class)
+ .hasMessage("endDate must use YYYY-MM-DD")
+ .satisfies(ex -> assertThat(((BusinessException)
ex).getCode()).isEqualTo(400));
+ }
- assertThat(result).isNotNull();
- assertThat(result.getItems()).isEmpty();
+ @Test
+ void queryLogsShouldRejectReversedDateRange() {
+ assertThatThrownBy(() -> auditService.queryLogs(
+ 1, 10, null, null, "2025-02-01", "2025-01-31", null))
+ .isInstanceOf(BusinessException.class)
+ .hasMessage("startDate must not be after endDate")
+ .satisfies(ex -> assertThat(((BusinessException)
ex).getCode()).isEqualTo(400));
}
@Test