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]