camaleon_cms 2.8.0 → 2.8.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of camaleon_cms might be problematic. Click here for more details.

Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -7
  3. data/app/assets/javascripts/camaleon_cms/admin/lte/app.js +71 -57
  4. data/app/assets/stylesheets/camaleon_cms/admin/admin-manifest.css +2 -1
  5. data/app/assets/stylesheets/camaleon_cms/admin/{colorpicker.css.scss → colorpicker.css} +5 -5
  6. data/app/assets/stylesheets/camaleon_cms/admin/lte/_admin.css.scss +450 -69
  7. data/app/assets/stylesheets/camaleon_cms/admin/lte/skins/skin-black-light.css +15 -18
  8. data/app/assets/stylesheets/camaleon_cms/admin/lte/skins/skin-black.css +22 -18
  9. data/app/assets/stylesheets/camaleon_cms/admin/lte/skins/skin-blue-light.css +0 -3
  10. data/app/assets/stylesheets/camaleon_cms/admin/lte/skins/skin-blue.css +1 -4
  11. data/app/assets/stylesheets/camaleon_cms/admin/lte/skins/skin-green-light.css +0 -3
  12. data/app/assets/stylesheets/camaleon_cms/admin/lte/skins/skin-green.css +0 -3
  13. data/app/assets/stylesheets/camaleon_cms/admin/lte/skins/skin-purple-light.css +0 -3
  14. data/app/assets/stylesheets/camaleon_cms/admin/lte/skins/skin-purple.css +0 -4
  15. data/app/assets/stylesheets/camaleon_cms/admin/lte/skins/skin-red-light.css +0 -3
  16. data/app/assets/stylesheets/camaleon_cms/admin/lte/skins/skin-red.css +0 -3
  17. data/app/assets/stylesheets/camaleon_cms/admin/lte/skins/skin-yellow-light.css +0 -3
  18. data/app/assets/stylesheets/camaleon_cms/admin/lte/skins/skin-yellow.css +0 -3
  19. data/app/assets/stylesheets/camaleon_cms/bootstrap.min.css.map +1 -0
  20. data/app/controllers/camaleon_cms/admin/media_controller.rb +12 -9
  21. data/app/helpers/camaleon_cms/html_helper.rb +1 -1
  22. data/app/helpers/camaleon_cms/uploader_helper.rb +50 -12
  23. data/app/models/camaleon_cms/custom_field_group.rb +1 -4
  24. data/app/models/camaleon_cms/term_taxonomy.rb +13 -2
  25. data/app/uploaders/camaleon_cms_aws_uploader.rb +3 -3
  26. data/app/uploaders/camaleon_cms_local_uploader.rb +10 -4
  27. data/app/uploaders/camaleon_cms_uploader.rb +8 -0
  28. data/app/views/camaleon_cms/admin/settings/custom_fields/_get_items.html.erb +1 -2
  29. data/app/views/camaleon_cms/admin/settings/custom_fields/_render.html.erb +2 -2
  30. data/config/initializers/sass.rb +12 -16
  31. data/lib/camaleon_cms/engine.rb +1 -1
  32. data/lib/camaleon_cms/version.rb +1 -1
  33. metadata +46 -45
@@ -30,6 +30,8 @@ module CamaleonCms
30
30
 
31
31
  file = cama_uploader.fetch_file("private/#{params[:file]}")
32
32
 
33
+ return render plain: helpers.sanitize(file[:error]) if file.is_a?(Hash) && file[:error].present?
34
+
33
35
  send_file file, disposition: 'inline'
34
36
  end
35
37
 
@@ -51,16 +53,15 @@ module CamaleonCms
51
53
  def actions
52
54
  authorize! :manage, :media if params[:media_action] != 'crop_url'
53
55
  params[:folder] = params[:folder].gsub('//', '/') if params[:folder].present?
56
+
54
57
  case params[:media_action]
55
58
  when 'new_folder'
56
59
  params[:folder] = slugify_folder(params[:folder])
57
- render partial: 'render_file_item', locals: { files: [cama_uploader.add_folder(params[:folder])] }
60
+ return render partial: 'render_file_item', locals: { files: [cama_uploader.add_folder(params[:folder])] }
58
61
  when 'del_folder'
59
- cama_uploader.delete_folder(params[:folder])
60
- render plain: ''
62
+ r = cama_uploader.delete_folder(params[:folder])
61
63
  when 'del_file'
62
- cama_uploader.delete_file(params[:folder].gsub('//', '/'))
63
- render plain: ''
64
+ r = cama_uploader.delete_file(params[:folder].gsub('//', '/'))
64
65
  when 'crop_url'
65
66
  user_url = params[:url].to_s
66
67
  user_url = "#{current_site.the_url(locale: nil)}#{user_url}" unless user_url.start_with?('data:', 'http')
@@ -70,16 +71,18 @@ module CamaleonCms
70
71
  else
71
72
  cama_tmp_upload(user_url, formats: params[:formats], name: params[:name])
72
73
  end
73
- if r[:error].present?
74
- render plain: helpers.sanitize(r[:error])
75
- else
74
+ if r[:error].blank?
76
75
  params[:file_upload] = r[:file_path]
77
76
  sett = { remove_source: true }
78
77
  sett[:same_name] = true if params[:same_name].present?
79
78
  sett[:name] = params[:name] if params[:name].present?
80
- upload(sett)
79
+ return upload(sett)
81
80
  end
82
81
  end
82
+
83
+ return render plain: helpers.sanitize(r[:error]) if r[:error].present?
84
+
85
+ render plain: ''
83
86
  end
84
87
 
85
88
  # upload files from media uploader
@@ -117,7 +117,7 @@ module CamaleonCms
117
117
 
118
118
  libs = {}
119
119
  libs[:colorpicker] =
120
- { js: ['camaleon_cms/admin/bootstrap-colorpicker'], css: ['camaleon_cms/admin/colorpicker.css'] }
120
+ { js: ['camaleon_cms/admin/bootstrap-colorpicker'], css: ['camaleon_cms/admin/colorpicker'] }
121
121
  libs[:datepicker] = { js: [] }
122
122
  libs[:datetimepicker] = { js: [], css: [] }
123
123
  libs[:tinymce] =
@@ -1,7 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CamaleonCms
2
4
  module UploaderHelper
5
+ SUSPICIOUS_PATTERNS = [
6
+ /<script[\s>]/i, # Script tags
7
+ /on\w{3,}\s*=/i, # Inline event handlers like oncut, onload, onclick, etc.
8
+ /javascript:/i, # JavaScript in href/src attributes
9
+ /<iframe[\s>]/i, # Iframes
10
+ /<object[\s>]/i, # Object tags
11
+ /<embed[\s>]/i, # Embed tags
12
+ /<base[\s>]/i, # Base tags (can be used to manipulate URLs)
13
+ /data:/i # data: URLs (which can include scripts)
14
+ ].freeze
15
+
3
16
  include ActionView::Helpers::NumberHelper
4
17
  include CamaleonCms::CamaleonHelper
18
+
5
19
  # upload a file into server
6
20
  # settings:
7
21
  # folder: Directory where the file will be saved (default: "")
@@ -12,8 +26,9 @@ module CamaleonCms
12
26
  # formats: extensions permitted, sample: jpg,png,... or generic: images | videos | audios | documents (default *)
13
27
  # remove_source: Boolean (delete source file after saved if this is true, default false)
14
28
  # same_name: Boolean (save the file with the same name if defined true, else search for a non used name)
15
- # versions: (String) Create addtional multiple versions of the image uploaded, sample: '300x300,505x350' ==> Will create two extra images with these dimensions
16
- # sample "test.png", versions: '200x200,450x450' will generate: thumb/test-png_200x200.png, test-png_450x450.png
29
+ # versions: (String) Create additional multiple versions of the image uploaded,
30
+ # sample: '300x300,505x350' ==> Will create two extra images with these dimensions
31
+ # sample "test.png", versions: '200x200,450x450' will generate: thumb/test-png_200x200.png, test-png_450x450.png
17
32
  # thumb_size: String (redefine the dimensions of the thumbnail, sample: '100x100' ==> only for images)
18
33
  # temporal_time: if great than 0 seconds, then this file will expire (removed) in that time (default: 0)
19
34
  # To manage jobs, please check https://edgeguides.rubyonrails.org/active_job_basics.html
@@ -36,6 +51,8 @@ module CamaleonCms
36
51
  uploaded_io = File.open(cama_resize_upload(uploaded_io.path, settings[:dimension]))
37
52
  end
38
53
 
54
+ return { error: 'Potentially malicious content found!' } if file_content_unsafe?(uploaded_io)
55
+
39
56
  settings = settings.to_sym
