【问题标题】:Rails 4: "Pundit::NotAuthorizedError"Rails 4:“权威::NotAuthorizedError”
【发布时间】:2015-09-09 23:04:18
【问题描述】:

在我的 Rails 4 应用中,有 5 个模型:

class User < ActiveRecord::Base
  has_many :administrations
  has_many :calendars, through: :administrations
end

class Calendar < ActiveRecord::Base
  has_many :administrations
  has_many :users, through: :administrations
  has_many :posts
end

class Administration < ActiveRecord::Base
  belongs_to :user
  belongs_to :calendar
end

class Post < ActiveRecord::Base
  belongs_to :calendar
end

class Comment < ActiveRecord::Base
  belongs_to :post
  belongs_to :user
end

我使用 Devise 实现了身份验证(因此我们可以访问 current_user)。

现在,我正在尝试使用 Pundit(第一个计时器)实施授权。

按照documentation,我安装了gem并运行rails g pundit:install生成器。

然后,我创建了一个CalendarPolicy,如下:

class CalendarPolicy < ApplicationPolicy

  attr_reader :user, :calendar

  def initialize(user, calendar)
    @user = user
    @calendar = calendar
  end

  def index?
    user.owner? || user.editor? || user.viewer?
  end

  def show?
    user.owner? || user.editor? || user.viewer?
  end

  def update?
    user.owner? || user.editor?
  end

  def edit?
    user.owner? || user.editor?
  end

  def destroy?
    user.owner?
  end

end

我还使用以下方法更新了我的User 模型:

def owner?
  Administration.find_by(user_id: params[:user_id], calendar_id: params[:calendar_id]).role == "Owner"
end

def editor?
  Administration.find_by(user_id: params[:user_id], calendar_id: params[:calendar_id]).role == "Editor"
end

def viewer?
  Administration.find_by(user_id: params[:user_id], calendar_id: params[:calendar_id]).role == "Viewer"
end

我用authorize @calendar 更新了我的CalendarsController 操作,如下所示:

  def index
    @user = current_user
    @calendars = @user.calendars.all
  end

  # GET /calendars/1
  # GET /calendars/1.json
  def show
    @user = current_user
    @calendar = @user.calendars.find(params[:id])
    authorize @calendar
  end

  # GET /calendars/new
  def new
    @user = current_user
    @calendar = @user.calendars.new
    authorize @calendar
  end

  # GET /calendars/1/edit
  def edit
    @user = current_user
    authorize @calendar
  end

  # POST /calendars
  # POST /calendars.json
def create
  @user = current_user
  @calendar = @user.calendars.create(calendar_params)
  authorize @calendar
  respond_to do |format|
    if @calendar.save
      current_user.set_default_role(@calendar.id, 'Owner')
      format.html { redirect_to calendar_path(@calendar), notice: 'Calendar was successfully created.' }
      format.json { render :show, status: :created, location: @calendar }
    else
      format.html { render :new }
      format.json { render json: @calendar.errors, status: :unprocessable_entity }
    end
  end
end

  # PATCH/PUT /calendars/1
  # PATCH/PUT /calendars/1.json
  def update
    @user = current_user
    @calendar = Calendar.find(params[:id])
    authorize @calendar
    respond_to do |format|
      if @calendar.update(calendar_params)
        format.html { redirect_to calendar_path(@calendar), notice: 'Calendar was successfully updated.' }
        format.json { render :show, status: :ok, location: @calendar }
      else
        format.html { render :edit }
        format.json { render json: @calendar.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /calendars/1
  # DELETE /calendars/1.json
  def destroy
    @user = current_user
    @calendar.destroy
    authorize @calendar
    respond_to do |format|
      format.html { redirect_to calendars_url, notice: 'Calendar was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

我将after_action :verify_authorized, :except =&gt; :index 包含在我的ApplicationController 中。

现在,当我登录时,我可以访问 http://localhost:3000/calendars/,但是当我尝试访问 http://localhost:3000/calendars/new 时,我收到以下错误:

Pundit::NotAuthorizedError in CalendarsController#new
not allowed to new? this #<Calendar id: nil, name: nil, created_at: nil, updated_at: nil>

  @user = current_user
  @calendar = @user.calendars.new
  authorize @calendar
end

显然,我一定做错了什么。

问题:我不知道是什么。

有什么想法吗?

【问题讨论】:

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


    【解决方案1】:

    除非您通过它们,否则您无权访问模型中的参数。您应该将日历传递给模型实例函数,并且您已经可以访问用户。

    user.editor?(calendar)
    
    def editor?(calendar)
      Administration.find_by(user_id: self.id, calendar_id: calendar.id).role == "Editor"
    end
    

    【讨论】:

    • 好的,所以我根据您的回答更新了 User 模型以及 CalendarPolicy 中的所有 3 种方法。但我仍然收到相同的错误消息。还有其他想法吗?
    • 您使用的是 pry 还是调试器?我会将一个放在控制器中,一个放在授权方法中,一个放在模型中。然后确保所有变量都按预期设置。
    • 我不使用 Pry 也不使用调试器。我在开发和测试中安装了 Byebug。 “我会在控制器中放置一个,在授权方法中放置一个,在模型中放置一个。”是什么意思?
    【解决方案2】:

    问题是我没有在 CalendarPolicy 中定义 create 操作。

    由于 CalendarPolicy 继承自 ApplicationPolicy — CalendarPolicy &lt; ApplicationPolicy — 并且 ApplicationPolicy 中的 create 操作默认设置为 false,因此我遇到了错误。

    只需将以下代码添加到CalendarPolicy 即可解决问题:

    def create?
      true
    end
    

    额外提示:无需向CalendarPolicy 添加新操作,因为我们在ApplicationPolicy 中已有以下代码:

    def new?
      create?
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多