style: fix linter issues and data location

This commit is contained in:
Diana Olarte
2025-09-26 15:24:06 +10:00
committed by Adolfo R. Brandes
parent 651ded21a7
commit 727bf74049
14 changed files with 78 additions and 75 deletions

View File

@@ -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<T> {
row: {
original: T;
};
}
export const ROUTES = {
LIBRARIES_TEAM_PATH: '/libraries/:libraryId',
LIBRARIES_USER_PATH: '/libraries/user/:username'

View File

@@ -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<TeamMember[]> => {
const { data } = await getAuthenticatedHttpClient().get(getApiUrl(`/api/authz/v1/roles/users?scope=${libraryId}`));
export const getTeamMembers = async (object: string): Promise<TeamMember[]> => {
const { data } = await getAuthenticatedHttpClient().get(getApiUrl(`/api/authz/v1/roles/users?scope=${object}`));
return camelCaseObject(data.results);
};

View File

@@ -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<TeamMember[], Error>({
queryKey: ['team-members', libraryId],
queryFn: () => getTeamMembers(libraryId),
export const useTeamMembers = (object: string) => useQuery<TeamMember[], Error>({
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.
*

View File

@@ -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(),
}));

View File

@@ -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';

View File

@@ -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(),
}));

View File

@@ -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'];

View File

@@ -1,14 +1,14 @@
import { Spinner, Container } from '@openedx/paragon';
const LoadingPage= () => {
const LoadingPage = () => {
return (
<Container className="d-flex vh-100" data-testid="loading-page">
<Spinner
variant="primary"
animation="border"
role="status"
className="mb-3 m-auto"
/>
<Spinner
variant="primary"
animation="border"
role="status"
className="mb-3 m-auto"
/>
</Container>
);
};

8
src/data/api.ts Normal file
View File

@@ -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<PermissionValidationResponse[]> => {
const { data } = await getAuthenticatedHttpClient().post(getApiUrl(`/api/authz/v1/permissions/validate/me`), validations);
return data;
};

View File

@@ -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(),
});

View File

@@ -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<PermissionValidationResponse[]> => {
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,
});
}
};

31
src/types.ts Normal file
View File

@@ -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<T> {
row: {
original: T;
};
}