fix: add question in group check + extra create question errors service
This commit is contained in:
		
							parent
							
								
									78b65f148e
								
							
						
					
					
						commit
						566bb5a5fb
					
				
					 4 changed files with 47 additions and 6 deletions
				
			
		|  | @ -6,6 +6,7 @@ import {getLearningObjectId, getQuestionId} from "../../../controllers/questions | ||||||
| import {fetchQuestion} from "../../../services/questions"; | import {fetchQuestion} from "../../../services/questions"; | ||||||
| import {FALLBACK_SEQ_NUM} from "../../../config"; | import {FALLBACK_SEQ_NUM} from "../../../config"; | ||||||
| import {fetchAnswer} from "../../../services/answers"; | import {fetchAnswer} from "../../../services/answers"; | ||||||
|  | import {mapToUsername} from "../../../interfaces/user"; | ||||||
| 
 | 
 | ||||||
| export const onlyAllowAuthor = authorize( | export const onlyAllowAuthor = authorize( | ||||||
|     (auth: AuthenticationInfo, req: AuthenticatedRequest) => req.body.author === auth.username |     (auth: AuthenticationInfo, req: AuthenticatedRequest) => req.body.author === auth.username | ||||||
|  | @ -46,3 +47,26 @@ export const onlyAllowAuthorRequestAnswer = authorize( | ||||||
|         return answer.author.username == auth.username; |         return answer.author.username == auth.username; | ||||||
|     } |     } | ||||||
| ); | ); | ||||||
|  | 
 | ||||||
