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?
如果有 attachment
和 record_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
所以这将检查用户试图访问的特定对象。
添加:
这种类型的授权可以使用一些授权库自动完成,例如:
您也可以允许访客用户使用某些类型的图像,而其他类型的图像只允许注册用户使用。
这将与 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
我在我的 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?
如果有 attachment
和 record_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
所以这将检查用户试图访问的特定对象。
添加:
这种类型的授权可以使用一些授权库自动完成,例如:
您也可以允许访客用户使用某些类型的图像,而其他类型的图像只允许注册用户使用。
这将与 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