mirror of
https://github.com/taobataoma/meanTorrent.git
synced 2026-01-29 10:39:19 +01:00
Two different strategies are adopted, one for when the user authenticates locally and the other through providers. When authenticating locally, the signin function in the client controller redirects to the previous state (storing and using a state name) after successful login. When authenticating through a provider, the first call to provider stores the previous URL (not state, URL) in the session. Then, when provider actually calls the authentication callback, session redirect_to path is used for redirecting user.
242 lines
6.6 KiB
JavaScript
242 lines
6.6 KiB
JavaScript
'use strict';
|
|
|
|
/**
|
|
* Module dependencies.
|
|
*/
|
|
var path = require('path'),
|
|
errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller')),
|
|
mongoose = require('mongoose'),
|
|
passport = require('passport'),
|
|
User = mongoose.model('User');
|
|
|
|
// URLs for which user can't be redirected on signin
|
|
var noReturnUrls = [
|
|
'/authentication/signin',
|
|
'/authentication/signup'
|
|
];
|
|
|
|
/**
|
|
* Signup
|
|
*/
|
|
exports.signup = function (req, res) {
|
|
// For security measurement we remove the roles from the req.body object
|
|
delete req.body.roles;
|
|
|
|
// Init Variables
|
|
var user = new User(req.body);
|
|
var message = null;
|
|
|
|
// Add missing user fields
|
|
user.provider = 'local';
|
|
user.displayName = user.firstName + ' ' + user.lastName;
|
|
|
|
// Then save the user
|
|
user.save(function (err) {
|
|
if (err) {
|
|
return res.status(400).send({
|
|
message: errorHandler.getErrorMessage(err)
|
|
});
|
|
} else {
|
|
// Remove sensitive data before login
|
|
user.password = undefined;
|
|
user.salt = undefined;
|
|
|
|
req.login(user, function (err) {
|
|
if (err) {
|
|
res.status(400).send(err);
|
|
} else {
|
|
res.json(user);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Signin after passport authentication
|
|
*/
|
|
exports.signin = function (req, res, next) {
|
|
passport.authenticate('local', function (err, user, info) {
|
|
if (err || !user) {
|
|
res.status(400).send(info);
|
|
} else {
|
|
// Remove sensitive data before login
|
|
user.password = undefined;
|
|
user.salt = undefined;
|
|
|
|
req.login(user, function (err) {
|
|
if (err) {
|
|
res.status(400).send(err);
|
|
} else {
|
|
res.json(user);
|
|
}
|
|
});
|
|
}
|
|
})(req, res, next);
|
|
};
|
|
|
|
/**
|
|
* Signout
|
|
*/
|
|
exports.signout = function (req, res) {
|
|
req.logout();
|
|
res.redirect('/');
|
|
};
|
|
|
|
/**
|
|
* OAuth provider call
|
|
*/
|
|
exports.oauthCall = function(strategy, scope) {
|
|
return function(req, res, next) {
|
|
// Set redirection path on session.
|
|
// Do not redirect to a signin or signup page
|
|
if (noReturnUrls.indexOf(req.query.redirect_to) === -1) {
|
|
req.session.redirect_to = req.query.redirect_to;
|
|
}
|
|
// Authenticate
|
|
passport.authenticate(strategy, scope)(req, res, next);
|
|
};
|
|
};
|
|
|
|
/**
|
|
* OAuth callback
|
|
*/
|
|
exports.oauthCallback = function (strategy) {
|
|
return function (req, res, next) {
|
|
// Pop redirect URL from session
|
|
var sessionRedirectURL = req.session.redirect_to;
|
|
delete req.session.redirect_to;
|
|
|
|
passport.authenticate(strategy, function (err, user, redirectURL) {
|
|
if (err) {
|
|
return res.redirect('/authentication/signin?err=' + encodeURIComponent(errorHandler.getErrorMessage(err)));
|
|
}
|
|
if (!user) {
|
|
return res.redirect('/authentication/signin');
|
|
}
|
|
req.login(user, function (err) {
|
|
if (err) {
|
|
return res.redirect('/authentication/signin');
|
|
}
|
|
|
|
return res.redirect(redirectURL || sessionRedirectURL || '/');
|
|
});
|
|
})(req, res, 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,
|
|
profileImageURL: providerUserProfile.profileImageURL,
|
|
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
|
|
var user = req.user;
|
|
|
|
// Check if user exists, is not signed in using this provider, and doesn't have that provider data already configured
|
|
if (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(new Error('User is already connected using this provider'), user);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Remove OAuth provider
|
|
*/
|
|
exports.removeOAuthProvider = function (req, res, next) {
|
|
var user = req.user;
|
|
var provider = req.query.provider;
|
|
|
|
if (!user) {
|
|
return res.status(401).json({
|
|
message: 'User is not authenticated'
|
|
});
|
|
} else if (!provider) {
|
|
return res.status(400).send();
|
|
}
|
|
|
|
// 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.status(400).send({
|
|
message: errorHandler.getErrorMessage(err)
|
|
});
|
|
} else {
|
|
req.login(user, function (err) {
|
|
if (err) {
|
|
return res.status(400).send(err);
|
|
} else {
|
|
return res.json(user);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
};
|