Reputation: 9716
In my mean js app i have an account model and corresponding routes and controllers. To remove a specific account i need to have authorization and I need to be logged in.
All users can however list all accounts, I only wont to list the accounts created by the specific user. So i need to add autorization to the list part of the code.
I update the routes for app.route('/accounts')
with users.requiresLogin
andaccounts.hasAuthorization
as shown below:
module.exports = function(app) {
var users = require('../../app/controllers/users.server.controller');
var accounts = require('../../app/controllers/accounts.server.controller');
// Accounts Routes
app.route('/accounts')
.get(users.requiresLogin,accounts.hasAuthorization,accounts.list)
.post(users.requiresLogin, accounts.create);
app.route('/accounts/:accountId')
.get(users.requiresLogin, accounts.hasAuthorization,accounts.read)
.put(users.requiresLogin, accounts.hasAuthorization, accounts.update)
.delete(users.requiresLogin, accounts.hasAuthorization, accounts.delete);
// Finish by binding the Account middleware
app.param('accountId', accounts.accountByID);
};
Now I get an errror since req is not provided with user.
GET /modules/accounts/views/list-accounts.client.view.html 304 8.266 ms - - TypeError: Cannot read property 'user' of undefined at exports.hasAuthorization (/Users/david/Repositories/budget/app/controllers/accounts.server.controller.js:103:17)
So I imagine i need to update the accounts.server.controller somehow. The delete account does provide an account in the req, so that only the creator can delete as I mentioned earlier. How do I update the code so that the "List of accounts" part work and list only the accounts belonging to that specific user?
/**
* Delete an Account
*/
exports.delete = function(req, res) {
var account = req.account ;
account.remove(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(account);
}
});
};
/**
* List of Accounts
*/
exports.list = function(req, res) {
Account.find().sort('-created').populate('user', 'displayName').exec(function(err, accounts) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(accounts);
}
});
};
/**
* Account middleware
*/
exports.accountByID = function(req, res, next, id) {
Account.findById(id).populate('user', 'displayName').exec(function(err, account) {
if (err) return next(err);
if (! account) return next(new Error('Failed to load Account ' + id));
req.account = account ;
next();
});
};
/**
* Account authorization middleware
*/
exports.hasAuthorization = function(req, res, next) {
if (req.account.user.id !== req.user.id) {
return res.status(403).send('User is not authorized');
}
next();
};
The account client service only contains the basic stuff:
//Accounts service used to communicate Accounts REST endpoints
angular.module('accounts').factory('Accounts', ['$resource',
function($resource) {
return $resource('accounts/:accountId', { accountId: '@_id'
}, {
update: {
method: 'PUT'
}
});
}
]);
And the user object is not mentioned in the controller.
Upvotes: 0
Views: 772
Reputation: 2240
The accounts.hasAuthorization assume it get executed after the accounts.accountById ,on your current configuration req.account will be undefined.
I'm assumming that somewhere in your account model you have:
user: {
type: Schema.ObjectId,
ref: 'User'
}
If you want the user only have access only to the accounts he/she owns :
Change accounts.list route only to requires Login and this gives us access to the req.user :
app.route('/accounts')
.get(users.requiresLogin,accounts.list)
Change the exports.list in the accounts controller:
exports.list = function(req, res) {
Account.find({user: req.user._id}).sort('-created')
.... //
};
Upvotes: 1