Skip to content

Commit

Permalink
Ft 164489784 login with twitter
Browse files Browse the repository at this point in the history
  • Loading branch information
jnkindi committed Apr 9, 2019
1 parent c72ba96 commit dc4c569
Show file tree
Hide file tree
Showing 12 changed files with 105 additions and 17 deletions.
4 changes: 4 additions & 0 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,8 @@ FacebookCallback_URL =
FACEBOOK_APP_ID =
FACEBOOK_APP_SECRET =

TWITTER_CONSUMER_KEY=
TWITTER_CONSUMER_SECRET=
TWITTER_CALLBACK=

SECRETKEY =
5 changes: 3 additions & 2 deletions controllers/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ class User {
static async socialLogin(req, res) {
const ruser = {
username: req.user.username,
email: req.user.email,
email: req.user.email || '',
firstname: req.user.firstname,
lastname: req.user.lastname,
lastname: req.user.lastname || '',
bio: req.user.bio || '',
image: req.user.image,
provider: req.user.provider,
provideruserid: req.user.provideruserid
Expand Down
10 changes: 10 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,29 @@
import express from 'express';
import bodyParser from 'body-parser';
import passport from 'passport';
import session from 'express-session';
import swaggerUi from 'swagger-ui-express';
import YAML from 'yamljs';
import dotenv from 'dotenv';
import user from './routes/user';
import Strategy from './middlewares/auth';

dotenv.config();

const swaggerDocument = YAML.load('./swagger.yaml');

const app = express();

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.use(session({
secret: process.env.SECRETKEY,
resave: false,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
const strategy = new Strategy();
app.use('/api/v1/login', user);
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
Expand Down
4 changes: 3 additions & 1 deletion middlewares/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import passport from 'passport';
import serializePassportUser from './serialize';
import facebookStrategy from './passportStrategy/facebook';
import GoogleStrategy from './passportStrategy/google';
import TwitterStrategy from './passportStrategy/twitter';
import models from '../models/index';

const { user } = models;
Expand All @@ -13,13 +14,14 @@ dotenv.config();
*/
class Strategy {
/**
* @author frank harerimana
* @author frank harerimana with Jacques Nyilinkindi
* @param {*} passport
* @return { O } strategy
*/
constructor() {
this.facebookStrategy = passport.use(facebookStrategy);
this.GoogleStrategy = passport.use(GoogleStrategy);
this.TwitterStrategy = passport.use(TwitterStrategy);
this.serializePassportUser = serializePassportUser(passport, user);
}
}
Expand Down
37 changes: 34 additions & 3 deletions middlewares/callbackHandler.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable no-underscore-dangle */
import usernameGenerator from './uniquestring';

const usernamestring = new usernameGenerator();
/**
* @author frank harerimana
* @param {*} accessToken
Expand All @@ -13,11 +14,10 @@ const GetSocial = async (accessToken, refreshToken, profile, done) => {
/**
* get unique formatted username
*/
const usernamestring = new usernameGenerator(profile.displayName);

const SocialUser = {
email: profile._json.email,
username: usernamestring.getUsername(),
username: usernamestring.getUsername(profile.displayName),
firstname: profile.name.familyName,
lastname: profile.name.givenName,
image: profile.photos[0].value,
Expand All @@ -27,4 +27,35 @@ const GetSocial = async (accessToken, refreshToken, profile, done) => {

done(null, SocialUser);
};
export default GetSocial;

/**
* @author Jacques Nyilinkindi
* @param {*} token
* @param {*} tokenSecret
* @param {*} profile
* @param {*} done
* @returns { Object } user
*/
const GetSocialTwitter = async (token, tokenSecret, profile, done) => {
/**
* get unique formatted username
*/
const { _json } = profile;
// _json.profile_image_url.
const image = usernamestring.generateLargeTwitterProfile(_json.profile_image_url);
const names = usernamestring.removeSpecialCharacters(_json.name);

const SocialUser = {
username: usernamestring.getUsername(profile.username),
firstname: names,
image,
bio: _json.description,
provider: _json.provider,
provideruserid: _json.id.toString()
};
done(null, SocialUser);
};
export {
GetSocial,
GetSocialTwitter
};
2 changes: 1 addition & 1 deletion middlewares/passportStrategy/facebook.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import FacebookStrategy from 'passport-facebook';
import GetSocial from '../callbackHandler';
import { GetSocial } from '../callbackHandler';
/**
* @author frank harerimana
* @returns Facebook strategy
Expand Down
2 changes: 1 addition & 1 deletion middlewares/passportStrategy/google.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import GoogleStrategy from 'passport-google-oauth20';
import GetSocial from '../callbackHandler';
import { GetSocial } from '../callbackHandler';

/**
* @author frank harerimana
Expand Down
17 changes: 17 additions & 0 deletions middlewares/passportStrategy/twitter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import TwitterStrategy from 'passport-twitter';
import { GetSocialTwitter } from '../callbackHandler';
/**
* @author Jacques Nyilinkindi
* @returns Twitter strategy
*/
const Twitter = new TwitterStrategy({
consumerKey: process.env.TWITTER_CONSUMER_KEY,
consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
callbackURL: process.env.TWITTER_CALLBACK,
},
async (token, tokenSecret, profile, done) => {
GetSocialTwitter(
token, tokenSecret, profile, done
);
});
export default Twitter;
2 changes: 1 addition & 1 deletion middlewares/serialize.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const serializePassportUser = (passport, user) => {
done(null, SocialUser.provideruserid);
});
passport.deserializeUser((provideruserid, done) => {
user.findByPk(provideruserid).then((SocialUser) => {
user.findAll({ where: { provideruserid } }).then((SocialUser) => {
done(null, SocialUser);
})
.catch(err => done(err, false));
Expand Down
31 changes: 25 additions & 6 deletions middlewares/uniquestring.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,42 @@
/* eslint-disable class-methods-use-this */
/**
* @author frank harerimana
* Generate unique username
*/
class Generate {
/**
* @param {*} strings
*/
constructor(strings) {
this.strings = strings;
* @author frank harerimana
*/
constructor() {
this.randomNumber = Math.floor(Math.random() * 10000);
this.randomString = Math.random().toString(36).slice(2);
}

/**
* @author frank harerimana
* @param { String } name
* @returns { String } username
*/
getUsername() {
return this.strings.replace(/\s/g, '-').toLowerCase() + this.randomNumber;
getUsername(name) {
return name.replace(/\s/g, '-').toLowerCase() + this.randomNumber;
}

/**
* @author Jacques Nyilinkindi
* @param { String } words
* @returns { String } string
*/
removeSpecialCharacters(words) {
return words.replace(/[^a-zA-Z ]/g, '').trim();
}

/**
* @author Jacques Nyilinkindi
* @param { String } image
* @returns { String } string
*/
generateLargeTwitterProfile(image) {
return image.replace('_normal', '');
}
}
export default Generate;
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"passport-facebook": "^3.0.0",
"passport-google-oauth20": "^2.0.0",
"passport-linkedin": "^1.0.0",
"passport-twitter": "^1.0.4",
"pg": "^7.9.0",
"request": "^2.87.0",
"sequelize": "^4.42.0",
Expand Down
7 changes: 5 additions & 2 deletions routes/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ import user from '../controllers/user';

const route = express.Router();

route.get('/auth/google', passport.authenticate('google', { scope: ['email', 'profile'] }));
route.get('/auth/google', passport.authenticate('google', { session: false, scope: ['email', 'profile'] }));
route.get('/google/redirect', passport.authenticate('google', { failureRedirect: 'auth/google' }), user.socialLogin);
// passport.authenticate('google', user.googleLogin)
route.get('/auth/facebook', passport.authenticate('facebook', { scope: ['email'] }));
route.get('/auth/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/auth/facebook' }), user.socialLogin);
route.get('/auth/facebook/callback', passport.authenticate('facebook', { session: false, failureRedirect: '/auth/facebook' }), user.socialLogin);
// passport.authenticate twitter
route.get('/auth/twitter', passport.authenticate('twitter'));
route.get('/auth/twitter/callback', passport.authenticate('twitter', { failureRedirect: '/auth/twitter' }), user.socialLogin);

export default route;

0 comments on commit dc4c569

Please sign in to comment.