Skip to content

Commit

Permalink
[ft-#166240824] enable login via Facebook, Google, Twitter
Browse files Browse the repository at this point in the history
  • Loading branch information
Ramadhan authored and Ramadhan committed Jun 13, 2019
2 parents 9e77be6 + db9436e commit 012a090
Show file tree
Hide file tree
Showing 28 changed files with 498 additions and 215 deletions.
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ DB_URL=TheProductionDatabaseConnectionUrl__Format:postgres://user:pass@host:5432
FACEBOOK passport
clientID=FACEBOOK_APP_ID,
clientSecret=FACEBOOK_APP_SECRET,
callbackURL="http://www.example.com/auth/facebook/callback"
callbackURL="http://www.example.com/auth/facebook/callback"
TOKEN_KEY=TheTokenKey
16 changes: 8 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
language: node_js
node_js:
- stable
- stable
cache:
directories:
- "node_modules"
- "node_modules"
before_script:
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64
> ./cc-test-reporter
- chmod +x ./cc-test-reporter
- "./cc-test-reporter before-build"
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64
/cc-test-reporter
- chmod +x ./cc-test-reporter
- "./cc-test-reporter before-build"
script:
- npm test
- npm test
after_script:
- "./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT"
- "./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT"
deploy:
provider: heroku
api_key:
Expand Down
16 changes: 9 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "index.js",
"scripts": {
"start": "babel-node src/index.js",
"test": "NODE_ENV=test nyc --reporter=html --reporter=text --reporter=lcov ./node_modules/.bin/mocha ./test/* --require @babel/register --exit",
"test": "NODE_ENV=test nyc --reporter=html --reporter=text --reporter=lcov ./node_modules/.bin/mocha --exclude src/index.js ./test/* --require @babel/register --exit",
"dev": "nodemon --exec babel-node src/index.js",
"coverage": "nyc report --reporter=text-lcov | coveralls"
},
Expand All @@ -28,8 +28,9 @@
"@babel/preset-env": "^7.4.5",
"@babel/register": "^7.4.4",
"babel-plugin-istanbul": "^5.1.2",
"babel-polyfill": "^6.26.0",
"bcrypt": "^3.0.6",
"body-parser": "^1.18.3",
"chai-http": "^4.3.0",
"cors": "^2.8.5",
"dotenv": "^8.0.0",
"expect": "^24.8.0",
Expand All @@ -44,18 +45,19 @@
"passport-twitter": "^1.0.4",
"pg": "^7.11.0",
"sequelize": "^5.8.7",
"sinon": "^7.3.2",
"sinon-chai": "^3.3.0",
"swagger-node-express": "^2.1.3",
"swagger-ui-express": "^4.0.6"
},
"nyc": {
"per-file": true,
"check-coverage": true,
"branches": 50,
"branches": 80,
"lines": 80,
"functions": 80,
"statements": 80
"functions": 100,
"statements": 80,
"exclude": [
"src/index.js"
]
},
"author": "Andela Simulations Programme",
"license": "MIT"
Expand Down
66 changes: 66 additions & 0 deletions src/api/controllers/authController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import bcrypt, { hashSync, genSaltSync } from 'bcrypt';
import models from '../models/index';
import generateToken from '../../helpers/tokens/generate.token';
import sendResult from '../../helpers/results/send.auth';

const { User } = models;

/**
* containing all user's model controllers (signup, login)
*
* @export
* @class Auth
*/
export default class Auth {
/**
* register a new user
*
* @static
* @param {*} req the request
* @param {*} res the response to be sent
* @memberof Auth
* @returns {Object} res
*/
static async signup(req, res) {
const { username, email, password } = req.body;
const salt = genSaltSync(parseFloat(process.env.BCRYPT_HASH_ROUNDS) || 10);
const hashedPassword = hashSync(password, salt);
const user = await User.create({
username,
email,
password: hashedPassword
});
const tokenData = { username, email };
const token = generateToken(tokenData, process.env.TOKEN_KEY);
return sendResult(res, 201, 'user created successfully', user, token);
}

/**
*login an existing user
*
* @static
* @param {*} req the request
* @param {*} res the response to be sent
* @memberof Auth
* @returns {Object} res
*/
static login(req, res) {
const { email, password } = req.body;
User.findByEmail(email).then((user) => {
if (user) {
const isPasswordValid = bcrypt.compareSync(password, user.dataValues.password);
if (isPasswordValid) {
const tokenData = { username: user.dataValues.username, email };
const token = generateToken(tokenData, process.env.TOKEN_KEY);
return sendResult(res, 200, 'user logged in successfully', user, token);
}
return res.status(401).json({
message: 'password is incorrect'
});
}
return res.status(404).json({
message: "user doesn't exist"
});
});
}
}
32 changes: 17 additions & 15 deletions src/api/controllers/socialAuth.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import jwt from 'jsonwebtoken';
import model from '../models';
import generateToken from '../../helpers/tokens/generate.token';

const { User } = model;

