Skip to content

Commit

Permalink
Add Blog Policy
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisalley committed Oct 25, 2024
1 parent f3653ad commit 7abfc0d
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 0 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ group :development, :test do
end

group :test do
gem "factory_bot_rails", "~> 6.4"
gem "shoulda-matchers", "~> 6.0"
gem "pundit-matchers", "~> 3.1"
end
Expand Down
6 changes: 6 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ GEM
diff-lcs (1.5.1)
drb (2.2.1)
erubi (1.13.0)
factory_bot (6.5.0)
activesupport (>= 5.0.0)
factory_bot_rails (6.4.3)
factory_bot (~> 6.4)
railties (>= 5.0.0)
globalid (1.2.1)
activesupport (>= 6.1)
i18n (1.14.6)
Expand Down Expand Up @@ -325,6 +330,7 @@ DEPENDENCIES
brakeman
debug
devise (~> 4.9)
factory_bot_rails (~> 6.4)
importmap-rails
jbuilder
puma (>= 5.0)
Expand Down
52 changes: 52 additions & 0 deletions app/policies/blog_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
class BlogPolicy < ApplicationPolicy
class Scope
attr_reader :user, :scope

def initialize(user, scope)
@user = user
@scope = scope
end

def resolve
scope
end
end

def index?
true
end

def show?
true
end

def new?
create?
end

def create?
is_admin?
end

def edit?
update?
end

def update?
is_admin? || is_owner?
end

def destroy?
update? && record.posts.count == 0
end

private

def is_admin?
user&.administrator
end

def is_owner?
user&.id == record.user.id
end
end
9 changes: 9 additions & 0 deletions spec/factories/blogs.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FactoryBot.define do
factory :blog do
factory :valid_blog do
sequence(:name) { |n| "Blog #{n}" }
user { FactoryBot.create(:registered_user) }
posts { [] }
end
end
end
9 changes: 9 additions & 0 deletions spec/factories/posts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FactoryBot.define do
factory :post do
factory :valid_post do
sequence(:name) { |n| "Post #{n}" }
user { FactoryBot.create(:registered_user) }
blog { FactoryBot.create(:valid_blog) }
end
end
end
13 changes: 13 additions & 0 deletions spec/factories/users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FactoryBot.define do
factory :user do
factory :registered_user do
sequence(:email) { |n| "testuser#{n}@example.com" }
password { '1234567A' }
password_confirmation { '1234567A' }

factory :administrator do
administrator { true }
end
end
end
end
51 changes: 51 additions & 0 deletions spec/policies/blog_policy_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
require 'rails_helper'

describe BlogPolicy do
subject { described_class.new(user, blog) }

let(:resolved_scope) { described_class::Scope.new(user, Blog.all).resolve }
let(:blog) { FactoryBot.create(:valid_blog) }

context 'with visitors' do
let(:user) { nil }

it { expect(resolved_scope).to include(blog) }
it { is_expected.to permit_only_actions(%i[index show]) }
it { is_expected.to forbid_actions(%i[new create edit update destroy]) }
end

context 'with registered users' do
let(:user) { FactoryBot.create(:registered_user) }

it { expect(resolved_scope).to include(blog) }
it { is_expected.to permit_only_actions(%i[index show]) }
it { is_expected.to forbid_actions(%i[new create edit update destroy]) }

context 'when registered user is the blog owner' do
before { blog.user = user }

it { is_expected.to permit_only_actions(%i[index show edit update destroy]) }
it { is_expected.to forbid_new_and_create_actions }

context 'blog has a post' do
before { blog.posts << FactoryBot.create(:valid_post) }

it { is_expected.to forbid_action(:destroy) }
end
end
end

context 'with administrators' do
let(:user) { FactoryBot.create(:administrator) }
let(:blog) { FactoryBot.create(:valid_blog) }

it { expect(resolved_scope).to include(blog) }
it { is_expected.to permit_all_actions }

context 'blog has a post' do
before { blog.posts << FactoryBot.create(:valid_post) }

it { is_expected.to forbid_action(:destroy) }
end
end
end
1 change: 1 addition & 0 deletions spec/rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
# return unless Rails.env.test?
require 'rspec/rails'
# Add additional requires below this line. Rails is not loaded until this point!
require 'factory_bot'

# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
Expand Down

0 comments on commit 7abfc0d

Please sign in to comment.