简体   繁体   English

CanCanCan 不允许访问返回所有记录的端点

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM