Fabio Poloni
Fabio Poloni

Reputation: 8371

Policy for REST API but not for Controllers in sails.js

Assume the following situation:

Policies:

Model:

Controller:

I want to restrict the access to UserController.login to the policy userIsNotLoggedIn and restrict the access to the REST API of User to the policy userIsAdministrator.

If I set the policy of UserController.login to userNotLoggedIn, not authorized users cannot access the REST API for User which is good and as expected. And they can also perform a login. But if you're logged in you still can't access the REST API (which makes sense, since I haven't declared a policy for it yet).

// config/policies.js
'UserController': {
    'login': 'userNotLoggedIn'
}

Now I want to open up the REST API for the userIsAdministrator policy by restricting User.* to userIsAdministrator in policies.js, but now you can't perform UserController.login since it uses User.findOne which is restricted to userIsAdministrator. This is bad.

// config/policies.js
'UserController': {
    'login': 'userNotLoggedIn'
},

'User': {
    '*': 'userIsAdministrator'
}

If I then open User.findOne to userIsNotLoggedIn, the login performs as expected, but this opens up the REST API as well, so anyone can query the user database without being logged in.

// config/policies.js
'UserController': {
    'login': 'userNotLoggedIn'
},

'User': {
    '*': 'userIsAdministrator',
    'findOne': 'userIsNotLoggedIn'
}

Is it possible to restrict the access of User.* to userIsAdministrator for the REST API only, while keeping it open for the controllers so UserController.login is still able to look up the user and log in?

Upvotes: 2

Views: 167

Answers (1)

Fabio Poloni
Fabio Poloni

Reputation: 8371

To apply a policy to a Blueprint Action you have to specify it on the controller not on the model:

// config/policies.js
'UserController': {
    '*': 'userIsAdministrator',
    'login': 'userNotLoggedIn'
}

Blueprint Action Routes like all RESTful routes map to the corresponding Blueprint Action of the controller.

Translation of the "policy" above:

  • Apply userIsAdministrator to all methods of UserController (this also prevents RESTful routes from being run) except the following further declared policies
  • Apply userNotLoggedIn to UserController.login

So setting this in combination with a global '*': false should keep all data secret.

Upvotes: 1

Related Questions