Как мне сделать авторизацию на файлы, загруженные с помощью Refile gem, используя Pundit? Я загрузил файлы, которые должны быть ограничены пользователем, который их загрузил, но любой, у кого есть URL-адрес, который генерирует файл attachment_url, может получить доступ к файлу. Поскольку Refile использует свое собственное приложение Sinatra, для меня нет контроллера рельсов для вызова метода авторизации Pundit.Pundit authorizaton для файлов, загруженных с помощью Refile gem
ответ
В вашем контроллере у вас может быть способ, который будет загружать файл. Для более сложного примера предположим, что у вас есть действие download
в вашем контроллере UsersController
. Изнутри вы можете использовать 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
Edit: я посмотрел дальше в Refile
источник и обнаружил, что создание файла ссылок вызвано креплением двигателя в пределах маршрутов. Создайте файл инициализации и поместите здесь код. Это позволит вам сохранить существующую функциональность, описанную выше, при удалении общедоступных ссылок на загруженные файлы.
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
Thanks kobaltz! По сути, это то, что я делал по предложению автора Refile за вычетом обработки изображений. Мои файлы были pdf, поэтому мое действие загрузки создало временную ссылку непосредственно на S3 для загрузки файлов, полностью обходя Refile. Если бы это были изображения, вы абсолютно правы, это убьет мое приложение, не используя кеширование. Еще раз спасибо! – Jerome
Нет проблем. Я показал обработку изображения, поскольку он напрямую связан с функцией Refile, тогда как файлы PDF обычно не обрабатываются после обработки. Кроме того, имейте в виду, что ваш URL-адрес вложений будет по-прежнему доступен, если кто-то попытается применить грубую силу на сайте. Вы можете объявить об этом, закрыв это отверстие в камне Refile. – kobaltz
@ Jerome вы можете поделиться некоторыми подробностями о том, как вам удалось получить URL-адреса S3, может быть, пример кода? Также вы были бы любезны поделиться ссылкой на проблему github, где вы обсуждали это с помощью jnicklas? – Mohamad