Pundit 一直要求我登录
Pundit keeps asking me to be logged in
我正在建立一个简单的网站,人们可以在上面上传他们的诗歌并创作新的诗歌。
我正在尝试使用 Pundit,以便:
- 每个人都可以看到所有 poems/poetries(在索引中)
- 只有登录用户才能创建诗歌
- 只有创建诗歌的用户才能更新或删除它
我遵循了官方文档,但我仍然需要登录才能在我的控制器中执行任何操作。
我不确定我做错了什么,因为我正在关注文档,这似乎是一种 copy/paste 类型的工作。
我的代码:
poetries_controller.rb
class PoetriesController < ApplicationController
before_action :set_poetry, only: [:show, :edit, :update, :destroy]
def index
@poetries = policy_scope(Poetry).order("RANDOM()").limit(30)
end
def show
end
def new
@poetry = Poetry.new
authorize @poetry
end
def create
Poetry.create(poetry_params)
authorize @poetry
redirect_to poetries_path
end
def edit
end
def update
@poetry.save
redirect_to poetry_path(@poetry)
end
def destroy
@poetry.destroy
redirect_to poetries_path
end
private
def poetry_params
params.require(:poetry).permit(:title, :author, :body)
end
def set_poetry
@poetry = Poetry.find(params[:id])
authorize @poetry
end
end
application_controller.rb
class ApplicationController < ActionController::Base
include Pundit
protect_from_forgery with: :exception
before_action :authenticate_user!
after_action :verify_authorized, :except => :index, unless: :devise_controller?
after_action :verify_policy_scoped, :only => :index, unless: :devise_controller?
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
private
def user_not_authorized
flash[:alert] = "Non sei autorizzato a eseguire questa azione"
redirect_to(root_path)
end
end
poetry_policy.rb
class PoetryPolicy < ApplicationPolicy
class Scope < Scope
def resolve
scope.all
end
end
def show?
true # Anyone can view a poetry
end
def create?
true # Anyone can create a poetry
end
def update?
record.user == user # Only poetry creator can update it
end
def destroy?
record.user == user # Only poetry creator can update it
end
end
application_policy.rb
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
@user = user
@record = record
end
def index?
false
end
def show?
scope.where(:id => record.id).exists?
end
def create?
false
end
def new?
create?
end
def update?
false
end
def edit?
update?
end
def destroy?
false
end
def scope
Pundit.policy_scope!(user, record.class)
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
scope.all
end
end
end
index.html.erb
<div class="container">
<div class="row">
<% @poetries.each do | poetry| %>
<div class="col-xs-12 col-sm-4">
<% if policy(poetry).show? %>
<%= link_to poetry_path(poetry) do %>
<div class="card">
<div class="card-description">
<h2> <%=poetry.title=%> </h2>
<% a = sanitize(poetry.body.truncate(170), tags: %w(br)) %></p>
<p> <%= a %></p>
<p><i><%=poetry.author=%><i></p>
</div>
</div>
<% end %>
<% end %>
</div>
<% end %>
<!-- </div> -->
</div>
</div>
你在 ApplicationController 中调用 before_action :authenticate_user!
,这就是为什么 Devise 不允许你看到诗歌#index。这根本不是 Pundit 的问题。
将此回调从 ApplicationController 移至所需的控制器,您确实要在其中检查身份验证。并用特定的动作来限制它。
class PoetriesController < ApplicationController
before_action :authenticate_user!, except: [:index, :show]
end
我正在建立一个简单的网站,人们可以在上面上传他们的诗歌并创作新的诗歌。
我正在尝试使用 Pundit,以便:
- 每个人都可以看到所有 poems/poetries(在索引中)
- 只有登录用户才能创建诗歌
- 只有创建诗歌的用户才能更新或删除它
我遵循了官方文档,但我仍然需要登录才能在我的控制器中执行任何操作。
我不确定我做错了什么,因为我正在关注文档,这似乎是一种 copy/paste 类型的工作。
我的代码:
poetries_controller.rb
class PoetriesController < ApplicationController
before_action :set_poetry, only: [:show, :edit, :update, :destroy]
def index
@poetries = policy_scope(Poetry).order("RANDOM()").limit(30)
end
def show
end
def new
@poetry = Poetry.new
authorize @poetry
end
def create
Poetry.create(poetry_params)
authorize @poetry
redirect_to poetries_path
end
def edit
end
def update
@poetry.save
redirect_to poetry_path(@poetry)
end
def destroy
@poetry.destroy
redirect_to poetries_path
end
private
def poetry_params
params.require(:poetry).permit(:title, :author, :body)
end
def set_poetry
@poetry = Poetry.find(params[:id])
authorize @poetry
end
end
application_controller.rb
class ApplicationController < ActionController::Base
include Pundit
protect_from_forgery with: :exception
before_action :authenticate_user!
after_action :verify_authorized, :except => :index, unless: :devise_controller?
after_action :verify_policy_scoped, :only => :index, unless: :devise_controller?
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
private
def user_not_authorized
flash[:alert] = "Non sei autorizzato a eseguire questa azione"
redirect_to(root_path)
end
end
poetry_policy.rb
class PoetryPolicy < ApplicationPolicy
class Scope < Scope
def resolve
scope.all
end
end
def show?
true # Anyone can view a poetry
end
def create?
true # Anyone can create a poetry
end
def update?
record.user == user # Only poetry creator can update it
end
def destroy?
record.user == user # Only poetry creator can update it
end
end
application_policy.rb
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
@user = user
@record = record
end
def index?
false
end
def show?
scope.where(:id => record.id).exists?
end
def create?
false
end
def new?
create?
end
def update?
false
end
def edit?
update?
end
def destroy?
false
end
def scope
Pundit.policy_scope!(user, record.class)
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
scope.all
end
end
end
index.html.erb
<div class="container">
<div class="row">
<% @poetries.each do | poetry| %>
<div class="col-xs-12 col-sm-4">
<% if policy(poetry).show? %>
<%= link_to poetry_path(poetry) do %>
<div class="card">
<div class="card-description">
<h2> <%=poetry.title=%> </h2>
<% a = sanitize(poetry.body.truncate(170), tags: %w(br)) %></p>
<p> <%= a %></p>
<p><i><%=poetry.author=%><i></p>
</div>
</div>
<% end %>
<% end %>
</div>
<% end %>
<!-- </div> -->
</div>
</div>
你在 ApplicationController 中调用 before_action :authenticate_user!
,这就是为什么 Devise 不允许你看到诗歌#index。这根本不是 Pundit 的问题。
将此回调从 ApplicationController 移至所需的控制器,您确实要在其中检查身份验证。并用特定的动作来限制它。
class PoetriesController < ApplicationController
before_action :authenticate_user!, except: [:index, :show]
end