diff --git a/backend/src/components/permissionUtils.js b/backend/src/components/permissionUtils.js index ab54006c..a9fcd451 100644 --- a/backend/src/components/permissionUtils.js +++ b/backend/src/components/permissionUtils.js @@ -177,6 +177,27 @@ function checkSdcDistrictCollectionAccess(req, res, next) { return next(); } +function checkAnyEdxUserSignoffPermission(permissions) { + return function(req, res, next) { + const hasPermission = permissions.some(permission => req.session.activeInstitutePermissions.includes(permission)); + if (!hasPermission) { + return res.status(HttpStatus.FORBIDDEN).json({ + message: 'User doesn\'t have permission.' + }); + } + return next(); + }; +} + +function checkPermissionForSignOff(req, res, next) { + if (!req.session.activeInstitutePermissions.includes(req.body.districtSignatoryRole)) { + return res.status(HttpStatus.FORBIDDEN).json({ + message: 'User doesn\'t have permission.' + }); + } + return next(); +} + //Find Institute IDs function findInstituteInformation_query(req, res, next) { res.locals.requestedInstituteType = req.query.schoolID ? 'SCHOOL' : 'DISTRICT'; @@ -577,7 +598,9 @@ const permUtils = { findSdcSchoolCollectionsInDuplicate, checkSdcDuplicateAccess, checkUserAccessToDuplicateSdcSchoolCollections, - checkDistrictBelongsInSdcDistrictCollection + checkDistrictBelongsInSdcDistrictCollection, + checkAnyEdxUserSignoffPermission, + checkPermissionForSignOff }; module.exports = permUtils; diff --git a/backend/src/routes/sdc.js b/backend/src/routes/sdc.js index 8d62ebad..52df3523 100644 --- a/backend/src/routes/sdc.js +++ b/backend/src/routes/sdc.js @@ -15,7 +15,7 @@ const isValidBackendToken = auth.isValidBackendToken(); const { getCodes } = require('../components/utils'); const { validateAccessToken, checkEdxUserPermission, checkPermissionForRequestedInstitute, findSchoolID_params, findDistrictID_params, checkEDXUserAccessToRequestedInstitute, findSdcSchoolCollectionID_params, findSdcDistrictCollectionID_params, findSdcSchoolCollectionID_fromRequestedSdcSchoolCollectionStudent, loadSdcSchoolCollection, loadSdcDistrictCollection, findSdcSchoolCollectionStudentID_params, loadSdcSchoolCollectionStudent, checkSdcSchoolCollectionAccess, checkSdcDistrictCollectionAccess, checkInstituteCollectionAccess, checkIfCreateorUpdateSDCStudentIsAllowed, findSInstituteTypeCollectionID_body, - loadInstituteCollection, checkStudentBelongsInCollection, findSdcSchoolCollectionStudentID_body, checkSdcDuplicateAccess, checkUserAccessToDuplicateSdcSchoolCollections, findSdcSchoolCollectionsInDuplicate, checkDistrictBelongsInSdcDistrictCollection, findDistrictID_query } = require('../components/permissionUtils'); + loadInstituteCollection, checkStudentBelongsInCollection, findSdcSchoolCollectionStudentID_body, checkSdcDuplicateAccess, checkUserAccessToDuplicateSdcSchoolCollections, findSdcSchoolCollectionsInDuplicate, checkDistrictBelongsInSdcDistrictCollection, findDistrictID_query, checkAnyEdxUserSignoffPermission, checkPermissionForSignOff } = require('../components/permissionUtils'); const { PERMISSION } = require('../util/Permission'); const {getPenMatch} = require('../components/penMatch'); const validate = require('../components/validator'); @@ -96,5 +96,5 @@ router.get('/sdcDistrictCollection/:sdcDistrictCollectionID/sdcSchoolCollections router.get('/sdcDistrictCollection/:sdcDistrictCollectionID/provincial-duplicates', passport.authenticate('jwt', {session: false}, undefined), isValidBackendToken, validateAccessToken, checkEdxUserPermission(PERMISSION.DISTRICT_SDC_VIEW), validate(getBySdcDistrictCollectionSchema), findSdcDistrictCollectionID_params, loadSdcDistrictCollection, checkSdcDistrictCollectionAccess, getProvincialDuplicates); router.get('/sdcDistrictCollection/:sdcDistrictCollectionID/users', passport.authenticate('jwt', {session: false}, undefined), isValidBackendToken, validateAccessToken, checkEdxUserPermission(PERMISSION.DISTRICT_SDC_VIEW), validate(getSdcDistrictUsersSchema), findSdcDistrictCollectionID_params, loadSdcDistrictCollection, checkSdcDistrictCollectionAccess, findDistrictID_query, checkDistrictBelongsInSdcDistrictCollection, getEdxUsers); -router.post('/sdcDistrictCollection/:sdcDistrictCollectionID/sign-off', passport.authenticate('jwt', {session: false}, undefined), isValidBackendToken, validateAccessToken, checkEdxUserPermission(PERMISSION.DISTRICT_SDC_EDIT), validate(districtSignoffSchema), findSdcDistrictCollectionID_params, loadSdcDistrictCollection, checkSdcDistrictCollectionAccess, submitDistrictSignature); +router.post('/sdcDistrictCollection/:sdcDistrictCollectionID/sign-off', passport.authenticate('jwt', {session: false}, undefined), isValidBackendToken, validateAccessToken, checkAnyEdxUserSignoffPermission([PERMISSION.DISTRICT_SDC_EDIT, PERMISSION.SUPERINT, PERMISSION.SECR_TRES]), validate(districtSignoffSchema), checkPermissionForSignOff, findSdcDistrictCollectionID_params, loadSdcDistrictCollection, checkSdcDistrictCollectionAccess, submitDistrictSignature); module.exports = router; diff --git a/backend/src/util/Permission.js b/backend/src/util/Permission.js index 59efe3e9..a9ddd670 100644 --- a/backend/src/util/Permission.js +++ b/backend/src/util/Permission.js @@ -10,10 +10,13 @@ const PERMISSION = Object.freeze( DISTRICT_SDC_EDIT: 'DIS_SDC_EDIT', SCHOOL_SDC_EDIT: 'SCH_SDC_EDIT', DISTRICT_SDC_VIEW: 'DIS_SDC_VIEW', - SCHOOL_SDC_VIEW: 'SCH_SDC_VIEW' + SCHOOL_SDC_VIEW: 'SCH_SDC_VIEW', + SUPERINT: 'SUPERINT', + SECR_TRES: 'SECR_TRES' } ); + module.exports = { - PERMISSION, + PERMISSION }; diff --git a/backend/src/validations/sdc.js b/backend/src/validations/sdc.js index 2166839b..3634af22 100644 --- a/backend/src/validations/sdc.js +++ b/backend/src/validations/sdc.js @@ -1,5 +1,6 @@ const { object, string, boolean, number, array } = require('yup'); const {baseRequestSchema} = require('./base'); +const { PERMISSION } = require('../util/Permission'); const baseQuerySchema = object({ type: string().optional(), @@ -108,7 +109,7 @@ const baseDistrictCollectionSchema = object({ }).concat(baseRequestSchema); const baseSignature = object({ - districtSignatoryRole: string().nonNullable(), + districtSignatoryRole: string().nonNullable().oneOf([PERMISSION.SUPERINT, PERMISSION.SECR_TRES, PERMISSION.DISTRICT_SDC_EDIT]), districtSignatoryUserID: string().nullable().optional(), }).noUnknown();