Devise 和 Cancancan - 如何让它发挥作用?

Devise and Cancancan - How to make it work?

自从昨天我从 Pundit(因为它太难)切换到 Cancancan(对我来说看起来更好)以来,我正在制作一个网络应用程序(聊天之类的东西)。

我正在尝试做一些简单的工作,例如显示所有文章及其选项(显示、编辑、销毁),然后对其设置权限,以便创建此类文章的唯一用户能够编辑或销毁它。

问题是我不明白完全实施是什么意思。 Google 缺少示例,其中的示例大多已过时。

这是我的:

Ability.rb -我不知道这是否正确

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user (not logged in)
    if user.admin?
        can :manage, :all
    else
        can :read, :all
    end

    can :read, :articles
    can :create, :articles
  end
end

User.rb(设计)

class User
  include Mongoid::Document
  has_many :articles
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  ## Database authenticatable
  field :username,               type: String, default: ""
  field :email,              type: String, default: ""
  field :encrypted_password, type: String, default: ""

  ## Recoverable
  field :reset_password_token,   type: String
  field :reset_password_sent_at, type: Time

  ## Rememberable
  field :remember_created_at, type: Time

  ## Trackable
  field :sign_in_count,      type: Integer, default: 0
  field :current_sign_in_at, type: Time
  field :last_sign_in_at,    type: Time
  field :current_sign_in_ip, type: String
  field :last_sign_in_ip,    type: String

  ## Admin
  field :admin, :type => Boolean, :default => false
end

Article.rb

class Article
  include Mongoid::Document
  belongs_to :user

  field :title, type: String
  field :content, type: String

  default_scope -> { order(created_at: :desc) }
end

index.html(显示文章 - 只有我添加 Cancancan 的部分)

<tbody>
   <% @articles.each do |article| %>
     <tr>
       <td><%= article.title %></td>
       <td><%= article.content %></td>
       <td><%= link_to 'Show', article %></td>
       <td>
          <% if can? :update, @article %>
             <%= link_to 'Edit', edit_article_path(article) %>
          <% end %>
       </td>
       <td><%= link_to 'Destroy', article, method: :delete, data: { confirm: 'Are you sure?' } %></td>
              </tr>
            <% end %>
          </tbody>

您需要在 Ability 文件中通过 class 定义您的权限:

#app/models/ability.rb
class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user (not logged in)
    if user.admin?
        can :manage, :all
    else
        can :read, :all
    end

    can [:credit, :edit, :update, :destroy], Article, user_id: user.id
  end
end

--

#app/views/articles/index.html.erb
<tbody>
   <% @articles.each do |article| %>
     <tr>
       <td><%= article.title %></td>
       <td><%= article.content %></td>
       <td><%= link_to 'Show', article %></td>
       <td><%= link_to 'Edit', article if can? :update, article %></td>
       <td><%= link_to 'Destroy', article, method: :delete, data: { confirm: 'Are you sure?' } if can? :destroy, article %></td>
      </tr>
    <% end %>
</tbody>

顺便说一句,第二个要考虑的重要因素是 Devise = 身份验证; CanCanCan = 授权:

  • Authentication = is user logged in?
  • Authorization = can user do this?

我看到很多人 post 谈论 "authorizing" 和 Devise,但这是完全错误的。 Devise 仅处理身份验证(用户已登录?);在处理 授权 时,您需要使用不同的模式,利用 Devise 创建的 user 对象。

只是想指出这一点,考虑到您在原来的 post 中提到了 Devise