From f19043d0469f9494c05a1d04d2cc5a2d0fbcb553 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 28 Oct 2015 17:42:42 -0400 Subject: [PATCH] profile cover photos --- public/src/client/account/profile.js | 30 ++++++++++- src/controllers/accounts/edit.js | 15 ++++++ src/controllers/accounts/profile.js | 3 ++ src/controllers/uploads.js | 6 ++- src/routes/api.js | 3 +- src/socket.io/user/profile.js | 14 +++++ src/user/picture.js | 76 +++++++++++++++++++++++++++- 7 files changed, 142 insertions(+), 5 deletions(-) diff --git a/public/src/client/account/profile.js b/public/src/client/account/profile.js index 5a7756cc93..deffc3ab9a 100644 --- a/public/src/client/account/profile.js +++ b/public/src/client/account/profile.js @@ -2,7 +2,14 @@ /* globals define, ajaxify, app, utils, socket, bootbox */ -define('forum/account/profile', ['forum/account/header', 'forum/infinitescroll', 'translator'], function(header, infinitescroll, translator) { +define('forum/account/profile', [ + 'forum/account/header', + 'forum/infinitescroll', + 'translator', + 'coverPhoto', + 'uploader', + 'components' +], function(header, infinitescroll, translator, coverPhoto, uploader, components) { var Account = {}, yourid, theirid, @@ -41,6 +48,10 @@ define('forum/account/profile', ['forum/account/header', 'forum/infinitescroll', socket.on('event:user_status_change', onUserStatusChange); infinitescroll.init(loadMorePosts); + + if (parseInt(yourid, 10) === parseInt(theirid, 10)) { + setupCoverPhoto(); + } }; function processPage() { @@ -161,5 +172,22 @@ define('forum/account/profile', ['forum/account/header', 'forum/infinitescroll', }); } + function setupCoverPhoto() { + coverPhoto.init(components.get('account/cover'), + function(imageData, position, callback) { + socket.emit('user.updateCover', { + uid: yourid, + imageData: imageData, + position: position + }, callback); + }, + function() { + uploader.open(RELATIVE_PATH + '/api/user/uploadcover', { uid: yourid }, 0, function(imageUrlOnServer) { + components.get('account/cover').css('background-image', 'url(' + imageUrlOnServer + ')'); + }); + } + ); + } + return Account; }); diff --git a/src/controllers/accounts/edit.js b/src/controllers/accounts/edit.js index a84dc7c991..0205b60356 100644 --- a/src/controllers/accounts/edit.js +++ b/src/controllers/accounts/edit.js @@ -120,4 +120,19 @@ editController.uploadPicture = function (req, res, next) { }); }; +editController.uploadCoverPicture = function(req, res, next) { + var params = JSON.parse(req.body.params); + + user.updateCoverPicture({ + file: req.files.files[0].path, + uid: params.uid + }, function(err, image) { + if (err) { + return next(err); + } + + res.json([{url: image.url.startsWith('http') ? image.url : nconf.get('relative_path') + image.url}]); + }); +}; + module.exports = editController; \ No newline at end of file diff --git a/src/controllers/accounts/profile.js b/src/controllers/accounts/profile.js index e55ee0d157..5d06a62b3e 100644 --- a/src/controllers/accounts/profile.js +++ b/src/controllers/accounts/profile.js @@ -76,6 +76,9 @@ profileController.get = function(req, res, callback) { userData.profileviews = 1; } + userData['cover:url'] = userData['cover:url'] || nconf.get('relative_path') + '/images/cover-default.png'; + userData['cover:position'] = userData['cover:position'] || '50% 50%'; + plugins.fireHook('filter:user.account', {userData: userData, uid: req.uid}, next); } ], function(err, results) { diff --git a/src/controllers/uploads.js b/src/controllers/uploads.js index 491553fb24..d798524f3e 100644 --- a/src/controllers/uploads.js +++ b/src/controllers/uploads.js @@ -93,7 +93,11 @@ uploadsController.uploadThumb = function(req, res, next) { }; uploadsController.uploadGroupCover = function(data, next) { - uploadImage(0/*req.user.uid*/, data, next); + uploadImage(0, data, next); +}; + +uploadsController.uploadUserCover = function(data, next) { + uploadImage(data.uid, data, next); }; function uploadImage(uid, image, callback) { diff --git a/src/routes/api.js b/src/routes/api.js index 402bf85341..32d764f5de 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -28,7 +28,8 @@ module.exports = function(app, middleware, controllers) { router.post('/post/upload', middlewares, uploadsController.uploadPost); router.post('/topic/thumb/upload', middlewares, uploadsController.uploadThumb); router.post('/user/:userslug/uploadpicture', middlewares.concat([middleware.authenticate, middleware.checkGlobalPrivacySettings, middleware.checkAccountPermissions]), controllers.accounts.edit.uploadPicture); - + + router.post('/user/uploadcover', middlewares.concat([middleware.authenticate, middleware.checkGlobalPrivacySettings, middleware.checkAccountPermissions]), controllers.accounts.edit.uploadCoverPicture); router.post('/groups/uploadpicture', middlewares.concat([middleware.authenticate]), controllers.groups.uploadCover); }; diff --git a/src/socket.io/user/profile.js b/src/socket.io/user/profile.js index 4e0be0acc5..4eccfbcfe5 100644 --- a/src/socket.io/user/profile.js +++ b/src/socket.io/user/profile.js @@ -23,6 +23,20 @@ module.exports = function(SocketUser) { ], callback); }; + SocketUser.updateCover = function(socket, data, callback) { + if (!socket.uid) { + return callback(new Error('[[error:no-privileges]]')); + } + + user.isAdministrator(socket.uid, function(err, isAdmin) { + if (!isAdmin && data.uid !== socket.uid) { + return callback(new Error('[[error:no-privileges]]')); + } + + user.updateCoverPicture(data, callback); + }); + }; + function isAdminOrSelfAndPasswordMatch(uid, data, callback) { async.parallel({ isAdmin: async.apply(user.isAdministrator, uid), diff --git a/src/user/picture.js b/src/user/picture.js index cf89f34399..20bb9647ef 100644 --- a/src/user/picture.js +++ b/src/user/picture.js @@ -4,10 +4,12 @@ var async = require('async'), path = require('path'), fs = require('fs'), nconf = require('nconf'), + crypto = require('crypto'), winston = require('winston'), request = require('request'), mime = require('mime'), + uploadsController = require('../controllers/uploads'), plugins = require('../plugins'), file = require('../file'), image = require('../image'), @@ -51,7 +53,7 @@ module.exports = function(User) { next(); } } - ], function(err, result) { + ], function(err) { function done(err, image) { if (err) { return callback(err); @@ -99,7 +101,7 @@ module.exports = function(User) { return callback(new Error('[[error:no-plugin]]')); } - request.head(url, function(err, res, body) { + request.head(url, function(err, res) { if (err) { return callback(err); } @@ -126,4 +128,74 @@ module.exports = function(User) { }); }); }; + + User.updateCoverPosition = function(uid, position, callback) { + User.setUserField(uid, 'cover:position', position, callback); + }; + + User.updateCoverPicture = function(data, callback) { + var tempPath, url, md5sum; + + if (!data.imageData && data.position) { + return User.updateCoverPosition(data.uid, data.position, callback); + } + + async.series([ + function(next) { + if (data.file) { + return next(); + } + + md5sum = crypto.createHash('md5'); + md5sum.update(data.imageData); + md5sum = md5sum.digest('hex'); + next(); + }, + function(next) { + if (data.file) { + return next(); + } + + tempPath = path.join(nconf.get('base_dir'), nconf.get('upload_path'), md5sum); + var buffer = new Buffer(data.imageData.slice(data.imageData.indexOf('base64') + 7), 'base64'); + + fs.writeFile(tempPath, buffer, { + encoding: 'base64' + }, next); + }, + function(next) { + uploadsController.uploadUserCover({ + name: 'profileCover', + path: data.file ? data.file : tempPath, + uid: data.uid + }, function(err, uploadData) { + if (err) { + return next(err); + } + + url = uploadData.url; + next(); + }); + }, + function(next) { + User.setUserField(data.uid, 'cover:url', url, next); + }, + function(next) { + require('fs').unlink(data.file ? data.file : tempPath, next); + } + ], function(err) { + if (err) { + return callback(err); + } + + if (data.position) { + User.updateCoverPosition(data.uid, data.position, function(err) { + callback(err, {url: url}); + }); + } else { + callback(err, {url: url}); + } + }); + }; + }; \ No newline at end of file