Skip to content

Commit

Permalink
Merge branch 'staging' of github.com:FreeCodeCamp/freecodecamp into s…
Browse files Browse the repository at this point in the history
…taging

Conflicts:
	seed/field-guides.json
  • Loading branch information
Quincy Larson committed Jun 12, 2015
2 parents b3fb1d4 + 0f5f92b commit 173d46a
Show file tree
Hide file tree
Showing 59 changed files with 17,541 additions and 304 deletions.
44 changes: 29 additions & 15 deletions common/models/User-Identity.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,46 @@ var debug = require('debug')('freecc:models:userIdent');
var defaultProfileImage =
require('../utils/constantStrings.json').defaultProfileImage;

function getFirstImageFromProfile(profile) {
return profile && profile.photos && profile.photos[0] ?
profile.photos[0].value :
null;
}
module.exports = function(UserIdent) {

UserIdent.observe('before save', function(ctx, next) {
var userIdent = ctx.currentInstance;
// treat userIdent as immutable
var userIdent = ctx.currentInstance || ctx.instance;
if (!userIdent) {
debug('no user identity instance found');
return next();
}
userIdent.user(function(err, user) {
if (err) { return next(err); }
debug('got user', user.username);
if (!user) {
debug('no user attached to identity!');
return next();
}

var picture = userIdent.profile && userIdent.profile[0] ?
userIdent.profile[0].value :
null;
var picture = getFirstImageFromProfile(userIdent.profile);

// check if user has picture
// set user.picture from twitter
if (picture && !user.picture || user.picture === defaultProfileImage) {
debug('use has no pic');
debug('picture', picture, user.picture);
// check if picture was found
// check if user has no picture
// check if user has default picture
// set user.picture from oauth provider
if (
picture &&
(!user.picture || user.picture === defaultProfileImage)
) {
debug('setting user picture');
user.picture = userIdent.profile.photos[0].value;
user.save(function(err) {
return user.save(function(err) {
if (err) { return next(err); }
next();
});
} else {
debug('exiting after user ident');
next();
}

debug('exiting after user ident');
next();
});
});
};
171 changes: 171 additions & 0 deletions common/models/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
var debug = require('debug')('freecc:user:remote');
var blacklistedUsernames =
require('../../server/utils/constants').blacklistedUsernames;

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;
// set salt factor for passwords
User.settings.saltWorkFactor = 5;
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: '[email protected]',
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.afterRemote('confirm', function(ctx) {
ctx.req.flash('success', {
msg: [
'You\'re email has been confirmed!'
]
});
ctx.res.redirect('/email-signin');
});

User.afterRemote('login', function(ctx, instance, next) {
var res = ctx.res;
var req = ctx.req;

User.findOne({where: {email: ctx.args.credentials.email}},
function(err, response) {
if (err) {
return next(err);
}
if (response.emailVerified !== true) {
return res.redirect('/');
}
User.login({
email: ctx.args.credentials.email,
password: ctx.args.credentials.password,
ttl: Infinity
}, function(err, accessToken) {
if (err) {
req.flash('errors', {
msg: [
'Invalid username or password.'
]
});
return res.redirect('/');
}
var config = {
signed: !!req.signedCookies,
maxAge: accessToken.ttl
};
if (accessToken && accessToken.id) {
res.cookie('access_token', accessToken.id, config);
res.cookie('userId', accessToken.userId, config);
}
req.logIn(response, function(err) {
if (err) {
return next(err);
}
req.flash('success', { msg: 'Success! You are logged in.' });
return res.redirect('/');
});
});
});
return 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');

// check to see if username is on blacklist
if (username && blacklistedUsernames.indexOf(username) !== -1) {
return cb(null, true);
}

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'
}
}
);
};
23 changes: 14 additions & 9 deletions common/models/user.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,8 @@
"type": "string"
},
"sentSlackInvite": {
"type": {
"type": false
}
"type": "boolean",
"default": false
},
"resetPasswordExpires": {
"type": "string"
Expand All @@ -145,10 +144,12 @@
"completedDate": "string",
"solution": "string"
}
]
],
"default": []
},
"uncompletedCoursewares": {
"type": "array"
"type": "array",
"default": []
},
"completedCoursewares": {
"type": [
Expand All @@ -164,13 +165,16 @@
"githubLink": "string",
"verified": "boolean"
}
]
],
"default": []
},
"completedFieldGuides": {
"type": []
"type": "array",
"default": []
},
"uncompletedFieldGuides": {
"type": []
"type": "array",
"default": []
},
"currentStreak": {
"type": "number",
Expand Down Expand Up @@ -217,7 +221,8 @@
"default": []
},
"uncompletedChallenges": {
"type": "array"
"type": "array",
"default": []
}
},
"validations": [],
Expand Down
1 change: 1 addition & 0 deletions coverage/coverage.json

Large diffs are not rendered by default.

Loading

0 comments on commit 173d46a

Please sign in to comment.