From 91632ecf979adbf11e8af88eb6953986a9b478a2 Mon Sep 17 00:00:00 2001 From: Hajar RAHMOUNI Date: Sun, 8 Oct 2023 16:21:37 +0200 Subject: [PATCH 1/2] update route and delete-photo tests --- database/connection.js | 2 +- routes/announcement.js | 6 ++ test/routes.test.js | 236 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 240 insertions(+), 4 deletions(-) diff --git a/database/connection.js b/database/connection.js index a96ff52..c1c6259 100644 --- a/database/connection.js +++ b/database/connection.js @@ -2,7 +2,7 @@ const mongoose = require('mongoose'); require('dotenv').config(); const dbName = process.env.DB_NAME; -const url = `mongodb://monogodb:27017/${dbName}`; +const url = `mongodb://mongodb:27017/${dbName}`; const connectToDatabase = async () => { try { diff --git a/routes/announcement.js b/routes/announcement.js index cfbb2df..ea083d8 100644 --- a/routes/announcement.js +++ b/routes/announcement.js @@ -226,9 +226,11 @@ router.get('/delete/:id', isAuthenticated, isAgent, async (req, res) => { const deletedAnnouncement = await Announcement.findByIdAndRemove(announcementId); if (!deletedAnnouncement) { + console.log('404') return res.status(404).json({ message: 'annonce non trouvée' }); } if (user.username !== deletedAnnouncement.userName) { + console.log('403') return res.status(403).json({ message: 'User non autorisé' }); } @@ -250,16 +252,19 @@ router.get('/delete/:id', isAuthenticated, isAgent, async (req, res) => { // Route to delete a photo router.delete('/delete-photo/:announcementId/:filename', isAuthenticated, isAgent, async (req, res) => { try { + console.log('here ') const filename = req.params.filename; const announcementId = req.params.announcementId; const user = req.user; const announcement = await Announcement.findById(announcementId); if (!announcement) { + console.log('Annonce non trouvée') return res.status(404).json({ message: 'Annonce non trouvée' }); } if (!announcement.photos.includes(filename)) { + console.log('Photo non trouvée') return res.status(404).json({ message: 'Photo non trouvée' }); } @@ -280,6 +285,7 @@ router.delete('/delete-photo/:announcementId/:filename', isAuthenticated, isAgen return res.status(200).json({ message: 'Photo supprimée avec succès' }); } else { + console.log('Fichier non trouvé') return res.status(404).json({ message: 'Fichier introuvable' }); } } catch (error) { diff --git a/test/routes.test.js b/test/routes.test.js index aa72fa4..3ff76dd 100644 --- a/test/routes.test.js +++ b/test/routes.test.js @@ -511,7 +511,7 @@ describe('POST /add-announcement', () => { availabilityDate: '2023-10-15', }; - const filePath = '/home/firdaous/Téléchargements/img1.jpeg'; + const filePath = 'public/uploads/1696762934167-images.jpeg'; const stats = fs.statSync(filePath); const fileSizeInBytes = stats.size; @@ -559,7 +559,7 @@ describe('POST /add-announcement', () => { availabilityDate: '2023-10-15', }; - const filePath = '/home/firdaous/Téléchargements/img1.jpeg'; + const filePath = 'public/uploads/1696762934167-images.jpeg'; const stats = fs.statSync(filePath); const fileSizeInBytes = stats.size; @@ -588,7 +588,7 @@ describe('POST /add-announcement', () => { }); describe('GET /announcements/delete/:id', () => { - it('should delete an announcement for an authenticated agent', async () => { + it('should delete an announcement for an authenticated agent who s not the owner of the announcement', async () => { const announcement = new Announcement({ title: 'Exemple de titre', propertyType: 'À la vente', @@ -644,6 +644,236 @@ describe('GET /announcements/delete/:id', () => { const deletedAnnouncement = await Announcement.findById(announcement._id); expect(deletedAnnouncement).to.be.null; }); + + it('should not delete an announcement for an authenticated consultant', async () => { + const announcement = new Announcement({ + title: 'Exemple de titre- 2', + propertyType: 'À la vente', + publicationStatus: 'Publiée', + propertyStatus: 'Disponible', + description: 'Description de l\'annonce', + price: 200, + availabilityDate: new Date('2023-10-15'), + userName: 'rahmouni' + }); + + await announcement.save(); + + const consultant = chai.request.agent(app); + await consultant + .post('/login') + .send({ username: 'hajar', password: 'hajar' }); + + + const res = await consultant + .get(`/announcements/delete/${announcement._id}`) + + expect(res).to.have.status(403); + const deletedAnnouncement = await Announcement.findById(announcement._id); + expect(deletedAnnouncement).not.to.be.null; + }); + + describe('POST /announcements/:id/update', () => { + it('should allow an agent to update its announcement', async function () { + + const announcement = new Announcement({ + title: 'Exemple de titre', + propertyType: 'À la vente', + publicationStatus: 'Publiée', + propertyStatus: 'Disponible', + description: 'Description de l\'annonce', + price: 10000, + availabilityDate: new Date('2023-10-15'), + userName: 'elhalafi' + }); + + await announcement.save(); + + const agentAgent = chai.request.agent(app); + await agentAgent + .post('/login') + .send({ username: 'elhalafi', password: 'elhalafi' }); + + const updatedAnnouncementData = { + title: 'updated title', + description: 'Description de l\'annonce updated', + }; + const filePath = 'public/uploads/1696765095124-image.jpg'; + const stats = fs.statSync(filePath); + const fileSizeInBytes = stats.size; + const res = await agentAgent + .post(`/announcements/update/${announcement._id}`) + .field('title', updatedAnnouncementData.title) + .field('description', updatedAnnouncementData.description) + .attach('photos[]', filePath, { + filename: '1696765095124-image.jpg', + contentType: 'image/jpeg', + knownLength: fileSizeInBytes + }); + + expect(res).to.have.status(200); + const updatedAnnouncement = await Announcement.findById(announcement._id); + expect(updatedAnnouncement.title).to.equal(updatedAnnouncementData.title); + expect(updatedAnnouncement.description).to.equal(updatedAnnouncementData.description); + }); + + it('should allow an agent who is not the owner of the ad to update it', async function () { + + const announcement = new Announcement({ + title: 'Exemple de titre', + propertyType: 'À la vente', + publicationStatus: 'Publiée', + propertyStatus: 'Disponible', + description: 'Description de l\'annonce', + price: 10000, + availabilityDate: new Date('2023-10-15'), + userName: 'elhalafi' + }); + + await announcement.save(); + + const agentAgent = chai.request.agent(app); + await agentAgent + .post('/login') + .send({ username: 'rahmouni', password: 'rahmouni' }); + + const updatedAnnouncementData = { + title: 'updated title', + description: 'Description de l\'annonce updated', + }; + const filePath = 'public/uploads/1696765095124-image.jpg'; + const stats = fs.statSync(filePath); + const fileSizeInBytes = stats.size; + const res = await agentAgent + .post(`/announcements/update/${announcement._id}`) + .field('title', updatedAnnouncementData.title) + .field('description', updatedAnnouncementData.description) + .attach('photos[]', filePath, { + filename: '1696765095124-image.jpg', + contentType: 'image/jpeg', + knownLength: fileSizeInBytes + }); + + expect(res).to.have.status(403); + const updatedAnnouncement = await Announcement.findById(announcement._id); + expect(updatedAnnouncement.title).to.equal(updatedAnnouncementData.title); + expect(updatedAnnouncement.description).to.equal(updatedAnnouncementData.description); + }); + + it('should not allow a consultant to update an announcement', async function () { + + const announcement = new Announcement({ + title: 'T1 meublé', + propertyType: 'À la vente', + publicationStatus: 'Publiée', + propertyStatus: 'Disponible', + description: 'Description de l\'annonce', + price: 10000, + availabilityDate: new Date('2023-10-15'), + userName: 'elhalafi' + }); + + await announcement.save(); + + const consultantAgent = chai.request.agent(app); + await consultantAgent + .post('/login') + .send({ username: 'firdaous', password: 'firdaous' }); + + const updatedAnnouncementData = { + title: 'updated title', + description: 'Description de l\'annonce updated', + }; + const filePath = 'public/uploads/1696765095124-image.jpg'; + const stats = fs.statSync(filePath); + const fileSizeInBytes = stats.size; + const res = await consultantAgent + .post(`/announcements/update/${announcement._id}`) + .field('title', updatedAnnouncementData.title) + .field('description', updatedAnnouncementData.description) + .attach('photos[]', filePath, { + filename: '1696765095124-image.jpg', + contentType: 'image/jpeg', + knownLength: fileSizeInBytes + }); + + expect(res).to.have.status(403); + + // ON s'assure que l'annonce n'a pas été mise à jour + const updatedAnnouncement = await Announcement.findById(announcement._id); + expect(updatedAnnouncement.title).to.equal(announcement.title); + expect(updatedAnnouncement.description).to.equal(announcement.description); + }); + + }); + + describe('DELETE /delete-photo/:announcementId/:filename', () => { + it('should allow an agent to delete a photo from an announcement', async () => { + const agentAgent = chai.request.agent(app); + await agentAgent + .post('/login') + .send({ username: 'elhalafi', password: 'elhalafi' }); + + const announcement = new Announcement({ + title: 'Exemple de titre', + propertyType: 'À la vente', + publicationStatus: 'Publiée', + propertyStatus: 'Disponible', + description: 'Description de l\'annonce', + price: 10000, + availabilityDate: new Date('2023-10-15'), + userName: 'elhalafi', + photos: ['1696765095124-image.jpg', '1696770072099-image.jpg'] + }); + + await announcement.save(); + + const announcementId = announcement._id; + const filenameToDelete = '1696765095124-image.jpg'; + console.log(announcement); + const res = await agentAgent + .delete(`/announcements/delete-photo/${announcementId}/${filenameToDelete}`); + + expect(res).to.have.status(200); + expect(res.body.message).to.equal('Photo supprimée avec succès'); + + const updatedAnnouncement = await Announcement.findById(announcementId); + expect(updatedAnnouncement.photos).to.not.include(filenameToDelete); + }); + it('should allow an agent to delete a photo from an announcement that is not its annoucement', async () => { + const agentAgent = chai.request.agent(app); + await agentAgent + .post('/login') + .send({ username: 'hajar', password: 'hajar' }); + + const announcement = new Announcement({ + title: 'Exemple de titre', + propertyType: 'À la vente', + publicationStatus: 'Publiée', + propertyStatus: 'Disponible', + description: 'Description de l\'annonce', + price: 10000, + availabilityDate: new Date('2023-10-15'), + userName: 'elhalafi', + photos: ['1696765095124-image.jpg', '1696770072099-image.jpg'] + }); + + await announcement.save(); + + const announcementId = announcement._id; + const filenameToDelete = '1696765095124-image.jpg'; + console.log(announcement); + const res = await agentAgent + .delete(`/announcements/delete-photo/${announcementId}/${filenameToDelete}`); + + expect(res).to.have.status(403); + expect(res.body.message).to.equal('Vous n\'êtes pas autorisé à effectuer cette action.'); + + const updatedAnnouncement = await Announcement.findById(announcementId); + expect(updatedAnnouncement.photos).to.include(filenameToDelete); + }); + }); + }); -- GitLab From 402285f7d8800b81bfbd86037c4b27e95fb28301 Mon Sep 17 00:00:00 2001 From: Hajar RAHMOUNI Date: Sun, 8 Oct 2023 17:23:10 +0200 Subject: [PATCH 2/2] add backup uploads --- .../backup_uploads/1696775788500-image3.jpg | 0 test/routes.test.js | 58 ++++++++++++------- 2 files changed, 37 insertions(+), 21 deletions(-) create mode 100644 public/backup_uploads/1696775788500-image3.jpg diff --git a/public/backup_uploads/1696775788500-image3.jpg b/public/backup_uploads/1696775788500-image3.jpg new file mode 100644 index 0000000..e69de29 diff --git a/test/routes.test.js b/test/routes.test.js index 3ff76dd..b808d30 100644 --- a/test/routes.test.js +++ b/test/routes.test.js @@ -4,7 +4,7 @@ const app = require('../app'); const models = require("../schemas/models"); // Import your Express app const expect = chai.expect; const fs = require('fs'); - +const path = require('path'); chai.use(chaiHttp); describe('Authentication Routes', () => { @@ -511,7 +511,7 @@ describe('POST /add-announcement', () => { availabilityDate: '2023-10-15', }; - const filePath = 'public/uploads/1696762934167-images.jpeg'; + const filePath = 'public/uploads/1696775788500-image2.jpg'; const stats = fs.statSync(filePath); const fileSizeInBytes = stats.size; @@ -526,19 +526,19 @@ describe('POST /add-announcement', () => { .field('availabilityDate', announcementData.availabilityDate) .attach('photos[]', filePath, { filename: 'image.jpg', - contentType: 'image/jpeg', + contentType: 'image/jpg', knownLength: fileSizeInBytes }); expect(res).to.have.status(200); - await new Promise(resolve => setTimeout(resolve, 1500)); + /*await new Promise(resolve => setTimeout(resolve, 1500)); const announcementId = res.body._id; await Announcement.deleteOne({ _id: announcementId }); const uploadedFilePath = `/public/uploads/${res.body.photos[0]}`; if (fs.existsSync(uploadedFilePath)) { fs.unlinkSync(uploadedFilePath); - } + }*/ await agent.get('/logout'); }); @@ -559,7 +559,7 @@ describe('POST /add-announcement', () => { availabilityDate: '2023-10-15', }; - const filePath = 'public/uploads/1696762934167-images.jpeg'; + const filePath = 'public/uploads/1696775788500-image2.jpg'; const stats = fs.statSync(filePath); const fileSizeInBytes = stats.size; @@ -574,7 +574,7 @@ describe('POST /add-announcement', () => { .field('availabilityDate', announcementData.availabilityDate) .attach('photos', filePath, { filename: 'image.jpg', - contentType: 'image/jpeg', + contentType: 'image/jpg', knownLength: fileSizeInBytes }); @@ -698,7 +698,7 @@ describe('GET /announcements/delete/:id', () => { title: 'updated title', description: 'Description de l\'annonce updated', }; - const filePath = 'public/uploads/1696765095124-image.jpg'; + const filePath = 'public/uploads/1696775788500-image2.jpg'; const stats = fs.statSync(filePath); const fileSizeInBytes = stats.size; const res = await agentAgent @@ -706,8 +706,8 @@ describe('GET /announcements/delete/:id', () => { .field('title', updatedAnnouncementData.title) .field('description', updatedAnnouncementData.description) .attach('photos[]', filePath, { - filename: '1696765095124-image.jpg', - contentType: 'image/jpeg', + filename: '1696775788500-image2.jpg', + contentType: 'image/jpg', knownLength: fileSizeInBytes }); @@ -741,7 +741,7 @@ describe('GET /announcements/delete/:id', () => { title: 'updated title', description: 'Description de l\'annonce updated', }; - const filePath = 'public/uploads/1696765095124-image.jpg'; + const filePath = 'public/uploads/1696775788500-image2.jpg'; const stats = fs.statSync(filePath); const fileSizeInBytes = stats.size; const res = await agentAgent @@ -749,8 +749,8 @@ describe('GET /announcements/delete/:id', () => { .field('title', updatedAnnouncementData.title) .field('description', updatedAnnouncementData.description) .attach('photos[]', filePath, { - filename: '1696765095124-image.jpg', - contentType: 'image/jpeg', + filename: '1696775788500-image2.jpg', + contentType: 'image/jpg', knownLength: fileSizeInBytes }); @@ -784,7 +784,7 @@ describe('GET /announcements/delete/:id', () => { title: 'updated title', description: 'Description de l\'annonce updated', }; - const filePath = 'public/uploads/1696765095124-image.jpg'; + const filePath = 'public/uploads/1696775788500-image2.jpg'; const stats = fs.statSync(filePath); const fileSizeInBytes = stats.size; const res = await consultantAgent @@ -792,8 +792,8 @@ describe('GET /announcements/delete/:id', () => { .field('title', updatedAnnouncementData.title) .field('description', updatedAnnouncementData.description) .attach('photos[]', filePath, { - filename: '1696765095124-image.jpg', - contentType: 'image/jpeg', + filename: '1696775788500-image2.jpg', + contentType: 'image/jpg', knownLength: fileSizeInBytes }); @@ -823,14 +823,24 @@ describe('GET /announcements/delete/:id', () => { price: 10000, availabilityDate: new Date('2023-10-15'), userName: 'elhalafi', - photos: ['1696765095124-image.jpg', '1696770072099-image.jpg'] + photos: ['1696775788500-image3.jpg', '1696775788500-image2.jpg'] }); await announcement.save(); const announcementId = announcement._id; - const filenameToDelete = '1696765095124-image.jpg'; - console.log(announcement); + const filenameToDelete = '1696775788500-image2.jpg'; + + const uploads = 'public/backup_uploads'; + const originalFilePath = path.join('public', 'uploads', filenameToDelete); + const backupFilePath = path.join(uploads, filenameToDelete); + + // Copy the file to the backup folder before deleting + if (!fs.existsSync(uploads)) { + fs.mkdirSync(uploads); + } + fs.copyFileSync(originalFilePath, backupFilePath); + const res = await agentAgent .delete(`/announcements/delete-photo/${announcementId}/${filenameToDelete}`); @@ -839,6 +849,12 @@ describe('GET /announcements/delete/:id', () => { const updatedAnnouncement = await Announcement.findById(announcementId); expect(updatedAnnouncement.photos).to.not.include(filenameToDelete); + + // Restore the file to the uploads folder after the test + fs.copyFileSync(backupFilePath, originalFilePath); + + // Cleanup: Delete the backup file + fs.unlinkSync(backupFilePath); }); it('should allow an agent to delete a photo from an announcement that is not its annoucement', async () => { const agentAgent = chai.request.agent(app); @@ -855,13 +871,13 @@ describe('GET /announcements/delete/:id', () => { price: 10000, availabilityDate: new Date('2023-10-15'), userName: 'elhalafi', - photos: ['1696765095124-image.jpg', '1696770072099-image.jpg'] + photos: ['1696775788500-image2.jpg', '1696775788500-image3.jpg'] }); await announcement.save(); const announcementId = announcement._id; - const filenameToDelete = '1696765095124-image.jpg'; + const filenameToDelete = '1696775788500-image2.jpg'; console.log(announcement); const res = await agentAgent .delete(`/announcements/delete-photo/${announcementId}/${filenameToDelete}`); -- GitLab