Question

So I'm trying to build an app with nodejs, using express and passport, but as I try to do some kind of TDD, I want to decouple bussiness logic from controllers.

So I have a common scenario like this:

  • An authenticated user wants to delete an item, he sends a request to the api:

    DELETE /api/item/1

  • The request is handled by the controller method, which passes the user that makes the request to the next layer (which doesn't seem like a good approach):

    exports.delete = function (req, res, next) { var itemId = req.params.id; var userId = req.user._id; itemService.delete(itemId, userId, function (err, item) { if (err) next(err); return res.json(item); }); };

  • The service layer (or whatever you want to call it, the layer that has all the bussiness logic) then checks if the item is owned by that user, and then deletes it or returns an error otherwise.

So I was wondering if there is any way to get the current user from any layer without passing it from the controller.

Was it helpful?

Solution

You should ensure the user owns the item before even passing it to the controller, in the routes configuration:

app.del('/api/item/1', ensureUserOwnsItem, itemController.delete);

This will cause the function ensureUserOwnsItem to be called before calling the controller. It should looks like this:

function ensureUserOwnsItem(req, res, next) {
    if (/* user owns item */) {
        next();
    } else {
        res.send(401, 'You can\'t delete an item you don\'t own');
    }
}

You would be able to reuse it on the POST route:

app.post('/api/item/1', ensureUserOwnsItem, itemController.post);

I recommend you put this function inside an AuthController or something like that.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top