diff --git a/src/authz-module/components/UserPermissions.test.tsx b/src/authz-module/components/UserPermissions.test.tsx index fac0fa65..c8fb5598 100644 --- a/src/authz-module/components/UserPermissions.test.tsx +++ b/src/authz-module/components/UserPermissions.test.tsx @@ -1,3 +1,4 @@ +import { screen } from '@testing-library/react'; import { initializeMockApp } from '@edx/frontend-platform/testing'; import { renderWrapper } from '@src/setupTest'; import * as coursesConstants from '@src/authz-module/roles-permissions'; @@ -52,6 +53,30 @@ describe('UserPermissions', () => { expect(container.querySelector('.d-flex')).toBeInTheDocument(); }); + it('renders library role permissions with their metadata labels', () => { + const props = { + row: { + original: { + role: 'library_admin', + }, + }, + }; + + const { container } = renderWrapper(); + + // Resource group headers from libraryResourceTypes + expect(screen.getByText('Library')).toBeInTheDocument(); + expect(screen.getByText('Team')).toBeInTheDocument(); + // Explicit labels from the permission metadata + expect(screen.getAllByText('Manage tags').length).toBeGreaterThan(0); + expect(screen.getAllByText('Publish').length).toBeGreaterThan(0); + expect(screen.getAllByText('Reuse').length).toBeGreaterThan(0); + // No permission renders with an empty label + const labels = Array.from(container.querySelectorAll('li span.font-weight-light')); + expect(labels.length).toBeGreaterThan(0); + labels.forEach((label) => expect(label.textContent?.trim()).not.toBe('')); + }); + it('returns null when role is empty', () => { const props = { row: { @@ -87,8 +112,8 @@ describe('UserPermissions', () => { }, ]; - const originalRolesObject = coursesConstants.rolesObject; - const rolesObjectSpy = jest.spyOn(coursesConstants, 'rolesObject', 'get') + const originalRolesObject = coursesConstants.courseRolesWithPermissions; + const courseRolesWithPermissionsSpy = jest.spyOn(coursesConstants, 'courseRolesWithPermissions', 'get') .mockReturnValue([...originalRolesObject, ...mockRoleObject] as typeof originalRolesObject); const props = { @@ -101,10 +126,10 @@ describe('UserPermissions', () => { const { getByTestId } = renderWrapper(); expect(getByTestId('render-permission-inline')).toBeInTheDocument(); - rolesObjectSpy.mockRestore(); + courseRolesWithPermissionsSpy.mockRestore(); }); - it('returns null when role is not found in rolesObject (line 52 coverage)', () => { + it('returns null when role is not found in courseRolesWithPermissions (line 52 coverage)', () => { const props = { row: { original: { diff --git a/src/authz-module/components/UserPermissions.tsx b/src/authz-module/components/UserPermissions.tsx index 468b5a5e..efa56be4 100644 --- a/src/authz-module/components/UserPermissions.tsx +++ b/src/authz-module/components/UserPermissions.tsx @@ -1,13 +1,14 @@ +import { useIntl } from '@edx/frontend-platform/i18n'; import { DJANGO_MANAGED_ROLES } from '@src/authz-module/constants'; import { courseResourceTypes, coursePermissions, - rolesObject, + courseRolesWithPermissions, libraryResourceTypes, libraryPermissions, - rolesLibraryObject, + libraryRolesWithPermissions, + getPermissionMetadata, } from '@src/authz-module/roles-permissions'; -import { PermissionItem } from '@src/types'; import RenderPermissionColumn from './RenderPermissionColumn'; import RenderPermissionInLine from './RenderPermissionInLine'; import RenderAdminRole from './RenderAdminRole'; @@ -21,6 +22,7 @@ interface UserPermissionsProps { } const UserPermissions = ({ row }: UserPermissionsProps) => { + const intl = useIntl(); let roleKey = row?.original?.role; if (!roleKey) { return null; } @@ -39,27 +41,29 @@ const UserPermissions = ({ row }: UserPermissionsProps) => { ? { resourceTypes: libraryResourceTypes, permissions: libraryPermissions, - roles: rolesLibraryObject, + roles: libraryRolesWithPermissions, } : { resourceTypes: courseResourceTypes, permissions: coursePermissions, - roles: rolesObject, + roles: courseRolesWithPermissions, }; const roleObj = config.roles.find(r => r.role === roleKey); if (!roleObj) { return null; } const rolePerms = new Set(roleObj.permissions.map(String)); - // Build resource list with permissions (only once) + // Build resource list with permissions (only once). Permissions without an + // explicit label (most library ones) get a localized label derived from + // their action key, the same enrichment the permissions matrix uses. const resources = config.resourceTypes .map(resource => { - const perms = config.permissions.filter( - p => p.resource === resource.key && rolePerms.has(String(p.key)), - ); + const perms = config.permissions + .filter(p => p.resource === resource.key && rolePerms.has(String(p.key))) + .map(p => getPermissionMetadata(p, intl)); return perms.length ? { ...resource, perms } : null; }) - .filter((r): r is PermissionItem => r !== null); + .filter((r): r is NonNullable => r !== null); const isSingleRow = resources.length <= 3; const mid = Math.ceil(resources.length / 2); diff --git a/src/authz-module/roles-permissions/RolesPermissions.test.tsx b/src/authz-module/roles-permissions/RolesPermissions.test.tsx index a29fa0ae..760c791a 100644 --- a/src/authz-module/roles-permissions/RolesPermissions.test.tsx +++ b/src/authz-module/roles-permissions/RolesPermissions.test.tsx @@ -5,7 +5,7 @@ import { renderWrapper } from '@src/setupTest'; import RolesPermissions from './RolesPermissions'; // Mock utils -jest.mock('./library/utils', () => ({ +jest.mock('./utils', () => ({ buildPermissionMatrixByResource: jest.fn(() => [ { key: 'test-resource', @@ -18,23 +18,25 @@ jest.mock('./library/utils', () => ({ // Mock constants jest.mock('./course/constants', () => ({ - rolesObject: [ + courseRolesWithPermissions: [ { name: 'Course Admin', role: 'admin', permissions: [], userCount: 1, }, ], coursePermissions: [], courseResourceTypes: [], + courseRolesMetadata: [], })); jest.mock('./library/constants', () => ({ - rolesLibraryObject: [ + libraryRolesWithPermissions: [ { name: 'Library Admin', role: 'admin', permissions: [], userCount: 1, }, ], libraryPermissions: [], libraryResourceTypes: [], + libraryRolesMetadata: [], })); jest.mock('@openedx/paragon', () => ({ diff --git a/src/authz-module/roles-permissions/RolesPermissions.tsx b/src/authz-module/roles-permissions/RolesPermissions.tsx index eff45521..bd84765a 100644 --- a/src/authz-module/roles-permissions/RolesPermissions.tsx +++ b/src/authz-module/roles-permissions/RolesPermissions.tsx @@ -10,17 +10,17 @@ import { import { coursePermissions, courseResourceTypes, - rolesObject, - rolesLibraryObject, + courseRolesWithPermissions, + libraryRolesWithPermissions, libraryPermissions, libraryResourceTypes, } from '@src/authz-module/roles-permissions'; import AnchorButton from '../components/AnchorButton'; import PermissionTable from '../components/PermissionTable'; -import { buildPermissionMatrixByResource } from './library/utils'; +import { buildPermissionMatrixByResource } from './utils'; -import messages from './library/messages'; +import messages from './messages'; const RolesPermissions = () => { const intl = useIntl(); @@ -28,7 +28,7 @@ const RolesPermissions = () => { const libraryPermissionsByResource = useMemo(() => { const permissionsByResource = buildPermissionMatrixByResource({ - roles: rolesLibraryObject, + roles: libraryRolesWithPermissions, permissions: libraryPermissions, resources: libraryResourceTypes, intl, @@ -39,7 +39,7 @@ const RolesPermissions = () => { const coursePermissionsByResource = useMemo(() => { const permissionsByResource = buildPermissionMatrixByResource({ - roles: rolesObject, + roles: courseRolesWithPermissions, permissions: coursePermissions, resources: courseResourceTypes, intl, @@ -56,13 +56,13 @@ const RolesPermissions = () => { onClick={() => setActive('courses')} variant={`${active === 'courses' ? 'primary' : 'outline-primary'}`} > - {intl.formatMessage(messages['library.authz.tabs.permissionsRoles.courses.tab']) } + {intl.formatMessage(messages['authz.tabs.permissionsRoles.courses.tab']) } @@ -71,8 +71,8 @@ const RolesPermissions = () => {
{ >
-

{intl.formatMessage(messages['library.authz.tabs.permissionsRoles.courses.alert.title'])}

+

{intl.formatMessage(messages['authz.tabs.permissionsRoles.courses.alert.title'])}

- {intl.formatMessage(messages['library.authz.tabs.permissionsRoles.courses.alert.note'])} - {intl.formatMessage(messages['library.authz.tabs.permissionsRoles.courses.alert.description'])} + {intl.formatMessage(messages['authz.tabs.permissionsRoles.courses.alert.note'])} + {intl.formatMessage(messages['authz.tabs.permissionsRoles.courses.alert.description'])}
- {intl.formatMessage(messages['library.authz.tabs.permissionsRoles.courses.alert.link'])} + {intl.formatMessage(messages['authz.tabs.permissionsRoles.courses.alert.link'])}
@@ -99,8 +99,8 @@ const RolesPermissions = () => { { active === 'libraries' && ( )} diff --git a/src/authz-module/roles-permissions/course/constants.ts b/src/authz-module/roles-permissions/course/constants.ts index 964fe391..219a95e5 100644 --- a/src/authz-module/roles-permissions/course/constants.ts +++ b/src/authz-module/roles-permissions/course/constants.ts @@ -67,42 +67,77 @@ export const CONTENT_COURSE_PERMISSIONS = { export const courseResourceTypes: ResourceMetadata[] = [ { - key: 'course_access_content', label: 'Course Access & content', description: 'Permissions related to accessing the course and managing core course content, including creating, editing, and publishing materials.', icon: BookOpen, + key: 'course_access_content', + label: 'Course Access & content', + description: 'Permissions related to accessing the course and managing core course content, including creating, editing, and publishing materials.', + icon: BookOpen, }, { - key: 'course_library_updates', label: 'Library updates', description: 'Permissions for reviewing and managing updates made to content libraries connected to the course.', icon: LibraryBooks, + key: 'course_library_updates', + label: 'Library updates', + description: 'Permissions for reviewing and managing updates made to content libraries connected to the course.', + icon: LibraryBooks, }, { - key: 'course_updates_handouts', label: 'Course updates & handouts', description: 'Permissions for viewing and managing course updates and handouts that are visible to learners.', icon: Sync, + key: 'course_updates_handouts', + label: 'Course updates & handouts', + description: 'Permissions for viewing and managing course updates and handouts that are visible to learners.', + icon: Sync, }, { - key: 'course_pages_resources', label: 'Pages & resources', description: 'Permissions for viewing and managing course pages and additional learning resources.', icon: Article, + key: 'course_pages_resources', + label: 'Pages & resources', + description: 'Permissions for viewing and managing course pages and additional learning resources.', + icon: Article, }, { - key: 'course_files', label: 'Files', description: 'Permissions for viewing and managing course pages and additional learning resources.', icon: Folder, + key: 'course_files', + label: 'Files', + description: 'Permissions for viewing and managing course pages and additional learning resources.', + icon: Folder, }, { - key: 'course_schedule_details', label: 'Schedule & details', description: 'Permissions for viewing and editing the course schedule and course information.', icon: Calendar, + key: 'course_schedule_details', + label: 'Schedule & details', + description: 'Permissions for viewing and editing the course schedule and course information.', + icon: Calendar, }, { - key: 'course_grading', label: 'Grading', description: 'Permissions related to viewing and managing grading configuration and grading policies.', icon: Award, + key: 'course_grading', + label: 'Grading', + description: 'Permissions related to viewing and managing grading configuration and grading policies.', + icon: Award, }, { - key: 'course_team_group', label: 'Course team & groups', description: 'Permissions for viewing and managing the course team, learner groups, and group configurations.', icon: Group, + key: 'course_team_group', + label: 'Course team & groups', + description: 'Permissions for viewing and managing the course team, learner groups, and group configurations.', + icon: Group, }, { - key: 'course_tags_taxonomies', label: 'Tags', description: 'Permissions for managing tags used to organize course content.', icon: LocalOffer, + key: 'course_tags_taxonomies', + label: 'Tags', + description: 'Permissions for managing tags used to organize course content.', + icon: LocalOffer, }, { - key: 'course_advanced_certificates', label: 'Advanced & certificates', description: 'Permissions for managing advanced course settings and course certificates.', icon: CheckCircle, + key: 'course_advanced_certificates', + label: 'Advanced & certificates', + description: 'Permissions for managing advanced course settings and course certificates.', + icon: CheckCircle, }, { - key: 'course_import_export', label: 'Import / export', description: 'Permissions for importing and exporting course content and related data.', icon: Download, + key: 'course_import_export', + label: 'Import / export', + description: 'Permissions for importing and exporting course content and related data.', + icon: Download, }, { - key: 'course_other', label: 'Other', description: 'Additional permissions not included in other categories, such as viewing checklists and platform-level course roles.', icon: DrawShapes, + key: 'course_other', + label: 'Other', + description: 'Additional permissions not included in other categories, such as viewing checklists and platform-level course roles.', + icon: DrawShapes, }, - ]; export const coursePermissions: PermissionMetadata[] = [ @@ -329,150 +364,136 @@ export const coursePermissions: PermissionMetadata[] = [ }, ]; -// roles hardcoded, todo: need to add the constants from above in order to merge the different permissions array. -export const rolesObject: Role[] = [ +export const courseRolesMetadata: RoleMetadata[] = [ { role: 'course_admin', - contextType: 'course', - scope: '', - permissions: [ - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_UPDATES, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_PAGES_RESOURCES, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_FILES, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_GRADING_SETTINGS, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_CHECKLISTS, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_GLOBAL_STAFF_SUPER_ADMINS, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_TEAM, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_SCHEDULE, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_DETAILS, - CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_CONTENT, - CONTENT_COURSE_PERMISSIONS.REVIEW_COURSE_LIBRARY_UPDATES, - CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_UPDATES, - CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_PAGES_RESOURCES, - CONTENT_COURSE_PERMISSIONS.CREATE_COURSE_FILES, - CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_FILES, - CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_GRADING_SETTINGS, - CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_GROUP_CONFIGURATION, - CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_DETAILS, - CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_TAGS, - CONTENT_COURSE_PERMISSIONS.PUBLISH_COURSE_CONTENT, - CONTENT_COURSE_PERMISSIONS.DELETE_COURSE_FILES, - CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_SCHEDULE, - CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_ADVANCED_SETTINGS, - CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_CERTIFICATES, - CONTENT_COURSE_PERMISSIONS.IMPORT_COURSE, - CONTENT_COURSE_PERMISSIONS.EXPORT_COURSE, - CONTENT_COURSE_PERMISSIONS.EXPORT_COURSE_TAGS, - CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_TEAM, - ], - userCount: 1, name: 'Course Admin', - description: 'course level administration, including access and role management for the course team, plus all Staff capabilities.', + description: 'Can manage the course team and all course settings.', + contextType: 'course', }, - { role: 'course_staff', - contextType: 'course', - scope: '', - permissions: [ - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_UPDATES, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_PAGES_RESOURCES, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_FILES, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_GRADING_SETTINGS, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_CHECKLISTS, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_GLOBAL_STAFF_SUPER_ADMINS, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_TEAM, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_SCHEDULE, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_DETAILS, - CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_CONTENT, - CONTENT_COURSE_PERMISSIONS.REVIEW_COURSE_LIBRARY_UPDATES, - CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_UPDATES, - CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_PAGES_RESOURCES, - CONTENT_COURSE_PERMISSIONS.CREATE_COURSE_FILES, - CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_FILES, - CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_GRADING_SETTINGS, - CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_GROUP_CONFIGURATION, - CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_DETAILS, - CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_TAGS, - CONTENT_COURSE_PERMISSIONS.PUBLISH_COURSE_CONTENT, - CONTENT_COURSE_PERMISSIONS.DELETE_COURSE_FILES, - CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_SCHEDULE, - CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_ADVANCED_SETTINGS, - CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_CERTIFICATES, - CONTENT_COURSE_PERMISSIONS.IMPORT_COURSE, - CONTENT_COURSE_PERMISSIONS.EXPORT_COURSE, - CONTENT_COURSE_PERMISSIONS.EXPORT_COURSE_TAGS, - ], - userCount: 1, name: 'Course Staff', - description: 'operating the course lifecycle in Studio, publishing content, handling scheduling, and managing high impact configuration for the course.', + description: 'Can publish content and manage the course lifecycle in Studio.', + contextType: 'course', }, { role: 'course_editor', - contextType: 'course', - scope: '', - permissions: [ - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_UPDATES, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_PAGES_RESOURCES, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_FILES, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_GRADING_SETTINGS, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_CHECKLISTS, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_GLOBAL_STAFF_SUPER_ADMINS, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_TEAM, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_SCHEDULE, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_DETAILS, - CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_CONTENT, - CONTENT_COURSE_PERMISSIONS.REVIEW_COURSE_LIBRARY_UPDATES, - CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_UPDATES, - CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_PAGES_RESOURCES, - CONTENT_COURSE_PERMISSIONS.CREATE_COURSE_FILES, - CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_FILES, - CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_GRADING_SETTINGS, - CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_GROUP_CONFIGURATION, - CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_DETAILS, - CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_TAGS, - ], - userCount: 1, name: 'Course Editor', - description: 'building and maintaining course content and supporting assets, without operational controls or high impact actions that can affect a live course.', + description: 'Can create and edit course content, but cannot publish or change critical course settings.', + contextType: 'course', disabled: true, }, { role: 'course_auditor', - contextType: 'course', - scope: '', - permissions: [ - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_UPDATES, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_PAGES_RESOURCES, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_FILES, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_GRADING_SETTINGS, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_CHECKLISTS, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_TEAM, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_SCHEDULE, - CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_DETAILS, - ], - userCount: 1, name: 'Course Auditor', - description: ' QA, compliance review, content review, and general oversight, no changes in Studio.', + description: 'Can view course content and settings, but cannot make changes.', + contextType: 'course', disabled: true, }, - -]; -export const courseRolesMetadata: RoleMetadata[] = [ - { - role: 'course_admin', name: 'Course Admin', description: 'Can manage the course team and all course settings.', contextType: 'course', - }, - { - role: 'course_staff', name: 'Course Staff', description: 'Can publish content and manage the course lifecycle in Studio.', contextType: 'course', - }, - { - role: 'course_editor', name: 'Course Editor', description: 'Can create and edit course content, but cannot publish or change critical course settings.', contextType: 'course', disabled: true, - }, - { - role: 'course_auditor', name: 'Course Auditor', description: 'Can view course content and settings, but cannot make changes.', contextType: 'course', disabled: true, - }, ]; + +// Permission keys granted to each course role. +const COURSE_ROLE_PERMISSIONS: Record = { + course_admin: [ + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_UPDATES, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_PAGES_RESOURCES, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_FILES, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_GRADING_SETTINGS, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_CHECKLISTS, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_GLOBAL_STAFF_SUPER_ADMINS, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_TEAM, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_SCHEDULE, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_DETAILS, + CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_CONTENT, + CONTENT_COURSE_PERMISSIONS.REVIEW_COURSE_LIBRARY_UPDATES, + CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_UPDATES, + CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_PAGES_RESOURCES, + CONTENT_COURSE_PERMISSIONS.CREATE_COURSE_FILES, + CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_FILES, + CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_GRADING_SETTINGS, + CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_GROUP_CONFIGURATION, + CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_DETAILS, + CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_TAGS, + CONTENT_COURSE_PERMISSIONS.PUBLISH_COURSE_CONTENT, + CONTENT_COURSE_PERMISSIONS.DELETE_COURSE_FILES, + CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_SCHEDULE, + CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_ADVANCED_SETTINGS, + CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_CERTIFICATES, + CONTENT_COURSE_PERMISSIONS.IMPORT_COURSE, + CONTENT_COURSE_PERMISSIONS.EXPORT_COURSE, + CONTENT_COURSE_PERMISSIONS.EXPORT_COURSE_TAGS, + CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_TEAM, + ], + course_staff: [ + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_UPDATES, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_PAGES_RESOURCES, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_FILES, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_GRADING_SETTINGS, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_CHECKLISTS, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_GLOBAL_STAFF_SUPER_ADMINS, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_TEAM, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_SCHEDULE, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_DETAILS, + CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_CONTENT, + CONTENT_COURSE_PERMISSIONS.REVIEW_COURSE_LIBRARY_UPDATES, + CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_UPDATES, + CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_PAGES_RESOURCES, + CONTENT_COURSE_PERMISSIONS.CREATE_COURSE_FILES, + CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_FILES, + CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_GRADING_SETTINGS, + CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_GROUP_CONFIGURATION, + CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_DETAILS, + CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_TAGS, + CONTENT_COURSE_PERMISSIONS.PUBLISH_COURSE_CONTENT, + CONTENT_COURSE_PERMISSIONS.DELETE_COURSE_FILES, + CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_SCHEDULE, + CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_ADVANCED_SETTINGS, + CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_CERTIFICATES, + CONTENT_COURSE_PERMISSIONS.IMPORT_COURSE, + CONTENT_COURSE_PERMISSIONS.EXPORT_COURSE, + CONTENT_COURSE_PERMISSIONS.EXPORT_COURSE_TAGS, + ], + course_editor: [ + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_UPDATES, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_PAGES_RESOURCES, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_FILES, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_GRADING_SETTINGS, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_CHECKLISTS, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_GLOBAL_STAFF_SUPER_ADMINS, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_TEAM, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_SCHEDULE, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_DETAILS, + CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_CONTENT, + CONTENT_COURSE_PERMISSIONS.REVIEW_COURSE_LIBRARY_UPDATES, + CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_UPDATES, + CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_PAGES_RESOURCES, + CONTENT_COURSE_PERMISSIONS.CREATE_COURSE_FILES, + CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_FILES, + CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_GRADING_SETTINGS, + CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_GROUP_CONFIGURATION, + CONTENT_COURSE_PERMISSIONS.EDIT_COURSE_DETAILS, + CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_TAGS, + ], + course_auditor: [ + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_UPDATES, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_PAGES_RESOURCES, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_FILES, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_GRADING_SETTINGS, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_CHECKLISTS, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_TEAM, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_SCHEDULE, + CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_DETAILS, + ], +}; + +export const courseRolesWithPermissions: Role[] = courseRolesMetadata.map((meta) => ({ + ...meta, + scope: '', + userCount: 1, + permissions: COURSE_ROLE_PERMISSIONS[meta.role] ?? [], +})); diff --git a/src/authz-module/roles-permissions/index.ts b/src/authz-module/roles-permissions/index.ts index 690fa56a..c8273c33 100644 --- a/src/authz-module/roles-permissions/index.ts +++ b/src/authz-module/roles-permissions/index.ts @@ -3,13 +3,15 @@ export { libraryResourceTypes, libraryPermissions, libraryRolesMetadata, - rolesLibraryObject, + libraryRolesWithPermissions, } from './library/constants'; export { CONTENT_COURSE_PERMISSIONS, courseResourceTypes, coursePermissions, - rolesObject, + courseRolesWithPermissions, courseRolesMetadata, } from './course/constants'; + +export { buildPermissionMatrixByResource, getPermissionMetadata } from './utils'; diff --git a/src/authz-module/roles-permissions/library/constants.ts b/src/authz-module/roles-permissions/library/constants.ts index c03e53d7..0a5c121f 100644 --- a/src/authz-module/roles-permissions/library/constants.ts +++ b/src/authz-module/roles-permissions/library/constants.ts @@ -37,159 +37,213 @@ export const CONTENT_LIBRARY_PERMISSIONS = { // but for the MVP we decided to manage it in the frontend export const libraryRolesMetadata: RoleMetadata[] = [ { - role: 'library_admin', name: 'Library Admin', description: 'The Library Admin has full control over the library, including managing users, modifying content, and handling publishing workflows. They ensure content is properly maintained and accessible as needed.', contextType: 'library', + role: 'library_admin', + name: 'Library Admin', + description: 'The Library Admin has full control over the library, including managing users, modifying content, and handling publishing workflows. They ensure content is properly maintained and accessible as needed.', + contextType: 'library', }, { - role: 'library_author', name: 'Library Author', description: 'The Library Author is responsible for creating, editing, and publishing content within a library. They can manage tags and collections but cannot delete libraries or manage users.', contextType: 'library', + role: 'library_author', + name: 'Library Author', + description: 'The Library Author is responsible for creating, editing, and publishing content within a library. They can manage tags and collections but cannot delete libraries or manage users.', + contextType: 'library', }, { - role: 'library_contributor', name: 'Library Contributor', description: 'The Library Contributor can create and edit content within a library but cannot publish it. They support the authoring process while leaving final publishing to Authors or Admins.', contextType: 'library', + role: 'library_contributor', + name: 'Library Contributor', + description: 'The Library Contributor can create and edit content within a library but cannot publish it. They support the authoring process while leaving final publishing to Authors or Admins.', + contextType: 'library', }, { - role: 'library_user', name: 'Library User', description: 'The Library User can view and reuse content but cannot edit or delete any resource.', contextType: 'library', + role: 'library_user', + name: 'Library User', + description: 'The Library User can view and reuse content but cannot edit or delete any resource.', + contextType: 'library', }, ]; export const libraryResourceTypes: ResourceMetadata[] = [ { - key: 'library', label: 'Library', description: 'Permissions related to viewing, managing, and publishing the library structure and metadata.', icon: CollectionsBookmark, + key: 'library', + label: 'Library', + description: 'Permissions related to viewing, managing, and publishing the library structure and metadata.', + icon: CollectionsBookmark, }, { - key: 'library_content', label: 'Content', description: 'Permissions for creating, editing, deleting, and publishing content within the library.', icon: Notes, + key: 'library_content', + label: 'Content', + description: 'Permissions for creating, editing, deleting, and publishing content within the library.', + icon: Notes, }, { - key: 'library_team', label: 'Team', description: 'Permissions for viewing and managing users who have access to the library.', icon: Group, + key: 'library_team', + label: 'Team', + description: 'Permissions for viewing and managing users who have access to the library.', + icon: Group, }, { - key: 'library_collection', label: 'Collection', description: 'Permissions for creating and managing content collections within the library.', icon: AutoAwesomeMosaic, + key: 'library_collection', + label: 'Collection', + description: 'Permissions for creating and managing content collections within the library.', + icon: AutoAwesomeMosaic, }, ]; export const libraryPermissions: PermissionMetadata[] = [ { - key: CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY, resource: 'library', label: 'View', description: 'See the library in Studio and access its content in read-only mode.', icon: RemoveRedEye, + key: CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY, + resource: 'library', + label: 'View', + description: 'See the library in Studio and access its content in read-only mode.', + icon: RemoveRedEye, }, { - key: CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TAGS, resource: 'library', label: 'Manage tag', description: 'Create, edit, and delete tags on this library.', icon: Settings, + key: CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TAGS, + resource: 'library', + label: 'Manage tags', + description: 'Create, edit, and delete tags on this library.', + icon: Settings, }, { - key: CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY, resource: 'library', label: 'Publish', description: 'Publish the library to make it available for use in courses.', icon: DownloadDone, + key: CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY, + resource: 'library', + label: 'Delete', + description: 'Allows users to delete the entire content library.', + icon: Delete, }, { - key: CONTENT_LIBRARY_PERMISSIONS.CREATE_LIBRARY_CONTENT, resource: 'library_content', label: 'Create', description: 'Create new content items in the library.', icon: Plus, + key: CONTENT_LIBRARY_PERMISSIONS.CREATE_LIBRARY_CONTENT, + resource: 'library_content', + label: 'Create', + description: 'Create new content items in the library.', + icon: Plus, }, { - key: CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_CONTENT, resource: 'library_content', label: 'Edit', description: 'Edit existing content items in the library.', icon: EditOutline, + key: CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_CONTENT, + resource: 'library_content', + label: 'Edit', + description: 'Edit existing content items in the library.', + icon: EditOutline, }, { - key: CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY_CONTENT, resource: 'library_content', label: 'Delete', description: 'Permanently remove content items from the library.', icon: Delete, + key: CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY_CONTENT, + resource: 'library_content', + label: 'Delete', + description: 'Permanently remove content items from the library.', + icon: Delete, }, { - key: CONTENT_LIBRARY_PERMISSIONS.PUBLISH_LIBRARY_CONTENT, resource: 'library_content', label: 'Publish', description: 'Publish individual content items to make them available for reuse in courses.', icon: DownloadDone, + key: CONTENT_LIBRARY_PERMISSIONS.PUBLISH_LIBRARY_CONTENT, + resource: 'library_content', + label: 'Publish', + description: 'Publish individual content items to make them available for reuse in courses.', + icon: DownloadDone, }, { - key: CONTENT_LIBRARY_PERMISSIONS.REUSE_LIBRARY_CONTENT, resource: 'library_content', label: 'Reuse', description: 'Add published content from this library to a course.', icon: SpinnerIcon, + key: CONTENT_LIBRARY_PERMISSIONS.REUSE_LIBRARY_CONTENT, + resource: 'library_content', + label: 'Reuse', + description: 'Add published content from this library to a course.', + icon: SpinnerIcon, }, { - key: CONTENT_LIBRARY_PERMISSIONS.IMPORT_LIBRARY_CONTENT, resource: 'library_content', label: 'Import Content from Course', description: ' Import content from an existing course into this library.', icon: FileDownload, + key: CONTENT_LIBRARY_PERMISSIONS.IMPORT_LIBRARY_CONTENT, + resource: 'library_content', + label: 'Import Content from Course', + description: ' Import content from an existing course into this library.', + icon: FileDownload, }, { - key: CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY_TEAM, resource: 'library_team', label: 'View', description: 'See the list of users with a role assigned to this library.', icon: RemoveRedEye, + key: CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY_TEAM, + resource: 'library_team', + label: 'View', + description: 'See the list of users with a role assigned to this library.', + icon: RemoveRedEye, }, { - key: CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TEAM, resource: 'library_team', label: 'Manage', description: 'Add, change, or remove role assignments for this library from the Roles and Permissions console.', icon: Settings, + key: CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TEAM, + resource: 'library_team', + label: 'Manage', + description: 'Add, change, or remove role assignments for this library from the Roles and Permissions console.', + icon: Settings, }, { - key: CONTENT_LIBRARY_PERMISSIONS.CREATE_LIBRARY_COLLECTION, resource: 'library_collection', label: 'View', description: 'Create new collections to organize content within the library.', icon: RemoveRedEye, + key: CONTENT_LIBRARY_PERMISSIONS.CREATE_LIBRARY_COLLECTION, + resource: 'library_collection', + label: 'Create', + description: 'Create new collections to organize content within the library.', + icon: Plus, }, { - key: CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_COLLECTION, resource: 'library_collection', label: 'Publish', description: 'Update the name and contents of existing collections.', icon: EditOutline, + key: CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_COLLECTION, + resource: 'library_collection', + label: 'Edit', + description: 'Update the name and contents of existing collections.', + icon: EditOutline, }, { - key: CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY_COLLECTION, resource: 'library_collection', label: 'Edit', description: 'Permanently remove collections from the library.', icon: EditOutline, + key: CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY_COLLECTION, + resource: 'library_collection', + label: 'Delete', + description: 'Permanently remove collections from the library.', + icon: Delete, }, ]; -export const rolesLibraryObject: Role[] = [ - { - role: 'library_admin', - contextType: 'library', - scope: '', - permissions: [ - CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY, - CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TAGS, - CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY, - CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_CONTENT, - CONTENT_LIBRARY_PERMISSIONS.PUBLISH_LIBRARY_CONTENT, - CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY_TEAM, - CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TEAM, - CONTENT_LIBRARY_PERMISSIONS.CREATE_LIBRARY_COLLECTION, - CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_COLLECTION, - CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY_COLLECTION, - CONTENT_LIBRARY_PERMISSIONS.CREATE_LIBRARY_CONTENT, - CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY_CONTENT, - CONTENT_LIBRARY_PERMISSIONS.REUSE_LIBRARY_CONTENT, - CONTENT_LIBRARY_PERMISSIONS.IMPORT_LIBRARY_CONTENT, - ], - userCount: 1, - name: 'Library Admin', - description: 'The Library Admin has full control over the library, including managing users, modifying content, and handling publishing workflows. They ensure content is properly maintained and accessible as needed.', - }, - { - role: 'library_author', - contextType: 'library', - scope: '', - permissions: [ - CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY, - CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TAGS, - CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_CONTENT, - CONTENT_LIBRARY_PERMISSIONS.PUBLISH_LIBRARY_CONTENT, - CONTENT_LIBRARY_PERMISSIONS.REUSE_LIBRARY_CONTENT, - CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY_TEAM, - CONTENT_LIBRARY_PERMISSIONS.CREATE_LIBRARY_COLLECTION, - CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_COLLECTION, - CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY_COLLECTION, - CONTENT_LIBRARY_PERMISSIONS.CREATE_LIBRARY_CONTENT, - CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY_CONTENT, - CONTENT_LIBRARY_PERMISSIONS.IMPORT_LIBRARY_CONTENT, - ], - userCount: 1, - name: 'Library Author', - description: 'The Library Author is responsible for creating, editing, and publishing content within a library. They can manage tags and collections but cannot delete libraries or manage users.', - }, - { - role: 'library_contributor', - contextType: 'library', - scope: '', - permissions: [ - CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY, - CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TAGS, - CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_CONTENT, - CONTENT_LIBRARY_PERMISSIONS.REUSE_LIBRARY_CONTENT, - CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY_TEAM, - CONTENT_LIBRARY_PERMISSIONS.CREATE_LIBRARY_COLLECTION, - CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_COLLECTION, - CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY_COLLECTION, - CONTENT_LIBRARY_PERMISSIONS.CREATE_LIBRARY_CONTENT, - CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY_CONTENT, - CONTENT_LIBRARY_PERMISSIONS.IMPORT_LIBRARY_CONTENT, +const LIBRARY_ROLE_PERMISSIONS: Record = { + library_admin: [ + CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY, + CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TAGS, + CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY, + CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_CONTENT, + CONTENT_LIBRARY_PERMISSIONS.PUBLISH_LIBRARY_CONTENT, + CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY_TEAM, + CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TEAM, + CONTENT_LIBRARY_PERMISSIONS.CREATE_LIBRARY_COLLECTION, + CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_COLLECTION, + CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY_COLLECTION, + CONTENT_LIBRARY_PERMISSIONS.CREATE_LIBRARY_CONTENT, + CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY_CONTENT, + CONTENT_LIBRARY_PERMISSIONS.REUSE_LIBRARY_CONTENT, + CONTENT_LIBRARY_PERMISSIONS.IMPORT_LIBRARY_CONTENT, + ], + library_author: [ + CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY, + CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TAGS, + CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_CONTENT, + CONTENT_LIBRARY_PERMISSIONS.PUBLISH_LIBRARY_CONTENT, + CONTENT_LIBRARY_PERMISSIONS.REUSE_LIBRARY_CONTENT, + CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY_TEAM, + CONTENT_LIBRARY_PERMISSIONS.CREATE_LIBRARY_COLLECTION, + CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_COLLECTION, + CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY_COLLECTION, + CONTENT_LIBRARY_PERMISSIONS.CREATE_LIBRARY_CONTENT, + CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY_CONTENT, + CONTENT_LIBRARY_PERMISSIONS.IMPORT_LIBRARY_CONTENT, + ], + library_contributor: [ + CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY, + CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TAGS, + CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_CONTENT, + CONTENT_LIBRARY_PERMISSIONS.REUSE_LIBRARY_CONTENT, + CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY_TEAM, + CONTENT_LIBRARY_PERMISSIONS.CREATE_LIBRARY_COLLECTION, + CONTENT_LIBRARY_PERMISSIONS.EDIT_LIBRARY_COLLECTION, + CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY_COLLECTION, + CONTENT_LIBRARY_PERMISSIONS.CREATE_LIBRARY_CONTENT, + CONTENT_LIBRARY_PERMISSIONS.DELETE_LIBRARY_CONTENT, + CONTENT_LIBRARY_PERMISSIONS.IMPORT_LIBRARY_CONTENT, + ], + library_user: [ + CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY, + CONTENT_LIBRARY_PERMISSIONS.REUSE_LIBRARY_CONTENT, + CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY_TEAM, + ], +}; - ], - userCount: 1, - name: 'Library Contributor', - description: 'The Library Contributor can create and edit content within a library but cannot publish it. They support the authoring process while leaving final publishing to Authors or Admins.', - }, - { - role: 'library_user', - contextType: 'library', - scope: '', - permissions: [ - CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY, - CONTENT_LIBRARY_PERMISSIONS.REUSE_LIBRARY_CONTENT, - CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY_TEAM, - ], - userCount: 1, - name: 'Library User', - description: 'The Library User can view and reuse content but cannot edit or delete anything.', - }, -]; +export const libraryRolesWithPermissions: Role[] = libraryRolesMetadata.map((meta) => ({ + ...meta, + scope: '', + userCount: 1, + permissions: LIBRARY_ROLE_PERMISSIONS[meta.role] ?? [], +})); diff --git a/src/authz-module/roles-permissions/library/messages.ts b/src/authz-module/roles-permissions/messages.ts similarity index 55% rename from src/authz-module/roles-permissions/library/messages.ts rename to src/authz-module/roles-permissions/messages.ts index 13e102f4..c23f8f21 100644 --- a/src/authz-module/roles-permissions/library/messages.ts +++ b/src/authz-module/roles-permissions/messages.ts @@ -1,63 +1,63 @@ import { defineMessages } from '@edx/frontend-platform/i18n'; const messages = defineMessages({ - 'library.authz.tabs.permissions': { - id: 'library.authz.tabs.permissions', + 'authz.tabs.permissions': { + id: 'authz.tabs.permissions', defaultMessage: 'Permissions', description: 'Libraries AuthZ title for the permissions tab', }, - 'library.authz.tabs.permissionsRoles': { - id: 'library.authz.tabs.permissionsRoles', + 'authz.tabs.permissionsRoles': { + id: 'authz.tabs.permissionsRoles', defaultMessage: 'Roles and Permissions', description: 'Libraries AuthZ title for the permissions and roles tab', }, - 'library.authz.tabs.permissionsRoles.courses.alert.title': { - id: 'library.authz.tabs.permissionsRoles.courses.alert.title', + 'authz.tabs.permissionsRoles.courses.alert.title': { + id: 'authz.tabs.permissionsRoles.courses.alert.title', defaultMessage: 'Course Roles', description: 'Libraries AuthZ title for the course roles alert', }, - 'library.authz.tabs.permissionsRoles.courses.tab': { - id: 'library.authz.tabs.permissionsRoles.courses.tab', + 'authz.tabs.permissionsRoles.courses.tab': { + id: 'authz.tabs.permissionsRoles.courses.tab', defaultMessage: 'Courses', description: 'Libraries AuthZ title for the course roles tab', }, - 'library.authz.tabs.permissionsRoles.libraries.tab': { - id: 'library.authz.tabs.permissionsRoles.libraries.tab', + 'authz.tabs.permissionsRoles.libraries.tab': { + id: 'authz.tabs.permissionsRoles.libraries.tab', defaultMessage: 'Libraries', description: 'Libraries AuthZ title for the libraries roles tab', }, - 'library.authz.tabs.permissionsRoles.libraries.tab.title': { - id: 'library.authz.tabs.permissionsRoles.libraries.tab.title', + 'authz.tabs.permissionsRoles.libraries.tab.title': { + id: 'authz.tabs.permissionsRoles.libraries.tab.title', defaultMessage: 'Library Roles', description: 'Libraries AuthZ title for the library roles table', }, - 'library.authz.tabs.permissionsRoles.courses.tab.title': { - id: 'library.authz.tabs.permissionsRoles.courses.tab.title', + 'authz.tabs.permissionsRoles.courses.tab.title': { + id: 'authz.tabs.permissionsRoles.courses.tab.title', defaultMessage: 'Course Roles', description: 'Libraries AuthZ title for the course roles table', }, - 'library.authz.tabs.permissionsRoles.courses.alert.note': { - id: 'library.authz.tabs.permissionsRoles.courses.alert.note', + 'authz.tabs.permissionsRoles.courses.alert.note': { + id: 'authz.tabs.permissionsRoles.courses.alert.note', defaultMessage: 'Note:', description: 'Libraries AuthZ note for the course roles alert', }, - 'library.authz.tabs.permissionsRoles.courses.alert.description': { - id: 'library.authz.tabs.permissionsRoles.courses.alert.description', + 'authz.tabs.permissionsRoles.courses.alert.description': { + id: 'authz.tabs.permissionsRoles.courses.alert.description', defaultMessage: 'This list shows the permissions currently available in Authoring Studio. Some roles may grant additional permissions managed outside this interface.', description: 'Libraries AuthZ description for the course roles alert', }, - 'library.authz.tabs.permissionsRoles.courses.alert.link': { - id: 'library.authz.tabs.permissionsRoles.courses.alert.link', + 'authz.tabs.permissionsRoles.courses.alert.link': { + id: 'authz.tabs.permissionsRoles.courses.alert.link', defaultMessage: 'See full documentation', description: 'Libraries AuthZ link for the course roles alert', }, - 'library.authz.team.remove.user.toast.success.description': { - id: 'library.authz.team.remove.user.toast.success.description', + 'authz.team.remove.user.toast.success.description': { + id: 'authz.team.remove.user.toast.success.description', defaultMessage: 'The {role} role has been successfully removed.{rolesCount, plural, =0 { The user no longer has access to this library and has been removed from the member list.} other {}}', description: 'Libraries team management remove user toast success', }, - 'library.authz.team.toast.default.error.message': { - id: 'library.authz.team.toast.default.error.message', + 'authz.team.toast.default.error.message': { + id: 'authz.team.toast.default.error.message', defaultMessage: 'Something went wrong on our end.

Please try again later.', description: 'Libraries default error message', }, diff --git a/src/authz-module/roles-permissions/library/utils.test.ts b/src/authz-module/roles-permissions/utils.test.ts similarity index 89% rename from src/authz-module/roles-permissions/library/utils.test.ts rename to src/authz-module/roles-permissions/utils.test.ts index 0d4f0ff5..f5c9b2bb 100644 --- a/src/authz-module/roles-permissions/library/utils.test.ts +++ b/src/authz-module/roles-permissions/utils.test.ts @@ -1,4 +1,5 @@ import { createIntl } from '@edx/frontend-platform/i18n'; +import type { Role } from '@src/types'; import { buildPermissionMatrixByResource } from './utils'; const intl = createIntl({ locale: 'en', messages: {} }); @@ -14,15 +15,15 @@ const permissions = [ const resources = [ { key: 'library', label: 'Library', description: '' }, ]; -const roles = [ +const roles: Role[] = [ { - name: 'admin', permissions: ['create_library', 'edit_library'], userCount: 2, role: 'admin', description: '', contextType: '', scope: '', + name: 'admin', permissions: ['create_library', 'edit_library'], userCount: 2, role: 'admin', description: '', contextType: 'library', scope: '', }, { - name: 'editor', permissions: ['edit_library'], userCount: 2, role: 'editor', description: '', contextType: '', scope: '', + name: 'editor', permissions: ['edit_library'], userCount: 2, role: 'editor', description: '', contextType: 'library', scope: '', }, { - name: 'guest', permissions: [], userCount: 2, role: 'guest', description: '', contextType: '', scope: '', + name: 'guest', permissions: [], userCount: 2, role: 'guest', description: '', contextType: 'library', scope: '', }, ]; diff --git a/src/authz-module/roles-permissions/library/utils.ts b/src/authz-module/roles-permissions/utils.ts similarity index 98% rename from src/authz-module/roles-permissions/library/utils.ts rename to src/authz-module/roles-permissions/utils.ts index affcaec2..e805b253 100644 --- a/src/authz-module/roles-permissions/library/utils.ts +++ b/src/authz-module/roles-permissions/utils.ts @@ -96,4 +96,4 @@ const buildPermissionMatrixByResource = ({ }); }; -export { buildPermissionMatrixByResource }; +export { buildPermissionMatrixByResource, getPermissionMetadata };