[英]CanCanCan Rails Not Working
我將Rails 4與Devise和CanCanCan結合使用,由於某些原因,當我嘗試僅向用戶授予他們制造的產品的CRUD權限時,CanCanCan權限設置均無法通過,並且用戶只能進行只讀操作 。 但是,版主和管理員權限按預期方式工作。
能力
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.is? :admin
can :manage, :all
elsif user.is? :moderator
can :read, :all
can :manage, @products
elsif user.is? :user
can :read, :all
can :create, :all
can :manage, @products do |product|
product.try(:user) == user
end
else
can :read, :all
end
end
end
user.rb
has_many :products
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
before_save :assign_role
Roles = [ :admin , :moderator , :user ]
def is?( requested_role )
self.role == requested_role.to_s
end
def assign_role
self.role = Role.find_by role: "user" if self.role.nil?
end
.html文件
<% if can? :update, @products %>
<%= link_to "Edit", edit_product_path(@product) %>
<% end %>
<% if can? :destroy, @products %>
<%= link_to "Delete", product_path(@product), method: :delete, data: { confirm: "Are you sure?"} %>
<% end %>
控制者
class ProductsController < ApplicationController
respond_to :html, :json
load_and_authorize_resource
def create
@product = current_user.products.build(product_params)
@product.user_id = current_user.id
if @product.save
redirect_to products_path
else
render 'new'
end
end
def product_params
params.require(:product).permit(:product_name, :product_description, :user_id)
end
編輯:
用戶SQL表
+------------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
| email | varchar(255) | NO | UNI | | |
| encrypted_password | varchar(255) | NO | | | |
| reset_password_token | varchar(255) | YES | UNI | NULL | |
| reset_password_sent_at | datetime | YES | | NULL | |
| remember_created_at | datetime | YES | | NULL | |
| sign_in_count | int(11) | NO | | 0 | |
| current_sign_in_at | datetime | YES | | NULL | |
| last_sign_in_at | datetime | YES | | NULL | |
| current_sign_in_ip | varchar(255) | YES | | NULL | |
| last_sign_in_ip | varchar(255) | YES | | NULL | |
| role | varchar(255) | YES | | NULL | |
+------------------------+--------------+------+-----+---------+----------------+
產品SQL表
+-----------------------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| project_goal | int(11) | YES | | NULL | |
| product_name | varchar(255) | YES | | NULL | |
| product_description | varchar(255) | YES | | NULL | |
| project_category | varchar(255) | YES | | NULL | |
...
| expiration_date | datetime | YES | | NULL | |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
| user_id | int(11) | YES | | NULL | |
+-----------------------------------+--------------+------+-----+---------+----------------+
這是我的文件結構
而不是像這樣設置一個塊:
can :manage, @products do |product|
product.try(:user) == user
end
您可以嘗試根據user_id建立權限:
can :manage, Product do |product|
product.user_id == user.id
end
您可以這樣更簡潔地表達此權限:
can :manage, Product, user_id: user.id
雖然上面的語法應該可以工作,但是如果您遇到問題,請嘗試以下更詳細的版本:
can :manage, Product, :user_id => user.id
當然,這種方法假定用戶和產品(產品屬於用戶)之間存在某種關系。
另外,請記住, :manage
表示“任何操作”,因此在指定:manage
之后為任何CRUD操作和/或自定義方法定義條件是多余的。
最后一點,您可能想嘗試為標准訪問級別使用其他符號,因為當您實際上是指用戶角色時,很容易將符號:user誤認為用戶對象。
您似乎在abilities類中使用了一個實例變量。 試試看,看看是否可行:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.is? :admin
can :manage, :all
elsif user.is? :moderator
can :read, :all
can :manage, Product # use class here not instance variable
elsif user.is? :user
can :read, :all
can :create, :all
can :manage, Product do |product| # <–-use the class here not instance variable.
product.try(:user) == user # cancancan code examples general call ids you might wanna consider revisions?
end
else
can :read, :all
end
end
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.