From d107f12e71c0fe1e7ac0fdc7463f59c4965a42cd Mon Sep 17 00:00:00 2001 From: Chris Brame Date: Mon, 16 May 2022 23:54:40 -0400 Subject: [PATCH] refactor(accounts): security enhancements --- src/controllers/accounts.js | 9 +++- src/controllers/api/v1/routes.js | 1 - src/controllers/api/v1/users.js | 79 -------------------------------- 3 files changed, 7 insertions(+), 82 deletions(-) diff --git a/src/controllers/accounts.js b/src/controllers/accounts.js index 7a253a4a4..2353303a7 100644 --- a/src/controllers/accounts.js +++ b/src/controllers/accounts.js @@ -19,6 +19,7 @@ const userSchema = require('../models/user') const permissions = require('../permissions') const emitter = require('../emitter') const xss = require('xss') +const path = require('path') const accountsController = {} @@ -462,6 +463,8 @@ accountsController.uploadImage = function (req, res) { } }) + const allowedExts = ['.png', '.jpg', '.jpeg', '.gif'] + const object = {} let error @@ -474,7 +477,8 @@ accountsController.uploadImage = function (req, res) { const filename = info.filename const mimetype = info.mimeType const ext = path.extname(filename) - if (mimetype.indexOf('image/') === -1 || ext === '.svg') { + + if (!allowedExts.includes(ext)) { error = { status: 400, message: 'Invalid File Type' @@ -486,8 +490,9 @@ accountsController.uploadImage = function (req, res) { const savePath = path.join(__dirname, '../../public/uploads/users') if (!fs.existsSync(savePath)) fs.mkdirSync(savePath) - object.filePath = path.join(savePath, 'aProfile_' + object.username + path.extname(filename)) object.filename = 'aProfile_' + object.username + path.extname(filename) + object.filename = object.filename.replace('/', '').replace('..', '') + object.filePath = path.join(savePath, object.filename) object.mimetype = mimetype file.on('limit', function () { diff --git a/src/controllers/api/v1/routes.js b/src/controllers/api/v1/routes.js index 5499c6360..95f98a369 100644 --- a/src/controllers/api/v1/routes.js +++ b/src/controllers/api/v1/routes.js @@ -130,7 +130,6 @@ module.exports = function (middleware, router, controllers) { router.get('/api/v1/users/:username', apiv1, canUser('accounts:view'), apiCtrl.users.single) router.put('/api/v1/users/:username', apiv1, canUser('accounts:update'), apiCtrl.users.update) router.get('/api/v1/users/:username/groups', apiv1, apiCtrl.users.getGroups) - router.post('/api/v1/users/:username/uploadprofilepic', apiv1, apiCtrl.users.uploadProfilePic) router.put('/api/v1/users/:username/updatepreferences', apiv1, apiCtrl.users.updatePreferences) router.get('/api/v1/users/:username/enable', apiv1, canUser('accounts:update'), apiCtrl.users.enableUser) router.delete('/api/v1/users/:username', apiv1, canUser('accounts:delete'), apiCtrl.users.deleteUser) diff --git a/src/controllers/api/v1/users.js b/src/controllers/api/v1/users.js index 042b2634a..e6c2683ab 100644 --- a/src/controllers/api/v1/users.js +++ b/src/controllers/api/v1/users.js @@ -1080,85 +1080,6 @@ apiUsers.getGroups = function (req, res) { } } -apiUsers.uploadProfilePic = function (req, res) { - const fs = require('fs') - const path = require('path') - const Busboy = require('busboy') - const busboy = Busboy({ - headers: req.headers, - limits: { - files: 1, - fileSize: 1024 * 1024 * 3 - } - }) - - const object = {} - let error - - if (_.isUndefined(req.params.username)) return res.status(400).json({ error: 'Invalid Username' }) - object.username = req.params.username - - busboy.on('file', function (name, file, info) { - const mimetype = info.mimeType - - if (mimetype.indexOf('image/') === -1) { - error = { - status: 400, - message: 'Invalid file type' - } - - return file.resume() - } - - const savePath = path.join(__dirname, '../../../../public/uploads/users') - if (!fs.existsSync(savePath)) fs.mkdirSync(savePath) - - object.filePath = path.join(savePath, 'aProfile_' + object.username + '.jpg') - object.filename = 'aProfile_' + object.username + '.jpg' - object.mimetype = mimetype - - file.on('limit', function () { - error = { - status: 400, - message: 'File too large' - } - - return file.resume() - }) - - file.pipe(fs.createWriteStream(object.filePath)) - }) - - busboy.on('finish', function () { - if (error) return res.status(error.status).send(error.message) - - if (_.isUndefined(object.username) || _.isUndefined(object.filePath) || _.isUndefined(object.filename)) { - return res.status(400).send('Invalid Form Data') - } - - if (!fs.existsSync(object.filePath)) return res.status(400).send('File failed to save to disk') - - UserSchema.getUserByUsername(object.username, function (err, user) { - if (err) return res.status(400).send(err.message) - - user.image = object.filename - - user.save(function (err) { - if (err) return res.status(500).send(err.message) - - emitter.emit('trudesk:profileImageUpdate', { - userid: user._id, - img: user.image - }) - - return res.json({ success: true, user: stripUserFields(user) }) - }) - }) - }) - - req.pipe(busboy) -} - function stripUserFields (user) { user.password = undefined user.accessToken = undefined