Move api hooks to user.js

This commit is contained in:
terakilobyte
2015-06-11 19:11:07 -04:00
parent f7bb14803e
commit 34c3fef7d4
6 changed files with 286 additions and 126 deletions

140
common/models/user.js Normal file
View File

@ -0,0 +1,140 @@
var debug = require('debug')('freecc:user:remote');
module.exports = function(User) {
// NOTE(berks): user email validation currently not needed but build in. This
// work around should let us sneak by
// see:
// https://github.com/strongloop/loopback/issues/1137#issuecomment-109200135
delete User.validations.email;
debug('setting up user hooks');
// send verification email to new camper
User.afterRemote('create', function(ctx, user, next) {
debug('user created, sending email');
if (!user.email) { return next(); }
var mailOptions = {
type: 'email',
to: user.email,
from: 'Team@freecodecamp.com',
subject: 'Welcome to Free Code Camp!',
redirect: '/',
text: [
'Greetings from San Francisco!\n\n',
'Thank you for joining our community.\n',
'Feel free to email us at this address if you have ',
'any questions about Free Code Camp.\n',
'And if you have a moment, check out our blog: ',
'blog.freecodecamp.com.\n',
'Good luck with the challenges!\n\n',
'- the Free Code Camp Volunteer Team'
].join('')
};
user.verify(mailOptions, function(err) {
if (err) { return next(err); }
debug('verification email sent');
ctx.req.flash('success', {
msg: [
'Please check your email and click on the verification link '
+ 'before logging in.'
]
});
ctx.res.redirect('/');
});
});
User.beforeRemote('login', function(ctx, instance, next) {
debug('before called');
debug(ctx, instance, next);
next();
});
User.afterRemote('login', function(ctx, instance, next) {
var res = ctx.res;
var req = ctx.req;
if (!instance || instance.emailVerified !== true) {
debug(instance);
req.flash('errors', {
msg: [
'Please verify your email address.'
]
});
return res.redirect('/');
}
var config = {
signed: !!req.signedCookies,
maxAge: 1000 * accessToken.ttl
};
if (accessToken && accessToken.id) {
res.cookie('access_token', accessToken.id, config);
res.cookie('userId', accessToken.userId, config);
}
res.redirect('/');
});
User.afterRemote('logout', function(ctx, result, next) {
var res = ctx.result;
res.clearCookie('access_token');
res.clearCookie('userId');
next();
});
User.doesExist = function doesExist(username, email, cb) {
if (!username && !email) {
return process.nextTick(function() {
cb(null, false);
});
}
debug('checking existence');
var where = {};
if (username) {
where.username = username.toLowerCase();
} else {
where.email = email ? email.toLowerCase() : email;
}
debug('where', where);
User.count(
where,
function (err, count) {
if (err) {
debug('err checking existance: ', err);
return cb(err);
}
if (count > 0) {
return cb(null, true);
}
return cb(null, false);
}
);
};
User.remoteMethod(
'doesExist',
{
description: 'checks whether a user exists using email or username',
accepts: [
{
arg: 'username',
type: 'string'
},
{
arg: 'email',
type: 'string'
}
],
returns: [
{
arg: 'exists',
type: 'boolean'
}
],
http: {
path: '/exists',
verb: 'get'
}
}
);
};

View File

@ -242,5 +242,5 @@
"property": "doesExist" "property": "doesExist"
} }
], ],
"methods": [] "methods": ["login"]
} }

View File

