move profile icons into the database
This commit is contained in:
@@ -42,7 +42,6 @@ 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'),
|
||||
SFTP_KEYS_DIR: path.join(baseDir(), 'boxdata/sftp/ssh'),
|
||||
ACME_ACCOUNT_KEY_FILE: path.join(baseDir(), 'boxdata/acme/acme.key'),
|
||||
|
||||
+28
-16
@@ -18,8 +18,9 @@ var assert = require('assert'),
|
||||
BoxError = require('../boxerror.js'),
|
||||
HttpError = require('connect-lastmile').HttpError,
|
||||
HttpSuccess = require('connect-lastmile').HttpSuccess,
|
||||
users = require('../users.js'),
|
||||
safe = require('safetydance'),
|
||||
settings = require('../settings.js'),
|
||||
users = require('../users.js'),
|
||||
_ = require('underscore');
|
||||
|
||||
function authorize(req, res, next) {
|
||||
@@ -37,17 +38,21 @@ function authorize(req, res, next) {
|
||||
function get(req, res, next) {
|
||||
assert.strictEqual(typeof req.user, 'object');
|
||||
|
||||
next(new HttpSuccess(200, {
|
||||
id: req.user.id,
|
||||
username: req.user.username,
|
||||
email: req.user.email,
|
||||
fallbackEmail: req.user.fallbackEmail,
|
||||
displayName: req.user.displayName,
|
||||
twoFactorAuthenticationEnabled: req.user.twoFactorAuthenticationEnabled,
|
||||
role: req.user.role,
|
||||
source: req.user.source,
|
||||
avatarUrl: users.getAvatarUrlSync(req.user)
|
||||
}));
|
||||
users.getAvatarUrl(req.user, function (error, avatarUrl) {
|
||||
if (error) return next(BoxError.toHttpError(error));
|
||||
|
||||
next(new HttpSuccess(200, {
|
||||
id: req.user.id,
|
||||
username: req.user.username,
|
||||
email: req.user.email,
|
||||
fallbackEmail: req.user.fallbackEmail,
|
||||
displayName: req.user.displayName,
|
||||
twoFactorAuthenticationEnabled: req.user.twoFactorAuthenticationEnabled,
|
||||
role: req.user.role,
|
||||
source: req.user.source,
|
||||
avatarUrl
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
function update(req, res, next) {
|
||||
@@ -72,7 +77,10 @@ function setAvatar(req, res, next) {
|
||||
|
||||
if (!req.files.avatar) return next(new HttpError(400, 'avatar is missing'));
|
||||
|
||||
users.setAvatar(req.user.id, req.files.avatar.path, function (error) {
|
||||
const avatar = safe.fs.readFileSync(req.files.avatar.path);
|
||||
if (!avatar) return next(BoxError.toHttpError(new BoxError(BoxError.FS_ERROR, safe.error.message)));
|
||||
|
||||
users.setAvatar(req.user.id, avatar, function (error) {
|
||||
if (error) return next(BoxError.toHttpError(error));
|
||||
|
||||
next(new HttpSuccess(202, {}));
|
||||
@@ -82,17 +90,21 @@ function setAvatar(req, res, next) {
|
||||
function clearAvatar(req, res, next) {
|
||||
assert.strictEqual(typeof req.user, 'object');
|
||||
|
||||
users.clearAvatar(req.user.id, function (error) {
|
||||
users.setAvatar(req.user.id, null, function (error) {
|
||||
if (error) return next(BoxError.toHttpError(error));
|
||||
|
||||
next(new HttpSuccess(202, {}));
|
||||
});
|
||||
}
|
||||
|
||||
function getAvatar(req, res) {
|
||||
function getAvatar(req, res, next) {
|
||||
assert.strictEqual(typeof req.params.identifier, 'string');
|
||||
|
||||
res.sendFile(users.getAvatarFileSync(req.params.identifier));
|
||||
users.getAvatar(req.params.identifier, function (error, avatar) {
|
||||
if (error) return next(BoxError.toHttpError(error));
|
||||
|
||||
res.send(avatar);
|
||||
});
|
||||
}
|
||||
|
||||
function changePassword(req, res, next) {
|
||||
|
||||
@@ -967,8 +967,8 @@ describe('Users API', function () {
|
||||
expect(result.body.role).to.equal('user');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,8 +11,6 @@ exports = module.exports = {
|
||||
createInvite,
|
||||
sendInvite,
|
||||
setGroups,
|
||||
setAvatar,
|
||||
clearAvatar,
|
||||
makeOwner,
|
||||
|
||||
disableTwoFactorAuthentication,
|
||||
@@ -210,28 +208,6 @@ function changePassword(req, res, next) {
|
||||
});
|
||||
}
|
||||
|
||||
function setAvatar(req, res, next) {
|
||||
assert.strictEqual(typeof req.resource, 'object');
|
||||
|
||||
if (!req.files.avatar) return next(new HttpError(400, 'avatar is missing'));
|
||||
|
||||
users.setAvatar(req.resource.id, req.files.avatar.path, function (error) {
|
||||
if (error) return next(BoxError.toHttpError(error));
|
||||
|
||||
next(new HttpSuccess(202, {}));
|
||||
});
|
||||
}
|
||||
|
||||
function clearAvatar(req, res, next) {
|
||||
assert.strictEqual(typeof req.resource, 'object');
|
||||
|
||||
users.clearAvatar(req.resource.id, function (error) {
|
||||
if (error) return next(BoxError.toHttpError(error));
|
||||
|
||||
next(new HttpSuccess(202, {}));
|
||||
});
|
||||
}
|
||||
|
||||
// This route transfers ownership from token user to user specified in path param
|
||||
function makeOwner(req, res, next) {
|
||||
assert.strictEqual(typeof req.resource, 'object');
|
||||
|
||||
@@ -178,8 +178,6 @@ function initializeExpressSync() {
|
||||
router.post('/api/v1/users/:userId/make_owner', json, token, authorizeOwner, routes.users.load, routes.users.makeOwner);
|
||||
router.post('/api/v1/users/:userId/send_invite', json, token, authorizeUserManager, routes.users.load, routes.users.sendInvite);
|
||||
router.post('/api/v1/users/:userId/create_invite', json, token, authorizeUserManager, routes.users.load, routes.users.createInvite);
|
||||
router.post('/api/v1/users/:userId/avatar', json, token, authorizeUserManager, routes.users.load, multipart, routes.users.setAvatar);
|
||||
router.del ('/api/v1/users/:userId/avatar', token, authorizeUserManager, routes.users.load, routes.users.clearAvatar);
|
||||
router.post('/api/v1/users/:userId/twofactorauthentication_disable', json, token, authorizeUserManager, routes.users.load, routes.users.disableTwoFactorAuthentication);
|
||||
|
||||
// Group management
|
||||
|
||||
+29
-5
@@ -13,6 +13,8 @@ exports = module.exports = {
|
||||
del,
|
||||
update,
|
||||
count,
|
||||
getAvatar,
|
||||
setAvatar,
|
||||
|
||||
addAppPassword,
|
||||
getAppPasswords,
|
||||
@@ -25,13 +27,13 @@ exports = module.exports = {
|
||||
var assert = require('assert'),
|
||||
BoxError = require('./boxerror.js'),
|
||||
database = require('./database.js'),
|
||||
debug = require('debug')('box:userdb'),
|
||||
mysql = require('mysql');
|
||||
|
||||
var USERS_FIELDS = [ 'id', 'username', 'email', 'fallbackEmail', 'password', 'salt', 'createdAt', 'resetToken', 'displayName',
|
||||
// the avatar field is special and not added here to reduce response sizes
|
||||
const USERS_FIELDS = [ 'id', 'username', 'email', 'fallbackEmail', 'password', 'salt', 'createdAt', 'resetToken', 'displayName',
|
||||
'twoFactorAuthenticationEnabled', 'twoFactorAuthenticationSecret', 'active', 'source', 'role', 'resetTokenCreationTime' ].join(',');
|
||||
|
||||
var APP_PASSWORD_FIELDS = [ 'id', 'name', 'userId', 'identifier', 'hashedPassword', 'creationTime' ].join(',');
|
||||
const APP_PASSWORD_FIELDS = [ 'id', 'name', 'userId', 'identifier', 'hashedPassword', 'creationTime' ].join(',');
|
||||
|
||||
function postProcess(result) {
|
||||
assert.strictEqual(typeof result, 'object');
|
||||
@@ -209,8 +211,6 @@ function getByAccessToken(accessToken, callback) {
|
||||
assert.strictEqual(typeof accessToken, 'string');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
debug('getByAccessToken: ' + accessToken);
|
||||
|
||||
database.query('SELECT ' + USERS_FIELDS + ' FROM users, tokens WHERE tokens.accessToken = ?', [ accessToken ], function (error, result) {
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
if (result.length === 0) return callback(new BoxError(BoxError.NOT_FOUND, 'User not found'));
|
||||
@@ -322,3 +322,27 @@ function delAppPassword(id, callback) {
|
||||
});
|
||||
}
|
||||
|
||||
function getAvatar(id, callback) {
|
||||
assert.strictEqual(typeof id, 'string');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
database.query('SELECT avatar FROM users WHERE id = ?', [ id ], function (error, result) {
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
if (result.length === 0) return callback(new BoxError(BoxError.NOT_FOUND, 'User not found'));
|
||||
|
||||
callback(null, result[0].avatar);
|
||||
});
|
||||
}
|
||||
|
||||
function setAvatar(id, avatar, callback) {
|
||||
assert.strictEqual(typeof id, 'string');
|
||||
assert(avatar === null || typeof Buffer.isBuffer(avatar));
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
database.query('UPDATE users SET avatar=? WHERE id = ?', [ avatar, id ], function (error, result) {
|
||||
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
|
||||
if (result.length === 0) return callback(new BoxError(BoxError.NOT_FOUND, 'User not found'));
|
||||
|
||||
callback(null);
|
||||
});
|
||||
}
|
||||
|
||||
+22
-29
@@ -31,10 +31,9 @@ exports = module.exports = {
|
||||
sendPasswordResetByIdentifier,
|
||||
|
||||
setupAccount,
|
||||
getAvatarUrlSync,
|
||||
getAvatarFileSync,
|
||||
getAvatarUrl,
|
||||
setAvatar,
|
||||
clearAvatar,
|
||||
getAvatar,
|
||||
|
||||
count,
|
||||
|
||||
@@ -62,11 +61,9 @@ let assert = require('assert'),
|
||||
debug = require('debug')('box:user'),
|
||||
eventlog = require('./eventlog.js'),
|
||||
externalLdap = require('./externalldap.js'),
|
||||
fs = require('fs'),
|
||||
groups = require('./groups.js'),
|
||||
hat = require('./hat.js'),
|
||||
mailer = require('./mailer.js'),
|
||||
path = require('path'),
|
||||
paths = require('./paths.js'),
|
||||
qrcode = require('qrcode'),
|
||||
safe = require('safetydance'),
|
||||
@@ -816,38 +813,34 @@ function delAppPassword(id, callback) {
|
||||
});
|
||||
}
|
||||
|
||||
function getAvatarFileSync(id) {
|
||||
assert.strictEqual(typeof id, 'string');
|
||||
|
||||
return path.join(paths.PROFILE_ICONS_DIR, id);
|
||||
}
|
||||
|
||||
function getAvatarUrlSync(user) {
|
||||
function getAvatarUrl(user, callback) {
|
||||
assert.strictEqual(typeof user, 'object');
|
||||
|
||||
if (fs.existsSync(path.join(paths.PROFILE_ICONS_DIR, user.id))) return `${settings.adminOrigin()}/api/v1/profile/avatar/${user.id}`;
|
||||
|
||||
const emailHash = require('crypto').createHash('md5').update(user.email).digest('hex');
|
||||
return `https://www.gravatar.com/avatar/${emailHash}.jpg`;
|
||||
}
|
||||
|
||||
function setAvatar(id, filename, callback) {
|
||||
assert.strictEqual(typeof id, 'string');
|
||||
assert.strictEqual(typeof filename, 'string');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
// rename() was failing on some servers with EXDEV
|
||||
fs.copyFile(filename, path.join(paths.PROFILE_ICONS_DIR, id), function (error) {
|
||||
if (error) return callback(new BoxError(BoxError.FS_ERROR, error.message));
|
||||
userdb.getAvatar(user.id, function (error, avatar) {
|
||||
if (error) return callback(error);
|
||||
if (avatar) return callback(null, `${settings.adminOrigin()}/api/v1/profile/avatar/${user.id}`);
|
||||
|
||||
fs.unlink(filename, () => callback()); // ignore any unlink error
|
||||
const emailHash = require('crypto').createHash('md5').update(user.email).digest('hex');
|
||||
return callback(null, `https://www.gravatar.com/avatar/${emailHash}.jpg`);
|
||||
});
|
||||
}
|
||||
|
||||
function clearAvatar(id, callback) {
|
||||
function getAvatar(id, callback) {
|
||||
assert.strictEqual(typeof id, 'string');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
safe.fs.unlinkSync(path.join(paths.PROFILE_ICONS_DIR, id));
|
||||
callback();
|
||||
userdb.getAvatar(id, function (error, avatar) {
|
||||
if (error) return callback(error);
|
||||
|
||||
return callback(null, avatar);
|
||||
});
|
||||
}
|
||||
|
||||
function setAvatar(id, avatar, callback) {
|
||||
assert.strictEqual(typeof id, 'string');
|
||||
assert(avatar === null || Buffer.isBuffer(avatar));
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
userdb.setAvatar(id, avatar, callback);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user