Skip to main content
Version: v2.0

Creating a custom role

This tutorial will walk you through adding a custom author role to your application.

Prerequisites​

Ensure you have completed the Organization and Roles Tutorial

Data model​

The data model for this tutorial is the same as the Organization and Roles Tutorial

Generate a new policy​

rails generate rhino:policy Author
info

rails generate is a built in Rails command that will run a generator for you. In this case we are generating a new policy called "author". There are a number of generators available in Rails & Rhino. You can see a list of them by running rails generate without any arguments.

There will now be a new files, app/policies/author_policy.rb with the skeleton of a policy and test/policies/author_policy_test.rb with the skeleton of a policy test.

Edit the policy​

app/policies/author_policy.rb
class AuthorPolicy < ::Rhino::ViewerPolicy
def check_author
return false unless auth_owner

# Check if the user is the author of the blog
record.class.where(id: record.id).joins(record.joins_for(:blog)).exists?("blogs.user_id": auth_owner.id)
end

# Can always create (for themselves)
def create?
authorize_action(true)
end

# Can only update if they are the author
def update?
authorize_action(check_author)
end

# Can only destroy if they are the author
def destroy?
authorize_action(check_author)
end

class Scope < ::Rhino::ViewerPolicy::Scope
end
end

Seed the database​

Create an additional organization and role for testing.

db/seeds.rb
# Function to generate sample blogs and blog posts
def generate_blogs(user, org)
5.times do
blog = Blog.create!(user_id: user.id, organization: org, title: FFaker::Book.unique.author, category_id: Category.ids.sample)
20.times do
BlogPost.create!(blog_id: blog.id, title: FFaker::Book.unique.title, body: FFaker::Book.unique.description, published: [true, false].sample)
end
end
end

AdminUser.find_or_create_by(email: "admin@example.com") do |u|
u.password = "password"
end

# Create two sample users
user = User.find_or_create_by(email: "test@example.com") do |u|
u.password = "password"
u.confirmed_at = DateTime.now
end
user_other = User.find_or_create_by(email: "other@example.com") do |u|
u.password = "password"
u.confirmed_at = DateTime.now
end

# Create sample organizations
-org = ["Single User Org", "Multi User Org", "Viewer Org", "Editor Org"].map do |name|
+org = ["Single User Org", "Multi User Org", "Viewer Org", "Editor Org", "Author Org"].map do |name|
Organization.create!(name:)
end

role_admin = Role.create!(name: "admin")
role_viewer = Role.create!(name: "viewer")
role_editor = Role.create!(name: "editor")
+role_author = Role.create!(name: "author")

# The test@example.com user is the only user and admin of the "Single User Org" organization
UsersRole.create!(user: user, organization: org[0], role: role_admin)
# Only test@example.com authors blogs in the "MuSinglelti User Org" organization
generate_blogs(user, org[0])

# The test@example.com and other@example.com are both users and admins of the "Multi User Org" organization
UsersRole.create!(user: user, organization: org[1], role: role_admin)
# Both users author blogs in the "Multi User Org" organization
generate_blogs(user, org[1])
generate_blogs(user_other, org[1])

# The test@example.com is a viewer and other@example.com is an admin of the "Viewer Org" organization
UsersRole.create!(user: user, organization: org[2], role: role_viewer)
UsersRole.create!(user: user_other, organization: org[2], role: role_admin)
# Only other@example.com authors blogs in the "Viewer Org" organization
generate_blogs(user_other, org[3])

# The test@example.com is an editor and other@example.com is an admin of the "Editor Org" organization
UsersRole.create!(user: user, organization: org[3], role: role_editor)
UsersRole.create!(user: user_other, organization: org[3], role: role_admin)
# Only other@example.com authors blogs in the "Editor Org" organization
generate_blogs(user_other, org[3])

+# The test@example.com is an author and other@example.com is an admin of the "Author Org" organization
+UsersRole.create!(user: user, organization: org[4], role: role_author)
+UsersRole.create!(user: user_other, organization: org[4], role: role_admin)
+# Only other@example.com authors blogs in the "Editor Org" organization
+generate_blogs(user, org[4])
+generate_blogs(user_other, org[4])

And add the seed data to the database

rails db:seed

Restart the server​

rails s

Try the Author Org​

Login to the application with test@example.com and password and switch to the "Author Org" organization. Viewing the blogs where the author is test@example.com will allow editing and deleting:

While blogs where the author is not test@example.com will not: