Skip to content

Commit

Permalink
Merge b782f37 into be76858
Browse files Browse the repository at this point in the history
  • Loading branch information
kagabof committed Jul 25, 2019
2 parents be76858 + b782f37 commit cc17018
Show file tree
Hide file tree
Showing 18 changed files with 151 additions and 13 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"start": "npm run create && NODE_ENV=staging babel-node ./src/index.js",
"dev": "nodemon --exec babel-node ./src/index.js",
"create": "NODE_ENV=staging sequelize db:migrate",
"migrate": "sequelize db:migrate:undo:all && sequelize db:migrate",
"migrate": "sequelize db:migrate:undo:all && sequelize db:migrate && sequelize db:seed:all",
"seqinit": "sequelize init",
"build": "npm run clear && babel src --out-dir build",
"clear": "rm -rf build",
Expand Down
3 changes: 2 additions & 1 deletion src/controllers/authController.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ export default class AuthController {

const payload = { username: user.username,
id: user.id,
email: user.email };
email: user.email,
roles: user.roles };

const token = await generateToken(payload);
return res.status(200).json({ message: 'Logged in successfully',
Expand Down
3 changes: 3 additions & 0 deletions src/controllers/helpers/validateRoles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const validateRoles = data => (data.permissions && data.role && data.tablesAllowed)
&& data;
export default validateRoles;
19 changes: 19 additions & 0 deletions src/controllers/rolesController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* eslint-disable require-jsdoc */
import model from '../models';

const { Permissions } = model;

class PermitionsController {
static async createRole(req, res) {
try {
const permissions = req.body.permissions.split(',');
const tablesAllowed = req.body.tablesAllowed.split(',');
const role = await Permissions.create({ role: req.body.role, permissions, tablesAllowed });
return role && res.status(201).json({ message: 'Role successfully created' });
} catch (error) {
return res.status(400).json({ error: 'tableAllowed, role, and permissions are required ' });
}
}
}

export default PermitionsController;
9 changes: 6 additions & 3 deletions src/controllers/userController.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ export default class UserController {
const user = await User.create({ username,
email,
password: hashedPasword,
verified });
verified,
roles: ['user'] });

const payload = { username: user.username,
id: user.id,
email: user.email,
verified: user.verified };
verified: user.verified,
roles: user.roles };

