Aman-Mittal opened a new issue, #258:
URL: https://github.com/apache/fineract-backoffice-ui/issues/258

   ## Business value
   
   Fineract uses HTTP **403** for two unrelated things: you lack the 
permission, and *the operation is not allowed in this state*. 
`errorInterceptor` treats every 403 as the first, so the platform's explanation 
of the second is thrown away and replaced with a message that sends the user to 
the wrong place entirely.
   
   Closing a group that still has active members answers:
   
   ```json
   {
     "httpStatusCode": "403",
     "userMessageGlobalisationCode": "validation.msg.domain.rule.violation",
     "defaultUserMessage": "Errors contain reason for domain rule violation.",
     "errors": [
       {
         "defaultUserMessage": "Group cannot be closed because of active 
clients associated with it.",
         "userMessageGlobalisationCode": 
"error.msg.Group.close.active.clients.exist",
         "parameterName": "id"
       }
     ]
   }
   ```
   
   The user is shown:
   
   > You do not have permission to perform this action. Contact an 
administrator if you believe this is a mistake.
   
   They had the permission. What they needed to know was to remove the members 
first — which the response says, in a field the interceptor never reaches. 
Instead they go and ask an administrator for a right they already hold, and the 
administrator finds nothing wrong.
   
   This is not specific to groups. Every state-machine rule in Fineract comes 
back this way: closing a client with open loans, disbursing before approval, 
undoing a transaction that has been reversed. The whole class currently reports 
as a permissions problem.
   
   ## Where it is
   
   `src/app/core/interceptors/error.interceptor.ts`, in `messageFor`. The 403 
branch returns before the `errors[]` handling that would have produced the 
right message:
   
   ```ts
   // Fineract's 403 body describes the missing permission in backend terms 
("NOT_ALLOWED",
   // a permission code) which means nothing to the user. ...
   if (error.status === 403) {
     return i18n.translate('COMMON.ERRORS.FORBIDDEN');
   }
   
   if (error.error?.errors && Array.isArray(error.error.errors) && 
error.error.errors.length > 0) {
     // ← this is what should run for a domain-rule 403, and never does
   ```
   
   The comment is right about *authorization* 403s — that body really is 
unhelpful, and the friendly message is the correct treatment. The bug is that 
it also swallows the domain-rule 403, which is the informative one.
   
   ## Reproducing it
   
   Against a local Fineract:
   
   1. Create a client and activate it.
   2. Create a group, activate it, and add the client as a member.
   3. Add a value to the `GroupClosureReason` code (System → Manage Codes) — it 
ships empty.
   4. Open the group and choose Close.
   
   Expected: the platform's reason. Actual: the permissions message.
   
   `e2e/group-membership.spec.ts` drives exactly this sequence and currently 
asserts only that the command is refused and the group is left Active, with a 
comment pointing here — it should assert the message once this is fixed.
   
   ## Describing the change
   
   Distinguish the two. A domain-rule violation is identifiable without 
guessing:
   
   - `userMessageGlobalisationCode` is `validation.msg.domain.rule.violation`, 
and
   - `errors[]` is populated with entries carrying a real `defaultUserMessage`.
   
   An authorization 403 has neither. So the conservative fix is to let a 403 
fall through to the existing `errors[]` handling when that array has content, 
and keep `COMMON.ERRORS.FORBIDDEN` otherwise:
   
   ```ts
   const isDomainRuleViolation =
     error.error?.userMessageGlobalisationCode === 
'validation.msg.domain.rule.violation' ||
     (Array.isArray(error.error?.errors) && error.error.errors.length > 0);
   
   if (error.status === 403 && !isDomainRuleViolation) {
     return i18n.translate('COMMON.ERRORS.FORBIDDEN');
   }
   ```
   
   Deliberately conservative: a genuine permission 403 that happens to carry an 
`errors[]` array still shows the friendly message only if the array is empty, 
and anything unrecognised keeps today's behaviour. Nothing gets *worse* than it 
is now.
   
   `error.interceptor.spec.ts` already covers the 403 path and the `errors[]` 
stacking separately — this needs a case for the two combined. Please add one 
asserting the group-close body above produces the platform's message rather 
than the permissions text.
   
   ## Scope
   
   In scope: the 403 branch in `messageFor`, and a unit spec for it.
   
   Out of scope: the 401 session handling beside it, changing 
`COMMON.ERRORS.FORBIDDEN` itself, and any per-screen error handling — this is 
one interceptor and every screen benefits.
   
   ## Getting started
   
   - `src/app/core/interceptors/error.interceptor.ts` and its spec.
   - `npm test` must pass; `npm run lint` and `npm run build` too.
   - Worth reading the existing spec first — the 403 case there encodes the 
reasoning this change has to preserve.
   


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