Expand All @@ -26,17 +26,15 @@ class socialLogin {
}
});
if (!findIfExist) {
findIfExist = User.create({
firstName: req.user.name.givenName,
lastName: req.user.name.familyName,
userName: req.user.username,
findIfExist = await User.create({
username: req.user.name.familyName,
profileImage: req.user.photos[0].value,
provider: req.user.provider,
uniqueId: req.user.id
});
}
const token = jwt.sign({ id: findIfExist.id }, 'secret', { expiresIn: '1d' });
res.json({ user: { ...findIfExist.get(), token } });
const token = generateToken(findIfExist, process.env.TOKEN_KEY);
return res.status(200).json({ user: { ...findIfExist.get(), token } });
}

/**
Expand All @@ -57,17 +55,18 @@ class socialLogin {
});
if (!findIfExist) {
findIfExist = User.create({
firstName: req.user.name.familyName,
lastName: req.user.name.givenName,
userName: req.user.displayName,
username: req.user.displayName,
email: req.user.emails[0].value,
profileImage: req.user.photos[0].value,
provider: req.user.provider,
uniqueId: req.user.id
});
} else {
const token = 'generateToken(findIfExist, process.env.TOKEN_KEY)';
return res.status(200).json({ token });
}
const token = jwt.sign({ id: findIfExist.id }, 'secret', { expiresIn: '1d' });
res.json({ user: { ...findIfExist.get(), token } });
const token = generateToken(findIfExist, process.env.TOKEN_KEY);
return res.status(200).json({ user: { ...findIfExist.get(), token } });
}

/**
Expand All @@ -88,14 +87,17 @@ class socialLogin {
});
if (!findIfExist) {
findIfExist = User.create({
userName: req.user.username,
username: req.user.username,
profileImage: req.user.photos[0].value,
provider: req.user.provider,
uniqueId: req.user.id
});
} else {
const token = 'generateToken(findIfExist, process.env.TOKEN_KEY)';
return res.status(200).json({ token });
}
const token = jwt.sign({ id: findIfExist.id }, 'secret', { expiresIn: '1d' });
res.json({ user: { ...findIfExist.get(), token } });
const token = generateToken(findIfExist, process.env.TOKEN_KEY);
return res.status(200).json({ user: { ...findIfExist.get(), token } });
}
}

Expand Down
12 changes: 3 additions & 9 deletions src/api/models/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Sequelize from 'sequelize';
import { currentEnv } from '../../configs/environnements';
import { currentEnv } from '../../configs/environments';

const env = currentEnv;

Expand All @@ -8,16 +8,10 @@ const sequelize = new Sequelize(env.dbUrl, {
});

const models = {
Test: sequelize.import('./test'),
User: sequelize.import('./user')
User: sequelize.import('./user'),
Token: sequelize.import('./token')
};

Object.keys(models).forEach((key) => {
if ('associate' in models[key]) {
models[key].associate(models);
}
});

export { sequelize };

export default models;
9 changes: 0 additions & 9 deletions src/api/models/test.js

This file was deleted.

10 changes: 10 additions & 0 deletions src/api/models/token.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const token = (sequelize, DataTypes) => {
const Token = sequelize.define('Tokens', {
data: {
type: DataTypes.TEXT,
}
});
return Token;
};

export default token;
27 changes: 17 additions & 10 deletions src/api/models/user.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
const user = (sequelize, DataTypes) => {
const User = sequelize.define('user', {
firstName: {
const User = sequelize.define('Users', {
username: {
type: DataTypes.STRING,
allowNull: true
},
lastName: {
type: DataTypes.STRING,
allowNull: true
},
userName: {
email: {
type: DataTypes.STRING,
allowNull: true
},
email: {
password: {
type: DataTypes.STRING,
allowNull: true
},
Expand All @@ -22,14 +18,25 @@ const user = (sequelize, DataTypes) => {
},
provider: {
type: DataTypes.STRING,
allowNull: false
allowNull: true
},
uniqueId: {
type: DataTypes.STRING,
allowNull: false
allowNull: true
},
verified: {
type: DataTypes.BOOLEAN,
defaultValue: true
}
});

User.findByEmail = (email) => {
const queryResult = User.findOne({
where: { email }
});

return queryResult;
};
return User;
};

Expand Down
10 changes: 10 additions & 0 deletions src/api/routes/authRouter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Router } from 'express';
import authController from '../controllers/authController';

const authRouter = Router();

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


export default authRouter;
12 changes: 0 additions & 12 deletions src/api/routes/db.test.js

This file was deleted.

8 changes: 4 additions & 4 deletions src/api/routes/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import express from 'express';
import dbTestRouter from './db.test';
import authRouter from './authRouter';

const v2router = express();
const router = express();

v2router.use('/dbTest', dbTestRouter);
router.use('/auth', authRouter);

export default v2router;
export default router;
2 changes: 1 addition & 1 deletion src/api/routes/passport/facebook.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import express from 'express';
import { passport } from '../../../configs/environnements';
import { passport } from '../../../configs/environments';
import socialLogin from '../../controllers/socialAuth';

// Declaring the app
Expand Down
2 changes: 1 addition & 1 deletion src/api/routes/passport/google.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import express from 'express';
import { passport } from '../../../configs/environnements';
import { passport } from '../../../configs/environments';
import socialLogin from '../../controllers/socialAuth';
// Declaring the app
const googleRouter = express();
Expand Down
2 changes: 1 addition & 1 deletion src/api/routes/passport/twitter.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import express from 'express';
import { passport } from '../../../configs/environnements';
import { passport } from '../../../configs/environments';
import socialLogin from '../../controllers/socialAuth';
// Declaring the app
const twitterRouter = express();
Expand Down
Loading

0 comments on commit 012a090

Please sign in to comment.