Implement User Authorization with Pundit (Rails)

Stacie Taylor-Cima
Mar 28, 2018 · 3 min read

So, you’re building an app with users and want to allow/restrict access to certain functionality based on a a user’s role. Maybe you even checked out my article on how to add user roles to your app by leveraging the Ruby Enum class and now you want to build it out a step further.

In this article I will be introducing you to Pundit — a Ruby gem that allows us to build a simple, robust and scaleable authorization system in our app.

Since this article builds off of my previous article that demonstrates how to add roles to your users, I’ll continue with the same example app. In this example, we’re building a wiki app — a website that allows collaborative editing of its content and structure by its users.

Our existing roles are standard users, premium users, and admin users. To keep it simple, I’ll demonstrate how I am going to: Authorize admin users to delete any post.

Let’s Get Started!

Add Roles to User Model

I will highlight high-level what steps to take, but if you need a more in-depth explanation, check out my previous article: Use Enum to Represent User Roles in your Database.

  • Create a migration to add a role column to the users table: $ rails g migration AddRoleToUsers role:integer
  • Migrate database
  • Define the enum roles in User model
  • Set a default role in the User model
  • Use the after_initialize callback on the user model to implement default values for roles.

Implement Authorization with Pundit

Add Pundit to the Project:

  • Start by adding Pundit to your project by following the installation guide on Pundit’s README. While you’re in there, really give this a good read. The creators of these packages spend a lot of time carefully crafting their guides to ensure you have all the information you need to be successful in using their creation! Do yourself a favor and truly read it instead of just scanning it to get the code snippets you need.

Create a New Policy File:

  • When you install Pundit, it will automatically create ApplicationPolicy, which is a base class with policies inside the app/policies folder. Policy classes are the core of Pundit and is where the logic for your authorizations will live.
  • In our example, we are authorizing actions on our wikis, so we need to create a WikiPolicy. Create a file named wiki_policy.rb inside the app/policies folder and inherit from the ApplicationPolicy with the following code (replacing Wiki with your own model name):

Write Access Rules:

  • Now we need to write the access rules that will allow specified users access to specific functions. These should return a Boolean, because we’ll essentially be saying: “if the user is an admin or the owner of the wiki, they can access the delete action”.
  • Since I’m only demonstrating how to allow admins to delete any post, we’ll only need to add one method to our WikiPolicy:

Check the Rule in the Controller

  • We’ve set our rules, now we need to call upon them in our controller actions. Pundit provides an authorize method that you can use like this:
  • Now if any other users — that are not an admin or the wiki owner — attempt to click the delete button on a wiki, they’ll get an error.

Hide the Delete Button from View

  • If a user can’t delete a wiki, there is no point in even rendering the “Delete” button. Great news, Pundit provides a special helper method (in the form of a conditional) that you can add to your views:

Now you’ve got users with roles who are authorized for access to only certain functionality in your app. Go write your rules and start authorizing those users!

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade