1

在我的 Rails 应用程序中,我invoices有很多projects.

模型:

class Invoice < ActiveRecord::Base

  attr_accessible :project_id

end

控制器:

class InvoicesController < ApplicationController

  before_filter :authorized_user, :only => [ :show, :edit, :destroy ]
  before_filter :authorized_project, :only => [ :create, :update ]

  def create # safe
    @invoice = @project.invoices.build(params[:invoice])  
    if @invoice.save
      flash[:success] = "Invoice saved."
      redirect_to edit_invoice_path(@invoice)
    else
      render :new
    end
  end

  def update # not safe yet
    if @invoice.update_attributes(params[:invoice])
      flash[:success] = "Invoice updated."
      redirect_to edit_invoice_path(@invoice)
    else
      render :edit
    end
  end

  private

    def authorized_user
      @invoice = Invoice.find(params[:id])
      redirect_to root_path unless current_user?(@invoice.user)
    end

    def authorized_project
      @project = Project.find(params[:invoice][:project_id])
      redirect_to root_path unless current_user?(@project.user)
    end

end

我最大的担忧是,有朝一日,恶意用户可能会创建一个invoice属于project另一个用户的。

现在感谢这个板上一些人的帮助,我设法想出了一个before_filter确保在创建项目时不会发生这种情况的方法。

问题是我不明白如何将此过滤器也应用于update操作。

由于更新操作没有使用 Rails 的build功能,我根本不知道如何进入@project那里。

有人可以帮忙吗?

4

2 回答 2

1

在您的情况下,我将从 开始current_user,而不是@project(提供User has_many :invoices):

current_user.invoices.build(params[:invoice])

current_user?(@invoice.user)此外,您可以执行以下操作,而不是显式检查:

def find_invoice
  @invoice = current_user.invoices.find(params[:id])
end

def find_project
  @project = current_user.projects.find(params[:invoice][:project_id])
end

错误的发票或项目会抛出 500,您可能想处理也可能不想处理。

如果User has_many :invoices, :through => :projects并且Project因此has_many :invoices然后:

def find_invoice
  @invoice = @project.invoices.find(params[:id])
end
于 2013-09-27T16:14:33.053 回答
0

@project.invoices.build方法创建一个Invoice自动与该特定@project. 您不必做任何工作,也不存在将其链接到错误项目的风险。

不过,您需要确定这project_id不是可访问的属性。

于 2013-09-27T15:30:10.223 回答