diff --git a/src/routes/cloudron.js b/src/routes/cloudron.js index 8e6eb2bd0..7e7b0a87f 100644 --- a/src/routes/cloudron.js +++ b/src/routes/cloudron.js @@ -5,6 +5,7 @@ exports = module.exports = { logout: logout, passwordResetRequest: passwordResetRequest, passwordReset: passwordReset, + setupAccount: setupAccount, reboot: reboot, isRebootRequired: isRebootRequired, getConfig: getConfig, @@ -29,6 +30,7 @@ let assert = require('assert'), clients = require('../clients.js'), cloudron = require('../cloudron.js'), constants = require('../constants.js'), + debug = require('debug')('box:routes/cloudron'), externalLdap = require('../externalldap.js'), HttpError = require('connect-lastmile').HttpError, HttpSuccess = require('connect-lastmile').HttpSuccess, @@ -120,6 +122,44 @@ function passwordReset(req, res, next) { }); } +function setupAccount(req, res, next) { + assert.strictEqual(typeof req.body, 'object'); + + if (!req.body.email || typeof req.body.email !== 'string') return next(new HttpError(400, 'email must be a non-empty string')); + if (!req.body.resetToken || typeof req.body.resetToken !== 'string') return next(new HttpError(400, 'resetToken must be a non-empty string')); + if (!req.body.password || typeof req.body.password !== 'string') return next(new HttpError(400, 'password must be a non-empty string')); + if (!req.body.username || typeof req.body.username !== 'string') return next(new HttpError(400, 'username must be a non-empty string')); + if (!req.body.displayName || typeof req.body.displayName !== 'string') return next(new HttpError(400, 'displayName must be a non-empty string')); + + debug(`setupAccount: for email ${req.body.email} and username ${req.body.username} with token ${req.body.resetToken}`); + + users.getByResetToken(req.body.resetToken, function (error, userObject) { + if (error) return next(new HttpError(401, 'Invalid Reset Token')); + + users.update(userObject.id, { username: req.body.username, displayName: req.body.displayName }, auditSource(req), function (error) { + if (error && error.reason === BoxError.ALREADY_EXISTS) return next(new HttpError(409, 'Username already used')); + if (error && error.reason === BoxError.BAD_FIELD) return next(new HttpError(400, error.message)); + if (error && error.reason === BoxError.NOT_FOUND) return next(new HttpError(404, 'No such user')); + if (error) return next(new HttpError(500, error)); + + userObject.username = req.body.username; + userObject.displayName = req.body.displayName; + + // setPassword clears the resetToken + users.setPassword(userObject.id, req.body.password, function (error) { + if (error && error.reason === BoxError.BAD_FIELD) return next(new HttpError(400, error.message)); + if (error) return next(new HttpError(500, error)); + + clients.addTokenByUserId(clients.ID_WEBADMIN, userObject.id, Date.now() + constants.DEFAULT_TOKEN_EXPIRATION, {}, function (error, result) { + if (error) return next(new HttpError(500, error)); + + next(new HttpSuccess(201, { accessToken: result.accessToken })); + }); + }); + }); + }); +} + function reboot(req, res, next) { // Finish the request, to let the appstore know we triggered the reboot next(new HttpSuccess(202, {})); diff --git a/src/server.js b/src/server.js index c5850643e..c53e49c33 100644 --- a/src/server.js +++ b/src/server.js @@ -141,6 +141,7 @@ function initializeExpressSync() { router.get ('/api/v1/cloudron/logout', routes.cloudron.logout); // this will invalidate the token if any and redirect to /login.html always router.post('/api/v1/cloudron/password_reset_request', routes.cloudron.passwordResetRequest); router.post('/api/v1/cloudron/password_reset', routes.cloudron.passwordReset); + router.post('/api/v1/cloudron/setup_account', routes.cloudron.setupAccount); // developer routes router.post('/api/v1/developer/login', routes.developer.login);