如何以当前用户或非用户身份更新资源?

时间:2014-10-19 05:08:59

标签: ruby-on-rails ruby ruby-on-rails-4

在我的应用程序中,我有以下资源Post和User。我希望用户能够更新自己的帖子和访客帖子,我希望访客能够更新其他访客帖子,但不能更新用户。访客只是非用户(@post.user.blank)。

Post Model
  belongs_to :user
  # columns: user_id, name, body
end

User Model
  has_many :posts
end

我的控制器让我感到困惑,因为我不确定如何制作它所以更新帖子可以由当前用户或访客完成,而不允许每个人都更新任何帖子。主要是另一个用户更新另一个用户帖子。

  def update
    @post = Post.find(params[:id])
    if @post.update(post_params)
      redirect_to @post
    else
      render action: 'edit'
    end
  end

  def post_params
    params.require(:post).permit(:name, :body)
  end

我在考虑做:

  def update
    @post = Post.find(params[:id])
    if @post.user == current_user or @post.user.blank?
      if @post.update(post_params)
        redirect_to @post
      else
        render action: 'edit'
      end
    end
  end

但我不确定这是多么安全。似乎用户可以访问其他用户帖子。

这是对的吗?我怎么能这样做?

3 个答案:

答案 0 :(得分:1)

我会这样做,因为逻辑更适合在模型中(或者可能在服务对象中):

用户必须有两种类型 一个。登录 湾客

class Post < AR::Base
  ...
  ...
  def created_by_guest?
    self.user == nil #probably created by guest if user is nil
  end

  def update_by_user(user, attributes)
    return false if user.guest and self.created_by_guest?
    #add code to try updating return true if it worked and false if did not work
  end
end
控制器中的

def update
  @post = Post.find(params[:id])
  if @post.update_by_user(current_user, update_params)
    #redirect to show
  else
    #edit page
  end
end

你也可以尝试一下Ryan bates的cancan gem,或者因为它已经停滞了一段时间你可以使用cancacnan ..

答案 1 :(得分:1)

如果满足以下条件之一,您希望允许更新:

  • 帖子是客座文件
  • 用户是帖子的所有者

让我们在模型中创建一个方法来检查是否允许用户根据传递以下两个条件之一进行更新:

Post Model
  belongs_to :user
  # columns: user_id, name, body

  def updatable_by?(user)
    @user_id.nil? || user == self.user # return true for guest post OR post owner
  end
end

然后,更新等待检查结果:

def update
  @post = Post.find(params[:id])
  if @post.updatable_by?(current_user) # <-- update if current_user is allowed
    if @post.update(post_params)
      redirect_to @post
    else
      render action: 'edit'
    end
  end
end

答案 2 :(得分:1)

我的方法是使用&#39; update_user&#39;内存的附加属性如下:

class Post < ActiveRecord::Base
  belongs_to :user

  attr_accessor :update_user
  validate :validate_user_scope, on: :update

  private

  def validate_user_scope
    if !(user.blank? || user == update_user)
      errors.add(:update_user, :not_permitted)
    end
  end
end


class User < ActiveRecord::Base
  has_many :posts
end

当然,这个优点是检查逻辑是在模型级别(而不是控制器)的Rails验证下完成的。

用户的访问范围(或访问权限)应该是&#34;业务逻辑&#34;和&#34;业务逻辑&#34;应该是模型逻辑之一,以便在模型级别编写,我认为。

我认为用户2784630在以下片段中的检查逻辑应该没问题:

if @post.user == current_user or @post.user.blank?

但是,如果你担心这个逻辑的全面性,那就让我们写一下test或rspec。以下是带有灯具的test / models / post_test.rb示例:

require 'test_helper'

class PostTest < ActiveSupport::TestCase
  ...
  # test all of posts of guest, user-A, and user-B are updated by
  # guest, user-A, and user-B
  test "update guest post by user_A" do
    p = posts(:guest_post)
    p.update_user = users(:user_A)
    assert p.valid?
  end
  ...
end