使用 Refile gem 上传文件的 Pundit 授权
Pundit authorizaton for files uploaded with Refile gem
我如何使用 Pundit 对通过 Refile gem 上传的文件进行授权?我上传的文件应该仅限于上传它们的用户,但是任何拥有 Refile 的 attachment_url 生成的 url 的人都可以访问该文件。由于 Refile 使用它自己的 Sinatra 应用程序,因此我没有 rails 控制器来调用 Pundit 的授权方法。
在你的控制器中,你可以有一个下载文件的方法。对于更复杂的示例,假设您的 UsersController
控制器中有一个 download
操作。在这里,您可以像往常一样使用 pundit
。这个 download
动作抓住了用户的形象。
免责声明:这是一个糟糕的生产实践示例,因为如果多次调用此操作,您将对服务器进行重击。每次调用此操作时,您实际上都是在调整图像大小。但是,作为概念证明,超出了 refile
文件下载的正常工作方式并添加了您正在寻求的授权。
我们创建了一个 processor
变量来初始化 ImageProcessor
填充选项。然后我们创建一个临时文件并将其设置为二进制模式。我们从我们的用户模型中获取文件并将其读入临时文件。将临时文件回退到文件开头,读入MiniMagick
。然后我们调用我们的 processor
来转换临时文件(保持原始文件完好无损)。然后我们将文件发送给用户。
def download
@user = User.find(params[:id])
authorize @user
processor = Refile.processor(:fill, Refile::ImageProcessor.new(:fill))
temp_file = Tempfile.new('profile_image')
temp_file.binmode
temp_file.write @user.profile_image.read
temp_file.rewind
image_file = MiniMagick::Image.new(temp_file.path)
file = processor.fill(image_file, 150, 150)
temp_file.close
send_file file.path
end
这是将文件呈现为 image_tag
的示例
连同调用要调整大小和下载的图像的代码。
<%= image_tag user_download_path(@user), class: 'img-circle img-thumbnail' %>
您可以将操作设置为接受各种其他处理选项和维度。对于此示例,我展示了如何填充 150x150 像素的尺寸。
编辑以增加清晰度:
temp_file
的作用是保留原图。如果您只想提供原始文件的未处理下载,您可以执行以下操作。您还应该阅读 send_file
和 send_data
,因为它们提供了其他内容,例如 filename
、disposition
、content_type
等用于自定义下载及其方式的选项应该处理。
def download
@user = User.find(params[:id])
authorize @user
send_file @user.profile_image.download
end
编辑:我进一步查看了 Refile
来源,发现文件链接的创建是由引擎在路由中的安装引起的。创建一个初始化文件并将下面的代码放在那里。这将允许您保留上述现有功能,同时删除指向已上传文件的 public 链接。
Refile.configure do |config|
# config.direct_upload = ["cache"]
# config.allow_origin = "*"
# config.logger = Logger.new(STDOUT)
# config.mount_point = "attachments"
config.automount = false
# config.content_max_age = 60 * 60 * 24 * 365
# config.types[:image] = Refile::Type.new(:image, content_type: %w[image/jpeg image/gif image/png])
end
我如何使用 Pundit 对通过 Refile gem 上传的文件进行授权?我上传的文件应该仅限于上传它们的用户,但是任何拥有 Refile 的 attachment_url 生成的 url 的人都可以访问该文件。由于 Refile 使用它自己的 Sinatra 应用程序,因此我没有 rails 控制器来调用 Pundit 的授权方法。
在你的控制器中,你可以有一个下载文件的方法。对于更复杂的示例,假设您的 UsersController
控制器中有一个 download
操作。在这里,您可以像往常一样使用 pundit
。这个 download
动作抓住了用户的形象。
免责声明:这是一个糟糕的生产实践示例,因为如果多次调用此操作,您将对服务器进行重击。每次调用此操作时,您实际上都是在调整图像大小。但是,作为概念证明,超出了 refile
文件下载的正常工作方式并添加了您正在寻求的授权。
我们创建了一个 processor
变量来初始化 ImageProcessor
填充选项。然后我们创建一个临时文件并将其设置为二进制模式。我们从我们的用户模型中获取文件并将其读入临时文件。将临时文件回退到文件开头,读入MiniMagick
。然后我们调用我们的 processor
来转换临时文件(保持原始文件完好无损)。然后我们将文件发送给用户。
def download
@user = User.find(params[:id])
authorize @user
processor = Refile.processor(:fill, Refile::ImageProcessor.new(:fill))
temp_file = Tempfile.new('profile_image')
temp_file.binmode
temp_file.write @user.profile_image.read
temp_file.rewind
image_file = MiniMagick::Image.new(temp_file.path)
file = processor.fill(image_file, 150, 150)
temp_file.close
send_file file.path
end
这是将文件呈现为 image_tag
连同调用要调整大小和下载的图像的代码。
<%= image_tag user_download_path(@user), class: 'img-circle img-thumbnail' %>
您可以将操作设置为接受各种其他处理选项和维度。对于此示例,我展示了如何填充 150x150 像素的尺寸。
编辑以增加清晰度:
temp_file
的作用是保留原图。如果您只想提供原始文件的未处理下载,您可以执行以下操作。您还应该阅读 send_file
和 send_data
,因为它们提供了其他内容,例如 filename
、disposition
、content_type
等用于自定义下载及其方式的选项应该处理。
def download
@user = User.find(params[:id])
authorize @user
send_file @user.profile_image.download
end
编辑:我进一步查看了 Refile
来源,发现文件链接的创建是由引擎在路由中的安装引起的。创建一个初始化文件并将下面的代码放在那里。这将允许您保留上述现有功能,同时删除指向已上传文件的 public 链接。
Refile.configure do |config|
# config.direct_upload = ["cache"]
# config.allow_origin = "*"
# config.logger = Logger.new(STDOUT)
# config.mount_point = "attachments"
config.automount = false
# config.content_max_age = 60 * 60 * 24 * 365
# config.types[:image] = Refile::Type.new(:image, content_type: %w[image/jpeg image/gif image/png])
end