Skip to content

Commit

Permalink
Support CanCanCan 2.x
Browse files Browse the repository at this point in the history
Fixes #2901, Closes #3029
  • Loading branch information
mshibuya committed Jul 1, 2018
1 parent 431e11b commit a32d49e
Show file tree
Hide file tree
Showing 15 changed files with 181 additions and 146 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ matrix:
- rvm: 2.3.7
env: CI_ORM=active_record CI_DB_ADAPTER=postgresql CI_DB_USERNAME=postgres
gemfile: gemfiles/rails_5.2.gemfile
- rvm: 2.3.7
env: CI_ORM=active_record CI_DB_ADAPTER=sqlite3
gemfile: gemfiles/cancan.gemfile
- rvm: 2.4.4
env: CI_ORM=mongoid
gemfile: gemfiles/rails_5.2.gemfile
Expand Down
35 changes: 34 additions & 1 deletion Appraisals
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ appraise "rails-4.0" do
gem 'capybara', '>= 0.8', group: :test
gem 'kaminari', '~> 0.14'

group :test do
gem 'cancancan', '~> 1.12'
end

group :active_record do
gem 'paper_trail', '~> 5.0'

Expand Down Expand Up @@ -35,6 +39,10 @@ appraise "rails-4.1" do
gem 'devise', '>= 3.2'
gem 'capybara', '>= 0.8', group: :test

group :test do
gem 'cancancan', '~> 1.12'
end

group :active_record do
gem 'paper_trail', '>= 5.0'

Expand Down Expand Up @@ -65,6 +73,10 @@ appraise "rails-4.2" do
gem 'devise', '>= 3.4'
gem 'capybara', '>= 0.8', group: :test

group :test do
gem 'cancancan', '~> 1.12'
end

group :active_record do
gem 'paper_trail', '>= 5.0'

Expand Down Expand Up @@ -94,6 +106,10 @@ appraise "rails-5.0" do
gem 'sass-rails', '~> 5.0'
gem 'devise', '~> 4.0'

group :test do
gem 'cancancan', '~> 2.0'
end

group :active_record do
gem 'paper_trail', '>= 5.0'

Expand All @@ -109,6 +125,7 @@ appraise "rails-5.0" do
gem 'kaminari-mongoid'
gem 'mongoid-paperclip', '>= 0.0.8', require: 'mongoid_paperclip'
gem 'carrierwave-mongoid', '>= 0.6.3', require: 'carrierwave/mongoid'
gem 'cancancan-mongoid'
end
end

Expand All @@ -117,6 +134,10 @@ appraise "rails-5.1" do
gem 'sass-rails', '~> 5.0'
gem 'devise', '~> 4.0'

group :test do
gem 'cancancan', '~> 2.0'
end

group :active_record do
gem 'pg', '~> 0.14', platforms: :ruby
gem 'paper_trail', '>= 5.0'
Expand All @@ -133,6 +154,7 @@ appraise "rails-5.1" do
gem 'kaminari-mongoid'
gem 'mongoid-paperclip', '>= 0.0.8', require: 'mongoid_paperclip'
gem 'carrierwave-mongoid', '>= 0.6.3', require: 'carrierwave/mongoid'
gem 'cancancan-mongoid'
end
end

Expand All @@ -142,7 +164,7 @@ appraise "rails-5.2" do
gem 'devise', '~> 4.4'

group :test do
gem 'cancancan', '~> 1.12', github: 'mshibuya/cancancan', branch: 'topic-backport-rails-5-2-support-to-1-x'
gem 'cancancan', '~> 2.0'
end

group :active_record do
Expand All @@ -155,5 +177,16 @@ appraise "rails-5.2" do
gem 'kaminari-mongoid'
gem 'mongoid-paperclip', '>= 0.0.8', require: 'mongoid_paperclip'
gem 'carrierwave-mongoid', '>= 0.6.3', require: 'carrierwave/mongoid'
gem 'cancancan-mongoid'
end
end

appraise "cancan" do
gem 'rails', '~> 5.1.0'
gem 'sass-rails', '~> 5.0'
gem 'devise', '~> 4.0'

group :test do
gem 'cancan', '>= 1.6'
end
end
2 changes: 0 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ group :development, :test do
end

group :test do
gem 'cancan', '>= 1.6'
gem 'cancancan', '~> 1.12'
gem 'carrierwave', '>= 0.8'
gem 'coveralls'
gem 'database_cleaner', ['>= 1.2', '!= 1.4.0', '!= 1.5.0']
Expand Down
48 changes: 48 additions & 0 deletions gemfiles/cancan.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# This file was generated by Appraisal

source "https://rubygems.org"

gem "appraisal", ">= 2.0"
gem "rails", "~> 5.1.0"
gem "haml"
gem "devise", "~> 4.0"
gem "sass-rails", "~> 5.0"

group :active_record do
gem "paper_trail"

platforms :ruby, :mswin, :mingw do
gem "mysql2", ">= 0.3.14"
gem "sqlite3", ">= 1.3"
end
end

group :development, :test do
gem "pry", ">= 0.9"
end

group :test do
gem "carrierwave", ">= 0.8"
gem "coveralls"
gem "database_cleaner", [">= 1.2", "!= 1.4.0", "!= 1.5.0"]
gem "dragonfly", "~> 1.0"
gem "factory_girl", ">= 4.2"
gem "generator_spec", ">= 0.8"
gem "launchy", ">= 2.2"
gem "mini_magick", ">= 3.4"
gem "paperclip", [">= 3.4", "!= 4.3.0"]
gem "poltergeist", "~> 1.5"
gem "pundit"
gem "rack-cache", require: "rack/cache"
gem "rspec-rails", ">= 2.14"
gem "rubocop", "~> 0.41.2"
gem "simplecov", ">= 0.9", require: false
gem "timecop", ">= 0.5"
gem "cancan", ">= 1.6"

platforms :ruby_19 do
gem "tins", "~> 1.6.0", require: false
end
end

gemspec path: "../"
3 changes: 1 addition & 2 deletions gemfiles/rails_4.0.gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ group :development, :test do
end

group :test do
gem "cancan", ">= 1.6"
gem "cancancan", "~> 1.12"
gem "carrierwave", ">= 0.8"
gem "coveralls"
gem "database_cleaner", [">= 1.2", "!= 1.4.0", "!= 1.5.0"]
Expand All @@ -49,6 +47,7 @@ group :test do
gem "rubocop", "~> 0.41.2"
gem "simplecov", ">= 0.9", require: false
gem "timecop", ">= 0.5"
gem "cancancan", "~> 1.12"

platforms :ruby_19 do
gem "tins", "~> 1.6.0", require: false
Expand Down
3 changes: 1 addition & 2 deletions gemfiles/rails_4.1.gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ group :development, :test do
end

group :test do
gem "cancan", ">= 1.6"
gem "cancancan", "~> 1.12"
gem "carrierwave", ">= 0.8"
gem "coveralls"
gem "database_cleaner", [">= 1.2", "!= 1.4.0", "!= 1.5.0"]
Expand All @@ -46,6 +44,7 @@ group :test do
gem "rubocop", "~> 0.41.2"
gem "simplecov", ">= 0.9", require: false
gem "timecop", ">= 0.5"
gem "cancancan", "~> 1.12"

platforms :ruby_19 do
gem "tins", "~> 1.6.0", require: false
Expand Down
3 changes: 1 addition & 2 deletions gemfiles/rails_4.2.gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ group :development, :test do
end

group :test do
gem "cancan", ">= 1.6"
gem "cancancan", "~> 1.12"
gem "carrierwave", ">= 0.8"
gem "coveralls"
gem "database_cleaner", [">= 1.2", "!= 1.4.0", "!= 1.5.0"]
Expand All @@ -47,6 +45,7 @@ group :test do
gem "rubocop", "~> 0.41.2"
gem "simplecov", ">= 0.9", require: false
gem "timecop", ">= 0.5"
gem "cancancan", "~> 1.12"

