Skip to content

Commit

Permalink
Merge e5354dd into 9915d43
Browse files Browse the repository at this point in the history
  • Loading branch information
Ramadhan0 committed Jun 24, 2019
2 parents 9915d43 + e5354dd commit 8eba245
Show file tree
Hide file tree
Showing 17 changed files with 470 additions and 11 deletions.
22 changes: 20 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,28 @@ TOKEN_KEY=TheTokenKey
MAILER_API_KEY=theTokenOfTheMailerService
MAILER_EMAIL=theEmailUsedByTheMailerAsSender
API_BASE_URL=theApiBaseUrlToInsertInTheLinksSharedInEmails
TOKEN_KEY=TheTokenKey

BCRYPT_HASH_ROUNDS=theBcryptSaltingRounds



FACEBOOK_CLIENT_ID=theFacebookAppId
FACEBOOK_CLIENT_SECRET=theFacebookAppSecret
FACEBOOK_CALLBACK=http://www.example.com/users/facebook/callback

GOOGLE_CLIENT_ID=theGoogleAppId
GOOGLE_CLIENT_SECRET=theGoogleAppSecret
GOOGLE_CALLBACK=http://www.example.com/users/google/callback


TWITTER_CLIENT_ID=theTwitterClientId
TWITTER_CONSUMER_SECRET=theTwitterConsumerSecret
TWITTER_CALLBACK=http://www.example.com/users/twitter/callback

TWITTER_SESSION_KEY=theTwitterSessionKey


USERNAME=thePostgresUsername
PASSWORD=TheDatabasePassword
USERNAME=thePostgresUsername
PASSWORD=TheDatabasePassword
DEV_DATABASE=theDevelopementDbName
Expand Down
6 changes: 3 additions & 3 deletions .hound.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
fail_on_violations: true
eslint:
enabled: true
config_file: .eslintrc.json
ignore_file: .eslintignore
enabled: true
config_file: .eslintrc.json
ignore_file: .eslintignore
13 changes: 13 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"main": "index.js",
"scripts": {
"start": "babel-node src/index.js",
"setup": "NODE_ENV=test npm run migrate:undo && NODE_ENV=test npm run migrate && NODE_ENV=test npm run seed",
"test": "npm run setup:test && NODE_ENV=test nyc --reporter=html --reporter=text --reporter=lcov ./node_modules/.bin/mocha ./tests/* --require @babel/register --timeout 4000 --exit",
"dev": "NODE_ENV=development nodemon --exec babel-node src/index.js",
"coverage": "nyc report --reporter=text-lcov | coveralls",
Expand Down Expand Up @@ -51,6 +52,15 @@
"dotenv": "^8.0.0",
"expect": "^24.8.0",
"express": "^4.16.4",
"express-session": "^1.16.2",
"passport": "^0.4.0",
"passport-facebook": "^3.0.0",
"passport-google-oauth": "^2.0.0",
"passport-pinterest": "^1.0.0",
"passport-twitter": "^1.0.4",
"sinon": "^7.3.2",
"sinon-chai": "^3.3.0",
"joi": "^14.3.1",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.11",
"morgan": "^1.9.1",
Expand All @@ -68,6 +78,9 @@
"functions": 100,
"statements": 80,
"exclude": [
"src/configs/environments.js",
"src/index.js",
"src/configs/passport.js",
"src/index.js"
]
},
Expand Down
2 changes: 1 addition & 1 deletion src/api/controllers/authController.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import bcrypt, { hashSync, genSaltSync } from 'bcrypt';
import models from '../models/index';
import models from '../models';
import generateToken from '../../helpers/tokens/generate.token';
import sendResult from '../../helpers/results/send.auth';
import status from '../../helpers/constants/status.codes';
Expand Down
118 changes: 118 additions & 0 deletions src/api/controllers/socialAuth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import module from '../models';
import generateToken from '../../helpers/tokens/generate.token';
import status from '../../helpers/constants/status.codes';

const { User } = module;

/**
*
*
* @class socialLogin
*/
class socialLogin {
/**
* signup || login via facebook
*
* @static
* @param {object} req - request object
* @param {object} res - response object
* @memberof socialLogin
* @returns {object} - the response body
*
*/
static async facebookAuth(req, res) {
let existingUser = await User.findOne({
where: {
uniqueId: req.user.id
}
});
if (!existingUser) {
existingUser = await User.create({
username: req.user.name.familyName,
profileImage: req.user.photos[0].value,
provider: req.user.provider,
uniqueId: req.user.id
});
}
const token = generateToken({
id: existingUser.dataValues.id,
username: existingUser.dataValues.username
},
process.env.TOKEN_KEY);
return res.status(status.CREATED).json({ user: { ...existingUser.get(), token } });
}

/**
* signup || login via Google
*
* @static
* @param {object} req - request object
* @param {object} res - request response
* @memberof socialLogin
* @returns {object} - the response body
*
*/
static async googleAuth(req, res) {
let existingUser = await User.findOne({
where: {
uniqueId: req.user.id
}
});
if (!existingUser) {
existingUser = User.create({
username: req.user.displayName,
email: req.user.emails[0].value,
profileImage: req.user.photos[0].value,
provider: req.user.provider,
uniqueId: req.user.id
});
console.log(existingUser.dataValues);
const token = generateToken({ username: req.user.displayName, id: req.user.id },
process.env.TOKEN_KEY);
return res.status(status.CREATED).json({ user: { ...existingUser.get(), token } });
}
const token = generateToken({
id: existingUser.dataValues.id,
username: existingUser.dataValues.username
},
process.env.TOKEN_KEY);
return res.status(status.CREATED).json({ user: { ...existingUser.get(), token } });
}

/**
* signup || login user via Twitter
*
* @static
* @param {object} req - request object
* @param {object} res - request response
* @memberof socialLogin
* @returns {object} - the response body
*
*/
static async twitterAuth(req, res) {
let existingUser = await User.findOne({
where: {
uniqueId: req.user.id
}
});
if (!existingUser) {
existingUser = User.create({
username: req.user.username,
profileImage: req.user.photos[0].value,
provider: req.user.provider,
uniqueId: req.user.id
});
const token = generateToken({ username: req.user.displayName, id: req.user.id },
process.env.TOKEN_KEY);
return res.status(status.CREATED).json({ user: { ...existingUser.get(), token } });
}
const token = generateToken({
id: existingUser.dataValues.id,
username: existingUser.dataValues.username
},
process.env.TOKEN_KEY);
return res.status(status.CREATED).json({ user: { ...existingUser.get(), token } });
}
}

export default socialLogin;
4 changes: 2 additions & 2 deletions src/api/migrations/20190620192200-create-user.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ export default {
type: Sequelize.INTEGER
},
username: {
type: Sequelize.STRING,
unique: true
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING,
Expand Down Expand Up @@ -68,5 +67,6 @@ export default {
type: Sequelize.DATE
}
}),
// eslint-disable-next-line no-unused-vars
down: (queryInterface, Sequelize) => queryInterface.dropTable('Users')
};
51 changes: 51 additions & 0 deletions src/api/migrations/20190624064739-create-test-articl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
export default {
up: (queryInterface, Sequelize) => queryInterface.createTable('Articles', {
id: {
allowNull: false,
unique: true,
primaryKey: true,
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4
},
title: {
type: Sequelize.STRING,
allowNull: false
},
slug: {
type: Sequelize.STRING,
allowNull: false,
unique: true
},
description: {
type: Sequelize.STRING,
allowNull: false
},
body: {
type: Sequelize.TEXT,
allowNull: false
},
tagList: {
type: Sequelize.ARRAY(Sequelize.TEXT),
allowNull: false
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
},
userId: {
type: Sequelize.INTEGER,
references: {
model: 'Users',
key: 'id'
},
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
allowNull: false
}
}),
down: (queryInterface, Sequelize) => queryInterface.dropTable('Articles')
};
10 changes: 10 additions & 0 deletions src/api/models/test-articl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict';
module.exports = (sequelize, DataTypes) => {
const test - articl = sequelize.define('test-articl', {
name: DataTypes.STRING
}, {});
test - articl.associate = function(models) {
// associations can be defined here
};
return test - articl;
};
1 change: 0 additions & 1 deletion src/api/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,5 @@ export default (sequelize, DataTypes) => {

return queryResult;
};

