Skip to content
This repository has been archived by the owner on Oct 29, 2024. It is now read-only.

Commit

Permalink
➕ Add gem "pundit" for authorization
Browse files Browse the repository at this point in the history
  • Loading branch information
ledermann committed May 18, 2017
1 parent c627f3a commit 518b95c
Show file tree
Hide file tree
Showing 13 changed files with 158 additions and 5 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ gem 'rack'
gem 'faker'
gem 'clearance'
gem 'simple_form'
gem 'pundit'

group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
Expand Down
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ GEM
pg (0.20.0)
public_suffix (2.0.5)
puma (3.8.2)
pundit (1.1.0)
activesupport (>= 3.0.0)
rack (2.0.3)
rack-contrib (1.2.0)
rack (>= 0.9.1)
Expand Down Expand Up @@ -306,6 +308,7 @@ DEPENDENCIES
pdf-reader
pg (~> 0.18)
puma (~> 3.7)
pundit
rack
rails (~> 5.1.1)
responders
Expand Down
10 changes: 10 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

class ApplicationController < ActionController::Base
include Clearance::Controller
include Pundit
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized

self.responder = ApplicationResponder
respond_to :html

Expand All @@ -10,4 +13,11 @@ class ApplicationController < ActionController::Base
helper_method def body_js_class
@body_js_class ||= [ controller_name.camelcase, action_name.camelcase ].join
end

private

def user_not_authorized
flash[:alert] = "You are not authorized to perform this action."
redirect_to(request.referrer || root_path)
end
end
15 changes: 14 additions & 1 deletion app/controllers/posts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ def index
page(params[:page]).
per(25)
end
authorize @posts

respond_with @posts do |format|
format.js { render 'kaminari/infinite-scrolling', locals: { objects: @posts } }
Expand All @@ -19,6 +20,8 @@ def index

def show
@post = find_post
authorize @post

respond_with @post do |format|
format.pdf { render pdf: @post.title,
disposition: 'inline',
Expand All @@ -28,27 +31,37 @@ def show

def new
@post = Post.new
authorize @post
end

def edit
@post = find_post
authorize @post

respond_with @post
end

def create
@post = Post.create(post_params)
@post = Post.new(post_params)
authorize @post
@post.save

respond_with @post
end

def update
@post = find_post
authorize @post
@post.update(post_params)

respond_with @post
end

def destroy
@post = find_post
authorize @post
@post.destroy!

respond_with @post
end

Expand Down
8 changes: 8 additions & 0 deletions app/policies/application_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class ApplicationPolicy
attr_reader :user, :record

def initialize(user, record)
@user = user
@record = record
end
end
30 changes: 30 additions & 0 deletions app/policies/post_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
class PostPolicy < ApplicationPolicy
def index?
true
end

def show?
true
end

def create?
user&.is_admin?
end

def new?
create?
end

def update?
user&.is_admin?
end

def edit?
update?
end

def destroy?
user&.is_admin?
end

end
3 changes: 3 additions & 0 deletions app/views/layouts/application.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ html[lang="en"]

#main
.container
- if alert
p.alert.alert-danger
= alert
- if notice
p.alert.alert-info
= notice
Expand Down
2 changes: 2 additions & 0 deletions config/environments/test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,6 @@

# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true

config.middleware.use Clearance::BackDoor
end
20 changes: 20 additions & 0 deletions spec/controllers/posts_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,21 @@
end

describe "GET #new" do
before do
sign_in_as(build(:admin))
end

it "returns a success response" do
get :new, params: {}, session: valid_session
expect(response).to be_success
end
end

describe "GET #edit" do
before do
sign_in_as(build(:admin))
end

it "returns a success response" do
post = create(:post, valid_attributes)
get :edit, params: {id: post.to_param}, session: valid_session
Expand All @@ -77,6 +85,10 @@
end

describe "POST #create" do
before do
sign_in_as(build(:admin))
end

context "with valid params" do
it "creates a new Post" do
expect {
Expand All @@ -99,6 +111,10 @@
end

describe "PUT #update" do
before do
sign_in_as(build(:admin))
end

context "with valid params" do
let(:new_attributes) {
{
Expand Down Expand Up @@ -130,6 +146,10 @@
end

describe "DELETE #destroy" do
before do
sign_in_as(build(:admin))
end

it "destroys the requested post" do
post = create(:post, valid_attributes)
expect {
Expand Down
5 changes: 5 additions & 0 deletions spec/factories/clearance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,10 @@
factory :user do
email
password "password"
is_admin false

factory :admin do
is_admin true
end
end
end
8 changes: 4 additions & 4 deletions spec/features/posts_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
end

scenario 'User edits an existing page' do
visit edit_post_path(example_post)
visit edit_post_path(example_post, as: create(:admin))

expect(page).to have_selector('h1', text: 'Editing Post')
expect(page).to have_button('Update Post')
Expand All @@ -87,7 +87,7 @@
end

in_browser(:second_user) do
visit edit_post_path(example_post)
visit edit_post_path(example_post, as: create(:admin))

fill_in 'post[title]', with: 'Fooo'
fill_in 'post[content]', with: 'dolor sit amet'
Expand All @@ -101,7 +101,7 @@
end

scenario 'User deletes an existing page', js: true do
visit post_path(example_post)
visit post_path(example_post, as: create(:admin))

page.accept_alert 'Are you sure?' do
find(:xpath, '//a[@title="Destroy"]').click
Expand All @@ -113,7 +113,7 @@
end

scenario 'User creates a new page', js: true do
visit posts_path
visit posts_path(as: create(:admin))

click_on 'Add new Post'

Expand Down
45 changes: 45 additions & 0 deletions spec/policies/post_policy_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require 'rails_helper'

describe PostPolicy do
let(:post) { build(:post) }

subject { PostPolicy.new(user, post) }

context "for a visitor" do
let(:user) { nil }

it { should permit(:index) }
it { should permit(:show) }

it { should_not permit(:create) }
it { should_not permit(:new) }
it { should_not permit(:update) }
it { should_not permit(:edit) }
it { should_not permit(:destroy) }
end

context "for a user" do
let(:user) { build(:user) }

it { should permit(:index) }
it { should permit(:show) }

it { should_not permit(:create) }
it { should_not permit(:new) }
it { should_not permit(:update) }
it { should_not permit(:edit) }
it { should_not permit(:destroy) }
end

context "for a admin" do
let(:user) { build(:admin) }

it { should permit(:index) }
it { should permit(:show) }
it { should permit(:create) }
it { should permit(:new) }
it { should permit(:update) }
it { should permit(:edit) }
it { should permit(:destroy) }
end
end
13 changes: 13 additions & 0 deletions spec/support/pundit.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
RSpec::Matchers.define :permit do |action|
match do |policy|
policy.public_send("#{action}?")
end

failure_message do |policy|
"#{policy.class} does not permit #{action} on #{policy.record} for #{policy.user.inspect}."
end

failure_message_when_negated do |policy|
"#{policy.class} does not forbid #{action} on #{policy.record} for #{policy.user.inspect}."
end
end

0 comments on commit 518b95c

Please sign in to comment.