From 88997ca242bfcd6b68b86ebd1b21d5a6ccf8db41 Mon Sep 17 00:00:00 2001 From: jansenk Date: Thu, 20 Dec 2018 15:08:35 -0500 Subject: [PATCH] fix(auth) allow global staff to view gradebook --- src/data/actions/roles.js | 46 ++++++++++++++++---------------- src/data/actions/roles.test.js | 48 +++++++++++++++++++++++++++++++--- 2 files changed, 68 insertions(+), 26 deletions(-) diff --git a/src/data/actions/roles.js b/src/data/actions/roles.js index af27ef5..ce37ecd 100644 --- a/src/data/actions/roles.js +++ b/src/data/actions/roles.js @@ -1,38 +1,38 @@ import { - GOT_ROLES, - ERROR_FETCHING_ROLES - } from '../constants/actionTypes/roles'; + GOT_ROLES, + ERROR_FETCHING_ROLES, +} from '../constants/actionTypes/roles'; import { fetchGrades } from './grades'; import { fetchTracks } from './tracks'; import { fetchCohorts } from './cohorts'; import { fetchAssignmentTypes } from './assignmentTypes'; import LmsApiService from '../services/LmsApiService'; -const allowed_roles = ['staff', 'instructor', 'support']; +const allowedRoles = ['staff', 'instructor', 'support']; const gotRoles = canUserViewGradebook => ({ type: GOT_ROLES, canUserViewGradebook }); -const errorFetchingRoles = () => ({type: ERROR_FETCHING_ROLES }); +const errorFetchingRoles = () => ({ type: ERROR_FETCHING_ROLES }); const getRoles = (courseId, urlQuery) => ( - (dispatch) => { - return LmsApiService.fetchUserRoles(courseId) - .then(response => response.data) - .then(roles => { - var canUserViewGradebook = roles.some(role => (role.course_id === courseId) && allowed_roles.includes(role.role)); - dispatch(gotRoles(canUserViewGradebook)); - if(canUserViewGradebook){ - dispatch(fetchGrades(courseId, urlQuery.cohort, urlQuery.track)); - dispatch(fetchTracks(courseId)); - dispatch(fetchCohorts(courseId)); - dispatch(fetchAssignmentTypes(courseId)); - } - }) - .catch(() => { - dispatch(errorFetchingRoles()) - }); - }); + dispatch => LmsApiService.fetchUserRoles(courseId) + .then(response => response.data) + .then((response) => { + const canUserViewGradebook = response.is_staff + || (response.roles.some(role => (role.course_id === courseId) + && allowedRoles.includes(role.role))); + dispatch(gotRoles(canUserViewGradebook)); + if (canUserViewGradebook) { + dispatch(fetchGrades(courseId, urlQuery.cohort, urlQuery.track)); + dispatch(fetchTracks(courseId)); + dispatch(fetchCohorts(courseId)); + dispatch(fetchAssignmentTypes(courseId)); + } + }) + .catch(() => { + dispatch(errorFetchingRoles()); + })); export { getRoles, errorFetchingRoles, -}; \ No newline at end of file +}; diff --git a/src/data/actions/roles.test.js b/src/data/actions/roles.test.js index 0e5bc5d..ba0c3bb 100644 --- a/src/data/actions/roles.test.js +++ b/src/data/actions/roles.test.js @@ -23,6 +23,12 @@ const rolesUrl = `${configuration.LMS_BASE_URL}/api/enrollment/v1/roles/`; const course1Id = 'course-v1:edX+DemoX+Demo_Course'; const course2Id = 'course-v1:edX+DemoX+Demo_Course_2'; +function makeRoleListObj(roles, isGlobalStaff){ + return { + roles: roles, + is_staff: isGlobalStaff, + } +} function makeRoleObj(courseId, role) { return { course_id: courseId, @@ -52,7 +58,25 @@ describe('actions', () => { ]; const store = mockStore(); axiosMock.onGet(rolesUrl) - .replyOnce(200, JSON.stringify([course1StaffRole, course2DummyRole])); + .replyOnce(200, JSON.stringify(makeRoleListObj([course1StaffRole, course2DummyRole], false))); + + return store.dispatch(getRoles(course1Id, urlParams)).then(() => { + expect(store.getActions()).toEqual(expectedActions); + }); + }); + + it('dispatches got_roles action and other actions after fetching irrelevent roles but user is global staff', () => { + const expectedActions = [ + { type: GOT_ROLES, canUserViewGradebook: true }, + { type: STARTED_FETCHING_GRADES }, + { type: STARTED_FETCHING_TRACKS }, + { type: STARTED_FETCHING_COHORTS }, + { type: STARTED_FETCHING_ASSIGNMENT_TYPES }, + ]; + const store = mockStore(); + + axiosMock.onGet(rolesUrl) + .replyOnce(200, JSON.stringify(makeRoleListObj([course1DummyRole, course2DummyRole], true))); return store.dispatch(getRoles(course1Id, urlParams)).then(() => { expect(store.getActions()).toEqual(expectedActions); @@ -66,7 +90,7 @@ describe('actions', () => { const store = mockStore(); axiosMock.onGet(rolesUrl) - .replyOnce(200, JSON.stringify([course1DummyRole, course2StaffRole])); + .replyOnce(200, JSON.stringify(makeRoleListObj([course1DummyRole, course2StaffRole], false))); return store.dispatch(getRoles(course1Id, urlParams)).then(() => { expect(store.getActions()).toEqual(expectedActions); @@ -80,7 +104,25 @@ describe('actions', () => { const store = mockStore(); axiosMock.onGet(rolesUrl) - .replyOnce(200, JSON.stringify([])); + .replyOnce(200, JSON.stringify(makeRoleListObj([], false))); + + return store.dispatch(getRoles(course1Id, urlParams)).then(() => { + expect(store.getActions()).toEqual(expectedActions); + }); + }); + + it('dispatches got_roles action and other actions after fetching empty roles but user is global staff', () => { + const expectedActions = [ + { type: GOT_ROLES, canUserViewGradebook: true }, + { type: STARTED_FETCHING_GRADES }, + { type: STARTED_FETCHING_TRACKS }, + { type: STARTED_FETCHING_COHORTS }, + { type: STARTED_FETCHING_ASSIGNMENT_TYPES }, + ]; + const store = mockStore(); + + axiosMock.onGet(rolesUrl) + .replyOnce(200, JSON.stringify(makeRoleListObj([], true))); return store.dispatch(getRoles(course1Id, urlParams)).then(() => { expect(store.getActions()).toEqual(expectedActions);