[英]CanCanCan not allowing access to endpoints which returns all records
I'm trying to configure authorisation for an API that I'm building in Rails.我正在尝试为我在 Rails 中构建的 API 配置授权。 The authorisation seems to be working but won't work on endpoints which return all records for a resource.授权似乎有效,但不适用于返回资源所有记录的端点。 These endpoints also happen to be created outside the resource block in config/routes.rb
(not sure if that is the correct way to explain that).这些端点也恰好是在config/routes.rb
的资源块之外创建的(不确定这是否是解释这一点的正确方法)。
eg: When I go to the following endpoint I get a 200 HTTP response if there is data or a 204 HTTP response if the record does not exist:例如:当我 go 到以下端点时,如果有数据,我会收到 200 HTTP 响应;如果记录不存在,则会收到 204 HTTP 响应:
http://localhost:3000/v1/resources/venues/zoom
But when I go to the following endpoint, I get an authorisation error:但是当我 go 到以下端点时,我收到授权错误:
http://localhost:3000/v1/resources/venues/all
This is my config/routes.rb
file:这是我的config/routes.rb
文件:
Rails.application.routes.draw do
# Private Messaging
resources :conversations, only: [:index, :create]
resources :messages, only: [:create]
mount ActionCable.server => '/cable'
# Admin
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
namespace :v1 do
namespace :resources do
# Users
post '/users/:id/avatar/upload' => 'users#upload_avatar'
patch '/users/:id/avatar/update' => 'users#update_avatar'
put '/users/:id/avatar/update' => 'users#update_avatar'
delete '/users/:id/avatar/delete' => 'users#delete_avatar'
namespace :users do
get ':id' => :show
end
# Venue Types
get '/venue_types/all' => 'venue_types#all'
post '/venues/:name/images/upload' => 'venues#upload_images'
namespace :venue_types do
get ':name' => :show
patch ':name' => :update
put ':name' => :update
delete ':name' => :delete
post 'new'
end
# Attributes
get '/attribute_defaults/all' => 'attribute_defaults#all'
namespace :attribute_defaults do
get ':id' => :show
patch ':id' => :update
put ':id' => :update
delete ':id' => :delete
post 'new'
end
# Venues
get '/venues/all' => 'venues#all'
namespace :venues do
get ':name' => :show
patch ':name' => :update
put ':name' => :update
delete ':name' => :delete
post 'new'
end
# Venue Attributes
get '/venue_attributes/all' => 'venue_attributes#all'
namespace :venue_attributes do
get ':id' => :show
patch ':id' => :update
put ':id' => :update
delete ':id' => :delete
post 'new'
end
# Bids
get '/bids/all' => 'bids#all'
namespace :bids do
get ':id' => :show
patch ':id' => :update
put ':id' => :update
delete ':id' => :delete
post 'new'
end
# Bookings
get '/bookings/all' => 'bookings#all'
namespace :bookings do
get ':id' => :show
patch ':id' => :update
put ':id' => :update
delete ':id' => :delete
post 'new'
end
# Venue Ratings
get '/venue_ratings/all' => 'venue_ratings#all'
namespace :venue_ratings do
get ':id' => :show
patch ':id' => :update
put ':id' => :update
delete ':id' => :delete
post 'new'
end
# User Ratings
get '/user_ratings/all' => 'user_ratings#all'
namespace :user_ratings do
get ':id' => :show
patch ':id' => :update
put ':id' => :update
delete ':id' => :delete
post 'new'
end
end
end
# Auth
devise_for :users,
path: 'auth',
path_names: {
sign_in: 'login',
sign_out: 'logout',
registration: 'register'
},
controllers: {
sessions: 'sessions',
registrations: 'registrations',
confirmations: 'confirmations'
}
end
This is my app/models/ability.rb
file:这是我的app/models/ability.rb
文件:
# frozen_string_literal: true
class Ability
include CanCan::Ability
def initialize(user)
# Admin
if user.present? && user.is_admin?
can :manage, :all
# Host
elsif user.present? && user.is_host?
can :manage, User, id: user.id
can [:read, :write, :update], [Venue, VenueAttribute, Bid, UserRating, VenueRating]
can [:read], User
can :destroy, [Venue, VenueAttribute]
# Guest
elsif user.present? && user.is_guest?
can :manage, User, id: user.id
can [:write, :update], [Bid, VenueRating], id: user.id
can [:write, :update], [UserRating], rated_by: user.id
can :read, Bid, id: user.id
can :read, [Venue, User, VenueRating, UserRating]
# No role
else
can :read, [Venue, User, UserRating, VenueRating]
end
end
end
This is my app/controllers/v1/resources/venues_controller.rb
file:这是我的app/controllers/v1/resources/venues_controller.rb
文件:
class V1::Resources::VenuesController < ActionController::API
load_and_authorize_resource param_method: :venue_params
respond_to :json
before_action :authenticate_user!, except: [:all, :show]
before_action :set_venue, except: [:all, :new]
# GET /v1/resources/venues/all
def all
@venues = Venue.all.where(is_published: true, is_expired: false)
if !@venues.empty?
render json: @venues, methods: :image_urls, status: :ok
else
head :no_content
end
end
# POST /v1/resources/venues/new
def new
@venue = Venue.new(venue_params)
if @venue.save
render json: @venue, status: :created
else
render json: @venue.errors, status: :unprocessable_entity
end
end
# GET /v1/resources/venues/:name
def show
if @venue
render json: @venue, methods: :image_urls, status: :ok
else
head :no_content
end
end
# PATCH/PUT /v1/resources/venues/:name
def update
if @venue.update(venue_params)
render json: @venue, status: :ok
else
render json: @venue.errors, status: :unprocessable_entity
end
end
# DELETE /v1/resources/venues/:name
def delete
@venue.destroy
head :no_content
end
# POST /v1/resources/venues/:name/images/upload
def upload_images
@venue.images.attach(params[:images])
render json: @venue, methods: :image_urls, status: :ok
end
private
# Use callbacks to share common setup or constraints between actions.
def set_venue
@venue = Venue.find_by(name: params[:name])
end
# Never trust parameters from the scary internet, only allow the white list through.
def venue_params
params.require(:venue).permit(:name, :price, :minimum_bid, :is_published, :currency, :is_expired, :location, :venue_type_id, :user_id, images: [])
end
end
The app/controllers/application_controller.rb
file has no extra code in it. app/controllers/application_controller.rb
文件中没有额外的代码。
Any idea how I can go about debugging this problem?知道如何调试这个问题吗? Also how do I give access to users that aren't authenticated?另外,我如何授予未经身份验证的用户访问权限? I would like users without accounts to be able to browse venues.我希望没有帐户的用户能够浏览场地。
At first, change load_and_authorize_resource
to authorize_resource
since you're loading it manually.首先,将load_and_authorize_resource
更改为authorize_resource
因为您是手动加载它。 Authorize manually in all
action.在all
操作中手动授权。
class V1::Resources::VenuesController < ActionController::API
authorize_resource param_method: :venue_params
skip_authorize_resource only: :all
respond_to :json
before_action :authenticate_user!, except: [:all, :show]
before_action :set_venue, except: [:all, :new]
# GET /v1/resources/venues/all
def all
@venues = Venue.all.where(is_published: true, is_expired: false)
authorize! :read, Venue
if !@venues.empty?
render json: @venues, methods: :image_urls, status: :ok
else
head :no_content
end
end
end
Add to ability.rb添加到能力.rb
if user.nil?
can :read, Venue
to get it working for not authenticated users使其适用于未经过身份验证的用户
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.