40
57
  settings[:uploaded_io] = uploaded_io
41
58
  settings = {
@@ -54,10 +71,13 @@ module CamaleonCms
54
71
  same_name: false,
55
72
  versions: '',
56
73
  thumb_size: nil
57
- }.merge(settings)
74
+ }.merge!(settings)
58
75
  hooks_run('before_upload', settings)
59
76
  res = { error: nil }
60
77
 
78
+ # guard against path traversal
79
+ return { error: 'Invalid file path' } unless cama_uploader.class.valid_folder_path?(settings[:folder])
80
+
61
81
  # formats validations
62
82
  return { error: "#{ct('file_format_error')} (#{settings[:formats]})" } unless cama_uploader.class.validate_file_format(
63
83
  uploaded_io.path, settings[:formats]
@@ -194,7 +214,7 @@ module CamaleonCms
194
214
  # Return: (String) file path where saved this cropped
195
215
  # sample: cama_resize_and_crop(my_file, 200, 200, {gravity: :north_east, overwrite: false})
196
216
  def cama_resize_and_crop(file, w, h, settings = {})
197
- settings = { gravity: :north_east, overwrite: true, output_name: '' }.merge(settings)
217
+ settings = { gravity: :north_east, overwrite: true, output_name: +'' }.merge!(settings)
198
218
  img = MiniMagick::Image.open(file)
199
219
  if file.end_with? '.svg'
200
220
  img.format 'jpg'
@@ -300,10 +320,11 @@ module CamaleonCms
300
320
 
301
321
  # resize image if the format is correct
302
322
  # return resized file path
303
- def cama_resize_upload(image_path, dimesion, args = {})
304
- if cama_uploader.class.validate_file_format(image_path, 'image') && dimesion.present?
305
- r = { file: image_path, w: dimesion.split('x')[0], h: dimesion.split('x')[1], w_offset: 0, h_offset: 0,
306
- resize: !dimesion.split('x')[2] || dimesion.split('x')[2] == 'resize', replace: true, gravity: :north_east }.merge(args)
323
+ def cama_resize_upload(image_path, dimension, args = {})
324
+ if cama_uploader.class.validate_file_format(image_path, 'image') && dimension.present?
325
+ r = { file: image_path, w: dimension.split('x')[0], h: dimension.split('x')[1], w_offset: 0, h_offset: 0,
326
+ resize: !dimension.split('x')[2] || dimension.split('x')[2] == 'resize',
327
+ replace: true, gravity: :north_east }.merge!(args)
307
328
  hooks_run('on_uploader_resize', r)
308
329
  image_path = if r[:w].present? && r[:h].present?
309
330
  cama_resize_and_crop(r[:file], r[:w], r[:h], { overwrite: r[:replace], gravity: r[:gravity] })
@@ -334,7 +355,7 @@ module CamaleonCms
334
355
  data
335
356
  } # permit to read custom attributes from aws file and add to file parsed object
336
357
  },
337
- custom_uploader: nil # posibility to use custom file uploader
358
+ custom_uploader: nil # possibility to use custom file uploader
338
359
  }
339
360
  hooks_run('on_uploader', args)
340
361
  return args[:custom_uploader] if args[:custom_uploader].present?
@@ -355,13 +376,30 @@ module CamaleonCms
355
376
  end
356
377
 
357
378
  def slugify_folder(val)
358
- splitted_folder = val.split('/')
359
- splitted_folder[-1] = slugify(splitted_folder.last)
360
- splitted_folder.join('/')
379
+ split_folder = val.split('/')
380
+ split_folder[-1] = slugify(split_folder.last)
381
+ split_folder.join('/')
361
382
  end
362
383
 
363
384
  private
364
385
 
386
+ def file_content_unsafe?(uploaded_io)
387
+ file = uploaded_io.is_a?(ActionDispatch::Http::UploadedFile) ? uploaded_io.tempfile : uploaded_io
388
+ file_content_unsafe = nil
389
+
390
+ file.set_encoding(Encoding::BINARY) if file.respond_to?(:binmode) && file.respond_to?(:set_encoding)
391
+
392
+ file_content = file.read
393
+ SUSPICIOUS_PATTERNS.each do |pattern|
394
+ if file_content =~ pattern
395
+ Rails.logger.info { "Potentially malicious content found: #{pattern.inspect}" }
396
+ break file_content_unsafe = pattern.inspect
397
+ end
398
+ end
399
+
400
+ file_content_unsafe
401
+ end
402
+
365
403
  # helper for resize and crop method
366
404
  def cama_crop_offsets_by_gravity(gravity, original_dimensions, cropped_dimensions)
367
405
  original_width, original_height = original_dimensions
@@ -24,12 +24,9 @@ module CamaleonCms
24
24
  # - options (textbox sample): {"field_key":"text_box","multiple":"1","required":"1",
25
25
  # "translate":"1"}
26
26
  # * field_key (string) | translate (boolean) | default_value (unique value) |
27
- # default_values (array - multiple values for this field) | label_eval (boolean) |
28
- # multiple_options (array)
27
+ # default_values (array - multiple values for this field) | multiple_options (array)
29
28
  # * multiple_options (used for select, radio and checkboxes ): [{"title"=>"Option Title",
30
29
  # "value"=>"2", "default"=>"1"}, {"title"=>"abcde", "value"=>"3"}]
31
- # * label_eval: (Boolean, default false), true => will evaluate the label and description of
32
- # current field using (eval('my_label')) to have translatable|dynamic labels
33
30
  # ****** check all options for each case in Admin::CustomFieldsHelper ****
34
31
  # SAMPLE: my_model.add_field({"name"=>"Sub Title", "slug"=>"subtitle"}, {"field_key"=>"text_box",
35
32
  # "translate"=>true, default_value: "Get in Touch"})
@@ -3,6 +3,12 @@ module CamaleonCms
3
3
  include CamaleonCms::Metas
4
4
  include CamaleonCms::CustomFieldsRead
5
5
 
6
+ TRANSLATION_TAG_HIDE_MAP = { '<!--' => '!--', '-->' => '--!' }.freeze
7
+ TRANSLATION_TAG_HIDE_REGEX = Regexp.new(TRANSLATION_TAG_HIDE_MAP.keys.map { |x| Regexp.escape(x) }.join('|')).freeze
8
+ TRANSLATION_TAG_RESTORE_MAP = { '--!' => '-->', '!--' => '<!--' }.freeze
9
+ TRANSLATION_TAG_RESTORE_REGEX =
10
+ Regexp.new(TRANSLATION_TAG_RESTORE_MAP.keys.map { |x| Regexp.escape(x) }.join('|')).freeze
11
+
6
12
  def self.inherited(subclass)
7
13
  super
8
14
 
@@ -22,11 +28,16 @@ module CamaleonCms
22
28
  %i[name description].each do |attr|
23
29
  next unless new_record? || attribute_changed?(attr)
24
30
 
25
- self[attr] = ActionController::Base.helpers.sanitize(__send__(attr))
31
+ self[attr] = ActionController::Base.helpers.sanitize(
32
+ __send__(attr)&.gsub(TRANSLATION_TAG_HIDE_REGEX, TRANSLATION_TAG_HIDE_MAP)
33
+ )&.gsub(TRANSLATION_TAG_RESTORE_REGEX, TRANSLATION_TAG_RESTORE_MAP)
26
34
  end
27
35
  end
28
36
  else
29
- normalizes :name, :description, with: ->(field) { ActionController::Base.helpers.sanitize(field) }
37
+ normalizes :name, :description, with: lambda { |field|
38
+ ActionController::Base.helpers.sanitize(field.gsub(TRANSLATION_TAG_HIDE_REGEX, TRANSLATION_TAG_HIDE_MAP))
39
+ .gsub(TRANSLATION_TAG_RESTORE_REGEX, TRANSLATION_TAG_RESTORE_MAP)
40
+ }
30
41
  end
31
42
 
32
43
  # callbacks
@@ -36,11 +36,11 @@ class CamaleonCmsAwsUploader < CamaleonCmsUploader
36
36
  end
37
37
 
38
38
  def fetch_file(file_name)
39
- bucket.object(file_name).download_file(file_name) unless file_exists?(file_name)
39
+ return file_name if file_exists?(file_name)
40
40
 
41
- raise ActionController::RoutingError, 'File not found' unless file_exists?(file_name)
41
+ return file_name if bucket.object(file_name).download_file(file_name) && file_exists?(file_name)
42
42
 
43
- file_name
43
+ { error: 'File not found' }
44
44
  end
45
45
 
46
46
  # parse an AWS file into custom file_object
@@ -1,8 +1,8 @@
1
1
  class CamaleonCmsLocalUploader < CamaleonCmsUploader
