Skip to content

Commit

Permalink
Merge branch 'feature/166816206-social-login' of https://github.com/a…
Browse files Browse the repository at this point in the history
…ndela/demeter-ah-backend into feature/166816206-social-login
  • Loading branch information
fantastic-genius committed Jul 5, 2019
2 parents 83aead2 + 678f3ca commit 9bd681a
Show file tree
Hide file tree
Showing 23 changed files with 785 additions and 97 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"one-var": 0,
"one-var-declaration-per-line": 0,
"new-cap": 0,
"consistent-return": 0,
"consistent-return": 0,
"no-console": "off",
"no-param-reassign": 0,
"comma-dangle": 0,
"curly": ["error", "multi-line"],
Expand Down
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,4 @@ node_modules
# Optional REPL history
.node_repl_history

#nyc output
.nyc_output
.nyc_output
11 changes: 11 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ cache:
env:
global:
- NODE_ENV=test
- FACEBOOK_APP_ID=414345019166283
- FACEBOOK_SECRET=42c013c3adb4617c4d231ca11576fd21
- FACEBOOK_CALLBACk=http://localhost:5000/auth/facebook/callback
- TWITTER_KEY=zgwMUevHI3lQy8rHEbLnFZ0Xu
- TWITTER_SECRET=ZjILyBUlWQh6EjcNZdjuPOTiwGPOUHTBp2IJ4TaUrrQmqX4iGB
- TWITTER_CALLBACk=http://localhost:5000/auth/twitter/callback
- SESSION_SECRET=secret
- GOOGLE_CLIENT_ID=437904595396-ktobr2fr8tuhed3f8ojatg6d0f4h7ibp.apps.googleusercontent.com
- GOOGLE_CLIENT_SECRET=mGJz_ZmBNaf6b1gqi95sDVk3
- BASE_URL=http://localhost:5000
- GOOGLE_CALLBACK=auth/google/callback
before_script:
- psql -c 'create database haventest;' -U postgres
services:
Expand Down
89 changes: 86 additions & 3 deletions controllers/users/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import Sequelize from 'sequelize';
import db from '../../db/models';
import { blackListThisToken } from '../../utils';
import {
blackListThisToken, randomString, hashPassword, getToken
} from '../../utils';
import { sendMail } from '../../utils/mailer';
import { resetPasswordMessage } from '../../utils/mailer/mails';

export default {
signUp: async (req, res) => {
Expand All @@ -14,11 +19,13 @@ export default {
email,
username
});
user.response.token = getToken(user.id, user.email);
return res.status(201).json({
message: 'User Registration successful',
user: user.response()
});
} catch (e) {
console.log('message', e);
return res.status(500).json({
message: 'Something went wrong'
});
Expand Down Expand Up @@ -52,12 +59,88 @@ export default {
});
}
},

signOut: async (req, res) => {
const token = req.headers['x-access-token'];
await blackListThisToken(token);
return res.status(200).send({
message: 'Thank you'
message: 'Signed out successfully'
});
},
resetPassword: async (req, res) => {
const { email } = req.body;
try {
const user = await db.User.findOne({ where: { email } });
if (user) {
const passwordResetToken = randomString();
const date = new Date();
date.setHours(date.getHours() + 2);
user.update({ passwordResetToken, passwordResetExpire: date });
await sendMail({
email: user.email,
subject: 'Password Reset LInk',
content: resetPasswordMessage(user.email, passwordResetToken)
});
return res.status(200).json({
message: 'Password reset successful. Check your email for password reset link!'
});
}
throw new Error('User not found');
} catch (err) {
return res.status(400).json({
message: 'User does not exist'
});
}
},

activate: async (req, res) => {
try {
const user = await db.User.findOne({
where: { emailVerificationToken: req.params.token, activated: false }
});
if (user) {
await user.update({ activated: true, emailVerificationToken: null });
return res.status(200).json({
message: 'Activation successful, You can now login',
user: user.response()
});
}
return res.status(400).json({
error: 'Invalid activation Link'
});
} catch (e) {
return res.status(400).json({
message: 'Bad request'
});
}
},

