From b4a74a7c3428a1db5e47ef598af45a84ec08efd7 Mon Sep 17 00:00:00 2001 From: abdelrahman ragab hashem Date: Tue, 20 Apr 2021 22:16:11 +0200 Subject: [PATCH 1/5] feat: implement save exam recording --- .../Event/Exam/exam-logic-impl.ts | 11 ++++++++++ .../BusinessLogic/Event/Exam/exam-logic.ts | 1 + services/Routes/Event/Exam/index.ts | 21 +++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/controller/BusinessLogic/Event/Exam/exam-logic-impl.ts b/controller/BusinessLogic/Event/Exam/exam-logic-impl.ts index 258906b..55d00a8 100644 --- a/controller/BusinessLogic/Event/Exam/exam-logic-impl.ts +++ b/controller/BusinessLogic/Event/Exam/exam-logic-impl.ts @@ -2,7 +2,10 @@ import Exam from "@models/Events/Exam"; import UserInputError from "@services/utils/UserInputError"; import { getRepository } from "typeorm"; import ExamsLogic from "./exam-logic"; +import { mkdir, appendFile } from 'fs/promises' +import { join } from 'path' +let upload_folder = process.env['UPLOADED_RECORDING_PATH'] || 'recordings'; export default class ExamsLogicImpl implements ExamsLogic { async getExamById(examId: string): Promise { const res = await getRepository(Exam).findOne(examId) @@ -34,4 +37,12 @@ export default class ExamsLogicImpl implements ExamsLogic { async createExam(exam: Exam): Promise { return await getRepository(Exam).save(exam) } + async saveRecording(chunk: Buffer, examId: string, userId: string): Promise { + let video_dir = join(upload_folder, examId) + + await mkdir(video_dir, { recursive: true }) + + // TODO make sure the chunk order is right + await appendFile(join(video_dir, `${userId}.webm`), chunk) + } } \ No newline at end of file diff --git a/controller/BusinessLogic/Event/Exam/exam-logic.ts b/controller/BusinessLogic/Event/Exam/exam-logic.ts index 51b8a1b..60c9d60 100644 --- a/controller/BusinessLogic/Event/Exam/exam-logic.ts +++ b/controller/BusinessLogic/Event/Exam/exam-logic.ts @@ -6,4 +6,5 @@ export default interface ExamsLogic { updateExam(examId: string, newData: Exam) : Promise; deleteExamById(examId: string) : Promise; getExamsByYear(year: number): Promise; + saveRecording(chunk: Buffer, examId: string, userId: string) : void; } \ No newline at end of file diff --git a/services/Routes/Event/Exam/index.ts b/services/Routes/Event/Exam/index.ts index 1f17528..f25e53f 100644 --- a/services/Routes/Event/Exam/index.ts +++ b/services/Routes/Event/Exam/index.ts @@ -5,6 +5,7 @@ import ExamParser, { ExamRequest } from "@services/Routes/BodyParserMiddleware/E import ExamsLogic from "@controller/BusinessLogic/Event/Exam/exam-logic" import ExamsLogicImpl from "@controller/BusinessLogic/Event/Exam/exam-logic-impl" import simpleFinalMWDecorator from "@services/utils/RequestDecorator" +import multer from "multer" const router = Router() @@ -13,6 +14,26 @@ router.use(passport.authenticate('access-token', { session: false })) const parser: BodyParserMiddleware = new ExamParser() +var storage = multer.memoryStorage(); +var upload = multer({ storage: storage }); + +/** + * save exam recording + * + * req body must contain + * - usedId + * - examId + * - chunckIndex : number of current chunk + * - chuck : actual recorded chunk in webm format + // TODO add parser to validate the exam info fields + */ +router.put('/record', upload.single('chuck'), async (req, res) => { + simpleFinalMWDecorator(res, async () => { + const logic: ExamsLogic = new ExamsLogicImpl() + await logic.saveRecording(req.file.buffer, req.body.examId, req.body.userId); + }) +}) + router.get('/:examId', async (req, res) => { simpleFinalMWDecorator(res, async () => { const logic: ExamsLogic = new ExamsLogicImpl() From 33b81c8b992c959d67223e75bc8b72a9b108387f Mon Sep 17 00:00:00 2001 From: abdelrahman ragab hashem Date: Tue, 20 Apr 2021 22:17:36 +0200 Subject: [PATCH 2/5] ignore recording folder --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index d13e313..fd853ff 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ todo localhost.pem localhost-key.pem lectures/ -ormconfig.json \ No newline at end of file +ormconfig.json +recordings/ From 877df671c5b49ef209b7b9907b637abdda17d12b Mon Sep 17 00:00:00 2001 From: abdelrahman ragab hashem Date: Tue, 20 Apr 2021 22:30:57 +0200 Subject: [PATCH 3/5] fix: workaroud fix import for eg-tsom --- controller/BusinessLogic/Event/Exam/exam-logic-impl.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/controller/BusinessLogic/Event/Exam/exam-logic-impl.ts b/controller/BusinessLogic/Event/Exam/exam-logic-impl.ts index 55d00a8..84bbdac 100644 --- a/controller/BusinessLogic/Event/Exam/exam-logic-impl.ts +++ b/controller/BusinessLogic/Event/Exam/exam-logic-impl.ts @@ -2,7 +2,9 @@ import Exam from "@models/Events/Exam"; import UserInputError from "@services/utils/UserInputError"; import { getRepository } from "typeorm"; import ExamsLogic from "./exam-logic"; -import { mkdir, appendFile } from 'fs/promises' +import { promises } from 'fs' +const mkdir = promises.mkdir +const appendFile = promises.appendFile import { join } from 'path' let upload_folder = process.env['UPLOADED_RECORDING_PATH'] || 'recordings'; From 896077a92487353822a06dcf9ade97353c8c322c Mon Sep 17 00:00:00 2001 From: A-Siam Date: Wed, 21 Apr 2021 00:22:18 +0200 Subject: [PATCH 4/5] restrict examination to students only --- services/Routes/Event/Exam/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/Routes/Event/Exam/index.ts b/services/Routes/Event/Exam/index.ts index f25e53f..72fee73 100644 --- a/services/Routes/Event/Exam/index.ts +++ b/services/Routes/Event/Exam/index.ts @@ -6,6 +6,7 @@ import ExamsLogic from "@controller/BusinessLogic/Event/Exam/exam-logic" import ExamsLogicImpl from "@controller/BusinessLogic/Event/Exam/exam-logic-impl" import simpleFinalMWDecorator from "@services/utils/RequestDecorator" import multer from "multer" +import { onlyStudents } from "@services/Routes/User/AuthorizationMiddleware" const router = Router() @@ -27,7 +28,7 @@ var upload = multer({ storage: storage }); * - chuck : actual recorded chunk in webm format // TODO add parser to validate the exam info fields */ -router.put('/record', upload.single('chuck'), async (req, res) => { +router.put('/record',onlyStudents, upload.single('chuck'), async (req, res) => { simpleFinalMWDecorator(res, async () => { const logic: ExamsLogic = new ExamsLogicImpl() await logic.saveRecording(req.file.buffer, req.body.examId, req.body.userId); From 77eec277d24e96387ac973dc0e79d22e28b2b482 Mon Sep 17 00:00:00 2001 From: abdelrahman ragab hashem Date: Wed, 21 Apr 2021 00:37:01 +0200 Subject: [PATCH 5/5] fix: exam interface --- controller/BusinessLogic/Event/Exam/exam-logic.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/BusinessLogic/Event/Exam/exam-logic.ts b/controller/BusinessLogic/Event/Exam/exam-logic.ts index 60c9d60..f8baca7 100644 --- a/controller/BusinessLogic/Event/Exam/exam-logic.ts +++ b/controller/BusinessLogic/Event/Exam/exam-logic.ts @@ -6,5 +6,5 @@ export default interface ExamsLogic { updateExam(examId: string, newData: Exam) : Promise; deleteExamById(examId: string) : Promise; getExamsByYear(year: number): Promise; - saveRecording(chunk: Buffer, examId: string, userId: string) : void; + saveRecording(chunk: Buffer, examId: string, userId: string) : Promise; } \ No newline at end of file