Как мне выполнить авторизацию файлов, загруженных с помощью Refile gem, с помощью Pundit? Я загрузил файлы, которые должны быть ограничены пользователем, который их загрузил, но любой, у кого есть URL-адрес, сгенерированный файлом attachment_url Refile, может получить доступ к файлу. Поскольку Refile использует собственное приложение Sinatra, у меня нет контроллера rails, в котором я мог бы вызвать метод авторизации Pundit.
Авторизация Pundit для файлов, загруженных с помощью Refile gem
Ответы (1)
В вашем контроллере у вас может быть метод, который будет загружать файл. Для более сложного примера предположим, что у вас есть действие 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
Редактировать: я просмотрел источник 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