簡體   English   中英

如何以當前用戶或非用戶身份更新資源?

[英]How to update a resource as current user or a non-user?

在我的應用程序中,我有以下資源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

但我不確定這是多么安全。 似乎用戶可以訪問其他用戶的帖子。

這是正確的嗎? 我怎么能這樣做?

我會這樣做,因為邏輯在模型中(或者在服務對象中)會更好:

用戶必須有兩種類型a。 登錄的b。 客人

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

另外你可能想嘗試瑞安貝茨的cancan gem,或者因為它已經停滯了一段時間你可以使用cancacnan ..

如果滿足以下條件之一,您希望允許更新:

  • Post是客座文章
  • 用戶是帖子的所有者

讓我們在模型中創建一個方法,以檢查是否允許用戶根據傳遞以下兩個條件之一進行更新:

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

我的方法是使用內存上的'update_user'附加屬性進行自定義驗證,如下所示:

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驗證下完成的。

用戶的訪問范圍(或訪問權限)應該是“業務邏輯”之一,“業務邏輯”應該是模型邏輯之一,因此我認為在模型級別編寫會很好。

我認為user2784630在以下片段中的檢查邏輯應該沒問題:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM