0

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.requiresLoginandaccounts.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.

1
  • I can change list in the server controller to only find items with that specific user: Account.find({ user: req.user}) is that enough? Commented Dec 30, 2014 at 13:15

1 Answer 1

1

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')
    .... //
    
    };
    
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.