Авторизация Pundit для файлов, загруженных с помощью Refile gem

Как мне выполнить авторизацию файлов, загруженных с помощью Refile gem, с помощью Pundit? Я загрузил файлы, которые должны быть ограничены пользователем, который их загрузил, но любой, у кого есть URL-адрес, сгенерированный файлом attachment_url Refile, может получить доступ к файлу. Поскольку Refile использует собственное приложение Sinatra, у меня нет контроллера rails, в котором я мог бы вызвать метод авторизации Pundit.


person Jerome    schedule 01.03.2015    source источник


Ответы (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
person kobaltz    schedule 14.03.2015
comment
Спасибо кобальт! По сути, это то, что я сделал по предложению автора Refile за вычетом обработки изображения. Мои файлы были в формате pdf, поэтому мое действие загрузки создало временную ссылку непосредственно на S3 для загрузки файлов, полностью минуя Refile. Если бы это были изображения, вы абсолютно правы, это убило бы мое приложение, не используя кеширование. Спасибо еще раз! - person Jerome; 15.03.2015
comment
Без проблем. Я показал обработку изображений, поскольку она напрямую связана с функцией Refile, тогда как файлы PDF обычно не подвергаются постобработке. Кроме того, имейте в виду, что ваш URL-адрес вложения по-прежнему будет доступен, если кто-то попытается взломать сайт. Вы можете объявить об этом, закрыв эту дыру в драгоценном камне Refile. - person kobaltz; 15.03.2015
comment
@ Джером, не могли бы вы поделиться некоторыми подробностями о том, как вам удалось получить URL-адреса S3, может быть, какой-нибудь пример кода? Также не могли бы вы поделиться ссылкой на выпуск github, где вы обсуждали это с jnicklas? - person Mohamad; 01.08.2015