diff --git a/app.js b/app.js
index 731a87c..8b709ef 100644
--- a/app.js
+++ b/app.js
@@ -14,7 +14,6 @@ const compression = require('compression')
const { UserModel } = require('./model/users')
const { BlogModel } = require('./model/blog')
-const { ImageModel } = require('./model/images')
const { callbacks } = require('./utils/callbacks')
const app = express()
@@ -66,11 +65,9 @@ app.get(`/${config.admin_route}`, (req, res) => {
const users = await UserModel.find().sort({ isAdmin: -1 }).exec()
const blog = await BlogModel.find()
- const images = await ImageModel.find().sort({ date: -1 })
return res.render('admin', {
users: (users) || [],
blog: (blog) || [],
- images: (images) || [],
version: config.VERSION
})
})(req, res)
diff --git a/model/images.js b/model/images.js
deleted file mode 100644
index 90a40a8..0000000
--- a/model/images.js
+++ /dev/null
@@ -1,24 +0,0 @@
-const mongoose = require('mongoose')
-
-const ImageSchema = new mongoose.Schema({
- filename: {
- type: String,
- required: true
- },
- description: {
- type: String,
- required: true
- },
- path: {
- type: String,
- required: true
- },
- date: {
- type: Date,
- required: true,
- default: Date.now
- }
-})
-
-const ImageModel = mongoose.model('image', ImageSchema)
-module.exports = { ImageSchema, ImageModel }
diff --git a/public/css/admin.css b/public/css/admin.css
index ff2c3f0..03646b9 100644
--- a/public/css/admin.css
+++ b/public/css/admin.css
@@ -70,18 +70,4 @@ section {
float: right;
}
-#delete-button-images{
- /* self style */
- background-color: red;
- color: var(--light-gray);
- border: none;
- border-radius: 3px;
- font-weight: 600;
-
- /* self align */
- height: 25px;
- width: 75px;
- float: right;
-}
-
/* ----------CSS for Delete Buttons ends here----------------- */
diff --git a/public/js/dashboard.js b/public/js/dashboard.js
index 35e1467..8915df6 100644
--- a/public/js/dashboard.js
+++ b/public/js/dashboard.js
@@ -1,4 +1,4 @@
-/* global blogTableSelections, usersTableSelections, imagesTableSelections, alert, XMLHttpRequest */
+/* global blogTableSelections, usersTableSelections, alert, XMLHttpRequest */
// uncheck all checkboxes on load and remove all data from selectionsArray(s) and hide Delete-Buttons
document.addEventListener('DOMContentLoaded', () => {
@@ -90,7 +90,6 @@ const deleteButtonVisibility = (tableId, buttonId) => {
const disableAllDeleteButtons = () => {
deleteButtonVisibility('blog-table', 'delete-button-blog')
deleteButtonVisibility('blog-table', 'delete-button-users')
- deleteButtonVisibility('images-table', 'delete-button-images')
}
const deleteHandler = async (route) => { // eslint-disable-line
@@ -105,10 +104,6 @@ const deleteHandler = async (route) => { // eslint-disable-line
selections = blogTableSelections
itemDesc = 'article'
break
- case 'image':
- selections = imagesTableSelections
- itemDesc = 'image'
- break
default:
console.log('deleteHandler: invalid selection')
return
diff --git a/public/js/editDb.js b/public/js/editDb.js
index 887c75a..b44b0ea 100644
--- a/public/js/editDb.js
+++ b/public/js/editDb.js
@@ -1,4 +1,4 @@
-/* global alert, XMLHttpRequest, FormData, IS_NEW, OBJ_ID */
+/* global alert, XMLHttpRequest, IS_NEW, OBJ_ID */
const editUser = (event) => { // eslint-disable-line
event.preventDefault()
@@ -137,27 +137,3 @@ const deleteBlog = () => { // eslint-disable-line
XHR.send()
}
-
-const editImage = (event) => { // eslint-disable-line
- event.preventDefault()
- const XHR = new XMLHttpRequest()
-
- // Success
- XHR.onreadystatechange = () => {
- if (XHR.readyState === 4) {
- if (XHR.status !== 200) {
- alert(JSON.parse(XHR.responseText).error)
- return
- }
-
- alert('Image saved succesfully')
- window.location.reload()
- }
- }
-
- XHR.open('POST', '/api/image')
- XHR.withCredentials = true
-
- const fd = new FormData(document.getElementById('edit-images-form'))
- XHR.send(fd)
-}
diff --git a/routes/api.js b/routes/api.js
index 8c7c8ab..4e2579f 100644
--- a/routes/api.js
+++ b/routes/api.js
@@ -6,12 +6,10 @@ const usersRoute = require('./users')
const blogRoute = require('./blog')
const contactRoute = require('./contact')
const editRoute = require('./edit')
-const imagesRoute = require('./images')
router.use('/users', passport.authenticate('loggedIn', { session: false }), usersRoute)
router.use('/edit', passport.authenticate('loggedIn', { session: false }), editRoute)
router.use('/blog', blogRoute)
router.use('/contact', contactRoute)
-router.use('/image', imagesRoute)
module.exports = router
diff --git a/routes/edit.js b/routes/edit.js
index d9d3b7f..b51d0e1 100644
--- a/routes/edit.js
+++ b/routes/edit.js
@@ -42,9 +42,4 @@ router.get('/user/:id', async (req, res, next) => {
return res.render('edit-user', { data: userExists, isNew: false })
})
-// Create new image
-router.get('/image', (req, res, next) => {
- return res.render('edit-image', { data: null, isNew: true })
-})
-
module.exports = router
diff --git a/routes/images.js b/routes/images.js
deleted file mode 100644
index a9b4431..0000000
--- a/routes/images.js
+++ /dev/null
@@ -1,115 +0,0 @@
-const fs = require('fs')
-const { resolve } = require('path')
-const express = require('express')
-const multer = require('multer')
-const mongoose = require('mongoose')
-const passport = require('passport')
-const { ImageModel } = require('../model/images')
-
-const router = express.Router()
-
-const storage = multer.diskStorage({
- destination: (req, file, cb) => {
- // Create directory if it doesnt exist.
- if (!fs.existsSync('uploads/')) {
- fs.mkdirSync('uploads/', { recursive: true })
- }
- cb(null, 'uploads/')
- },
- filename: (req, file, cb) => {
- // If its not a .jpeg, then it will be caught later.
- const suffix = (file.mimetype === 'image/png') ? '.png' : '.jpeg'
- const prefix = Date.now() + '-' + Math.round(Math.random() * 1E9)
- cb(null, prefix + suffix)
- }
-})
-
-const fileFilter = (req, file, cb) => {
- if (file.fieldname !== 'File' || file.encoding !== '7bit') {
- req.uploadFileError = 'Bad File Encoding'
- cb(null, false)
- return
- }
-
- if (file.mimetype !== 'image/png' && file.mimetype !== 'image/jpeg') {
- req.uploadFileError = 'bad file type: use .png or .jpeg instead'
- cb(null, false)
- return
- }
-
- cb(null, true)
-}
-
-// Max size: 25MB
-const upload = multer({ storage, fileFilter, limits: { fileSize: 26214400 } })
-
-// Return all images.
-router.get('/', passport.authenticate('loggedIn', { session: false }), async (req, res) => {
- const images = await ImageModel.find().sort({ date: -1 })
- if (!images) return res.status(404).send({ error: 'No posts found' })
- res.status(200).send(images)
-})
-
-// Return image by its id.
-router.get('/:id', async (req, res) => {
- if (!mongoose.Types.ObjectId.isValid(req.params.id)) {
- return res.status(400).send({ error: 'Invalid ID' })
- }
-
- const imageExists = await ImageModel.findById(req.params.id)
- if (!imageExists) {
- return res.status(404).send({ error: 'ID does not exist' })
- }
-
- // May exist in DB but not exist in filesystem.
- if (!fs.existsSync(imageExists.path)) {
- await ImageModel.findByIdAndDelete(req.params.id)
- return res.status(404).send({ error: 'image does not exist' })
- }
-
- res.status(200).sendFile(resolve(imageExists.path))
-})
-
-// Create a new image.
-router.post('/', passport.authenticate('loggedIn', { session: false }), upload.single('File'), (req, res) => {
- if (typeof req.uploadFileError === 'string') {
- return res.status(500).send({ error: req.uploadFileError })
- }
-
- if (!req.file || !req.body || !req.body.Description) {
- return res.status(500).send({ error: 'expected image and description' })
- }
-
- const image = new ImageModel({
- filename: req.file.filename,
- description: req.body.Description,
- path: req.file.path
- })
-
- image.save((err) => {
- if (err) return res.status(500).send({ error: 'Internal Server Error' })
- })
-
- return res.status(200).send(image)
-})
-
-// Delete an existing image by its ID.
-router.delete('/:id', passport.authenticate('loggedIn', { session: false }), async (req, res) => {
- if (!mongoose.Types.ObjectId.isValid(req.params.id)) {
- return res.status(400).send({ error: 'Invalid ID' })
- }
-
- const imageExists = await ImageModel.findByIdAndDelete(req.params.id)
- if (!imageExists) {
- return res.status(404).send({ error: 'ID does not exist' })
- }
-
- // Delete file (from disk) if it exists.
- if (fs.existsSync(imageExists.path)) {
- fs.unlinkSync(resolve(imageExists.path))
- }
-
- return res.status(200).send(imageExists)
-})
-
-module.exports = router
diff --git a/test/images.spec.js b/test/images.spec.js
deleted file mode 100644
index 98de1e8..0000000
--- a/test/images.spec.js
+++ /dev/null
@@ -1,198 +0,0 @@
-/* global describe, it, before */
-
-const fs = require('fs')
-const { resolve } = require('path')
-const chai = require('chai')
-const { app } = require('../app')
-const chaiHttp = require('chai-http')
-const TestHelper = require('./test-helper')
-const expect = chai.expect
-const UserModel = require('../model/users').UserModel
-const ImageModel = require('../model/images').ImageModel
-const auth = require('../auth/auth')
-const ENV = require('../utils/config').ENV
-
-chai.use(chaiHttp)
-let authenticatedAgent = null
-let agent = null
-
-describe('Images Route', () => {
- before(async () => {
- expect(ENV === 'development').to.equal(true)
- const user = await UserModel.findOne()
- authenticatedAgent = new TestHelper(chai, app, auth.tokenizeUser(user))
- agent = new TestHelper(chai, app)
- })
-
- // IMAGES-GET route.
- describe('Images: GET ROUTE', () => {
- it('Should require authentication', async () => {
- const unauthed = await agent.get('/api/image/')
- const authed = await authenticatedAgent.get('/api/image/')
- expect(unauthed.statusCode).to.equal(401)
- expect(authed.statusCode).to.equal(200)
- })
-
- it('Should return all images in database', async () => {
- const images = await authenticatedAgent.get('/api/image/')
- const dbImages = await ImageModel.find().sort({ date: -1 }).exec()
- expect(images.text).to.equal(JSON.stringify(dbImages))
- })
- })
-
- // IMAGES-GET-ID route.
- describe('Images: GET ID ROUTE', () => {
- it('Should not require authentication', async () => {
- const id = await ImageModel.findOne()
- const resp = await agent.get(`/api/image/${id.id}`)
- expect(resp.status).to.equal(200)
- })
-
- it('Should return an error when ID is malformed', async () => {
- const resp = await agent.get('/api/image/:641a2cbbe8f88f$3bd1a25f8')
- const resp1 = await agent.get('/api/image/123')
- expect(resp.status).to.equal(400)
- expect(resp1.status).to.equal(400)
- })
-
- it('Should return an error when ID is valid but doesnt exist', async () => {
- const resp = await agent.get('/api/image/64b3c0cf45b4dc3d407b7416')
- const resp1 = await agent.get('/api/image/64b3c0cf45b4dc3d407b7417')
- expect(resp.status).to.equal(404)
- expect(resp1.status).to.equal(404)
- })
-
- it('Should return an error when image doesnt exist on filesystem', async () => {
- const image = await ImageModel.findOne({ path: 'test/assets/doesnt-exist.jpeg' })
- expect(image).to.not.be.null // eslint-disable-line
- const resp = await agent.get(`/api/image/${image.id}`)
- expect(resp.status).to.equal(404)
- })
-
- it('Should return image file when image is registered and exists', async () => {
- const image = await ImageModel.findOne({ path: 'test/assets/1x1.png' })
- const resp = await agent.get(`/api/image/${image.id}`)
-
- // Returns image file.
- expect(resp.status).to.equal(200)
- expect(resp.type).to.equal('image/png')
-
- // Returns uncompressed image file.
- const data = fs.readFileSync(resolve('test/assets/1x1.png'))
- expect(data.equals(resp.body)).to.equal(true)
- })
- })
-
- // IMAGES-POST route.
- describe('Images: POST ROUTE', () => {
- it('Should return an error if user is not authenticated', async () => {
- const resp = await agent.post('/api/image/')
- expect(resp.status).to.equal(401)
- })
-
- it('Should return an error when encoding is not multiform', async () => {
- const user = await UserModel.findOne()
- const resp = await chai.request(app)
- .post('/api/image/')
- .set('Cookie', `jwt=${auth.tokenizeUser(user)}`)
- .set('Content-Type', 'application/json')
- .send({ description: 'desc', file: 'no file' })
-
- expect(resp.status).to.equal(500)
- })
-
- it('Should return an error if description is missing', async () => {
- const user = await UserModel.findOne()
- const data = fs.readFileSync(resolve('test/assets/1x1.png'))
- const resp = await chai.request(app).post('/api/image/')
- .set('Cookie', `jwt=${auth.tokenizeUser(user)}`)
- .attach('File', data, '1x1.png')
-
- expect(resp.status).to.equal(500)
- })
-
- it('Should return an error if image is missing', async () => {
- const user = await UserModel.findOne()
- const resp = await chai.request(app).post('/api/image/')
- .set('Cookie', `jwt=${auth.tokenizeUser(user)}`)
- .field('Description', 'my failed image upload')
-
- expect(resp.status).to.equal(500)
- })
-
- it('Should return an error if image is not jpeg or png', async () => {
- const user = await UserModel.findOne()
- const data = fs.readFileSync(resolve('test/assets/1x1.gif'))
- const resp = await chai.request(app).post('/api/image/')
- .set('Cookie', `jwt=${auth.tokenizeUser(user)}`)
- .field('Description', 'my failed image upload')
- .attach('File', data, '1x1.gif')
-
- expect(resp.status).to.equal(500)
- })
-
- it('Should return saved image model', async () => {
- const user = await UserModel.findOne()
- const data = fs.readFileSync(resolve('test/assets/1x1.png'))
- const resp = await chai.request(app).post('/api/image/')
- .set('Cookie', `jwt=${auth.tokenizeUser(user)}`)
- .field('Description', 'my image upload')
- .attach('File', data, '1x1.png')
-
- expect(resp.status).to.equal(200)
- const respData = JSON.parse(resp.text)
- const dbData = await ImageModel.findById(respData._id)
- expect(dbData === null).to.equal(false)
- })
-
- it('Should save image to filesystem and database', async () => {
- const user = await UserModel.findOne()
- const data = fs.readFileSync(resolve('test/assets/1x1.png'))
- const resp = await chai.request(app).post('/api/image/')
- .set('Cookie', `jwt=${auth.tokenizeUser(user)}`)
- .field('Description', 'my image upload')
- .attach('File', data, '1x1.png')
-
- expect(resp.status).to.equal(200)
- const path = JSON.parse(resp.text).path
- expect(fs.existsSync(path)).to.be.true // eslint-disable-line
- })
- })
-
- // IMAGES-DELETE route.
- describe('Images: DELETE ROUTE', () => {
- it('Should require authentication', async () => {
- const resp = await agent.post('/api/image/')
- expect(resp.status).to.equal(401)
- })
-
- it('Should return an error if ID is malformed', async () => {
- const resp = await authenticatedAgent.delete('/api/image/:641a2cbbe8f88f$3bd1a25f8')
- const resp1 = await authenticatedAgent.delete('/api/image/123')
- expect(resp.status).to.equal(400)
- expect(resp1.status).to.equal(400)
- })
-
- it('Should return an error if ID is valid but does not exist', async () => {
- const resp = await authenticatedAgent.delete('/api/image/64b3c0cf45b4dc3d407b7416')
- const resp1 = await authenticatedAgent.delete('/api/image/64b3c0cf45b4dc3d407b7417')
- expect(resp.status).to.equal(404)
- expect(resp1.status).to.equal(404)
- })
-
- it('Should delete image from database', async () => {
- const image = await ImageModel.findOne({ path: { $ne: 'test/assets/1x1.png' } })
- const resp = await authenticatedAgent.delete(`/api/image/${image.id}`)
- expect(resp.status).to.equal(200)
- const isDeleted = await ImageModel.findById(image.id)
- expect(isDeleted).to.be.null // eslint-disable-line
- })
-
- it('Should delete image from filesystem if it exists', async () => {
- const image = await ImageModel.findOne({ path: { $ne: 'test/assets/1x1.png' } })
- const resp = await authenticatedAgent.delete(`/api/image/${image.id}`)
- expect(resp.status).to.equal(200)
- expect(fs.existsSync(image.path)).to.be.false // eslint-disable-line
- })
- })
-})
diff --git a/utils/seed.js b/utils/seed.js
index a36e47f..94d19b8 100644
--- a/utils/seed.js
+++ b/utils/seed.js
@@ -4,7 +4,6 @@ const mongoose = require('mongoose')
const { hashPassword } = require('../auth/auth')
const { UserModel } = require('../model/users')
const { BlogModel } = require('../model/blog')
-const { ImageModel } = require('../model/images')
const seed = async () => {
if (config.ENV !== 'development') {
@@ -22,7 +21,6 @@ const seed = async () => {
try {
await UserModel.collection.drop()
await BlogModel.collection.drop()
- await ImageModel.collection.drop()
console.log('Reset database succesfully')
} catch (error) {
console.log('ERROR while resetting database: ', error)
@@ -64,32 +62,11 @@ const seed = async () => {
author: ['admin2']
})
- const imageA = new ImageModel({
- filename: '1689501903131-459608087.png',
- description: 'lorem ipsum dolor',
- path: 'test/assets/1x1.png'
- })
-
- const imageB = new ImageModel({
- filename: '1689502000136-727547610.png',
- description: 'lorem ipsum dolor',
- path: 'test/assets/1x1.png'
- })
-
- const imageC = new ImageModel({
- filename: '1689502000136-727547610.png',
- description: 'lorem ipsum dolor',
- path: 'test/assets/doesnt-exist.jpeg'
- })
-
await userAdmin.save()
await userB.save()
await blogA.save()
await blogA.save()
await blogB.save()
- await imageA.save()
- await imageB.save()
- await imageC.save()
console.log('Finished seeding')
mongoose.connection.close()
diff --git a/views/admin.ejs b/views/admin.ejs
index 23c1723..fe810e3 100644
--- a/views/admin.ejs
+++ b/views/admin.ejs
@@ -21,7 +21,6 @@
@@ -54,21 +53,6 @@
<%- include('./components/users-table.ejs', { data: users }) %>
- Images
-
-
diff --git a/views/components/images-table.ejs b/views/components/images-table.ejs deleted file mode 100644 index 890dd91..0000000 --- a/views/components/images-table.ejs +++ /dev/null @@ -1,44 +0,0 @@ -
- - | -Path | -Description | -Preview | - - - <% data.forEach((entry) => { %> -|
---|---|---|---|---|
- - | -<%= `/api/image/${entry.id}` %> | -<%= entry.description %> | -- - | -|
- | - | - | - | - |
diff --git a/views/edit-image.ejs b/views/edit-image.ejs deleted file mode 100644 index a5acfe3..0000000 --- a/views/edit-image.ejs +++ /dev/null @@ -1,45 +0,0 @@ - - -
- - - -
- - - - - - - -
-