[英]Rails 6, Devise and Active Storage
我在 Rails 6 应用程序中使用 Devise 和 Active Storage。 目前正在使用before_action: authenticate_user!
为非用户禁用所有图像,这很好,除了我想让我的record_type
中active_storage_attachments
为“新闻”的图像可供用户和非用户查看。
下面的代码是我目前所拥有的,查看记录类型为新闻的record_type
::Attachment。 此代码显示用户和非用户的所有图像,这并不理想。
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
“新闻”。 但是,您需要检查用户尝试访问的特定图像是否属于“新闻”类型,然后允许他或不允许他。 执行此操作的一种方法是您可以检查的显示操作:
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 一起使用(@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
这里的其他答案对我的用例很有帮助,但如果其他人难以获得原始记录来做 model 特定的事情(就像我所做的那样),那么find_signed可能有助于获取其他检查、条件等所需的信息。
class ActiveStorage::BaseController < ActionController::Base
include Rails.application.routes.url_helpers
include ActiveStorage::SetCurrent
before_action :check_attachment
protect_from_forgery with: :exception
private
def check_attachment
blob_id = ActiveStorage::Blob.find_signed(params[:signed_id])
attachment = ActiveStorage::Attachment.find_by(blob_id: blob_id)
record = attachment.record_type.constantize.find(attachment.record_id)
if # Other model specific checks
# Can also redirect somewhere else here if needed:
# redirect_to root_path, alert: 'You do not have permission to access this.'
end
end
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.