changePassword: async (req, res) => {
const { password } = req.body;
const { Op } = Sequelize;

const passwordHash = await hashPassword(password);

const { resetToken } = req.query;
try {
const user = await db.User.findOne({
where: {
passwordResetToken: resetToken,
passwordResetExpire: {
[Op.gt]: new Date()
}
}
});
if (user) {
user.update({ password: passwordHash, resetToken: null, resetExpire: null });
return res.status(200).json({
message: 'Password has successfully been changed.'
});
}
throw new Error('Invalid operation');
} catch (err) {
return res.status(400).json({
message: 'Bad request'
});
}
}
};
8 changes: 4 additions & 4 deletions db/config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ module.exports = {
development: {
use_env_variable: 'DATABASE_URL',
dialect: 'postgres',
logging: false
logging: false,
},
test: {
use_env_variable: 'TEST_DATABASE_URL',
dialect: 'postgres',
logging: false
logging: false,
},
production: {
use_env_variable: 'DATABASE_URL',
dialect: 'postgres',
logging: false
}
logging: false,
},
};
6 changes: 4 additions & 2 deletions db/migrations/20190627191529-create-user.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ module.exports = {
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
type: Sequelize.DATE,
defaultValue: Sequelize.literal('NOW()')
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
type: Sequelize.DATE,
defaultValue: Sequelize.literal('NOW()')
}
}),
down: queryInterface => queryInterface.dropTable('Users')
Expand Down
37 changes: 37 additions & 0 deletions db/migrations/20190701141832-create-articles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module.exports = {
up: (queryInterface, Sequelize) => queryInterface.createTable('Articles', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
title: {
type: Sequelize.STRING
},
description: {
type: Sequelize.TEXT
},
slug: {
type: Sequelize.STRING
},
body: {
type: Sequelize.TEXT
},
images: {
type: Sequelize.STRING
},
userId: {
type: Sequelize.INTEGER
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
}),
down: queryInterface => queryInterface.dropTable('articles')
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@


module.exports = {
up: (queryInterface, Sequelize) => queryInterface
.addColumn('Users', 'emailVerificationToken', {
type: Sequelize.STRING,
allowNull: true
})
.then(() => queryInterface.addColumn('Users', 'activated', {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false
})),
down: queryInterface => queryInterface
.removeColumn('Users', 'emailVerificationToken')
.then(() => queryInterface.removeColumn('Users', 'activated'))
};
12 changes: 12 additions & 0 deletions db/migrations/alter_users_table.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module.exports = {
up: (queryInterface, Sequelize) => queryInterface
.addColumn('Users', 'passwordResetToken', {
type: Sequelize.STRING,
allowNull: true,
})
.then(() => queryInterface.addColumn('Users', 'passwordResetExpire', {
type: Sequelize.DATE,
allowNull: true,
})),
down: queryInterface => queryInterface.removeColumn('Users', 'passwordResetToken').then(() => queryInterface.removeColumn('Users', 'passwordResetExpire')),
};
20 changes: 20 additions & 0 deletions db/models/Article.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import SequelizeSlugify from 'sequelize-slugify';

module.exports = (sequelize, DataTypes) => {
const Article = sequelize.define('Article', {
title: DataTypes.STRING,
description: DataTypes.TEXT,
slug: DataTypes.STRING,
body: DataTypes.TEXT,
images: DataTypes.STRING
}, {});

SequelizeSlugify.slugifyModel(Article, {
source: ['title'],
slugOptions: { lower: true },
overwrite: false,
column: 'slug'
});
Article.associate = models => Article.belongsTo(models.User);
return Article;
};
28 changes: 26 additions & 2 deletions db/models/User.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import bcrypt from 'bcryptjs';
import { getToken } from '../../utils';
import { getToken, randomString } from '../../utils';
import { sendMail } from '../../utils/mailer';
import { activationMessage } from '../../utils/mailer/mails';

module.exports = (sequelize, DataTypes) => {
const User = sequelize.define(
Expand All @@ -12,16 +14,38 @@ module.exports = (sequelize, DataTypes) => {
firstName: DataTypes.STRING,
lastName: DataTypes.STRING,
password: DataTypes.STRING,
social: DataTypes.BOOLEAN
social: DataTypes.BOOLEAN,
passwordResetToken: DataTypes.STRING,
passwordResetExpire: DataTypes.DATE,
emailVerificationToken: DataTypes.STRING,
activated: {
type: DataTypes.BOOLEAN,
default: false
}
},
{
hooks: {
beforeCreate: async (user) => {
user.password = !user.social ? await bcrypt.hash(user.password, 10) : null;
user.emailVerificationToken = !user.social ? randomString() : null;
},
afterCreate: async (user) => {
if (!user.social) {
await sendMail({
email: user.email,
subject: 'Activate Account',
content: activationMessage(user.email, user.emailVerificationToken)
});
}
}
}
}
);
User.associate = models => User.hasMany(models.Article, {
foreignKey: 'userId',
cascade: true
});

User.prototype.passwordsMatch = function match(password) {
return bcrypt.compare(password, this.password);
};
Expand Down
21 changes: 21 additions & 0 deletions db/seeders/20190701143128-users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import bcrypt from 'bcryptjs';

const password = bcrypt.hash('12345678', 10);

module.exports = {
up: queryInterface => queryInterface.bulkInsert('Users', [{
firstName: 'John',
lastName: 'Doe',
username: 'john',
password,
email: 'john@haven.com'
},
{
firstName: 'James',
lastName: 'Mark',
username: 'james',
password,
email: 'james@haven.com'
}], {}),
down: queryInterface => queryInterface.bulkDelete('User', null, {})
};
13 changes: 7 additions & 6 deletions env-sample
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ DATABASE_URL=
TEST_DATABASE_URL=
NODE_ENV=
SECRET=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
BASE_URL=
FACEBOOK_APP_ID=
FACEBOOK_SECRET=
FACEBOOK_CALLBACk=
TWITTER_CALLBACk=
TWITTER_SECRET=
TWITTER_KEY=

TWITTER_SECRET=
TWITTER_CALLBACk=
SESSION_SECRET=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
BASE_URL=
GOOGLE_CALLBACK=
Loading

0 comments on commit 9bd681a

Please sign in to comment.