Skip to content

Commit

Permalink
feat(social-login): enable social login through facebook and google
Browse files Browse the repository at this point in the history
- add test for response from social login
- enable social login to facebook
- enable social login to google

[Delivers #159206051]
  • Loading branch information
OKiMaureen committed Aug 10, 2018
1 parent 864281c commit 3fc805a
Show file tree
Hide file tree
Showing 11 changed files with 10,715 additions and 28 deletions.
79 changes: 54 additions & 25 deletions config/passport.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,60 @@
import passport from 'passport';
import bcrypt from 'bcrypt';
import local from 'passport-local';
import db from '../models';
import GoogleStrategy from 'passport-google-oauth20';
import FacebookStrategy from 'passport-facebook';
import AuthController from '../controllers/authController';
import { User } from '../models';

const LocalStrategy = local.Strategy;

passport.use(new LocalStrategy(
{
usernameField: 'user[email]',
passwordField: 'user[password]'
},
((email, password, done) => {
db.User.findOne({ where: { email } })
.then((user) => {
bcrypt.compare(
password,
user.hashedPassword,
(err, res) => {
if (!user || !res || err) {
return done(null, false, {
errors: { 'email or password': 'is invalid' }
});
}
return done(null, user);
const passportConfig = (app) => {
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(
{
usernameField: 'user[email]',
passwordField: 'user[password]'
},
((email, password, done) => {
User.findOne({ email })
.then((user) => {
if (!user || !user.validPassword(password)) {
return done(null, false, {
errors: { 'email or password': 'is invalid' }
});
}
);
})
.catch(done);
})
));

return done(null, user);
})
.catch(done);
})
));

/**
* configurations for passport strategies
*/

passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: '/api/users/login/google/redirect',
}, AuthController.strategyCallback));

passport.use(new FacebookStrategy({
clientID: process.env.FACEBOOK_APP_ID,
clientSecret: process.env.FACEBOOK_APP_SECRET,
callbackURL: '/api/users/login/facebook/redirect',
profileFields: ['id', 'displayName', 'photos', 'email'],
}, AuthController.strategyCallback));

passport.serializeUser(((user, done) => {
done(null, user.id);
}));
passport.deserializeUser(((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
}));
};

export default passportConfig;
99 changes: 99 additions & 0 deletions controllers/authController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { User } from '../models';
import utilities from '../helpers/utilities';
/**
* @class AuthController
*
* @export
*
*/
export default class AuthController {
/**
* @description - json response function
* @static
*
*
* @param {object} req
* @param {object} res
*
* @returns {json} json
*
* @memberof AuthController
*
*/
static jsonResponse(req, res) {
const user = {
email: req.user.email,
token: utilities.signToken({ id: req.user.id }),
firstname: req.user.firstname,
lastname: req.user.lastname,
username: req.user.username,
image: req.user.image,
};
if (req.user.created) {
return res.status(201).json({ success: true, user });
}
return res.status(200).json({ success: true, user });
}

/**
* @description - model query function
* @static
*
*
* @param {object} user
* @param {function} done
*
* @returns {object} newOrFoundUser
*
* @memberof AuthController
*
*/
static queryModel(user, done) {
User.findOrCreate({
where: {
email: user.email,
},
defaults: user,
}).spread((newOrFoundUser, created) => {
if (!newOrFoundUser) { return done(null, false); }
const {
id, email, username, lastname, firstname, image,
} = newOrFoundUser.dataValues;
return done(null, {
id,
email,
username,
lastname,
firstname,
image,
created,
});
});
}


/**
* @description - strategy callback function
* @static
*
* @param {object} accessToken
* @param {object} refreshToken
* @param {object} profile
* @param {function} done
*
* @returns {json} json
*
* @memberof AuthController
*
*/
static strategyCallback(accessToken, refreshToken, profile, done) {
const userProfile = {
firstname: profile.name.familyName,
lastname: profile.name.givenName,
username: profile.id,
email: profile.emails[0].value,
image: profile.photos[0].value,
};
AuthController.queryModel(userProfile, done);
}
}
2 changes: 1 addition & 1 deletion helpers/utilities.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import jwt from 'jsonwebtoken';

import { } from 'dotenv/config';
/** Class representing all utility functions */
export default class Utilities {
/**
Expand Down
10 changes: 9 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import path from 'path';
import express from 'express';
import bodyParser from 'body-parser';
import session from 'express-session';
import passport from 'passport';
import cors from 'cors';
import errorhandler from 'errorhandler';
import methodOverride from 'method-override';
Expand All @@ -10,15 +11,22 @@ import debugLog from 'debug';

import { } from 'dotenv/config';

import passportConfig from './config/passport';
import routes from './routes';

const isProduction = process.env.NODE_ENV === 'production';

const debug = debugLog('index');
passport.serializeUser(((user, done) => {
done(null, user);
}));
passport.deserializeUser(((user, done) => {
done(null, user);
}));

// Create global app object
const app = express();

passportConfig(app);
app.use(cors());

// Normal express config defaults;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ module.exports = {
allowNull: false,
unique: true,
},
lastname: {
type: Sequelize.STRING,
},
firstname: {
type: Sequelize.STRING,
},
email: {
type: Sequelize.STRING,
allowNull: false,
Expand Down Expand Up @@ -40,7 +46,7 @@ module.exports = {
type: Sequelize.DATE
}
}),
down: (queryInterface/* , Sequelize */) => {
down: (queryInterface) => {
queryInterface.dropTable('Users');
}
};
6 changes: 6 additions & 0 deletions models/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ module.exports = (sequelize, DataTypes) => {
allowNull: false,
unique: true,
},
lastname: {
type: DataTypes.STRING,
},
firstname: {
type: DataTypes.STRING,
},
email: {
type: DataTypes.STRING,
allowNull: false,
Expand Down
Loading

0 comments on commit 3fc805a

Please sign in to comment.