Melhor forma de impor permissões — controller ou constraint?

Tenho um plugin que adiciona um modelo, server, que possui um campo user_id. Quero que apenas o proprietário do server possa fazer um POST (ou talvez deveria ser um PUT? — a ação executará uma reconstrução via linha de comando de uma instância do Discourse no servidor deles; não tenho certeza de qual seria a melhor prática.)

Em config/routes.rb, está assim:

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

É recomendado que matches? em pfaffmanager_constraint.rb verifique path_parameters[:action] e aplique a permissão ali, ou devo fazer isso em servers_controller.rb?

Além disso, acho que o que realmente deveria fazer é mover essa rota para dentro de namespace :user. Talvez, depois que eu resolver isso, o problema seja resolvido como parte dessa mudança, mas isso quase funciona, e gostaria de permitir que outras pessoas testem esse código.

A rota do Rails está aqui:
https://github.com/pfaffman/discourse-pfaffmanager/blob/master/config/routes.rb#L12

E meu controlador tenta aplicar as permissões:

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

Mas meu spec está retornando 200 quando outro usuário faz o post:

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

Acho que preciso fazer o Ember prestar atenção nisso de alguma forma?

Você não pode passar um método para o before_action para verificar sua condição?

Acho que as permissões precisam ser aplicadas no controlador ou nas restrições. O modelo não sabe quem o está chamando, creio eu.

Muito obrigado por pensar nisso.

Acho que você precisa de um método guardião para verificar se um usuário tem permissão para executar uma determinada ação. Por exemplo: can_upgrade_server?

Além disso, ao fazer isso, você pode usar o método guardian.ensure_can_upgrade_server!, que verifica a condição e lança uma exceção, o que, na minha opinião, é exatamente o que você deseja.

Ooooh! Método do Guardião! Sim! Vou dar uma olhada nisso! Obrigado.

O único modelo que usa guardian é o modelo de usuário. Parece que a maior parte da ação com guardian ocorre nos controladores.

Por exemplo, o controlador de categorias usa ensure_can_create_category, que, creio eu, é magicamente criado em lib/guardian.rb.

Mas, por enquanto, não estou usando o guardian porque estou tendo dificuldade em descobrir como instanciá-lo corretamente. Tenho o seguinte no meu controlador:

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

E aqui estão os testes que o validam:

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