Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix upload to s3 for private files - Updated #851

Merged
merged 6 commits into from
Oct 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 7 additions & 7 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ source 'https://rubygems.org'

gemspec

gem 'rspec_junit_formatter'
gem 'capybara-webkit'
# gem 'selenium-webdriver'
gem 'capybara-webkit' ### preferred, use this one before submitting PR
#gem 'selenium-webdriver' ### another alternative

gem 'capybara-screenshot'

gem 'rspec_junit_formatter'
gem 'rspec-rails'

gem 'puma'
gem 'factory_bot'
gem 'faker'
gem 'database_cleaner'
# gem 'poltergeist'
gem 'draper', '~> 3'
gem 'transactional_capybara'
gem 'rack_session_access'
group :development, :test do
gem 'rspec-rails'
end
42 changes: 19 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,23 @@ http://camaleon.tuzitio.com/store/plugins
![](screenshot.png)

## With Camaleon you can do:
* Integrate into existing Rails projects
* Multiples sites in the same installation
* Multi-language sites
* Design and create the architecture of your project without programming by dynamic contents and fields
* Extend or customize the functionalities by plugins
* Manage your content visualization by themes
* Advanced User roles
* Integrate into existent Rails projects
* Other features:
- Shortcodes
- Widgets
- Drag and Drop / Sortable / Multi level menus
- Templates/Layouts for pages
- Easy migration from Wordpress
* Extend or customize the functionality using plugins
* Manage your content visualization using themes
* Easier administration. Camaleon CMS permits you to adapt the CMS to all your needs and not you adapt to the CMS. You can create your custom architecture with any custom attributes that you need for all content types.

