2015-09-09 2 views
0

В моем Rails 4 приложения, есть 5 моделей:Rails 4: "Пандит :: NotAuthorizedError"

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, я установил драгоценный камень и запустил генератор 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 

Я обновил свои CalendarsController действия с authorize @calendar, следующим образом:

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 => :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 

Очевидно, что я должен сделать что-то неправильно.

Проблема: я не могу понять, что.

Любая идея?

ответ

0

Проблема заключалась в том, что я не определил create действие в CalendarPolicy.

Поскольку CalendarPolicy наследует от ApplicationPolicy - CalendarPolicy < ApplicationPolicy - и create действия в ApplicationPolicy устанавливается в false по умолчанию, я получаю сообщение об ошибке.

Просто добавив следующий код CalendarPolicy исправили проблему:

def create? 
    true 
end 

Дополнительный совет: нет необходимости добавлять новое действие в CalendarPolicy, так как мы уже имеем следующий код в ApplicationPolicy:

def new? 
    create? 
end 
1

У вас нет доступа к параметрам модели, если вы не передадите их. Вы должны передать календарь функции экземпляра модели, и у вас уже есть доступ к пользователю.

user.editor?(calendar) 

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

Итак, я обновил все 3 метода в модели 'User', а также' CalendarPolicy' в соответствии с вашим ответом. Но я все равно получаю такое же сообщение об ошибке. Любая другая идея? –

+1

Вы используете pry или отладчик? Я бы поставил один в контроллер, один в методе авторизации и один в модели. Затем убедитесь, что все переменные заданы так, как ожидалось на этом пути. – penner

+0

Я не использую Pry и Debugger. У меня есть Byebug, установленный в разработке и тестировании. Что вы подразумеваете под «Я бы поставил один в контроллер, один в методе авторизации и один в модели».? –

Смежные вопросы