Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
refactor(accounts): security enhancements
  • Loading branch information
polonel committed May 17, 2022
1 parent 691d12c commit d107f12
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 82 deletions.
9 changes: 7 additions & 2 deletions src/controllers/accounts.js
Expand Up @@ -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 = {}

Expand Down Expand Up @@ -462,6 +463,8 @@ accountsController.uploadImage = function (req, res) {
}
})

const allowedExts = ['.png', '.jpg', '.jpeg', '.gif']

const object = {}
let error

Expand All @@ -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'
Expand All @@ -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 () {
Expand Down
1 change: 0 additions & 1 deletion src/controllers/api/v1/routes.js
Expand Up @@ -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)
Expand Down
79 changes: 0 additions & 79 deletions src/controllers/api/v1/users.js
Expand Up @@ -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
Expand Down

0 comments on commit d107f12

Please sign in to comment.