diff --git a/src/routes/accesscontrol.js b/src/routes/accesscontrol.js index b29b83775..17bc113e4 100644 --- a/src/routes/accesscontrol.js +++ b/src/routes/accesscontrol.js @@ -27,7 +27,7 @@ async function passwordAuth(req, res, next) { const verifyFunc = username.indexOf('@') === -1 ? users.verifyWithUsername : users.verifyWithEmail; - let [error, user] = await safe(verifyFunc(username, password, users.AP_WEBADMIN, { totpToken })); + let [error, user] = await safe(verifyFunc(username, password, users.AP_WEBADMIN, { totpToken, skipTotpCheck: false })); if (error && error.reason === BoxError.INVALID_CREDENTIALS) return next(new HttpError(401, error.message)); if (error && error.reason === BoxError.NOT_FOUND) return next(new HttpError(401, 'Unauthorized')); if (error) return next(new HttpError(500, error)); diff --git a/src/routes/profile.js b/src/routes/profile.js index a7cdf577d..4882b7b04 100644 --- a/src/routes/profile.js +++ b/src/routes/profile.js @@ -1,7 +1,7 @@ 'use strict'; exports = module.exports = { - authorize, + canEditProfile, get, setDisplayName, setEmail, @@ -25,7 +25,7 @@ const assert = require('assert'), safe = require('safetydance'), users = require('../users.js'); -async function authorize(req, res, next) { +async function canEditProfile(req, res, next) { assert.strictEqual(typeof req.user, 'object'); const [error, profileConfig] = await safe(users.getProfileConfig()); @@ -66,12 +66,6 @@ async function setEmail(req, res, next) { assert.strictEqual(typeof req.body, 'object'); if ('email' in req.body && typeof req.body.email !== 'string') return next(new HttpError(400, 'email must be string')); - if (!req.body.password || typeof req.body.password !== 'string') return next(new HttpError(400, 'password must be non empty string')); - - const [verifyError] = await safe(users.verify(req.user.id, req.body.password, users.AP_WEBADMIN, { skipTotpCheck: true })); // just check password - if (verifyError) return next(BoxError.toHttpError(verifyError)); - - req.body.password = ''; // this will prevent logs from displaying plain text password const [error] = await safe(users.update(req.user, { email: req.body.email }, AuditSource.fromRequest(req))); if (error) return next(BoxError.toHttpError(error)); @@ -84,12 +78,6 @@ async function setFallbackEmail(req, res, next) { assert.strictEqual(typeof req.body, 'object'); if ('fallbackEmail' in req.body && typeof req.body.fallbackEmail !== 'string') return next(new HttpError(400, 'fallbackEmail must be string')); - if (!req.body.password || typeof req.body.password !== 'string') return next(new HttpError(400, 'password must be non empty string')); - - const [verifyError] = await safe(users.verify(req.user.id, req.body.password, users.AP_WEBADMIN, { skipTotpCheck: true })); // just check password - if (verifyError) return next(BoxError.toHttpError(verifyError)); - - req.body.password = ''; // this will prevent logs from displaying plain text password const [error] = await safe(users.update(req.user, { fallbackEmail: req.body.fallbackEmail }, AuditSource.fromRequest(req))); if (error) return next(BoxError.toHttpError(error)); diff --git a/src/routes/users.js b/src/routes/users.js index b413456f1..b23b91f1d 100644 --- a/src/routes/users.js +++ b/src/routes/users.js @@ -167,6 +167,7 @@ async function del(req, res, next) { async function verifyPassword(req, res, next) { assert.strictEqual(typeof req.body, 'object'); + assert.strictEqual(typeof req.user, 'object'); if (typeof req.body.password !== 'string') return next(new HttpError(400, 'API call requires user password')); diff --git a/src/server.js b/src/server.js index 13398846a..75693d7d4 100644 --- a/src/server.js +++ b/src/server.js @@ -160,9 +160,9 @@ async function initializeExpressSync() { // working off the user behind the provided token router.get ('/api/v1/profile', token, authorizeUser, routes.profile.get); - router.post('/api/v1/profile/display_name', json, token, authorizeUser, routes.profile.authorize, routes.profile.setDisplayName); - router.post('/api/v1/profile/email', json, token, authorizeUser, routes.profile.authorize, routes.profile.setEmail); - router.post('/api/v1/profile/fallback_email', json, token, authorizeUser, routes.profile.authorize, routes.profile.setFallbackEmail); + router.post('/api/v1/profile/display_name', json, token, authorizeUser, routes.profile.canEditProfile, routes.profile.setDisplayName); + router.post('/api/v1/profile/email', json, token, authorizeUser, routes.profile.canEditProfile, routes.users.verifyPassword, routes.profile.setEmail); + router.post('/api/v1/profile/fallback_email', json, token, authorizeUser, routes.profile.canEditProfile, routes.users.verifyPassword, routes.profile.setFallbackEmail); router.get ('/api/v1/profile/avatar/:identifier', routes.profile.getAvatar); // this is not scoped so it can used directly in img tag router.post('/api/v1/profile/avatar', json, token, authorizeUser, (req, res, next) => { return typeof req.body.avatar === 'string' ? next() : multipart(req, res, next); }, routes.profile.setAvatar); // avatar is not exposed in LDAP. so it's personal and not locked router.get ('/api/v1/profile/background_image', token, authorizeUser, routes.profile.getBackgroundImage);