## Some features
* Integrate into existent Ruby on Rails Projects
* Easy administration
Camaleon CMS permits you to adapt the CMS to all your needs and not you adapt to the CMS.
I.E. you can create your custom architecture with all attributes that you need for each kind of content.
* Camaleon CMS is FREE and Open source
* Shortcodes
* Widgets
* Drag and Drop / Sortable / Multi level menus
* Templates/Layouts for pages
* Advanced User roles
* File Uploads with built in Local and Amazon S3 support
* Easy migration from Wordpress
* Security
- Remote code execution
- SQL injections
Expand Down Expand Up @@ -132,11 +130,11 @@ I.E. you can create your custom architecture with all attributes that you need f
## Support
If you have problems, please enter an issue [here.](https://github.com/owen2345/camaleon-cms/issues)
If you need support, need some extra functionality or need plugins, please contact us on:
* Site: http://camaleon.tuzitio.com/
* Gitter: https://gitter.im/camaleoncms/Lobby
* Email: owenperedo@gmail.com
* Skype: owen-2345
* Stack Overflow: Use "camaleon" as tag to ask questions related to this CMS (don't forget to include cms version + rails version).
* Gitter: https://gitter.im/camaleoncms/Lobby
* Site: http://camaleon.tuzitio.com/

## Author
Owen Peredo Diaz
Expand All @@ -150,9 +148,7 @@ http://camaleon.tuzitio.com/license.html
RAILS_ENV=test bundle exec rake app:db:migrate
RAILS_ENV=test bundle exec rake app:db:test:prepare
```
* Configure/Install Poltergeist and change your phanthomjs path in spec/spec_helper.rb

* Run testing
* Run tests
```
bundle exec rspec
```
Expand All @@ -164,10 +160,10 @@ bundle exec rspec
* Push to the branch (git push origin my_feature_branch)
* Create a pull request from your branch into master (Please be sure to provide enough detail for us to understand what this change is doing)

## Camaleon CMS is FREE and Open source
It was released on July, 2015 and tested previously with more than 20 projects by 6 months and on August 22, 2015 was published as a gem.

## Version History
Previous stable version (v1.x): https://github.com/owen2345/camaleon-cms/tree/version_1x

http://camaleon.tuzitio.com/version-history.html

Previous stable version (v1.x): https://github.com/owen2345/camaleon-cms/tree/version_1x

Camaleon CMS was originally released in July 2015 and tested previously with more than 20 projects by 6 months and on August 22, 2015 was published as a gem.
18 changes: 11 additions & 7 deletions app/controllers/camaleon_cms/admin/media_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ def crop

# download private files
def download_private_file
f_path = CamaleonCmsLocalUploader::private_file_path(params[:file], current_site)
if File.exist?(f_path)
send_file f_path, disposition: 'inline'
else
raise ActionController::RoutingError, 'File not found'
end
cama_uploader.enable_private_mode!

file = cama_uploader.fetch_file("private/#{params[:file]}")

send_file file, disposition: 'inline'

end

# render media for modal content
Expand Down Expand Up @@ -92,9 +92,13 @@ def upload(settings = {})
end

private

# init basic media variables
def init_media_vars
@cama_uploader = CamaleonCmsLocalUploader.new({current_site: current_site, private: true}) if params[:private].present?
# @cama_uploader = CamaleonCmsLocalUploader.new({current_site: current_site, private: true})

cama_uploader.enable_private_mode! if params[:private].present?

cama_uploader.clear_cache if params[:cama_media_reload] == 'clear_cache'
cama_uploader.reload if params[:cama_media_reload] == 'reload'
@media_formats = (params[:media_formats] || "").sub("media", ",video,audio").sub("all", "").split(",")
Expand Down
10 changes: 5 additions & 5 deletions app/models/camaleon_cms/media.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ class CamaleonCms::Media < ActiveRecord::Base
self.table_name = "#{PluginRoutes.static_system_info['db_prefix']}media"
belongs_to :site, class_name: 'CamaleonCms::Site'
validates :name, uniqueness: {
scope: [:site_id, :is_folder, :folder_path],
scope: [:site_id, :is_folder, :folder_path, :is_public],
message: 'Duplicates not allowed'
}
scope :only_folder, ->{ where(is_folder: true) }
Expand All @@ -18,7 +18,7 @@ def self.search(search_expression = '', folder = nil)
where('name like ?', "%#{search_expression}%")
end
end

# search file or folder by key
def self.find_by_key(key)
key = key.cama_fix_media_key
Expand All @@ -28,13 +28,13 @@ def self.find_by_key(key)
where(folder_path: File.dirname(key), name: File.basename(key))
end
end

# return all items of current folder
def items
coll = is_public ? site.public_media : site.private_media
coll.where(folder_path: "#{folder_path}/#{name}".cama_fix_media_key)
end

private
# recover folder or file format
def create_parent_folders
Expand All @@ -46,7 +46,7 @@ def create_parent_folders
_p.push(f_name)
end
end

# return all children items
def delete_folder_items
items.destroy_all if is_folder
Expand Down
44 changes: 34 additions & 10 deletions app/uploaders/camaleon_cms_aws_uploader.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
class CamaleonCmsAwsUploader < CamaleonCmsUploader

def after_initialize
@cloudfront = @aws_settings[:cloud_front] || @current_site.get_option("filesystem_s3_cloudfront")
@aws_region = @aws_settings[:region] || @current_site.get_option("filesystem_region", 'us-west-2')
Expand All @@ -10,6 +9,14 @@ def after_initialize
@aws_settings[:aws_file_read_settings] ||= lambda{|data, s3_file| data }
end

def setup_private_folder
if is_private_uploader?
add_folder(PRIVATE_DIRECTORY)

@aws_settings["inner_folder"] = "#{@aws_settings["inner_folder"]}/#{PRIVATE_DIRECTORY}"
end
end

# recover all files from AWS and parse it to save into DB as cache
def browser_files
bucket.objects(@aws_settings["inner_folder"].present? ? {prefix: @aws_settings["inner_folder"]} : nil).each do |file|
Expand All @@ -27,21 +34,38 @@ def objects(prefix = '/', sort = 'created_at')
super(prefix, sort)
end

def fetch_file(file_name)
bucket.object(file_name).download_file(file_name) unless file_exists?(file_name)

if file_exists?(file_name)
file_name
else
raise ActionController::RoutingError, 'File not found'
end
end

# parse an AWS file into custom file_object
def file_parse(s3_file)
key = s3_file.is_a?(String) ? s3_file : s3_file.key
key = key.cama_fix_media_key
is_dir = s3_file.is_a?(String) || File.extname(key) == ''

if is_private_uploader?
url = is_dir ? '' : File.basename(key)
else
url = is_dir ? '' : (@cloudfront.present? ? File.join(@cloudfront, key) : s3_file.public_url)
end

res = {
"name" => File.basename(key),
"folder_path" => File.dirname(key),
"url" => is_dir ? '' : (@cloudfront.present? ? File.join(@cloudfront, key) : s3_file.public_url),
"is_folder" => is_dir,
"file_size" => is_dir ? 0 : s3_file.size.round(2),
"thumb" => '',
'file_type' => is_dir ? '' : self.class.get_file_format(key),
'created_at' => is_dir ? '' : s3_file.last_modified,
'dimension' => ''
"name" => File.basename(key),
"folder_path" => File.dirname(key),
"url" => url,
"is_folder" => is_dir,
"file_size" => is_dir ? 0 : s3_file.size.round(2),
"thumb" => '',
'file_type' => is_dir ? '' : self.class.get_file_format(key),
'created_at' => is_dir ? '' : s3_file.last_modified,
'dimension' => ''
}.with_indifferent_access
res["thumb"] = version_path(res['url']).sub('.svg', '.jpg') if res['file_type'] == 'image' && File.extname(res['name']).downcase != '.gif'
res['key'] = File.join(res['folder_path'], res['name'])
Expand Down
40 changes: 22 additions & 18 deletions app/uploaders/camaleon_cms_local_uploader.rb
Original file line number Diff line number Diff line change
@@ -1,33 +1,37 @@
class CamaleonCmsLocalUploader < CamaleonCmsUploader
PRIVATE_DIRECTORY = 'private'
def after_initialize
@root_folder = @args[:root_folder] || @current_site.upload_directory

FileUtils.mkdir_p(@root_folder)
end

def setup_private_folder
@root_folder = Rails.root.join(self.class::PRIVATE_DIRECTORY).to_s

FileUtils.mkdir_p(@root_folder) unless Dir.exist?(@root_folder)
end

def browser_files(prefix = '/', objects = {})
path = File.join(@root_folder, prefix)

Dir.entries(path).each do |f_name|
next if f_name == '..' || f_name == '.' || f_name == 'thumb'

obj = file_parse(File.join(path, f_name).sub(@root_folder, '').cama_fix_media_key)
cache_item(obj)
browser_files(File.join(prefix, obj['name'])) if obj['is_folder']
end
end

# return the full file path for private file with key
# sample: 'my_file.pdf' ==> /var/www/my_app/private/my_file.pdf
def self.private_file_path(key, current_site)
Rails.root.join(self::PRIVATE_DIRECTORY, current_site.id.to_s, key.gsub(/(\/){2,}/, "/")).to_s
end

# check if this uploader is private mode
def is_private_uploader?
@args[:private]
if obj['is_folder']
browser_files(File.join(prefix, obj['name']))
end
end
end

def after_initialize
if is_private_uploader?
@root_folder = Rails.root.join(self.class::PRIVATE_DIRECTORY, @current_site.id.to_s).to_s
def fetch_file(file_name)
if file_exists?(file_name)
file_name
else
@root_folder = @args[:root_folder] || @current_site.upload_directory
raise ActionController::RoutingError, 'File not found'
end
FileUtils.mkdir_p(@root_folder) unless Dir.exist?(@root_folder)
end

def file_parse(key)
Expand Down
24 changes: 22 additions & 2 deletions app/uploaders/camaleon_cms_uploader.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
class CamaleonCmsUploader
PRIVATE_DIRECTORY = 'private'

attr_accessor :thumb
# root_folder= '/var/www/my_public_foler/', current_site= CamaSite.first.decorate, thumb = {w: 100, h: 75},
# aws_settings: {region, access_key, secret_key, bucket}
Expand Down Expand Up @@ -55,7 +57,7 @@ def cache_item(file_parsed, _objects_db = nil, custom_cache_key = nil)
end
file_parsed
end

# return the media collection for current situation
def get_media_collection
is_private_uploader? ? @current_site.public_media : @current_site.private_media
Expand Down Expand Up @@ -136,9 +138,27 @@ def get_file(key, use_cache = true)
# deprecated
end

def enable_private_mode!
@args[:private] = true

setup_private_folder
end

def disable_private_mode!
@args[:private] = false
end

def file_exists?(file_name)
File.exist?(file_name)
end

private
def cache_key
"cama_media_cache#{'_private' if is_private_uploader?}"
end
def is_private_uploader?() end

# check if this uploader is private mode
def is_private_uploader?
@args[:private]
end
end