diff --git a/package.json b/package.json index b4446b7ace..54a0121443 100644 --- a/package.json +++ b/package.json @@ -65,8 +65,8 @@ "nodebb-plugin-spam-be-gone": "0.5.0", "nodebb-rewards-essentials": "0.0.9", "nodebb-theme-lavender": "4.0.0", - "nodebb-theme-persona": "5.0.2", - "nodebb-theme-vanilla": "6.0.2", + "nodebb-theme-persona": "5.0.3", + "nodebb-theme-vanilla": "6.0.3", "nodebb-widget-essentials": "3.0.0", "nodemailer": "2.6.4", "nodemailer-sendmail-transport": "1.0.0", diff --git a/public/src/client/account/edit.js b/public/src/client/account/edit.js index 87675643a3..dd8cbd8406 100644 --- a/public/src/client/account/edit.js +++ b/public/src/client/account/edit.js @@ -60,7 +60,9 @@ define('forum/account/edit', ['forum/account/header', 'translator', 'components' if (parseInt(ajaxify.data.theirid, 10) !== parseInt(ajaxify.data.yourid, 10)) { return; } - + if (!picture && ajaxify.data.defaultAvatar) { + picture = ajaxify.data.defaultAvatar; + } components.get('header/userpicture')[picture ? 'show' : 'hide'](); components.get('header/usericon')[!picture ? 'show' : 'hide'](); if (picture) { @@ -85,6 +87,8 @@ define('forum/account/edit', ['forum/account/header', 'translator', 'components' templates.parse('partials/modals/change_picture_modal', { pictures: pictures, uploaded: uploaded, + icon: { text: ajaxify.data['icon:text'], bgColor: ajaxify.data['icon:bgColor'] }, + defaultAvatar: ajaxify.data.defaultAvatar, allowProfileImageUploads: ajaxify.data.allowProfileImageUploads, }, function (html) { translator.translate(html, function (html) { @@ -115,12 +119,6 @@ define('forum/account/edit', ['forum/account/header', 'translator', 'components' handleImageUpload(modal); function updateImages() { - var userIcon = modal.find('.user-icon'); - - userIcon - .css('background-color', ajaxify.data['icon:bgColor']) - .text(ajaxify.data['icon:text']); - // Check to see which one is the active picture if (!ajaxify.data.picture) { modal.find('.list-group-item .user-icon').parents('.list-group-item').addClass('active'); diff --git a/src/controllers/accounts/edit.js b/src/controllers/accounts/edit.js index cae91cf9d7..61f4cad452 100644 --- a/src/controllers/accounts/edit.js +++ b/src/controllers/accounts/edit.js @@ -29,6 +29,7 @@ editController.get = function (req, res, callback) { userData.allowProfileImageUploads = parseInt(meta.config.allowProfileImageUploads, 10) === 1; userData.allowAccountDelete = parseInt(meta.config.allowAccountDelete, 10) === 1; userData.profileImageDimension = parseInt(meta.config.profileImageDimension, 10) || 200; + userData.defaultAvatar = user.getDefaultAvatar(); userData.groups = userData.groups.filter(function (group) { return group && group.userTitleEnabled && !groups.isPrivilegeGroup(group.name) && group.name !== 'registered-users'; diff --git a/src/middleware/header.js b/src/middleware/header.js index f74b38e3e6..deb8d87cac 100644 --- a/src/middleware/header.js +++ b/src/middleware/header.js @@ -80,7 +80,7 @@ module.exports = function (middleware) { username: '[[global:guest]]', userslug: '', email: '', - picture: meta.config.defaultAvatar, + picture: user.getDefaultAvatar(), status: 'offline', reputation: 0, 'email:confirmed': 0, diff --git a/src/user/data.js b/src/user/data.js index ca8dbd758f..f5f4fd3db7 100644 --- a/src/user/data.js +++ b/src/user/data.js @@ -6,6 +6,7 @@ var nconf = require('nconf'); var winston = require('winston'); var db = require('../database'); +var meta = require('../meta'); var plugins = require('../plugins'); var utils = require('../utils'); @@ -134,7 +135,7 @@ module.exports = function (User) { user.uid = 0; user.username = '[[global:guest]]'; user.userslug = ''; - user.picture = ''; + user.picture = User.getDefaultAvatar(); user['icon:text'] = '?'; user['icon:bgColor'] = '#aaa'; } @@ -145,6 +146,9 @@ module.exports = function (User) { } else if (user.uploadedpicture) { user.uploadedpicture = user.uploadedpicture.startsWith('http') ? user.uploadedpicture : nconf.get('relative_path') + user.uploadedpicture; } + if (meta.config.defaultAvatar && !user.picture) { + user.picture = User.getDefaultAvatar(); + } if (user.hasOwnProperty('status') && parseInt(user.lastonline, 10)) { user.status = User.getStatus(user); @@ -155,7 +159,7 @@ module.exports = function (User) { } // User Icons - if (user.hasOwnProperty('picture') && user.username && parseInt(user.uid, 10)) { + if (user.hasOwnProperty('picture') && user.username && parseInt(user.uid, 10) && !meta.config.defaultAvatar) { user['icon:text'] = (user.username[0] || '').toUpperCase(); user['icon:bgColor'] = iconBackgrounds[Array.prototype.reduce.call(user.username, function (cur, next) { return cur + next.charCodeAt(); @@ -174,6 +178,13 @@ module.exports = function (User) { plugins.fireHook('filter:users.get', users, callback); } + User.getDefaultAvatar = function () { + if (!meta.config.defaultAvatar) { + return ''; + } + return meta.config.defaultAvatar.startsWith('http') ? meta.config.defaultAvatar : nconf.get('relative_path') + meta.config.defaultAvatar; + }; + User.setUserField = function (uid, field, value, callback) { callback = callback || function () {}; async.waterfall([ diff --git a/test/authentication.js b/test/authentication.js index b0dd89186c..3a986f483a 100644 --- a/test/authentication.js +++ b/test/authentication.js @@ -9,6 +9,7 @@ var async = require('async'); var db = require('./mocks/databasemock'); var user = require('../src/user'); var meta = require('../src/meta'); +var helpers = require('./helpers'); describe('authentication', function () { function loginUser(username, password, callback) { @@ -120,32 +121,16 @@ describe('authentication', function () { }); it('should logout a user', function (done) { - request({ - url: nconf.get('url') + '/api/config', - json: true, - jar: jar, - }, function (err, response, body) { + helpers.logoutUser(jar, function (err) { assert.ifError(err); - - request.post(nconf.get('url') + '/logout', { - form: {}, + request({ + url: nconf.get('url') + '/api/me', json: true, jar: jar, - headers: { - 'x-csrf-token': body.csrf_token, - }, - }, function (err) { + }, function (err, response, body) { assert.ifError(err); - - request({ - url: nconf.get('url') + '/api/me', - json: true, - jar: jar, - }, function (err, response, body) { - assert.ifError(err); - assert.equal(body, 'not-authorized'); - done(); - }); + assert.equal(body, 'not-authorized'); + done(); }); }); }); @@ -317,9 +302,9 @@ describe('authentication', function () { it('should be able to login with email', function (done) { - user.create({ username: 'ginger', password: '123456', email: 'ginger@nodebb.org' }, function (err, uid) { + user.create({ username: 'ginger', password: '123456', email: 'ginger@nodebb.org' }, function (err) { assert.ifError(err); - loginUser('ginger@nodebb.org', '123456', function (err, response, body) { + loginUser('ginger@nodebb.org', '123456', function (err, response) { assert.ifError(err); assert.equal(response.statusCode, 200); done(); diff --git a/test/helpers/index.js b/test/helpers/index.js index e850ba23e2..c589c7cdd5 100644 --- a/test/helpers/index.js +++ b/test/helpers/index.js @@ -12,6 +12,7 @@ var helpers = module.exports; helpers.loginUser = function (username, password, callback) { var jar = request.jar(); + request({ url: nconf.get('url') + '/api/config', json: true, @@ -42,6 +43,30 @@ helpers.loginUser = function (username, password, callback) { }); }; + +helpers.logoutUser = function (jar, callback) { + request({ + url: nconf.get('url') + '/api/config', + json: true, + jar: jar, + }, function (err, response, body) { + if (err) { + return callback(err, response, body); + } + + request.post(nconf.get('url') + '/logout', { + form: {}, + json: true, + jar: jar, + headers: { + 'x-csrf-token': body.csrf_token, + }, + }, function (err, response, body) { + callback(err, response, body); + }); + }); +}; + helpers.connectSocketIO = function (res, callback) { myXhr.callbacks.headerCallback = function () { this.setDisableHeaderCheck(true); diff --git a/test/user.js b/test/user.js index 4678c2282f..b710863a4b 100644 --- a/test/user.js +++ b/test/user.js @@ -650,13 +650,13 @@ describe('User', function () { }); it('should set user picture to uploaded', function (done) { - User.setUserField(uid, 'uploadedpicture', 'test', function (err) { + User.setUserField(uid, 'uploadedpicture', '/test', function (err) { assert.ifError(err); socketUser.changePicture({ uid: uid }, { type: 'uploaded', uid: uid }, function (err) { assert.ifError(err); User.getUserField(uid, 'picture', function (err, picture) { assert.ifError(err); - assert.equal(picture, 'test'); + assert.equal(picture, nconf.get('relative_path') + '/test'); done(); }); }); @@ -802,6 +802,18 @@ describe('User', function () { }); }); + it('should get default profile avatar', function (done) { + assert.strictEqual(User.getDefaultAvatar(), ''); + meta.config.defaultAvatar = 'https://path/to/default/avatar'; + assert.strictEqual(User.getDefaultAvatar(), meta.config.defaultAvatar); + meta.config.defaultAvatar = '/path/to/default/avatar'; + nconf.set('relative_path', '/community'); + assert.strictEqual(User.getDefaultAvatar(), '/community' + meta.config.defaultAvatar); + meta.config.defaultAvatar = ''; + nconf.set('relative_path', ''); + done(); + }); + it('should fail to get profile pictures with invalid data', function (done) { socketUser.getProfilePictures({ uid: uid }, null, function (err) { assert.equal(err.message, '[[error:invalid-data]]');