cancancommunity / cancancan Goto Github PK
View Code? Open in Web Editor NEWThe authorization Gem for Ruby on Rails.
License: MIT License
The authorization Gem for Ruby on Rails.
License: MIT License
#ability
can :show, Parent
can :index, Child
#controller
load_and_authorize_resource :parent
load_and_authorize_resource :child, :through => :parent
def index
end
The index action fails on not having the ability to :index Parent.
Access denied on index {#<Parent ..
Stepping through the code, Parent is authorized on :show first which is correct.
When authorizing Child:
def authorize_resource
unless skip?(:authorize)
@controller.authorize!(authorization_action, resource_instance || resource_class_with_parent)
end
end
resource_instance
is nil and resource_class_with_parent
returns a hash:
subject_hash = resource_class_with_parent
=> {<#Parent instance..> => Child(class) }
Child is then ignored completely when matching the rule
def nested_subject_matches_conditions?(subject_hash)
parent, child = subject_hash.first
matches_conditions_hash?(parent, @conditions[parent.class.name.downcase.to_sym] || {})
end
It would appear this subject notation has to do with nesting and is no longer being used. resource_class_with_parent
is not used anywhere else.
defining authorize_resource
to return the resource class instead solves this issue.
def authorize_resource
unless skip?(:authorize)
@controller.authorize!(authorization_action, resource_instance || resource_class)
end
end
The tests do not indicate an reason why this should not be the case all of the time. Is this behaviour intended?
Rails 4 + Cancan
ability.rb
if user.is_sys_admin?
can :manage, [MdmArea, MdmCity, MdmCountry, MdmState] #Model Array
end
mdm_controller.rb
authorize_resource ['MdmCountry', 'MdmState', 'MdmCity', 'MdmArea'] # Not working
Please solve this ? or any solution
Thanks
I am having trouble using cancancan to select records based on abilities.
My ability.rb file looks like this:
can :read, Business if user.admin?
can :read, Business, Business.user_related(user) do
Business.user_related(user).any?
end
My controller tries this:
@businesses = Business.accessible_by(current_ability, :read)
If I comment out the top rule, everything seems to work. That is, I can load businesses produced by the Business.user_related scope. But if I include the top rule I get the error: "Unable to merge an Active Record scope with other conditions. Instead use a hash or SQL for read Business ability."
If the user is an admin, cancancan doesn't need to consult the database at all - they have access to all businesses. How can I express this in ability.rb?
Hello,
Backporting issue from ryanb/cancan#774
In the following configuration:
class ItemsController < ApplicationController
load_resource :user
load_and_authorize_resource :item, :through => :user
def create
@item.save
end
end
ItemsController#create
is called through a HTTP POST to a classic route like /users/4/items
.
If we submit params like { :user_id => 4, :title => 'test' }
to #create
, everything works fine.
Now if we submit params like { :title => 'test' }
to #create
, then what happen is that the created items belongs to the currently logged user.
This is because in ControllerResource#build_resource
, when #assign_attributes
calls #initial_attributes
the latter ends up assigning 'user_id' the nested resource.
Ironically, without the #assign_attributes
call everything would be working fine as it'd build the resource through its parent and thus user_id
would be correctly set.
I know that theorically I'd be sending user_id
to build this resource, but I thought cancan's load_resource :through
would do the equivalent of @user.items.build(params[:item])
which would work, but apparently that's not the case.
I'm using cancancan to get an index of objects from my database. In this case, each object has a very large text field (in some cases >1MB) that I don't need for the index option. I have found that this means that doing the index for some customers right now takes >7s!
Since all I need is a selection of info about each item in the database (e.g. title), I wanted to select only e.g. the title and id. However, since cancancan uses includes
(not joins
) internally, the select is completely ignored and there's no way to NOT select that large text field.
May I propose that, when using accessible_by, cancancan should use joins instead such that those using the gem can ignore large fields that may slow things down?
I believe the relevant line is here: https://github.com/CanCanCommunity/cancancan/blob/develop/lib/cancan/model_adapters/active_record_adapter.rb#L104
I'm happy to provide a PR if I can get a hint about how I might know at that point of the code how we're doing an accessible_by
instead of a normal permissions check.
Hi all,
I've tried to use cancancan on my rails app and so far it's fine. However, once I tried to apply it to non model backed controllers with non restful resources, I run into several issues.
I use authorize_resource :class => false, which according to the documentation should be calling:
authorize!
on every action in the controller for me automatically.
unfortunately this is not the case and the authorization is only done if I call authorize on every single action in the controller.
Is there a way around this?
DOESN'T WORK:
class DashboardsController < ApplicationController
authorize_resource :class => false
def home
end
WORKS:
class DashboardsController < ApplicationController
authorize_resource :class => false
def home
authorize! :home, :dashboard
end
I create example app: https://github.com/znz/rails4-cancancan-example
In the app, http://localhost:3000/comments/new?comment%5Bpost_id%5D=1
causes ActiveModel::ForbiddenAttributesError
.
In lib/cancan/controller_resource.rb
,
resource_params
called from build_resource
returns params['comment']
directly instead of comment_params
(includes permit
) because param_actions
does not include :new
.
For now, I will use post_id=1
instead of comment[post_id]=1
and set comment.post_id = params[:post_id]
in CommentController#new
.
There are too many differences in the way AR 3 and 4 work and the active_record_model_adapter
code is too complex already. Lets extract out a separate AR 4 and AR 3 adapter (perhaps inheriting from the same parent).
This does, to an extent still rely on #14 and getting some proper testing done, but work can begin on both.
Issues that deal with AR 4 specific logic will be useful for the AR4 adapter:
#26
#39
The current implementation of assign_attributes
doesn't make use of strong_parameters
and bypasses mass-assignment protection afforded by attr_accessible
. This presents a major potential security issue.
I am using load_and_authorise_resource
for my BoomsController and my BlastsController.
Blasts have many booms, Booms have many keywords.
Since the addition of the ability for Blast, I cannot access the index page for blasts. I get the error:
undefined method `class_name' for nil:NilClass
lib/cancan/model_adapters/active_record_adapter.rb
def tableized_conditions(conditions, model_class = @model_class)
return conditions unless conditions.kind_of? Hash
conditions.inject({}) do |result_hash, (name, value)|
if value.kind_of? Hash
value = value.dup
association_class = model_class.reflect_on_association(name).class_name.constantize
nested = value.inject({}) do |nested,(k,v)|
if v.kind_of? Hash
value.delete(k)
nested[k] = v
else
can :create, Boom
can :manage, Boom, :keyword => { :organization => { :id => Organization.with_role(:operator, user).pluck(:id) } }
can :create, Blast
can :manage, Blast, :boom => { :keyword => { :organization => { :id => Organization.with_role(:operator, user).pluck(:id) } } }
In ability.rb, line 288 the function keys
is called on the subject to figure out whether it's a hash.
In my app I have a model called Key
and another one that has_many :keys
. This causes cancan to fail there with undefined method key?
.
Maybe cancan should check the subject's class rather than whether the method exists?
Hello,
When you have the following:
# Models
class Item
has_many :permissions, as: :subject
end
class Permission
belongs_to :user
belongs_to :subject, polymorphic: true
# db field 'action'
end
# Ability
alias_action :read, :update, :destroy, to: :modify
can :read, Item, permissions: { action: 'read', user_id: user.id }
can :modify, Item, permissions: { action: 'modify', user_id: user.id }
Trying to do Item.accessible_by(current_ability)
fails with the following error:
Mysql2::Error: Unknown column 'permissions.action' in 'where clause': SELECT `items`.* FROM `items` WHERE ((`permissions`.`action` = 'modify' AND `permissions`.`user_id` = 14) OR (`permissions`.`action` = 'read' AND `permissions`.`user_id` = 14))
To fix it, you can do one of the following:
:read
action from the :modify
aliascan :read, ...
rulecan [:read, :update, :destroy], ...
instead of can :modify
This only seem to happen with :read
, I couldn't reproduce with :update
.
See #74 for more informations.
Is there are some work planed on parameter authorization feature?
Article I found (http://hawkins.io/2012/07/parameter_authorization_in_rails_apis/) helps to deal with that issue, but I would like to have this embedded in the cancancan
as a part of it's DSL.
I know that the original cancan have some functionality of that feature in the branch 2.0.
PS. https://github.com/CanCanCommunity/cancancan#strong-parameters is great, but I guess it should be moved to the Ability class, so it will be isolated from the controller, and incapsulated in one place, for easier overview of permissions and consistency between actions and controllers.
I tried to install cancancan on my windows machine and when I tried to run bundle install, I got an error when kgio-2.9.2 tried to install. After doing some research, I found that KGIO doesn't work on windows.
Does cancancan depend on KGIO? I didn't see it in the dependencies. If not, is there something strange going on?
Thanks!
Alex
First you delete an entire article of me saying the contents of this article is better off inside the other wiki pages, so far so good (even if it'd have been better to edit the article with the edit proposal at top and let me move/delete it).
Then I do that and you still revert the changes to the other wiki articles without a reason:
https://github.com/CanCanCommunity/cancancan/wiki/Checking-Abilities/_history
At least provide an explanation because that sends a wrong signal, something like "please don't contribute".
Hi,
Quick question. I started using cancan (Gem lock says v1.6) with my own Rails 4 app and set all the abilities up. I'm getting this error:
The can? and cannot? call cannot be used with a raw sql 'can' definition. The checking code cannot be determined for :new
I'm pretty sure that has to do with the use of Rails 4.
Q1 : Is it a strong parameter issue ?
Q2: How to upgrade to cancancan from cancan 1.6. Does it suffice to remove the gem/replace it with the cancancan or do i have to delete some initializers too ?
Thanks in advance,
When load_resource is invoked by a new
action it initialises the object with parameters, as cancan always did. At the moment this doesn't work because the params_method machinery - for which we thank you very much - is only invoked for actions that are in param_actions, and :new is not one of them.
Initialising a new object without populating it from params would probably break a lot of code so I suggest that we apply the strong_parameters mechanism on new as well.
Hi,
I can't figure out what is going on here. I am trying to define the ability for a user to update their own user details. I'm following the wiki.
This is my ability.rb
:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.admin?
can :manage, User
else
can [:read, :update], User, id: '51524f53745448da24000003' # THIS DOESN'T WORK
# can [:read, :update], User, id: user.id # THIS WORKS
end
end
end
When I define the id:
as user.id
instead of the Mongo id it works, which is really weird. Could it be something to do with Mongo?
I am using better_errors to inspect the CanCan::AccessDenied
when I make a request to http://localhost:3001/users/51524f53745448da24000003/edit
and this is what it shows:
Local Variables
action :edit
subject #<User _id: 51524f53745448da24000003, created_at: 2013-03-27 01:45:55 UTC, updated_at: 2014-06-03 04:56:25 UTC, name: "Dave", email: "[email protected]", encrypted_password: "$2a$10$RDVcNWyxAOglTtFwPobPw.ZIFV5JL0zoart7r.ausx1VIlB2b7yeq", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 18, current_sign_in_at: 2014-06-03 04:15:50 UTC, last_sign_in_at: 2014-05-28 22:55:02 UTC, current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", authentication_token: "cpGcucqF5B1nNzKvYs3Q", role: "user", active: true, contributors: ["", "522d56d6745448a573000076", "522d572c745448a57300007d"], run_harvests: nil>
args []
message nil
Instance Variables
@rules [#<CanCan::Rule:0x007f9df4970ee8 @conditions={:id=>"51524f53745448da24000003"}, @base_behavior=true, @expanded_actions=[:read, :index, :show, :update, :edit], @block=nil, @actions=[:read, :update], @match_all=false, @subjects=[User]>, #<CanCan::Rule:0x007f9df4970d30 @conditions={:id=>"522e8549745448bb70000003"}, @base_behavior=true, @expanded_actions=[:edit], @block=nil, @actions=[:edit], @match_all=false, @subjects=[Source]>]
Notice that conditions.id
of the User
rule has the correct id. However, the local variable args is an empty array, surely this should be id: '51524f53745448da24000003'
?
I realise that hard-coding the id is really bad, but I'm trying to understand why it's not working rather than use this in the real world.
Note, that I used to be using cancan
, when I couldn't get past this issue I tried using cancancan
but have exactly the same issue.
Thanks,
Dave
in file https://github.com/CanCanCommunity/cancancan/blob/develop/lib/cancan/rule.rb#L94 is do follow comparison
subject.class.to_s == sub.to_s
but ยดsubject.class.to_sยด aways return "Class" instead of "ModelName" . This is correct?
I using this guide (https://github.com/CanCanCommunity/cancancan/wiki/Role-Based-Authorization) to using a bitmask (I added a column named "roles_mask" to user model).
I have this files involved:
I folowed word by word of this guide except the lines that I wrote for indicate that roles is a accessible attribute:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_filter :configure_permitted_parameters, if: :devise_controller?
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:email, :password, :password_confirmation, :roles) }
end
end
When create a user, all fields are captured except :roles_mask =/, I don't understand why roles field is not captured. I think there's something that I don't achieve to see. I got a message "Unpermitted parameters: roles" in trace.
@models = Model.accessible_by(current_ability) gives me:
"NoMethodError at /models".
What am I doing wrong?
I am on Linux 3.2.0-60-generic #91-Ubuntu with ruby 2.1.1p76 (2014-02-24 revision 45161) [x86_64-linux] , Rails 4.0.3 and 'mongoid', :github=>"mongoid/mongoid".
This is the Gemfile:
source 'https://rubygems.org'
gem 'rails', '4.0.3'
gem 'sass-rails', '> 4.0.0'> 4.0.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '
gem 'jquery-rails'
gem 'jquery-ui-rails'
gem 'turbolinks'
gem 'jbuilder', '> 1.2'> 1.7'
gem 'bootstrap-sass'
gem 'cancancan', '
gem 'country_select'
gem 'devise'
gem 'mongoid', :github=>"mongoid/mongoid"
gem 'figaro'
gem 'rolify'
gem 'simple_form'
gem "kaminari"
group :development do
gem 'better_errors'
gem 'binding_of_caller', :platforms=>[:mri_19, :mri_20, :rbx]
gem 'quiet_assets'
gem 'rails_layout'
end
group :production do
gem 'unicorn'
end
group :doc do
gem 'sdoc', require: false
end
gem 'debugger', group: [:development, :test]
Need help.
Hello,
I found this blog post that explain the problem I'm having:
http://www.tigraine.at/2014/03/13/cancan-beware-of-symbol-conditions
Basically, if you look at the following rules:
can :manage, Item, user: { role: :admin } #1
can :manage, Item, user: { role: 'admin' } #2
With both rules Item.accessible_by(current_ability)
will return the correct results. But only the 2nd rule will work with can? :manage, Item.accessible_by(current_ability).first
This is because the symbols are not translated to a string the usual way rails does.
Not sure if really a bug or a not.
[EDIT] I believe this is a bug, just because of the unexpected behavior.
Hi,
First, i've just found out this fork of cancan. AWESOME ! So thanks for keeping cancan alive.
Now on to the issue.
I've tried defining two abilities as follow:
can :manage, Entity, id: @entity.id
can :manage, @entity
They seem to be identical in what they do but they actually aren't. I see the difference when i do:
Entity.accessible_by(current_ability)
Using the first definition, i get a list containing my entity.
using the second one i get an empty list (and the executed SQL has that strange 't'='f'
condition in it)
It would be great if both those abilities worked the same way. I like using Entity.accessible_by
as a generic way to get my entities. Depending on the user, the entity may not always be the same (i'm using a polymorphic association) so the above statements aren't actually the same in my case (@entity
can either be a TypeOneEntity
or a TypeTwoEntity
).
Thanks
Hello!
I'm trying to use CanCan in my new project. Let's say we have two models - Event
and Band
. Event
has many Bands
and it's possible to create a new ones using nested_attributes and fields_for
forms.
Everything works great when cancan is turned off. However, if i'll enable it for events_controller
and add a new band using nested_fields, i'm getting:
Couldn't find Band with id=0
which is rised by @event = Event.new(event_params)
line in create
method. It happens only when i'm trying to create a new event. When event exists and i'm creating a band in event edit form - no exception is thrown.
My ability.rb
file looks like that:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
# Guests
can :read, :all
# Members
unless user.new_record?
can [:edit, :update, :new, :create], Event, user_id: user.id
can [:edit, :update, :new, :create], Band
end
end
end
Have you any idea what am i doing wrong here? Thanks in advance.
I have two tables that are joined - both tables are name-spaced.
When I define an ability that sets up a nested condition - the accessible_by method fails with this error (uninitialized constant):
1) CanCan::ModelAdapters::ActiveRecordAdapter fetches all namespace::table_x when one is related by table_y
Failure/Error: expect(Namespace::TableX.accessible_by(ability)).to eq([table_x])
NameError:
uninitialized constant TableZ
# ./lib/cancan/model_adapters/active_record_adapter.rb:71:in `block in tableized_conditions'
# ./lib/cancan/model_adapters/active_record_adapter.rb:67:in `each'
# ./lib/cancan/model_adapters/active_record_adapter.rb:67:in `inject'
# ./lib/cancan/model_adapters/active_record_adapter.rb:67:in `tableized_conditions'
# ./lib/cancan/model_adapters/active_record_adapter.rb:57:in `conditions'
# ./lib/cancan/model_adapters/active_record_adapter.rb:105:in `database_records'
# ./lib/cancan/model_additions.rb:23:in `accessible_by'
# ./spec/cancan/model_adapters/active_record_adapter_spec.rb:98:in `block (2 levels) in <top (required)>'
I have a proposed fix - but not 100% sure if it is the "right" way to fix things". I'll be submitting a pull request that includes a test that would fail prior to the fix and the fix.
After switching from CanCan, I noticed (Rails 3.2.17) that my queries of the below were failing:
SomeModel.where(admin_id: Admin.accessible_by(current_ability, :read))
Would throw an exception of the form:
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: missing FROM-clause entry for table "customers"
LINE 1: ..." ON "roles"."id" = "users_roles"."role_id" WHERE "customers...
^
: SELECT "users"."id" FROM "users" INNER JOIN "users_roles" ON "users_roles"."user_id" = "users"."id" INNER JOIN "roles" ON "roles"."id" = "users_roles"."role_id" WHERE "customers"."id" IN (1) AND (((roles.name = 'admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))
Admin
is using Rolify to generate the admin role in the query above and the query is scoped by the current customer_id as defined by the ability:
can [:read, :update], Admin, customers: {id: user.customer_ids}
The query itself actually succeeds however and returns records, and as a workaround I have been able to do:
SomeModel.where(admin_id: Admin.accessible_by(current_ability, :read).map(&:id))
But it obviously has performance implications opposed to using raw SQL.
Reverting to CanCan 1.6.10 seems to work as well.
In lib/cancan/rule.rb:114
, there is ActiveRecord specific code which should really be in a adapter. The context of the code is too complex to refactor it into the adapter though... so that whole method needs to be broken down as well.
As discovered in #13 ... I guarded it so that datamapper and mongoid would work as a temporary solution.
Suppose I have the following:
# routes.rb
resources :plans do
collection do
get 'requested'
get 'pending'
end
end
# PlansController
load_and_authorize_resource
def requested
...
render :index
end
def pending
...
render :index
end
# Ability
can :requested, Plan, dept_id: 304
can :pending, Plan, status: 'sent'
Where 'request' and 'pending' are two collection actions which should list the plans based on the respective filter. Problem is, if I don't add:
can :index, Plan
I get nothing. If I add this, it will show everything in both actions. In this cases, it seems that CanCan locks the actions, but is ignoring the conditions.
Any idea on how to solve this? Am I doing it wrong or not understanding something?
Thanks in advance.
Hello!
https://github.com/CanCanCommunity/cancancan/wiki/Controller-Authorization-Example
I think that this line of code is making all strong parameter filtering nonsense and let pass all non authorised params:
@project.attributes = params[:project]
Is it a mistake in example or in the gem itself?
Hi All,
I posted a few days ago and the comments helped me move forward on this project. Seems like everything is working but since Index uses a block (I think that's what I got from this) I might need some fancier filtering code.
I've read these posts but only went so far to conclude that I need to potentially add sql statements into the blocks:
ryanb/cancan#209 (comment)
ryanb/cancan@9d91545
https://github.com/ryanb/cancan/wiki/authorizing-controller-actions
http://stackoverflow.com/questions/16470869/cancan-not-filtering-products-in-index
My problem is filtering out index's for people that have PageRights that let them edit, are owners, or if the page is public. I'd like to do this filtering in the controller before the view.
Anyway a user can have an :editor, :admin, :guest as a role
A Page can be owned by a user, and has a public flag (aka guests can read it)
Only admin/editors are allowed to create pages/edit etc..
So for this I created a PageRights model that belongs to Page and User and has a right in it that I created aliases for index.
Code follows:
PageController
# before_filter :authenticate_user!, only: [:new, :create, :edit, :update, :destroy]
before_filter :new_page, only: [:create]
before_filter :find_page, only: [:edit, :update, :destroy]
load_and_authorize_resource #:only => [:new, :create, :edit, :update, :destroy]
def index
@pages = Page.all
end
Page
class Page < ActiveRecord::Base
extend FriendlyId
belongs_to :use
has_many :page_rights
has_many :users, through: :page_rights
friendly_id :title, use: :slugged
validates_presence_of :title, :body, :slug
acts_as_taggable
has_paper_trail
validates_inclusion_of :public_flag, :in => [true, false]
end
User
require 'role_model'
require 'typus/orm/active_record/instance_methods'
class User < ActiveRecord::Base
before_save :default_role
has_many :page_rights
has_many :pages, through: :page_rights
has_many :pages
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:omniauthable
include RoleModel
roles_attribute :roles_mask
roles :admin, :editor, :super_admin
include Typus::Orm::ActiveRecord::InstanceMethods
# If DeviseUser#locale is not found, we will use the default one.
def locale
::I18n.locale
end
def role
Typus.master_role
end
private
def default_role
self.roles << :editor
end
end
Ability
class Ability
include CanCan::Ability
def initialize(user)
alias_action :show, :index, :update, :edit, :to => :edit_page #page_right allows users to edit_page
alias_action :show, :index, :update, :edit, :new, :destroy, :to => :crud_page
user ||= User.new # guest user (not logged in)
if user.has_role? :super_admin
can :manage, :all
elsif user.has_role? :admin
can :manage, Page
else
can :read, Page do |page|
page.public_flag
end
if user.has_role? :editor
can :manage, Page, :user_id => user.id
can :create, Page
can :edit_page, Page do |page|
check_page_rights(user, page, 'edit_page')
end
can :crud_page, Page do |page|
check_page_rights(user, page, 'crud_page')
end
end
end
end
def check_page_rights(user, page, current_right)
common_page_right = page.page_rights && user.page_rights
if common_page_right.present? && common_page_right.first.right.present?
common_page_right.first.right == current_right
end
end
end
I'm stuck for this so any help is appreciated. I had an SO question a while back to no avail. I realize this is less then an issue and more of a Q so if there is a better place for this let me know.
Upon this line in my spec_helper:
require 'cancan/matchers'
I get this:
/Users/jaiken/.rvm/gems/ruby-2.0.0-p247@pws/gems/cancancan-1.7.0/lib/cancan/matchers.rb:2:in `<top (required)>': undefined method `define' for RSpec::Matchers:Module (NoMethodError)
from /Users/jaiken/.rvm/gems/ruby-2.0.0-p247@pws/gems/activesupport-3.2.17/lib/active_support/dependencies.rb:251:in `require'
from /Users/jaiken/.rvm/gems/ruby-2.0.0-p247@pws/gems/activesupport-3.2.17/lib/active_support/dependencies.rb:251:in `block in require'
from /Users/jaiken/.rvm/gems/ruby-2.0.0-p247@pws/gems/activesupport-3.2.17/lib/active_support/dependencies.rb:236:in `load_dependency'
from /Users/jaiken/.rvm/gems/ruby-2.0.0-p247@pws/gems/activesupport-3.2.17/lib/active_support/dependencies.rb:251:in `require'
from /Users/jaiken/projects/phrg/pws/spec/spec_helper.rb:12:in `<top (required)>'
from /Users/jaiken/projects/phrg/pws/spec/models/agent_originator_spec.rb:1:in `require'
from /Users/jaiken/projects/phrg/pws/spec/models/agent_originator_spec.rb:1:in `<top (required)>'
from /Users/jaiken/.rvm/gems/ruby-2.0.0-p247@pws/gems/rspec-core-2.14.8/lib/rspec/core/configuration.rb:896:in `load'
from /Users/jaiken/.rvm/gems/ruby-2.0.0-p247@pws/gems/rspec-core-2.14.8/lib/rspec/core/configuration.rb:896:in `block in load_spec_files'
from /Users/jaiken/.rvm/gems/ruby-2.0.0-p247@pws/gems/rspec-core-2.14.8/lib/rspec/core/configuration.rb:896:in `each'
from /Users/jaiken/.rvm/gems/ruby-2.0.0-p247@pws/gems/rspec-core-2.14.8/lib/rspec/core/configuration.rb:896:in `load_spec_files'
from /Users/jaiken/.rvm/gems/ruby-2.0.0-p247@pws/gems/rspec-core-2.14.8/lib/rspec/core/command_line.rb:22:in `run'
from /Users/jaiken/.rvm/gems/ruby-2.0.0-p247@pws/gems/rspec-core-2.14.8/lib/rspec/core/runner.rb:80:in `run'
from /Users/jaiken/.rvm/gems/ruby-2.0.0-p247@pws/gems/rspec-core-2.14.8/lib/rspec/core/runner.rb:17:in `block in autorun'
cancancan 1.70
Rails 3.2.17
Rspec 2.14.1
Hi,
It seems that using Entity.accessible_by(current_ability)
with a nested condition like so: {group: { familly_id: 3 }}
gets me the following deprecation warning:
DEPRECATION WARNING: It looks like you are eager loading table(s) (one of: entities, groups) that are referenced in a string SQL snippet. For example:
Post.includes(:comments).where("comments.title = 'foo'")
Currently, Active Record recognizes the table in the string, and knows to JOIN the comments table to the query, rather than loading comments in a separate query. However, doing this without writing a full-blown SQL parser is inherently flawed. Since we don't want to write an SQL parser, we are removing this functionality. From now on, you must explicitly tell Active Record when you are referencing a table from a string:
Post.includes(:comments).where("comments.title = 'foo'").references(:comments)
If you don't rely on implicit join references you can disable the feature entirely by setting `config.active_record.disable_implicit_join_references = true`. (called from block in <module:IRB> at /usr/local/rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/irb/inspector.rb:122)
So i tried activating the above config and well, as expected, the requests fails because of a missing FROM-clause.
I tried using a scope but it doesn't seem to be compatible with accessible_by
I know I can work around this fairly easily, I am just wondering if there's something that I missed that would allow me to add a scope in front of the find method of load_resource (and load_and_authorize_resource)
For example, if I were using friendly_id, I would want to add the friendly
scope so it would end up looking something like Article.friendly.find(params[:id])
now that this is a gem called cancancan it seems like the documentation is either incorrect or confusing in several locations
there should be at least a short transition guide, going from cancan to cancancan
for example, do you need to change the include
include CanCan::Ability
to
include CanCanCan::Ability
because as of writing, it said CanCan::Ability but this seems incorrect.
For the sake of an example I'm using a singleton profile for the current user
require 'spec_helper'
class Profile < Struct.new(:user); end
class ProfilesController < ApplicationController
load_and_authorize_resource through: :current_user, singleton: true
end
describe ProfilesController do
login_user # macro which sets :current_user for devise
before do
@routes.draw do
resource :profile
end
end
describe 'GET new' do
it 'assigns a new profile to @profile' do
get :new
expect(assigns :profile).to be_a Profile
end
end
end
results in
ProfilesController GET new assigns a new profile to @profile
Failure/Error: get :new
NoMethodError:
undefined method `current_user=' for #<struct Profile user={}>
https://github.com/CanCanCommunity/cancancan/blob/master/lib/cancan/controller_resource.rb#L90 tries to use profile.current_user=
, but it isn't defined on the profile model.
Is there an option to override the parent_name
to user
Hi Cancancan Community,
I don't if it's better to put this question/bug/issue/request here on Stackoverflow but the problem is really simple:
how to obtain a list of users which "can do an action"? Is it possibile with the current version?
If not would be great to be able to do that
A Company
has many Customer
's and many Employee
's. Company
's and Employee
's belong to User
's so they can sign into our system. An Employee
should be able to read a Company
's Employee
's and Customer
's.
I expect Employee.accessible_by(Ability.new(user)).to_sql
to produce the same SQL structure as Customer.accessible_by(Ability.new(user)).to_sql
, however, it is missing the joins. It should reference the Company
's collection and then refer back to the Employee
's collection, just like the Customer
query does.
class User < ActiveRecord::Base
has_many :companies
has_many :customers
has_many :employees
end
class Company < ActiveRecord::Base
has_many :customers
has_many :employees
belongs_to :user
end
class Customer < ActiveRecord::Base
belongs_to :company
belongs_to :user
end
class Employee < ActiveRecord::Base
belongs_to :company
belongs_to :user
end
class Ability
include CanCan::Ability
def initialize(user)
can :read, Customer, company: { employees: { user_id: user_id } }
can :read, Employee, company: { employees: { user_id: user_id } }
end
end
> Employee.accessible_by(Ability.new(user)).to_sql
=> "SELECT `employees`.* FROM `employees` WHERE `employees`.`user_id` = 16"
> Customer.accessible_by(Ability.new(user)).to_sql
=> "SELECT `customers`.`id` AS t0_r0, `customers`.`company_id` AS t0_r1, `customers`.`user_id`
AS t0_r2, `companies`.`id` AS t1_r0, `companies`.`user_id` AS t1_r1, `employees`.`id` AS t2_r0,
`employees`.`company_id` AS t2_r1, `employees`.`permissions` AS t2_r2, `employees`.`user_id` AS
t2_r3 FROM `customers` LEFT OUTER JOIN `companies` ON `companies`.`id` =
`customers`.`company_id` LEFT OUTER JOIN `employees` ON `employees`.`company_id` =
`companies`.`id` WHERE `employees`.`user_id` = 16"
Finally!
https://github.com/CanCanCommunity/cancancan/blob/master/lib/cancan/model_adapters/active_record_adapter.rb#L100 is still using #scoped. This causes a deprecation warning in Rails 4. Use #all instead if the Rails version is 4 or greater.
Im thinking if it's possible to add the adapter for Sequel:
ryanb/cancan#884
It looks like it passes all the tests. I dunno if it passes on this branch/fork.
Hello,
If I have the following ability.
can :manage, Model, id: 23
With the wollowing controller:
class ModelsController < ApplicationController
load_and_authorize_resource
respond_to :html
def new
respond_with @model
end
Then I can happily naviguate to new_models_path
(/models/new), but I shouldn't be able to do that., because I only have the rights to manage a single entity. If I change :manage
for [:read, :update, :destroy]
then it works as expected.
I found out that inside new
, @model is set to the model I have right access to... this looks like a bug too.
I'm in the process of migrating from CanCan to CanCanCan and have run into an issue. I'm not sure if it was always resident in CanCan and my tests were faulty, or introduced in CanCanCan. Regardless, its an open question.
I have an ability file that looks something like this:
class Ability
include CanCan::Ability
def initialize(user)
@user = user
send(user.role)
end
def employee
can [:update], User, id: @user.id
...other universal rules
end
def admin
employee
can [:update], User, company_id: @user.company_id
end
end
My expectation would be that the :update
rule is rewritten for the higher role, but its not. I have to do the following:
def admin
employee
cannot[:update], User
can [:update], User, company_id: @user.company_id
end
Which is pretty gross.
Thoughts?
I am using Rails 4.0.1 and ruby 2.1.1. I am trying to integrate cancan with rails_admin. My application_controller.rb looks like this
helper_method :current_user
private
def current_user
@current_user ||= User.find_by(email: session[:user_id]) if session[:user_id]
end
My current_user helper method is working fine from rest of the application. My ability.rb looks like this
class Ablity
include CanCan::Ability
def initialize(user)
if user
can :access, :rails_admin
end
end
end
Control is not going inside the if condition at all, which means the "user" parameter is "nil". When I try to access rails_admin I get a CanCan::AccessDenied exception. Where am I going wrong?
when use
Hello,
I want it so that my index
action is only accessible by those who can update
other users (other users can only update themselves).
This is what I tried:
# ability
if user.name == "A"
can :read, User, id: user.id # User A can read itself
elsif user.name == "B"
can :read, User, id: user.id # User B can read itself
can :update, User, id: user.id # User B can update itself
elsif user.name == "C"
can :read, User # User C can read everyone
can :update, User # User C can update everyone
end
# controller
def index
authorize! :update, User
respond_with @users
end
The problem is that both user B & C can list the index action, but I want only the user C to be able to do it. What did I do wrong? Am I supposed to do User.all.each{ |u| authorize!(:update, u) }
instead?
Additional infos: ryanb/cancan#615
Unfortunately supermodel is locked at ~> 3.0.0
so I can't do it (re: #13)
Need to pull supermodel out, probably using a proper dummy rails app, and convert the spec_helper to using the dummy app rather than supermodel
and with_model
.
This will doubly allow us to do some capybara
integration tests for better testing.
I found something wrong in https://github.com/CanCanCommunity/cancancan/blob/master/lib/cancan/rule.rb#L33, which not calling a block when:
can :index, Subject do |subject|
// Some condition
end
Which always return true during can?(:index, Subject), even codition return false. After I change the method into:
def matches_conditions?(action, subject, extra_args)
if @match_all
call_block_with_all(action, subject, extra_args)
elsif @block && subject_class?(subject)
@block.call(subject, *extra_args)
elsif @conditions.kind_of?(Hash) && subject.class == Hash
nested_subject_matches_conditions?(subject)
elsif @conditions.kind_of?(Hash) && !subject_class?(subject)
matches_conditions_hash?(subject)
else
# Don't stop at "cannot" definitions when there are conditions.
conditions_empty? ? true : @base_behavior
end
end
Now, it return the right response for that ability.
In Rails 4 there is a problem using load_and_authorize_resource
, it throws a ActiveModel::ForbiddenAttributesError.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.