如何允许用户删除或更新非用户资源并且只有自己的?

时间:2014-08-03 11:46:25

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

我的应用程序中的非用户无法删除或更新用户的评论,用户只能更新或删除自己的评论或非用户评论。我遇到的问题是正确而安全地写这个问题。

这就是我创建新评论的方法,但这无法访问user_id,但我不知道如何处理更新和删除方法。现在他们只允许当前用户删除或更新评论

CommentsController

def new
  @post = Post.find(params[:post_id])
  @comment = Comment.new
end

def edit
  @post = Post.find(params[:post_id])
  @comment = Comment.find(params[:id])
end

def create
  @post = Post.find(params[:post_id])

  if signed_in?
    @comment = current_user.comments.build(comment_params)  
  else
    @comment = Comment.create(comment_params)
  end
  if @comment.save.....
end

def update
  @post = Post.find(params[:post_id])
  @comment = current_user.comments.find(params[:id])
  if @comment.update(comment_params)..........
end

def destroy
  @comment = current_user.comments.find(params[:id])
  @comment.destroy
end

private

def comment_params
  params.require(:comment).permit(:body, :post_id)
end

我认为必须要有一些如何进入@ comment.user字段,但如果我必须先找到评论,我该怎么办呢?或者,如果没有正确的方法,该如何做?

答案

这就是我最终做的事情:

def update
  @post = Post.find(params[:post_id])
  @comment = Comment.find(params[:id])
  if @comment.user == current_user
    if @comment.update(comment_params)
      redirect_to @comment
    else
      render action: 'edit'
    end
  elsif @comment.user.blank?
    if @comment.update(comment_params)
      redirect_to @comment
    else
      render action: 'edit'
    end
  else
    redirect_to @comment, notice: "An Error occured"
  end
end

2 个答案:

答案 0 :(得分:1)

假设访客用户创建的评论将user_id字段设置为nil,您可以执行类似

的操作
class Post < ActiveRecord::Base
  ...
  scope :comments_editable_by, ->(user_id) { where('user_id is null or user_id = ?', user_id) }
  ...
end

commentsupdate操作中使用此范围代替destroy

答案 1 :(得分:1)

我认为您最好的选择是使用授权系统,例如declarative_authorizationpunditcancancan。它们还提供视图助手,使您可以隐藏无法更新特定注释的用户的更新链接。

虽然如果这是您唯一需要授权的地方,那么按照您的建议编写自己的解决方案可能是更好的选择。你可以这样做:

def CommentsController < ApplicationController
  ...
  def update
    @comment.update comment_params
    if @comment.authorized_update!(current_user)
      redirect_to @comment, status: :accepted
    else
      redirect_to @comment, status: :unauthorized
    end
  end
end

然后在你的模型中:

def Comment < ActiveRecord::Base
  ...
  def authorized_update!(current_user)
    if user == current_user
      self.save
    else
      errors[:base] << "Unauthorized"
      false
    end
  end
end

你可能不得不调整它以满足你的需求,但你明白了。