summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJules Laplace <jules@okfoc.us>2017-03-16 21:03:55 +0100
committerJules Laplace <jules@okfoc.us>2017-03-16 21:03:55 +0100
commit13fd58333e8280effb679ac93913971b096d5fe3 (patch)
treec1fb731eb1a8a61b3e237c9feaaa1f7b2e2b6923
parent8e05164678d302700c794feecd50d83357f7719d (diff)
CRUD users
-rw-r--r--.gitignore4
-rw-r--r--.jshintrc1
-rw-r--r--src/hooks/index.js9
-rw-r--r--src/services/meal/hooks/index.js3
-rw-r--r--src/services/meal/meal-model.js2
-rw-r--r--src/services/user/hooks/index.js91
-rw-r--r--src/services/user/user-model.js2
-rw-r--r--test/services/user/index.test.js96
8 files changed, 184 insertions, 24 deletions
diff --git a/.gitignore b/.gitignore
index 3cd787d..52721e8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,3 +29,7 @@ node_modules
lib/
data/
+
+*~
+*.swp
+
diff --git a/.jshintrc b/.jshintrc
index 1c271e2..31fd4a1 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -1,4 +1,5 @@
{
+ "asi": true,
"node": true,
"esnext": true,
"bitwise": true,
diff --git a/src/hooks/index.js b/src/hooks/index.js
index 2b122bb..4c535c4 100644
--- a/src/hooks/index.js
+++ b/src/hooks/index.js
@@ -8,12 +8,3 @@
const hooks = require('feathers-hooks');
const auth = require('feathers-authentication').hooks;
-const or = require('promise-or');
-
-exports.restrictToOwnersOrAdmins = function() {
- var ownerHook = auth.restrictToOwner()
- var adminHook = auth.restrictToRoles({ roles: ["admin"] })
- return function(hook) {
- return or(ownerHook(hook), adminHook(hook))
- };
-};
diff --git a/src/services/meal/hooks/index.js b/src/services/meal/hooks/index.js
index 2e2795a..dd0d7ca 100644
--- a/src/services/meal/hooks/index.js
+++ b/src/services/meal/hooks/index.js
@@ -9,7 +9,6 @@ exports.before = {
auth.verifyToken(),
auth.populateUser(),
auth.restrictToAuthenticated(),
- globalHooks.restrictToOwnersOrAdmins(),
],
find: [],
get: [],
@@ -26,6 +25,6 @@ exports.after = {
create: [],
update: [],
patch: [],
- remove: []
+ remove: [],
};
diff --git a/src/services/meal/meal-model.js b/src/services/meal/meal-model.js
index d15b244..90f35ca 100644
--- a/src/services/meal/meal-model.js
+++ b/src/services/meal/meal-model.js
@@ -21,7 +21,7 @@ module.exports = function(sequelize) {
type: Sequelize.INTEGER,
allowNull: false
},
- user_id: {
+ userid: {
type: Sequelize.INTEGER,
references: {
model: sequelize.model('users'),
diff --git a/src/services/user/hooks/index.js b/src/services/user/hooks/index.js
index 9dfe425..85f8e04 100644
--- a/src/services/user/hooks/index.js
+++ b/src/services/user/hooks/index.js
@@ -4,39 +4,114 @@ const globalHooks = require('../../../hooks');
const hooks = require('feathers-hooks');
const auth = require('feathers-authentication').hooks;
+var _feathersErrors = require('feathers-errors');
+var _feathersErrors2 = _interopRequireDefault(_feathersErrors);
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function validateRoleOnCreate () {
+ return function(hook) {
+ var _this = this;
+
+ var userRole = hook.params.user && hook.params.user.role;
+
+ return new Promise(function (resolve, reject) {
+ // Set provider as undefined so we avoid an infinite loop if this hook is
+ // set on the resource we are requesting.
+ var params = Object.assign({}, hook.params, { provider: undefined });
+
+ if (! hook.data.role) {
+ hook.data.role = 'user'
+ resolve(hook);
+ }
+ if (userRole && userRole.toString() === 'user') {
+ reject(new _feathersErrors2.default.Forbidden('You do not have permission to create new users.'));
+ }
+ else if (userRole && userRole.toString() === 'manager' && hook.data.role.toString() !== 'user') {
+ reject(new _feathersErrors2.default.Forbidden('You do not have permission to change this user\'s role.'));
+ }
+ else {
+ resolve(hook);
+ }
+ });
+ }
+}
+
+function validateRoleOnUpdate () {
+ return function(hook) {
+ var _this = this;
+
+ var userRole = hook.params.user.role;
+
+ return new Promise(function (resolve, reject) {
+ // Set provider as undefined so we avoid an infinite loop if this hook is
+ // set on the resource we are requesting.
+ var params = Object.assign({}, hook.params, { provider: undefined });
+
+ return _this.get(hook.id, params).then(function (data) {
+ if (data.toJSON) {
+ data = data.toJSON();
+ } else if (data.toObject) {
+ data = data.toObject();
+ }
+
+ var dataRole = data.role;
+ if (userRole.toString() === 'user' && dataRole.toString() !== 'user') {
+ reject(new _feathersErrors2.default.Forbidden('You do not have permission to change your role.'));
+ }
+ else if (userRole.toString() === 'manager' && dataRole.toString() !== 'user') {
+ reject(new _feathersErrors2.default.Forbidden('You do not have permission to change this user\'s role.'));
+ }
+ else {
+ resolve(hook);
+ }
+ }).catch(reject);
+ });
+ }
+}
+
+const roleConfig = {
+ fieldName: 'role',
+ roles: ['manager','admin'],
+ owner: true,
+ ownerField: 'id'
+}
+
exports.before = {
all: [],
find: [
auth.verifyToken(),
auth.populateUser(),
- auth.restrictToAuthenticated()
+ auth.restrictToAuthenticated(),
],
get: [
auth.verifyToken(),
auth.populateUser(),
auth.restrictToAuthenticated(),
- auth.restrictToOwner({ ownerField: 'id' })
+ auth.restrictToRoles(roleConfig),
],
create: [
- auth.hashPassword()
+ auth.hashPassword(),
+ validateRoleOnCreate(),
],
update: [
auth.verifyToken(),
auth.populateUser(),
auth.restrictToAuthenticated(),
- auth.restrictToOwner({ ownerField: 'id' })
+ auth.restrictToRoles(roleConfig),
+ validateRoleOnUpdate(),
],
patch: [
auth.verifyToken(),
auth.populateUser(),
auth.restrictToAuthenticated(),
- auth.restrictToOwner({ ownerField: 'id' })
+ validateRoleOnUpdate(),
+ validateRoleOnUpdate(),
],
remove: [
auth.verifyToken(),
auth.populateUser(),
auth.restrictToAuthenticated(),
- auth.restrictToOwner({ ownerField: 'id' })
+ validateRoleOnUpdate(),
]
};
@@ -47,5 +122,7 @@ exports.after = {
create: [],
update: [],
patch: [],
- remove: []
+ remove: [
+ // remove user's meals
+ ],
};
diff --git a/src/services/user/user-model.js b/src/services/user/user-model.js
index 03db95b..d7c00ee 100644
--- a/src/services/user/user-model.js
+++ b/src/services/user/user-model.js
@@ -19,7 +19,7 @@ module.exports = function(sequelize) {
allowNull: false
},
role: {
- type: Sequelize.ENUM('user', 'manager', 'admin'),
+ type: Sequelize.STRING,
allowNull: false
},
goal: {
diff --git a/test/services/user/index.test.js b/test/services/user/index.test.js
index a43dcae..83dc105 100644
--- a/test/services/user/index.test.js
+++ b/test/services/user/index.test.js
@@ -1,10 +1,98 @@
'use strict';
+const chai = require('chai')
+const chaiHttp = require('chai-http')
+const should = chai.should();
const assert = require('assert');
const app = require('../../../src/app');
-describe('user service', function() {
+const User = app.service('users')
+const authentication = require('feathers-authentication/client');
+const bodyParser = require('body-parser');
+var token, userid
+
+app
+ .use(bodyParser.json())
+ .use(bodyParser.urlencoded({ extended: true }))
+ .configure(authentication());
+chai.use(chaiHttp);
+
+
+describe('user service', () => {
+ before((done) => {
+ this.server = app.listen(3030)
+ this.server.once('listening', () => {
+ done()
+ })
+ })
+
+ after((done) => {
+ this.server.close(function(){})
+ done()
+ })
+
it('registered the users service', () => {
- assert.ok(app.service('users'));
- });
-});
+ assert.ok(app.service('users'))
+ })
+
+ it('should create a new user', (done) => {
+ chai.request(app)
+ .post('/users')
+ .set('Accept', 'application/json')
+ .send({
+ email: 'test@test.com',
+ password: 'password',
+ goal: 2000,
+ })
+ .end((err, res) => {
+ res.body.should.have.property('email')
+ res.body.email.should.equal('test@test.com')
+ res.body.should.not.have.property('password')
+ res.body.goal.should.equal(2000)
+ done()
+ })
+ })
+
+ it('should authenticate a new user', (done) => {
+ chai.request(app)
+ .post('/auth/local')
+ .set('Accept', 'application/json')
+ .send({
+ email: 'test@test.com',
+ password: 'password',
+ })
+ .end((err, res) => {
+ res.body.should.have.property('token')
+ res.body.should.have.property('data')
+ res.body.data.should.have.property('id')
+ token = res.body.token
+ userid = res.body.data.id
+ done()
+ })
+ })
+
+ it('user should be able to update itself', (done) => {
+ chai.request(app)
+ .patch('/users/'.concat(userid))
+ .set('Accept', 'application/json')
+ .set('Authorization', 'Bearer '.concat(token))
+ .send({
+ goal: 2500,
+ })
+ .end((err, res) => {
+ done()
+ })
+ })
+
+ it('user should be able to destroy itself', (done) => {
+ chai.request(app)
+ .delete('/users/'.concat(userid))
+ .set('Accept', 'application/json')
+ .set('Authorization', 'Bearer '.concat(token))
+ .send()
+ .end((err, res) => {
+ done()
+ })
+ })
+
+})