unbridled-41 opened a new pull request, #3980:
URL: https://github.com/apache/rocketmq-dashboard/pull/3980

   Fixes #3568.
   
   ## Problem / Evidence
   
   The cloud credential inventory has no export action. The backend 
`CloudCredentialController` only exposes list/create/update/delete/reveal, so 
operators auditing which vendors and credentials are configured have to copy 
rows manually. `#3568` requests a backend export endpoint with the existing 
vendor/search filters that exports only non-sensitive metadata and never secret 
keys.
   
   ## What was added
   
   - `GET /api/cloud-credentials/export` (same `vendor`/`search` params as the 
list API) returning the CSV inside the standard result envelope, mirroring the 
existing `AuditController` export precedent: rows collected via 
`repository.findPage(vendor, search, 1, 10_000)`, a 400 error when the result 
set exceeds the 10,000-record bound ("narrow the filters"), CSV rendered with 
the shared `CsvUtil` quoting/formula-injection guard plus the same UTF-8 BOM 
header treatment as the audit export.
   - Every row passes through the same `maskAccessKey` path used by the list 
API, so the CSV contains only name, vendor, masked access key, remark, and 
creation/modification timestamps. `secretKey` is never included 
(regression-tested).
   - Settings credentials page: an export button next to the create button that 
downloads the backend CSV as `rocketmq-cloud-credentials-YYYY-MM-DD.csv` with 
the currently selected filters applied, with a localized failure message.
   
   Differences from other inventories: this follows the backend-rendered 
audit-export pattern rather than client-side CSV building, because masking must 
happen server-side to guarantee secrets never reach the export.
   
   ## Priority & scoring
   
   FEATURE_PRIORITY = 90 (project need 37: explicit maintainer-evaluated issue 
#3568; external maturity 26: seven in-repo export endpoints + the audit 
backend-export precedent already establish the pattern in this project; fit 18: 
audit/rotation use case with masking requirement honored; testability 9: 
controller/service/UI all covered). IMPLEMENTATION_CONFIDENCE = 88: minimal 
diff reusing established `CsvUtil`/`maskAccessKey`/blob-download 
infrastructure, no new dependencies, no API breaking changes.
   
   ## Tests
   
   - New regressions first failed (frontend: two tab tests could not find an 
export control and the API test failed on the missing client function; backend: 
`cannot find symbol exportMaskedCsv`), then passed:
     - `npx vitest run src/api/cloudCredential.test.ts 
src/pages/settings/__tests__/CloudCredentialTab.test.tsx` → 15 passed (15): API 
filters passthrough, blob download with `text/csv` type and dated filename, 
failure message without download, plus all pre-existing coverage.
     - `mvn test 
-Dtest='CloudCredentialServiceTest,CloudCredentialControllerTest'` → 20 passed: 
masked CSV contents (name, vendor, `LTAI****0001`, remark; no secret value or 
raw key anywhere), oversize bound → 400, envelope payload, vendor/search param 
passthrough.
   - Full backend suite `mvn test`: 2039 tests, 4 failures — the two 
pre-existing `AuthCorsIntegrationTest` failures and 
`AliyunInstanceProviderTest.getGroupProgressShouldMapLagRowsTest` (all 
identical to the pristine baseline), plus 
`OpenAiCompatibleLlmGatewayTest.successfulAndFailedStreamsEmitOneTerminalSequence`,
 a known load-flaky case that passes 9/9 when re-run in isolation. Zero new 
failures.
   - Full web suite `npx vitest run --testTimeout=60000`: 925 tests, 1 failure 
— `ConsumerPage.test.tsx`, the known load-flaky file untouched by this PR; it 
passes 29/29 in isolation. Zero new failures.
   - `npm run build`, `tsc -b`, and `eslint` on touched files: clean.
   
   ## Risk
   
   Low. Additive only: one read-only endpoint, one button, one i18n key, no 
changes to existing endpoints or components. The 10k bound keeps response size 
bounded; masking is regression-tested so secret material cannot leak through 
the export even if the list API contract evolves.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to