platforms :ruby_19 do
gem "tins", "~> 1.6.0", require: false
Expand Down
4 changes: 2 additions & 2 deletions gemfiles/rails_5.0.gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ group :development, :test do
end

group :test do
gem "cancan", ">= 1.6"
gem "cancancan", "~> 1.12"
gem "carrierwave", ">= 0.8"
gem "coveralls"
gem "database_cleaner", [">= 1.2", "!= 1.4.0", "!= 1.5.0"]
Expand All @@ -46,6 +44,7 @@ group :test do
gem "rubocop", "~> 0.41.2"
gem "simplecov", ">= 0.9", require: false
gem "timecop", ">= 0.5"
gem "cancancan", "~> 2.0"

platforms :ruby_19 do
gem "tins", "~> 1.6.0", require: false
Expand All @@ -57,6 +56,7 @@ group :mongoid do
gem "kaminari-mongoid"
gem "mongoid-paperclip", ">= 0.0.8", require: "mongoid_paperclip"
gem "carrierwave-mongoid", ">= 0.6.3", require: "carrierwave/mongoid"
gem "cancancan-mongoid"
end

gemspec path: "../"
4 changes: 2 additions & 2 deletions gemfiles/rails_5.1.gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ group :development, :test do
end

group :test do
gem "cancan", ">= 1.6"
gem "cancancan", "~> 1.12"
gem "carrierwave", ">= 0.8"
gem "coveralls"
gem "database_cleaner", [">= 1.2", "!= 1.4.0", "!= 1.5.0"]
Expand All @@ -47,6 +45,7 @@ group :test do
gem "rubocop", "~> 0.41.2"
gem "simplecov", ">= 0.9", require: false
gem "timecop", ">= 0.5"
gem "cancancan", "~> 2.0"

platforms :ruby_19 do
gem "tins", "~> 1.6.0", require: false
Expand All @@ -58,6 +57,7 @@ group :mongoid do
gem "kaminari-mongoid"
gem "mongoid-paperclip", ">= 0.0.8", require: "mongoid_paperclip"
gem "carrierwave-mongoid", ">= 0.6.3", require: "carrierwave/mongoid"
gem "cancancan-mongoid"
end

gemspec path: "../"
4 changes: 2 additions & 2 deletions gemfiles/rails_5.2.gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ group :development, :test do
end

group :test do
gem "cancan", ">= 1.6"
gem "cancancan", "~> 1.12", github: "mshibuya/cancancan", branch: "topic-backport-rails-5-2-support-to-1-x"
gem "carrierwave", ">= 0.8"
gem "coveralls"
gem "database_cleaner", [">= 1.2", "!= 1.4.0", "!= 1.5.0"]
Expand All @@ -41,6 +39,7 @@ group :test do
gem "rubocop", "~> 0.41.2"
gem "simplecov", ">= 0.9", require: false
gem "timecop", ">= 0.5"
gem "cancancan", "~> 2.0"

platforms :ruby_19 do
gem "tins", "~> 1.6.0", require: false
Expand All @@ -52,6 +51,7 @@ group :mongoid do
gem "kaminari-mongoid"
gem "mongoid-paperclip", ">= 0.0.8", require: "mongoid_paperclip"
gem "carrierwave-mongoid", ">= 0.6.3", require: "carrierwave/mongoid"
gem "cancancan-mongoid"
end

gemspec path: "../"
2 changes: 1 addition & 1 deletion lib/rails_admin/extensions/cancancan.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
require 'rails_admin/extensions/cancancan/authorization_adapter'

RailsAdmin.add_extension(:cancan, RailsAdmin::Extensions::CanCanCan, authorization: true)
RailsAdmin.add_extension(:cancancan, RailsAdmin::Extensions::CanCanCan, authorization: true)
53 changes: 15 additions & 38 deletions lib/rails_admin/extensions/cancancan/authorization_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,28 @@ module RailsAdmin
module Extensions
module CanCanCan
# This adapter is for the CanCanCan[https://github.com/CanCanCommunity/cancancan] authorization library.
class AuthorizationAdapter
# See the +authorize_with+ config method for where the initialization happens.
def initialize(controller, ability = ::Ability)
@controller = controller
@controller.instance_variable_set '@ability', ability
@controller.extend ControllerExtension
@controller.current_ability.authorize! :access, :rails_admin
end

