- More, more, more...
This commit is contained in:
17
config.js
17
config.js
@@ -1,12 +1,15 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'wEvent API',
|
name: 'Eventment.io API',
|
||||||
env: process.env.NODE_ENV || 'development',
|
env: process.env.NODE_ENV || 'development',
|
||||||
port: process.env.PORT || 3001,
|
port: process.env.PORT || 3001,
|
||||||
base_url: process.env.BASE_URL || 'http://localhost:3000',
|
base_url: process.env.BASE_URL || 'http://localhost:3001',
|
||||||
|
api: {
|
||||||
|
url: 'http://localhost:3001',
|
||||||
|
},
|
||||||
db: {
|
db: {
|
||||||
uri: process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/wEvent-dev',
|
uri: process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/wEvent-dev',
|
||||||
},
|
},
|
||||||
version: '0.0.1',
|
version: '0.1.0',
|
||||||
assetStoreUrl: 'https://www.google.com/',
|
assetStoreUrl: 'https://www.google.com/',
|
||||||
services: {
|
services: {
|
||||||
apple: {},
|
apple: {},
|
||||||
@@ -21,10 +24,14 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
security: {
|
security: {
|
||||||
jwt: {
|
jwt: {
|
||||||
audience: 'wEvents.io',
|
audience: 'Eventment.io',
|
||||||
daysValid: 365,
|
daysValid: 365,
|
||||||
issuer: 'patrons.wEvents.io',
|
issuer: 'patrons.eventment.io',
|
||||||
secret: 'Th!sIs a d3v3lopm3nt server $#cr¢T.',
|
secret: 'Th!sIs a d3v3lopm3nt server $#cr¢T.',
|
||||||
},
|
},
|
||||||
|
reset: {
|
||||||
|
route: '/reset',
|
||||||
|
tokenPlaceholder: ':reset_token',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
37
fixtures/item.js
Normal file
37
fixtures/item.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
const item = {
|
||||||
|
eventId: 'x9374bdH93u3ihds453s',
|
||||||
|
title: 'Stay Local, Get Away!',
|
||||||
|
subtitle: 'A romantic weekend for two at the Malden Econolodge!',
|
||||||
|
donor: 'Charlie Baker',
|
||||||
|
description: 'There may be bedbugs, there is absolutely no continental breakfast, and bring earplugs to sleep through police actions. A luxurious courtyard double.',
|
||||||
|
images: [
|
||||||
|
{ url: 'https://random.pics/chdgfj' },
|
||||||
|
{ url: 'https://random.pics/745gdf' },
|
||||||
|
{ url: 'https://random.pics/34sd56' },
|
||||||
|
],
|
||||||
|
type: 'auction',
|
||||||
|
quantityAvailable: 1,
|
||||||
|
soldCount: 0,
|
||||||
|
currentPrice: 125,
|
||||||
|
startingPrice: 100,
|
||||||
|
reservePrice: 199,
|
||||||
|
estimatedValue: 225.49,
|
||||||
|
currentWinner: 'mifi',
|
||||||
|
bidders: [
|
||||||
|
{ name: 'mifi' },
|
||||||
|
{ name: 'mifi79' },
|
||||||
|
],
|
||||||
|
bidCount: 2,
|
||||||
|
bidIncrement: 5,
|
||||||
|
catalogNumber: 16,
|
||||||
|
start: Date.now(),
|
||||||
|
end: Date.now() + (3*60*60*1000),
|
||||||
|
hideBeforeStart: false,
|
||||||
|
hideAfterEnd: true,
|
||||||
|
notifyOnAvailable: false,
|
||||||
|
isShippable: true,
|
||||||
|
shippingCost: 25.68,
|
||||||
|
organizationTake: 0.75,
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = item;
|
||||||
1
index.js
1
index.js
@@ -13,6 +13,7 @@ const validateJsonData = require('./lib/validateType.js');
|
|||||||
* Initialize Server
|
* Initialize Server
|
||||||
*/
|
*/
|
||||||
const server = restify.createServer({
|
const server = restify.createServer({
|
||||||
|
maxParamLength: 500,
|
||||||
name: config.name,
|
name: config.name,
|
||||||
version: config.version,
|
version: config.version,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const mongooseStringQuery = require('mongoose-string-query');
|
const timestamps = require('mongoose-timestamp');
|
||||||
const mongooseTimestamps = require('mongoose-timestamp');
|
|
||||||
|
|
||||||
const AddressSchema = new mongoose.Schema(
|
const AddressSchema = new mongoose.Schema(
|
||||||
{
|
{
|
||||||
@@ -38,7 +37,6 @@ const AddressSchema = new mongoose.Schema(
|
|||||||
{ minimize: false },
|
{ minimize: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
AddressSchema.plugin(mongooseStringQuery);
|
AddressSchema.plugin(timestamps);
|
||||||
AddressSchema.plugin(mongooseTimestamps);
|
|
||||||
|
|
||||||
module.exports = AddressSchema;
|
module.exports = AddressSchema;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const mongooseStringQuery = require('mongoose-string-query');
|
const timestamps = require('mongoose-timestamp');
|
||||||
const mongooseTimestamps = require('mongoose-timestamp');
|
|
||||||
|
|
||||||
const EmailSchema = new mongoose.Schema(
|
const EmailSchema = new mongoose.Schema(
|
||||||
{
|
{
|
||||||
@@ -24,7 +23,6 @@ EmailSchema.virtual('address').get(function() {
|
|||||||
return this.user + '@' + this.domain;
|
return this.user + '@' + this.domain;
|
||||||
});
|
});
|
||||||
|
|
||||||
EmailSchema.plugin(mongooseStringQuery);
|
EmailSchema.plugin(timestamps);
|
||||||
EmailSchema.plugin(mongooseTimestamps);
|
|
||||||
|
|
||||||
module.exports = EmailSchema;
|
module.exports = EmailSchema;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const mongooseStringQuery = require('mongoose-string-query');
|
const timestamps = require('mongoose-timestamp');
|
||||||
const mongooseTimestamps = require('mongoose-timestamp');
|
|
||||||
|
|
||||||
const PhoneSchema = new mongoose.Schema(
|
const PhoneSchema = new mongoose.Schema(
|
||||||
{
|
{
|
||||||
@@ -23,7 +22,6 @@ const PhoneSchema = new mongoose.Schema(
|
|||||||
{ minimize: false },
|
{ minimize: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
PhoneSchema.plugin(mongooseStringQuery);
|
PhoneSchema.plugin(timestamps);
|
||||||
PhoneSchema.plugin(mongooseTimestamps);
|
|
||||||
|
|
||||||
module.exports = PhoneSchema;
|
module.exports = PhoneSchema;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ const { ITEM_TYPES } = require('./constants.js');
|
|||||||
|
|
||||||
const config = require('../config.js');
|
const config = require('../config.js');
|
||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const mongooseStringQuery = require('mongoose-string-query');
|
|
||||||
const timestamps = require('mongoose-timestamp');
|
const timestamps = require('mongoose-timestamp');
|
||||||
|
|
||||||
const ItemSchema = new mongoose.Schema(
|
const ItemSchema = new mongoose.Schema(
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ const LoginSchema = new mongoose.Schema(
|
|||||||
required: true,
|
required: true,
|
||||||
trim: true,
|
trim: true,
|
||||||
},
|
},
|
||||||
|
associatedEmail: {
|
||||||
|
type: String,
|
||||||
|
trim: true,
|
||||||
|
},
|
||||||
secret: {
|
secret: {
|
||||||
type: String,
|
type: String,
|
||||||
trim: true,
|
trim: true,
|
||||||
@@ -66,6 +70,10 @@ const UserSchema = new mongoose.Schema(
|
|||||||
phone: [ PhoneSchema ],
|
phone: [ PhoneSchema ],
|
||||||
|
|
||||||
credentials: [ LoginSchema ],
|
credentials: [ LoginSchema ],
|
||||||
|
tokenCheckBit: {
|
||||||
|
type: String,
|
||||||
|
trim: true,
|
||||||
|
},
|
||||||
|
|
||||||
organizationIdentifier: {
|
organizationIdentifier: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -88,6 +96,11 @@ const UserSchema = new mongoose.Schema(
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
resetCheckBit: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{ minimize: false },
|
{ minimize: false },
|
||||||
@@ -114,6 +127,10 @@ UserSchema.methods.authenticate = function (username, password) {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
UserSchema.methods.isNomAvailable = function (nom) {
|
||||||
|
return !!!this.model('User').findOne({ nomDeBid });
|
||||||
|
};
|
||||||
|
|
||||||
UserSchema.methods.generateJWT = function (props = {}) {
|
UserSchema.methods.generateJWT = function (props = {}) {
|
||||||
const { exp, iss } = props;
|
const { exp, iss } = props;
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
@@ -143,6 +160,23 @@ UserSchema.methods.getNomDeBid = function () {
|
|||||||
return this.nomDeBid || `${this.firstName} ${this.lastName.charAt(0)}`;
|
return this.nomDeBid || `${this.firstName} ${this.lastName.charAt(0)}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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.isEventManager = function () {
|
UserSchema.methods.isEventManager = function () {
|
||||||
return this.isOrganizationEmployee || false;
|
return this.isOrganizationEmployee || false;
|
||||||
};
|
};
|
||||||
@@ -151,6 +185,28 @@ UserSchema.methods.isRegistrationVerified = function () {
|
|||||||
return this.isVerified || false;
|
return this.isVerified || false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
UserSchema.methods.sendPasswordReset = function () {
|
||||||
|
const resetToken = this.generateResetToken();
|
||||||
|
|
||||||
|
let resetRoute = config.security.resetRoute;
|
||||||
|
resetRoute = resetRoute.replace(':user_id', this.id);
|
||||||
|
resetRoute = resetRoute.replace(':reset_token?', resetToken);
|
||||||
|
|
||||||
|
const resetUrl = `${config.api.url}${resetRoute}`;
|
||||||
|
console.log('[sendPasswordReset] resetUrl:', resetUrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
UserSchema.methods.setNomDeBid = function (nomDeBid, callback = () => {}) {
|
||||||
|
const alreadyExists = this.isNomAvailable(nomDeBid);
|
||||||
|
|
||||||
|
if (this.isNomAvailable(nomDeBid)) {
|
||||||
|
this.nomDeBid = nomDeBid;
|
||||||
|
return this.save(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
callback({ success: false, info: 'Nom de Bid already exists!' }, false);
|
||||||
|
};
|
||||||
|
|
||||||
UserSchema.methods.setPassword = function (password, callback = () => {}) {
|
UserSchema.methods.setPassword = function (password, callback = () => {}) {
|
||||||
const hasLocalStrategy = !!this.credentials.length &&
|
const hasLocalStrategy = !!this.credentials.length &&
|
||||||
!!this.credentials.filter(strategy => strategy.method === 'local').length;
|
!!this.credentials.filter(strategy => strategy.method === 'local').length;
|
||||||
@@ -167,7 +223,7 @@ UserSchema.methods.setPassword = function (password, callback = () => {}) {
|
|||||||
if (hasLocalStrategy) {
|
if (hasLocalStrategy) {
|
||||||
this.model('User').findOneAndUpdate(
|
this.model('User').findOneAndUpdate(
|
||||||
{ _id: this._id, 'credentials.method': 'local' },
|
{ _id: this._id, 'credentials.method': 'local' },
|
||||||
{ $set: { 'credentials.$': strategy } },
|
{ $set: { 'credentials.$': strategy, resetCheckBit: null } },
|
||||||
{ upsert: true },
|
{ upsert: true },
|
||||||
callback,
|
callback,
|
||||||
);
|
);
|
||||||
@@ -175,6 +231,7 @@ UserSchema.methods.setPassword = function (password, callback = () => {}) {
|
|||||||
|
|
||||||
if (!hasLocalStrategy) {
|
if (!hasLocalStrategy) {
|
||||||
this.credentials.push(strategy);
|
this.credentials.push(strategy);
|
||||||
|
this.resetCheckBit = null;
|
||||||
this.save(callback);
|
this.save(callback);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -270,11 +327,46 @@ UserSchema.statics.findOneAndUpdateOrCreate = function (
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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, resetCheckBit: key }, (err, user) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return callback(err, false, 'The reset token was not valid.');
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(err, user);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
UserSchema.statics.verifyTokenAndResetPassword = function (token, password, callback) {
|
||||||
|
this.verifyResetToken(token, (err, user, info) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return callback(err, false, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
user.setPassword(password, callback);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PATH OPERATIONS
|
* PATH OPERATIONS
|
||||||
*/
|
*/
|
||||||
UserSchema.path('avatar').get(v => `${config.assetStoreUrl}${v}`);
|
UserSchema.path('avatar').get(v => (v ? `${config.assetStoreUrl}${v}` : null));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export
|
* Export
|
||||||
|
|||||||
@@ -2,17 +2,17 @@ const errors = require('restify-errors');
|
|||||||
|
|
||||||
const config = require('../config');
|
const config = require('../config');
|
||||||
|
|
||||||
const handlePassportResponse = (req, res, next) => (err, passportUser, info) => {
|
const handlePassportResponse = (req, res, next) => (err, user, info) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isVerifiedUser = passportUser.isRegistrationVerified();
|
const isVerifiedUser = user &&
|
||||||
if (passportUser && isVerifiedUser) {
|
user.isRegistrationVerified();
|
||||||
const user = passportUser;
|
|
||||||
user.token = passportUser.generateJWT();
|
if (user && isVerifiedUser) {
|
||||||
return res.send({ ...user.toAuthJSON() });
|
return res.send({ ...user.toAuthJSON() });
|
||||||
} else if (passportUser && !isVerifiedUser){
|
} else if (user && !isVerifiedUser){
|
||||||
return res.send({
|
return res.send({
|
||||||
registrationSuccess: true,
|
registrationSuccess: true,
|
||||||
nextSteps: 'Check your email for our confirmation email, you will not be able to login without confirming.'
|
nextSteps: 'Check your email for our confirmation email, you will not be able to login without confirming.'
|
||||||
@@ -71,7 +71,7 @@ module.exports = function (server, auth) {
|
|||||||
|
|
||||||
/* Facebook */
|
/* Facebook */
|
||||||
server.get(
|
server.get(
|
||||||
'/auth/facebook',
|
'/auth/facebook/login',
|
||||||
passport.authenticate('facebook', {
|
passport.authenticate('facebook', {
|
||||||
scope: ['email', 'public_profile'],
|
scope: ['email', 'public_profile'],
|
||||||
session: false,
|
session: false,
|
||||||
@@ -79,7 +79,7 @@ module.exports = function (server, auth) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
server.get(
|
server.get(
|
||||||
'/auth/facebook/callback',
|
'/auth/facebook/loggedin',
|
||||||
(req, res, next) => {
|
(req, res, next) => {
|
||||||
const callback = handlePassportResponse(req, res, next);
|
const callback = handlePassportResponse(req, res, next);
|
||||||
return passport.authenticate(
|
return passport.authenticate(
|
||||||
@@ -89,4 +89,50 @@ module.exports = function (server, auth) {
|
|||||||
)(req, res, next);
|
)(req, res, next);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
server.get(
|
||||||
|
'/auth/facebook/link',
|
||||||
|
auth.secure,
|
||||||
|
(req, res, next) => {
|
||||||
|
req.user.record.setLinkCheckBit((err, linkCheckBit) => {
|
||||||
|
passport.authenticate('facebookLink', {
|
||||||
|
scope: ['email', 'public_profile'],
|
||||||
|
session: false,
|
||||||
|
state: linkCheckbit,
|
||||||
|
})(req, res, next),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
server.get(
|
||||||
|
'/auth/facebook/linked',
|
||||||
|
(req, res, next) => {
|
||||||
|
const linkCheckBit = req.query.state;
|
||||||
|
|
||||||
|
return passport.authenticate(
|
||||||
|
'facebook',
|
||||||
|
{ failureRedirect: '/profile' },
|
||||||
|
(err, profile) => {
|
||||||
|
if (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
User.linkFacebookProfile(linkCheckBit, profile, (err, user) => {
|
||||||
|
if (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return next(err, false, 'Linking the account to Facebook was unsuccessful, please try again.');
|
||||||
|
}
|
||||||
|
|
||||||
|
res.send({
|
||||||
|
success: true,
|
||||||
|
info: 'Facerbook account successfully linked',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
)(req, res, next);
|
||||||
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ const Event = require('../models/event');
|
|||||||
|
|
||||||
module.exports = function (server, auth) {
|
module.exports = function (server, auth) {
|
||||||
server.post('/events', auth.manager, (req, res, next) => {
|
server.post('/events', auth.manager, (req, res, next) => {
|
||||||
|
|
||||||
let data = req.body || {};
|
let data = req.body || {};
|
||||||
|
|
||||||
let event = new Event(data);
|
let event = new Event(data);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ module.exports = function(server, auth) {
|
|||||||
require('./events.js')(server, auth);
|
require('./events.js')(server, auth);
|
||||||
require('./installs.js')(server, auth);
|
require('./installs.js')(server, auth);
|
||||||
require('./items.js')(server, auth);
|
require('./items.js')(server, auth);
|
||||||
|
require('./reset.js')(server, auth);
|
||||||
require('./sales.js')(server, auth);
|
require('./sales.js')(server, auth);
|
||||||
require('./users.js')(server, auth);
|
require('./users.js')(server, auth);
|
||||||
};
|
};
|
||||||
|
|||||||
68
routes/reset.js
Normal file
68
routes/reset.js
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
const errors = require('restify-errors');
|
||||||
|
const jwt = require('jsonwebtoken');
|
||||||
|
|
||||||
|
const config = require('../config');
|
||||||
|
const User = require('../models/user');
|
||||||
|
|
||||||
|
const {
|
||||||
|
api: { url },
|
||||||
|
security: { reset: { route, tokenPlaceholder } },
|
||||||
|
} = config;
|
||||||
|
|
||||||
|
const routes = {
|
||||||
|
resetWithToken: `${route}/${tokenPlaceholder}([A-Za-z0-9_]+\.{3})`,
|
||||||
|
getTestToken: `${route}/generate`,
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = function (server, auth) {
|
||||||
|
server.get(routes.getTestToken, auth.secure, function (req, res, next) {
|
||||||
|
const { record: user } = req.user;
|
||||||
|
const resetToken = user.generateResetToken();
|
||||||
|
const resetUrl = `${url}${route}/${resetToken}`;
|
||||||
|
|
||||||
|
res.send({ resetToken, resetUrl });
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
server.post(routes.resetWithToken, auth.bypass, function (req, res, next) {
|
||||||
|
const { reset_token } = req.params;
|
||||||
|
const { password } = req.body;
|
||||||
|
|
||||||
|
if (!reset_token) {
|
||||||
|
return next(
|
||||||
|
new errors.InvalidContentError('A reset token was not provided.'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!password) {
|
||||||
|
return next(
|
||||||
|
new errors.InvalidContentError('Password cannot be empty.'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
User.verifyTokenAndResetPassword(reset_token, password, (err, user, info) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
return next(
|
||||||
|
new errors.InvalidContentError(err),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
console.error(err);
|
||||||
|
res.send({
|
||||||
|
success: false,
|
||||||
|
info: 'Password reset failed. ' + info,
|
||||||
|
});
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
res.send({
|
||||||
|
success: true,
|
||||||
|
info: 'Password reset successful.',
|
||||||
|
...user.toAuthJSON()
|
||||||
|
});
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -26,17 +26,55 @@ module.exports = function (server, auth) {
|
|||||||
|
|
||||||
if (info) {
|
if (info) {
|
||||||
res.send(200, {
|
res.send(200, {
|
||||||
registrationSuccess: false,
|
success: false,
|
||||||
nextSteps: 'Please fix the problems indicated and try again.'
|
nextSteps: 'Please fix the problems indicated and try again.'
|
||||||
...info
|
...info
|
||||||
});
|
});
|
||||||
|
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
res.send(200, {
|
res.send(200, {
|
||||||
registrationSuccess: true,
|
success: true,
|
||||||
nextSteps: 'Check your email for our confirmation email, you will not be able to login without confirming.'
|
nextSteps: 'Check your email for our confirmation email, you will not be able to login without confirming.'
|
||||||
})
|
});
|
||||||
|
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
server.post('/signup/verify/resend', (req, res, next) => {
|
||||||
|
const { body: { email = null } = {} } = req;
|
||||||
|
|
||||||
|
User.resendVerificationEmail(email, (err, user, info) => {
|
||||||
|
if (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
res.send(200, {
|
||||||
|
success: false,
|
||||||
|
nextSteps: 'There was no user located with the email address provided. Please try again.',
|
||||||
|
});
|
||||||
|
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user && info.success) {
|
||||||
|
res.send(200, {
|
||||||
|
success: true,
|
||||||
|
nextSteps: 'Check your email for our confirmation email, you will not be able to login without confirming.',
|
||||||
|
});
|
||||||
|
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
res.send(200, {
|
||||||
|
success: false,
|
||||||
|
nextSteps: 'There was a problem resending the verification email. Please try again later.',
|
||||||
|
});
|
||||||
|
|
||||||
|
next();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const aqp = require('api-query-params');
|
const aqp = require('api-query-params');
|
||||||
const errors = require('restify-errors');
|
const errors = require('restify-errors');
|
||||||
|
|
||||||
|
const config = require('../config');
|
||||||
const User = require('../models/user');
|
const User = require('../models/user');
|
||||||
const { PUBLIC, STAFF } = require('../strategies/selects/user');
|
const { PUBLIC, STAFF } = require('../strategies/selects/user');
|
||||||
|
|
||||||
@@ -93,66 +94,6 @@ module.exports = function (server, auth) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
server.put('/users/password/:user_id/:reset_token?', function (req, res, next) {
|
|
||||||
let {
|
|
||||||
currentPassword = null,
|
|
||||||
newPassword = null,
|
|
||||||
...data
|
|
||||||
} = req.body || {};
|
|
||||||
|
|
||||||
if (!newPassword) {
|
|
||||||
return next(
|
|
||||||
new errors.InvalidContentError('Password cannot be empty.'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let filter = { _id: req.params.user_id };
|
|
||||||
let resetToken = req.params.reset_token || null;
|
|
||||||
if (resetToken) {
|
|
||||||
fiter.resetToken = resetToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
User.findOne(filter, function (err, user) {
|
|
||||||
if (err) {
|
|
||||||
console.error(err);
|
|
||||||
return next(
|
|
||||||
new errors.InvalidContentError(err),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
return next(
|
|
||||||
new errors.ResourceNotFoundError(
|
|
||||||
'The user you requested could not be found.',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!resetToken &&
|
|
||||||
!!user.getAuthStrategy('local') &&
|
|
||||||
!user.validatePassword(currentPassword)
|
|
||||||
) {
|
|
||||||
return next(
|
|
||||||
new errors.InvalidContentError(
|
|
||||||
'The current password was incorrect.',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
user.setPassword(newPassword, function (err) {
|
|
||||||
if (err) {
|
|
||||||
console.error(err);
|
|
||||||
return next(
|
|
||||||
new errors.InvalidContentError(err),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
res.send(200, data);
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
server.del('/users/:user_id', auth.manager, (req, res, next) => {
|
server.del('/users/:user_id', auth.manager, (req, res, next) => {
|
||||||
User.deleteOne({ _id: req.params.user_id }, function (err) {
|
User.deleteOne({ _id: req.params.user_id }, function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ const config = require('../../config');
|
|||||||
const User = require('../../models/user');
|
const User = require('../../models/user');
|
||||||
|
|
||||||
module.exports = function(passport) {
|
module.exports = function(passport) {
|
||||||
passport.use(new FacebookStrategy(
|
|
||||||
|
passport.use('facebook', new FacebookStrategy(
|
||||||
{
|
{
|
||||||
clientID: config.services.facebook.appId,
|
clientID: config.services.facebook.appId,
|
||||||
clientSecret: config.services.facebook.appSecret,
|
clientSecret: config.services.facebook.appSecret,
|
||||||
callbackURL: 'http://localhost:3001/auth/facebook/callback',
|
callbackURL: 'http://localhost:3001/auth/facebook/loggedin',
|
||||||
profileFields: ['id', 'email', 'first_name', 'last_name', 'picture'],
|
profileFields: ['id', 'email', 'first_name', 'last_name', 'picture'],
|
||||||
},
|
},
|
||||||
(accessToken, refreshToken, profile, done) => {
|
(accessToken, refreshToken, profile, done) => {
|
||||||
@@ -28,6 +29,7 @@ module.exports = function(passport) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessToken,
|
accessToken,
|
||||||
|
associatedEmail: email,
|
||||||
method: profile.provider,
|
method: profile.provider,
|
||||||
userId,
|
userId,
|
||||||
},
|
},
|
||||||
@@ -43,4 +45,32 @@ module.exports = function(passport) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
|
passport.use('facebookLink', new FacebookStrategy(
|
||||||
|
{
|
||||||
|
clientID: config.services.facebook.appId,
|
||||||
|
clientSecret: config.services.facebook.appSecret,
|
||||||
|
callbackURL: 'http://localhost:3001/auth/facebook/linked',
|
||||||
|
profileFields: ['id', 'email', 'first_name', 'last_name', 'picture'],
|
||||||
|
},
|
||||||
|
(accessToken, refreshToken, profile, done) => {
|
||||||
|
const {
|
||||||
|
email,
|
||||||
|
first_name: firstName,
|
||||||
|
id: userId,
|
||||||
|
last_name: lastName,
|
||||||
|
picture: { data: { url = null } = {} } = {},
|
||||||
|
} = profile._json;
|
||||||
|
const avatar = url;
|
||||||
|
|
||||||
|
const strategy = {
|
||||||
|
accessToken,
|
||||||
|
associatedEmail: email,
|
||||||
|
method: profile.provider,
|
||||||
|
userId,
|
||||||
|
};
|
||||||
|
|
||||||
|
return done(null, { avatar, strategy });
|
||||||
|
}
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ module.exports = function (passport) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
basic: authenticateBasic(passport),
|
basic: authenticateBasic(passport),
|
||||||
|
bypass: (req, res, next) => next(),
|
||||||
manager: authenticateEventManager(passport),
|
manager: authenticateEventManager(passport),
|
||||||
managerOrSelf: authenticateEventManagerOrSelf(passport),
|
managerOrSelf: authenticateEventManagerOrSelf(passport),
|
||||||
passport,
|
passport,
|
||||||
|
|||||||
Reference in New Issue
Block a user