From 5501c0c759f44fcf0447f66ba1a7d2088ec0f8bb Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 13 Apr 2015 15:01:38 -0400 Subject: [PATCH] closes #3005 --- public/src/client/account/edit.js | 4 +- src/controllers/accounts.js | 74 ++--------------- src/socket.io/user.js | 24 ++++-- src/user.js | 1 + src/user/picture.js | 131 ++++++++++++++++++++++++++++++ 5 files changed, 158 insertions(+), 76 deletions(-) create mode 100644 src/user/picture.js diff --git a/public/src/client/account/edit.js b/public/src/client/account/edit.js index b3c8c0af6a..4b2e0ff93d 100644 --- a/public/src/client/account/edit.js +++ b/public/src/client/account/edit.js @@ -203,7 +203,7 @@ define('forum/account/edit', ['forum/account/header', 'uploader', 'translator'], if (!url) { return; } - socket.emit('user.uploadProfileImageFromUrl', url, function(err, imageUrlOnServer) { + socket.emit('user.uploadProfileImageFromUrl', {url: url, uid: ajaxify.variables.get('theirid')}, function(err, imageUrlOnServer) { if (err) { return app.alertError(err.message); } @@ -300,7 +300,7 @@ define('forum/account/edit', ['forum/account/header', 'uploader', 'translator'], } else { if (!passwordsmatch) { app.alertError('[[user:change_password_error_match]]'); - } + } if (!passwordvalid) { app.alertError('[[user:change_password_error]]'); diff --git a/src/controllers/accounts.js b/src/controllers/accounts.js index 3f5d23653a..78629b50cc 100644 --- a/src/controllers/accounts.js +++ b/src/controllers/accounts.js @@ -3,8 +3,6 @@ var accountsController = {}; var fs = require('fs'), - path = require('path'), - winston = require('winston'), nconf = require('nconf'), async = require('async'), validator = require('validator'), @@ -20,8 +18,7 @@ var fs = require('fs'), meta = require('../meta'), plugins = require('../plugins'), languages = require('../languages'), - image = require('../image'), - file = require('../file'), + helpers = require('./helpers'); function getUserDataByUserSlug(userslug, callerUID, callback) { @@ -369,32 +366,10 @@ accountsController.accountSettings = function(req, res, next) { accountsController.uploadPicture = function (req, res, next) { var userPhoto = req.files.files[0]; - var uploadSize = parseInt(meta.config.maximumProfileImageSize, 10) || 256; - var extension = path.extname(userPhoto.name); + var updateUid = req.uid; - var imageDimension = parseInt(meta.config.profileImageDimension, 10) || 128; - var convertToPNG = parseInt(meta.config['profile:convertProfileImageToPNG'], 10) === 1; async.waterfall([ - function(next) { - next(userPhoto.size > uploadSize * 1024 ? new Error('[[error:file-too-big, ' + uploadSize + ']]') : null); - }, - function(next) { - next(!extension ? new Error('[[error:invalid-image-extension]]') : null); - }, - function(next) { - file.isFileTypeAllowed(userPhoto.path, ['png', 'jpeg', 'jpg', 'gif'], next); - }, - function(next) { - image.resizeImage(userPhoto.path, extension, imageDimension, imageDimension, next); - }, - function(next) { - if (convertToPNG) { - image.convertImageToPng(userPhoto.path, extension, next); - } else { - next(); - } - }, function(next) { user.getUidByUserslug(req.params.userslug, next); }, @@ -414,50 +389,17 @@ accountsController.uploadPicture = function (req, res, next) { updateUid = uid; next(); }); + }, + function(next) { + user.uploadPicture(updateUid, userPhoto, next); } - ], function(err, result) { - - function done(err, image) { - fs.unlink(userPhoto.path); - if (err) { - return res.json({error: err.message}); - } - - user.setUserFields(updateUid, {uploadedpicture: image.url, picture: image.url}); - - res.json([{name: userPhoto.name, url: image.url.startsWith('http') ? image.url : nconf.get('relative_path') + image.url}]); - } - + ], function(err, image) { + fs.unlink(userPhoto.path); if (err) { - fs.unlink(userPhoto.path); return next(err); } - if (plugins.hasListeners('filter:uploadImage')) { - return plugins.fireHook('filter:uploadImage', {image: userPhoto, uid: updateUid}, done); - } - - var filename = updateUid + '-profileimg' + (convertToPNG ? '.png' : extension); - - user.getUserField(updateUid, 'uploadedpicture', function (err, oldpicture) { - if (err) { - return next(err); - } - if (!oldpicture) { - file.saveFileToLocal(filename, 'profile', userPhoto.path, done); - return; - } - - var absolutePath = path.join(nconf.get('base_dir'), nconf.get('upload_path'), 'profile', path.basename(oldpicture)); - - fs.unlink(absolutePath, function (err) { - if (err) { - winston.error(err); - } - - file.saveFileToLocal(filename, 'profile', userPhoto.path, done); - }); - }); + res.json([{name: userPhoto.name, url: image.url.startsWith('http') ? image.url : nconf.get('relative_path') + image.url}]); }); }; diff --git a/src/socket.io/user.js b/src/socket.io/user.js index 3cd15c9b92..e395418142 100644 --- a/src/socket.io/user.js +++ b/src/socket.io/user.js @@ -263,19 +263,27 @@ SocketUser.changePicture = function(socket, data, callback) { }); }; -SocketUser.uploadProfileImageFromUrl = function(socket, url, callback) { - if (!socket.uid || !url) { +SocketUser.uploadProfileImageFromUrl = function(socket, data, callback) { + function upload() { + user.uploadFromUrl(data.uid, data.url, function(err, uploadedImage) { + callback(err, uploadedImage ? uploadedImage.url : null); + }); + } + + if (!socket.uid || !data.url || !data.uid) { return; } - plugins.fireHook('filter:uploadImage', {image: {url: url}, uid: socket.uid}, function(err, data) { - if (err) { - return callback(err); + if (parseInt(socket.uid, 10) === parseInt(data.uid, 10)) { + return upload(); + } + + user.isAdministrator(socket.uid, function(err, isAdmin) { + if (err || !isAdmin) { + return callback(err || new Error('[[error:not-allowed]]')); } - user.setUserFields(socket.uid, {uploadedpicture: data.url, picture: data.url}, function(err) { - callback(err, data.url); - }); + upload(); }); }; diff --git a/src/user.js b/src/user.js index 281000ccc0..7ad9810554 100644 --- a/src/user.js +++ b/src/user.js @@ -29,6 +29,7 @@ var async = require('async'), require('./user/settings')(User); require('./user/search')(User); require('./user/jobs')(User); + require('./user/picture')(User); User.getUserField = function(uid, field, callback) { User.getUserFields(uid, [field], function(err, user) { diff --git a/src/user/picture.js b/src/user/picture.js new file mode 100644 index 0000000000..d726773a55 --- /dev/null +++ b/src/user/picture.js @@ -0,0 +1,131 @@ +'use strict'; + +var async = require('async'), + path = require('path'), + fs = require('fs'), + nconf = require('nconf'), + winston = require('winston'), + request = require('request'), + mime = require('mime'), + + plugins = require('../plugins'), + file = require('../file'), + image = require('../image'), + meta = require('../meta'); + +module.exports = function(User) { + + User.uploadPicture = function (uid, picture, callback) { + + var uploadSize = parseInt(meta.config.maximumProfileImageSize, 10) || 256; + var extension = path.extname(picture.name); + var updateUid = uid; + var imageDimension = parseInt(meta.config.profileImageDimension, 10) || 128; + var convertToPNG = parseInt(meta.config['profile:convertProfileImageToPNG'], 10) === 1; + + async.waterfall([ + function(next) { + next(picture.size > uploadSize * 1024 ? new Error('[[error:file-too-big, ' + uploadSize + ']]') : null); + }, + function(next) { + next(!extension ? new Error('[[error:invalid-image-extension]]') : null); + }, + function(next) { + file.isFileTypeAllowed(picture.path, ['png', 'jpeg', 'jpg', 'gif'], next); + }, + function(next) { + image.resizeImage(picture.path, extension, imageDimension, imageDimension, next); + }, + function(next) { + if (convertToPNG) { + image.convertImageToPng(picture.path, extension, next); + } else { + next(); + } + } + ], function(err, result) { + + function done(err, image) { + if (err) { + return callback(err); + } + + User.setUserFields(updateUid, {uploadedpicture: image.url, picture: image.url}); + + callback(null, image); + } + + if (err) { + return callback(err); + } + + if (plugins.hasListeners('filter:uploadImage')) { + return plugins.fireHook('filter:uploadImage', {image: picture, uid: updateUid}, done); + } + + var filename = updateUid + '-profileimg' + (convertToPNG ? '.png' : extension); + + User.getUserField(updateUid, 'uploadedpicture', function (err, oldpicture) { + if (err) { + return callback(err); + } + + if (!oldpicture) { + return file.saveFileToLocal(filename, 'profile', picture.path, done); + } + + var absolutePath = path.join(nconf.get('base_dir'), nconf.get('upload_path'), 'profile', path.basename(oldpicture)); + + fs.unlink(absolutePath, function (err) { + if (err) { + winston.error(err); + } + + file.saveFileToLocal(filename, 'profile', picture.path, done); + }); + }); + }); + }; + + User.uploadFromUrl = function(uid, url, callback) { + var filename = 'uid:' + uid + ':tmp-image'; + downloadFromUrl(url, filename, function(err, downloadedImage) { + if (err) { + return callback(err); + } + + User.uploadPicture(uid, downloadedImage, function(err, image) { + fs.unlink(filename); + callback(err, image); + }); + }); + }; + + function downloadFromUrl(url, filename, callback) { + request.head(url, function(err, res, body) { + if (err) { + return callback(err); + } + var uploadSize = parseInt(meta.config.maximumProfileImageSize, 10) || 256; + var size = res.headers['content-length']; + var type = res.headers['content-type']; + var extension = mime.extension(type); + + if (size > uploadSize * 1024) { + return callback(new Error('[[error:file-too-big, ' + uploadSize + ']]')); + } + + request.get(url) + .on('error', function(err) { + winston.error(err); + }) + .pipe(fs.createWriteStream(filename)) + .on('close', function(err) { + if (err) { + return callback(err); + } + callback(null, {path: filename, size: size, type: type, name: filename + '.' + extension}); + }); + }); + } +}; \ No newline at end of file