diff --git a/src/hooks/useUserSelfTenantPermissions.js b/src/hooks/useUserSelfTenantPermissions.js
new file mode 100644
index 000000000..7ffde2e84
--- /dev/null
+++ b/src/hooks/useUserSelfTenantPermissions.js
@@ -0,0 +1,51 @@
+import { useQuery } from 'react-query';
+
+import { useStripes } from '../StripesContext';
+import { useNamespace } from '../components';
+import useOkapiKy from '../useOkapiKy';
+
+const INITIAL_DATA = [];
+
+const useUserSelfTenantPermissions = (
+ { tenantId },
+ options = {},
+) => {
+ const stripes = useStripes();
+ const ky = useOkapiKy();
+ const api = ky.extend({
+ hooks: {
+ beforeRequest: [(req) => req.headers.set('X-Okapi-Tenant', tenantId)]
+ }
+ });
+ const [namespace] = useNamespace({ key: 'user-self-permissions' });
+
+ const user = stripes.user.user;
+
+ const {
+ isFetching,
+ isLoading,
+ data,
+ } = useQuery(
+ [namespace, user?.id, tenantId],
+ ({ signal }) => {
+ return api.get(
+ 'users-keycloak/_self',
+ { signal },
+ ).json();
+ },
+ {
+ enabled: Boolean(user?.id && tenantId) && stripes.hasInterface('users-keycloak'),
+ keepPreviousData: true,
+ ...options,
+ },
+ );
+
+ return ({
+ isFetching,
+ isLoading,
+ userPermissions: data?.permissions.permissions || INITIAL_DATA,
+ totalRecords: data?.permissions.permissions.length || 0,
+ });
+};
+
+export default useUserSelfTenantPermissions;
diff --git a/src/hooks/useUserSelfTenantPermissions.test.js b/src/hooks/useUserSelfTenantPermissions.test.js
new file mode 100644
index 000000000..e8604bab7
--- /dev/null
+++ b/src/hooks/useUserSelfTenantPermissions.test.js
@@ -0,0 +1,71 @@
+import { renderHook, waitFor } from '@folio/jest-config-stripes/testing-library/react';
+import {
+ QueryClient,
+ QueryClientProvider,
+} from 'react-query';
+
+import permissions from 'fixtures/permissions';
+import useUserSelfTenantPermissions from './useUserSelfTenantPermissions';
+import useOkapiKy from '../useOkapiKy';
+
+jest.mock('../useOkapiKy');
+jest.mock('../components', () => ({
+ useNamespace: () => ([]),
+}));
+jest.mock('../StripesContext', () => ({
+ useStripes: () => ({
+ user: {
+ user: {
+ id: 'userId'
+ }
+ },
+ hasInterface: () => true
+ }),
+}));
+
+const queryClient = new QueryClient();
+
+// eslint-disable-next-line react/prop-types
+const wrapper = ({ children }) => (
+
+ {children}
+
+);
+
+const response = {
+ permissions: { permissions },
+};
+
+describe('useUserSelfTenantPermissions', () => {
+ const getMock = jest.fn(() => ({
+ json: () => Promise.resolve(response),
+ }));
+ const setHeaderMock = jest.fn();
+ const kyMock = {
+ extend: jest.fn(({ hooks: { beforeRequest } }) => {
+ beforeRequest.forEach(handler => handler({ headers: { set: setHeaderMock } }));
+
+ return {
+ get: getMock,
+ };
+ }),
+ };
+
+ beforeEach(() => {
+ getMock.mockClear();
+ useOkapiKy.mockClear().mockReturnValue(kyMock);
+ });
+
+ it('should fetch user permissions for specified tenant', async () => {
+ const options = {
+ userId: 'userId',
+ tenantId: 'tenantId',
+ };
+ const { result } = renderHook(() => useUserSelfTenantPermissions(options), { wrapper });
+
+ await waitFor(() => !result.current.isLoading);
+
+ expect(setHeaderMock).toHaveBeenCalledWith('X-Okapi-Tenant', options.tenantId);
+ expect(getMock).toHaveBeenCalledWith('users-keycloak/_self', expect.objectContaining({}));
+ });
+});
diff --git a/src/hooks/useUserTenantPermissionNames.js b/src/hooks/useUserTenantPermissionNames.js
new file mode 100644
index 000000000..dc7c2057a
--- /dev/null
+++ b/src/hooks/useUserTenantPermissionNames.js
@@ -0,0 +1,59 @@
+import { useQuery } from 'react-query';
+
+import { useStripes } from '../StripesContext';
+import { useNamespace } from '../components';
+import useOkapiKy from '../useOkapiKy';
+
+const INITIAL_DATA = [];
+
+const useUserTenantPermissionNames = (
+ { tenantId },
+ options = {},
+) => {
+ const stripes = useStripes();
+ const ky = useOkapiKy();
+ const api = ky.extend({
+ hooks: {
+ beforeRequest: [(req) => req.headers.set('X-Okapi-Tenant', tenantId)]
+ }
+ });
+ const [namespace] = useNamespace({ key: 'user-affiliation-permissions' });
+
+ const user = stripes.user.user;
+
+ const searchParams = {
+ full: 'true',
+ indexField: 'userId',
+ };
+
+ const {
+ isFetching,
+ isLoading,
+ data = {},
+ } = useQuery(
+ [namespace, user?.id, tenantId],
+ ({ signal }) => {
+ return api.get(
+ `perms/users/${user.id}/permissions`,
+ {
+ searchParams,
+ signal,
+ },
+ ).json();
+ },
+ {
+ enabled: Boolean(user?.id && tenantId) && !stripes.hasInterface('roles'),
+ keepPreviousData: true,
+ ...options,
+ },
+ );
+
+ return ({
+ isFetching,
+ isLoading,
+ userPermissions: data.permissionNames || INITIAL_DATA,
+ totalRecords: data.totalRecords,
+ });
+};
+
+export default useUserTenantPermissionNames;
diff --git a/src/hooks/useUserTenantPermissionNames.test.js b/src/hooks/useUserTenantPermissionNames.test.js
new file mode 100644
index 000000000..cc15aecda
--- /dev/null
+++ b/src/hooks/useUserTenantPermissionNames.test.js
@@ -0,0 +1,72 @@
+import { renderHook, waitFor } from '@folio/jest-config-stripes/testing-library/react';
+import {
+ QueryClient,
+ QueryClientProvider,
+} from 'react-query';
+
+import permissions from 'fixtures/permissions';
+import useUserTenantPermissionNames from './useUserTenantPermissionNames';
+import useOkapiKy from '../useOkapiKy';
+
+jest.mock('../useOkapiKy');
+jest.mock('../components', () => ({
+ useNamespace: () => ([]),
+}));
+jest.mock('../StripesContext', () => ({
+ useStripes: () => ({
+ user: {
+ user: {
+ id: 'userId'
+ }
+ },
+ hasInterface: () => false
+ }),
+}));
+
+const queryClient = new QueryClient();
+
+// eslint-disable-next-line react/prop-types
+const wrapper = ({ children }) => (
+
+ {children}
+
+);
+
+const response = {
+ permissionNames: permissions,
+ totalRecords: permissions.length,
+};
+
+describe('useUserTenantPermissionNames', () => {
+ const getMock = jest.fn(() => ({
+ json: () => Promise.resolve(response),
+ }));
+ const setHeaderMock = jest.fn();
+ const kyMock = {
+ extend: jest.fn(({ hooks: { beforeRequest } }) => {
+ beforeRequest.forEach(handler => handler({ headers: { set: setHeaderMock } }));
+
+ return {
+ get: getMock,
+ };
+ }),
+ };
+
+ beforeEach(() => {
+ getMock.mockClear();
+ useOkapiKy.mockClear().mockReturnValue(kyMock);
+ });
+
+ it('should fetch user permissions for specified tenant', async () => {
+ const options = {
+ userId: 'userId',
+ tenantId: 'tenantId',
+ };
+ const { result } = renderHook(() => useUserTenantPermissionNames(options), { wrapper });
+
+ await waitFor(() => !result.current.isLoading);
+
+ expect(setHeaderMock).toHaveBeenCalledWith('X-Okapi-Tenant', options.tenantId);
+ expect(getMock).toHaveBeenCalledWith(`perms/users/${options.userId}/permissions`, expect.objectContaining({}));
+ });
+});
diff --git a/src/hooks/useUserTenantPermissions.js b/src/hooks/useUserTenantPermissions.js
index 80030eea1..4173160c3 100644
--- a/src/hooks/useUserTenantPermissions.js
+++ b/src/hooks/useUserTenantPermissions.js
@@ -1,58 +1,37 @@
-import { useQuery } from 'react-query';
-
import { useStripes } from '../StripesContext';
-import { useNamespace } from '../components';
-import useOkapiKy from '../useOkapiKy';
-
-const INITIAL_DATA = [];
+import useUserSelfTenantPermissions from './useUserSelfTenantPermissions';
+import useUserTenantPermissionNames from './useUserTenantPermissionNames';
const useUserTenantPermissions = (
{ tenantId },
options = {},
) => {
const stripes = useStripes();
- const ky = useOkapiKy();
- const api = ky.extend({
- hooks: {
- beforeRequest: [(req) => req.headers.set('X-Okapi-Tenant', tenantId)]
- }
- });
- const [namespace] = useNamespace({ key: 'user-affiliation-permissions' });
-
- const user = stripes.user.user;
- const searchParams = {
- full: 'true',
- indexField: 'userId',
- };
+ const {
+ isFetching: isPermissionsFetching,
+ isLoading: isPermissionsLoading,
+ userPermissions: permissionsData = {},
+ totalRecords: permissionsTotalRecords
+ } = useUserTenantPermissionNames({ tenantId }, options);
const {
- isFetching,
- isLoading,
- data = {},
- } = useQuery(
- [namespace, user?.id, tenantId],
- ({ signal }) => {
- return api.get(
- `perms/users/${user.id}/permissions`,
- {
- searchParams,
- signal,
- },
- ).json();
- },
- {
- enabled: Boolean(user?.id && tenantId),
- keepPreviousData: true,
- ...options,
- },
- );
+ isFetching: isSelfPermissionsFetching,
+ isLoading: isSelfPermissionsLoading,
+ userPermissions:selfPermissionsData = {},
+ totalRecords: selfPermissionsTotalRecords
+ } = useUserSelfTenantPermissions({ tenantId }, options);
+
+ const isFetching = stripes.hasInterface('roles') ? isSelfPermissionsFetching : isPermissionsFetching;
+ const isLoading = stripes.hasInterface('roles') ? isSelfPermissionsLoading : isPermissionsLoading;
+ const userPermissions = stripes.hasInterface('roles') ? selfPermissionsData : permissionsData;
+ const totalRecords = stripes.hasInterface('roles') ? selfPermissionsTotalRecords : permissionsTotalRecords;
return ({
isFetching,
isLoading,
- userPermissions: data.permissionNames || INITIAL_DATA,
- totalRecords: data.totalRecords,
+ userPermissions,
+ totalRecords
});
};
diff --git a/src/hooks/useUserTenantPermissions.test.js b/src/hooks/useUserTenantPermissions.test.js
index e64b9c440..c3f4aa9bd 100644
--- a/src/hooks/useUserTenantPermissions.test.js
+++ b/src/hooks/useUserTenantPermissions.test.js
@@ -1,71 +1,74 @@
-import { renderHook, waitFor } from '@folio/jest-config-stripes/testing-library/react';
-import {
- QueryClient,
- QueryClientProvider,
-} from 'react-query';
-
-import permissions from 'fixtures/permissions';
+import { renderHook } from '@folio/jest-config-stripes/testing-library/react';
+import { useStripes } from '../StripesContext';
+import useUserSelfTenantPermissions from './useUserSelfTenantPermissions';
+import useUserTenantPermissionNames from './useUserTenantPermissionNames';
import useUserTenantPermissions from './useUserTenantPermissions';
-import useOkapiKy from '../useOkapiKy';
-jest.mock('../useOkapiKy');
-jest.mock('../components', () => ({
- useNamespace: () => ([]),
-}));
-jest.mock('../StripesContext', () => ({
- useStripes: () => ({
- user: {
- user: {
- id: 'userId'
- }
- }
- }),
-}));
+jest.mock('../StripesContext');
+jest.mock('./useUserSelfTenantPermissions');
+jest.mock('./useUserTenantPermissionNames');
-const queryClient = new QueryClient();
+describe('useUserTenantPermissions', () => {
+ const tenantId = 'tenant-id';
+ const options = {};
-// eslint-disable-next-line react/prop-types
-const wrapper = ({ children }) => (
-
- {children}
-
-);
+ beforeEach(() => {
+ useStripes.mockReturnValue({
+ hasInterface: jest.fn()
+ });
+ });
-const response = {
- permissionNames: permissions,
- totalRecords: permissions.length,
-};
+ it('should return _self permissions data when "roles" interface is present', () => {
+ useStripes().hasInterface.mockReturnValue(true);
-describe('useUserTenantPermissions', () => {
- const getMock = jest.fn(() => ({
- json: () => Promise.resolve(response),
- }));
- const setHeaderMock = jest.fn();
- const kyMock = {
- extend: jest.fn(({ hooks: { beforeRequest } }) => {
- beforeRequest.forEach(handler => handler({ headers: { set: setHeaderMock } }));
+ useUserSelfTenantPermissions.mockReturnValue({
+ isFetching: true,
+ isLoading: true,
+ userPermissions: ['self'],
+ totalRecords: 1
+ });
- return {
- get: getMock,
- };
- }),
- };
+ useUserTenantPermissionNames.mockReturnValue({
+ isFetching: false,
+ isLoading: false,
+ userPermissions: ['permission name'],
+ totalRecords: 1
+ });
- beforeEach(() => {
- getMock.mockClear();
- useOkapiKy.mockClear().mockReturnValue(kyMock);
+ const { result } = renderHook(() => useUserTenantPermissions({ tenantId }, options));
+
+ expect(result.current).toStrictEqual({
+ isFetching: true,
+ isLoading: true,
+ userPermissions: ['self'],
+ totalRecords: 1
+ });
});
- it('should fetch user permissions for specified tenant', async () => {
- const options = {
- userId: 'userId',
- tenantId: 'tenantId',
- };
- const { result } = renderHook(() => useUserTenantPermissions(options), { wrapper });
+ it('should return tenant permissions data when "roles" interface is NOT present', () => {
+ useStripes().hasInterface.mockReturnValue(false);
+
+ useUserSelfTenantPermissions.mockReturnValue({
+ isFetching: true,
+ isLoading: true,
+ userPermissions: ['self'],
+ totalRecords: 1
+ });
+
+ useUserTenantPermissionNames.mockReturnValue({
+ isFetching: false,
+ isLoading: false,
+ userPermissions: ['permission name'],
+ totalRecords: 1
+ });
- await waitFor(() => !result.current.isLoading);
+ const { result } = renderHook(() => useUserTenantPermissions({ tenantId }, options));
- expect(setHeaderMock).toHaveBeenCalledWith('X-Okapi-Tenant', options.tenantId);
- expect(getMock).toHaveBeenCalledWith(`perms/users/${options.userId}/permissions`, expect.objectContaining({}));
+ expect(result.current).toStrictEqual({
+ isFetching: false,
+ isLoading: false,
+ userPermissions: ['permission name'],
+ totalRecords: 1
+ });
});
});