CanCan Route Constraints

I use Sidekiq to handle the background jobs which is working great, but I noticed that some of them seemed to be failing! I had no way of seeing which jobs where failing or why because I handn’t mounted the WebUI anywhere. The issue I had was securing it, I can’t just rely on the fact that a random user wont know that it is at /sidekiq, especially since it lets you perform some job control.

The only solution is to secure access to it, which I can only do within the routes. I also wanted to use the Authorization system I already had in place instead of adding something extra in (like HTTP basic etc…).

I use CanCan which is a great solution, I just need to get it working in the router.

The class I wrote to do this is actually pretty simple:

For my uses I mounted sidekiq like this:

So how does it work?

The router lets you pass a class to the route constraints option, the only requirement being that this class/instance of a class has to respond to matches?. So my CanCanConstraint class is re-usable as it lets you specify which permission in CanCan you want to check the user has, in this case I check if the user can manage sidekiq (this is the same as using can? :manage, :sidekiq in a view).

When matches? gets called it first checks if the session variable of user_id exists (assuming that guests would not be given access) and if it doesn’t return false. If it does exist it finds that user in the same way that ApplicationController#current_user does and then passes that user to Ability.new which is exactly what CanCan does (which is why you write your code in initialize). This then gives you the can? method same as in views. can? returns true or false based on the users assigned permissions, if you meet the requirements and it returns true the router will allow that route to exist for you.

This means that for anyone not given manage permissions on sidekiq the route simply wont exist, you will get a 404 instead of a 403.

Adam Laycock

IT Engineer and Developer working in education. I try to do everything in my power to create better systems for schools be it the windows domain or a plugin for their WordPress site.

1 Response

  1. Josh Illian says:

    Thanks for this. I ended up using the gist of your solution for another Rails engine – Flipper. Exactly the direction I needed. Appreciate you taking the time to capture this solution and write about it.

Leave a Reply

Your email address will not be published. Required fields are marked *