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

时间:2011-11-30 19:50:20

标签: ruby-on-rails ruby-on-rails-3 devise cancan

你如何阻止其他用户编辑一个对象,比如说一个不属于自己的个人资料对象?

大多数在线示例都是具有多个用户角色的复合体,我无法使其正常工作,但必须简单:

  def initialize(user)

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

  end

在我的ProfilesController#edit

authorize! :update, @profile

3 个答案:

答案 0 :(得分:12)

第一个问题是,您是否为User

制作了角色?

应用程序/模型/ 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个用户。现在设置了CanCan,假设您希望admin能够执行所有操作,default用户可以使用自己的配置文件执行所有操作,banned用户无法执行任何操作和访客用户可以看到个人资料:

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

这样你就可以让用户只编辑他们自己的个人资料和无人资格了。


其他一些便利说明:确保user_id表中有Profile列。此外,如果您可能需要让猜测用户看到如下配置文件:

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

他们无法使用任何其他操作,CanCan仍会检查除show以外的所有其他操作的身份验证。

祝你好运!


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

我所做的是运行迁移,将role列添加到Devise users表中:

rails generate migration add_role_to_users role:string

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

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

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

这是您成功完成user.role工作的方式。

注意:请务必保留以下行:can :manage, Profile, :user_id => user.id,不做任何更改。将role列添加到user后,它应该可以正常工作。

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

答案 1 :(得分:4)

尝试这样的事情......

can :update, Profile, :user_id => user.id

答案 2 :(得分:0)

<强>更新

似乎上面的代码示例正确。在阅读了cancan rtfm的所有文档后,我发现了你需要添加的角色列。

由于我的个人资料更新操作的组织方式,似乎CanCan无效!我解决了如下:

  def edit

    @profile = Profile.find params[:id]
    what = params[:what]

    if can? :update, @profile
      if ["basics", "location", "details", "photos", "interests"].member?(what)
        render :action => "edit_#{what}"
      else
        render :action => "edit_basics"
      end
    else
      raise CanCan::AccessDenied.new("Not authorized!", :update, Profile)
    end
  end

也许不是最干净的方式,而是让它发挥作用的唯一方法。欢迎任何有关改进的建议,我确实有

  load_and_authorize_resource

内部配置文件控制器虽然!也许是一个错误