Added schema and finduserbyid to the new Users model file
This commit is contained in:
34
server.js
34
server.js
@ -1,25 +1,38 @@
|
|||||||
var express = require('express'),
|
var express = require('express'),
|
||||||
mongoose = require('mongoose'),
|
http = require('http'),
|
||||||
|
path = require('path'),
|
||||||
fs = require('fs'),
|
fs = require('fs'),
|
||||||
|
mongoose = require('mongoose'),
|
||||||
|
passport = require('passport'),
|
||||||
config = require('./conf');
|
config = require('./conf');
|
||||||
|
|
||||||
|
var User = require('./server/models/User');
|
||||||
|
|
||||||
var db = mongoose.connect(config.db);
|
var db = mongoose.connect(config.db);
|
||||||
var app = express();
|
var app = express();
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Express Settings
|
|
||||||
*/
|
|
||||||
app.set('port', process.env.PORT || 3000);
|
app.set('port', process.env.PORT || 3000);
|
||||||
|
app.set('views', __dirname + '/client/views');
|
||||||
|
app.set('view engine', 'jade');
|
||||||
app.use(express.favicon());
|
app.use(express.favicon());
|
||||||
app.use(express.logger('dev'));
|
app.use(express.logger('dev'));
|
||||||
app.use(express.json());
|
app.use(express.cookieParser());
|
||||||
app.use(express.urlencoded());
|
app.use(express.bodyParser());
|
||||||
app.use(express.methodOverride());
|
app.use(express.methodOverride());
|
||||||
|
app.use(express.cookieSession({ secret: process.env.COOKIE_SECRET || 'secret' }));
|
||||||
|
app.use(passport.initialize());
|
||||||
|
app.use(passport.session());
|
||||||
app.use(app.router);
|
app.use(app.router);
|
||||||
app.use(express.static(config.root + '/public'));
|
app.use(express.static(config.root + '/public'));
|
||||||
|
|
||||||
|
passport.use(User.localStrategy);
|
||||||
|
passport.use(User.twitterStrategy());
|
||||||
|
passport.use(User.facebookStrategy());
|
||||||
|
passport.use(User.googleStrategy());
|
||||||
|
passport.use(User.linkedInStrategy());
|
||||||
|
passport.serializeUser(User.serializeUser);
|
||||||
|
passport.deserializeUser(User.deserializeUser);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API Controllers
|
* API Controllers
|
||||||
@ -28,13 +41,6 @@ var articles = require('./controllers/articles');
|
|||||||
var users = require('./controllers/users');
|
var users = require('./controllers/users');
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API Models
|
|
||||||
*/
|
|
||||||
var Article = require('./models/article');
|
|
||||||
var User = require('./models/user');
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API Routes
|
* API Routes
|
||||||
*/
|
*/
|
||||||
|
@ -1,175 +1,199 @@
|
|||||||
var User
|
var _ = require('underscore'),
|
||||||
, _ = require('underscore')
|
mongoose = require('mongoose'),
|
||||||
, passport = require('passport')
|
crypto = require('crypto'),
|
||||||
, LocalStrategy = require('passport-local').Strategy
|
passport = require('passport'),
|
||||||
, TwitterStrategy = require('passport-twitter').Strategy
|
LocalStrategy = require('passport-local').Strategy,
|
||||||
, FacebookStrategy = require('passport-facebook').Strategy
|
TwitterStrategy = require('passport-twitter').Strategy,
|
||||||
, GoogleStrategy = require('passport-google').Strategy
|
FacebookStrategy = require('passport-facebook').Strategy,
|
||||||
, LinkedInStrategy = require('passport-linkedin').Strategy
|
GoogleStrategy = require('passport-google').Strategy,
|
||||||
, check = require('validator').check
|
LinkedInStrategy = require('passport-linkedin').Strategy,
|
||||||
, userRoles = require('../../client/js/routingConfig').userRoles;
|
check = require('validator').check,
|
||||||
|
userRoles = require('../../client/js/routingConfig').userRoles;
|
||||||
|
|
||||||
|
var UserSchema = new mongoose.Schema({
|
||||||
|
name: String,
|
||||||
|
email: String,
|
||||||
|
username: {
|
||||||
|
type: String,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
provider: String,
|
||||||
|
hashed_password: String,
|
||||||
|
salt: String,
|
||||||
|
facebook: {},
|
||||||
|
twitter: {},
|
||||||
|
google: {}
|
||||||
|
});
|
||||||
|
|
||||||
|
var User = mongoose.model('User', UserSchema);
|
||||||
|
|
||||||
var users = [
|
var users = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
username: "user",
|
username: "user",
|
||||||
password: "123",
|
password: "123",
|
||||||
role: userRoles.user
|
role: userRoles.user
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
username: "admin",
|
username: "admin",
|
||||||
password: "123",
|
password: "123",
|
||||||
role: userRoles.admin
|
role: userRoles.admin
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
addUser: function(username, password, role, callback) {
|
addUser: function(username, password, role, callback) {
|
||||||
if(this.findByUsername(username) !== undefined) return callback("UserAlreadyExists");
|
if (this.findByUsername(username) !== undefined) {
|
||||||
|
return callback("UserAlreadyExists");
|
||||||
// Clean up when 500 users reached
|
|
||||||
if(users.length > 500) {
|
|
||||||
users = users.slice(0, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = {
|
|
||||||
id: _.max(users, function(user) { return user.id; }).id + 1,
|
|
||||||
username: username,
|
|
||||||
password: password,
|
|
||||||
role: role
|
|
||||||
};
|
|
||||||
users.push(user);
|
|
||||||
callback(null, user);
|
|
||||||
},
|
|
||||||
|
|
||||||
findOrCreateOauthUser: function(provider, providerId) {
|
|
||||||
var user = module.exports.findByProviderId(provider, providerId);
|
|
||||||
if(!user) {
|
|
||||||
user = {
|
|
||||||
id: _.max(users, function(user) { return user.id; }).id + 1,
|
|
||||||
username: provider + '_user', // Should keep Oauth users anonymous on demo site
|
|
||||||
role: userRoles.user,
|
|
||||||
provider: provider
|
|
||||||
};
|
|
||||||
user[provider] = providerId;
|
|
||||||
users.push(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
return user;
|
|
||||||
},
|
|
||||||
|
|
||||||
findAll: function() {
|
|
||||||
return _.map(users, function(user) { return _.clone(user); });
|
|
||||||
},
|
|
||||||
|
|
||||||
findById: function(id) {
|
|
||||||
return _.clone(_.find(users, function(user) { return user.id === id }));
|
|
||||||
},
|
|
||||||
|
|
||||||
findByUsername: function(username) {
|
|
||||||
return _.clone(_.find(users, function(user) { return user.username === username; }));
|
|
||||||
},
|
|
||||||
|
|
||||||
findByProviderId: function(provider, id) {
|
|
||||||
return _.find(users, function(user) { return user[provider] === id; });
|
|
||||||
},
|
|
||||||
|
|
||||||
validate: function(user) {
|
|
||||||
check(user.username, 'Username must be 1-20 characters long').len(1, 20);
|
|
||||||
check(user.password, 'Password must be 5-60 characters long').len(5, 60);
|
|
||||||
check(user.username, 'Invalid username').not(/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/);
|
|
||||||
|
|
||||||
// TODO: Seems node-validator's isIn function doesn't handle Number arrays very well...
|
|
||||||
// Till this is rectified Number arrays must be converted to string arrays
|
|
||||||
// https://github.com/chriso/node-validator/issues/185
|
|
||||||
var stringArr = _.map(_.values(userRoles), function(val) { return val.toString() });
|
|
||||||
check(user.role, 'Invalid user role given').isIn(stringArr);
|
|
||||||
},
|
|
||||||
|
|
||||||
localStrategy: new LocalStrategy(
|
|
||||||
function(username, password, done) {
|
|
||||||
|
|
||||||
var user = module.exports.findByUsername(username);
|
|
||||||
|
|
||||||
if(!user) {
|
|
||||||
done(null, false, { message: 'Incorrect username.' });
|
|
||||||
}
|
|
||||||
else if(user.password != password) {
|
|
||||||
done(null, false, { message: 'Incorrect username.' });
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return done(null, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
),
|
|
||||||
|
|
||||||
twitterStrategy: function() {
|
|
||||||
if(!process.env.TWITTER_CONSUMER_KEY) throw new Error('A Twitter Consumer Key is required if you want to enable login via Twitter.');
|
|
||||||
if(!process.env.TWITTER_CONSUMER_SECRET) throw new Error('A Twitter Consumer Secret is required if you want to enable login via Twitter.');
|
|
||||||
|
|
||||||
return new TwitterStrategy({
|
|
||||||
consumerKey: process.env.TWITTER_CONSUMER_KEY,
|
|
||||||
consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
|
|
||||||
callbackURL: process.env.TWITTER_CALLBACK_URL || 'http://localhost:8000/auth/twitter/callback'
|
|
||||||
},
|
|
||||||
function(token, tokenSecret, profile, done) {
|
|
||||||
var user = module.exports.findOrCreateOauthUser(profile.provider, profile.id);
|
|
||||||
done(null, user);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
facebookStrategy: function() {
|
|
||||||
if(!process.env.FACEBOOK_APP_ID) throw new Error('A Facebook App ID is required if you want to enable login via Facebook.');
|
|
||||||
if(!process.env.FACEBOOK_APP_SECRET) throw new Error('A Facebook App Secret is required if you want to enable login via Facebook.');
|
|
||||||
|
|
||||||
return new FacebookStrategy({
|
|
||||||
clientID: process.env.FACEBOOK_APP_ID,
|
|
||||||
clientSecret: process.env.FACEBOOK_APP_SECRET,
|
|
||||||
callbackURL: process.env.FACEBOOK_CALLBACK_URL || "http://localhost:8000/auth/facebook/callback"
|
|
||||||
},
|
|
||||||
function(accessToken, refreshToken, profile, done) {
|
|
||||||
var user = module.exports.findOrCreateOauthUser(profile.provider, profile.id);
|
|
||||||
done(null, user);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
googleStrategy: function() {
|
|
||||||
|
|
||||||
return new GoogleStrategy({
|
|
||||||
returnURL: process.env.GOOGLE_RETURN_URL || "http://localhost:8000/auth/google/return",
|
|
||||||
realm: process.env.GOOGLE_REALM || "http://localhost:8000/"
|
|
||||||
},
|
|
||||||
function(identifier, profile, done) {
|
|
||||||
var user = module.exports.findOrCreateOauthUser('google', identifier);
|
|
||||||
done(null, user);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
linkedInStrategy: function() {
|
|
||||||
if(!process.env.LINKED_IN_KEY) throw new Error('A LinkedIn App Key is required if you want to enable login via LinkedIn.');
|
|
||||||
if(!process.env.LINKED_IN_SECRET) throw new Error('A LinkedIn App Secret is required if you want to enable login via LinkedIn.');
|
|
||||||
|
|
||||||
return new LinkedInStrategy({
|
|
||||||
consumerKey: process.env.LINKED_IN_KEY,
|
|
||||||
consumerSecret: process.env.LINKED_IN_SECRET,
|
|
||||||
callbackURL: process.env.LINKED_IN_CALLBACK_URL || "http://localhost:8000/auth/linkedin/callback"
|
|
||||||
},
|
|
||||||
function(token, tokenSecret, profile, done) {
|
|
||||||
var user = module.exports.findOrCreateOauthUser('linkedin', profile.id);
|
|
||||||
done(null,user);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
serializeUser: function(user, done) {
|
|
||||||
done(null, user.id);
|
|
||||||
},
|
|
||||||
|
|
||||||
deserializeUser: function(id, done) {
|
|
||||||
var user = module.exports.findById(id);
|
|
||||||
|
|
||||||
if(user) { done(null, user); }
|
|
||||||
else { done(null, false); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean up when 500 users reached
|
||||||
|
if(users.length > 500) {
|
||||||
|
users = users.slice(0, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = new User({
|
||||||
|
id: _.max(users, function(user) { return user.id; }).id + 1,
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
role: role
|
||||||
|
});
|
||||||
|
users.push(user);
|
||||||
|
callback(null, user);
|
||||||
|
},
|
||||||
|
|
||||||
|
findOrCreateOauthUser: function(provider, providerId) {
|
||||||
|
var user = module.exports.findByProviderId(provider, providerId);
|
||||||
|
if(!user) {
|
||||||
|
user = {
|
||||||
|
id: _.max(users, function(user) { return user.id; }).id + 1,
|
||||||
|
username: provider + '_user', // Should keep Oauth users anonymous on demo site
|
||||||
|
role: userRoles.user,
|
||||||
|
provider: provider
|
||||||
|
};
|
||||||
|
user[provider] = providerId;
|
||||||
|
users.push(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
},
|
||||||
|
|
||||||
|
findAll: function() {
|
||||||
|
return _.map(users, function(user) { return _.clone(user); });
|
||||||
|
},
|
||||||
|
|
||||||
|
findById: function(id) {
|
||||||
|
return _.clone(_.find(users, function(user) { return user.id === id }));
|
||||||
|
},
|
||||||
|
|
||||||
|
findByUsername: function(username) {
|
||||||
|
User.findOne({ username: username }, function(err, user) {
|
||||||
|
if (user) {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
findByProviderId: function(provider, id) {
|
||||||
|
return _.find(users, function(user) { return user[provider] === id; });
|
||||||
|
},
|
||||||
|
|
||||||
|
validate: function(user) {
|
||||||
|
check(user.username, 'Username must be 1-20 characters long').len(1, 20);
|
||||||
|
check(user.password, 'Password must be 5-60 characters long').len(5, 60);
|
||||||
|
check(user.username, 'Invalid username').not(/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/);
|
||||||
|
|
||||||
|
// TODO: Seems node-validator's isIn function doesn't handle Number arrays very well...
|
||||||
|
// Till this is rectified Number arrays must be converted to string arrays
|
||||||
|
// https://github.com/chriso/node-validator/issues/185
|
||||||
|
var stringArr = _.map(_.values(userRoles), function(val) { return val.toString() });
|
||||||
|
check(user.role, 'Invalid user role given').isIn(stringArr);
|
||||||
|
},
|
||||||
|
|
||||||
|
localStrategy: new LocalStrategy(
|
||||||
|
function(username, password, done) {
|
||||||
|
|
||||||
|
var user = module.exports.findByUsername(username);
|
||||||
|
|
||||||
|
if(!user) {
|
||||||
|
done(null, false, { message: 'Incorrect username.' });
|
||||||
|
}
|
||||||
|
else if(user.password != password) {
|
||||||
|
done(null, false, { message: 'Incorrect username.' });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return done(null, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
),
|
||||||
|
|
||||||
|
twitterStrategy: function() {
|
||||||
|
if(!process.env.TWITTER_CONSUMER_KEY) throw new Error('A Twitter Consumer Key is required if you want to enable login via Twitter.');
|
||||||
|
if(!process.env.TWITTER_CONSUMER_SECRET) throw new Error('A Twitter Consumer Secret is required if you want to enable login via Twitter.');
|
||||||
|
|
||||||
|
return new TwitterStrategy({
|
||||||
|
consumerKey: process.env.TWITTER_CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
|
||||||
|
callbackURL: process.env.TWITTER_CALLBACK_URL || 'http://localhost:8000/auth/twitter/callback'
|
||||||
|
},
|
||||||
|
function(token, tokenSecret, profile, done) {
|
||||||
|
var user = module.exports.findOrCreateOauthUser(profile.provider, profile.id);
|
||||||
|
done(null, user);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
facebookStrategy: function() {
|
||||||
|
if(!process.env.FACEBOOK_APP_ID) throw new Error('A Facebook App ID is required if you want to enable login via Facebook.');
|
||||||
|
if(!process.env.FACEBOOK_APP_SECRET) throw new Error('A Facebook App Secret is required if you want to enable login via Facebook.');
|
||||||
|
|
||||||
|
return new FacebookStrategy({
|
||||||
|
clientID: process.env.FACEBOOK_APP_ID,
|
||||||
|
clientSecret: process.env.FACEBOOK_APP_SECRET,
|
||||||
|
callbackURL: process.env.FACEBOOK_CALLBACK_URL || "http://localhost:8000/auth/facebook/callback"
|
||||||
|
},
|
||||||
|
function(accessToken, refreshToken, profile, done) {
|
||||||
|
var user = module.exports.findOrCreateOauthUser(profile.provider, profile.id);
|
||||||
|
done(null, user);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
googleStrategy: function() {
|
||||||
|
|
||||||
|
return new GoogleStrategy({
|
||||||
|
returnURL: process.env.GOOGLE_RETURN_URL || "http://localhost:8000/auth/google/return",
|
||||||
|
realm: process.env.GOOGLE_REALM || "http://localhost:8000/"
|
||||||
|
},
|
||||||
|
function(identifier, profile, done) {
|
||||||
|
var user = module.exports.findOrCreateOauthUser('google', identifier);
|
||||||
|
done(null, user);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
linkedInStrategy: function() {
|
||||||
|
if(!process.env.LINKED_IN_KEY) throw new Error('A LinkedIn App Key is required if you want to enable login via LinkedIn.');
|
||||||
|
if(!process.env.LINKED_IN_SECRET) throw new Error('A LinkedIn App Secret is required if you want to enable login via LinkedIn.');
|
||||||
|
|
||||||
|
return new LinkedInStrategy({
|
||||||
|
consumerKey: process.env.LINKED_IN_KEY,
|
||||||
|
consumerSecret: process.env.LINKED_IN_SECRET,
|
||||||
|
callbackURL: process.env.LINKED_IN_CALLBACK_URL || "http://localhost:8000/auth/linkedin/callback"
|
||||||
|
},
|
||||||
|
function(token, tokenSecret, profile, done) {
|
||||||
|
var user = module.exports.findOrCreateOauthUser('linkedin', profile.id);
|
||||||
|
done(null,user);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
serializeUser: function(user, done) {
|
||||||
|
done(null, user.id);
|
||||||
|
},
|
||||||
|
|
||||||
|
deserializeUser: function(id, done) {
|
||||||
|
var user = module.exports.findById(id);
|
||||||
|
|
||||||
|
if(user) { done(null, user); }
|
||||||
|
else { done(null, false); }
|
||||||
|
}
|
||||||
};
|
};
|
Reference in New Issue
Block a user