You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rocketmq.apache.org by li...@apache.org on 2026/10/15 10:13:31 UTC

(rocketmq-dashboard) branch rocketmq-studio updated: fix(web): reject exporting a Grafana dashboard the mock inventory does not hold (#6511)

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 faf2b95eb fix(web): reject exporting a Grafana dashboard the mock inventory does not hold (#6511)
faf2b95eb is described below

commit faf2b95eb5f30c3577005c16c4ad21d7fbbfb014
Author: Apulupie <16...@users.noreply.github.com>
AuthorDate: Thu Oct 15 18:13:25 2026 +0800

    fix(web): reject exporting a Grafana dashboard the mock inventory does not hold (#6511)
    
    The mock branch of `exportGrafanaDashboard` answered an unknown uid with a fabricated
    `{ "uid": <uid> }` document, while the endpoint it stands in for answers 404
    (`GrafanaDashboardController.exportDashboard` -> `GrafanaDashboardService.getDashboardJson` throws
    `BusinessException(404, "Grafana dashboard not found: " + uid)`, and the OpenAPI annotation on that
    operation documents the 404), and the sibling `getGrafanaDashboard` in the same file already throws
    the same message. `GrafanaDashboardList.handleExport` therefore downloaded a file that contains only
    the uid and still reported `grafana.exported`.
    
    The lookup is now shared by both functions through `getMockGrafanaDashboard`, which throws for an
    unknown uid - the same shape the alert-rule asset service already uses (`getMockAlertRuleAsset`).
    No user-facing copy changes; the export button now reports the failure through the existing
    `grafana.exportFailed` branch.
---
 web/src/services/grafanaService.test.ts |  8 ++++++++
 web/src/services/grafanaService.ts      | 19 ++++++++++++-------
 2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/web/src/services/grafanaService.test.ts b/web/src/services/grafanaService.test.ts
index ab39689c3..4d24349ef 100644
--- a/web/src/services/grafanaService.test.ts
+++ b/web/src/services/grafanaService.test.ts
@@ -51,6 +51,14 @@ describe('grafanaService', () => {
     await expect(getGrafanaDashboard('nope')).rejects.toThrow();
   });
 
+  it('rejects exporting an unknown dashboard uid in mock mode', async () => {
+    // The export endpoint documents a 404 for an unknown uid; the mock branch used to answer
+    // with a fabricated {"uid": ...} document instead.
+    await expect(exportGrafanaDashboard('nope')).rejects.toThrow(
+      'Grafana dashboard not found: nope',
+    );
+  });
+
   it('exports a dashboard as a blob in mock mode', async () => {
     const blob = await exportGrafanaDashboard('rocketmq-overview');
     expect(blob).toBeInstanceOf(Blob);
diff --git a/web/src/services/grafanaService.ts b/web/src/services/grafanaService.ts
index 7d2080a41..a8889cc79 100644
--- a/web/src/services/grafanaService.ts
+++ b/web/src/services/grafanaService.ts
@@ -18,21 +18,26 @@ export async function listGrafanaDashboards(): Promise<GrafanaDashboardInfo[]> {
   return metricsApi.listGrafanaDashboards();
 }
 
+function getMockGrafanaDashboard(uid: string) {
+  const found = mockGrafanaDashboards.find((dashboard) => dashboard.uid === uid);
+  if (!found) {
+    throw new Error(`Grafana dashboard not found: ${uid}`);
+  }
+  return found;
+}
+
 export async function getGrafanaDashboard(uid: string): Promise<Record<string, unknown>> {
   if (isMockMode()) {
-    const found = mockGrafanaDashboards.find((dashboard) => dashboard.uid === uid);
-    if (!found) {
-      throw new Error(`Grafana dashboard not found: ${uid}`);
-    }
-    return structuredClone(found.model);
+    return structuredClone(getMockGrafanaDashboard(uid).model);
   }
   return metricsApi.getGrafanaDashboard(uid);
 }
 
 export async function exportGrafanaDashboard(uid: string): Promise<Blob> {
   if (isMockMode()) {
-    const found = mockGrafanaDashboards.find((dashboard) => dashboard.uid === uid);
-    const model = found ? found.model : { uid };
+    // The export endpoint answers 404 for an unknown uid; the mock must not fabricate a
+    // document for one, or the console reports a successful export that contains nothing.
+    const model = getMockGrafanaDashboard(uid).model;
     return new Blob([JSON.stringify(model, null, 2)], { type: 'application/json' });
   }
   return metricsApi.exportGrafanaDashboard(uid);