Devise + CanCan只是阻止其他用户编辑对象

问题描述:

如何防止其他用户编辑对象,说配置对象不属于自己?

How would you prevent other users from editing a object, say a profile object that does - not - belong to themselves?

大多数在线示例是与多个用户的复合角色,我无法得到这个工作,必须简单:

Most online examples are complexes with multiple user roles, i haven't been able to get this working, must be simple though:

  def initialize(user)

      can :update, Profile do |profile|
        profile.try(:user) == current_user
      end

  end

在我的ProfilesController#编辑

And inside my ProfilesController#edit

authorize! :update, @profile


第一个问题是,有没有为用户发挥作用?

First question is, have you made your roles for the User?

app / models / user.rb

app/models/user.rb

class User < ActiveRecord::Base
  attr_accessible :email, :password, :remember_me
  devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, # regular devise stuff
  before_create :setup_default_role_for_new_users

  ROLES = %w[admin default banned]

  private

  def setup_default_role_for_new_users
    if self.role.blank?
      self.role = "default"
    end
  end
end

正如你所看到的,我在这里有3个不同的角色,当一个新用户被创建时,它们始终是 default users。现在用CanCan设置,让我们说你想让 admin 能够做所有的事情,默认用户是能够使用自己的个人资料进行一切,禁止用户无法做任何事情,访客用户可以查看个人资料:

As you can see I have 3 different roles here and when a new user is created they are always default users. Now with CanCan set up, lets say you wanted to have the admin be able to do everything, the default users be able to do everything with their own profiles, banned users cannot do anything and guest users be able to see profiles:

class Ability
  include CanCan::Ability
  # Remember that CanCan is for a resource, meaning it must have a class(model).

  def initialize(user)
    user ||= User.new # guest user (not logged in)

    if user.role == "admin"
      can :manage, :all
    elsif user.role == "default"
      can :manage, Profile, :user_id => user.id
    elsif user.role == "banned"
      cannot :manage, :all
    else
      can :read, Profile # guest user
    end
  end
end

所以这就是让用户只编辑自己的个人资料和没有人

So that's how you let users edit only their own profiles and nobody elses.

其他一些方便的说明:确保您有一个个人资料表中的> user_id 列。另外,如果您可能需要让用户看到这样的个人资料:

Some other handy notes: Make sure you have a user_id column in your Profile table. Also if you may need to let guess users see profiles like this:

class ProfileController < ApplicationController
    before_filter :authenticate_user!, :except => :show
    load_and_authorize_resource
end

他们将无法使用任何除了 show 之外,CanCan还会检查身份验证。

They won't be able to use any other action and CanCan still checks authentication on everything else except show.

祝你好运!

更新:制作:用户角色属性

我所做的是运行一个迁移,将角色列添加到Devise 用户表中:

What I did was run a migration that would add the role column to the Devise users table:

rails generate migration add_role_to_users role:string

然后 rake db:migrate 。新的迁移文件应如下所示,并检查您的 db / schema.rb 文件,以确保其中的用户表的正确位置。如果不是,那么 rake db:drop ,然后 rake db:create 然后 rake db:migrate 再次。

And then rake db:migrate. The new migration file should look like this and also check your db/schema.rb file to make sure its apart of the users table correctly. If it isn't then rake db:drop, then rake db:create and then rake db:migrate again.

class AddRoleToUsers < ActiveRecord::Migration
  def self.up
    add_column :users, :role, :string
  end

  def self.down
    remove_column :users, :role
  end
end

这是你如何成功地使 user.role work。

This is how you successfully make the user.role work.

注意:请确保您离开: can:manage,个人资料,:user_id => user.id 是没有变化的。将角色列添加到用户后,它应该工作。

Note: Make sure you leave the line: can :manage, Profile, :user_id => user.id as is with no changes. It should work after adding the role column to user.

重要!如果您使用Rails 3,DO MAKE 角色 attr_accessible 或每个人都可以编辑他们的角色! Rails 4默认使用强参数,并且不受此问题的影响,您可以选择允许的参数。

IMPORTANT! If you use Rails 3, DO NOT MAKE role attr_accessible or everyone can edit their roles! Rails 4 uses Strong Parameters by default and is not affected by this issue as you can choose the allowed parameters.