1 Commits

Author SHA1 Message Date
Mike Fitzpatrick
1936683f0e - Fixes for missing signup imports 2019-08-17 02:47:31 -04:00
19 changed files with 52 additions and 352 deletions

View File

@@ -11,22 +11,15 @@ module.exports = {
},
version: '0.1.0',
assetStoreUrl: 'https://www.google.com/',
mail: {
smtp: {
host: 'mail.fitz.guru',
port: 587,
secure: false,
auth: {
user: 'donotreply@eventment.io',
pass: '3ventment.eieio',
},
tls: {
rejectUnauthorized: false,
},
services: {
apple: {},
facebook: {
appId: '2359355590971136',
appSecret: 'a5703f7d0af8e694aec5bd4175a85d6b',
},
from: {
address: 'donotreply@eventment.io',
name: 'Eventment.io Support',
google: {
appId: '442412638360-p0idffou0qlpgor7agideudb1dh10mpf.apps.googleusercontent.com',
appSecret: 'a7fmS7Wc9Ssycr21WXdQ4TYl',
},
},
security: {
@@ -40,20 +33,5 @@ module.exports = {
route: '/reset',
tokenPlaceholder: ':reset_token',
},
confirm: {
route: '/confirm',
tokenPlaceholder: ':confirm_token',
},
},
services: {
apple: {},
facebook: {
appId: '2359355590971136',
appSecret: 'a5703f7d0af8e694aec5bd4175a85d6b',
},
google: {
appId: '442412638360-p0idffou0qlpgor7agideudb1dh10mpf.apps.googleusercontent.com',
appSecret: 'a7fmS7Wc9Ssycr21WXdQ4TYl',
},
},
};

View File

@@ -1,28 +0,0 @@
const config = require('../config');
const helpers = require('../lib/helpers');
const Mailer = require('../lib/Mailer');
module.exports = {
confirmation: ({ email, firstName, token }, callback = helpers.emptyFunction) => {
const link = `${config.api.url}${config.security.confirm.route}/${encodeURI(token)}`;
const mail = {
subject: 'Please confirm your account',
text: `Please confirm your account\r\r\r\r${firstName},\r\rAn account was recently created on the Eventment giving platform for this email (${email}).\r\rTo complete your registration, please open this link in your browser: ${link}\r\rIf you did not create this account, please disregard this email.`,
html: `<h2>Please confirm your account</h2><p>${firstName},</p><p>An account was recently created on the Eventment giving platform for this email (${email}).</p>To complete your registration, please <a href="${link}">click here</a>.</p><p><b>If you did not create this account, please disregard this email.</b></p>`,
};
Mailer(email, mail, callback);
},
reset: ({ email, firstName, token }, callback = helpers.emptyFunction) => {
const link = `${config.api.url}${config.security.reset.route}/${encodeURI(token)}`;
const mail = {
subject: 'Please confirm your account',
text: `Password Reset Request\r\r\r\r${firstName},\r\rA password reset request was made for your account on the Eventment giving platform.\r\rTo reset your password, please open this link in your browser: ${link}\r\rIf you did not make this request, you may disregard this email and your password will remain unchanged.`,
html: `<h2>Password Reset Request</h2><p>${firstName},</p><p>A password reset request was made for your account on the Eventment giving platform.</p>To reset your password, please <a href="${link}">click here</a>.</p><p><b>If you did not make this request, you may disregard this email and your password will remain unchanged.</b></p>`,
};
Mailer(email, mail, callback);
},
};

View File

@@ -1,17 +0,0 @@
const config = require('../config.js');
const nodemailer = require('nodemailer');
const from = `${config.mail.from.name} <${config.mail.from.address}>`;
const transporter = nodemailer.createTransport(config.mail.smtp);
module.exports = (email, options, callback) => {
callback = typeof callback === 'function' ? callback : (error, info) => {
if (error) {
return console.log(error);
}
console.log('Message %s sent: %s', info.messageId, info.response);
};
transporter.sendMail({ to: email, from, ...options }, callback);
};

View File

@@ -1,6 +0,0 @@
module.exports = {
emptyFunction: (...args) => args,
};

View File

@@ -1,3 +1,5 @@
const errors = require('restify-errors');
const validateJsonData = (req, res, next) => {
if (!req.is('application/json')) {
return next(

View File

@@ -1,76 +0,0 @@
const mongoose = require('mongoose');
const timestamps = require('mongoose-timestamp');
const ItemAuctionStatusSchema = new mongoose.Schema(
{
bidCount: Number,
bidders: [ mongoose.Schema.Types.ObjectId ],
currentBid: Number,
currentMax: Number,
winners: [ mongoose.Schema.Types.ObjectId ],
},
{ minimize: false },
);
const AuctionSchema = new mongoose.Schema(
{
eventId: {
type: String,
required: true,
trim: true,
},
scoreboard: [ ItemAuctionStatusSchema ],
},
{ minimize: false },
);
AuctionSchema.plugin(timestamps);
AuctionSchema.statics.getAuctionStatus = function(eventId, bidderId, callback = () => {}) {
this.findOne({ _id: eventId }, (err, event) => {
if (err) {
return next(err);
}
const statusObject = [];
if (event) {
statusObject.push(event.scoreboard.map((item) => ({
id: item._id,
bidCount: item.bidCount,
currentPrice: item.currentBid,
isBidding: item.bidders.indexOf(bidderId) > -1,
isWinning: item.winners.indexOf(bidderId) > -1,
})));
}
return callback(null, statusObject);
});
};
AuctionSchema.statics.getAuctionItemStatus = function(eventId, itemId, bidderId, callback = () => {}) {
this.findOne({ _id: eventId }, (err, event) => {
if (err) {
return next(err);
}
const itemStatus = {};
if (event) {
const item = event.scoreboard.id(itemId);
if (item) {
itemStatus._id = item._id;
itemStatus.bidCount = item.bidCount;
itemStatus.currentPrice = item.currentBid;
itemStatus.isBidding = item.bidders.indexOf(bidderId) > -1;
itemStatus.isWinning = item.winners.indexOf(bidderId) > -1;
}
}
return callback(null, itemStatus);
});
};
const Auction = mongoose.model('Auction', AuctionSchema);
module.exports = Auction;

View File

@@ -3,11 +3,6 @@ const timestamps = require('mongoose-timestamp');
const BidSchema = new mongoose.Schema(
{
eventId: {
type: String,
required: true,
trim: true,
},
itemId: {
type: String,
required: true,

View File

@@ -15,7 +15,7 @@ const PhoneSchema = new mongoose.Schema(
label: {
type: String,
required: true,
enum: [ 'home', 'mobile' ],
enum: [ 'home', 'mobile', 'work' ],
},
},

View File

@@ -1,9 +1,7 @@
const config = require('../config.js');
const mongoose = require('mongoose');
const timestamps = require('mongoose-timestamp');
const config = require('../config.js');
const Item = require('./item');
const PostSchema = new mongoose.Schema(
{
author: String,
@@ -135,11 +133,7 @@ const EventSchema = new mongoose.Schema(
EventSchema.plugin(timestamps);
EventSchema.path('images').get(v => `${config.assetStoreUrl}${v.url}`);
EventSchema.methods.getEventAuctionItems = function(callback = () => {}) {
return Item.getAuctionItemsByEvent(this.id, callback);
};
EventSchema.path('images').get(v => `${config.assetStoreUrl}${v.url}`)
const Event = mongoose.model('Event', EventSchema);
module.exports = Event;

View File

@@ -131,9 +131,5 @@ ItemSchema.statics.addBatch = function(data = [], callback = () => {}) {
};
ItemSchema.statics.getAuctionItemsByEvent = function(eventId, callback = () => {}) {
return this.find({ eventId, type: 'auction' }, callback);
};
const Item = mongoose.model('Item', ItemSchema);
module.exports = Item;

View File

@@ -5,7 +5,6 @@ const timestamps = require('mongoose-timestamp');
const config = require('../config.js');
const UserEmails = require('../emails/user');
const AddressSchema = require('./common/address.js');
const PhoneSchema = require('./common/phone.js');
@@ -98,7 +97,7 @@ const UserSchema = new mongoose.Schema(
default: false,
},
tokenCheckBit: {
resetCheckBit: {
type: String,
default: null,
},
@@ -128,30 +127,11 @@ UserSchema.methods.authenticate = function (username, password) {
return false;
};
UserSchema.methods.confirmRegistration = function (callback = () => {}) {
this.isVerified = true;
this.tokenCheckBit = undefined;
this.save(callback);
UserSchema.methods.isNomAvailable = function (nom) {
return !!!this.model('User').findOne({ nomDeBid });
};
UserSchema.methods.generateAccountToken = function (callback = () => {}) {
const tokenCheckBit = crypto.randomBytes(16).toString('hex');
const token = jwt.sign({
sub: this.id,
key: tokenCheckBit,
iss: config.security.jwt.issuer,
aud: config.security.jwt.audience,
iat: Date.now(),
exp: (Date.now() + (24*60*60*1000)),
}, config.security.jwt.secret);
this.tokenCheckBit = tokenCheckBit;
this.save();
return token;
};
UserSchema.methods.generateLoginToken = function (props = {}) {
UserSchema.methods.generateJWT = function (props = {}) {
const { exp, iss } = props;
const today = new Date();
@@ -180,12 +160,25 @@ UserSchema.methods.getNomDeBid = function () {
return this.nomDeBid || `${this.firstName} ${this.lastName.charAt(0)}`;
};
UserSchema.methods.isEventManager = function () {
return this.isOrganizationEmployee || false;
UserSchema.methods.generateResetToken = function (callback = () => {}) {
const resetCheckBit = crypto.randomBytes(16).toString('hex');
const token = jwt.sign({
sub: this.id,
key: resetCheckBit,
iss:config.security.jwt.issuer,
aud: config.security.jwt.audience,
iat: Date.now(),
exp: (Date.now() + (24*60*60*1000)),
}, config.security.jwt.secret);
this.resetCheckBit = resetCheckBit;
this.save();
return token;
};
UserSchema.methods.isNomAvailable = function (nom) {
return !!!this.model('User').findOne({ nomDeBid });
UserSchema.methods.isEventManager = function () {
return this.isOrganizationEmployee || false;
};
UserSchema.methods.isRegistrationVerified = function () {
@@ -193,7 +186,7 @@ UserSchema.methods.isRegistrationVerified = function () {
};
UserSchema.methods.sendPasswordReset = function () {
const resetToken = this.generateAccountToken();
const resetToken = this.generateResetToken();
let resetRoute = config.security.resetRoute;
resetRoute = resetRoute.replace(':user_id', this.id);
@@ -203,19 +196,6 @@ UserSchema.methods.sendPasswordReset = function () {
console.log('[sendPasswordReset] resetUrl:', resetUrl);
};
UserSchema.methods.sendConfirmationEmail = function (callback) {
const user = {
email: this.email,
firstName: this.firstName,
token: this.generateAccountToken(),
};
callback = typeof callback === 'function' ? callback :
(err, info) => console.log('[UserSchema.methods.sendConfirmationEmail]', { err, info });
UserEmails.confirmation(user, callback);
};
UserSchema.methods.setNomDeBid = function (nomDeBid, callback = () => {}) {
const alreadyExists = this.isNomAvailable(nomDeBid);
@@ -243,7 +223,7 @@ UserSchema.methods.setPassword = function (password, callback = () => {}) {
if (hasLocalStrategy) {
this.model('User').findOneAndUpdate(
{ _id: this._id, 'credentials.method': 'local' },
{ $set: { 'credentials.$': strategy }, $unset: { tokenCheckBit: '' } },
{ $set: { 'credentials.$': strategy, resetCheckBit: null } },
{ upsert: true },
callback,
);
@@ -251,7 +231,7 @@ UserSchema.methods.setPassword = function (password, callback = () => {}) {
if (!hasLocalStrategy) {
this.credentials.push(strategy);
this.tokenCheckBit = undefined;
this.resetCheckBit = null;
this.save(callback);
}
};
@@ -262,9 +242,8 @@ UserSchema.methods.toAuthJSON = function () {
return {
email: this.email,
token: this.generateLoginToken(),
token: this.generateJWT(),
user: {
id: this._id,
nomDeBid: nomDeBid,
email: this.email,
firstName: this.firstName,
@@ -287,11 +266,6 @@ UserSchema.methods.toProfileJSON = function () {
email: this.email,
firstName: this.firstName,
generatedNomDeBid: !hasNomDeBid,
hasLinkedApple: !!this.getAuthStrategy('apple'),
hasLinkedFacebook: !!this.getAuthStrategy('facebook'),
hasLinkedGoogle: !!this.getAuthStrategy('google'),
hasLocalAccount: !!this.getAuthStrategy('local'),
id: this.id,
isAllowedToBid: this.isAllowedToBid,
isOrganizationEmployee: this.isOrganizationEmployee,
isVerified: this.isVerified,
@@ -374,32 +348,14 @@ UserSchema.statics.findOneAndUpdateOrCreate = function (
});
};
UserSchema.statics.register = function (user, callback = () => {}) {
this.create(user, (err, user) => {
if (err) {
return callback(err, null);
}
if (user) {
user.sendConfirmationEmail((err, info) => {
if (err) {
return callback(err, null);
}
callback(null, user);
});
}
});
};
UserSchema.statics.verifyAccountToken = function (token, callback) {
UserSchema.statics.verifyResetToken = function (token, callback) {
jwt.verify(token, config.security.jwt.secret, (err, decoded) => {
if (err) {
return callback(err);
}
const { sub, key } = decoded;
this.findOne({ _id: sub, tokenCheckBit: key }, (err, user) => {
this.findOne({ _id: sub, resetCheckBit: key }, (err, user) => {
if (err) {
return callback(err);
}
@@ -414,7 +370,7 @@ UserSchema.statics.verifyAccountToken = function (token, callback) {
};
UserSchema.statics.verifyTokenAndResetPassword = function (token, password, callback) {
this.verifyAccountToken(token, (err, user, info) => {
this.verifyResetToken(token, (err, user, info) => {
if (err) {
return callback(err);
}
@@ -427,20 +383,6 @@ UserSchema.statics.verifyTokenAndResetPassword = function (token, password, call
});
};
UserSchema.statics.verifyTokenAndConfirmRegistration = function (token, callback) {
this.verifyAccountToken(token, (err, user, info) => {
if (err) {
return callback(err);
}
if (!user) {
return callback(err, false, info);
}
user.confirmRegistration(callback);
});
};
/**
* PATH OPERATIONS

View File

@@ -13,7 +13,6 @@
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.6.0",
"mongoose-timestamp": "^0.6.0",
"nodemailer": "^6.3.0",
"passport": "^0.4.0",
"passport-facebook": "^3.0.0",
"passport-google-oauth": "^2.0.0",

View File

@@ -1,43 +0,0 @@
const errors = require('restify-errors');
const config = require('../config');
const Auction = require('../models/auction');
const Bid = require('../models/bid');
const User = require('../models/user');
module.exports = function (server, auth) {
server.get('/auction', auth.basic, function (req, res, next) {
Auction.getAuctionStatus(null, req.user.bidderId, (err, doc) => {
if (err) {
return next(err);
}
res.send(doc);
next();
});
});
server.get('/auction/:event_id', auth.basic, function (req, res, next) {
Auction.getAuctionStatus(req.params.event_id, req.user.bidderId, (err, doc) => {
if (err) {
return next(err);
}
res.send(doc);
next();
});
});
server.get('/auction/:event_id/:item_id', auth.basic, function (req, res, next) {
const { event_id: eventId, item_id: itemId } = req.params;
Auction.getAuctionItemStatus(eventId, itemId, req.user.bidderId, (err, doc) => {
if (err) {
return next(err);
}
res.send(doc);
next();
});
});
};

View File

@@ -1,5 +1,4 @@
module.exports = function(server, auth) {
require('./auction.js')(server, auth);
require('./auth.js')(server, auth);
require('./bids.js')(server, auth);
require('./demo.js')(server, auth);

View File

@@ -23,6 +23,7 @@ module.exports = function (server, auth) {
server.get('/items', auth.basic, (req, res, next) => {
const select = req.user.isManager ? STAFF : PUBLIC;
Item.find(req.params, select, function(err, docs) {
if (err) {
console.error(err);

View File

@@ -15,9 +15,9 @@ const routes = {
};
module.exports = function (server, auth) {
server.get(routes.getTestToken, auth.basic, function (req, res, next) {
server.get(routes.getTestToken, auth.secure, function (req, res, next) {
const { record: user } = req.user;
const resetToken = user.generateAccountToken();
const resetToken = user.generateResetToken();
const resetUrl = `${url}${route}/${resetToken}`;
res.send({ resetToken, resetUrl });
@@ -26,7 +26,7 @@ module.exports = function (server, auth) {
server.post(routes.resetWithToken, auth.bypass, function (req, res, next) {
const { reset_token } = req.params;
const { body: { password } = {}} = req;
const { password } = req.body;
if (!reset_token) {
return next(

View File

@@ -11,7 +11,7 @@ module.exports = function (server, auth) {
let errors = {};
let errorCount = 0;
if (!user) {
errors.user = `is required - can't make something from nothing...`;
errors.user = 'is required - can\'t make something from nothing...';
errorCount++;
}
@@ -21,7 +21,7 @@ module.exports = function (server, auth) {
User.register(user, (err, user, info) => {
if (err) {
return next(err);
next(err);
}
if (info) {
@@ -43,42 +43,7 @@ module.exports = function (server, auth) {
});
});
server.get('/signup/confirm/:token([A-Za-z0-9_]+\.{3})', (req, res, next) => {
const { token } = req.params;
if (!token) {
return next(
new errors.InvalidContentError('A confirmation token was not provided.'),
);
}
User.verifyTokenAndConfirmRegistration(token, (err, user, info) => {
if (err) {
console.error(err);
return next(
new errors.InvalidContentError(err),
);
}
if (!user) {
console.error(err);
res.send({
success: false,
info: `Account registration confirmation failed. ${info}`,
});
return next();
}
res.send({
success: true,
info: 'New account registration confirmed.',
...user.toAuthJSON()
});
next();
});
});
server.get('/signup/validate/email/:email', (req, res, next) => {
server.get('/signup/validate/email/:email', auth.basic, (req, res, next) => {
const email = decodeURI(req.params.email);
User.findOne({ email }, (err, user) => {
@@ -91,7 +56,7 @@ module.exports = function (server, auth) {
});
});
server.get('/signup/validate/nom/:nom_de_bid', (req, res, next) => {
server.get('/signup/validate/nom/:nom_de_bid', auth.basic, (req, res, next) => {
const nomDeBid = decodeURI(req.params.nom_de_bid);
User.findOne({ nomDeBid }, (err, user) => {
@@ -104,7 +69,7 @@ module.exports = function (server, auth) {
});
});
server.post('/signup/verify/resend', (req, res, next) => {
server.post('/signup/verify/resend', auth.basic, (req, res, next) => {
const { body: { email = null } = {} } = req;
User.resendVerificationEmail(email, (err, user, info) => {

View File

@@ -26,7 +26,7 @@ module.exports = function (server, auth) {
});
});
server.get('/users', auth.basic, (req, res, next) => {
server.get('/users', auth.manager, (req, res, next) => {
const { filter } = aqp(req.query);
const select = req.user.isManager ? STAFF : PUBLIC;
@@ -54,7 +54,7 @@ module.exports = function (server, auth) {
);
}
res.send(req.user.isManager ? doc : doc.toProfileJSON());
res.send(doc);
next();
});
});

View File

@@ -1,5 +1,4 @@
const createRequestUserObject = (req, user) => ({
bidderId: user.id || null,
isGuest: !(user && user.id),
isManager: user && user.isEventManager(),
isSelf: user && user.id === req.params.user_id,