Reputation: 1044
company.rb:
class Company < ActiveRecord::Base
has_many :companies_admins, dependent: :destroy
has_many :supervisors, through: :companies_admins
end
companies_admin.rb:
class CompaniesAdmin < ActiveRecord::Base
belongs_to :company
belongs_to :supervisor, foreign_key: "admin_id"
end
supervisor.rb:
class Supervisor < Admin
has_many :companies_admins, foreign_key: "admin_id"
has_many :companies, through: :companies_admins, foreign_key: "admin_id"
end
i use cancancan gem. My ability.rb:
class Ability
include CanCan::Ability
def initialize(user)
user ||= Admin.new # guest user (not logged in)
if user.type == "Administrator"
can :manage, :all
elsif user.type == "Supervisor"
can :manage, Company, companies_admins: {supervisor: { :id => user.id } }
end
end
end
companies_controller.rb:
class CompaniesController < ApplicationController
load_and_authorize_resource only: [:new, :create, :edit, :update, :index, :show, :destroy]
load_and_authorize_resource :supervisor
load_and_authorize_resource through: :supervisor
...
end
I need to supervisor only companies able to manage, with whom he has a relationship. Example: supervisor
when I open the page of company id=10 get access denied.
Started GET "/companies/10" for 127.0.0.1 at 2016-06-05 14:23:01 +0300
Processing by CompaniesController#show as HTML
Parameters: {"id"=>"10"}
Company Load (0.4ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT 1 [["id", 10]]
Admin Load (0.3ms) SELECT "admins".* FROM "admins" WHERE "admins"."id" = $1 LIMIT 1 [["id", 4]]
CompaniesAdmin Load (0.4ms) SELECT "companies_admins".* FROM "companies_admins" WHERE "companies_admins"."company_id" = $1 [["company_id", 10]]
Supervisor Load (0.4ms) SELECT "admins".* FROM "admins" WHERE "admins"."type" IN ('Supervisor') AND "admins"."id" = $1 LIMIT 1 [["id", 2]]
Supervisor Load (0.4ms) SELECT "admins".* FROM "admins" WHERE "admins"."type" IN ('Supervisor') AND "admins"."id" = $1 LIMIT 1 [["id", 4]]
Redirected to http://localhost:3000/
Completed 302 Found in 20ms (ActiveRecord: 1.9ms)
The question is why? how to identify the expression "include"?
Edit: Very strange, even by the administrator, I get access denied when to replace :all Company. Why?
def initialize(user)
user ||= Admin.new # guest user (not logged in)
puts user.type
if user.type == "Administrator"
can :manage, Company
elsif user.type == "Supervisor"
can :show, :all
end
end
Started GET "/companies/10" for 127.0.0.1 at 2016-06-05 22:55:49 +0300
Processing by CompaniesController#show as HTML
Parameters: {"id"=>"10"}
Admin Load (0.3ms) SELECT "admins".* FROM "admins" WHERE "admins"."id" = $1 LIMIT 1 [["id", 1]]
Administrator
Redirected to http://localhost:3000/
Completed 302 Found in 42ms (ActiveRecord: 2.5ms)
in rails console:
irb(main):005:0> mi = Admin.find(1)
Admin Load (0.7ms) SELECT "admins".* FROM "admins" WHERE "admins"."id" = $1 LIMIT 1 [["id", 1]]
=> #<Administrator id: 1, type: "Administrator", login: "mars", crypted_password: "8d6ff3f5b32b22726a45b1f8fa69519debf9ec8157d78f8e41...", password_salt: "2oMqwXKIukbKpdEXip", persistence_token: "37127e1f262d4efb44bc458df76e110a6ee78969c94c84a43c...", created_at: "2016-06-04 21:11:18", updated_at: "2016-06-05 09:06:15">
irb(main):006:0> comp = Company.find(10)
Company Load (0.9ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT 1 [["id", 10]]
=> #<Company id: 10, parent_id: nil, address_id: 6, name: "test_address"...>
irb(main):007:0> ability = Ability.new(mi)
Administrator
=> #<Ability:0x007f09513a0938 @rules=[#<CanCan::Rule:0x007f09513a0898 @match_all=false, @base_behavior=true, @actions=[:manage], @subjects=[Company(id: integer, parent_id: integer, address_id: integer, name: string, info: string, created_at: datetime, updated_at: datetime, site_link: string, vk_link: string, raiting: float, city_id: integer, paid: integer)], @conditions={}, @block=nil>], @rules_index={Company(id: integer, parent_id: integer, address_id: integer, name: string, info: string, created_at: datetime, updated_at: datetime, site_link: string, vk_link: string, raiting: float, city_id: integer, paid: integer)=>[0]}>
irb(main):008:0> ability.can?(:manage, comp)
=> true
What have I done wrong?
Upvotes: 0
Views: 1957
Reputation: 1044
hmm, that's it works:
class Ability
include CanCan::Ability
def initialize(user)
user ||= Admin.new # guest user (not logged in)
if user.type == "Administrator"
can :manage, Company
elsif user.type == "Supervisor"
can :manage, Company do |comp|
comp.supervisor_ids.include?(user.id)
end
end
end
end
companies_controller.rb:
class CompaniesController < ApplicationController
load_and_authorize_resource only: [:new, :create, :edit, :update, :index, :show, :destroy]
....
Upvotes: 2