From 8d2c73b579fafb980ad8d42d2d5877392bb5cb6e Mon Sep 17 00:00:00 2001
From: Gildas Garcia <1122076+djhi@users.noreply.github.com>
Date: Fri, 21 Jul 2023 10:34:13 +0200
Subject: [PATCH 1/2] Call checkError when getPermissions fails
---
docs/AuthProviderWriting.md | 4 ++--
.../ra-core/src/auth/usePermissions.spec.tsx | 23 +++++++++++++++++--
packages/ra-core/src/auth/usePermissions.ts | 9 +++++++-
3 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/docs/AuthProviderWriting.md b/docs/AuthProviderWriting.md
index 7512d3b33e9..6081538c4ad 100644
--- a/docs/AuthProviderWriting.md
+++ b/docs/AuthProviderWriting.md
@@ -157,7 +157,7 @@ If the login fails, `authProvider.login()` should return a rejected Promise with
When the user credentials are missing or become invalid, a secure API usually answers to the `dataProvider` with an HTTP error code 401 or 403.
-Fortunately, each time the `dataProvider` returns an error, react-admin calls the `authProvider.checkError()` method. If it returns a rejected promise, react-admin calls the `authProvider.logout()` method immediately, and asks the user to log in again.
+Fortunately, each time the `dataProvider` or the `authProvider.getPermissions` returns an error, react-admin calls the `authProvider.checkError()` method. If it returns a rejected promise, react-admin calls the `authProvider.logout()` method immediately, and asks the user to log in again.
So it's up to you to decide which HTTP status codes should let the user continue (by returning a resolved promise) or log them out (by returning a rejected promise).
@@ -502,5 +502,5 @@ When the auth backend returns an error, the Auth Provider should return a reject
| `logout` | Auth backend failed to log the user out | `void` |
| `getIdentity` | Auth backend failed to return identity | `Object` free format - returned as `error` when `useGetIdentity()` is called |
| `handleCallback` | Failed to authenticate users after redirection | `void | { redirectTo?: string, logoutOnFailure?: boolean, message?: string }` |
-| `getPermissions` | Auth backend failed to return permissions | `Object` free format - returned as `error` when `usePermissions()` is called |
+| `getPermissions` | Auth backend failed to return permissions | `Object` free format - returned as `error` when `usePermissions()` is called. The error will be passed to `checkError` |
diff --git a/packages/ra-core/src/auth/usePermissions.spec.tsx b/packages/ra-core/src/auth/usePermissions.spec.tsx
index 32378343dd0..a3df64a2fee 100644
--- a/packages/ra-core/src/auth/usePermissions.spec.tsx
+++ b/packages/ra-core/src/auth/usePermissions.spec.tsx
@@ -62,12 +62,12 @@ describe('usePermissions', () => {
});
});
- it('should return an error after a tick if the auth call fails', async () => {
+ it('should return an error after a tick if the auth.getPermissions call fails and checkError resolves', async () => {
const authProvider = {
login: () => Promise.reject('bad method'),
logout: () => Promise.reject('bad method'),
checkAuth: () => Promise.reject('bad method'),
- checkError: () => Promise.reject('bad method'),
+ checkError: () => Promise.resolve(),
getPermissions: () => Promise.reject('not good'),
};
render(
@@ -80,4 +80,23 @@ describe('usePermissions', () => {
expect(screen.queryByText('ERROR')).not.toBeNull();
});
});
+
+ it('should call logout when the auth.getPermissions call fails and checkError rejects', async () => {
+ const authProvider = {
+ login: () => Promise.reject('bad method'),
+ logout: jest.fn(() => Promise.resolve()),
+ checkAuth: () => Promise.reject('bad method'),
+ checkError: () => Promise.reject(),
+ getPermissions: () => Promise.reject('not good'),
+ };
+ render(
+
+ {stateInpector}
+
+ );
+ await waitFor(() => {
+ expect(screen.queryByText('LOADING')).toBeNull();
+ });
+ expect(authProvider.logout).toHaveBeenCalled();
+ });
});
diff --git a/packages/ra-core/src/auth/usePermissions.ts b/packages/ra-core/src/auth/usePermissions.ts
index 04e955a7a18..8c450449a5a 100644
--- a/packages/ra-core/src/auth/usePermissions.ts
+++ b/packages/ra-core/src/auth/usePermissions.ts
@@ -1,6 +1,7 @@
import { useMemo } from 'react';
import { useQuery, UseQueryOptions } from 'react-query';
import useAuthProvider from './useAuthProvider';
+import useLogoutIfAccessDenied from './useLogoutIfAccessDenied';
const emptyParams = {};
@@ -41,13 +42,19 @@ const usePermissions = (
}
) => {
const authProvider = useAuthProvider();
+ const logoutIfAccessDenied = useLogoutIfAccessDenied();
const result = useQuery(
['auth', 'getPermissions', params],
authProvider
? () => authProvider.getPermissions(params)
: async () => [],
- queryParams
+ {
+ ...queryParams,
+ onError: error => {
+ logoutIfAccessDenied(error);
+ },
+ }
);
return useMemo(
From 082469b8bab9ed79598f23ab4da641554c471951 Mon Sep 17 00:00:00 2001
From: Gildas Garcia <1122076+djhi@users.noreply.github.com>
Date: Fri, 21 Jul 2023 11:00:42 +0200
Subject: [PATCH 2/2] Fix breaking change
---
packages/ra-core/src/auth/usePermissions.ts | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/packages/ra-core/src/auth/usePermissions.ts b/packages/ra-core/src/auth/usePermissions.ts
index 8c450449a5a..02328540413 100644
--- a/packages/ra-core/src/auth/usePermissions.ts
+++ b/packages/ra-core/src/auth/usePermissions.ts
@@ -50,10 +50,13 @@ const usePermissions = (
? () => authProvider.getPermissions(params)
: async () => [],
{
- ...queryParams,
onError: error => {
+ if (process.env.NODE_ENV !== 'production') {
+ console.error(error);
+ }
logoutIfAccessDenied(error);
},
+ ...queryParams,
}
);