# This method is called in every controller action and should raise an exception
# when the authorization fails. The first argument is the name of the controller
# action as a symbol (:create, :bulk_delete, etc.). The second argument is the
# AbstractModel instance that applies. The third argument is the actual model
# instance if it is available.
class AuthorizationAdapter < RailsAdmin::Extensions::CanCan::AuthorizationAdapter
def authorize(action, abstract_model = nil, model_object = nil)
@controller.current_ability.authorize!(action, model_object || abstract_model && abstract_model.model) if action
return unless action
action, subject = resolve_action_and_subject(action, abstract_model, model_object)
@controller.current_ability.authorize!(action, subject)
end

# This method is called primarily from the view to determine whether the given user
# has access to perform the action on a given model. It should return true when authorized.
# This takes the same arguments as +authorize+. The difference is that this will
# return a boolean whereas +authorize+ will raise an exception when not authorized.
def authorized?(action, abstract_model = nil, model_object = nil)
@controller.current_ability.can?(action, model_object || abstract_model && abstract_model.model) if action
return unless action
action, subject = resolve_action_and_subject(action, abstract_model, model_object)
@controller.current_ability.can?(action, subject)
end

# This is called when needing to scope a database query. It is called within the list
# and bulk_delete/destroy actions and should return a scope which limits the records
# to those which the user can perform the given action on.
def query(action, abstract_model)
abstract_model.model.accessible_by(@controller.current_ability, action)
end

# This is called in the new/create actions to determine the initial attributes for new
# records. It should return a hash of attributes which match what the user
# is authorized to create.
def attributes_for(action, abstract_model)
@controller.current_ability.attributes_for(action, abstract_model && abstract_model.model)
end
private

module ControllerExtension
def current_ability
# use _current_user instead of default current_user so it works with
# whatever current user method is defined with RailsAdmin
@current_ability ||= @ability.new(_current_user)
def resolve_action_and_subject(action, abstract_model, model_object)
subject = model_object || abstract_model && abstract_model.model
if subject
[action, subject]
else
# For :dashboard compatibility
[:read, action]
end
end
end
Expand Down
23 changes: 4 additions & 19 deletions spec/helpers/rails_admin/application_helper_spec.rb
Original file line number Diff line number Diff line change
@@ -1,27 +1,12 @@
require 'spec_helper'
require 'cancan'

class TestAbility
include CanCan::Ability
def initialize(_user)
can :access, :rails_admin
can :edit, FieldTest
cannot :edit, FieldTest, string_field: 'dangerous'
end
end

describe RailsAdmin::ApplicationHelper, type: :helper do
describe '#authorized?' do
before do
allow(RailsAdmin.config).to receive(:_current_user).and_return(FactoryGirl.create(:user))
allow(helper.controller).to receive(:authorization_adapter).and_return(RailsAdmin::AUTHORIZATION_ADAPTERS[:cancan].new(RailsAdmin.config, TestAbility))
end
let(:abstract_model) { RailsAdmin.config(FieldTest).abstract_model }

it 'doesn\'t test unpersisted objects' do
am = RailsAdmin.config(FieldTest).abstract_model
expect(helper.authorized?(:edit, am, FactoryGirl.create(:field_test, string_field: 'dangerous'))).to be_falsey
expect(helper.authorized?(:edit, am, FactoryGirl.create(:field_test, string_field: 'not-dangerous'))).to be_truthy
expect(helper.authorized?(:edit, am, FactoryGirl.build(:field_test, string_field: 'dangerous'))).to be_truthy
it 'doesn\'t use unpersisted objects' do
expect(helper).to receive(:action).with(:edit, abstract_model, nil).and_call_original
helper.authorized?(:edit, abstract_model, FactoryGirl.build(:field_test))
end
end

Expand Down
Loading

0 comments on commit a32d49e

Please sign in to comment.