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

发布于 2024-12-18 15:04:54 字数 326 浏览 2 评论 0原文

您如何防止其他用户编辑对象,例如不属于自己的配置文件对象?

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

  def initialize(user)

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

  end

在我的 ProfilesController#edit 中

authorize! :update, @profile

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

And inside my ProfilesController#edit

authorize! :update, @profile

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

意犹 2024-12-25 15:04:54

第一个问题是,您为用户确定了自己的角色吗?

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 个不同的角色,当创建新用户时,它们始终是默认用户。现在 CanCan 设置完毕,假设您希望 admin 能够执行所有操作,default 用户能够使用自己的配置文件执行所有操作,被禁止的用户无法执行任何操作,而来宾用户可以查看个人资料:

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

因此,您可以让用户只编辑自己的个人资料,而不能编辑其他人的个人资料。


其他一些方便的注意事项:确保您的 Profile 表中有一个 user_id 列。此外,如果您可能需要让猜测用户看到这样的个人资料:

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

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

祝你好运!


更新:为用户创建 :role 属性

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

rails generate migration add_role_to_users role:string

然后rake db:迁移。新的迁移文件应如下所示,并检查您的 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,请不要创建role attr_accessible,否则每个人都可以编辑他们的角色! Rails 4 默认使用 强参数,并且不受此问题的影响,您可以选择允许的参数。

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

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

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.


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

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

Good luck!


UPDATE: Making :role attribute for Users

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

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

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

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.

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.

迷鸟归林 2024-12-25 15:04:54

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

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

Give something like this a try....

can :update, Profile, :user_id => user.id
若有似无的小暗淡 2024-12-25 15:04:54

更新

看起来上面的代码示例是正确的。在阅读了 cancan rtfm ;p 的所有文档后,我发现了您需要添加的角色列。

由于我组织个人资料更新操作的方式,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

不过我确实有内部配置文件控制器!也许是一个错误

UPDATE

Seems like the above code examples where correct. After reading all of the docs of cancan rtfm ;p I found out about the role column you need to add.

Because of the way I have my profile update action organized it seems CanCan does not work! I solved like below:

  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

Maybe not the cleanest way but the only way to get it to work. Any suggestions on improvements are welcome, I did have the

  load_and_authorize_resource

Inside profiles controller though! Perhaps a bug

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文