Rails6、设计与主动存储

Rails 6, Devise and Active Storage

我在我的 rails 6 应用程序中使用 Devise 和 Active Storage。目前使用 before_action: authenticate_user! 禁用非用户的所有图像,这很好,除了我想让我的 active_storage_attachments 中带有 record_type 'News' 的图像可供用户和非用户查看用户。

下面的代码是我目前所拥有的,查看 ActiveStorage::Attachment 其中 record_type 是新闻。此代码显示用户和非用户的所有图像,这并不理想。

class ActiveStorage::BaseController < ActionController::Base
  before_action :allow_certain_assets
  include ActiveStorage::SetCurrent

  protect_from_forgery with: :exception
  
  private
  
  def allow_certain_assets
    if (ActiveStorage::Attachment.where(record_type: 'News')).present?
    else
      authenticate_user!
    end
  end
  
end

您的代码存在问题:

(ActiveStorage::Attachment.where(record_type: 'News')).present?

如果有 attachmentrecord_type 'News',它将检查整个数据库。但是相反,您需要检查用户尝试访问的特定图像是否属于 'News' 类型,然后允许他或不允许他。一种方法是在您可以检查的显示操作上:

def show
  # this code might be incorrect and I am not sure how you would be getting 
  # the attachment object but this would explain a way you can authenticate it
  @attachment = ActiveStorage::Attachment.find params[:id]
  authenticate_user! unless @attachment.record_type == 'News'
end

所以这将检查用户试图访问的特定对象。

添加:

这种类型的授权可以使用一些授权库自动完成,例如:

  1. CanCanCan
  2. Pundit

您也可以允许访客用户使用某些类型的图像,而其他类型的图像只允许注册用户使用。

这将与 Pundit gem (one of the options mentioned by @Deep )

一起使用
# controller
class ImagesController < ApplicationController
  def index
    authorize :image, :index?
    @images = policy_scope(ActiveRecord::Attachment)
  end

  def show
    @image = policy_scope(ActiveRecord::Attachment).find(params[:id])
    authorize @image, policy_class: ImagePolicy
  end
end
# policy
class ImagePolicy < ApplicationPolicy
  def index?
    true # must be true so that every can see the list
  end

  def show?
    true # optional: add more logic here
  end

  class Scope
    def initialize(user, scope)
      @user  = user
      @scope = scope
    end

    def resolve
      if user
        scope
      else        
        scope.where(record_type: 'News') # we limit the records here
      end
    end
  end
end