feat: ( permissions ) enforce specific permission keys across API and backoffice

This commit is contained in:
Abubeker Yasin
2026-09-04 15:44:28 +03:00
parent 7c7f5a7a70
commit 7a61ebcb27
69 changed files with 1061 additions and 251 deletions

View File

@@ -4,6 +4,8 @@ const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000';
const GENERIC_ERROR_MESSAGE = 'Something went wrong. Please try again.';
const NETWORK_ERROR_MESSAGE = 'Could not reach the server. Please check your connection and try again.';
const FORBIDDEN_MESSAGE =
'You do not have permission to do that. Ask an administrator if you need access.';
/**
* Extracts a user-facing message from a failed request. Prefers a real backend-provided message
@@ -55,6 +57,21 @@ class ApiClient {
}
}
// A 403 from this API is always a permission check, and the server's own text
// names raw permission keys ("Missing permission. Required one of: …") which
// means nothing to a user. Replace it with something actionable, but only when
// the server did not send a more specific message of its own.
if (error.response?.status === 403) {
const body = error.response.data;
const serverMessage = typeof body?.message === 'string' ? body.message : '';
if (!serverMessage || serverMessage.startsWith('Missing permission')) {
const friendly = FORBIDDEN_MESSAGE;
if (body && typeof body === 'object') body.message = friendly;
error.message = friendly;
return Promise.reject(error);
}
}
// Normalize in place so every existing `err?.response?.data?.message || err?.message ||
// '<fallback>'` call site across the app picks up a friendly message automatically,
// instead of raw axios/network text or an unjoined NestJS validation array.