mirror of
https://github.com/taobataoma/meanTorrent.git
synced 2026-07-15 12:22:21 +02:00
Finalizing the User Accounts Module
This commit is contained in:
@@ -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 = '';
|
||||
|
||||
@@ -153,7 +156,6 @@ exports.changePassword = function(req, res, next) {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
res.send(400, {
|
||||
message: 'Passwords do not match'
|
||||
@@ -197,9 +199,8 @@ 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) {
|
||||
@@ -207,7 +208,7 @@ exports.oauthCallback = function(strategy) {
|
||||
return res.redirect('/#!/signin');
|
||||
}
|
||||
|
||||
return res.redirect('/');
|
||||
return res.redirect(redirectURL || '/');
|
||||
});
|
||||
})(req, res, next);
|
||||
};
|
||||
@@ -250,94 +251,112 @@ exports.hasAuthorization = function(req, res, next) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to save or update a user.
|
||||
* When the user is logged in, it joins the user data to the existing one.
|
||||
* Otherwise it creates a new user.
|
||||
*
|
||||
* @author Kentaro Wakayama
|
||||
*
|
||||
* @date 2014-04-09
|
||||
*
|
||||
* @param {Object} req This is the request object which contains the user when he is signed in.
|
||||
* @param {String} token This is the accesstoken.
|
||||
* @param {String} tokenSecret This is the refreshtoken.
|
||||
* @param {Object} profile This is the user profile of the current provider.
|
||||
* @param {Function} done Callback to supply Passport with the user that authenticated.
|
||||
*
|
||||
* @param {Object} providerData This Object contains all data which is specific for the provider
|
||||
* @param {String} providerData.provider This is the passport provider name.
|
||||
* @param {String} providerData.idKey This is the Key / Attribute name for saving / retrieving the provider id.
|
||||
* @param {String} providerData.name This is the user's name.
|
||||
* @param {String} [providerData.email] This is the user's email.
|
||||
* @param {String} providerData.username This is the user's username.
|
||||
*
|
||||
* @return {[type]} [description]
|
||||
* Helper function to save or update a OAuth user profile
|
||||
*/
|
||||
exports.saveOrUpdate = function(req, token, tokenSecret, profile, done, providerData) {
|
||||
var provider = providerData.provider;
|
||||
var idKey = providerData.idKey;
|
||||
var searchProviderKey = provider + '.' + idKey;
|
||||
var searchObject = {};
|
||||
searchObject[searchProviderKey] = profile.id;
|
||||
|
||||
exports.saveOAuthUserProfile = function(req, providerUserProfile, done) {
|
||||
if (!req.user) {
|
||||
// no user active, this is a fresh login
|
||||
User.findOne(searchObject, function(err, 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);
|
||||
}
|
||||
if (!user) {
|
||||
|
||||
var possibleUsername = '';
|
||||
if (providerData.email) {
|
||||
possibleUsername = providerData.email.split('@')[0];
|
||||
} else {
|
||||
possibleUsername = profile.username;
|
||||
}
|
||||
|
||||
User.findUniqueUsername(possibleUsername, null, function(availableUsername) {
|
||||
user = new User({
|
||||
firstName: providerData.firstName,
|
||||
lastName: providerData.lastName,
|
||||
username: availableUsername,
|
||||
displayName: providerData.displayName,
|
||||
email: providerData.email,
|
||||
provider: provider,
|
||||
});
|
||||
|
||||
user[provider] = profile._json;
|
||||
user[provider].token = token;
|
||||
user[provider].tokenSecret = tokenSecret;
|
||||
user.save(function(err) {
|
||||
if (err) console.log(err);
|
||||
return done(err, user);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
user[provider].token = token;
|
||||
user[provider].tokenSecret = tokenSecret;
|
||||
user.save(function(err) {
|
||||
if (err) console.log(err);
|
||||
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 {
|
||||
// a user is already logged in, join the provider data to the existing user.
|
||||
User.findById( req.user._id, function(err, user) {
|
||||
// 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);
|
||||
}
|
||||
if (user) {
|
||||
user[provider] = profile._json;
|
||||
user[provider].token = token;
|
||||
user[provider].tokenSecret = tokenSecret;
|
||||
user.save(function(err) {
|
||||
if (err) console.log(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 {
|
||||
return done(err, user);
|
||||
req.login(user, function(err) {
|
||||
if (err) {
|
||||
res.send(400, err);
|
||||
} else {
|
||||
res.jsonp(user);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -67,18 +67,14 @@ var UserSchema = new Schema({
|
||||
required: 'Provider is required'
|
||||
},
|
||||
providerData: {},
|
||||
additionalProvidersData: {},
|
||||
updated: {
|
||||
type: Date
|
||||
},
|
||||
created: {
|
||||
type: Date,
|
||||
default: Date.now
|
||||
},
|
||||
facebook: {},
|
||||
twitter: {},
|
||||
github: {},
|
||||
google: {},
|
||||
linkedin: {}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
18
config/env/development.js
vendored
18
config/env/development.js
vendored
@@ -6,23 +6,23 @@ module.exports = {
|
||||
title: 'MEAN.JS - Development Environment'
|
||||
},
|
||||
facebook: {
|
||||
clientID: 'APP_ID',
|
||||
clientSecret: 'APP_SECRET',
|
||||
callbackURL: 'http://localhost:3000/auth/facebook/callback'
|
||||
clientID: '588647347851720',
|
||||
clientSecret: 'd2870185a0b41ab0ec32ac9d023be5b0',
|
||||
callbackURL: 'http://local.meanjs.herokuapp.com:3000/auth/facebook/callback'
|
||||
},
|
||||
twitter: {
|
||||
clientID: 'CONSUMER_KEY',
|
||||
clientSecret: 'CONSUMER_SECRET',
|
||||
clientID: 'f9JcCc0xSzEUkwF5E5ZKLQ',
|
||||
clientSecret: 'E9zzKZhZlZuy5T1qMsu3c75EkGf9yVwp0uAIOwtI0oM',
|
||||
callbackURL: 'http://localhost:3000/auth/twitter/callback'
|
||||
},
|
||||
google: {
|
||||
clientID: 'APP_ID',
|
||||
clientSecret: 'APP_SECRET',
|
||||
clientID: '751147574067-kt9q7nnkvns3b8cg742nsddk9d77k0bt.apps.googleusercontent.com',
|
||||
clientSecret: '-7acCDhnsbf22HoHB_8CkAHi',
|
||||
callbackURL: 'http://localhost:3000/auth/google/callback'
|
||||
},
|
||||
linkedin: {
|
||||
clientID: 'APP_ID',
|
||||
clientSecret: 'APP_SECRET',
|
||||
clientID: '77f1ywm1byjwpm',
|
||||
clientSecret: 'K6D9cufcuNIjcqUr',
|
||||
callbackURL: 'http://localhost:3000/auth/linkedin/callback'
|
||||
}
|
||||
};
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
var passport = require('passport'),
|
||||
FacebookStrategy = require('passport-facebook').Strategy,
|
||||
User = require('mongoose').model('User'),
|
||||
config = require('../config'),
|
||||
users = require('../../app/controllers/users');
|
||||
|
||||
@@ -15,18 +14,25 @@ module.exports = function() {
|
||||
passReqToCallback: true
|
||||
},
|
||||
function(req, accessToken, refreshToken, profile, done) {
|
||||
// Set the provider data and include tokens
|
||||
var providerData = profile._json;
|
||||
providerData.accessToken = accessToken;
|
||||
providerData.refreshToken = refreshToken;
|
||||
|
||||
var providerData = {
|
||||
// Create the user OAuth profile
|
||||
var providerUserProfile = {
|
||||
firstName: profile.name.givenName,
|
||||
lastName: profile.name.familyName,
|
||||
displayName: profile.displayName,
|
||||
provider: 'facebook',
|
||||
idKey: 'id',
|
||||
email: profile.emails[0].value,
|
||||
username: profile.username,
|
||||
provider: 'facebook',
|
||||
providerIdentifierField: 'id',
|
||||
providerData: providerData
|
||||
};
|
||||
users.saveOrUpdate(req, accessToken, refreshToken, profile, done, providerData);
|
||||
|
||||
// Save the user OAuth profile
|
||||
users.saveOAuthUserProfile(req, providerUserProfile, done);
|
||||
}
|
||||
));
|
||||
};
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
var passport = require('passport'),
|
||||
GoogleStrategy = require('passport-google-oauth').OAuth2Strategy,
|
||||
User = require('mongoose').model('User'),
|
||||
config = require('../config'),
|
||||
users = require('../../app/controllers/users');
|
||||
|
||||
@@ -15,18 +14,25 @@ module.exports = function() {
|
||||
passReqToCallback: true
|
||||
},
|
||||
function(req, accessToken, refreshToken, profile, done) {
|
||||
|
||||
var providerData = {
|
||||
// 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,
|
||||
provider: 'google',
|
||||
idKey: 'id',
|
||||
email: profile.emails[0].value,
|
||||
username: profile.username
|
||||
username: profile.username,
|
||||
provider: 'google',
|
||||
providerIdentifierField: 'id',
|
||||
providerData: providerData
|
||||
};
|
||||
users.saveOrUpdate(req, accessToken, refreshToken, profile, done, providerData);
|
||||
|
||||
// Save the user OAuth profile
|
||||
users.saveOAuthUserProfile(req, providerUserProfile, done);
|
||||
}
|
||||
));
|
||||
};
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
var passport = require('passport'),
|
||||
LinkedInStrategy = require('passport-linkedin').Strategy,
|
||||
User = require('mongoose').model('User'),
|
||||
config = require('../config'),
|
||||
users = require('../../app/controllers/users');
|
||||
|
||||
@@ -16,17 +15,25 @@ module.exports = function() {
|
||||
profileFields: ['id', 'first-name', 'last-name', 'email-address']
|
||||
},
|
||||
function(req, accessToken, refreshToken, profile, done) {
|
||||
// Set the provider data and include tokens
|
||||
var providerData = profile._json;
|
||||
providerData.accessToken = accessToken;
|
||||
providerData.refreshToken = refreshToken;
|
||||
|
||||
var providerData = {
|
||||
// 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: 'linkedin',
|
||||
idKey: 'id',
|
||||
username: profile.displayName,
|
||||
providerIdentifierField: 'id',
|
||||
providerData: providerData
|
||||
};
|
||||
users.saveOrUpdate(req, accessToken, refreshToken, profile, done, providerData);
|
||||
|
||||
// Save the user OAuth profile
|
||||
users.saveOAuthUserProfile(req, providerUserProfile, done);
|
||||
}
|
||||
));
|
||||
};
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
var passport = require('passport'),
|
||||
TwitterStrategy = require('passport-twitter').Strategy,
|
||||
User = require('mongoose').model('User'),
|
||||
config = require('../config'),
|
||||
users = require('../../app/controllers/users');
|
||||
|
||||
@@ -15,15 +14,22 @@ module.exports = function() {
|
||||
passReqToCallback: true
|
||||
},
|
||||
function(req, token, tokenSecret, profile, done) {
|
||||
// Set the provider data and include tokens
|
||||
var providerData = profile._json;
|
||||
providerData.token = token;
|
||||
providerData.tokenSecret = tokenSecret;
|
||||
|
||||
var providerData = {
|
||||
// Create the user OAuth profile
|
||||
var providerUserProfile = {
|
||||
displayName: profile.displayName,
|
||||
provider: 'twitter',
|
||||
idKey: 'id_str',
|
||||
username: profile.username,
|
||||
};
|
||||
username: profile.username,
|
||||
provider: 'twitter',
|
||||
providerIdentifierField: 'id_str',
|
||||
providerData: providerData
|
||||
};
|
||||
|
||||
users.saveOrUpdate(req, token, tokenSecret, profile, done, providerData);
|
||||
// Save the user OAuth profile
|
||||
users.saveOAuthUserProfile(req, providerUserProfile, done);
|
||||
}
|
||||
));
|
||||
};
|
||||
@@ -32,6 +32,9 @@
|
||||
<li>
|
||||
<a href="/#!/settings/profile">Edit Profile</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/#!/settings/accounts">Manage Social Accounts</a>
|
||||
</li>
|
||||
<li data-ng-show="authentication.user.provider === 'local'">
|
||||
<a href="/#!/settings/password">Change Password</a>
|
||||
</li>
|
||||
|
||||
@@ -13,6 +13,10 @@ angular.module('users').config(['$stateProvider',
|
||||
url: '/settings/password',
|
||||
templateUrl: 'modules/users/views/settings/password.html'
|
||||
}).
|
||||
state('accounts', {
|
||||
url: '/settings/accounts',
|
||||
templateUrl: 'modules/users/views/settings/accounts.html'
|
||||
}).
|
||||
state('signup', {
|
||||
url: '/signup',
|
||||
templateUrl: 'modules/users/views/signup.html'
|
||||
|
||||
@@ -4,9 +4,39 @@ angular.module('users').controller('SettingsController', ['$scope', '$http', '$l
|
||||
function($scope, $http, $location, Users, Authentication) {
|
||||
$scope.user = Authentication.user;
|
||||
|
||||
//If user is not signed in then redirect back home
|
||||
// If user is not signed in then redirect back home
|
||||
if (!$scope.user) $location.path('/');
|
||||
|
||||
// Check if there are additional accounts
|
||||
$scope.hasConnectedAdditionalSocialAccounts = function(provider) {
|
||||
for (var i in $scope.user.additionalProvidersData) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// Check if provider is already in use with current user
|
||||
$scope.isConnectedSocialAccount = function(provider) {
|
||||
return $scope.user.provider === provider || ($scope.user.additionalProvidersData && $scope.user.additionalProvidersData[provider]);
|
||||
};
|
||||
|
||||
$scope.removeUserSocialAccount = function(provider) {
|
||||
$scope.success = $scope.error = null;
|
||||
|
||||
$http.delete('/users/accounts', {
|
||||
params: {
|
||||
provider: provider
|
||||
}
|
||||
}).success(function(response) {
|
||||
// If successful show success message and clear form
|
||||
$scope.success = true;
|
||||
$scope.user = Authentication.user = response;
|
||||
}).error(function(response) {
|
||||
$scope.error = response.message;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.updateUserProfile = function() {
|
||||
$scope.success = $scope.error = null;
|
||||
var user = new Users($scope.user);
|
||||
|
||||
@@ -2,4 +2,15 @@
|
||||
.nav-users {
|
||||
position: fixed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.remove-account-container {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.btn-remove-account {
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
@@ -31,19 +31,4 @@
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
<h3 class="col-md-12 text-center">Add an other Account</h3>
|
||||
<div class="col-md-12 text-center">
|
||||
<a href="/auth/facebook" ng-disabled="user.facebook" class="undecorated-link btn">
|
||||
<img src="/modules/users/img/buttons/facebook.png">
|
||||
</a>
|
||||
<a href="/auth/twitter" ng-disabled="user.twitter" class="undecorated-link btn">
|
||||
<img src="/modules/users/img/buttons/twitter.png">
|
||||
</a>
|
||||
<a href="/auth/google" ng-disabled="user.google" class="undecorated-link btn">
|
||||
<img src="/modules/users/img/buttons/google.png">
|
||||
</a>
|
||||
<a href="/auth/linkedin" ng-disabled="user.linkedin" class="undecorated-link btn">
|
||||
<img src="/modules/users/img/buttons/linkedin.png">
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
Reference in New Issue
Block a user