In my rails (4.2.3) blog app, I use ckeditor to create the body of the post. I use carrierwave with cloudinary as my repository. The blog allows multiple users to log in and create posts.
Here are the highlights of the code:
# Gems
gem 'ckeditor', github: 'galetahub/ckeditor'
gem 'mini_magick'
gem 'carrierwave'
gem 'cloudinary'
# Uploader
class CkeditorPictureUploader < CarrierWave::Uploader::Base
include Ckeditor::Backend::CarrierWave
include Cloudinary::CarrierWave
include CarrierWave::MiniMagick
[:extract_content_type, :set_size, :read_dimensions].each do |method|
define_method :"#{method}_with_cloudinary" do
send(:"#{method}_without_cloudinary") if self.file.is_a?(CarrierWave::SanitizedFile)
{}
end
alias_method_chain method, :cloudinary
end
# ckeditor/config.js
// The location of an external file browser, that should be launched when "Browse Server" button is pressed.
config.filebrowserBrowseUrl = "/ckeditor/attachment_files";
// The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Flash dialog.
config.filebrowserFlashBrowseUrl = "/ckeditor/attachment_files";
// The location of a script that handles file uploads in the Flash dialog.
config.filebrowserFlashUploadUrl = "/ckeditor/attachment_files";
// The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Link tab of Image dialog.
config.filebrowserImageBrowseLinkUrl = "/ckeditor/pictures";
// The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Image dialog.
config.filebrowserImageBrowseUrl = "/ckeditor/pictures";
// The location of a script that handles file uploads in the Image dialog.
config.filebrowserImageUploadUrl = "/ckeditor/pictures";
// The location of a script that handles file uploads.
config.filebrowserUploadUrl = "/ckeditor/attachment_files";
config.allowedContent = true;
# In the forms:
<%= f.cktext_area :body, class: 'form-control ckeditor' %>
So, bloggers are able to create posts containing images, and they are uploaded to cloudinary.
However, I want to restrict one user from seeing another user's image.
If user A creates a post containing image A, image A is uploaded to cloudinary. When user B logs in, and edits the body, if they click on the image button and click 'browse server', they can see image A. I would like each user to only see their own images.
User B can also delete user A's image A from the upload dialog. That is catastrophic in my scenario.
Is there any way to partition my cloudinary space for different users in the context of ckeditor/carrierwave?
The only option I saw was that cloudinary allows you to override the public id for each upload, which forms a url part. And I could set the public_id from the uploader to be each user's id:
def public_id
return model.user.id
end
But I don't see how to use that to restrict access to those files only to that user from the uploader.
Another (pretty ugly) option is to remove the ckeditor->carrierwave->cloudinary integration entirely, and show my own "Upload image" button on top of each ckeditor text area, and when user clicks on it, only show their images in the modal popup. Once an image is uploaded/picked, I can (I think) then insert the image link into the cktextarea below it at the cursor position. I would have to reinvent the entire image resizing, etc. in my modal, since I cannot reuse the ones in the image dialog of ckeditor.