Aman-Mittal opened a new pull request, #657:
URL: https://github.com/apache/fineract-backoffice-ui/pull/657

   Adds three real-backend RBAC specs covering authorization dimensions the 
existing suite cannot reach, and fixes three UI defects those specs surfaced.
   
   The existing `rbac-*` specs sign in as users whose roles hold or lack a 
permission code. That covers the code check and nothing else, so three things 
went untested: Fineract's office scoping, the gap between authentication and 
authorization, and what happens when the deployment turns `rbacEnabled` off 
while the platform keeps enforcing.
   
   ## Specs
   
   **`rbac-office-scoped-user.spec.ts`** — a user holding `READ_CLIENT` + 
`READ_OFFICE` in a seeded branch office, **plus a Head Office control user 
holding the byte-identical role**. Fineract scopes every portfolio query to the 
office subtree, so two users with the same permission codes see different 
records and nothing in the code says so. The pair of users is the assertion, 
because `GET /offices` returns 200 to both — the difference is in the body, not 
the status. Also asserts that reading another office's client is **404, not 
403**: a move to 403 would change what the platform discloses, so it is pinned 
deliberately.
   
   **`rbac-permissionless-user.spec.ts`** — a role granted nothing. Fineract 
authenticates them (`POST /authentication` → 200, permissions 
`["FACTOR_PASSWORD"]`) and refuses every portfolio read. The app signs them in 
and lands them on `/dashboard` rather than stranding them; every gated module 
is absent from the nav and redirects to `/forbidden` by URL. The part worth 
having: the entries they are *left* with genuinely work. `/products/share` and 
`/tellers` answer 200 to anyone signed in because Fineract's catalogue has no 
READ code for them, so the nav is not a menu of guaranteed failures.
   
   **`rbac-disabled-flag-backend.spec.ts`** — `READ_CLIENT` only, with the 
deployment's `config.json` rewritten to `rbacEnabled: false` (the one stubbed 
thing; same technique as `oidc-login-backend.spec.ts`). The nav opens up and 
the guard admits `/accounting/chart-of-accounts` and `/clients/create` — **and 
Fineract still returns 403** for `/glaccounts`, `/loans`, `/users` and the 
client POST, while `/clients` stays 200. This makes `security.md` §5a 
executable instead of prose: the flag changes what is offered, never what is 
allowed.
   
   All three are registered in `BACKEND_SPECS`. `e2e/utils/fineract-login.ts` 
factors out the seeded-user sign-in that the existing specs each had their own 
copy of, and `seed-api.ts` gains the ability to place a seeded user in an 
office other than Head Office.
   
   ## UI fixes
   
   Each came from watching the live stack, not from reading the code.
   
   **1. `client-view` fetches accounts only once the client has loaded.** A 
branch user opening a head-office client got the page's own "This client 
doesn't exist, or you don't have permission to view it" *and* a toast reading 
"The requested resource is not available. • [id] Client not found with valuer 
35." The client request already passed `skipErrorToast()` with a comment naming 
exactly that toast; the accounts request ran beside it, failed identically, and 
did not skip it — so the suppression had no effect. The accounts are derived 
from the client, so ordering them removes both the duplicate toast and a 
request that could never have succeeded. A client that loads and accounts that 
then fail still toasts, which is the case where the toast is the only feedback.
   
   **2. `data-table` tells a refused list from a broken one, and withholds the 
futile retry.** On Chart of Accounts under `rbacEnabled: false`: "This list 
could not be loaded." over a "Try again" button that is refused identically on 
every press — a loop with no exit, over a message that says nothing about what 
happened. New optional `errorStatus` input; at 403 the table shows 
`COMMON.ERRORS.LOAD_FORBIDDEN` with a lock icon and no retry. `null` — every 
call site not updated — is byte-identical to before. Wired at Chart of Accounts 
and Loans, the two screens where the problem was observed; the remaining call 
sites are left for the screens that demonstrate the need.
   
   **3. `offices-list` gates the edit control on `UPDATE_OFFICE`.** A 
`READ_OFFICE` user was offered Edit on every row, and 
`organization/offices/edit/:id` declares `UPDATE_OFFICE` — so the control led 
straight to Access Denied. The create button beside it has been gated on 
`CREATE_OFFICE` all along. The spec asserts the hidden control **and** that 
Fineract answers 403 to the `PUT`, because a test checking only the button 
would pass against a broken boundary.
   
   ## Verification
   
   Run against a live Fineract stack after rebasing onto `03533bfc`:
   
   ```
   npm run lint                  clean
   npm run test:unit             278 files, 1822 tests passed
   npm run build                 bundle complete
   npm run i18n:check            no missing keys, no phrase labels, catalogues 
consistent
   npm run check:template-text   no new untranslated template text
   npm run typecheck:e2e         clean
   check-license.sh              all files have headers
   
   playwright --project=backend  33 passed (2.3m)  — the 3 new specs plus the 2 
existing rbac-* specs
   playwright --project=mocked   209 passed (4.4m) — 13 specs covering every 
component changed here
   ```
   
   Also green: `check:route-permissions` (317 screens agree), `check:icons`, 
`check:a11y-names`, `check:ui-primitives`, `check:nav-ids`, `check:responsive`, 
`check:internal-endpoints`.
   
   **Not verified, stated plainly:** the full 410-test `mocked` project did not 
complete on `03533bfc` — it was green at `409 passed` on the previous base with 
all of these changes applied, and the 13-spec targeted subset above is green on 
`03533bfc`, but the full run was abandoned twice to unrelated machine load. Low 
risk, but a gap rather than a pass. Not run: `--fresh` (every assertion is 
scoped to records seeded within the run, and the branch office is created per 
run, so the office-scope assertions are fresh-safe by construction — but that 
was not proven on a migration-fresh database), the `two-factor` and `mobile` 
projects, and `verify-api-client` (nothing generated was touched).
   
   ## Open question for reviewers
   
   **The Offices screen requests `includeAllOffices=true`**, so a branch user 
is shown the entire institution's office tree although `GET /offices` alone 
would have returned their own office. Both calls answer 200 — the client 
chooses the wider body. This is recorded as an assertion pair and a comment 
rather than changed, because an office register arguably *should* be 
institution-wide and that is a product decision, not a bug fix. Happy to follow 
either way.
   
   Two further findings were deliberately left alone: a branch user holding 
`CREATE_CLIENT` can create a client in Head Office (200) — office scope 
constrains the reads but not that write, which looks like platform behaviour 
rather than a UI issue and is not pinned in a spec; and AND semantics 
(`permissionsMatchAll: true`) exists in the guard but on no route, so testing 
it would have meant inventing a route. The guard's unit tests already cover 
those semantics.
   


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