Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moved SCHOOL_ADMIN, DISTRICT_ADMIN role to permissions #1663

Merged
merged 6 commits into from
Nov 2, 2023
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
7 changes: 0 additions & 7 deletions backend/src/components/edx/exchange.js
Original file line number Diff line number Diff line change
Expand Up @@ -1117,13 +1117,6 @@ async function getExchangeStats(req, res) {

async function createSchool(req, res) {
try {
if (!req.session.roles.includes('SCHOOL_ADMIN')) {
return res.status(HttpStatus.UNAUTHORIZED).json({
status: HttpStatus.UNAUTHORIZED,
message: 'You are not authorized to add or edit schools'
});
}

const {school, user} = req.body;

const isEmptyString = str => typeof str === 'string' && str.trim() === '';
Expand Down
111 changes: 42 additions & 69 deletions backend/src/components/institute/institute.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ async function addDistrictContact(req, res) {
const token = getBackendToken(req);

let district = cacheService.getDistrictJSONByDistrictId(req.body.districtID);
if(!district || !hasDistrictAdminRole(req)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
if(!district){
return res.status(HttpStatus.NOT_FOUND).json({
message: 'District not found'
});
}

Expand Down Expand Up @@ -125,9 +125,9 @@ async function updateDistrict(req, res) {

let district = cacheService.getDistrictJSONByDistrictId(req.body.districtId);

if (!district || !hasDistrictAdminRole(req)) {
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
if (!district) {
return res.status(HttpStatus.NOT_FOUND).json({
message: 'District not found'
});
}
const districtPayload = req.body;
Expand Down Expand Up @@ -158,9 +158,9 @@ async function updateDistrictContact(req, res) {
const token = getBackendToken(req);

let district = cacheService.getDistrictJSONByDistrictId(req.body.districtId);
if(!district || !hasDistrictAdminRole(req)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
if(!district){
return res.status(HttpStatus.NOT_FOUND).json({
message: 'District not found'
});
}

Expand Down Expand Up @@ -188,9 +188,9 @@ async function deleteDistrictContact(req, res) {
const token = getBackendToken(req);

let district = cacheService.getDistrictJSONByDistrictId(req.params.districtId);
if(!district || !hasDistrictAdminRole(req)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
if(!district){
return res.status(HttpStatus.NOT_FOUND).json({
message: 'District not found'
});
}

Expand Down Expand Up @@ -245,9 +245,9 @@ async function addNewDistrictNote(req, res) {
const token = getBackendToken(req);

let district = cacheService.getDistrictJSONByDistrictId(req.body.districtId);
if(!district || !hasDistrictAdminRole(req)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
if(!district){
return res.status(HttpStatus.NOT_FOUND).json({
message: 'District not found'
});
}
const params = {
Expand All @@ -271,9 +271,9 @@ async function updateDistrictNote(req, res) {
try {
const token = getBackendToken(req);
let district = cacheService.getDistrictJSONByDistrictId(req.body.districtId);
if(!district || !hasDistrictAdminRole(req)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
if(!district){
return res.status(HttpStatus.NOT_FOUND).json({
message: 'District not found'
});
}
const payload = {
Expand All @@ -293,9 +293,9 @@ async function deleteDistrictNote(req, res) {
try {
const token = getBackendToken(req);
let district = cacheService.getDistrictJSONByDistrictId(req.params.districtId);
if(!district || !hasDistrictAdminRole(req)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
if(!district){
return res.status(HttpStatus.NOT_FOUND).json({
message: 'District not found'
});
}
await utils.deleteData(token, `${config.get('server:institute:instituteDistrictURL')}/${req.params.districtId}/note/${req.params.noteId}`);
Expand Down Expand Up @@ -345,12 +345,6 @@ async function addSchool(req, res) {
try {
const token = getBackendToken(req);

if(!hasSchoolAdminRole(req, req.body)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
});
}

const payload = {
createUser: utils.getUser(req).idir_username,
createDate: null,
Expand Down Expand Up @@ -433,9 +427,9 @@ async function addNewSchoolNote(req, res) {
const token = getBackendToken(req);

let school = cacheService.getSchoolBySchoolID(req.body.schoolId);
if(!school || !hasSchoolAdminRole(req, school)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
if(!school){
return res.status(HttpStatus.NOT_FOUND).json({
message: 'School not found'
});
}

Expand Down Expand Up @@ -472,9 +466,9 @@ async function updateSchoolNote(req, res) {
try {
const token = getBackendToken(req);
let school = cacheService.getSchoolBySchoolID(req.body.schoolId);
if (!school || !hasSchoolAdminRole(req, school)) {
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
if (!school) {
return res.status(HttpStatus.NOT_FOUND).json({
message: 'School not found'
});
}
const payload = {
Expand All @@ -494,9 +488,9 @@ async function deleteSchoolNote(req, res) {
try {
const token = getBackendToken(req);
let school = cacheService.getSchoolBySchoolID(req.params.schoolId);
if(!school || !hasSchoolAdminRole(req, school)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
if(!school){
return res.status(HttpStatus.NOT_FOUND).json({
message: 'School not found'
});
}
await utils.deleteData(token, `${config.get('server:institute:instituteSchoolURL')}/${req.params.schoolId}/note/${req.params.noteId}`);
Expand All @@ -512,9 +506,9 @@ async function addSchoolContact(req, res) {
const token = getBackendToken(req);

let school = cacheService.getSchoolBySchoolID(req.body.schoolID);
if(!school || !hasSchoolAdminRole(req, school)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
if(!school){
return res.status(HttpStatus.NOT_FOUND).json({
message: 'School not found'
});
}

Expand Down Expand Up @@ -554,9 +548,9 @@ async function updateSchoolContact(req, res) {
const token = getBackendToken(req);

let school = cacheService.getSchoolBySchoolID(req.body.schoolID);
if(!school || !hasSchoolAdminRole(req, school)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
if(!school){
return res.status(HttpStatus.NOT_FOUND).json({
message: 'School not found'
});
}

Expand Down Expand Up @@ -587,9 +581,9 @@ async function deleteSchoolContact(req, res) {
const token = getBackendToken(req);

let school = cacheService.getSchoolBySchoolID(req.params.schoolId);
if(!school || !hasSchoolAdminRole(req, school)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
if(!school){
return res.status(HttpStatus.NOT_FOUND).json({
message: 'School not found'
});
}

Expand Down Expand Up @@ -844,20 +838,6 @@ async function updateAuthority(req, res) {
}
}

function hasDistrictAdminRole(req){
return req.session.roles.includes('DISTRICT_ADMIN');
}

function hasSchoolAdminRole(req, school){
if(school.schoolCategoryCode === 'INDEPEND' || school.schoolCategoryCode === 'INDP_FNS'){
return req.session.roles.includes('SCHOOL_ADMIN') || req.session.roles.includes('INDEPENDENT_SCHOOLS_ADMIN');
} else if(school.schoolCategoryCode === 'OFFSHORE'){
return req.session.roles.includes('SCHOOL_ADMIN') || req.session.roles.includes('OFFSHORE_SCHOOLS_ADMIN');
}

return req.session.roles.includes('SCHOOL_ADMIN');
}

function hasAuthorityAdminRole(req, authority){
if(authority?.authorityTypeCode === 'INDEPENDNT') {
return req.session.roles.includes('INDEPENDENT_AUTHORITY_ADMIN') || req.session.roles.includes('INDEPENDENT_SCHOOLS_ADMIN');
Expand Down Expand Up @@ -984,9 +964,9 @@ async function updateSchool(req, res) {

let school = cacheService.getSchoolBySchoolID(req.body.schoolId);

if (!school || !hasSchoolAdminRole(req, school)) {
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
if (!school) {
return res.status(HttpStatus.NOT_FOUND).json({
message: 'School not found'
});
}
const payload = req.body;
Expand Down Expand Up @@ -1086,13 +1066,6 @@ async function getSchoolsPaginated(req, res){
async function moveSchool(req, res) {
try {
const token = getBackendToken(req);

if(!hasSchoolAdminRole(req, req.body.toSchool)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
});
}

let school = cacheService.getSchoolBySchoolID(req.body.fromSchoolId);

if(!school || school.schoolCategoryCode === 'OFFSHORE') {
Expand Down
2 changes: 0 additions & 2 deletions backend/src/components/roles.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ const roles = {
//Help functions created in auth module: isValidStaffAdministrationAdmin
StaffAdministration: config.get('server:administration:roleAdmin'),
NominalRoll: config.get('server:nominalRoll:roleAdmin'),
District: 'DISTRICT_ADMIN',
School: 'SCHOOL_ADMIN',
SchoolIndependent: 'INDEPENDENT_SCHOOLS_ADMIN',
IndependentAuthority: 'INDEPENDENT_AUTHORITY_ADMIN',
SchoolOffshore: 'OFFSHORE_SCHOOLS_ADMIN'
Expand Down
62 changes: 13 additions & 49 deletions backend/src/components/sdc/sdc.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,7 @@ async function getFundingGroupDataForSchool(req, res) {
try {
const accessToken = getBackendToken(req);
validateAccessToken(accessToken, res);

let school = cacheService.getSchoolBySchoolID(req.params.schoolID);

if(!hasSchoolAdminRole(req, school)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
});
}


const data = await getData(accessToken, `${config.get('sdc:fundingGroupDataURL')}/search/${req.params.schoolID}`);
return res.status(HttpStatus.OK).json(data);
} catch (e) {
Expand All @@ -29,16 +21,7 @@ async function getFundingGroupDataForSchool(req, res) {
async function getSnapshotFundingDataForSchool(req, res) {
try {
const accessToken = getBackendToken(req);
validateAccessToken(accessToken, res);

let school = cacheService.getSchoolBySchoolID(req.params.schoolID);

if(!hasSchoolAdminRole(req, school)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
});
}

validateAccessToken(accessToken, res);
const data = await getData(accessToken, `${config.get('sdc:fundingGroupDataURL')}/snapshot/${req.params.schoolID}/${req.params.collectionID}`);
return res.status(HttpStatus.OK).json(data);
} catch (e) {
Expand All @@ -53,10 +36,9 @@ async function deleteFundingDataForSchool(req, res) {
validateAccessToken(accessToken, res);

let school = cacheService.getSchoolBySchoolID(req.params.schoolID);

if(!hasSchoolAdminRole(req, school)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
if(!school){
return res.status(HttpStatus.NOT_FOUND).json({
message: 'School not found'
});
}

Expand All @@ -75,9 +57,9 @@ async function updateFundingDataForSchool(req, res) {

let school = cacheService.getSchoolBySchoolID(req.params.schoolID);

if(!hasSchoolAdminRole(req, school)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
if(school?.schoolCategoryCode !== 'INDEPEND' && school?.schoolCategoryCode !== 'INDP_FNS') {
return res.status(HttpStatus.BAD_REQUEST).json({
message: 'Unable to update funding code for this school category'
});
}

Expand All @@ -100,10 +82,10 @@ async function addNewFundingForSchool(req, res) {
validateAccessToken(accessToken, res);

let school = cacheService.getSchoolBySchoolID(req.params.schoolID);
if(!hasSchoolAdminRole(req, school)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'

if(school?.schoolCategoryCode !== 'INDEPEND' && school?.schoolCategoryCode !== 'INDP_FNS') {
return res.status(HttpStatus.BAD_REQUEST).json({
message: 'Unable to add funding code for this school category'
});
}

Expand All @@ -122,16 +104,7 @@ async function addNewFundingForSchool(req, res) {
async function getAllCollectionsForSchool(req, res) {
try {
const accessToken = getBackendToken(req);
validateAccessToken(accessToken, res);

let school = cacheService.getSchoolBySchoolID(req.params.schoolID);

if(!hasSchoolAdminRole(req, school)){
return res.status(HttpStatus.UNAUTHORIZED).json({
message: 'You do not have the required access for this function'
});
}

validateAccessToken(accessToken, res);
const data = await getData(accessToken, `${config.get('sdc:schoolCollectionURL')}/searchAll/${req.params.schoolID}`);
return res.status(HttpStatus.OK).json(data);
} catch (e) {
Expand All @@ -140,15 +113,6 @@ async function getAllCollectionsForSchool(req, res) {
}
}

function hasSchoolAdminRole(req, school){
if(school.schoolCategoryCode === 'INDEPEND' || school.schoolCategoryCode === 'INDP_FNS'){
return req.session.roles.includes('SCHOOL_ADMIN') || req.session.roles.includes('INDEPENDENT_SCHOOLS_ADMIN');
}

return req.session.roles.includes('SCHOOL_ADMIN');
}


module.exports = {
getFundingGroupDataForSchool,
deleteFundingDataForSchool,
Expand Down
2 changes: 1 addition & 1 deletion backend/src/routes/edx-router.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,6 @@ router.post('/exchange/:secureExchangeID/documents', passport.authenticate('jwt'
router.get('/exchange/:secureExchangeID/documents/:documentId', auth.isValidExchangeUserToken, getExchangeDocumentById());

// Create School Saga
router.post('/create-school', passport.authenticate('jwt', {session: false}, undefined), auth.isValidSchoolAdmin, createSchool);
router.post('/create-school', passport.authenticate('jwt', {session: false}, undefined), utils.checkUserHasPermission(PERMISSION.EDIT_SCHOOL_PERMISSION), createSchool);

module.exports = router;
Loading
Loading