Merge branch 'master' of https://github.com/coralproject/talk into notification-room

This commit is contained in:
David Jay
2016-11-18 11:55:47 -05:00
83 changed files with 2070 additions and 225 deletions
+7
View File
@@ -1,6 +1,13 @@
const mongoose = require('../mongoose');
const Schema = mongoose.Schema;
/**
* this Schema manages application settings that get used on front- and backend
* NOTE: when you set a setting here, it will not automatically be exposed to
* the front end. You must add it to the whitelist in the settings route
* in /routes/api/settings/index.js
* @type {Schema}
*/
const SettingSchema = new Schema({
id: {type: String, default: '1'},
moderation: {type: String, enum: ['pre', 'post'], default: 'pre'},
+87 -2
View File
@@ -1,6 +1,7 @@
const mongoose = require('../mongoose');
const uuid = require('uuid');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
// SALT_ROUNDS is the number of rounds that the bcrypt algorithm will run
// through during the salting process.
@@ -12,6 +13,14 @@ const USER_ROLES = [
'moderator'
];
// In the event that the TALK_SESSION_SECRET is missing but we are testing, then
// set the process.env.TALK_SESSION_SECRET.
if (process.env.NODE_ENV === 'test' && !process.env.TALK_SESSION_SECRET) {
process.env.TALK_SESSION_SECRET = 'keyboard cat';
} else if (!process.env.TALK_SESSION_SECRET) {
throw new Error('TALK_SESSION_SECRET must be defined to encode JSON Web Tokens and other auth functionality');
}
// UserSchema is the mongoose schema defined as the representation of a User in
// MongoDB.
const UserSchema = new mongoose.Schema({
@@ -130,10 +139,14 @@ const UserService = module.exports = {};
* @param {Function} done [description]
*/
UserService.findLocalUser = (email, password) => {
if (!email || typeof email !== 'string') {
return Promise.reject('email is required for findLocalUser');
}
return UserModel.findOne({
profiles: {
$elemMatch: {
id: email,
id: email.toLowerCase(),
provider: 'local'
}
}
@@ -237,6 +250,7 @@ UserService.changePassword = (id, password) => {
})
.then((hashedPassword) => {
return UserModel.update({id}, {
$inc: {__v: 1},
$set: {
password: hashedPassword
}
@@ -268,6 +282,8 @@ UserService.createLocalUser = (email, password, displayName) => {
return Promise.reject('email is required');
}
email = email.toLowerCase();
if (!password) {
return Promise.reject('password is required');
}
@@ -296,9 +312,11 @@ UserService.createLocalUser = (email, password, displayName) => {
user.save((err) => {
if (err) {
if (err.code === 11000) {
return reject('Email address already in use');
}
return reject(err);
}
return resolve(user);
});
});
@@ -393,6 +411,57 @@ UserService.findByIdArray = (ids) => {
});
};
/**
* Creates a JWT from a user email. Only works for local accounts.
* @param {String} email of the local user
*/
UserService.createPasswordResetToken = function (email) {
if (!email || typeof email !== 'string') {
return Promise.reject('email is required when creating a JWT for resetting passord');
}
email = email.toLowerCase();
return UserModel.findOne({profiles: {$elemMatch: {id: email}}})
.then(user => {
if (user === null) {
// since we don't want to reveal that the email does/doesn't exist
// just go ahead and resolve the Promise with null and check in the endpoint
return Promise.resolve(null);
}
const payload = {email, jti: uuid.v4(), userId: user.id, version: user.__v};
const token = jwt.sign(payload, process.env.TALK_SESSION_SECRET, {expiresIn: '1d'});
return token;
});
};
/**
* verifies a jwt and returns the associated user
* @param {String} token the JSON Web Token to verify
*/
UserService.verifyPasswordResetToken = token => {
return new Promise((resolve, reject) => {
jwt.verify(token, process.env.TALK_SESSION_SECRET, (error, decoded) => {
if (error) {
return reject(error);
}
resolve(decoded);
});
})
.then(decoded => {
/**
* TODO: check the jti from this decoded token in redis
* and make an entry if it does not exist.
* reject if entry already exists.
*/
return UserService.findById(decoded.userId);
});
};
/**
* Finds a user using a value which gets compared using a prefix match against
* the user's email address and/or their display name.
@@ -426,3 +495,19 @@ UserService.search = (value) => {
]
});
};
/**
* Returns a count of the current users.
* @return {Promise}
*/
UserService.count = () => {
return UserModel.count();
};
/**
* Returns all the users.
* @return {Promise}
*/
UserService.all = () => {
return UserModel.find();
};