2
2
  def after_initialize
3
- @root_folder = @args[:root_folder] || @current_site.upload_directory
3
+ @root_folder = @current_site.upload_directory
4
4
 
5
- FileUtils.mkdir_p(@root_folder)
5
+ FileUtils.mkdir_p(@root_folder) unless Dir.exist?(@root_folder)
6
6
  end
7
7
 
8
8
  def setup_private_folder
@@ -25,9 +25,11 @@ class CamaleonCmsLocalUploader < CamaleonCmsUploader
25
25
  end
26
26
 
27
27
  def fetch_file(file_name)
28
- raise ActionController::RoutingError, 'File not found' unless file_exists?(file_name)
28
+ return { error: 'Invalid file path' } if file_name.include?('..')
29
+
30
+ return file_name if file_exists?(file_name)
29
31
 
30
- file_name
32
+ { error: 'File not found' }
31
33
  end
32
34
 
33
35
  def file_parse(key)
@@ -107,6 +109,8 @@ class CamaleonCmsLocalUploader < CamaleonCmsUploader
107
109
 
108
110
  # remove an existent folder
109
111
  def delete_folder(key)
112
+ return { error: 'Invalid folder path' } if key.include?('..')
113
+
110
114
  folder = File.join(@root_folder, key)
111
115
  FileUtils.rm_rf(folder) if Dir.exist? folder
112
116
  get_media_collection.find_by_key(key).take.destroy
@@ -114,6 +118,8 @@ class CamaleonCmsLocalUploader < CamaleonCmsUploader
114
118
 
115
119
  # remove an existent file
116
120
  def delete_file(key)
121
+ return { error: 'Invalid file path' } if key.include?('..')
122
+
117
123
  file = File.join(@root_folder, key)
118
124
  FileUtils.rm(file) if File.exist? file
119
125
  @instance.hooks_run('after_delete', key)
@@ -125,6 +125,14 @@ class CamaleonCmsUploader
125
125
  valid_formats.include?(File.extname(key).sub('.', '').split('?').first.try(:downcase))
126
126
  end
127
127
 
128
+ def self.valid_folder_path?(path)
129
+ return true if path == '/'
130
+
131
+ return false if path.include?('..') || File.absolute_path?(path) || path.include?('://')
132
+
133
+ true
134
+ end
135
+
128
136
  # verify if this file name already exist
129
137
  # if the file is already exist, return a new name for this file
130
138
  # sample: search_new_key("my_file/file.txt")
@@ -23,7 +23,6 @@
23
23
  <div class="panel-body">
24
24
  <%= hidden_field(:fields, :id, index: @index, value: @item_id) %>
25
25
  <%= hidden_field(:field_options, :field_key, index: @index, value: @key) %>
26
- <%= hidden_field(:field_options, :label_eval, index: @index, value: @item_options_value[:label_eval].to_s.cama_true? ? 'true' : '') %>
27
26
  <%= hidden_field(:field_options, :panel_hidden, index: @index, value: @item_options_value[:panel_hidden], class: 'input-panel-hidden') %>
28
27
  <div class="form-group input-group-sm">
29
28
  <label for=""><%= t('camaleon_cms.admin.table.name') %></label><br>
@@ -182,4 +181,4 @@
182
181
  jQuery(function () {
183
182
  $('#<%= @panel_id %>').find('.translatable').Translatable();
184
183
  })
185
- </script>
184
+ </script>
@@ -20,14 +20,14 @@
20
20
  <input name="<%= field_name %>[<%= field.slug %>][id]" type="hidden" value="<%= field.id %>"/>
21
21
  <input name="<%= field_name %>[<%= field.slug %>][group_number]" class="cama_custom_group_number" type="hidden" value="0"/>
22
22
  <label>
23
- <%= field.options[:label_eval].present? ? eval(field.name) : field.name %>
23
+ <%= field.name %>
24
24
  <%= raw "<em class='text-danger'>*</em>" if field.options[:required].to_s.to_bool %>
25
25
  <% if current_site.get_option('custom_fields_show_shortcodes') && ["post", "posttype", "category", "postTag", "site", "user", "navmenu", "theme"].include?(obj_class) %>
