move various login routes under auth/
This commit is contained in:
+1
-107
@@ -1,11 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
exports = module.exports = {
|
||||
login,
|
||||
logout,
|
||||
passwordResetRequest,
|
||||
passwordReset,
|
||||
setupAccount,
|
||||
getConfig,
|
||||
|
||||
updateDashboardDomain,
|
||||
@@ -25,112 +20,11 @@ const assert = require('assert'),
|
||||
AuditSource = require('../auditsource.js'),
|
||||
BoxError = require('../boxerror.js'),
|
||||
cloudron = require('../cloudron.js'),
|
||||
constants = require('../constants.js'),
|
||||
debug = require('debug')('box:routes/cloudron'),
|
||||
eventlog = require('../eventlog.js'),
|
||||
HttpError = require('connect-lastmile').HttpError,
|
||||
HttpSuccess = require('connect-lastmile').HttpSuccess,
|
||||
platform = require('../platform.js'),
|
||||
safe = require('safetydance'),
|
||||
speakeasy = require('speakeasy'),
|
||||
tokens = require('../tokens.js'),
|
||||
translation = require('../translation.js'),
|
||||
users = require('../users.js');
|
||||
|
||||
async function login(req, res, next) {
|
||||
assert.strictEqual(typeof req.user, 'object');
|
||||
|
||||
if ('type' in req.body && typeof req.body.type !== 'string') return next(new HttpError(400, 'type must be a string'));
|
||||
|
||||
const type = req.body.type || tokens.ID_WEBADMIN;
|
||||
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || null;
|
||||
const userAgent = req.headers['user-agent'] || '';
|
||||
const auditSource = { authType: 'basic', ip };
|
||||
|
||||
let error = tokens.validateTokenType(type);
|
||||
if (error) return next(new HttpError(400, error.message));
|
||||
|
||||
let token;
|
||||
[error, token] = await safe(tokens.add({ clientId: type, identifier: req.user.id, expires: Date.now() + constants.DEFAULT_TOKEN_EXPIRATION_MSECS }));
|
||||
if (error) return next(new HttpError(500, error));
|
||||
|
||||
await eventlog.add(req.user.ghost ? eventlog.ACTION_USER_LOGIN_GHOST : eventlog.ACTION_USER_LOGIN, auditSource, { userId: req.user.id, user: users.removePrivateFields(req.user) });
|
||||
|
||||
if (!req.user.ghost) safe(users.notifyLoginLocation(req.user, ip, userAgent, auditSource), { debug });
|
||||
|
||||
next(new HttpSuccess(200, token));
|
||||
}
|
||||
|
||||
async function logout(req, res) {
|
||||
assert.strictEqual(typeof req.token, 'object');
|
||||
|
||||
await eventlog.add(eventlog.ACTION_USER_LOGOUT, AuditSource.fromRequest(req), { userId: req.user.id, user: users.removePrivateFields(req.user) });
|
||||
|
||||
await safe(tokens.delByAccessToken(req.token.accessToken));
|
||||
res.redirect('/');
|
||||
}
|
||||
|
||||
async function passwordResetRequest(req, res, next) {
|
||||
if (!req.body.identifier || typeof req.body.identifier !== 'string') return next(new HttpError(401, 'A identifier must be non-empty string'));
|
||||
|
||||
const [error] = await safe(users.sendPasswordResetByIdentifier(req.body.identifier, AuditSource.fromRequest(req)));
|
||||
if (error && !(error.reason === BoxError.NOT_FOUND || error.reason === BoxError.CONFLICT)) return next(BoxError.toHttpError(error));
|
||||
|
||||
next(new HttpSuccess(202, {}));
|
||||
}
|
||||
|
||||
async function passwordReset(req, res, next) {
|
||||
assert.strictEqual(typeof req.body, 'object');
|
||||
|
||||
if (typeof req.body.resetToken !== 'string') return next(new HttpError(400, 'Missing resetToken'));
|
||||
if (typeof req.body.password !== 'string') return next(new HttpError(400, 'Missing password'));
|
||||
|
||||
let [error, userObject] = await safe(users.getByResetToken(req.body.resetToken));
|
||||
if (error) return next(new HttpError(401, 'Invalid resetToken'));
|
||||
if (!userObject) return next(new HttpError(401, 'Invalid resetToken'));
|
||||
|
||||
if (userObject.twoFactorAuthenticationEnabled) {
|
||||
if (typeof req.body.totpToken !== 'string') return next(new HttpError(401, 'A totpToken must be provided'));
|
||||
|
||||
const verified = speakeasy.totp.verify({ secret: userObject.twoFactorAuthenticationSecret, encoding: 'base32', token: req.body.totpToken, window: 2 });
|
||||
if (!verified) return next(new HttpError(401, 'Invalid totpToken'));
|
||||
}
|
||||
|
||||
// if you fix the duration here, the emails and UI have to be fixed as well
|
||||
if (Date.now() - userObject.resetTokenCreationTime > 7 * 24 * 60 * 60 * 1000) return next(new HttpError(401, 'Token expired'));
|
||||
if (!userObject.username) return next(new HttpError(409, 'No username set'));
|
||||
|
||||
// setPassword clears the resetToken
|
||||
[error] = await safe(users.setPassword(userObject, req.body.password, AuditSource.fromRequest(req)));
|
||||
if (error && error.reason === BoxError.BAD_FIELD) return next(new HttpError(400, error.message));
|
||||
if (error) return next(BoxError.toHttpError(error));
|
||||
|
||||
let result;
|
||||
[error, result] = await safe(tokens.add({ clientId: tokens.ID_WEBADMIN, identifier: userObject.id, expires: Date.now() + constants.DEFAULT_TOKEN_EXPIRATION_MSECS }));
|
||||
if (error) return next(BoxError.toHttpError(error));
|
||||
|
||||
next(new HttpSuccess(202, { accessToken: result.accessToken }));
|
||||
}
|
||||
|
||||
async function setupAccount(req, res, next) {
|
||||
assert.strictEqual(typeof req.body, 'object');
|
||||
|
||||
if (!req.body.inviteToken || typeof req.body.inviteToken !== 'string') return next(new HttpError(400, 'inviteToken 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'));
|
||||
|
||||
// only sent if profile is not locked
|
||||
if ('username' in req.body && typeof req.body.username !== 'string') return next(new HttpError(400, 'username must be a non-empty string'));
|
||||
if ('displayName' in req.body && typeof req.body.displayName !== 'string') return next(new HttpError(400, 'displayName must be a non-empty string'));
|
||||
|
||||
const [error, userObject] = await safe(users.getByInviteToken(req.body.inviteToken));
|
||||
if (error) return next(new HttpError(401, 'Invalid inviteToken'));
|
||||
if (!userObject) return next(new HttpError(401, 'Invalid inviteToken'));
|
||||
|
||||
const [setupAccountError, accessToken] = await safe(users.setupAccount(userObject, req.body, AuditSource.fromRequest(req)));
|
||||
if (setupAccountError) return next(BoxError.toHttpError(setupAccountError));
|
||||
|
||||
next(new HttpSuccess(201, { accessToken }));
|
||||
}
|
||||
translation = require('../translation.js');
|
||||
|
||||
async function getConfig(req, res, next) {
|
||||
const [error, cloudronConfig] = await safe(cloudron.getConfig());
|
||||
|
||||
Reference in New Issue
Block a user