return User;
};
22 changes: 22 additions & 0 deletions src/api/routes/authRouter.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@
import { Router } from 'express';
import ValidateUser from '../../middlewares/ValidateUser';
import authController from '../controllers/authController';
import socialAuthController from '../controllers/socialAuth';
import passport from '../../configs/passport';
import social from '../../middlewares/social/social';

const authRouter = new Router();

authRouter.post('/signup', ValidateUser.validateSignup, authController.signup);
authRouter.post('/login', authController.login);

authRouter.post('/mockFacebook', social, socialAuthController.facebookAuth);
authRouter.post('/mockGoogle', social, socialAuthController.googleAuth);
authRouter.post('/mockTwitter', social, socialAuthController.twitterAuth);

authRouter.get('/facebook', passport.authenticate('facebook'));
authRouter.get('/facebook/callback',
passport.authenticate('facebook'),
socialAuthController.facebookAuth);

authRouter.get('/google', passport.authenticate('google', { scope: ['email', 'profile'] }));
authRouter.get('/google/callback',
passport.authenticate('google'),
socialAuthController.googleAuth);

authRouter.get('/twitter', passport.authenticate('twitter', { scope: ['email', 'profile'] }));
authRouter.get('/twitter/callback',
passport.authenticate('twitter'),
socialAuthController.twitterAuth);

export default authRouter;
5 changes: 4 additions & 1 deletion src/configs/environments.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dotenv/config';
import dotenv from 'dotenv';

dotenv.config();
const appPort = process.env.PORT;
const env = process.env.NODE_ENV;
const jwtSecret = process.env.TOKEN_KEY;
Expand Down Expand Up @@ -70,6 +71,7 @@ const environments = [
secret: jwtSecret,
mailerEmail,
mailerToken,

baseUrl,
hashRounds,
username,
Expand All @@ -82,4 +84,5 @@ const environments = [
];

const currentEnv = environments.find(el => el.name === env.toLocaleLowerCase());

module.exports = currentEnv;
47 changes: 47 additions & 0 deletions src/configs/passport.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import passport from 'passport';
import FacebookStrategy from 'passport-facebook';
import { OAuth2Strategy } from 'passport-google-oauth';
import TwitterStrategy from 'passport-twitter';

const {
GOOGLE_CLIENT_ID,
GOOGLE_CLIENT_SECRET,
GOOGLE_CALLBACK,
FACEBOOK_CLIENT_ID,
FACEBOOK_CLIENT_SECRET,
FACEBOOK_CALLBACK,
TWITTER_CLIENT_ID,
TWITTER_CLIENT_SECRET,
TWITTER_CALLBACK
} = process.env;

passport.use(new OAuth2Strategy({
clientID: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
callbackURL: GOOGLE_CALLBACK,
profileFields: ['name', 'photos', 'email']
},
(accessToken, refreshToken, profile, done) => done(null, profile)));

passport.use(new FacebookStrategy({
clientID: FACEBOOK_CLIENT_ID,
clientSecret: FACEBOOK_CLIENT_SECRET,
callbackURL: FACEBOOK_CALLBACK,
profileFields: ['name', 'photos', 'email']
},
(accessToken, refreshTocken, profile, done) => done(null, profile)));

passport.use(new TwitterStrategy({
consumerKey: TWITTER_CLIENT_ID,
consumerSecret: TWITTER_CLIENT_SECRET,
callbackURL: TWITTER_CALLBACK,
profile: ['name', 'photo', 'email']
},
(accessToken, refreshTocken, profile, done) => {
done(null, profile);
}));

passport.serializeUser((user, done) => done(null, user));
passport.deserializeUser((user, done) => done(null, user));

export default passport;
Loading

0 comments on commit 8eba245

Please sign in to comment.