Авторизация 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