diff --git a/runTests b/runTests index d47f922ef..7c07f0b7c 100755 --- a/runTests +++ b/runTests @@ -22,7 +22,7 @@ fi mkdir -p ${DATA_DIR} cd ${DATA_DIR} mkdir -p appsdata -mkdir -p boxdata/appicons boxdata/mail boxdata/certs boxdata/mail/dkim/localhost boxdata/mail/dkim/foobar.com +mkdir -p boxdata/profileicons boxdata/appicons boxdata/mail boxdata/certs boxdata/mail/dkim/localhost boxdata/mail/dkim/foobar.com mkdir -p platformdata/addons/mail platformdata/nginx/cert platformdata/nginx/applications platformdata/collectd/collectd.conf.d platformdata/addons platformdata/logrotate.d platformdata/backup platformdata/logs/tasks # put cert diff --git a/setup/start.sh b/setup/start.sh index 585db64f8..fccf0b506 100755 --- a/setup/start.sh +++ b/setup/start.sh @@ -51,6 +51,7 @@ mkdir -p "${PLATFORM_DATA_DIR}/logs/backup" \ mkdir -p "${PLATFORM_DATA_DIR}/update" mkdir -p "${BOX_DATA_DIR}/appicons" +mkdir -p "${BOX_DATA_DIR}/profileicons" mkdir -p "${BOX_DATA_DIR}/certs" mkdir -p "${BOX_DATA_DIR}/acme" # acme keys mkdir -p "${BOX_DATA_DIR}/mail/dkim" diff --git a/src/paths.js b/src/paths.js index d3bb1d05c..db6056122 100644 --- a/src/paths.js +++ b/src/paths.js @@ -44,6 +44,7 @@ exports = module.exports = { // this is not part of appdata because an icon may be set before install APP_ICONS_DIR: path.join(baseDir(), 'boxdata/appicons'), + PROFILE_ICONS_DIR: path.join(baseDir(), 'boxdata/profileicons'), MAIL_DATA_DIR: path.join(baseDir(), 'boxdata/mail'), ACME_ACCOUNT_KEY_FILE: path.join(baseDir(), 'boxdata/acme/acme.key'), APP_CERTS_DIR: path.join(baseDir(), 'boxdata/certs'), diff --git a/src/routes/profile.js b/src/routes/profile.js index e3cca1b59..059cbab1a 100644 --- a/src/routes/profile.js +++ b/src/routes/profile.js @@ -3,6 +3,9 @@ exports = module.exports = { get: get, update: update, + getAvatar: getAvatar, + setAvatar: setAvatar, + clearAvatar: clearAvatar, changePassword: changePassword, setTwoFactorAuthenticationSecret: setTwoFactorAuthenticationSecret, enableTwoFactorAuthentication: enableTwoFactorAuthentication, @@ -12,14 +15,21 @@ exports = module.exports = { var assert = require('assert'), auditSource = require('../auditsource.js'), BoxError = require('../boxerror.js'), + fs = require('fs'), HttpError = require('connect-lastmile').HttpError, HttpSuccess = require('connect-lastmile').HttpSuccess, + path = require('path'), + paths = require('../paths.js'), + safe = require('safetydance'), users = require('../users.js'), + settings = require('../settings.js'), _ = require('underscore'); function get(req, res, next) { assert.strictEqual(typeof req.user, 'object'); + const emailHash = require('crypto').createHash('md5').update(req.user.email).digest('hex'); + next(new HttpSuccess(200, { id: req.user.id, username: req.user.username, @@ -28,7 +38,8 @@ function get(req, res, next) { displayName: req.user.displayName, twoFactorAuthenticationEnabled: req.user.twoFactorAuthenticationEnabled, admin: req.user.admin, - source: req.user.source + source: req.user.source, + avatarUrl: fs.existsSync(path.join(paths.PROFILE_ICONS_DIR, req.user.id)) ? `${settings.adminOrigin()}/api/v1/profile/avatar/${req.user.id}` : `https://www.gravatar.com/avatar/${emailHash}.jpg?s=128&d=mm` })); } @@ -49,6 +60,28 @@ function update(req, res, next) { }); } +function setAvatar(req, res, next) { + assert.strictEqual(typeof req.user, 'object'); + + if (!req.files.avatar) return next(new HttpError(400, 'avatar is missing')); + + if (!safe.fs.renameSync(req.files.avatar.path, path.join(paths.PROFILE_ICONS_DIR, req.user.id))) return next(new HttpError(500, safe.error)); + + next(new HttpSuccess(202, {})); +} + +function clearAvatar(req, res, next) { + assert.strictEqual(typeof req.user, 'object'); + + safe.fs.unlinkSync(path.join(paths.PROFILE_ICONS_DIR, req.user.id)); + + next(new HttpSuccess(202, {})); +} + +function getAvatar(req, res) { + res.sendFile(path.join(paths.PROFILE_ICONS_DIR, req.params.identifier)); +} + function changePassword(req, res, next) { assert.strictEqual(typeof req.body, 'object'); assert.strictEqual(typeof req.user, 'object'); diff --git a/src/server.js b/src/server.js index 3f3a65107..2e322b9b0 100644 --- a/src/server.js +++ b/src/server.js @@ -184,6 +184,9 @@ function initializeExpressSync() { // working off the user behind the provided token router.get ('/api/v1/profile', profileScope, routes.profile.get); router.post('/api/v1/profile', profileScope, routes.profile.update); + router.get ('/api/v1/profile/avatar/:identifier', routes.profile.getAvatar); + router.post('/api/v1/profile/avatar', profileScope, multipart, routes.profile.setAvatar); + router.del ('/api/v1/profile/avatar', profileScope, routes.profile.clearAvatar); router.post('/api/v1/profile/password', profileScope, routes.users.verifyPassword, routes.profile.changePassword); router.post('/api/v1/profile/twofactorauthentication', profileScope, routes.profile.setTwoFactorAuthenticationSecret); router.post('/api/v1/profile/twofactorauthentication/enable', profileScope, routes.profile.enableTwoFactorAuthentication);