blob: e2a9def20509197bb19250dddc73a39696378ca0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
// Fire me up!
const _ = require('lodash');
module.exports = {
implements: 'services/auth',
inject: ['mongo', 'settings', 'errors', 'services/utils', 'services/mails']
};
/**
* @param mongo
* @param settings
* @param errors
* @param {UtilsService} utilsService
* @param {MailsService} mailsService
* @returns {AuthService}
*/
module.exports.factory = (mongo, settings, errors, utilsService, mailsService) => {
class AuthService {
/**
* Reset password reset token for user.
*
* @param host Web Console host.
* @param email - user email
* @returns {Promise.<mongo.Account>} - that resolves account found by email with new reset password token.
*/
static resetPasswordToken(host, email) {
return mongo.Account.findOne({email}).exec()
.then((user) => {
if (!user)
throw new errors.MissingResourceException('Account with that email address does not exists!');
if (settings.activation.enabled && !user.activated)
throw new errors.MissingConfirmRegistrationException(user.email);
user.resetPasswordToken = utilsService.randomString(settings.tokenLength);
return user.save();
})
.then((user) => mailsService.sendResetLink(host, user)
.then(() => user));
}
/**
* Reset password by reset token.
*
* @param host Web Console host.
* @param {string} token - reset token
* @param {string} newPassword - new password
* @returns {Promise.<mongo.Account>} - that resolves account with new password
*/
static resetPasswordByToken(host, token, newPassword) {
return mongo.Account.findOne({resetPasswordToken: token}).exec()
.then((user) => {
if (!user)
throw new errors.MissingResourceException('Failed to find account with this token! Please check link from email.');
if (settings.activation.enabled && !user.activated)
throw new errors.MissingConfirmRegistrationException(user.email);
return new Promise((resolve, reject) => {
user.setPassword(newPassword, (err, _user) => {
if (err)
return reject(new errors.AppErrorException('Failed to reset password: ' + err.message));
_user.resetPasswordToken = undefined; // eslint-disable-line no-undefined
resolve(_user.save());
});
});
})
.then((user) => mailsService.sendPasswordChanged(host, user)
.then(() => user));
}
/**
* Find account by token.
*
* @param {string} token - reset token
* @returns {Promise.<{token, email}>} - that resolves token and user email
*/
static validateResetToken(token) {
return mongo.Account.findOne({resetPasswordToken: token}).exec()
.then((user) => {
if (!user)
throw new errors.IllegalAccessError('Invalid token for password reset!');
if (settings.activation.enabled && !user.activated)
throw new errors.MissingConfirmRegistrationException(user.email);
return {token, email: user.email};
});
}
/**
* Validate activationToken token.
*
* @param {mongo.Account} user - User object.
* @param {string} activationToken - activate account token
* @return {Error} If token is invalid.
*/
static validateActivationToken(user, activationToken) {
if (user.activated) {
if (!_.isEmpty(activationToken) && user.activationToken !== activationToken)
return new errors.AuthFailedException('Invalid email or password!');
}
else {
if (_.isEmpty(activationToken))
return new errors.MissingConfirmRegistrationException(user.email);
if (user.activationToken !== activationToken)
return new errors.AuthFailedException('This activation token isn\'t valid.');
}
}
/**
* Check if activation token expired.
*
* @param {mongo.Account} user - User object.
* @param {string} activationToken - activate account token
* @return {boolean} If token was already expired.
*/
static isActivationTokenExpired(user, activationToken) {
return !user.activated &&
new Date().getTime() - user.activationSentAt.getTime() >= settings.activation.timeout;
}
/**
* Reset password reset token for user.
*
* @param host Web Console host.
* @param email - user email.
* @returns {Promise}.
*/
static resetActivationToken(host, email) {
return mongo.Account.findOne({email}).exec()
.then((user) => {
if (!user)
throw new errors.MissingResourceException('Account with that email address does not exists!');
if (!settings.activation.enabled)
throw new errors.IllegalAccessError('Activation was not enabled!');
if (user.activationSentAt &&
new Date().getTime() - user.activationSentAt.getTime() < settings.activation.sendTimeout)
throw new errors.IllegalAccessError('Too Many Activation Attempts!');
user.activationToken = utilsService.randomString(settings.tokenLength);
user.activationSentAt = new Date();
return user.save();
})
.then((user) => mailsService.sendActivationLink(host, user));
}
}
return AuthService;
};