diff --git a/src/helpers/useValidateUserPermissions.test.tsx b/src/helpers/useValidateUserPermissions.test.tsx
new file mode 100644
index 0000000..c063c9b
--- /dev/null
+++ b/src/helpers/useValidateUserPermissions.test.tsx
@@ -0,0 +1,99 @@
+import { act, ReactNode } from 'react';
+import { renderHook, waitFor } from '@testing-library/react';
+import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
+import { useValidateUserPermissions } from './useValidateUserPermissions';
+
+jest.mock('@edx/frontend-platform/auth', () => ({
+ getAuthenticatedHttpClient: jest.fn(),
+}));
+
+const createWrapper = () => {
+ const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: {
+ retry: false,
+ },
+ },
+ });
+
+ const wrapper = ({ children }: { children: ReactNode }) => (
+
+ {children}
+
+ );
+
+ return wrapper;
+};
+const permissions = [
+ {
+ action: 'act:read',
+ object: 'lib:test-lib',
+ scope: 'org:OpenedX',
+ },
+];
+
+const mockValidPermissions = [
+ { action: 'act:read', object: 'lib:test-lib', allowed: true },
+];
+
+const mockInvalidPermissions = [
+ { action: 'act:read', object: 'lib:test-lib', allowed: false },
+];
+
+describe('useValidateUserPermissions', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('returns allowed true when permissions are valid', async () => {
+ getAuthenticatedHttpClient.mockReturnValue({
+ post: jest.fn().mockResolvedValueOnce({ data: mockValidPermissions }),
+ });
+
+
+ const { result } = renderHook(() => useValidateUserPermissions(permissions), {
+ wrapper: createWrapper(),
+ });
+
+ await waitFor(() => expect(result.current).toBeDefined());
+
+ expect(getAuthenticatedHttpClient).toHaveBeenCalled();
+ expect(result.current.data[0].allowed).toBe(true);
+ });
+
+ it('returns allowed false when permissions are invalid', async () => {
+ getAuthenticatedHttpClient.mockReturnValue({
+ post: jest.fn().mockResolvedValue({ data: mockInvalidPermissions }),
+ });
+
+ const { result } = renderHook(() => useValidateUserPermissions(permissions), {
+ wrapper: createWrapper(),
+ });
+
+ await waitFor(() => expect(result.current).toBeDefined());
+
+ expect(getAuthenticatedHttpClient).toHaveBeenCalled();
+ expect(result.current.data[0].allowed).toBe(false);
+ });
+
+ it('handles error when the API call fails', async () => {
+ const mockError = new Error('API Error');
+
+ getAuthenticatedHttpClient.mockReturnValue({
+ post: jest.fn().mockRejectedValue(new Error('API Error')),
+ });
+
+ try {
+ act(() => {
+ renderHook(() => useValidateUserPermissions(permissions), {
+ wrapper: createWrapper(),
+ });
+ });
+
+ } catch (error) {
+ expect(error).toEqual(mockError); // Check for the expected error
+ return;
+ }
+ });
+});
diff --git a/src/helpers/useValidateUserPermissions.ts b/src/helpers/useValidateUserPermissions.ts
new file mode 100644
index 0000000..9a09604
--- /dev/null
+++ b/src/helpers/useValidateUserPermissions.ts
@@ -0,0 +1,44 @@
+import { useSuspenseQuery } from "@tanstack/react-query";
+import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
+import { getApiUrl } from './utils';
+
+export interface PermissionValidationRequest {
+ action: string;
+ object?: string;
+ scope?: string;
+}
+
+export interface PermissionValidationResponse extends PermissionValidationRequest{
+ allowed: boolean;
+}
+
+const validateUserPermissions = async (validations: PermissionValidationRequest[]): Promise => {
+ const { data } = await getAuthenticatedHttpClient().post(getApiUrl(`/api/authz/v1/permissions/validate/me`), validations);
+ return data;
+};
+
+
+/**
+ * React Query hook to validate if the current user has permissions over a certain object in the instance.
+ * It helps to:
+ * - Determine whether the current user can access certain object.
+ * - Provide role-based rendering logic for UI components.
+ *
+ * @param permissions - The array of objects and actions to validate.
+ *
+ * @example
+ * const { data } = useValidateTeamMember([{
+ "action": "act:read",
+ "object": "lib:test-lib",
+ "scope": "org:OpenedX"
+ }]);
+ * if (data[0].allowed) { ... }
+ *
+ */
+export const useValidateUserPermissions = (permissions: PermissionValidationRequest[]) => {
+ return useSuspenseQuery({
+ queryKey: ['validate-user-permissions', permissions],
+ queryFn: () => validateUserPermissions(permissions),
+ retry: false,
+ });
+}
\ No newline at end of file
diff --git a/src/helpers/utils.ts b/src/helpers/utils.ts
new file mode 100644
index 0000000..8676ba1
--- /dev/null
+++ b/src/helpers/utils.ts
@@ -0,0 +1,4 @@
+import { getConfig } from '@edx/frontend-platform';
+
+export const getApiUrl = (path: string) => `${getConfig().LMS_BASE_URL}${path || ''}`;
+export const getStudioApiUrl = (path: string) => `${getConfig().STUDIO_BASE_URL}${path || ''}`;