|  | export const onlyAllowIfHasAccessToQuestion = authorize( | ||||||
|  |     async (auth, req) => { | ||||||
|  |         const hruid = req.params.hruid; | ||||||
|  |         const version = req.params.version; | ||||||
|  |         const language = req.query.lang as string; | ||||||
|  |         const seq = req.params.seq; | ||||||
|  |         requireFields({ hruid }); | ||||||
|  | 
 | ||||||
|  |         const learningObjectId = getLearningObjectId(hruid, version, language); | ||||||
|  |         const questionId = getQuestionId(learningObjectId, seq); | ||||||
|  | 
 | ||||||
|  |         const question = await fetchQuestion(questionId); | ||||||
|  |         const group = question.inGroup; | ||||||
|  | 
 | ||||||
|  |         if (auth.accountType === "teacher") { | ||||||
|  |             const cls = group.assignment.within; // TODO check if contains full objects
 | ||||||
|  |             return cls.teachers.map(mapToUsername).includes(auth.username); | ||||||
|  |         } else { // user is student
 | ||||||
|  |             return group.members.map(mapToUsername).includes(auth.username); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | @ -1,7 +1,11 @@ | ||||||
| import express from 'express'; | import express from 'express'; | ||||||
| import { createAnswerHandler, deleteAnswerHandler, getAnswerHandler, getAllAnswersHandler, updateAnswerHandler } from '../controllers/answers.js'; | import { createAnswerHandler, deleteAnswerHandler, getAnswerHandler, getAllAnswersHandler, updateAnswerHandler } from '../controllers/answers.js'; | ||||||
| import {adminOnly, authenticatedOnly, teachersOnly} from "../middleware/auth/checks/auth-checks"; | import {adminOnly, authenticatedOnly, teachersOnly} from "../middleware/auth/checks/auth-checks"; | ||||||
| import {onlyAllowAuthor, onlyAllowAuthorRequestAnswer} from "../middleware/auth/checks/question-checks"; | import { | ||||||
|  |     onlyAllowAuthor, | ||||||
|  |     onlyAllowAuthorRequestAnswer, | ||||||
|  |     onlyAllowIfHasAccessToQuestion | ||||||
|  | } from "../middleware/auth/checks/question-checks"; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| const router = express.Router({ mergeParams: true }); | const router = express.Router({ mergeParams: true }); | ||||||
|  | @ -10,7 +14,7 @@ router.get('/', adminOnly, getAllAnswersHandler); | ||||||
| 
 | 
 | ||||||
| router.post('/', teachersOnly, onlyAllowAuthor, createAnswerHandler); | router.post('/', teachersOnly, onlyAllowAuthor, createAnswerHandler); | ||||||
| 
 | 
 | ||||||
| router.get('/:seqAnswer', authenticatedOnly, getAnswerHandler); | router.get('/:seqAnswer', onlyAllowIfHasAccessToQuestion, getAnswerHandler); | ||||||
| 
 | 
 | ||||||
| router.delete('/:seqAnswer', teachersOnly, onlyAllowAuthorRequestAnswer, deleteAnswerHandler); | router.delete('/:seqAnswer', teachersOnly, onlyAllowAuthorRequestAnswer, deleteAnswerHandler); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,7 +3,11 @@ import { createQuestionHandler, deleteQuestionHandler, getAllQuestionsHandler, g | ||||||
| import answerRoutes from './answers.js'; | import answerRoutes from './answers.js'; | ||||||
| import {adminOnly, authenticatedOnly, studentsOnly} from "../middleware/auth/checks/auth-checks"; | import {adminOnly, authenticatedOnly, studentsOnly} from "../middleware/auth/checks/auth-checks"; | ||||||
| import {updateAnswerHandler} from "../controllers/answers"; | import {updateAnswerHandler} from "../controllers/answers"; | ||||||
| import {onlyAllowAuthor, onlyAllowAuthorRequest} from "../middleware/auth/checks/question-checks"; | import { | ||||||
|  |     onlyAllowAuthor, | ||||||
|  |     onlyAllowAuthorRequest, | ||||||
|  |     onlyAllowIfHasAccessToQuestion | ||||||
|  | } from "../middleware/auth/checks/question-checks"; | ||||||
| 
 | 
 | ||||||
| const router = express.Router({ mergeParams: true }); | const router = express.Router({ mergeParams: true }); | ||||||
| 
 | 
 | ||||||
|  | @ -15,7 +19,7 @@ router.get('/', adminOnly, getAllQuestionsHandler); | ||||||
| router.post('/', studentsOnly, onlyAllowAuthor, createQuestionHandler); | router.post('/', studentsOnly, onlyAllowAuthor, createQuestionHandler); | ||||||
| 
 | 
 | ||||||
| // Information about a question with id
 | // Information about a question with id
 | ||||||
| router.get('/:seq', authenticatedOnly, getQuestionHandler); // TODO every body in group + teachers?
 | router.get('/:seq', onlyAllowIfHasAccessToQuestion, getQuestionHandler); | ||||||
| 
 | 
 | ||||||
| router.delete('/:seq', studentsOnly, onlyAllowAuthorRequest, deleteQuestionHandler); | router.delete('/:seq', studentsOnly, onlyAllowAuthorRequest, deleteQuestionHandler); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ import { AssignmentDTO } from '@dwengo-1/common/interfaces/assignment'; | ||||||
| import { fetchStudent } from './students.js'; | import { fetchStudent } from './students.js'; | ||||||
| import { NotFoundException } from '../exceptions/not-found-exception'; | import { NotFoundException } from '../exceptions/not-found-exception'; | ||||||
| import { FALLBACK_VERSION_NUM } from '../config.js'; | import { FALLBACK_VERSION_NUM } from '../config.js'; | ||||||
|  | import {ConflictException} from "../exceptions/conflict-exception"; | ||||||
| 
 | 
 | ||||||
| export async function getQuestionsAboutLearningObjectInAssignment( | export async function getQuestionsAboutLearningObjectInAssignment( | ||||||
|     loId: LearningObjectIdentifier, |     loId: LearningObjectIdentifier, | ||||||
|  | @ -88,12 +89,20 @@ export async function createQuestion(loId: LearningObjectIdentifier, questionDat | ||||||
| 
 | 
 | ||||||
|     const clazz = await getClassRepository().findById((questionData.inGroup.assignment as AssignmentDTO).within); |     const clazz = await getClassRepository().findById((questionData.inGroup.assignment as AssignmentDTO).within); | ||||||
|     const assignment = mapToAssignment(questionData.inGroup.assignment as AssignmentDTO, clazz!); |     const assignment = mapToAssignment(questionData.inGroup.assignment as AssignmentDTO, clazz!); | ||||||
|     const inGroup = await getGroupRepository().findByAssignmentAndGroupNumber(assignment, questionData.inGroup.groupNumber); |     const group = await getGroupRepository().findByAssignmentAndGroupNumber(assignment, questionData.inGroup.groupNumber); | ||||||
|  | 
 | ||||||
|  |     if (!group){ | ||||||
|  |         throw new NotFoundException("Group with id and assignment not found"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (! group.members.contains(author)) { | ||||||
|  |         throw new ConflictException("Author is not part of this group"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     const question = await questionRepository.createQuestion({ |     const question = await questionRepository.createQuestion({ | ||||||
|         loId, |         loId, | ||||||
|         author, |         author, | ||||||
|         inGroup: inGroup!, |         inGroup: group!, | ||||||
|         content, |         content, | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Reference in a new issue
	
	 Gabriellvl
						Gabriellvl