Skip to content

Commit

Permalink
Merge ac2f069 into 9ebeac8
Browse files Browse the repository at this point in the history
  • Loading branch information
codeBlock-1984 committed Jul 23, 2019
2 parents 9ebeac8 + ac2f069 commit 397756f
Show file tree
Hide file tree
Showing 15 changed files with 126 additions and 10 deletions.
12 changes: 7 additions & 5 deletions src/controllers/authController.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ class AuthController {
*/
static async createAccount(req, res) {
try {
const { userName, email, password } = req.body;
const { userName, email, password, userRole } = req.body;
const hashedpassword = hashPassword(password);
const values = { userName, email, password: hashedpassword };

const role = userRole || 'user';
const values = { userName, email, password: hashedpassword, role };
const result = await User.create(values);
const { id, isVerified } = result;
const token = await generateToken({ id, email, isVerified });
const token = await generateToken({ id, email, isVerified, role });

const url = `${req.protocol}://${req.get('host')}/api/v1/auth/verify/${token}`;
const message = template(userName, url);
Expand Down Expand Up @@ -115,8 +117,8 @@ class AuthController {
const result = await User.findOne({ where: { email } });
if (result) {
if (bcrypt.compareSync(password, result.password)) {
const { id, isVerified } = result;
const token = await generateToken({ id, email, isVerified });
const { id, isVerified, role } = result;
const token = await generateToken({ id, email, isVerified, role });

const user = {
id: result.id,
Expand Down
1 change: 0 additions & 1 deletion src/controllers/reportController.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ class ReportController {
status: 201,
message: `${reportType} successfully reported`
});

} catch (error) {
return res.status(500).json({
status: 500,
Expand Down
6 changes: 6 additions & 0 deletions src/db/migrations/20190701154222-create-user.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ module.exports = {
required: false,
defaultValue: false,
},
role: {
type: Sequelize.ENUM(['superAdmin', 'admin', 'user']),
required: true,
allowNull: false,
defaultValue: 'user',
},
imageUrl: {
type: Sequelize.STRING,
required: false,
Expand Down
3 changes: 3 additions & 0 deletions src/db/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ module.exports = (sequelize, DataTypes) => {
bio: {
type: DataTypes.STRING,
},
role: {
type: DataTypes.ENUM(['superAdmin', 'admin', 'user']),
},
imageUrl: {
type: DataTypes.STRING,
required: false,
Expand Down
3 changes: 3 additions & 0 deletions src/db/seeders/20190701155734-user.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = {
email: 'john.doe@andela.com',
bio: 'local man is stuck in traffic',
isVerified: true,
role: 'superAdmin',
password: hash,
verificationToken: '',
imageUrl: 'image.png'
Expand All @@ -21,6 +22,7 @@ module.exports = {
email: 'cavdyofficials@gmail.com',
bio: '#ghost',
isVerified: true,
role: 'admin',
password: 'password',
verificationToken: '',
imageUrl: 'image.png'
Expand All @@ -31,6 +33,7 @@ module.exports = {
email: 'john.doe2@andela.com',
bio: 'local man is stuck in traffic',
isVerified: true,
role: 'user',
password: 'password',
verificationToken: '',
imageUrl: 'image.png'
Expand Down
5 changes: 5 additions & 0 deletions src/helpers/helperData/roles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const roles = {
allRoles: ['superAdmin', 'admin', 'user'],
};

export default roles;
23 changes: 22 additions & 1 deletion src/middleware/authValidator.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { body, check } from 'express-validator';
import { body, check, sanitizeBody } from 'express-validator';

const authValidator = {
passwordValidator: [
Expand All @@ -20,6 +20,27 @@ const authValidator = {
.normalizeEmail()
.withMessage('Invalid email address.'),
],
roleValidator: [
sanitizeBody('userRole')
.customSanitizer(value => {
if (value) {
return value.toLowerCase();
}
}),
body('userRole')
.trim()
.exists({ checkNull: false, checkFalsy: false })
.isIn(['superadmin', 'admin', 'user', ''])
.withMessage('Invalid userRole.'),
sanitizeBody('userRole')
.customSanitizer(value => {
if (value === 'superadmin') {
const role = value.replace('a', 'A');
return role;
}
return value;
}),
],
usernameValidator: [
body('userName')
.trim()
Expand Down
26 changes: 26 additions & 0 deletions src/middleware/authorize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { User } from '../db/models';

const authorize = (roles) => {

return (async (req, res, next) => {
const id = req.user;

const { role } = await User.findOne({
where: {
id
}
});

const isPermitted = roles.includes(role);
if (!isPermitted) {
return res.status(403).json({
status: 403,
message: `You don't have permission to perform this request`
});
}
return next();
});

};

export default authorize;
14 changes: 13 additions & 1 deletion src/routes/articleRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,33 @@ import ArticleController from '../controllers/articleController';
import validateSearchInput from '../middleware/searchInputValidator';
import articleValidator from '../middleware/articleValidator';
import validate from '../middleware/validate';
import authorize from '../middleware/authorize';
import upload from '../helpers/profilePic';
import verify from '../helpers/verifyToken';
import findItem from '../helpers/findItem';
import checkCategoryExists from '../middleware/checkCategoryExists';
import roles from '../helpers/helperData/roles';

const router = express.Router();
const { createArticle, getArticle } = ArticleController;
const { detailsValidator } = articleValidator;
const { allRoles } = roles;

router.get('/articles', validateSearchInput, ArticleController.search);
router.get(
'/articles/:slug',
findItem.findArticle,
getArticle
);
router.post('/articles/', verify, upload.array('images', 10), detailsValidator, validate, checkCategoryExists, createArticle);
router.post(
'/articles/',
verify,
authorize(allRoles),
upload.array('images', 10),
detailsValidator,
validate,
checkCategoryExists,
createArticle
);

export default router;
3 changes: 2 additions & 1 deletion src/routes/authRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ import findItem from '../helpers/findItem';

const router = express.Router();

const { usernameValidator, emailValidator, passwordValidator } = authValidator;
const { usernameValidator, roleValidator, emailValidator, passwordValidator } = authValidator;
const { checkExistingUser } = checkDuplicate;

router.post('/signup',
usernameValidator,
emailValidator,
roleValidator,
passwordValidator,
validate,
checkExistingUser,
Expand Down
1 change: 1 addition & 0 deletions src/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ router.use('/api/v1', bookmarkRoute);
router.use('/api/v1', tagRoute);
router.use('/api/v1', reportRoute);


export default router;
11 changes: 11 additions & 0 deletions test/article.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,17 @@ describe('Articles', () => {
});
});

it('should create article if isDraft is empty', (done) => {
const { isDraft, ...partialArticleDetails } = testArticle;
chai.request(app).post('/api/v1/articles')
.set('token', testToken)
.send(partialArticleDetails)
.end((err, res) => {
res.should.have.status(201);
done();
});
});

it('should return 400 error if article body is empty', (done) => {
const { body, ...partialArticleDetails } = testArticle;
chai.request(app).post('/api/v1/articles')
Expand Down
3 changes: 2 additions & 1 deletion test/auth.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ describe('Auth', () => {
const defaultUser = {
userName: 'jamie',
email: 'main.jane@gmail.com',
password: 'password'
password: 'password',
userRole: 'SUPERADMIN'
};
it(('should signup a user'), (done) => {
chai.request(app).post('/api/v1/auth/signup')
Expand Down
11 changes: 11 additions & 0 deletions test/authorize.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import chai from 'chai';
import authorize from '../src/middleware/authorize';

chai.should();

describe('authorize', () => {
it('should return a function', () => {
const result = authorize(['user', 'admin']);
result.should.be.a('function');
});
});
14 changes: 14 additions & 0 deletions test/report.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,19 @@ describe('Reports', () => {
done();
});
});

it('should return 404 error if comment does not exist', (done) => {
const invalidReport = { ...testReport, reportType: 'comment', typeId: 40 };
chai.request(app).post('/api/v1/reports')
.set('token', testToken)
.send(invalidReport)
.end((err, res) => {
res.should.have.status(404);
res.body.should.have.property('message');
res.body.message.should.be.an('string');
res.body.message.should.equal('comment not found');
done();
});
});
});
});

0 comments on commit 397756f

Please sign in to comment.