From 727bf74049cc604090a6c29ea2908b99d06eb913 Mon Sep 17 00:00:00 2001 From: Diana Olarte Date: Fri, 26 Sep 2025 15:24:06 +1000 Subject: [PATCH] style: fix linter issues and data location --- src/authz-module/constants.ts | 21 ------------- .../{libraries-manager => }/data/api.ts | 8 ++--- .../data/hooks.test.tsx | 0 .../{libraries-manager => }/data/hooks.ts | 16 +++++----- .../components/TeamTable.test.tsx | 4 +-- .../components/TeamTable.tsx | 5 +-- .../libraries-manager/context.test.tsx | 8 ++--- .../libraries-manager/context.tsx | 4 +-- src/components/LoadingPage.tsx | 14 ++++----- src/data/api.ts | 8 +++++ .../hooks.test.tsx} | 6 ++-- .../hooks.ts} | 28 ++++------------- src/{helpers => data}/utils.ts | 0 src/types.ts | 31 +++++++++++++++++++ 14 files changed, 78 insertions(+), 75 deletions(-) rename src/authz-module/{libraries-manager => }/data/api.ts (72%) rename src/authz-module/{libraries-manager => }/data/hooks.test.tsx (100%) rename src/authz-module/{libraries-manager => }/data/hooks.ts (60%) create mode 100644 src/data/api.ts rename src/{helpers/useValidateUserPermissions.test.tsx => data/hooks.test.tsx} (97%) rename src/{helpers/useValidateUserPermissions.ts => data/hooks.ts} (51%) rename src/{helpers => data}/utils.ts (100%) create mode 100644 src/types.ts diff --git a/src/authz-module/constants.ts b/src/authz-module/constants.ts index 2da6c73..18bad6b 100644 --- a/src/authz-module/constants.ts +++ b/src/authz-module/constants.ts @@ -1,24 +1,3 @@ -export interface TeamMember { - displayName: string; - username: string; - email: string; - roles: string[]; -} - -export interface LibraryMetadata { - id: string; - org: string; - title: string; - slug: string; -} - -export interface TableCellValue { - row: { - original: T; - }; -} - - export const ROUTES = { LIBRARIES_TEAM_PATH: '/libraries/:libraryId', LIBRARIES_USER_PATH: '/libraries/user/:username' diff --git a/src/authz-module/libraries-manager/data/api.ts b/src/authz-module/data/api.ts similarity index 72% rename from src/authz-module/libraries-manager/data/api.ts rename to src/authz-module/data/api.ts index 11fd85b..7e4498c 100644 --- a/src/authz-module/libraries-manager/data/api.ts +++ b/src/authz-module/data/api.ts @@ -1,7 +1,7 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; -import { LibraryMetadata, TeamMember } from '@src/authz-module/constants'; +import { LibraryMetadata, TeamMember } from '@src/types'; import { camelCaseObject } from '@edx/frontend-platform'; -import { getApiUrl, getStudioApiUrl } from '@src/helpers/utils'; +import { getApiUrl, getStudioApiUrl } from '@src/data/utils'; export interface GetTeamMembersResponse { members: TeamMember[]; @@ -9,8 +9,8 @@ export interface GetTeamMembersResponse { } // TODO: replece api path once is created -export const getTeamMembers = async (libraryId: string): Promise => { - const { data } = await getAuthenticatedHttpClient().get(getApiUrl(`/api/authz/v1/roles/users?scope=${libraryId}`)); +export const getTeamMembers = async (object: string): Promise => { + const { data } = await getAuthenticatedHttpClient().get(getApiUrl(`/api/authz/v1/roles/users?scope=${object}`)); return camelCaseObject(data.results); }; diff --git a/src/authz-module/libraries-manager/data/hooks.test.tsx b/src/authz-module/data/hooks.test.tsx similarity index 100% rename from src/authz-module/libraries-manager/data/hooks.test.tsx rename to src/authz-module/data/hooks.test.tsx diff --git a/src/authz-module/libraries-manager/data/hooks.ts b/src/authz-module/data/hooks.ts similarity index 60% rename from src/authz-module/libraries-manager/data/hooks.ts rename to src/authz-module/data/hooks.ts index e9e8b07..1228b04 100644 --- a/src/authz-module/libraries-manager/data/hooks.ts +++ b/src/authz-module/data/hooks.ts @@ -1,26 +1,26 @@ import { useQuery, useSuspenseQuery } from '@tanstack/react-query'; -import { LibraryMetadata, TeamMember } from '@src/authz-module/constants'; +import { LibraryMetadata, TeamMember } from '@src/types'; import { getLibrary, getTeamMembers } from './api'; /** - * React Query hook to fetch all team members for a specific library. - * It retrieves the full list of members who have access to the given library. + * React Query hook to fetch all team members for a specific object/scope. + * It retrieves the full list of members who have access to the given scope. * - * @param libraryId - The unique identifier of the library + * @param object - The unique identifier of the object/scope * * @example * ```tsx * const { data: teamMembers, isLoading, isError } = useTeamMembers('lib:123'); * ``` */ -export const useTeamMembers = (libraryId: string) => useQuery({ - queryKey: ['team-members', libraryId], - queryFn: () => getTeamMembers(libraryId), +export const useTeamMembers = (object: string) => useQuery({ + queryKey: ['team-members', object], + queryFn: () => getTeamMembers(object), staleTime: 1000 * 60 * 30, // refetch after 30 minutes }); /** - * React Query hook to retrive the inforation of the current library. + * React Query hook to retrieve the information of the current library. * * @param libraryId - The unique ID of the library. * diff --git a/src/authz-module/libraries-manager/components/TeamTable.test.tsx b/src/authz-module/libraries-manager/components/TeamTable.test.tsx index d9cf678..434c048 100644 --- a/src/authz-module/libraries-manager/components/TeamTable.test.tsx +++ b/src/authz-module/libraries-manager/components/TeamTable.test.tsx @@ -3,7 +3,7 @@ import userEvent from '@testing-library/user-event'; import { ROUTES } from '@src/authz-module/constants'; import { renderWrapper } from '@src/setupTest'; import TeamTable from './TeamTable'; -import { useTeamMembers } from '../data/hooks'; +import { useTeamMembers } from '@src/authz-module/data/hooks'; import { useLibraryAuthZ } from '../context'; const mockNavigate = jest.fn(); @@ -12,7 +12,7 @@ jest.mock('react-router', () => ({ useNavigate: () => mockNavigate, })); -jest.mock('../data/hooks', () => ({ +jest.mock('@src/authz-module/data/hooks', () => ({ useTeamMembers: jest.fn(), })); diff --git a/src/authz-module/libraries-manager/components/TeamTable.tsx b/src/authz-module/libraries-manager/components/TeamTable.tsx index 48a7dad..a751123 100644 --- a/src/authz-module/libraries-manager/components/TeamTable.tsx +++ b/src/authz-module/libraries-manager/components/TeamTable.tsx @@ -5,8 +5,9 @@ import { DataTable, Button, Chip, Skeleton, } from '@openedx/paragon'; import { Edit } from '@openedx/paragon/icons'; -import { ROUTES, TableCellValue, TeamMember } from '@src/authz-module/constants'; -import { useTeamMembers } from '../data/hooks'; +import { TableCellValue, TeamMember } from '@src/types'; +import { ROUTES } from '@src/authz-module/constants'; +import { useTeamMembers } from '@src/authz-module/data/hooks'; import { useLibraryAuthZ } from '../context'; import messages from './messages'; diff --git a/src/authz-module/libraries-manager/context.test.tsx b/src/authz-module/libraries-manager/context.test.tsx index 6bfc719..8a3be4b 100644 --- a/src/authz-module/libraries-manager/context.test.tsx +++ b/src/authz-module/libraries-manager/context.test.tsx @@ -1,8 +1,8 @@ import { screen } from '@testing-library/react'; import { useParams } from 'react-router-dom'; -import { useValidateUserPermissions } from '@src/helpers/useValidateUserPermissions'; +import { useValidateUserPermissions } from '@src/data/hooks'; import { renderWrapper } from '@src/setupTest'; -import { useLibrary } from './data/hooks'; +import { useLibrary } from '../data/hooks'; import { LibraryAuthZProvider, useLibraryAuthZ } from './context'; jest.mock('react-router-dom', () => ({ @@ -10,11 +10,11 @@ jest.mock('react-router-dom', () => ({ useParams: jest.fn(), })); -jest.mock('@src/helpers/useValidateUserPermissions', () => ({ +jest.mock('@src/data/hooks', () => ({ useValidateUserPermissions: jest.fn(), })); -jest.mock('./data/hooks', () => ({ +jest.mock('../data/hooks', () => ({ useLibrary: jest.fn(), })); diff --git a/src/authz-module/libraries-manager/context.tsx b/src/authz-module/libraries-manager/context.tsx index 9fada0d..1eddb64 100644 --- a/src/authz-module/libraries-manager/context.tsx +++ b/src/authz-module/libraries-manager/context.tsx @@ -3,8 +3,8 @@ import { } from 'react'; import { useParams } from 'react-router-dom'; import { AppContext } from '@edx/frontend-platform/react'; -import { useValidateUserPermissions } from '@src/helpers/useValidateUserPermissions'; -import { useLibrary } from './data/hooks'; +import { useValidateUserPermissions } from '@src/data/hooks'; +import { useLibrary } from '../data/hooks'; const LIBRARY_TEAM_PERMISSIONS = ['act:view_library_team', 'act:manage_library_team']; diff --git a/src/components/LoadingPage.tsx b/src/components/LoadingPage.tsx index bba9389..bdcc6ea 100644 --- a/src/components/LoadingPage.tsx +++ b/src/components/LoadingPage.tsx @@ -1,14 +1,14 @@ import { Spinner, Container } from '@openedx/paragon'; -const LoadingPage= () => { +const LoadingPage = () => { return ( - + ); }; diff --git a/src/data/api.ts b/src/data/api.ts new file mode 100644 index 0000000..f35ebd8 --- /dev/null +++ b/src/data/api.ts @@ -0,0 +1,8 @@ +import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; +import { PermissionValidationRequest, PermissionValidationResponse } from '@src/types'; +import { getApiUrl } from './utils'; + +export const validateUserPermissions = async (validations: PermissionValidationRequest[]): Promise => { + const { data } = await getAuthenticatedHttpClient().post(getApiUrl(`/api/authz/v1/permissions/validate/me`), validations); + return data; +}; \ No newline at end of file diff --git a/src/helpers/useValidateUserPermissions.test.tsx b/src/data/hooks.test.tsx similarity index 97% rename from src/helpers/useValidateUserPermissions.test.tsx rename to src/data/hooks.test.tsx index c063c9b..799fc96 100644 --- a/src/helpers/useValidateUserPermissions.test.tsx +++ b/src/data/hooks.test.tsx @@ -1,8 +1,8 @@ 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'; +import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; +import { useValidateUserPermissions } from './hooks'; jest.mock('@edx/frontend-platform/auth', () => ({ getAuthenticatedHttpClient: jest.fn(), @@ -25,6 +25,7 @@ const createWrapper = () => { return wrapper; }; + const permissions = [ { action: 'act:read', @@ -51,7 +52,6 @@ describe('useValidateUserPermissions', () => { post: jest.fn().mockResolvedValueOnce({ data: mockValidPermissions }), }); - const { result } = renderHook(() => useValidateUserPermissions(permissions), { wrapper: createWrapper(), }); diff --git a/src/helpers/useValidateUserPermissions.ts b/src/data/hooks.ts similarity index 51% rename from src/helpers/useValidateUserPermissions.ts rename to src/data/hooks.ts index 9a09604..2ef03d9 100644 --- a/src/helpers/useValidateUserPermissions.ts +++ b/src/data/hooks.ts @@ -1,33 +1,17 @@ -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; -}; - +import { useSuspenseQuery } from '@tanstack/react-query'; +import { PermissionValidationRequest, PermissionValidationResponse } from '@src/types'; +import { validateUserPermissions } from './api'; /** * React Query hook to validate if the current user has permissions over a certain object in the instance. - * It helps to: + * 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([{ + * const { data } = userValidateUserPermissions([{ "action": "act:read", "object": "lib:test-lib", "scope": "org:OpenedX" @@ -41,4 +25,4 @@ export const useValidateUserPermissions = (permissions: PermissionValidationRequ queryFn: () => validateUserPermissions(permissions), retry: false, }); -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/helpers/utils.ts b/src/data/utils.ts similarity index 100% rename from src/helpers/utils.ts rename to src/data/utils.ts diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..f913d14 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,31 @@ +export interface PermissionValidationRequest { + action: string; + object?: string; + scope?: string; +}; + +export interface PermissionValidationResponse extends PermissionValidationRequest{ + allowed: boolean; +}; + +// Libraries AuthZ types +export interface TeamMember { + displayName: string; + username: string; + email: string; + roles: string[]; +} + +export interface LibraryMetadata { + id: string; + org: string; + title: string; + slug: string; +} + +// Paragon table type +export interface TableCellValue { + row: { + original: T; + }; +}