add user signup through loopback
This commit is contained in:
@ -1,19 +0,0 @@
|
|||||||
var debug = require('debug')('freecc:models:user');
|
|
||||||
|
|
||||||
module.exports = function(User) {
|
|
||||||
debug('setting up user hooks');
|
|
||||||
/*
|
|
||||||
* NOTE(berks): not sure if this is still needed
|
|
||||||
User.observe('before save', function setUsername(ctx, next) {
|
|
||||||
// set username from twitter
|
|
||||||
if (ctx.instance.username && ctx.instance.username.match(/twitter/g)) {
|
|
||||||
ctx.instance.username =
|
|
||||||
ctx.instance.username.match(/twitter/g) ?
|
|
||||||
ctx.instance.username.split('.').pop().toLowerCase() :
|
|
||||||
ctx.instance.username;
|
|
||||||
debug('username set', ctx.instance.username);
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
};
|
|
@ -3,6 +3,7 @@
|
|||||||
"base": "User",
|
"base": "User",
|
||||||
"trackChanges": false,
|
"trackChanges": false,
|
||||||
"idInjection": true,
|
"idInjection": true,
|
||||||
|
"strict": true,
|
||||||
"properties": {
|
"properties": {
|
||||||
"email": {
|
"email": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -422,14 +422,18 @@ profileValidation.directive('uniqueUsername', ['$http', function($http) {
|
|||||||
link: function (scope, element, attrs, ngModel) {
|
link: function (scope, element, attrs, ngModel) {
|
||||||
element.bind("keyup", function (event) {
|
element.bind("keyup", function (event) {
|
||||||
ngModel.$setValidity('unique', true);
|
ngModel.$setValidity('unique', true);
|
||||||
if (element.val()) {
|
var username = element.val();
|
||||||
$http.get("/api/checkUniqueUsername/" + element.val()).success(function (data) {
|
if (username) {
|
||||||
if (element.val() === scope.storedUsername) {
|
var config = { params: { username: username } };
|
||||||
ngModel.$setValidity('unique', true);
|
$http
|
||||||
} else if (data) {
|
.get('/api/users/exists', config)
|
||||||
ngModel.$setValidity('unique', false);
|
.success(function (exists) {
|
||||||
}
|
if (username === scope.storedUsername) {
|
||||||
});
|
ngModel.$setValidity('unique', true);
|
||||||
|
} else if (exists) {
|
||||||
|
ngModel.$setValidity('unique', false);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -449,11 +453,13 @@ profileValidation.directive('existingUsername',
|
|||||||
element.removeClass('ng-dirty');
|
element.removeClass('ng-dirty');
|
||||||
ngModel.$setPristine();
|
ngModel.$setPristine();
|
||||||
}
|
}
|
||||||
if (element.val()) {
|
var username = element.val();
|
||||||
|
if (username) {
|
||||||
|
var config = { params: { username: username } };
|
||||||
$http
|
$http
|
||||||
.get('/api/checkExistingUsername/' + element.val())
|
.get('/api/users/exists', config)
|
||||||
.success(function (data) {
|
.success(function(exists) {
|
||||||
ngModel.$setValidity('exists', data);
|
ngModel.$setValidity('exists', exists);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -468,14 +474,18 @@ profileValidation.directive('uniqueEmail', ['$http', function($http) {
|
|||||||
link: function getUnique (scope, element, attrs, ngModel) {
|
link: function getUnique (scope, element, attrs, ngModel) {
|
||||||
element.bind("keyup", function (event) {
|
element.bind("keyup", function (event) {
|
||||||
ngModel.$setValidity('unique', true);
|
ngModel.$setValidity('unique', true);
|
||||||
|
var email = element.val();
|
||||||
if (element.val()) {
|
if (element.val()) {
|
||||||
$http.get("/api/checkUniqueEmail/" + encodeURIComponent(element.val())).success(function (data) {
|
var config = { params: { email: email } };
|
||||||
if (element.val() === scope.storedEmail) {
|
$http
|
||||||
ngModel.$setValidity('unique', true);
|
.get('/api/users/exists', config)
|
||||||
} else if (data) {
|
.success(function (exists) {
|
||||||
ngModel.$setValidity('unique', false);
|
if (email === scope.storedEmail) {
|
||||||
}
|
ngModel.$setValidity('unique', true);
|
||||||
});
|
} else if (exists) {
|
||||||
|
ngModel.$setValidity('unique', false);
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
84
server/boot/a-extendUser.js
Normal file
84
server/boot/a-extendUser.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
var debug = require('debug')('freecc:extendUser');
|
||||||
|
|
||||||
|
module.exports = function(app) {
|
||||||
|
var User = app.models.User;
|
||||||
|
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({
|
||||||
|
msg: 'Please check your email and click on the verification link '
|
||||||
|
+ 'before logging in.'
|
||||||
|
});
|
||||||
|
ctx.res.redirect('/');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
User.doesExist = function doesExist(username, email, cb) {
|
||||||
|
debug('checking existence');
|
||||||
|
var where = {};
|
||||||
|
if (username) {
|
||||||
|
where.username = username;
|
||||||
|
} else {
|
||||||
|
where.email = email;
|
||||||
|
}
|
||||||
|
User.count(
|
||||||
|
{ where: where },
|
||||||
|
function (err, count) {
|
||||||
|
if (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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
@ -35,12 +35,8 @@ module.exports = function(app) {
|
|||||||
router.post('/reset/:token', postReset);
|
router.post('/reset/:token', postReset);
|
||||||
router.get('/email-signup', getEmailSignup);
|
router.get('/email-signup', getEmailSignup);
|
||||||
router.get('/email-signin', getEmailSignin);
|
router.get('/email-signin', getEmailSignin);
|
||||||
router.post('/email-signup', postEmailSignup);
|
// router.post('/email-signup', postEmailSignup);
|
||||||
// router.post('/email-signin', postSignin);
|
|
||||||
router.get('/account/api', getAccountAngular);
|
router.get('/account/api', getAccountAngular);
|
||||||
router.get('/api/checkUniqueUsername/:username', checkUniqueUsername);
|
|
||||||
router.get('/api/checkExistingUsername/:username', checkExistingUsername);
|
|
||||||
router.get('/api/checkUniqueEmail/:email', checkUniqueEmail);
|
|
||||||
router.post('/account/profile', postUpdateProfile);
|
router.post('/account/profile', postUpdateProfile);
|
||||||
router.post('/account/password', postUpdatePassword);
|
router.post('/account/password', postUpdatePassword);
|
||||||
router.post('/account/delete', postDeleteAccount);
|
router.post('/account/delete', postDeleteAccount);
|
||||||
@ -65,49 +61,6 @@ module.exports = function(app) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* POST /signin
|
|
||||||
* Sign in using email and password.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO(berks): this should be done using loopback
|
|
||||||
function postSignin (req, res, next) {
|
|
||||||
req.assert('email', 'Email is not valid').isEmail();
|
|
||||||
req.assert('password', 'Password cannot be blank').notEmpty();
|
|
||||||
|
|
||||||
var errors = req.validationErrors();
|
|
||||||
|
|
||||||
if (errors) {
|
|
||||||
req.flash('errors', errors);
|
|
||||||
return res.redirect('/signin');
|
|
||||||
}
|
|
||||||
|
|
||||||
passport.authenticate('local', function(err, user, info) {
|
|
||||||
if (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
if (!user) {
|
|
||||||
req.flash('errors', { msg: info.message });
|
|
||||||
return res.redirect('/signin');
|
|
||||||
}
|
|
||||||
req.logIn(user, function(err) {
|
|
||||||
if (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
req.flash('success', { msg: 'Success! You are logged in.' });
|
|
||||||
if (/hotStories/.test(req.session.returnTo)) {
|
|
||||||
return res.redirect('../news');
|
|
||||||
}
|
|
||||||
if (/field-guide/.test(req.session.returnTo)) {
|
|
||||||
return res.redirect('../field-guide');
|
|
||||||
}
|
|
||||||
return res.redirect(req.session.returnTo || '/');
|
|
||||||
});
|
|
||||||
})(req, res, next);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /signout
|
* GET /signout
|
||||||
* Log out.
|
* Log out.
|
||||||
@ -146,107 +99,6 @@ module.exports = function(app) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* POST /email-signup
|
|
||||||
* Create a new local account.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function postEmailSignup (req, res, next) {
|
|
||||||
req.assert('email', 'valid email required').isEmail();
|
|
||||||
var errors = req.validationErrors();
|
|
||||||
|
|
||||||
if (errors) {
|
|
||||||
req.flash('errors', errors);
|
|
||||||
return res.redirect('/email-signup');
|
|
||||||
}
|
|
||||||
|
|
||||||
var possibleUserData = req.body;
|
|
||||||
|
|
||||||
if (possibleUserData.password.length < 8) {
|
|
||||||
req.flash('errors', {
|
|
||||||
msg: 'Your password is too short'
|
|
||||||
});
|
|
||||||
return res.redirect('email-signup');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (possibleUserData.username.length < 5 || possibleUserData.length > 20) {
|
|
||||||
req.flash('errors', {
|
|
||||||
msg: 'Your username must be between 5 and 20 characters'
|
|
||||||
});
|
|
||||||
return res.redirect('email-signup');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var user = new User({
|
|
||||||
email: req.body.email.trim(),
|
|
||||||
password: req.body.password,
|
|
||||||
profile: {
|
|
||||||
username: req.body.username.trim(),
|
|
||||||
picture:
|
|
||||||
'https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
User.findOne({ email: req.body.email }, function(err, existingEmail) {
|
|
||||||
if (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (existingEmail) {
|
|
||||||
req.flash('errors', {
|
|
||||||
msg: 'Account with that email address already exists.'
|
|
||||||
});
|
|
||||||
return res.redirect('/email-signup');
|
|
||||||
}
|
|
||||||
User.findOne(
|
|
||||||
{ 'profile.username': req.body.username },
|
|
||||||
function(err, existingUsername) {
|
|
||||||
if (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
if (existingUsername) {
|
|
||||||
req.flash('errors', {
|
|
||||||
msg: 'Account with that username already exists.'
|
|
||||||
});
|
|
||||||
return res.redirect('/email-signup');
|
|
||||||
}
|
|
||||||
|
|
||||||
user.save(function(err) {
|
|
||||||
if (err) { return next(err); }
|
|
||||||
req.logIn(user, function(err) {
|
|
||||||
if (err) { return next(err); }
|
|
||||||
res.redirect('/email-signup');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
var transporter = nodemailer.createTransport({
|
|
||||||
service: 'Mandrill',
|
|
||||||
auth: {
|
|
||||||
user: secrets.mandrill.user,
|
|
||||||
pass: secrets.mandrill.password
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var mailOptions = {
|
|
||||||
to: user.email,
|
|
||||||
from: 'Team@freecodecamp.com',
|
|
||||||
subject: 'Welcome to Free Code Camp!',
|
|
||||||
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('')
|
|
||||||
};
|
|
||||||
transporter.sendMail(mailOptions, function(err) {
|
|
||||||
if (err) { return err; }
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /account
|
* GET /account
|
||||||
* Profile page.
|
* Profile page.
|
||||||
@ -268,59 +120,6 @@ module.exports = function(app) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Unique username check API Call
|
|
||||||
*/
|
|
||||||
|
|
||||||
function checkUniqueUsername (req, res, next) {
|
|
||||||
User.count(
|
|
||||||
{ 'profile.username': req.params.username.toLowerCase() },
|
|
||||||
function (err, data) {
|
|
||||||
if (err) { return next(err); }
|
|
||||||
if (data === 1) {
|
|
||||||
return res.send(true);
|
|
||||||
} else {
|
|
||||||
return res.send(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Existing username check
|
|
||||||
*/
|
|
||||||
|
|
||||||
function checkExistingUsername (req, res, next) {
|
|
||||||
User.count(
|
|
||||||
{ 'profile.username': req.params.username.toLowerCase() },
|
|
||||||
function (err, data) {
|
|
||||||
if (err) { return next(err); }
|
|
||||||
if (data === 1) {
|
|
||||||
return res.send(true);
|
|
||||||
} else {
|
|
||||||
return res.send(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unique email check API Call
|
|
||||||
*/
|
|
||||||
|
|
||||||
function checkUniqueEmail (req, res, next) {
|
|
||||||
User.count(
|
|
||||||
{ email: decodeURIComponent(req.params.email).toLowerCase() },
|
|
||||||
function (err, data) {
|
|
||||||
if (err) { return next(err); }
|
|
||||||
if (data === 1) {
|
|
||||||
return res.send(true);
|
|
||||||
} else {
|
|
||||||
return res.send(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /campers/:username
|
* GET /campers/:username
|
||||||
|
@ -2,5 +2,8 @@
|
|||||||
"db": {
|
"db": {
|
||||||
"name": "db",
|
"name": "db",
|
||||||
"connector": "mongodb"
|
"connector": "mongodb"
|
||||||
|
},
|
||||||
|
"mail": {
|
||||||
|
"connector": "mail"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,19 @@
|
|||||||
|
var secrets = require('../config/secrets');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
db: {
|
db: {
|
||||||
connector: 'mongodb',
|
connector: 'mongodb',
|
||||||
url: process.env.MONGOHQ_URL
|
url: process.env.MONGOHQ_URL
|
||||||
|
},
|
||||||
|
mail: {
|
||||||
|
connector: 'mail',
|
||||||
|
transports: [{
|
||||||
|
type: 'smtp',
|
||||||
|
service: 'Mandrill',
|
||||||
|
auth: {
|
||||||
|
user: secrets.mandrill.user,
|
||||||
|
pass: secrets.mandrill.password
|
||||||
|
}
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"User": {
|
"User": {
|
||||||
"dataSource": "db"
|
"dataSource": "db",
|
||||||
|
"public": false
|
||||||
},
|
},
|
||||||
"AccessToken": {
|
"AccessToken": {
|
||||||
"dataSource": "db",
|
"dataSource": "db",
|
||||||
@ -26,6 +27,10 @@
|
|||||||
"dataSource": "db",
|
"dataSource": "db",
|
||||||
"public": false
|
"public": false
|
||||||
},
|
},
|
||||||
|
"Email": {
|
||||||
|
"dataSource": "mail",
|
||||||
|
"public": false
|
||||||
|
},
|
||||||
"bonfire": {
|
"bonfire": {
|
||||||
"dataSource": "db",
|
"dataSource": "db",
|
||||||
"public": true
|
"public": true
|
||||||
|
@ -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='/email-signin')
|
form(method='POST', action='/api/user/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
|
||||||
@ -24,4 +24,4 @@ block content
|
|||||||
br
|
br
|
||||||
br
|
br
|
||||||
br
|
br
|
||||||
br
|
br
|
||||||
|
@ -2,7 +2,7 @@ extends ../layout
|
|||||||
block content
|
block content
|
||||||
.jumbotron.text-center
|
.jumbotron.text-center
|
||||||
h2 Sign up with an email address here:
|
h2 Sign up with an email address here:
|
||||||
form.form-horizontal(method='POST', action='/email-signup', name="signupForm", novalidate="novalidate")
|
form.form-horizontal(method='POST', action='/api/users', name="signupForm", novalidate="novalidate")
|
||||||
input(type='hidden', name='_csrf', value=_csrf)
|
input(type='hidden', name='_csrf', value=_csrf)
|
||||||
.form-group
|
.form-group
|
||||||
.col-sm-6.col-sm-offset-3
|
.col-sm-6.col-sm-offset-3
|
||||||
|
Reference in New Issue
Block a user