refactor: adding namespace to permissions (#37)

Updating namespaces to permissions to use name spaced identifiers by adding the content_libraries prefix.
This commit is contained in:
Jacobo Dominguez
2025-11-18 12:05:32 -06:00
committed by GitHub
parent 72dc951d36
commit a37491b0a5
8 changed files with 4493 additions and 131 deletions

View File

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

View File

@@ -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';
@@ -361,9 +361,11 @@ describe('AddNewTeamMemberTrigger', () => {
await user.click(saveButton);
// should now reflect isPending = true
const loadingIndicator = await screen.findByRole('status', { name: 'Adding team member loader' });
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(
{

View File

@@ -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();
@@ -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',
@@ -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',
@@ -66,7 +67,7 @@ describe('TeamTable', () => {
{
role: 'viewer',
permissions: [
'view_library',
CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY,
],
userCount: 3,
name: 'Viewer',

View File

@@ -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[] = [
@@ -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.' },
];

View File

@@ -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', () => ({
@@ -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 }> {
@@ -65,6 +60,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',

View File

@@ -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: {