From 78353d6b656dc83da2e519ca846835cd87afb601 Mon Sep 17 00:00:00 2001 From: Gerald Schmittinger Date: Mon, 5 May 2025 23:38:18 +0200 Subject: [PATCH] feat(backend): Controller en route voor het aanmaken van leerobjecten aangemaakt. --- backend/package.json | 2 + backend/src/controllers/learning-objects.ts | 8 +++ backend/src/routes/learning-objects.ts | 11 +++- .../learning-object-service.ts | 3 +- .../learning-object-zip-processing-service.ts | 9 ++-- package-lock.json | 54 +++++++++++++++++++ 6 files changed, 81 insertions(+), 6 deletions(-) diff --git a/backend/package.json b/backend/package.json index 7b2ab878..a95cd334 100644 --- a/backend/package.json +++ b/backend/package.json @@ -31,6 +31,7 @@ "cross-env": "^7.0.3", "dotenv": "^16.4.7", "express": "^5.0.1", + "express-fileupload": "^1.5.1", "express-jwt": "^8.5.1", "gift-pegjs": "^1.0.2", "isomorphic-dompurify": "^2.22.0", @@ -51,6 +52,7 @@ "@mikro-orm/cli": "6.4.12", "@types/cors": "^2.8.17", "@types/express": "^5.0.0", + "@types/express-fileupload": "^1.5.1", "@types/js-yaml": "^4.0.9", "@types/node": "^22.13.4", "@types/response-time": "^2.3.8", diff --git a/backend/src/controllers/learning-objects.ts b/backend/src/controllers/learning-objects.ts index 83aa33f9..3622912c 100644 --- a/backend/src/controllers/learning-objects.ts +++ b/backend/src/controllers/learning-objects.ts @@ -7,6 +7,7 @@ import { BadRequestException } from '../exceptions/bad-request-exception.js'; import { NotFoundException } from '../exceptions/not-found-exception.js'; import { envVars, getEnvVar } from '../util/envVars.js'; import { FilteredLearningObject, LearningObjectIdentifierDTO, LearningPathIdentifier } from '@dwengo-1/common/interfaces/learning-content'; +import {UploadedFile} from "express-fileupload"; function getLearningObjectIdentifierFromRequest(req: Request): LearningObjectIdentifierDTO { if (!req.params.hruid) { @@ -72,3 +73,10 @@ export async function getAttachment(req: Request, res: Response): Promise } res.setHeader('Content-Type', attachment.mimeType).send(attachment.content); } + +export async function handlePostLearningObject(req: Request, res: Response): Promise { + if (!req.files || !req.files[0]) { + throw new BadRequestException('No file uploaded'); + } + await learningObjectService.storeLearningObject((req.files[0] as UploadedFile).tempFilePath); +} diff --git a/backend/src/routes/learning-objects.ts b/backend/src/routes/learning-objects.ts index 7532765b..254d7ebc 100644 --- a/backend/src/routes/learning-objects.ts +++ b/backend/src/routes/learning-objects.ts @@ -1,8 +1,15 @@ import express from 'express'; -import { getAllLearningObjects, getAttachment, getLearningObject, getLearningObjectHTML } from '../controllers/learning-objects.js'; +import { + getAllLearningObjects, + getAttachment, + getLearningObject, + getLearningObjectHTML, + handlePostLearningObject +} from '../controllers/learning-objects.js'; import submissionRoutes from './submissions.js'; import questionRoutes from './questions.js'; +import fileUpload from "express-fileupload"; const router = express.Router(); @@ -18,6 +25,8 @@ const router = express.Router(); // Example 2: http://localhost:3000/learningObject?full=true&hruid=un_artificiele_intelligentie router.get('/', getAllLearningObjects); +router.post('/', fileUpload({useTempFiles: true}), handlePostLearningObject) + // Parameter: hruid of learning object // Query: language // Route to fetch data of one learning object based on its hruid diff --git a/backend/src/services/learning-objects/learning-object-service.ts b/backend/src/services/learning-objects/learning-object-service.ts index 4f5409fd..9a0912ae 100644 --- a/backend/src/services/learning-objects/learning-object-service.ts +++ b/backend/src/services/learning-objects/learning-object-service.ts @@ -9,6 +9,7 @@ import { } from '@dwengo-1/common/interfaces/learning-content'; import {getLearningObjectRepository} from "../../data/repositories"; import {processLearningObjectZip} from "./learning-object-zip-processing-service"; +import {BadRequestException} from "../../exceptions/bad-request-exception"; function getProvider(id: LearningObjectIdentifierDTO): LearningObjectProvider { if (id.hruid.startsWith(getEnvVar(envVars.UserContentPrefix))) { @@ -58,7 +59,7 @@ const learningObjectService = { const learningObject = await processLearningObjectZip(learningObjectPath); if (!learningObject.hruid.startsWith(getEnvVar(envVars.UserContentPrefix))) { - throw Error("Learning object name must start with the user content prefix!"); + throw new BadRequestException("Learning object name must start with the user content prefix!"); } await learningObjectRepository.save(learningObject, {preventOverwrite: true}); diff --git a/backend/src/services/learning-objects/learning-object-zip-processing-service.ts b/backend/src/services/learning-objects/learning-object-zip-processing-service.ts index 3dbd5915..fcf80e2b 100644 --- a/backend/src/services/learning-objects/learning-object-zip-processing-service.ts +++ b/backend/src/services/learning-objects/learning-object-zip-processing-service.ts @@ -1,8 +1,9 @@ import unzipper from 'unzipper'; import mime from 'mime-types'; -import {LearningObjectMetadata} from "@dwengo-1/common/dist/interfaces/learning-content"; import {LearningObject} from "../../entities/content/learning-object.entity"; import {getAttachmentRepository, getLearningObjectRepository} from "../../data/repositories"; +import {BadRequestException} from "../../exceptions/bad-request-exception"; +import {LearningObjectMetadata} from "@dwengo-1/common/dist/interfaces/learning-content"; /** * Process an uploaded zip file and construct a LearningObject from its contents. @@ -20,7 +21,7 @@ export async function processLearningObjectZip(filePath: string): Promise=10.16.0" + } + }, "node_modules/bytes": { "version": "3.1.2", "license": "MIT", @@ -4235,6 +4269,18 @@ "url": "https://opencollective.com/express" } }, + "node_modules/express-fileupload": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.5.1.tgz", + "integrity": "sha512-LsYG1ALXEB7vlmjuSw8ABeOctMp8a31aUC5ZF55zuz7O2jLFnmJYrCv10py357ky48aEoBQ/9bVXgFynjvaPmA==", + "license": "MIT", + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/express-jwt": { "version": "8.5.1", "license": "MIT", @@ -7798,6 +7844,14 @@ "dev": true, "license": "MIT" }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "license": "MIT",