简体   繁体   English

如何允许用户删除或更新仅具有自己资源的非用户资源?

[英]How to allow users to delete or update non-user resources and only there own?

Non-users in my application cannot delete or update comments by a user and users only can update or delete there own comments or a non-users comments. 我的应用程序中的非用户无法删除或更新用户的评论,而用户只能更新或删除自己的评论或非用户的评论。 The problem I'm having is writing this correctly and safely. 我遇到的问题是正确,安全地编写此代码。

This is how I create a new comment and this works without access to the user_id but I'm not sure what to do with the update and delete methods. 这是我创建新注释的方式,并且可以在不访问user_id的情况下运行,但是我不确定如何处理update和delete方法。 Right now they just allow the current user to delete or update comments 目前,他们只允许当前用户删除或更新评论

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

I think have to some how get to the @comment.user field but how would I do that if I have to find the comment first? 我认为一定要如何到达@ comment.user字段,但是如果必须先找到评论,该怎么办? Or, how would this be done if that isn't the right way? 或者,如果这不是正确的方法,该怎么办?

Answer 回答

This is what I ended up doing: 这就是我最终要做的事情:

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

Assuming that comments created by guest users have user_id field set to nil, you can do something like 假设来宾用户创建的评论的user_id字段设置为nil,则可以执行以下操作

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

And use this scope instead of comments in the update and destroy actions. 并在updatedestroy操作中使用此作用域代替comments

I think your best bet is to use an authorization system such as declarative_authorization , pundit , or cancancan . 我认为最好的方法是使用一个授权系统,如declarative_authorizationpunditcancancan They also provide view helpers that will let you hide the update link from users that can't update a particular comment. 它们还提供了视图帮助器,可让您向无法更新特定评论的用户隐藏更新链接。

Although if this is the only place you want authorization then writing your own solution as you suggest is probably a better option. 尽管如果这是您唯一需要授权的地方,那么按照您的建议编写自己的解决方案可能是一个更好的选择。 You could do something like this: 您可以执行以下操作:

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

Then in your model: 然后在您的模型中:

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

You'll probably have to tweak it to fit your needs, but you get the idea. 您可能必须对其进行调整以满足您的需求,但是您明白了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM