Skip to content
This repository has been archived by the owner on Aug 30, 2021. It is now read-only.

Commit

Permalink
Merge branch '0.2.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
amoshaviv committed Apr 15, 2014
2 parents f150407 + ac3ffca commit c6a8a9b
Show file tree
Hide file tree
Showing 16 changed files with 323 additions and 131 deletions.
21 changes: 21 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
## License
(The MIT License)

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,28 @@ $ npm install -g bower
$ sudo npm install -g grunt-cli
```

## Downloading MEAN.JS
There are several ways you can get the MEAN.JS boilerplate:

### Yo Generator
The recommended way would be to use the [Official Yo Generator](http://meanjs.org/generator.html) which will generate the latest stable copy of the MEAN.JS boilerplate and supplies multiple sub-generators to ease your daily development cycles.

### Cloning The GitHub Repository
You can also use Git to directly clone the MEAN.JS repository:
```
$ git clone https://github.com/meanjs/mean.git meanjs
```
This will clone the latest version of the MEAN.JS repository to a **meanjs** folder.

### Downloading The Repository Zip File
Another way to use the MEAN.JS boilerplate is to download a zip copy from the [master branch on github](https://github.com/meanjs/mean/archive/master.zip). You can also do this using `wget` command:
```
$ wget https://github.com/meanjs/mean/archive/master.zip -O meanjs.zip; unzip meanjs.zip; rm meanjs.zip
```
Don't forget to rename **mean-master** after your project name.

## Quick Install
Once you've installed all the prerequisites, you're just a few steps away from starting to develop you MEAN application.
Once you've downloaded the boilerplate and installed all the prerequisites, you're just a few steps away from starting to develop you MEAN application.

The first thing you should do is install the Node.js dependencies. The boilerplate comes pre-bundled with a package.json file that contains the list of modules you need to start your application, to learn more about the modules installed visit the NPM & Package.json section.

Expand Down
121 changes: 117 additions & 4 deletions app/controllers/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ var mongoose = require('mongoose'),
User = mongoose.model('User'),
_ = require('lodash');

/**
* Get the error message from error object
*/
var getErrorMessage = function(err) {
var message = '';

Expand Down Expand Up @@ -153,7 +156,6 @@ exports.changePassword = function(req, res, next) {
});
}
});

} else {
res.send(400, {
message: 'Passwords do not match'
Expand Down Expand Up @@ -197,17 +199,16 @@ exports.me = function(req, res) {
*/
exports.oauthCallback = function(strategy) {
return function(req, res, next) {
passport.authenticate(strategy, function(err, user, email) {
passport.authenticate(strategy, function(err, user, redirectURL) {
if (err || !user) {
console.log(err);
return res.redirect('/#!/signin');
}
req.login(user, function(err) {
if (err) {
return res.redirect('/#!/signin');
}

return res.redirect('/');
return res.redirect(redirectURL || '/');
});
})(req, res, next);
};
Expand Down Expand Up @@ -247,4 +248,116 @@ exports.hasAuthorization = function(req, res, next) {
}

next();
};

/**
* Helper function to save or update a OAuth user profile
*/
exports.saveOAuthUserProfile = function(req, providerUserProfile, done) {
if (!req.user) {
// Define a search query fields
var searchMainProviderIdentifierField = 'providerData.' + providerUserProfile.providerIdentifierField;
var searchAdditionalProviderIdentifierField = 'additionalProvidersData.' + providerUserProfile.provider + '.' + providerUserProfile.providerIdentifierField;

// Define main provider search query
var mainProviderSearchQuery = {};
mainProviderSearchQuery.provider = providerUserProfile.provider;
mainProviderSearchQuery[searchMainProviderIdentifierField] = providerUserProfile.providerData[providerUserProfile.providerIdentifierField];

// Define additional provider search query
var additionalProviderSearchQuery = {};
additionalProviderSearchQuery[searchAdditionalProviderIdentifierField] = providerUserProfile.providerData[providerUserProfile.providerIdentifierField];

// Define a search query to find existing user with current provider profile
var searchQuery = {
$or: [mainProviderSearchQuery, additionalProviderSearchQuery]
};

User.findOne(searchQuery, function(err, user) {
if (err) {
return done(err);
} else {
if (!user) {
var possibleUsername = providerUserProfile.username || ((providerUserProfile.email) ? providerUserProfile.email.split('@')[0] : '');

User.findUniqueUsername(possibleUsername, null, function(availableUsername) {
user = new User({
firstName: providerUserProfile.firstName,
lastName: providerUserProfile.lastName,
username: availableUsername,
displayName: providerUserProfile.displayName,
email: providerUserProfile.email,
provider: providerUserProfile.provider,
providerData: providerUserProfile.providerData
});

// And save the user
user.save(function(err) {
return done(err, user);
});
});
} else {
return done(err, user);
}
}
});
} else {
// User is already logged in, join the provider data to the existing user
User.findById(req.user.id, function(err, user) {
if (err) {
return done(err);
} else {
// Check if user exists, is not signed in using this provider, and doesn't have that provider data already configured
if (user && user.provider !== providerUserProfile.provider && (!user.additionalProvidersData || !user.additionalProvidersData[providerUserProfile.provider])) {
// Add the provider data to the additional provider data field
if (!user.additionalProvidersData) user.additionalProvidersData = {};
user.additionalProvidersData[providerUserProfile.provider] = providerUserProfile.providerData;

// Then tell mongoose that we've updated the additionalProvidersData field
user.markModified('additionalProvidersData');

// And save the user
user.save(function(err) {
return done(err, user, '/#!/settings/accounts');
});
} else {
return done(err, user);
}
}
});
}
};

/**
* Remove OAuth provider
*/
exports.removeOAuthProvider = function(req, res, next) {
var user = req.user;
var provider = req.param('provider');

if (user && provider) {
// Delete the additional provider
if (user.additionalProvidersData[provider]) {
delete user.additionalProvidersData[provider];

// Then tell mongoose that we've updated the additionalProvidersData field
user.markModified('additionalProvidersData');
}

user.save(function(err) {
if (err) {
return res.send(400, {
message: getErrorMessage(err)
});
} else {
req.login(user, function(err) {
if (err) {
res.send(400, err);
} else {
res.jsonp(user);
}
});
}
});
}
};
1 change: 1 addition & 0 deletions app/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ var UserSchema = new Schema({
required: 'Provider is required'
},
providerData: {},
additionalProvidersData: {},
updated: {
type: Date
},
Expand Down
1 change: 1 addition & 0 deletions app/routes/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = function(app) {
app.get('/users/me', users.me);
app.put('/users', users.update);
app.post('/users/password', users.changePassword);
app.del('/users/accounts', users.removeOAuthProvider);

// Setting up the users api
app.post('/auth/signup', users.signup);
Expand Down
3 changes: 2 additions & 1 deletion config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
var _ = require('lodash'),
utilities = require('./utilities');

// Look for a valid NODE_ENV variable and if one cannot be found load the development NODE_ENV
process.env.NODE_ENV = ~utilities.walk('./config/env', /(.*)\.js$/).map(function(file) {
return file.split('/').pop().slice(0, -3);
}).indexOf(process.env.NODE_ENV) ? process.env.NODE_ENV : 'development';
Expand All @@ -11,4 +12,4 @@ process.env.NODE_ENV = ~utilities.walk('./config/env', /(.*)\.js$/).map(function
module.exports = _.extend(
require('./env/all'),
require('./env/' + process.env.NODE_ENV) || {}
);
);
53 changes: 21 additions & 32 deletions config/strategies/facebook.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

var passport = require('passport'),
FacebookStrategy = require('passport-facebook').Strategy,
User = require('mongoose').model('User'),
config = require('../config');
config = require('../config'),
users = require('../../app/controllers/users');

module.exports = function() {
// Use facebook strategy
Expand All @@ -14,36 +14,25 @@ module.exports = function() {
passReqToCallback: true
},
function(req, accessToken, refreshToken, profile, done) {
if (req.user) {
return done(new Error('User is already signed in'), req.user);
} else {
User.findOne({
'provider': 'facebook',
'providerData.id': profile.id
}, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
User.findUniqueUsername(profile.username, null, function(availableUsername) {
user = new User({
firstName: profile.name.givenName,
lastName: profile.name.familyName,
displayName: profile.displayName,
email: profile.emails[0].value,
username: availableUsername,
provider: 'facebook',
providerData: profile._json
});
user.save(function(err) {
return done(err, user);
});
});
} else {
return done(err, user);
}
});
}
// Set the provider data and include tokens
var providerData = profile._json;
providerData.accessToken = accessToken;
providerData.refreshToken = refreshToken;

// Create the user OAuth profile
var providerUserProfile = {
firstName: profile.name.givenName,
lastName: profile.name.familyName,
displayName: profile.displayName,
email: profile.emails[0].value,
username: profile.username,
provider: 'facebook',
providerIdentifierField: 'id',
providerData: providerData
};

// Save the user OAuth profile
users.saveOAuthUserProfile(req, providerUserProfile, done);
}
));
};
50 changes: 20 additions & 30 deletions config/strategies/google.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

var passport = require('passport'),
GoogleStrategy = require('passport-google-oauth').OAuth2Strategy,
User = require('mongoose').model('User'),
config = require('../config');
config = require('../config'),
users = require('../../app/controllers/users');

module.exports = function() {
// Use google strategy
Expand All @@ -14,35 +14,25 @@ module.exports = function() {
passReqToCallback: true
},
function(req, accessToken, refreshToken, profile, done) {
if (req.user) {
return done(new Error('User is already signed in'), req.user);
} else {
User.findOne({
'provider': 'google',
'providerData.id': profile.id
}, function(err, user) {
if (!user) {
var possibleUsername = profile.emails[0].value.split('@')[0];
// Set the provider data and include tokens
var providerData = profile._json;
providerData.accessToken = accessToken;
providerData.refreshToken = refreshToken;

// Create the user OAuth profile
var providerUserProfile = {
firstName: profile.name.givenName,
lastName: profile.name.familyName,
displayName: profile.displayName,
email: profile.emails[0].value,
username: profile.username,
provider: 'google',
providerIdentifierField: 'id',
providerData: providerData
};

User.findUniqueUsername(possibleUsername, null, function(availableUsername) {
user = new User({
firstName: profile.name.givenName,
lastName: profile.name.familyName,
displayName: profile.displayName,
email: profile.emails[0].value,
username: availableUsername,
provider: 'google',
providerData: profile._json
});
user.save(function(err) {
return done(err, user);
});
});
} else {
return done(err, user);
}
});
}
// Save the user OAuth profile
users.saveOAuthUserProfile(req, providerUserProfile, done);
}
));
};
Loading

0 comments on commit c6a8a9b

Please sign in to comment.