const token = await generateToken(payload);
const mailSend = await MailSender.sendMail(user.email, user.username, token);
Expand All @@ -60,7 +62,8 @@ export default class UserController {

const payload = { username: user.username,
userId: user.id,
email: user.email };
email: user.email,
role: user.role };
const token = await generateToken(payload);
// @sends a message to an existing email in our database with the below email template
const message = `<div>You are receiving this because you (or someone else) requested the reset of your password.<br>
Expand Down
7 changes: 7 additions & 0 deletions src/middlewares/roleCheck.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

const checkAdmin = (req, res, next) => (
req.user.roles.includes('admin')
? next()
: res.status(403).json({ message: 'Not allowed to perform the action' }));

export default checkAdmin;
2 changes: 1 addition & 1 deletion src/migrations/20190624-create-userschema.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ gender: { type: Sequelize.STRING,
allowNull: true },
provider: { type: Sequelize.STRING,
allowNull: true },
role: { type: Sequelize.STRING,
roles: { type: Sequelize.ARRAY(Sequelize.STRING),
allowNull: true }, }),
down: queryInterface => queryInterface.dropTable('User') };
2 changes: 1 addition & 1 deletion src/migrations/20190703214859-create-user.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ gender: { type: Sequelize.STRING,
allowNull: true },
provider: { type: Sequelize.STRING,
allowNull: true },
role: { type: Sequelize.STRING,
roles: { type: Sequelize.ARRAY(Sequelize.STRING),
allowNull: true }, }),
down: queryInterface => queryInterface.dropTable('User') };
12 changes: 12 additions & 0 deletions src/migrations/20190725090430-create-permissions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module.exports = { up: (queryInterface, Sequelize) => queryInterface.createTable('Permissions', { id: { allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER },
role: { type: Sequelize.STRING },
permissions: { allowNull: false, type: Sequelize.ARRAY(Sequelize.STRING) },
tablesAllowed: { allowNull: false, type: Sequelize.ARRAY(Sequelize.STRING) },
createdAt: { allowNull: false,
type: Sequelize.DATE },
updatedAt: { allowNull: false,
type: Sequelize.DATE } }),
down: (queryInterface, Sequelize) => queryInterface.dropTable('Permissions') };
11 changes: 11 additions & 0 deletions src/models/Permissions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@


module.exports = (sequelize, DataTypes) => {
const Permissions = sequelize.define('Permissions', { role: { type: DataTypes.STRING,
allowNull: false },
tablesAllowed: { type: DataTypes.ARRAY(DataTypes.STRING),
allowNull: false },
permissions: { type: DataTypes.ARRAY(DataTypes.STRING),
allowNull: false } }, {});
return Permissions;
};
4 changes: 2 additions & 2 deletions src/models/User.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default (sequelize) => {
export default (sequelize, DataTypes) => {
const User = sequelize.define('User',
{ username: { type: String, unique: true, required: true },
firstName: { allowNull: true, type: String },
Expand All @@ -15,7 +15,7 @@ export default (sequelize) => {
dateOfBirth: { allowNull: true, type: Date },
gender: { type: String },
provider: { type: String },
role: { type: String } },
roles: { type: DataTypes.ARRAY(DataTypes.STRING), allowNull: true } },
{ timestamps: true, tableName: 'User' });

User.associate = (models) => {
Expand Down
3 changes: 3 additions & 0 deletions src/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ import socialAPIRoute from './socialAPIRoute';
import optinAndOptOut from './optinAndOptOut';
import bookmarkRoute from './bookmarksRoutes';
import readerStatsRoute from './readerStatsRoute';
import role from './roleRoutes';

const { verifyToken } = Auth;

const router = express.Router();

router.use('/api', role);

router.use('/api', bookmarkRoute);
// article routes
Expand Down Expand Up @@ -50,4 +52,5 @@ router.patch('/api/users/verification/:userToken', UserController.verifyUser);
router.patch('/api/users/:username', verifyToken, bodyValidation, usernameAvailability, UserProfile.updateProfile);
router.get('/api/users/', verifyToken, UserProfile.getAllUser);


export default router;
12 changes: 12 additions & 0 deletions src/routes/roleRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import express from 'express';
import Auth from '../middlewares/Auth';
import checkAdmin from '../middlewares/roleCheck';
import roles from '../controllers/rolesController';

const role = express.Router();

const { verifyToken } = Auth;

role.post('/role', verifyToken, checkAdmin, roles.createRole);

export default role;
5 changes: 3 additions & 2 deletions src/seeders/20190703161356-users.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ module.exports = { up: queryInterface => queryInterface.bulkInsert('User', [{ us
firstName: 'john',
lastName: 'Doe',
email: 'michael.nzube@andela.com',
password: 'hashing',
password: 'process.env.JAWANS_ADMIN',
following: true,
bio: 'bios',
image: 'image' }], {}),
image: 'image',
roles: ['user'] }], {}),

down: queryInterface => queryInterface.bulkDelete('User', null, {}) };
11 changes: 11 additions & 0 deletions src/seeders/20190725062644-initUsers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = { up: queryInterface => queryInterface.bulkInsert('User', [{ username: 'john',
firstName: 'kagabo',
lastName: 'prince',
email: 'faustin.kagabo@andela.com',
password: '$2b$12$ohLYwcyFvN9o/fnRSd4G1.vcdNvt6SDJpiyTpOxiz38Y/wG4hNeza',
following: true,
bio: 'bios',
image: 'image',
roles: ['admin'] }], {}),

down: queryInterface => queryInterface.bulkDelete('User', null, {}) };
5 changes: 4 additions & 1 deletion src/test/mock/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ user2: { firstName: 'james',
lastName: 'bond',
email: 'jamesbond@ahjawans.com',
username: 'james_bond',
password: 'James@12345', } };
password: 'James@12345', },
userAdmin: { username: 'john',
password: 'Kagabo1@',
email: 'faustin.kagabo@andela.com' } };
52 changes: 52 additions & 0 deletions src/test/roleTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import chai from 'chai';
import chaiHttp from 'chai-http';
import app from '../index';
import mock from './mock/users';

chai.use(chaiHttp);
chai.should();
let tokenGen;
describe('role', () => {
it('admin signin', (done) => {
chai.request(app)
.post('/api/users/login')
.send(mock.userAdmin)
.end((req, res) => {
// eslint-disable-next-line prefer-destructuring
res.should.have.status(200);
res.body.data.should.have.property('token');
tokenGen = res.body.data.token;
done();
});
});

it('admin should create a role', (done) => {
const role = { tablesAllowed: 'Articles,User',
role: 'admin',
permissions: 'GET,DELETE' };
chai.request(app)
.post('/api/role')
.set('token', tokenGen)
.send(role)
.end((req, res) => {
res.should.have.status(201);
res.body.should.have.property('message');
done();
});
});

it('should not create a role if user is not an admin', (done) => {
const role = { tablesAllowed: 'Articles,User',
role: 'admin',
permissions: 'GET,DELETE' };
chai.request(app)
.post('/api/role')
.set('token', `${tokenGen}dgfwe`)
.send(role)
.end((req, res) => {
res.should.have.status(401);
res.body.should.have.property('error');
done();
});
});
});
2 changes: 1 addition & 1 deletion src/test/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ describe('User Profile view amend', () => {
chai.request(app)
.patch(`/api/users/${userGen}`)
.set('token', tokenGen)
.send({ id: 16,
.send({ id: 18,
username: 'shaluchandwani',
firstName: 'Shalu',
lastName: 'chandwani',
Expand Down

0 comments on commit cc17018

Please sign in to comment.