26
26
  <small class="shortcode_field"><br><%= raw cama_shortcode_print("[data field='#{field.slug}' #{"object='#{obj_class}' #{"id='#{record.id}'" if obj_class != "Theme" }" unless record.new_record?}]") %></small>
27
27
  <% end %>
28
28
  </label>
29
29
  <% if field.description.present? %>
30
- <p><small><%= field.options[:label_eval].present? ? eval(field.description) : field.description %></small></p>
30
+ <p><small><%= field.description %></small></p>
31
31
  <% end %>
32
32
  <div class="editor-custom-fields content-field-<%= field.id %>" data-add_field_title="<%= t('camaleon_cms.admin.button.add_new_field', default: 'Add new field')%>">
33
33
  <%= begin
@@ -1,3 +1,5 @@
1
+ require 'sassc'
2
+
1
3
  module Sprockets
2
4
  # Processor engine class for the SASS/SCSS compiler. Depends on the `sass` gem.
3
5
  #
@@ -11,23 +13,23 @@ module Sprockets
11
13
  # return them path (this prefix automatically the path with current theme location)
12
14
  # Sample: .container{ background: #ffffff url(asset_theme_path('img/patterns/pattern1.jpg')); }
13
15
  def asset_theme_path(path, options = {})
14
- asset_path(Autoload::Sass::Script::String.new("#{get_theme_prefix}/#{path.value}".gsub('//', '/')), options)
16
+ asset_path(::SassC::Script::Value::String.new("#{get_theme_prefix}/#{path.value}".gsub('//', '/')), options)
15
17
  end
16
18
 
17
19
  # return them path (this prefix automatically the path with current theme location)
18
20
  # Sample: .container{ background: #ffffff asset-theme-url('img/patterns/pattern1.jpg'); }
19
21
  def asset_theme_url(path, options = {})
20
- asset_url(Autoload::Sass::Script::String.new("#{get_theme_prefix}/#{path.value}".gsub('//', '/')), options)
22
+ asset_url(::SassC::Script::Value::String.new("#{get_theme_prefix}/#{path.value}".gsub('//', '/')), options)
21
23
  end
22
24
 
23
25
  # return them path (this prefix automatically the path with current theme location)
24
26
  def asset_plugin_path(path, options = {})
25
- asset_path(Autoload::Sass::Script::String.new("#{get_plugin_prefix}/#{path.value}"), options)
27
+ asset_path(::SassC::Script::Value::String.new("#{get_plugin_prefix}/#{path.value}"), options)
26
28
  end
27
29
 
28
30
  # return them path (this prefix automatically the path with current theme location)
29
31
  def asset_plugin_url(path, options = {})
30
- asset_url(Autoload::Sass::Script::String.new("#{get_plugin_prefix}/#{path.value}"), options)
32
+ asset_url(::SassC::Script::Value::String.new("#{get_plugin_prefix}/#{path.value}"), options)
31
33
  end
32
34
 
33
35
  private
@@ -35,23 +37,17 @@ module Sprockets
35
37
  # get plugin asset prefix
36
38
  def get_plugin_prefix
37
39
  file = options[:filename]
38
- res = ''
39
- if file.include?('/plugins/')
40
- res = "plugins/#{file.split('/plugins/').last.split('/').first}/#{if file.include?('apps/plugins/')
41
- 'assets/'
42
- end}"
43
- end
44
- res
40
+ return '' unless file.include?('/plugins/')
41
+
42
+ "plugins/#{file.split('/plugins/').last.split('/').first}/#{file.include?('apps/plugins/') ? 'assets/' : ''}"
45
43
  end
46
44
 
47
45
  # get theme asset prefix
48
46
  def get_theme_prefix
49
47
  file = options[:filename]
50
- res = ''
51
- if file.include?('/themes/')
52
- res = "themes/#{file.split('/themes/').last.split('/').first}/#{'assets/' if file.include?('apps/themes/')}"
53
- end
54
- res
48
+ return '' unless file.include?('/themes/')
49
+
50
+ "themes/#{file.split('/themes/').last.split('/').first}/#{'assets/' if file.include?('apps/themes/')}"
55
51
  end
56
52
  end
57
53
  end
@@ -10,7 +10,7 @@ require 'aws-sdk-s3'
10
10
  require 'font-awesome-rails'
11
11
  require 'tinymce-rails'
12
12
  require 'jquery-rails'
13
- require 'sass-rails'
13
+ require 'dartsass-sprockets'
14
14
  require 'cama_contact_form'
15
15
  require 'cama_meta_tag'
16
16
 
@@ -1,3 +1,3 @@
1
1
  module CamaleonCms