@ -1,121 +1,140 @@
var debug = require('debug')('freecc:extendUser'); //var debug = require('debug')('freecc:extendUser');
//
module.exports = function(app) { //module.exports = function(app) {
var User = app.models.User; // var User = app.models.User;
// NOTE(berks): user email validation currently not needed but build in. This // // NOTE(berks): user email validation currently not needed but build in. This
// work around should let us sneak by // // work around should let us sneak by
// see: // // see:
// https://github.com/strongloop/loopback/issues/1137#issuecomment-109200135 // // https://github.com/strongloop/loopback/issues/1137#issuecomment-109200135
delete User.validations.email; // delete User.validations.email;
debug('setting up user hooks'); // debug('setting up user hooks');
// send verification email to new camper // // send verification email to new camper
User.afterRemote('create', function(ctx, user, next) { // User.afterRemote('create', function(ctx, user, next) {
debug('user created, sending email'); // debug('user created, sending email');
if (!user.email) { return next(); } // if (!user.email) { return next(); }
//
var mailOptions = { // var mailOptions = {
type: 'email', // type: 'email',
to: user.email, // to: user.email,
from: 'Team@freecodecamp.com', // from: 'Team@freecodecamp.com',
subject: 'Welcome to Free Code Camp!', // subject: 'Welcome to Free Code Camp!',
redirect: '/', // redirect: '/',
text: [ // text: [
'Greetings from San Francisco!\n\n', // 'Greetings from San Francisco!\n\n',
'Thank you for joining our community.\n', // 'Thank you for joining our community.\n',
'Feel free to email us at this address if you have ', // 'Feel free to email us at this address if you have ',
'any questions about Free Code Camp.\n', // 'any questions about Free Code Camp.\n',
'And if you have a moment, check out our blog: ', // 'And if you have a moment, check out our blog: ',
'blog.freecodecamp.com.\n', // 'blog.freecodecamp.com.\n',
'Good luck with the challenges!\n\n', // 'Good luck with the challenges!\n\n',
'- the Free Code Camp Volunteer Team' // '- the Free Code Camp Volunteer Team'
].join('') // ].join('')
}; // };
user.verify(mailOptions, function(err) { // user.verify(mailOptions, function(err) {
if (err) { return next(err); } // if (err) { return next(err); }
debug('verification email sent'); // debug('verification email sent');
ctx.req.flash({ // ctx.req.flash('success', {
msg: 'Please check your email and click on the verification link ' // msg: [
+ 'before logging in.' // 'Please check your email and click on the verification link '
}); // + 'before logging in.'
ctx.res.redirect('/'); // ]
}); // });
}); // ctx.res.redirect('/');
// });
User.afterRemote('login', function(ctx, accessToken) { // });
var res = ctx.res; //
var req = ctx.req; // User.beforeRemote('login', function(ctx, results, next) {
// debug('before called');
var config = { // next();
signed: !!req.signedCookies, // });
maxAge: 1000 * accessToken.ttl //
}; // User.afterRemote('login', function(ctx, instance, next) {
if (accessToken && accessToken.id) { // debug('after called');
res.cookie('access_token', accessToken.id, config); // var res = ctx.res;
res.cookie('userId', accessToken.userId, config); // var req = ctx.req;
} //
res.redirect('/'); // if (!instance || !instance.emailVerified) {
}); // req.flash('errors', {
// msg: [
User.afterRemote('logout', function(ctx, result, next) { // 'Please verify your email address.'
var res = ctx.result; // ]
res.clearCookie('access_token'); // });
res.clearCookie('userId'); // return res.redirect('/');
next(); // }
}); //
// var config = {
User.doesExist = function doesExist(username, email, cb) { // signed: !!req.signedCookies,
if (!username && !email) { // maxAge: 1000 * accessToken.ttl
return process.nextTick(function() { // };
cb(null, false); // if (accessToken && accessToken.id) {
}); // res.cookie('access_token', accessToken.id, config);
} // res.cookie('userId', accessToken.userId, config);
debug('checking existence'); // }
var where = {}; // res.redirect('/');
if (username) { // });
where.username = username.toLowerCase(); //
} else { //
where.email = email ? email.toLowerCase() : email; //
} // User.afterRemote('logout', function(ctx, result, next) {
debug('where', where); // var res = ctx.result;
User.count( // res.clearCookie('access_token');
where, // res.clearCookie('userId');
function (err, count) { // next();
if (err) { // });
debug('err checking existance: ', err); //
return cb(err); // User.doesExist = function doesExist(username, email, cb) {
} // if (!username && !email) {
if (count > 0) { // return process.nextTick(function() {
return cb(null, true); // cb(null, false);
} // });
return cb(null, false); // }
} // debug('checking existence');
); // var where = {};
}; // if (username) {
// where.username = username.toLowerCase();
User.remoteMethod( // } else {
'doesExist', // where.email = email ? email.toLowerCase() : email;
{ // }
description: 'checks whether a user exists using email or username', // debug('where', where);
accepts: [ // User.count(
{ // where,
arg: 'username', // function (err, count) {
type: 'string' // if (err) {
}, // debug('err checking existance: ', err);
{ // return cb(err);
arg: 'email', // }
type: 'string' // if (count > 0) {
} // return cb(null, true);
], // }
returns: [ // return cb(null, false);
{ // }
arg: 'exists', // );
type: 'boolean' // };
} //
], // User.remoteMethod(
http: { // 'doesExist',
path: '/exists', // {
verb: 'get' // description: 'checks whether a user exists using email or username',
} // accepts: [
} // {
); // arg: 'username',
}; // type: 'string'
// },
// {
// arg: 'email',
// type: 'string'
// }
// ],
// returns: [
// {
// arg: 'exists',
// type: 'boolean'
// }
// ],
// http: {
// path: '/exists',
// verb: 'get'
// }
// }
// );
//};

View File

@ -654,7 +654,6 @@ module.exports = function(app) {
R.forEach(function (comment) { R.forEach(function (comment) {
comment.author.picture = picture; comment.author.picture = picture;
comment.author.username = username; comment.author.username = username;
comment.markModified('author');
tasks.push(function (cb) { tasks.push(function (cb) {
comment.save(cb); comment.save(cb);
}); });
@ -663,7 +662,6 @@ module.exports = function(app) {
R.forEach(function (story) { R.forEach(function (story) {
story.author.picture = picture; story.author.picture = picture;
story.author.username = username; story.author.username = username;
story.markModified('author');
tasks.push(function (cb) { tasks.push(function (cb) {
story.save(cb); story.save(cb);
}); });

View File

@ -61,7 +61,10 @@
}, },
"user": { "user": {
"dataSource": "db", "dataSource": "db",
"public": true "public": true,
"options": {
"emailVerificationRequired": true
}
}, },
"userCredential": { "userCredential": {
"dataSource": "db", "dataSource": "db",

View File

@ -2,7 +2,7 @@ extends ../layout
block content block content
.jumbotron.text-center(ng-controller="emailSignInController") .jumbotron.text-center(ng-controller="emailSignInController")
h2 Sign in with an email address here: h2 Sign in with an email address here:
form(method='POST', action='/auth/local') form(method='POST', action='/api/users/login')
input(type='hidden', name='_csrf', value=_csrf) input(type='hidden', name='_csrf', value=_csrf)
.col-sm-6.col-sm-offset-3 .col-sm-6.col-sm-offset-3
.form-group .form-group