At PetroFeed we’ve started to implement tiered packages for our users. We have a Basic (free) tier and a Pro (paid) tier. If you’ve ever done tiered authorization before you know it can be really invasive!
We use CanCan to reduce that complexity and define all that authorization in a single file. However I have yet to see an example of authorization for tiered packages. I’d like to show you a snapshot of what we’re doing with PetroFeed so that you can benefit from what we’ve done to date (and hopefully improve upon it too!)
This post presumes you’re familiar with the standard CanCan installation — If you’re not familiar with it, I suggest the README.
On a Basic plan in PetroFeed you can follow 10 Wells (Well == A hole in the ground that produces Oil) and a Pro plan allows unlimited follows. To achieve that our ability file looks like this:
The beauty of this code is that we can continue to use the standard CanCan authorization methods to check:
- Whether the user can access the page
- Whether the user can access the feature
Here’s an example of the
WellsController that handles the following of a well:
401 to see if a user is authorized to access pages, and the standard response for payment is
So that means when we rescue from the
CanCan::AccessDenied error we need to distinguish from a payment required exception vs an unauthorized exception.
Our code to do that looks like this:
current_ability is simply an instance of
Ability, and so we’ve defined the
payment_required? instance method on it to check wher the user received the exception due to a requirement for payment.
As a whole the code is really simple, and that’s because we’ve spent a lot of time figuring out how to do this elegantly! I foresee needing to package up the logic as different tiers are introduced into the app. If you have any suggestions on how to improve this, I’d love to hear your feedback! :D