2
- VERSION = '2.8.0'.freeze
2
+ VERSION = '2.8.2'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: camaleon_cms
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.0
4
+ version: 2.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Owen Peredo Diaz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-26 00:00:00.000000000 Z
11
+ date: 2024-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -52,6 +52,34 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: cama_contact_form
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.1.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.1.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: cama_meta_tag
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: cancancan
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -72,6 +100,20 @@ dependencies:
72
100
  - - "<"
73
101
  - !ruby/object:Gem::Version
74
102
  version: '4'
103
+ - !ruby/object:Gem::Dependency
104
+ name: dartsass-sprockets
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :runtime
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
75
117
  - !ruby/object:Gem::Dependency
76
118
  name: draper
77
119
  requirement: !ruby/object:Gem::Requirement
@@ -170,20 +212,6 @@ dependencies:
170
212
  - - "~>"
171
213
  - !ruby/object:Gem::Version
172
214
  version: '2.0'
173
- - !ruby/object:Gem::Dependency
174
- name: sass-rails
175
- requirement: !ruby/object:Gem::Requirement
176
- requirements:
177
- - - ">="
178
- - !ruby/object:Gem::Version
179
- version: '0'
180
- type: :runtime
181
- prerelease: false
182
- version_requirements: !ruby/object:Gem::Requirement
183
- requirements:
184
- - - ">="
185
- - !ruby/object:Gem::Version
186
- version: '0'
187
215
  - !ruby/object:Gem::Dependency
188
216
  name: sprockets-rails
189
217
  requirement: !ruby/object:Gem::Requirement
@@ -240,34 +268,6 @@ dependencies:
240
268
  - - ">="
241
269
  - !ruby/object:Gem::Version
242
270
  version: '0'
243
- - !ruby/object:Gem::Dependency
244
- name: cama_contact_form
245
- requirement: !ruby/object:Gem::Requirement
246
- requirements:
247
- - - "~>"
248
- - !ruby/object:Gem::Version
249
- version: 0.1.0
250
- type: :runtime
251
- prerelease: false
252
- version_requirements: !ruby/object:Gem::Requirement
253
- requirements:
254
- - - "~>"
255
- - !ruby/object:Gem::Version
256
- version: 0.1.0
257
- - !ruby/object:Gem::Dependency
258
- name: cama_meta_tag
259
- requirement: !ruby/object:Gem::Requirement
260
- requirements:
261
- - - ">="
262
- - !ruby/object:Gem::Version
263
- version: '0'
264
- type: :runtime
265
- prerelease: false
266
- version_requirements: !ruby/object:Gem::Requirement
267
- requirements:
268
- - - ">="
269
- - !ruby/object:Gem::Version
270
- version: '0'
271
271
  - !ruby/object:Gem::Dependency
272
272
  name: aws-sdk-s3
273
273
  requirement: !ruby/object:Gem::Requirement
@@ -644,7 +644,7 @@ files:
644
644
  - app/assets/stylesheets/camaleon_cms/admin/_jquery.tagsinput.css
645
645
  - app/assets/stylesheets/camaleon_cms/admin/admin-basic-manifest.css
646
646
  - app/assets/stylesheets/camaleon_cms/admin/admin-manifest.css
647
- - app/assets/stylesheets/camaleon_cms/admin/colorpicker.css.scss
647
+ - app/assets/stylesheets/camaleon_cms/admin/colorpicker.css
648
648
  - app/assets/stylesheets/camaleon_cms/admin/img/bg.png
649
649
  - app/assets/stylesheets/camaleon_cms/admin/img/colorpicker/alpha.png
650
650
  - app/assets/stylesheets/camaleon_cms/admin/img/colorpicker/hue.png
@@ -692,6 +692,7 @@ files:
692
692
  - app/assets/stylesheets/camaleon_cms/admin/uploader/uploader_manifest.css
693
693
  - app/assets/stylesheets/camaleon_cms/admin/widgets.css.scss
694
694
  - app/assets/stylesheets/camaleon_cms/bootstrap.min.css
695
+ - app/assets/stylesheets/camaleon_cms/bootstrap.min.css.map
695
696
  - app/assets/stylesheets/fonts/glyphicons-halflings-regular.eot
696
697
  - app/assets/stylesheets/fonts/glyphicons-halflings-regular.svg
697
698
  - app/assets/stylesheets/fonts/glyphicons-halflings-regular.ttf