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

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

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
Другие вопросы по тегам