Best way to enforce permissions--controller or constraint?

I have a plugin that adds a model, server, which has a user_id field. I want only the owner of the server to be able to make a POST (or maybe it should be a PUT?–the action will do a command-line rebuild of a Discourse instance on their server`; I’m not sure which would be best practice.)

In config/routes.rb is this:

post “/upgrade/:id” => “servers#queue_upgrade”, constraints: PfaffmanagerConstraint.new

Is it recommended to have matches? in pfaffmanager_constraint.rb check the path_parameters[:action] and enforce the permission there or to do it in servers_controller.rb?

Also, I think that what I should really do is move this route under namespace :user, so perhaps after I figure that out this problem will get solved as part of that, but this almost works, and I’d like to move to having other people try this code.

Rails route has this:
https://github.com/pfaffman/discourse-pfaffmanager/blob/master/config/routes.rb#L12

And my controller tries to enforce permissions:

https://github.com/pfaffman/discourse-pfaffmanager/blob/master/app/controllers/pfaffmanager/servers_controller.rb#L53-L70

But my spec is getting a 200 when a different user does the post:

https://github.com/pfaffman/discourse-pfaffmanager/blob/master/spec/requests/servers_controller_spec.rb#L149-L157

I guess I need to get Ember to pay attention to this somehow?

1 Like

Can’t you pass a method to before_action to check your condition?

1 Like

I think that the permissions need to be enforced in the controller or the constraints. The model doesn’t know who is calling it, I think.

Thanks very much for thinking about this.

1 Like

I think you need a guardian method to check if a user is allowed to perform a given action. for e.g. can_upgrade_server?

Also, once you do that, you can use guardian.ensure_can_upgrade_server! method which checks the condition and raises an exception which I think is exactly what you want.

2 Likes

Ooooh! Guardian method! Yes! I’ll look at those! Thanks.

2 Likes

The only model that uses guardian is the user model. It looks like most of the action with guardian is in the controllers.

For example, the categories controller uses ensure_can_create_category, which I think is magically created over in lib/guardian.rb.

But for now, I’m not using guardian because I’m having trouble figuring out how to instantiate it properly. I have this in my controller:

https://github.com/pfaffman/discourse-pfaffmanager/blob/master/app/controllers/pfaffmanager/servers_controller.rb#L54-L75

And here are specs that test it:

https://github.com/pfaffman/discourse-pfaffmanager/blob/master/spec/requests/servers_controller_spec.rb#L154-L181