btlqql opened a new pull request, #5351:
URL: https://github.com/apache/rocketmq-dashboard/pull/5351

   ### Which Issue(s) This PR Fixes
   
   - Fixes #5169
   
   ### Brief Description
   
   The ACL users tab had no export surface: `AclController` offered only `GET 
/api/acl/users`, `GET /api/acl/users/page` and `GET 
/api/acl/users/{id}/credentials` 
(`server/src/main/java/org/apache/rocketmq/studio/instance/acl/AclController.java:89-110`),
 so an access review of "which accounts exist, which are admin, which clusters 
can each reach, which have IP whitelists" could only be transcribed from a 
20-row paginated table.
   
   This PR adds `GET /api/acl/users/export`, which streams the account 
inventory as CSV (`text/csv;charset=UTF-8`, `Content-Disposition: attachment; 
filename="acl-users.csv"`, BOM-prefixed header) with columns: user id, 
username, masked access key, admin flag, cluster bindings (`;`-joined), 
read/write permission, IP whitelist pattern and created time. 
`AclUserCsvExporter` renders the document and the endpoint returns 
`ResponseEntity<byte[]>`.
   
   Two properties worth calling out:
   
   - **No secret can leak.** The rows come from the page query the users table 
reads, which already masks both credentials in `AclService` for both the Apache 
and the Tencent path, so the export repeats only what the list already shows. 
`secretKey` has no column at all, and the regression test asserts the raw 
secret values never appear in the CSV.
   - **The export matches the filtered view.** Instead of re-deriving the 
keyword filter, the endpoint walks the *same* page query 
(`AclService.pageUsers`, 100 rows per request — the service's own page-size 
cap) so the file is exactly the filtered inventory the reviewer saw on screen, 
including the repository-side `LIKE` pagination on the Apache path and the 
provider list on the Tencent path. The whole inventory is materialized, so the 
row count is bounded: above 10,000 records the endpoint returns `400` naming 
the limit, following `CloudCredentialService.exportMaskedCsv`.
   
   Scope note: the issue also asks for an **Export users** button on the users 
tab. This PR is the server side only — the web application is outside the files 
I own for this change — so the remaining follow-up is the button wired to this 
endpoint through the shared blob download path. Nothing else about the users 
tab changes; list, page, create, update, delete and credentials-reveal 
behaviour are untouched, and `AclService` is not modified.
   
   ### How Did You Test This Change?
   
   `AclControllerTest` (the controller slice, only `AclService` is mocked) 
gained three tests: the filtered export with the CSV contract and the masking 
regression, the multi-page walk, and the export bound.
   
   Before the fix — the endpoint does not exist, so the three new tests fail 
with 404 while the 27 pre-existing tests keep passing:
   
   ```
   $ cd server && mvn -B -ntp test -Dtest=AclControllerTest
   [ERROR] Tests run: 30, Failures: 3, Errors: 0, Skipped: 0, Time elapsed: 
9.513 s <<< FAILURE! -- in 
org.apache.rocketmq.studio.instance.acl.AclControllerTest
   java.lang.AssertionError: Status expected:<200> but was:<404>   <- 
exportUsersShouldStreamTheMaskedInventoryForTheFilteredInstanceTest:376
   java.lang.AssertionError: Status expected:<400> but was:<404>   <- 
exportUsersShouldRejectAnInventoryBeyondTheExportBoundTest:416
   java.lang.AssertionError: Status expected:<200> but was:<404>   <- 
exportUsersShouldWalkEveryPageOfTheFilteredResultTest:401
   [ERROR] Tests run: 30, Failures: 3, Errors: 0, Skipped: 0
   [INFO] BUILD FAILURE
   ```
   
   After the fix:
   
   ```
   $ cd server && mvn -B -ntp test -Dtest=AclControllerTest
   [INFO] You have 0 Checkstyle violations.
   [INFO] Tests run: 30, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 
9.335 s -- in org.apache.rocketmq.studio.instance.acl.AclControllerTest
   [INFO] Tests run: 30, Failures: 0, Errors: 0, Skipped: 0
   [INFO] BUILD SUCCESS
   ```
   
   The new tests assert the response headers (`text/csv;charset=UTF-8`, 
`attachment; filename="acl-users.csv"`), the BOM-prefixed header row, the 
masked access key and the cluster/permission/whitelist/created columns, that 
the raw secret values and any secret column are absent, that all 150 rows of a 
two-page result are exported in one document, and that 10,001 records produce a 
400 naming the limit.
   
   Neighbouring suites, to show the controller change does not disturb the 
package or the authorization matrix:
   
   ```
   $ cd server && mvn -B -ntp test 
-Dtest=AclControllerTest,AclServiceTest,AclUserVOTest,AuthInterceptorTest,AuthCredentialAuthorizationIntegrationTest,MybatisPlusAclRepositoryTest,ApacheAclReadServiceTest
   [INFO] Tests run: 192, Failures: 0, Errors: 0, Skipped: 0
   [INFO] BUILD SUCCESS
   ```
   
   ### Checklist
   
   - [x] One coherent change; unrelated modifications are not bundled in
   - [x] Commit subject follows Conventional Commits
   - [x] Tests added or updated for non-trivial changes
   - [ ] New UI text has both Chinese and English entries under `web/src/i18n/` 
— not applicable: no UI change in this PR (server-side endpoint only, see the 
scope note)
   - [x] Architecture constraints stay green (`mvn test` runs the ArchUnit 
checks) — the new endpoint reuses existing service/repository APIs, no new 
package or dependency edge
   - [x] New source files carry the ASF license header
   - [ ] Documentation touched where behaviour changed (README / `docs/` / 
in-app help) — not touched: the endpoint follows the existing export 
conventions and the users tab that would surface it is a follow-up outside this 
PR
   


-- 
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