From 702075b66dcc22bfa5e018f6a764ab23c8f9a9f5 Mon Sep 17 00:00:00 2001 From: Pitu <7425261+Pitu@users.noreply.github.com> Date: Tue, 3 Oct 2017 21:13:38 -0300 Subject: [PATCH] ES6 rewrite --- controllers/albumsController.js | 289 +++++++++----------- controllers/authController.js | 136 +++++----- controllers/tokenController.js | 64 ++--- controllers/uploadController.js | 456 ++++++++++++++------------------ controllers/utilsController.js | 56 ++-- routes/album.js | 91 +++---- routes/api.js | 66 +++-- 7 files changed, 517 insertions(+), 641 deletions(-) diff --git a/controllers/albumsController.js b/controllers/albumsController.js index 7b9cc46..7c9c7da 100644 --- a/controllers/albumsController.js +++ b/controllers/albumsController.js @@ -1,175 +1,132 @@ -const config = require('../config.js') -const db = require('knex')(config.database) -const randomstring = require('randomstring') -const utils = require('./utilsController.js') -const path = require('path') +const config = require('../config.js'); +const db = require('knex')(config.database); +const randomstring = require('randomstring'); +const utils = require('./utilsController.js'); +const path = require('path'); -let albumsController = {} +const albumsController = {}; -albumsController.list = function(req, res, next) { +albumsController.list = async (req, res, next) => { + const user = await utils.authorize(req, res); - let token = req.headers.token - if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' }) + const fields = ['id', 'name']; + if (req.params.sidebar === undefined) { + fields.push('timestamp'); + fields.push('identifier'); + } - db.table('users').where('token', token).then((user) => { - if (user.length === 0) return res.status(401).json({ success: false, description: 'Invalid token' }) + const albums = await db.table('albums').select(fields).where({ enabled: 1, userid: user.id }); + if (req.params.sidebar !== undefined) { + return res.json({ success: true, albums }); + } - let fields = ['id', 'name'] + let ids = []; + for (let album of albums) { + album.date = new Date(album.timestamp * 1000) + album.date = utils.getPrettyDate(album.date) - if (req.params.sidebar === undefined) { - fields.push('timestamp') - fields.push('identifier') + album.identifier = `${config.domain}/a/${album.identifier}`; + ids.push(album.id); + } + + const files = await db.table('files').whereIn('albumid', ids).select('albumid'); + const albumsCount = {}; + + for (let id of ids) albumsCount[id] = 0; + for (let file of files) albumsCount[file.albumid] += 1; + for (let album of albums) album.files = albumsCount[album.id]; + + return res.json({ success: true, albums }); +}; + +albumsController.create = async (req, res, next) => { + const user = await utils.authorize(req, res); + + const name = req.body.name; + if (name === undefined || name === '') { + return res.json({ success: false, description: 'No album name specified' }); + } + + const album = await db.table('albums').where({ + name: name, + enabled: 1, + userid: user.id + }).first(); + + if (album) { + return res.json({ success: false, description: 'There\'s already an album with that name' }) + } + + await db.table('albums').insert({ + name: name, + enabled: 1, + userid: user.id, + identifier: randomstring.generate(8), + timestamp: Math.floor(Date.now() / 1000) + }); + + return res.json({ success: true }); +}; + +albumsController.delete = async (req, res, next) => { + const user = await utils.authorize(req, res); + + const id = req.body.id; + if (id === undefined || id === '') { + return res.json({ success: false, description: 'No album specified' }); + } + + await db.table('albums').where({ id: id, userid: user.id }).update({ enabled: 0 }); + return res.json({ success: true }); +}; + +albumsController.rename = async (req, res, next) => { + const user = await utils.authorize(req, res); + + const id = req.body.id; + if (id === undefined || id === '') { + return res.json({ success: false, description: 'No album specified' }); + } + + const name = req.body.name; + if (name === undefined || name === '') { + return res.json({ success: false, description: 'No name specified' }); + } + + const album = await db.table('albums').where({ name: name, userid: user.id }).first(); + if (album) { + return res.json({ success: false, description: 'Name already in use' }) + } + + await db.table('albums').where({ id: id, userid: user.id }).update({ name: name }) + return res.json({ success: true }); +}; + +albumsController.get = async (req, res, next) => { + const identifier = req.params.identifier; + if (identifier === undefined) return res.status(401).json({ success: false, description: 'No identifier provided' }); + + const album = await db.table('albums').where('identifier', identifier).first(); + if (!album) return res.json({ success: false, description: 'Album not found' }); + + const title = album.name; + const files = await db.table('files').select('name').where('albumid', album.id).orderBy('id', 'DESC'); + + for (let file of files) { + file.file = `${config.domain}/${file.name}`; + + const ext = path.extname(file.name).toLowerCase(); + if (utils.imageExtensions.includes(ext) || utils.videoExtensions.includes(ext)) { + file.thumb = `${config.domain}/thumbs/${file.name.slice(0, -ext.length)}.png`; } + } - db.table('albums').select(fields).where({ enabled: 1, userid: user[0].id }).then((albums) => { + return res.json({ + success: true, + title: title, + count: files.length, + files + }); +}; - if (req.params.sidebar !== undefined) - return res.json({ success: true, albums }) - - let ids = [] - for (let album of albums) { - album.date = new Date(album.timestamp * 1000) - album.date = utils.getPrettyDate(album.date) // album.date.getFullYear() + '-' + (album.date.getMonth() + 1) + '-' + album.date.getDate() + ' ' + (album.date.getHours() < 10 ? '0' : '') + album.date.getHours() + ':' + (album.date.getMinutes() < 10 ? '0' : '') + album.date.getMinutes() + ':' + (album.date.getSeconds() < 10 ? '0' : '') + album.date.getSeconds() - - let basedomain = req.get('host') - for (let domain of config.domains) - if (domain.host === req.get('host')) - if (domain.hasOwnProperty('resolve')) - basedomain = domain.resolve - - album.identifier = basedomain + '/a/' + album.identifier - - ids.push(album.id) - } - - db.table('files').whereIn('albumid', ids).select('albumid').then((files) => { - - let albumsCount = {} - - for (let id of ids) albumsCount[id] = 0 - for (let file of files) albumsCount[file.albumid] += 1 - for (let album of albums) album.files = albumsCount[album.id] - - return res.json({ success: true, albums }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - -} - -albumsController.create = function(req, res, next) { - let token = req.headers.token - if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' }) - - db.table('users').where('token', token).then((user) => { - if (user.length === 0) return res.status(401).json({ success: false, description: 'Invalid token' }) - - let name = req.body.name - if (name === undefined || name === '') - return res.json({ success: false, description: 'No album name specified' }) - - db.table('albums').where({ - name: name, - enabled: 1, - userid: user[0].id - }).then((album) => { - if (album.length !== 0) return res.json({ success: false, description: 'There\'s already an album with that name' }) - - db.table('albums').insert({ - name: name, - enabled: 1, - userid: user[0].id, - identifier: randomstring.generate(8), - timestamp: Math.floor(Date.now() / 1000) - }).then(() => { - return res.json({ success: true }) - }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - -} - -albumsController.delete = function(req, res, next) { - let token = req.headers.token - if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' }) - - db.table('users').where('token', token).then((user) => { - if (user.length === 0) return res.status(401).json({ success: false, description: 'Invalid token'}) - - let id = req.body.id - if (id === undefined || id === ''){ - return res.json({ success: false, description: 'No album specified' }) - } - - db.table('albums').where({ id: id, userid: user[0].id }).update({ enabled: 0 }).then(() => { - return res.json({ success: true }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) -} - -albumsController.rename = function(req, res, next) { - let token = req.headers.token - if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' }) - - db.table('users').where('token', token).then((user) => { - if (user.length === 0) return res.status(401).json({ success: false, description: 'Invalid token'}) - - let id = req.body.id - if (id === undefined || id === '') - return res.json({ success: false, description: 'No album specified' }) - - let name = req.body.name - if (name === undefined || name === '') - return res.json({ success: false, description: 'No name specified' }) - - db.table('albums').where({ name: name, userid: user[0].id }).then((results) => { - if (results.length !== 0) return res.json({ success: false, description: 'Name already in use' }) - - db.table('albums').where({ id: id, userid: user[0].id }).update({ name: name }).then(() => { - return res.json({ success: true }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - -} - -albumsController.get = function(req, res, next) { - let identifier = req.params.identifier - if (identifier === undefined) return res.status(401).json({ success: false, description: 'No identifier provided' }) - - db.table('albums') - .where('identifier', identifier) - .then((albums) => { - if (albums.length === 0) return res.json({ success: false, description: 'Album not found' }) - - let title = albums[0].name - db.table('files').select('name').where('albumid', albums[0].id).orderBy('id', 'DESC').then((files) => { - - let basedomain = req.get('host') - for (let domain of config.domains) - if (domain.host === req.get('host')) - if (domain.hasOwnProperty('resolve')) - basedomain = domain.resolve - - for (let file of files) { - file.file = basedomain + '/' + file.name - - let ext = path.extname(file.name).toLowerCase() - if (utils.imageExtensions.includes(ext) || utils.videoExtensions.includes(ext)) { - file.thumb = basedomain + '/thumbs/' + file.name.slice(0, -ext.length) + '.png' - utils.generateThumbs(file) - } - } - - return res.json({ - success: true, - title: title, - count: files.length, - files - }) - - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) -} - -module.exports = albumsController +module.exports = albumsController; diff --git a/controllers/authController.js b/controllers/authController.js index 4b872e8..95a151e 100644 --- a/controllers/authController.js +++ b/controllers/authController.js @@ -1,88 +1,86 @@ -const config = require('../config.js') -const db = require('knex')(config.database) -const bcrypt = require('bcrypt') -const saltRounds = 10 -const randomstring = require('randomstring') +const config = require('../config.js'); +const db = require('knex')(config.database); +const bcrypt = require('bcrypt'); +const randomstring = require('randomstring'); +const utils = require('./utilsController.js'); -let authController = {} +let authController = {}; -authController.verify = function(req, res, next) { +authController.verify = async (req, res, next) => { + const username = req.body.username; + const password = req.body.password; - let username = req.body.username - let password = req.body.password + if (username === undefined) return res.json({ success: false, description: 'No username provided' }); + if (password === undefined) return res.json({ success: false, description: 'No password provided' }); - if (username === undefined) return res.json({ success: false, description: 'No username provided' }) - if (password === undefined) return res.json({ success: false, description: 'No password provided' }) + const user = await db.table('users').where('username', username).first(); + if (!user) return res.json({ success: false, description: 'Username doesn\'t exist' }); - db.table('users').where('username', username).then((user) => { - if (user.length === 0) return res.json({ success: false, description: 'Username doesn\'t exist' }) + bcrypt.compare(password, user.password, (err, result) => { + if (err) { + console.log(err); + return res.json({ success: false, description: 'There was an error' }); + } + if (result === false) return res.json({ success: false, description: 'Wrong password' }); + return res.json({ success: true, token: user.token }); + }); +}; - bcrypt.compare(password, user[0].password, function(err, result) { - if (result === false) return res.json({ success: false, description: 'Wrong password' }) - return res.json({ success: true, token: user[0].token }) - }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) +authController.register = async (req, res, next) => { + if (config.enableUserAccounts === false) { + return res.json({ success: false, description: 'Register is disabled at the moment' }); + } -} + const username = req.body.username; + const password = req.body.password; -authController.register = function(req, res, next) { + if (username === undefined) return res.json({ success: false, description: 'No username provided' }); + if (password === undefined) return res.json({ success: false, description: 'No password provided' }); - if (config.enableUserAccounts === false) - return res.json({ success: false, description: 'Register is disabled at the moment' }) - - let username = req.body.username - let password = req.body.password - - if (username === undefined) return res.json({ success: false, description: 'No username provided' }) - if (password === undefined) return res.json({ success: false, description: 'No password provided' }) - - if (username.length < 4 || username.length > 32) + if (username.length < 4 || username.length > 32) { return res.json({ success: false, description: 'Username must have 4-32 characters' }) - if (password.length < 6 || password.length > 64) + } + if (password.length < 6 || password.length > 64) { return res.json({ success: false, description: 'Password must have 6-64 characters' }) + } - db.table('users').where('username', username).then((user) => { - if (user.length !== 0) return res.json({ success: false, description: 'Username already exists' }) + const user = await db.table('users').where('username', username).first(); + if (user) return res.json({ success: false, description: 'Username already exists' }); - bcrypt.hash(password, saltRounds, function(err, hash) { - if (err) return res.json({ success: false, description: 'Error generating password hash (╯°□°)╯︵ ┻━┻' }) + bcrypt.hash(password, 10, async (err, hash) => { + if (err) { + console.log(err); + return res.json({ success: false, description: 'Error generating password hash (╯°□°)╯︵ ┻━┻' }); + } + const token = randomstring.generate(64); + await db.table('users').insert({ + username: username, + password: hash, + token: token + }); + return res.json({ success: true, token: token }) + }); +}; - let token = randomstring.generate(64) +authController.changePassword = async (req, res, next) => { + const user = await utils.authorize(req, res); - db.table('users').insert({ - username: username, - password: hash, - token: token - }).then(() => { - return res.json({ success: true, token: token }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - }) + let password = req.body.password; + if (password === undefined) return res.json({ success: false, description: 'No password provided' }); - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) + if (password.length < 6 || password.length > 64) { + return res.json({ success: false, description: 'Password must have 6-64 characters' }); + } -} + bcrypt.hash(password, 10, async (err, hash) => { + if (err) { + console.log(err); + return res.json({ success: false, description: 'Error generating password hash (╯°□°)╯︵ ┻━┻' }); + } -authController.changePassword = function(req, res, next) { + await db.table('users').where('id', user.id).update({ password: hash }); + return res.json({ success: true }); + }); +}; - let token = req.headers.token - if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' }) - - db.table('users').where('token', token).then((user) => { - if (user.length === 0) return res.status(401).json({ success: false, description: 'Invalid token'}) - - let password = req.body.password - if (password === undefined) return res.json({ success: false, description: 'No password provided' }) - if (password.length < 6 || password.length > 64) - return res.json({ success: false, description: 'Password must have 6-64 characters' }) - - bcrypt.hash(password, saltRounds, function(err, hash) { - if (err) return res.json({ success: false, description: 'Error generating password hash (╯°□°)╯︵ ┻━┻' }) - - db.table('users').where('id', user[0].id).update({ password: hash }).then(() => { - return res.json({ success: true }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) -} - -module.exports = authController +module.exports = authController; diff --git a/controllers/tokenController.js b/controllers/tokenController.js index c539df4..cbcc550 100644 --- a/controllers/tokenController.js +++ b/controllers/tokenController.js @@ -1,46 +1,34 @@ -const config = require('../config.js') -const db = require('knex')(config.database) -const randomstring = require('randomstring') +const config = require('../config.js'); +const db = require('knex')(config.database); +const randomstring = require('randomstring'); +const utils = require('./utilsController.js'); -let tokenController = {} +const tokenController = {}; -tokenController.verify = function(req, res, next) { +tokenController.verify = async (req, res, next) => { + const token = req.body.token; + if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' }); - if (req.body.token === undefined) return res.json({ success: false, description: 'No token provided' }) - let token = req.body.token + const user = await db.table('users').where('token', token).first(); + if (!user) return res.status(401).json({ success: false, description: 'Invalid token' }); + return res.json({ success: true, username: user.username }); +}; - db.table('users').where('token', token).then((user) => { - if (user.length === 0) return res.json({ success: false, description: 'Token mismatch' }) - return res.json({ success: true, username: user[0].username }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - -} +tokenController.list = async (req, res, next) => { + const user = await utils.authorize(req, res); + return res.json({ success: true, token: user.token }); +}; -tokenController.list = function(req, res, next) { +tokenController.change = async (req, res, next) => { + const user = await utils.authorize(req, res); + const newtoken = randomstring.generate(64); - let token = req.headers.token - if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' }) - - db.table('users').where('token', token).then((user) => { - if (user.length === 0) return res.json({ success: false, description: 'Token mismatch' }) - return res.json({ success: true, token: token }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - -} - -tokenController.change = function(req, res, next) { - - let token = req.headers.token - if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' }) - - let newtoken = randomstring.generate(64) - - db.table('users').where('token', token).update({ + await db.table('users').where('token', user.token).update({ token: newtoken, - timestamp: Math.floor(Date.now() / 1000) - }).then(() => { - res.json({ success: true, token: newtoken }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) -} + timestamp: Math.floor(Date.now() / 1000) + }); -module.exports = tokenController + res.json({ success: true, token: newtoken }); +}; + +module.exports = tokenController; diff --git a/controllers/uploadController.js b/controllers/uploadController.js index 850ab17..f0f75f6 100644 --- a/controllers/uploadController.js +++ b/controllers/uploadController.js @@ -1,22 +1,22 @@ -const config = require('../config.js') -const path = require('path') -const multer = require('multer') -const randomstring = require('randomstring') -const db = require('knex')(config.database) -const crypto = require('crypto') -const fs = require('fs') -const utils = require('./utilsController.js') +const config = require('../config.js'); +const path = require('path'); +const multer = require('multer'); +const randomstring = require('randomstring'); +const db = require('knex')(config.database); +const crypto = require('crypto'); +const fs = require('fs'); +const utils = require('./utilsController.js'); -let uploadsController = {} +const uploadsController = {}; const storage = multer.diskStorage({ destination: function(req, file, cb) { - cb(null, path.join(__dirname, '..', config.uploads.folder)) + cb(null, path.join(__dirname, '..', config.uploads.folder)); }, filename: function(req, file, cb) { - cb(null, randomstring.generate(config.uploads.fileLength) + path.extname(file.originalname)) + cb(null, randomstring.generate(config.uploads.fileLength) + path.extname(file.originalname)); } -}) +}); const upload = multer({ storage: storage, @@ -30,133 +30,93 @@ const upload = multer({ } return cb(null, true); } -}).array('files[]') +}).array('files[]'); -uploadsController.upload = function(req, res, next) { +uploadsController.upload = async (req, res, next) => { + if (config.private === true) { + await utils.authorize(req, res); + } - // Get the token - let token = req.headers.token + const token = req.headers.token || ''; + const user = await db.table('users').where('token', token).first(); + const albumid = req.headers.albumid || req.params.albumid; - // If we're running in private and there's no token, error - if (config.private === true) - if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' }) - - // If there is no token then just leave it blank so the query fails - if (token === undefined) token = '' - - db.table('users').where('token', token).then((user) => { - - if(user.length === 0) - if(config.private === true) - return res.status(401).json({ success: false, description: 'Invalid token provided' }) - - let userid - if(user.length > 0) - userid = user[0].id - - // Check if user is trying to upload to an album - let album - if (userid !== undefined) { - album = req.headers.albumid - if (album === undefined) - album = req.params.albumid - } - - /* - A rewrite is due so might as well do awful things here and fix them later :bloblul: - */ - - if (album !== undefined && userid !== undefined) { - // If both values are present, check if the album owner is the user uploading - db.table('albums').where({ id: album, userid: userid }).then((albums) => { - if (albums.length === 0) { - return res.json({ - success: false, - description: 'Album doesn\'t exist or it doesn\'t belong to the user' - }) - } - uploadsController.actuallyUpload(req, res, userid, album); - }) - } else { - uploadsController.actuallyUpload(req, res, userid, album); - } - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) -} - -uploadsController.actuallyUpload = function(req, res, userid, album) { - upload(req, res, function (err) { - if (err) { - console.error(err) + if (albumid && user) { + const album = await db.table('albums').where({ id: album, userid: user.id }).first(); + if (!album) { return res.json({ success: false, - description: err - }) + description: 'Album doesn\'t exist or it doesn\'t belong to the user' + }); + } + return uploadsController.actuallyUpload(req, res, user.id, albumid); + } + return uploadsController.actuallyUpload(req, res, user.id, albumid); +}; + +uploadsController.actuallyUpload = async (req, res, userid, album) => { + upload(req, res, async err => { + if (err) { + console.error(err); + return res.json({ success: false, description: err }); } - if (req.files.length === 0) return res.json({ success: false, description: 'no-files' }) + if (req.files.length === 0) return res.json({ success: false, description: 'no-files' }); - let files = [] - let existingFiles = [] - let iteration = 1 - - req.files.forEach(function(file) { + const files = []; + const existingFiles = []; + let iteration = 1; + req.files.forEach(async file => { // Check if the file exists by checking hash and size - let hash = crypto.createHash('md5') - let stream = fs.createReadStream(path.join(__dirname, '..', config.uploads.folder, file.filename)) + let hash = crypto.createHash('md5'); + let stream = fs.createReadStream(path.join(__dirname, '..', config.uploads.folder, file.filename)); - stream.on('data', function (data) { - hash.update(data, 'utf8') - }) + stream.on('data', data => { + hash.update(data, 'utf8'); + }); - stream.on('end', function () { - let fileHash = hash.digest('hex') + stream.on('end', async () => { + const fileHash = hash.digest('hex'); + const dbFile = await db.table('files') + .where(function() { + if (userid === undefined) this.whereNull('userid'); + else this.where('userid', userid); + }) + .where({ + hash: fileHash, + size: file.size + }) + .first(); - db.table('files') - .where(function() { - if (userid === undefined) - this.whereNull('userid') - else - this.where('userid', userid) - }) - .where({ - hash: fileHash, - size: file.size - }).then((dbfile) => { + if (!dbFile) { + files.push({ + name: file.filename, + original: file.originalname, + type: file.mimetype, + size: file.size, + hash: fileHash, + ip: req.ip, + albumid: album, + userid: userid, + timestamp: Math.floor(Date.now() / 1000) + }); + } else { + uploadsController.deleteFile(file.filename).then(() => {}).catch(err => console.error(err)); + existingFiles.push(dbFile); + } - if (dbfile.length !== 0) { - uploadsController.deleteFile(file.filename).then(() => {}).catch((e) => console.error(e)) - existingFiles.push(dbfile[0]) - } else { - files.push({ - name: file.filename, - original: file.originalname, - type: file.mimetype, - size: file.size, - hash: fileHash, - ip: req.ip, - albumid: album, - userid: userid, - timestamp: Math.floor(Date.now() / 1000) - }) - } - - if (iteration === req.files.length) - return uploadsController.processFilesForDisplay(req, res, files, existingFiles) - iteration++ - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - }) - }) - }) -} -uploadsController.processFilesForDisplay = function(req, res, files, existingFiles) { - - let basedomain = req.get('host') - for (let domain of config.domains) - if (domain.host === req.get('host')) - if (domain.hasOwnProperty('resolve')) - basedomain = domain.resolve + if (iteration === req.files.length) { + return uploadsController.processFilesForDisplay(req, res, files, existingFiles); + } + iteration++; + }); + }); + }); +}; +uploadsController.processFilesForDisplay = async (req, res, files, existingFiles) => { + let basedomain = config.domain; if (files.length === 0) { return res.json({ success: true, @@ -164,174 +124,154 @@ uploadsController.processFilesForDisplay = function(req, res, files, existingFil return { name: file.name, size: file.size, - url: basedomain + '/' + file.name - } + url: `${basedomain}/${file.name}` + }; }) - }) + }); } - db.table('files').insert(files).then(() => { + await db.table('files').insert(files); + for (let efile of existingFiles) files.push(efile); - for (let efile of existingFiles) files.push(efile) - - res.json({ - success: true, - files: files.map(file => { - return { - name: file.name, - size: file.size, - url: basedomain + '/' + file.name - } - }) + res.json({ + success: true, + files: files.map(file => { + return { + name: file.name, + size: file.size, + url: `${basedomain}/${file.name}` + }; }) + }); - for (let file of files) { - let ext = path.extname(file.name).toLowerCase() - if (utils.imageExtensions.includes(ext) || utils.videoExtensions.includes(ext)) { - file.thumb = basedomain + '/thumbs/' + file.name.slice(0, -ext.length) + '.png' - utils.generateThumbs(file) - } + for (let file of files) { + let ext = path.extname(file.name).toLowerCase(); + if (utils.imageExtensions.includes(ext) || utils.videoExtensions.includes(ext)) { + file.thumb = `${basedomain}/thumbs/${file.name.slice(0, -ext.length)}.png`; + utils.generateThumbs(file); } + } +}; - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) -} +uploadsController.delete = async (req, res) => { + const user = await utils.authorize(req, res); + const id = req.body.id; + if (id === undefined || id === '') { + return res.json({ success: false, description: 'No file specified' }); + } -uploadsController.delete = function(req, res) { - - let token = req.headers.token - if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' }) - - let id = req.body.id - if (id === undefined || id === '') - return res.json({ success: false, description: 'No file specified' }) - - db.table('users').where('token', token).then((user) => { - if (user.length === 0) return res.status(401).json({ success: false, description: 'Invalid token' }) - - db.table('files') + const file = await db.table('files') .where('id', id) .where(function() { - if (user[0].username !== 'root') - this.where('userid', user[0].id) + if (user.username !== 'root') { + this.where('userid', user.id); + } }) - .then((file) => { + .first(); - uploadsController.deleteFile(file[0].name).then(() => { - db.table('files').where('id', id).del().then(() => { - return res.json({ success: true }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - }).catch((e) => { - console.log(e.toString()) - db.table('files').where('id', id).del().then(() => { - return res.json({ success: true }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - }) + try { + await uploadsController.deleteFile(file.name); + await db.table('files').where('id', id).del(); + } catch (err) { + console.log(err); + } - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) -} + return res.json({ success: true }); +}; uploadsController.deleteFile = function(file) { - const ext = path.extname(file).toLowerCase() - return new Promise(function(resolve, reject) { - fs.stat(path.join(__dirname, '..', config.uploads.folder, file), function(err, stats) { - if (err) { return reject(err) } - fs.unlink(path.join(__dirname, '..', config.uploads.folder, file), function(err) { - if (err) { return reject(err) } - if(!utils.imageExtensions.includes(ext) && !utils.videoExtensions.includes(ext)) { - return resolve() + const ext = path.extname(file).toLowerCase(); + return new Promise((resolve, reject) => { + fs.stat(path.join(__dirname, '..', config.uploads.folder, file), (err, stats) => { + if (err) { return reject(err); } + fs.unlink(path.join(__dirname, '..', config.uploads.folder, file), err => { + if (err) { return reject(err); } + if (!utils.imageExtensions.includes(ext) && !utils.videoExtensions.includes(ext)) { + return resolve(); } - file = file.substr(0, file.lastIndexOf(".")) + ".png" - fs.stat(path.join(__dirname, '..', config.uploads.folder, "thumbs/", file), function(err, stats) { - if (err) { return reject(err) } - fs.unlink(path.join(__dirname, '..', config.uploads.folder, "thumbs/", file), function(err) { - if (err) { return reject(err) } - return resolve() - }) - }) - }) - }) - }) -} + file = file.substr(0, file.lastIndexOf('.')) + '.png'; + fs.stat(path.join(__dirname, '..', config.uploads.folder, 'thumbs/', file), (err, stats) => { + if (err) { + console.log(err); + return resolve(); + } + fs.unlink(path.join(__dirname, '..', config.uploads.folder, 'thumbs/', file), err => { + if (err) { return reject(err); } + return resolve(); + }); + }); + }); + }); + }); +}; -uploadsController.list = function(req, res) { +uploadsController.list = async (req, res) => { + const user = await utils.authorize(req, res); - let token = req.headers.token - if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' }) + let offset = req.params.page; + if (offset === undefined) offset = 0; - db.table('users').where('token', token).then((user) => { - if (user.length === 0) return res.status(401).json({ success: false, description: 'Invalid token'}) - - let offset = req.params.page - if (offset === undefined) offset = 0 - - db.table('files') + const files = await db.table('files') .where(function() { - if (req.params.id === undefined) - this.where('id', '<>', '') - else - this.where('albumid', req.params.id) + if (req.params.id === undefined) this.where('id', '<>', ''); + else this.where('albumid', req.params.id); }) .where(function() { - if (user[0].username !== 'root') - this.where('userid', user[0].id) + if (user.username !== 'root') this.where('userid', user.id); }) .orderBy('id', 'DESC') .limit(25) .offset(25 * offset) - .select('id', 'albumid', 'timestamp', 'name', 'userid') - .then((files) => { - db.table('albums').then((albums) => { + .select('id', 'albumid', 'timestamp', 'name', 'userid'); - let basedomain = req.get('host') - for (let domain of config.domains) - if (domain.host === req.get('host')) - if (domain.hasOwnProperty('resolve')) - basedomain = domain.resolve + const albums = await db.table('albums'); + let basedomain = config.domain; + let userids = []; - let userids = [] + for (let file of files) { + file.file = `${basedomain}/${file.name}`; + file.date = new Date(file.timestamp * 1000); + file.date = utils.getPrettyDate(file.date); - for (let file of files) { - file.file = basedomain + '/' + file.name - file.date = new Date(file.timestamp * 1000) - file.date = utils.getPrettyDate(file.date) // file.date.getFullYear() + '-' + (file.date.getMonth() + 1) + '-' + file.date.getDate() + ' ' + (file.date.getHours() < 10 ? '0' : '') + file.date.getHours() + ':' + (file.date.getMinutes() < 10 ? '0' : '') + file.date.getMinutes() + ':' + (file.date.getSeconds() < 10 ? '0' : '') + file.date.getSeconds() + file.album = ''; - file.album = '' - - if (file.albumid !== undefined) - for (let album of albums) - if (file.albumid === album.id) - file.album = album.name - - // Only push usernames if we are root - if (user[0].username === 'root') - if (file.userid !== undefined && file.userid !== null && file.userid !== '') - userids.push(file.userid) - - let ext = path.extname(file.name).toLowerCase() - if (utils.imageExtensions.includes(ext) || utils.videoExtensions.includes(ext)) { - file.thumb = basedomain + '/thumbs/' + file.name.slice(0, -ext.length) + '.png' - utils.generateThumbs(file) - } + if (file.albumid !== undefined) { + for (let album of albums) { + if (file.albumid === album.id) { + file.album = album.name; } + } + } - // If we are a normal user, send response - if (user[0].username !== 'root') return res.json({ success: true, files }) + // Only push usernames if we are root + if (user.username === 'root') { + if (file.userid !== undefined && file.userid !== null && file.userid !== '') { + userids.push(file.userid); + } + } - // If we are root but there are no uploads attached to a user, send response - if (userids.length === 0) return res.json({ success: true, files }) + let ext = path.extname(file.name).toLowerCase(); + if (utils.imageExtensions.includes(ext) || utils.videoExtensions.includes(ext)) { + file.thumb = `${basedomain}/thumbs/${file.name.slice(0, -ext.length)}.png`; + } + } - db.table('users').whereIn('id', userids).then((users) => { - for (let user of users) - for (let file of files) - if (file.userid === user.id) - file.username = user.username + // If we are a normal user, send response + if (user.username !== 'root') return res.json({ success: true, files }); - return res.json({ success: true, files }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - }) -} + // If we are root but there are no uploads attached to a user, send response + if (userids.length === 0) return res.json({ success: true, files }); -module.exports = uploadsController + const users = await db.table('users').whereIn('id', userids); + for (let dbUser of users) { + for (let file of files) { + if (file.userid === dbUser.id) { + file.username = dbUser.username; + } + } + } + + return res.json({ success: true, files }); +}; + +module.exports = uploadsController; diff --git a/controllers/utilsController.js b/controllers/utilsController.js index ec056ab..ebfb36d 100644 --- a/controllers/utilsController.js +++ b/controllers/utilsController.js @@ -1,12 +1,13 @@ -const path = require('path') -const config = require('../config.js') -const fs = require('fs') -const gm = require('gm') -const ffmpeg = require('fluent-ffmpeg') +const path = require('path'); +const config = require('../config.js'); +const fs = require('fs'); +const gm = require('gm'); +const ffmpeg = require('fluent-ffmpeg'); +const db = require('knex')(config.database); -const utilsController = {} -utilsController.imageExtensions = ['.jpg', '.jpeg', '.bmp', '.gif', '.png'] -utilsController.videoExtensions = ['.webm', '.mp4', '.wmv', '.avi', '.mov'] +const utilsController = {}; +utilsController.imageExtensions = ['.jpg', '.jpeg', '.bmp', '.gif', '.png']; +utilsController.videoExtensions = ['.webm', '.mp4', '.wmv', '.avi', '.mov']; utilsController.getPrettyDate = function(date) { return date.getFullYear() + '-' @@ -17,15 +18,24 @@ utilsController.getPrettyDate = function(date) { + (date.getMinutes() < 10 ? '0' : '') + date.getMinutes() + ':' + (date.getSeconds() < 10 ? '0' : '') - + date.getSeconds() + + date.getSeconds(); } -utilsController.generateThumbs = function(file, basedomain) { - if (config.uploads.generateThumbnails !== true) return - const ext = path.extname(file.name).toLowerCase() +utilsController.authorize = async (req, res) => { + const token = req.headers.token; + if (token === undefined) return res.status(401).json({ success: false, description: 'No token provided' }); - let thumbname = path.join(__dirname, '..', config.uploads.folder, 'thumbs', file.name.slice(0, -ext.length) + '.png') - fs.access(thumbname, (err) => { + const user = await db.table('users').where('token', token).first(); + if (!user) return res.status(401).json({ success: false, description: 'Invalid token' }); + return user; +}; + +utilsController.generateThumbs = function(file, basedomain) { + if (config.uploads.generateThumbnails !== true) return; + const ext = path.extname(file.name).toLowerCase(); + + let thumbname = path.join(__dirname, '..', config.uploads.folder, 'thumbs', file.name.slice(0, -ext.length) + '.png'); + fs.access(thumbname, err => { if (err && err.code === 'ENOENT') { if (utilsController.videoExtensions.includes(ext)) { ffmpeg(path.join(__dirname, '..', config.uploads.folder, file.name)) @@ -35,25 +45,23 @@ utilsController.generateThumbs = function(file, basedomain) { folder: path.join(__dirname, '..', config.uploads.folder, 'thumbs'), size: '200x?' }) - .on('error', (error) => { - console.log('Error - ', error.message) - }) + .on('error', error => console.log('Error - ', error.message)); } else { let size = { width: 200, height: 200 - } + }; gm(path.join(__dirname, '..', config.uploads.folder, file.name)) .resize(size.width, size.height + '>') .gravity('Center') .extent(size.width, size.height) .background('transparent') - .write(thumbname, (error) => { - if (error) console.log('Error - ', error) - }) + .write(thumbname, error => { + if (error) console.log('Error - ', error); + }); } } - }) -} + }); +}; -module.exports = utilsController +module.exports = utilsController; diff --git a/routes/album.js b/routes/album.js index 20ccc26..ab1ddfa 100644 --- a/routes/album.js +++ b/routes/album.js @@ -1,61 +1,50 @@ -const config = require('../config.js') -const routes = require('express').Router() -const db = require('knex')(config.database) -const path = require('path') -const utils = require('../controllers/utilsController.js') +const config = require('../config.js'); +const routes = require('express').Router(); +const db = require('knex')(config.database); +const path = require('path'); +const utils = require('../controllers/utilsController.js'); -routes.get('/a/:identifier', (req, res, next) => { +routes.get('/a/:identifier', async (req, res, next) => { + let identifier = req.params.identifier; + if (identifier === undefined) return res.status(401).json({ success: false, description: 'No identifier provided' }); - let identifier = req.params.identifier - if (identifier === undefined) return res.status(401).json({ success: false, description: 'No identifier provided' }) + const album = await db.table('albums').where('identifier', identifier).first(); + if (!album) return res.json({ success: false, description: 'Album not found' }); - db.table('albums') - .where('identifier', identifier) - .then((albums) => { - if (albums.length === 0) return res.json({ success: false, description: 'Album not found' }) + const files = await db.table('files').select('name').where('albumid', album.id).orderBy('id', 'DESC'); + let thumb = ''; + const basedomain = config.domain; - let title = albums[0].name - db.table('files').select('name').where('albumid', albums[0].id).orderBy('id', 'DESC').then((files) => { + for (let file of files) { + file.file = `${basedomain}/${file.name}`; - let thumb = '' - let basedomain = req.get('host') - for (let domain of config.domains) - if (domain.host === req.get('host')) - if (domain.hasOwnProperty('resolve')) - basedomain = domain.resolve + let ext = path.extname(file.name).toLowerCase(); + if (utils.imageExtensions.includes(ext) || utils.videoExtensions.includes(ext)) { + file.thumb = `${basedomain}/thumbs/${file.name.slice(0, -ext.length)}.png`; - for (let file of files) { - file.file = basedomain + '/' + file.name + /* + If thumbnail for album is still not set, do it. + A potential improvement would be to let the user upload a specific image as an album cover + since embedding the first image could potentially result in nsfw content when pasting links. + */ - let ext = path.extname(file.name).toLowerCase() - if (utils.imageExtensions.includes(ext) || utils.videoExtensions.includes(ext)) { - file.thumb = basedomain + '/thumbs/' + file.name.slice(0, -ext.length) + '.png' - - /* - If thumbnail for album is still not set, do it. - A potential improvement would be to let the user upload a specific image as an album cover - since embedding the first image could potentially result in nsfw content when pasting links. - */ - - if (thumb === '') { - thumb = file.thumb - } - - file.thumb = `` - } else { - file.thumb = `

.${ext}

` - } + if (thumb === '') { + thumb = file.thumb; } - return res.render('album', { - layout: false, - title: title, - count: files.length, - thumb, - files - }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) - }).catch(function(error) { console.log(error); res.json({ success: false, description: 'error' }) }) -}) + file.thumb = ``; + } else { + file.thumb = `

.${ext}

`; + } + } -module.exports = routes + return res.render('album', { + layout: false, + title: album.name, + count: files.length, + thumb, + files + }); +}); + +module.exports = routes; diff --git a/routes/api.js b/routes/api.js index b3ff798..83d3bc1 100644 --- a/routes/api.js +++ b/routes/api.js @@ -1,40 +1,36 @@ -const config = require('../config.js') -const routes = require('express').Router() -const uploadController = require('../controllers/uploadController') -const albumsController = require('../controllers/albumsController') -const tokenController = require('../controllers/tokenController') -const authController = require('../controllers/authController') +const config = require('../config.js'); +const routes = require('express').Router(); +const uploadController = require('../controllers/uploadController'); +const albumsController = require('../controllers/albumsController'); +const tokenController = require('../controllers/tokenController'); +const authController = require('../controllers/authController'); -routes.get ('/check', (req, res, next) => { - return res.json({ +routes.get('/check', (req, res, next) => { + return res.json({ private: config.private, maxFileSize: config.uploads.maxSize - }) -}) + }); +}); -routes.post ('/login', (req, res, next) => authController.verify(req, res, next)) -routes.post ('/register', (req, res, next) => authController.register(req, res, next)) -routes.post ('/password/change', (req, res, next) => authController.changePassword(req, res, next)) +routes.post('/login', (req, res, next) => authController.verify(req, res, next)); +routes.post('/register', (req, res, next) => authController.register(req, res, next)); +routes.post('/password/change', (req, res, next) => authController.changePassword(req, res, next)); +routes.get('/uploads', (req, res, next) => uploadController.list(req, res, next)); +routes.get('/uploads/:page', (req, res, next) => uploadController.list(req, res, next)); +routes.post('/upload', (req, res, next) => uploadController.upload(req, res, next)); +routes.post('/upload/delete', (req, res, next) => uploadController.delete(req, res, next)); +routes.post('/upload/:albumid', (req, res, next) => uploadController.upload(req, res, next)); +routes.get('/album/get/:identifier', (req, res, next) => albumsController.get(req, res, next)); +routes.get('/album/:id', (req, res, next) => uploadController.list(req, res, next)); +routes.get('/album/:id/:page', (req, res, next) => uploadController.list(req, res, next)); +routes.get('/albums', (req, res, next) => albumsController.list(req, res, next)); +routes.get('/albums/:sidebar', (req, res, next) => albumsController.list(req, res, next)); +routes.post('/albums', (req, res, next) => albumsController.create(req, res, next)); +routes.post('/albums/delete', (req, res, next) => albumsController.delete(req, res, next)); +routes.post('/albums/rename', (req, res, next) => albumsController.rename(req, res, next)); +routes.get('/albums/test', (req, res, next) => albumsController.test(req, res, next)); +routes.get('/tokens', (req, res, next) => tokenController.list(req, res, next)); +routes.post('/tokens/verify', (req, res, next) => tokenController.verify(req, res, next)); +routes.post('/tokens/change', (req, res, next) => tokenController.change(req, res, next)); -routes.get ('/uploads', (req, res, next) => uploadController.list(req, res)) -routes.get ('/uploads/:page', (req, res, next) => uploadController.list(req, res)) -routes.post ('/upload', (req, res, next) => uploadController.upload(req, res, next)) -routes.post ('/upload/delete', (req, res, next) => uploadController.delete(req, res, next)) -routes.post ('/upload/:albumid', (req, res, next) => uploadController.upload(req, res, next)) - -routes.get ('/album/get/:identifier', (req, res, next) => albumsController.get(req, res, next)) -routes.get ('/album/:id', (req, res, next) => uploadController.list(req, res, next)) -routes.get ('/album/:id/:page', (req, res, next) => uploadController.list(req, res, next)) - -routes.get ('/albums', (req, res, next) => albumsController.list(req, res, next)) -routes.get ('/albums/:sidebar', (req, res, next) => albumsController.list(req, res, next)) -routes.post ('/albums', (req, res, next) => albumsController.create(req, res, next)) -routes.post ('/albums/delete', (req, res, next) => albumsController.delete(req, res, next)) -routes.post ('/albums/rename', (req, res, next) => albumsController.rename(req, res, next)) -routes.get ('/albums/test', (req, res, next) => albumsController.test(req, res, next)) - -routes.get ('/tokens', (req, res, next) => tokenController.list(req, res)) -routes.post ('/tokens/verify', (req, res, next) => tokenController.verify(req, res)) -routes.post ('/tokens/change', (req, res, next) => tokenController.change(req, res)) - -module.exports = routes +module.exports = routes;