Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4,463 changes: 2,379 additions & 2,084 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^14.6.1",
"@types/react": "^18",
"@types/react-dom": "^18"
"@types/react-dom": "^18",
"ts-jest": "^29.4.5"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useLibrary, useUpdateLibrary } from '@src/authz-module/data/hooks';
import { useLibraryAuthZ } from './context';
import LibrariesTeamManager from './LibrariesTeamManager';
import { ToastManagerProvider } from './ToastManagerContext';
import { CONTENT_LIBRARY_PERMISSIONS } from './constants';

jest.mock('./context', () => {
const actual = jest.requireActual('./context');
Expand Down Expand Up @@ -71,8 +72,8 @@ describe('LibrariesTeamManager', () => {
},
],
permissions: [
{ key: 'view_library', label: 'view', resource: 'library' },
{ key: 'edit_library', label: 'edit', resource: 'library' },
{ key: CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY, label: 'view', resource: 'library' },
{ key: CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_COLLECTION, label: 'edit', resource: 'library' },
],
resources: [{ key: 'library', label: 'Library' }],
canManageTeam: true,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { act } from 'react';
import { screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { renderWrapper } from '@src/setupTest';
Expand Down Expand Up @@ -360,9 +360,11 @@ describe('AddNewTeamMemberTrigger', () => {
await user.click(saveButton);

// should now reflect isPending = true
const loadingIndicator = await screen.findByTestId('loading-indicator');
expect(loadingIndicator).toBeInTheDocument();
expect(loadingIndicator).toHaveTextContent('Loading...');
act(async () => {
const loadingIndicator = await screen.findByRole('status', { name: 'Adding team member loader' });
expect(loadingIndicator).toBeInTheDocument();
expect(loadingIndicator).toHaveTextContent('Loading...');
});

expect(mutateMock).toHaveBeenCalledWith(
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { renderWrapper } from '@src/setupTest';
import { useTeamMembers } from '@src/authz-module/data/hooks';
import { useLibraryAuthZ } from '@src/authz-module/libraries-manager/context';
import { ToastManagerProvider } from '@src/authz-module/libraries-manager/ToastManagerContext';
import { CONTENT_LIBRARY_PERMISSIONS } from '@src/authz-module/libraries-manager/constants';
import TeamTable from './index';

const mockNavigate = jest.fn();
Expand Down Expand Up @@ -45,9 +46,9 @@ describe('TeamTable', () => {
{
role: 'admin',
permissions: [
'delete_library',
'publish_library',
'manage_library_team',
CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY,
CONTENT_LIBRARY_PERMISSIONS.PUBLISH_LIBRARY_CONTENT,
CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TEAM,
],
userCount: 3,
name: 'Admin',
Expand All @@ -56,8 +57,8 @@ describe('TeamTable', () => {
{
role: 'editor',
permissions: [
'edit_library',
'publish_library',
CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_CONTENT,
CONTENT_LIBRARY_PERMISSIONS.PUBLISH_LIBRARY_CONTENT,
],
userCount: 3,
name: 'Editor',
Expand All @@ -66,7 +67,7 @@ describe('TeamTable', () => {
{
role: 'viewer',
permissions: [
'view_library',
CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY,
],
userCount: 3,
name: 'Viewer',
Expand Down
39 changes: 28 additions & 11 deletions src/authz-module/libraries-manager/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
import { PermissionMetadata, ResourceMetadata, RoleMetadata } from 'types';

export const CONTENT_LIBRARY_PERMISSIONS = {
DELETE_LIBRARY: 'content_libraries.delete_library',
MANAGE_LIBRARY_TAGS: 'content_libraries.manage_library_tags',
VIEW_LIBRARY: 'content_libraries.view_library',

EDIT_LIBRARY_CONTENT: 'content_libraries.edit_library_content',
PUBLISH_LIBRARY_CONTENT: 'content_libraries.publish_library_content',
REUSE_LIBRARY_CONTENT: 'content_libraries.reuse_library_content',

CREATE_LIBRARY_COLLECTION: 'content_libraries.create_library_collection',
EDIT_LIBRARY_COLLECTION: 'content_libraries.edit_library_collection',
DELETE_LIBRARY_COLLECTION: 'content_libraries.delete_library_collection',

MANAGE_LIBRARY_TEAM: 'content_libraries.manage_library_team',
VIEW_LIBRARY_TEAM: 'content_libraries.view_library_team',
};

// Note: this information will eventually come from the backend API
// but for the MVP we decided to manage it in the frontend
export const libraryRolesMetadata: RoleMetadata[] = [
Expand All @@ -17,18 +34,18 @@ export const libraryResourceTypes: ResourceMetadata[] = [
];

export const libraryPermissions: PermissionMetadata[] = [
{ key: 'delete_library', resource: 'library', description: 'Allows the user to delete the library and all its contents.' },
{ key: 'manage_library_tags', resource: 'library', description: 'Add or remove tags from content.' },
{ key: 'view_library', resource: 'library', description: 'View content, search, filter, and sort within the library.' },
{ key: CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY, resource: 'library', description: 'Allows the user to delete the library and all its contents.' },
{ key: CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TAGS, resource: 'library', description: 'Add or remove tags from content.' },
{ key: CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY, resource: 'library', description: 'View content, search, filter, and sort within the library.' },

{ key: 'edit_library_content', resource: 'library_content', description: 'Edit content in draft mode' },
{ key: 'publish_library_content', resource: 'library_content', description: 'Publish content, making it available for reuse' },
{ key: 'reuse_library_content', resource: 'library_content', description: 'Reuse published content within a course.' },
{ key: CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_CONTENT, resource: 'library_content', description: 'Edit content in draft mode' },
{ key: CONTENT_LIBRARY_PERMISSIONS.PUBLISH_LIBRARY_CONTENT, resource: 'library_content', description: 'Publish content, making it available for reuse' },
{ key: CONTENT_LIBRARY_PERMISSIONS.REUSE_LIBRARY_CONTENT, resource: 'library_content', description: 'Reuse published content within a course.' },

{ key: 'create_library_collection', resource: 'library_collection', description: 'Create new collections within a library.' },
{ key: 'edit_library_collection', resource: 'library_collection', description: 'Add or remove content from existing collections.' },
{ key: 'delete_library_collection', resource: 'library_collection', description: 'Delete entire collections from the library.' },
{ key: CONTENT_LIBRARY_PERMISSIONS.CREATE_LIBRARY_COLLECTION, resource: 'library_collection', description: 'Create new collections within a library.' },
{ key: CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_COLLECTION, resource: 'library_collection', description: 'Add or remove content from existing collections.' },
{ key: CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY_COLLECTION, resource: 'library_collection', description: 'Delete entire collections from the library.' },

{ key: 'manage_library_team', resource: 'library_team', description: 'View the list of users who have access to the library.' },
{ key: 'view_library_team', resource: 'library_team', description: 'Add, remove, and assign roles to users within the library.' },
{ key: CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TEAM, resource: 'library_team', description: 'View the list of users who have access to the library.' },
{ key: CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY_TEAM, resource: 'library_team', description: 'Add, remove, and assign roles to users within the library.' },
];
21 changes: 12 additions & 9 deletions src/authz-module/libraries-manager/context.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useValidateUserPermissions } from '@src/data/hooks';
import { renderWrapper } from '@src/setupTest';
import { usePermissionsByRole } from '@src/authz-module/data/hooks';
import { CustomErrors } from '@src/constants';
import { CONTENT_LIBRARY_PERMISSIONS } from './constants';
import { LibraryAuthZProvider, useLibraryAuthZ } from './context';

jest.mock('react-router-dom', () => ({
Expand All @@ -15,16 +16,10 @@ jest.mock('react-router-dom', () => ({
jest.mock('@src/data/hooks', () => ({
useValidateUserPermissions: jest.fn(),
}));

// Move the mock after imports and use actual values
jest.mock('@src/authz-module/data/hooks', () => ({
usePermissionsByRole: jest.fn().mockReturnValue({
data: [
{
role: 'library_author',
permissions: ['view_library_team', 'edit_library'],
user_count: 12,
},
],
}),
usePermissionsByRole: jest.fn(),
}));

class ErrorBoundary extends Component<{ children: ReactNode }, { hasError: boolean; error?: Error }> {
Expand Down Expand Up @@ -67,6 +62,14 @@ describe('LibraryAuthZProvider', () => {
(useParams as jest.Mock).mockReturnValue({ libraryId: 'lib123' });
(usePermissionsByRole as jest.Mock).mockReturnValue({
data: [
{
role: 'library_author',
permissions: [
CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY_TEAM,
CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_CONTENT,
],
user_count: 12,
},
{
role: 'instructor',
description: 'Can create and edit content',
Expand Down
9 changes: 7 additions & 2 deletions src/authz-module/libraries-manager/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@ import { useValidateUserPermissions } from '@src/data/hooks';
import { usePermissionsByRole } from '@src/authz-module/data/hooks';
import { PermissionMetadata, ResourceMetadata, Role } from 'types';
import { CustomErrors } from '@src/constants';
import { libraryPermissions, libraryResourceTypes, libraryRolesMetadata } from './constants';
import {
CONTENT_LIBRARY_PERMISSIONS, libraryPermissions, libraryResourceTypes, libraryRolesMetadata,
} from './constants';

const LIBRARY_TEAM_PERMISSIONS = ['view_library_team', 'manage_library_team'];
const LIBRARY_TEAM_PERMISSIONS = [
CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY_TEAM,
CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TEAM,
];

export type AppContextType = {
authenticatedUser: {
Expand Down