diff --git a/api/openapi.yaml b/api/openapi.yaml index 859736f4264f87c52b150231b95501cbc9fcbdad..c9ea4d582e467d54a04af8e03dfc4af03b0f2315 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -195,6 +195,44 @@ paths: "500": description: Erreur serveur interne. Veuillez réessayer plus tard. x-swagger-router-controller: Ad + + /announcements/{id}/photos: + post: + tags: + - ad + summary: Add photos to an ad + description: Upload photos to an existing ad. + operationId: addPhotosToAd + parameters: + - name: id + in: path + description: ID of the ad to which photos will be added + required: true + schema: + type: string + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + photos: + type: array + items: + type: string + format: binary + security: + - bearerAuth: [ ] + responses: + '200': + description: Success. Returns the updated ad details. + '404': + description: Ad not found. + '500': + description: Internal server error. Please try again later. + x-swagger-router-controller: Ad + + /announcements/{id}/ask: put: tags: @@ -423,6 +461,9 @@ components: availabilityDate: type: string format: date-time + photos: + type: string + format: binary required: - title - propertyType diff --git a/controllers/Ad.js b/controllers/Ad.js index 38e88fdcd95b3a2c07eab34bfdb3c82e056722ea..55061a45f67dc81408c03ffb8b52617330ce1841 100644 --- a/controllers/Ad.js +++ b/controllers/Ad.js @@ -2,7 +2,8 @@ const express = require('express'); const router = express.Router(); const AdService = require('../service/AdService'); const utils = require('../utils/writer.js'); - +const multer = require('multer'); +const upload = multer(); const extractToken = (req, res, next) => { req.token = req.headers.authorization ? req.headers.authorization.split(' ')[1] : null; next(); @@ -76,4 +77,12 @@ router.put('/:id/question/:questionId/answer', extractToken, async (req, res) => } }); +router.post('/:id/photos', extractToken, upload.array('photos'), async (req, res) => { + try { + const response = await AdService.addPhotosToAd(req.params.id, req.files); + utils.writeJson(res, response); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}); module.exports = router; diff --git a/models/Ad.js b/models/Ad.js index 340aa57c3299375a41716a4c738aad5219de163b..d2105c899a098a1cdfa3dcecd5b3989aadd39df9 100644 --- a/models/Ad.js +++ b/models/Ad.js @@ -22,7 +22,7 @@ const AdSchema = new Schema({ description: { type: String, required: true }, price: { type:Number, required: true }, availabilityDate: { type: Date, required: true }, - photos:{ type: [String] }, + photos: [{ type: String }], userName: { type: String, required: true }, questions: [ { diff --git a/package-lock.json b/package-lock.json index d48a5dade108251441a22b4f41addc76bb53fe2e..21be0993e03d8812030575206fb9c357bb5640a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "js-yaml": "^3.3.0", "jsonwebtoken": "^9.0.2", "mongoose": "^7.6.3", + "multer": "^1.4.5-lts.1", "oas3-tools": "^2.2.3", "passport": "^0.6.0", "passport-local": "^1.0.0", @@ -458,15 +459,14 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/busboy": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", - "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", "dependencies": { - "dicer": "0.2.5", - "readable-stream": "1.1.x" + "streamsearch": "^1.1.0" }, "engines": { - "node": ">=0.8.0" + "node": ">=10.16.0" } }, "node_modules/bytes": { @@ -726,6 +726,14 @@ "node": ">=0.8.0" } }, + "node_modules/dicer/node_modules/streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -870,47 +878,11 @@ "path-to-regexp": "^6.2.0" } }, - "node_modules/express-openapi-validator/node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, - "node_modules/express-openapi-validator/node_modules/multer": { - "version": "1.4.5-lts.1", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", - "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", - "dependencies": { - "append-field": "^1.0.0", - "busboy": "^1.0.0", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", - "object-assign": "^4.1.1", - "type-is": "^1.6.4", - "xtend": "^4.0.0" - }, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/express-openapi-validator/node_modules/path-to-regexp": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" }, - "node_modules/express-openapi-validator/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/express-session": { "version": "1.17.3", "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", @@ -1860,22 +1832,20 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/multer": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", - "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", - "deprecated": "Multer 1.x is affected by CVE-2022-24434. This is fixed in v1.4.4-lts.1 which drops support for versions of Node.js before 6. Please upgrade to at least Node.js 6 and version 1.4.4-lts.1 of Multer. If you need support for older versions of Node.js, we are open to accepting patches that would fix the CVE on the main 1.x release line, whilst maintaining compatibility with Node.js 0.10.", + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", "dependencies": { "append-field": "^1.0.0", - "busboy": "^0.2.11", + "busboy": "^1.0.0", "concat-stream": "^1.5.2", "mkdirp": "^0.5.4", "object-assign": "^4.1.1", - "on-finished": "^2.3.0", "type-is": "^1.6.4", "xtend": "^4.0.0" }, "engines": { - "node": ">= 0.10.0" + "node": ">= 6.0.0" } }, "node_modules/negotiator": { @@ -1974,6 +1944,18 @@ "serve-static": "^1.14.1" } }, + "node_modules/oas3-tools/node_modules/busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==", + "dependencies": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/oas3-tools/node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1995,6 +1977,25 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/oas3-tools/node_modules/multer": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", + "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", + "deprecated": "Multer 1.x is affected by CVE-2022-24434. This is fixed in v1.4.4-lts.1 which drops support for versions of Node.js before 6. Please upgrade to at least Node.js 6 and version 1.4.4-lts.1 of Multer. If you need support for older versions of Node.js, we are open to accepting patches that would fix the CVE on the main 1.x release line, whilst maintaining compatibility with Node.js 0.10.", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -2476,11 +2477,11 @@ } }, "node_modules/streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", "engines": { - "node": ">=0.8.0" + "node": ">=10.0.0" } }, "node_modules/string_decoder": { diff --git a/package.json b/package.json index 6a559e53178c8162783f312b230d585f95546eac..ed75a0522b8b199538b5738c5ac2e557b2adcc0a 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "js-yaml": "^3.3.0", "jsonwebtoken": "^9.0.2", "mongoose": "^7.6.3", + "multer": "^1.4.5-lts.1", "oas3-tools": "^2.2.3", "passport": "^0.6.0", "passport-local": "^1.0.0", diff --git a/service/AdService.js b/service/AdService.js index 39d11dccafb13365ae95d595feb3b61f8d85ea34..0902265eb1b63da3abd329f51f22218fac5afd85 100644 --- a/service/AdService.js +++ b/service/AdService.js @@ -1,6 +1,7 @@ const Ad = require('../models/Ad'); const User = require('../models/User'); - +const fs = require('fs'); +const path = require('path'); const {extractUserFromToken} = require("./UserService"); const secretKey = 'secretKey'; @@ -44,6 +45,33 @@ exports.addAd = async function (body, token) { } }; +// Service for adding photos to an ad +exports.addPhotosToAd = async function (announcementId, photos) { + try { + console.log(announcementId, ' ', photos); + + const photoPaths = photos.map(file => { + const photoFileName = `${Date.now()}_${file.originalname}`; + const relativePath = path.relative(process.cwd(), path.join(process.cwd(), 'uploads', photoFileName)); + fs.writeFileSync(relativePath, file.buffer); + return relativePath; + }); + + const updatedAnnouncement = await Ad.findByIdAndUpdate( + announcementId, + { $push: { photos: { $each: photoPaths } } }, + { new: true } + ); + + if (!updatedAnnouncement) { + return { status: 404, message: 'Ad not found.' }; + } + + return { status: 200, message: 'Photos added successfully.', updatedAd: updatedAnnouncement }; + } catch (error) { + throw error; + } +}; // Méthode pour mettre à jour une annonce exports.updateAd = async function (announcementId, reqBody, token) {