Sails.js authentication for model actions

Problem

I'm making an API that has different levels of access, the 'client' may only read. But 'admin' must have write access. The different roles are check every time as a policy in Sails.js and sets the rights in the req.session.

I just need to give the 'client' no access to create, update and delete actions, therefore i created an controller that has those CRUD actions and checks if the user has the right role. All of the actions that has restricted access are redirected trough routes.js to this controller.

Now my problem is that when i'm deleting an entry like: Category.destroy(req.param('id')); Gives me undefined and has no done method. Unlike mentioned by the docs I managed to fix the problem by creating this:

   var deleted = Category.destroy(req.param('id'), function(err, status) { 
    if (status == 1){
      res.json({message: 'Category is deleted'});
    } else {
      res.json({message: 'Oops, something went wrong'});
    }
  });

But there has to be another way to apply authentication to those basic actions. Because now i've to write all actions.

Is there something wrong with the code for the delete function that i wrote? And is it possible to apply policies and redirect to default model actions, as if there was no authentication at all?

Problem courtesy of: Loed

Solution

Just modified all the policies en renamed the controllers, as stated in de CLI: 'sails generate model example' gives an notification about the controller being named as singular. So I didn't need to redirect all model actions to the plural controller (examples). Now all the basic CRUD actions are working as it should.

The sails.js video tutorial helped me a lot: http://www.youtube.com/watch?feature=player_embedded&v=GK-tFvpIR7c

Solution courtesy of: Loed

Discussion

My guess (not a Sails user myself) would be you either pass a callback, or you'll get an object back which has a done() method:

Category.destroy(id, function(...) {...});      // method 1
Category.destroy(id).done(function(...) {...}); // method 2
Discussion courtesy of: robertklep

You can define policies at the Models or Controllers level. Here's an example from the /config/policies.js.

module.exports.policies = {
    // Default policy (allow public access)
    '*': true,
    'events': 'eventsPolicy', // Policy for a Model

    someController: { // Policy for a Controller
        // Apply the "authenticated" policy to all actions
        '*': 'authenticated',

        // For someAction, apply 'somePolicy' instead
        someAction: 'somePolicy'
    }
};

Under the api/policies is where you can define the access level.

module.exports = function (req, res, next) {
    if (req.session.user) {
        var action = req.param('action');
        if (action == "create") {
            req.body.userId = req.session.user.id;
            req.body.username = req.session.user.username;
        }
        next();
    } else {
        res.send("You're not authenticated.", 403);
    }
};

Hope this helps.

Discussion courtesy of: Dennis Rongo

This recipe can be found in it's original form on Stack Over Flow.