unbridled-41 commented on PR #5072:
URL:
https://github.com/apache/rocketmq-dashboard/pull/5072#issuecomment-5813355090
### Verification pass (evidence audit, 2026-09-24)
Fresh checkout of this branch (`/tmp/aud-d`, empty `server/target`); every
`file:line` re-read against base `a562601d` and the branch; every command
re-executed there; the pre-fix claim reproduced by writing the base content of
the production file back (`git show a562601d:<path> > <path>`, which does not
touch the index) and keeping the tests.
**Citations — all hold**
| Claim | base `a562601d` |
|---|---|
| the unique keys | `schema.sql:291-292` — `UNIQUE KEY uk_username
(username)`, `UNIQUE KEY uk_access_key (access_key)` |
| the create path | `AclController.java:112-114` → `AclService.java:226`
(`aclRepository.saveUser(user)`) → `MybatisPlusAclRepository.java:152`
(`userMapper.insert(entity)`) |
| the rename path | `AclController.java:117-120` → `AclService.java:256`
(`aclRepository.replaceUser(merged)`) → `MybatisPlusAclRepository.java:167`
(`userMapper.updateById(entity)`) |
| the console reaches the rename | `web/src/pages/instance/acl.tsx:411-413`
— the edit form sends `username`, not just `id` |
| where 500 comes from | `GlobalExceptionHandler.java:109-114` catch-all;
the only status mapping is `:42-47` (`BusinessException` →
`ResponseEntity.status(ex.getCode())`) |
| the in-repo precedent | `MybatisPlusAclRepository.java:255-263` — the
plain-access write catches the same exception and answers 409, quoting
CloudCredentialService |
**Reachability, checked beyond the description**: `saveUser` has exactly one
caller (`AclService.createUser`) and `CreateAclUserDTO` carries no `id`, so
`toAclUserVO()` always has a null id and only the insert branch is reachable
from the console — the branch this PR wraps. The rename path goes through
`replaceUser`'s update branch, which is also wrapped. The second unique key
cannot realistically collide: `createUser` generates the key with
`randomCredentialToken()` and a rename keeps the existing row's key, so the
message naming the username is accurate for every reachable conflict.
**Pre-fix reproduction** (command as written):
```
$ cd server && mvn -o test -Dtest=MybatisPlusAclRepositoryTest
saveUserShouldReportADuplicateUsernameAsAConflict:
Expecting actual throwable to be an instance of:
org.apache.rocketmq.studio.common.exception.BusinessException
but was:
org.springframework.dao.DuplicateKeyException: uk_username
at
…MybatisPlusAclRepository.saveUser(MybatisPlusAclRepository.java:152)
replaceUserShouldReportARenameOntoAnExistingUsernameAsAConflict:
… DuplicateKeyException: uk_username
at
…MybatisPlusAclRepository.replaceUser(MybatisPlusAclRepository.java:167)
[ERROR] Tests run: 25, Failures: 2, Errors: 0, Skipped: 0
```
**Post-fix**: `MybatisPlusAclRepositoryTest` → `Tests run: 25, Failures: 0,
Errors: 0, Skipped: 0`; with `AclServiceTest,AclControllerTest` → `Tests run:
130, Failures: 0, Errors: 0, Skipped: 0`.
**Coverage**: both reachable write branches are asserted (insert on create,
update on rename), and "no caller catches `DuplicateKeyException` from these
methods" is verified — the only caller of either method is `AclService`, which
has no try/catch around them (the other `DuplicateKeyException` handlers in the
codebase are in `AuthService`, `AiEventSink`, `AlertService`,
`CloudCredentialService` and touch different tables). The last hop, 409 out of
the advice, is the unconditional `ResponseEntity.status(ex.getCode())` line
whose 404/400/504 siblings `GlobalExceptionHandlerTest` pins
(`preservesNotFoundBusinessStatusAndEnvelope`,
`preservesBadRequestBusinessStatusAndEnvelope`,
`preservesLlmGatewayStatusAndEnvelope`); a 409-specific test would only
re-assert the same constant, so none was added.
**Commit hygiene**: `git show --stat cee16745` = the repository file + its
test, nothing else.
No description defect, no test gap and no code defect found in this pass;
nothing was added.
--
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]