camaleon_cms 2.7.5 → 2.8.1

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +20 -27
  3. data/app/apps/plugins/attack/config/config.json +2 -2
  4. data/app/apps/plugins/front_cache/admin_controller.rb +4 -6
  5. data/app/apps/plugins/front_cache/config/config.json +1 -1
  6. data/app/apps/plugins/front_cache/config/locales/translation.yml +1 -1
  7. data/app/apps/plugins/front_cache/front_cache_helper.rb +3 -3
  8. data/app/apps/plugins/visibility_post/config/config.json +2 -2
  9. data/app/apps/themes/camaleon_first/assets/js/main.js +1 -1
  10. data/app/apps/themes/camaleon_first/views/index.html.erb +1 -1
  11. data/app/apps/themes/default/assets/js/main.js +1 -1
  12. data/app/apps/themes/new/assets/js/main.js +1 -1
  13. data/app/apps/themes/new/views/index.html.erb +4 -4
  14. data/app/apps/themes/new/views/layouts/_footer.html.erb +2 -2
  15. data/app/assets/javascripts/camaleon_cms/admin/admin-basic-manifest.js +2 -2
  16. data/app/assets/javascripts/camaleon_cms/admin/admin-manifest.js +1 -1
  17. data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/de.js +2 -2
  18. data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/en.js +2 -2
  19. data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/fr.js +2 -2
  20. data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/it.js +2 -2
  21. data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/nl.js +1 -1
  22. data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/pt-BR.js +2 -2
  23. data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/ru.js +2 -2
  24. data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/uk.js +2 -2
  25. data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/zh-CN.js +1 -1
  26. data/app/assets/javascripts/camaleon_cms/admin/uploader/_media_manager.js +2 -2
  27. data/app/assets/stylesheets/camaleon_cms/admin/admin-manifest.css +2 -1
  28. data/app/assets/stylesheets/camaleon_cms/admin/{colorpicker.css.scss → colorpicker.css} +5 -5
  29. data/app/controllers/camaleon_cms/admin/appearances/nav_menus_controller.rb +15 -10
  30. data/app/controllers/camaleon_cms/admin/installers_controller.rb +1 -1
  31. data/app/controllers/camaleon_cms/admin/media_controller.rb +12 -9
  32. data/app/controllers/camaleon_cms/admin/settings_controller.rb +1 -1
  33. data/app/controllers/camaleon_cms/camaleon_controller.rb +8 -2
  34. data/app/decorators/camaleon_cms/application_decorator.rb +8 -0
  35. data/app/decorators/camaleon_cms/category_decorator.rb +1 -1
  36. data/app/decorators/camaleon_cms/post_decorator.rb +5 -5
  37. data/app/decorators/camaleon_cms/post_type_decorator.rb +3 -3
  38. data/app/decorators/camaleon_cms/term_taxonomy_decorator.rb +1 -1
  39. data/app/helpers/camaleon_cms/admin/category_helper.rb +1 -1
  40. data/app/helpers/camaleon_cms/frontend/nav_menu_helper.rb +12 -11
  41. data/app/helpers/camaleon_cms/html_helper.rb +7 -7
  42. data/app/helpers/camaleon_cms/plugins_helper.rb +1 -1
  43. data/app/helpers/camaleon_cms/session_helper.rb +1 -1
  44. data/app/helpers/camaleon_cms/short_code_helper.rb +1 -1
  45. data/app/helpers/camaleon_cms/site_helper.rb +1 -1
  46. data/app/helpers/camaleon_cms/theme_helper.rb +1 -1
  47. data/app/helpers/camaleon_cms/uploader_helper.rb +60 -17
  48. data/app/models/camaleon_cms/ability.rb +1 -1
  49. data/app/models/camaleon_cms/custom_field_group.rb +3 -6
  50. data/app/models/camaleon_cms/nav_menu.rb +1 -1
  51. data/app/models/camaleon_cms/post.rb +1 -1
  52. data/app/models/camaleon_cms/post_default.rb +1 -1
  53. data/app/models/camaleon_cms/post_type.rb +8 -8
  54. data/app/models/camaleon_cms/site.rb +1 -1
  55. data/app/models/camaleon_cms/term_taxonomy.rb +13 -0
  56. data/app/models/concerns/camaleon_cms/custom_fields_read.rb +11 -22
  57. data/app/models/concerns/camaleon_cms/site_default_settings.rb +1 -1
  58. data/app/uploaders/camaleon_cms_aws_uploader.rb +3 -3
  59. data/app/uploaders/camaleon_cms_local_uploader.rb +10 -4
  60. data/app/uploaders/camaleon_cms_uploader.rb +13 -0
  61. data/app/validators/camaleon_cms/post_uniq_validator.rb +11 -12
  62. data/app/validators/camaleon_cms/uniq_validator.rb +9 -3
  63. data/app/views/camaleon_cms/admin/media/index.html.erb +1 -1
  64. data/app/views/camaleon_cms/admin/settings/_email_settings.html.erb +2 -2
  65. data/app/views/camaleon_cms/admin/settings/custom_fields/_get_items.html.erb +1 -2
  66. data/app/views/camaleon_cms/admin/settings/custom_fields/_render.html.erb +2 -2
  67. data/app/views/camaleon_cms/default_theme/index.html.erb +4 -4
  68. data/app/views/camaleon_cms/default_theme/sitemap.xml.builder +3 -3
  69. data/app/views/layouts/camaleon_cms/admin/_footer.html.erb +1 -1
  70. data/config/initializers/custom_initializers.rb +14 -0
  71. data/config/initializers/sass.rb +12 -16
  72. data/lib/camaleon_cms/engine.rb +2 -2
  73. data/lib/camaleon_cms/version.rb +1 -1
  74. data/lib/ext/hash.rb +1 -1
  75. data/lib/ext/string.rb +2 -2
  76. data/lib/generators/camaleon_cms/theme_template/assets/js/main.js +1 -1
  77. metadata +53 -39
@@ -101,7 +101,7 @@ module CamaleonCms
101
101
  # add a post for current model
102
102
  # title: title for post, => required
103
103
  # content: html text content, => required
104
- # thumb: image url, => default (empty). check http://camaleon.tuzitio.com/api-methods.html#section_fileuploads
104
+ # thumb: image url, => default (empty). check https://camaleon.website/api-methods.html#section_fileuploads
105
105
  # categories: [1,3,4,5], => default (empty)
106
106
  # tags: String comma separated, => default (empty)
107
107
  # slug: string key for post, => default (empty)
@@ -111,7 +111,7 @@ module CamaleonCms
111
111
  # settings: Hash of post settings, sample => settings:
112
112
  # {has_content: false, has_summary: true, default_layout: 'my_layout', default_template: 'my_template' } (optional, see more in post.set_setting(...))
113
113
  # data_metas: {template: "", layout: ""}
114
- # sample: my_posttype.add_post(title: "My Title", post_order: 5, content: 'lorem_ipsum', settings: {default_template: "home/counters", has_content: false, has_seo: false, skip_fields: ["sub_tite", 'banner']}, fields: {pattern: true, bg: 'http://www.reallusion.com/de/images/3dx5/whatsnew/3dx5_features_banner_bg_02.jpg'})
114
+ # sample: my_posttype.add_post(title: "My Title", post_order: 5, content: 'lorem_ipsum', settings: {default_template: "home/counters", has_content: false, has_seo: false, skip_fields: ["sub_tite", 'banner']}, fields: {pattern: true, bg: 'https://www.reallusion.com/de/images/3dx5/whatsnew/3dx5_features_banner_bg_02.jpg'})
115
115
  # More samples here: https://gist.github.com/owen2345/eba9691585ed78ad6f7b52e9591357bf
116
116
  # return created post if it was created, else return errors
117
117
  def add_post(args)
@@ -139,12 +139,12 @@ module CamaleonCms
139
139
  # return all available route formats of this post type for content posts
140
140
  def contents_route_formats
141
141
  {
142
- 'post_of_post_type' => '<code>/group/:post_type_id-:title/:slug</code><br> (Sample: http://localhost.com/group/17-services/myservice.html)',
143
- 'post_of_category' => '<code>/category/:category_id-:title/:slug</code><br> (Sample: http://localhost.com/category/17-services/myservice.html)',
144
- 'post_of_category_post_type' => '<code>/:post_type_title/category/:category_id-:title/:slug</code><br> (Sample: http://localhost.com/services/category/17-services/myservice.html)',
145
- 'post_of_posttype' => '<code>/:post_type_title/:slug</code><br> (Sample: http://localhost.com/services/myservice.html)',
146
- 'post' => '<code>/:slug</code><br> (Sample: http://localhost.com/myservice.html)',
147
- 'hierarchy_post' => '<code>/:parent1_slug/:parent2_slug/.../:slug</code><br> (Sample: http://localhost.com/item-1/item-1-1/item-111.html)'
142
+ 'post_of_post_type' => '<code>/group/:post_type_id-:title/:slug</code><br> (Sample: https://localhost.com/group/17-services/myservice.html)',
143
+ 'post_of_category' => '<code>/category/:category_id-:title/:slug</code><br> (Sample: https://localhost.com/category/17-services/myservice.html)',
144
+ 'post_of_category_post_type' => '<code>/:post_type_title/category/:category_id-:title/:slug</code><br> (Sample: https://localhost.com/services/category/17-services/myservice.html)',
145
+ 'post_of_posttype' => '<code>/:post_type_title/:slug</code><br> (Sample: https://localhost.com/services/myservice.html)',
146
+ 'post' => '<code>/:slug</code><br> (Sample: https://localhost.com/myservice.html)',
147
+ 'hierarchy_post' => '<code>/:parent1_slug/:parent2_slug/.../:slug</code><br> (Sample: https://localhost.com/item-1/item-1-1/item-111.html)'
148
148
  }
149
149
  end
150
150
 
@@ -91,7 +91,7 @@ module CamaleonCms
91
91
  # return theme model with slug theme_slug for this site
92
92
  # theme_slug: (optional) if it is null, this will return current theme for this site
93
93
  def get_theme(theme_slug = nil)
94
- themes.where(slug: (theme_slug || get_theme_slug), status: nil).first_or_create!
94
+ themes.where(slug: theme_slug || get_theme_slug, status: nil).first_or_create!
95
95
  end
96
96
 
97
97
  # return plugin model with slug plugin_slug
@@ -16,6 +16,19 @@ module CamaleonCms
16
16
  # attr_accessible :data_options
17
17
  # attr_accessible :data_metas
18
18
 
19
+ # TODO: Remove the 1st branch when support will be dropped of Rails < 7.1
20
+ if ::Rails::VERSION::STRING < '7.1.0'
21
+ before_validation(on: %i[create update]) do
22
+ %i[name description].each do |attr|
23
+ next unless new_record? || attribute_changed?(attr)
24
+
25
+ self[attr] = ActionController::Base.helpers.sanitize(__send__(attr))
26
+ end
27
+ end
28
+ else
29
+ normalizes :name, :description, with: ->(field) { ActionController::Base.helpers.sanitize(field) }
30
+ end
31
+
19
32
  # callbacks
20
33
  before_validation :before_validating
21
34
  before_destroy :destroy_dependencies
@@ -3,18 +3,6 @@ module CamaleonCms
3
3
  extend ActiveSupport::Concern
4
4
  included do
5
5
  before_destroy :_destroy_custom_field_groups
6
- # DEPRECATED, INSTEAD USE: custom_fields
7
- has_many :fields, lambda { |object|
8
- where(object_class: object.class.to_s.gsub('Decorator', '').gsub('CamaleonCms::', ''))
9
- }, class_name: 'CamaleonCms::CustomField', foreign_key: :objectid
10
- # DEPRECATED, INSTEAD USE: custom_field_values
11
- has_many :field_values, lambda { |object|
12
- where(object_class: object.class.to_s.gsub('Decorator', '').gsub('CamaleonCms::', ''))
13
- }, class_name: 'CamaleonCms::CustomFieldsRelationship', foreign_key: :objectid, dependent: :delete_all
14
- # DEPRECATED, INSTEAD USE: custom_field_groups
15
- has_many :field_groups, lambda { |object|
16
- where(object_class: object.class.to_s.parseCamaClass)
17
- }, class_name: 'CamaleonCms::CustomFieldGroup', foreign_key: :objectid
18
6
  end
19
7
 
20
8
  # get custom field groups for current object
@@ -38,7 +26,7 @@ module CamaleonCms
38
26
  { kind: args,
39
27
  include_parent: false }
40
28
  else
41
- { kind: 'Post', include_parent: false }.merge(args)
29
+ { kind: 'Post', include_parent: false }.merge!(args)
42
30
  end
43
31
  class_name = self.class.to_s.parseCamaClass
44
32
  case class_name
@@ -73,7 +61,7 @@ module CamaleonCms
73
61
  CamaleonCms::CustomFieldGroup.where(object_class: "PostType_#{args[:kind]}", objectid: id)
74
62
  end
75
63
  else # 'Plugin' or other classes
76
- field_groups
64
+ custom_field_groups
77
65
  end
78
66
  end
79
67
 
@@ -131,7 +119,7 @@ module CamaleonCms
131
119
  # puts res[0]['my_slug1'].first ==> "val 1"
132
120
  def get_fields_grouped(field_keys)
133
121
  res = []
134
- custom_field_values.where(custom_field_slug: field_keys).order(group_number: :asc).group_by(&:group_number).each do |_group_number, group_fields|
122
+ custom_field_values.where(custom_field_slug: field_keys).order(group_number: :asc).group_by(&:group_number).each_value do |group_fields|
135
123
  group = {}
136
124
  field_keys.each do |field_key|
137
125
  _tmp = []
@@ -196,8 +184,8 @@ module CamaleonCms
196
184
  # kind: argument only for PostType model: (Post | Category | PostTag), default => Post. If kind = "" this will add group for all post_types
197
185
  def add_custom_field_group(values, kind = 'Post')
198
186
  values = values.with_indifferent_access
199
- group = get_field_groups(kind).where(slug: values[:slug]).first
200
- unless group.present?
187
+ group = get_field_groups(kind).find_by(slug: values[:slug])
188
+ unless group
201
189
  site = _cama_get_field_site
202
190
  values[:parent_id] = site.id if site.present?
203
191
  group = if is_a?(CamaleonCms::Post) # harcoded for post to support custom field groups
@@ -206,6 +194,7 @@ module CamaleonCms
206
194
  get_field_groups(kind).create!(values)
207
195
  end
208
196
  end
197
+
209
198
  group
210
199
  end
211
200
  alias add_field_group add_custom_field_group
@@ -215,8 +204,8 @@ module CamaleonCms
215
204
  # more details in add_manual_field(item, options) from custom field groups
216
205
  # kind: argument only for PostType model: (Post | Category | PostTag), default => Post
217
206
  def add_custom_field_to_default_group(item, options, kind = 'Post')
218
- g = get_field_groups(kind).where(slug: '_default').first
219
- g = add_custom_field_group({ name: 'Default Field Group', slug: '_default' }, kind) unless g.present?
207
+ g = get_field_groups(kind).find_by(slug: '_default')
208
+ g ||= add_custom_field_group({ name: 'Default Field Group', slug: '_default' }, kind)
220
209
  g.add_manual_field(item, options)
221
210
  end
222
211
  alias add_field add_custom_field_to_default_group
@@ -243,7 +232,7 @@ module CamaleonCms
243
232
 
244
233
  ActiveRecord::Base.transaction do
245
234
  custom_field_values.delete_all
246
- datas.each do |_index, fields_data|
235
+ datas.each_value do |fields_data|
247
236
  fields_data.each do |field_key, values|
248
237
  next unless values[:values].present?
249
238
 
@@ -260,7 +249,7 @@ module CamaleonCms
260
249
  # update new value for field with slug _key
261
250
  # Sample: my_posy.update_field_value('sub_title', 'Test Sub Title')
262
251
  def update_field_value(_key, value = nil, group_number = 0)
263
- custom_field_values.where(custom_field_slug: _key, group_number: group_number).first.update_column('value', value)
252
+ custom_field_values.find_by(custom_field_slug: _key, group_number: group_number)&.update_column('value', value)
264
253
  rescue StandardError
265
254
  nil
266
255
  end
@@ -287,7 +276,7 @@ module CamaleonCms
287
276
  # sample: my_post.set_field_value('subtitle', 'Sub Title', {group_number: 1})
288
277
  # sample: my_post.set_field_value('subtitle', 'Sub Title', {group_number: 1, group_number: 1}) # add field values for fields in group 1
289
278
  def set_field_value(key, value, args = {})
290
- args = { order: 0, group_number: 0, field_id: nil, clear: true }.merge(args)
279
+ args = { order: 0, group_number: 0, field_id: nil, clear: true }.merge!(args)
291
280
  unless args[:field_id].present?
292
281
  args[:field_id] = begin
293
282
  get_field_object(key).id
@@ -25,7 +25,7 @@ module CamaleonCms
25
25
  else
26
26
  title = 'Welcome'
27
27
  slug = 'welcome'
28
- content = "<p style='text-align: center;'><img width='155' height='155' src='http://camaleon.tuzitio.com/media/132/logo2.png' alt='logo' /></p><p><strong>Camaleon CMS</strong>&nbsp;is a free and open-source tool and a fexible content management system (CMS) based on <a href='http://rubyonrails.org'>Ruby on Rails</a>.</p> <p>With Camaleon you can do the following:</p> <ul> <li>Create instantly a lot of sites&nbsp;in the same installation</li> <li>Manage your content information in several languages</li> <li>Extend current functionality by&nbsp;plugins (MVC structure and no more echo or prints anywhere)</li> <li>Create or install different themes for each site</li> <li>Create your own structure without coding anything (adapt Camaleon as you want&nbsp;and not you for Camaleon)</li> <li>Create your store and start to sell your products using our plugins</li> <li>Avoid web attacks</li> <li>Compare the speed and enjoy the speed of your new Camaleon site</li> <li>Customize or create your themes for mobile support</li> <li>Support&nbsp;more visitors at the same time</li> <li>Manage your information with a panel like wordpress&nbsp;</li> <li>All urls are oriented for SEO</li> <li>Multiples roles of users</li> </ul>"
28
+ content = "<p style='text-align: center;'><img width='155' height='155' src='https://camaleon.website/media/132/logo2.png' alt='logo' /></p><p><strong>Camaleon CMS</strong>&nbsp;is a free and open-source tool and a fexible content management system (CMS) based on <a href='https://rubyonrails.org'>Ruby on Rails</a>.</p> <p>With Camaleon you can do the following:</p> <ul> <li>Create instantly a lot of sites&nbsp;in the same installation</li> <li>Manage your content information in several languages</li> <li>Extend current functionality by&nbsp;plugins (MVC structure and no more echo or prints anywhere)</li> <li>Create or install different themes for each site</li> <li>Create your own structure without coding anything (adapt Camaleon as you want&nbsp;and not you for Camaleon)</li> <li>Create your store and start to sell your products using our plugins</li> <li>Avoid web attacks</li> <li>Compare the speed and enjoy the speed of your new Camaleon site</li> <li>Customize or create your themes for mobile support</li> <li>Support&nbsp;more visitors at the same time</li> <li>Manage your information with a panel like wordpress&nbsp;</li> <li>All urls are oriented for SEO</li> <li>Multiples roles of users</li> </ul>"
29
29
  end
30
30
  user = users.admin_scope.first
31
31
  unless user.present?
@@ -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")
@@ -158,6 +166,11 @@ class CamaleonCmsUploader
158
166
  File.exist?(file_name)
159
167
  end
160
168
 
169
+ def self.delete_block(&block)
170
+ @delete_block = block if block
171
+ @delete_block
172
+ end
173
+
161
174
  private
162
175
 
163
176
  def cache_key
@@ -14,18 +14,17 @@ module CamaleonCms
14
14
  )
15
15
  .where.not(id: record.id)
16
16
  .where.not(status: %i[draft draft_child trash])
17
- if posts.size.positive?
18
- record.errors[:base] << if slug_array.size > 1
19
- "#{I18n.t('camaleon_cms.admin.post.message.requires_different_slug')}: #{posts.pluck(:slug).map do |slug|
20
- record.slug.to_s.translations.map do |lng, r_slug|
21
- if slug.translations_array.include?(r_slug)
22
- "#{r_slug} (#{lng})"
23
- end
24
- end.join(',')
25
- end.join(',').split(',').uniq.clean_empty.join(', ')} "
26
- else
27
- "#{I18n.t('camaleon_cms.admin.post.message.requires_different_slug')}: #{record.slug} "
28
- end
17
+ unless posts.empty?
18
+ record.errors[:base] <<
19
+ if slug_array.size > 1
20
+ "#{I18n.t('camaleon_cms.admin.post.message.requires_different_slug')}: #{posts.pluck(:slug).map do |slug|
21
+ record.slug.to_s.translations.map do |lng, r_slug|
22
+ "#{r_slug} (#{lng})" if slug.translations_array.include?(r_slug)
23
+ end.join(',')
24
+ end.join(',').split(',').uniq.clean_empty.join(', ')} "
25
+ else
26
+ "#{I18n.t('camaleon_cms.admin.post.message.requires_different_slug')}: #{record.slug} "
27
+ end
29
28
  end
30
29
 
31
30
  # avoid recursive page parent
@@ -3,9 +3,15 @@ module CamaleonCms
3
3
  def validate(record)
4
4
  return if record.skip_slug_validation?
5
5
 
6
- if CamaleonCms::TermTaxonomy.where(slug: record.slug).where.not(id: record.id).where("#{CamaleonCms::TermTaxonomy.table_name}.taxonomy" => record.taxonomy).where("#{CamaleonCms::TermTaxonomy.table_name}.parent_id" => record.parent_id).size.positive?
7
- record.errors[:base] << I18n.t('camaleon_cms.admin.post.message.requires_different_slug').to_s
8
- end
6
+ taxonomy_table = CamaleonCms::TermTaxonomy.table_name
7
+ slug_exists = CamaleonCms::TermTaxonomy.where(slug: record.slug)
8
+ .where.not(id: record.id)
9
+ .where("#{taxonomy_table}.taxonomy" => record.taxonomy)
10
+ .where("#{taxonomy_table}.parent_id" => record.parent_id).exists?
11
+
12
+ return unless slug_exists
13
+
14
+ record.errors[:base] << I18n.t('camaleon_cms.admin.post.message.requires_different_slug').to_s
9
15
  end
10
16
  end
11
17
  end
@@ -48,7 +48,7 @@
48
48
  <fieldset>
49
49
  <legend><%= t("camaleon_cms.admin.media.external", default: 'From URL') %></legend>
50
50
  <div class="form-group">
51
- <input type="text" name="remote_file" class="form-control" placeholder="http://..." class="required">
51
+ <input type="text" name="remote_file" class="form-control" placeholder="https://..." class="required">
52
52
  </div>
53
53
  <div class="form-group">
54
54
  <button type="submit" class="btn btn-primary"><%= t("camaleon_cms.admin.button.submit") %></button>
@@ -10,7 +10,7 @@
10
10
  <hr>
11
11
  <div class="alert alert-info">Gmail Need Permissions:
12
12
  <div class="pull-left">
13
- <a href="http://know.mailsbestfriend.com/smtp_error_password_command_failed_5345714-1194946499.shtml" target="_blank">Check
13
+ <a href="https://know.mailsbestfriend.com/smtp_error_password_command_failed_5345714-1194946499.shtml" target="_blank">Check
14
14
  here.</a>
15
15
  </div>
16
16
  <div class="pull-right">
@@ -55,4 +55,4 @@
55
55
  return false;
56
56
  });
57
57
  });
58
- </script>
58
+ </script>
@@ -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
@@ -12,19 +12,19 @@
12
12
  <!-- Wrapper for slides -->
13
13
  <div class="carousel-inner">
14
14
  <div class="item active">
15
- <img src="http://placehold.it/800x400" alt="...">
15
+ <img src="https://placehold.it/800x400" alt="...">
16
16
  <div class="carousel-caption">
17
17
  <h2>Heading</h2>
18
18
  </div>
19
19
  </div>
20
20
  <div class="item">
21
- <img src="http://placehold.it/800x400" alt="...">
21
+ <img src="https://placehold.it/800x400" alt="...">
22
22
  <div class="carousel-caption">
23
23
  <h2>Heading</h2>
24
24
  </div>
25
25
  </div>
26
26
  <div class="item">
27
- <img src="http://placehold.it/800x400" alt="...">
27
+ <img src="https://placehold.it/800x400" alt="...">
28
28
  <div class="carousel-caption">
29
29
  <h2>Heading</h2>
30
30
  </div>
@@ -67,4 +67,4 @@
67
67
  </div>
68
68
 
69
69
  </div>
70
- </section>
70
+ </section>
@@ -1,7 +1,7 @@
1
1
  xml.instruct! :xml, version: '1.0'
2
- xml.urlset 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9' do
2
+ xml.urlset 'xmlns' => 'https://www.sitemaps.org/schemas/sitemap/0.9' do
3
3
  current_site.get_languages.each_with_index do |lang, index|
4
- lang = (index.zero? ? nil : lang)
4
+ lang = (index == 0 ? nil : lang)
5
5
  xml.url do
6
6
  xml.loc current_site.the_url(locale: lang)
7
7
  xml.lastmod current_site.updated_at.to_date
@@ -54,7 +54,7 @@ xml.urlset 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9' do
54
54
  end
55
55
  end
56
56
 
57
- @r[:custom].each do |_key, item|
57
+ @r[:custom].each_value do |item|
58
58
  xml.url do
59
59
  xml.loc item[:url]
60
60
  xml.lastmod item[:lastmod] || Date.today.to_s
@@ -1,6 +1,6 @@
1
1
  <footer class="main-footer" id="main-footer">
2
2
  <div class="row">
3
- <div class="col-md-6"><strong>Copyright &copy; 2015 - <%= Time.now.year %> <a href="http://camaleon.tuzitio.com">Camaleon CMS.</a> </strong></div>
3
+ <div class="col-md-6"><strong>Copyright &copy; 2015 - <%= Time.now.year %> <a href="https://camaleon.website">Camaleon CMS.</a> </strong></div>
4
4
  <div class="col-md-6 hidden-xs">
5
5
  <div class="pull-left">
6
6
  <a id="link_see_intro" href="#" onclick="init_intro(); return false;"><i class="fa fa-tv"></i> <%= I18n.t('camaleon_cms.see_intro') %>.</a>
@@ -9,4 +9,18 @@ Rails.application.config.to_prepare do |_config|
9
9
  f = File.join(ap['path'], 'config', 'custom_models.rb')
10
10
  eval(File.read(f)) if File.exist?(f)
11
11
  end
12
+
13
+ # This block can be overridden in the app initializer to wrap the sleep and delete_file in an async job,
14
+ # something like this:
15
+ #
16
+ # CamaleonDeleteFileJob.set(wait: temporal_time).perform_later(file_key)
17
+ # # put this in app/jobs/camaleon_delete_file_job.rb:
18
+ # include CamaleonCms::UploaderHelper
19
+ # cama_uploader.delete_file(file_key)
20
+ CamaleonCmsUploader.delete_block do |settings, cama_uploader, file_key|
21
+ next unless Rails.env.test?
22
+
23
+ sleep(settings[:temporal_time])
24
+ cama_uploader.delete_file(file_key)
25
+ end
12
26
  end
@@ -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
 
@@ -59,7 +59,7 @@ module CamaleonCms
59
59
  app.config.assets.paths << File.join($camaleon_engine_dir, 'app', 'assets', 'fonts')
60
60
  app.config.encoding = 'utf-8'
61
61
 
62
- # add prefix url, like: http://localhost.com/blog/
62
+ # add prefix url, like: https://localhost.com/blog/
63
63
  # config.action_controller.relative_url_root = PluginRoutes.system_info["relative_url_root"] if PluginRoutes.system_info["relative_url_root"].present?
64
64
 
65
65
  # multiple route files
@@ -1,3 +1,3 @@
1
1
  module CamaleonCms
2
- VERSION = '2.7.5'.freeze
2
+ VERSION = '2.8.1'.freeze
3
3
  end
data/lib/ext/hash.rb CHANGED
@@ -19,7 +19,7 @@ class Hash
19
19
 
20
20
  # used for hash of objects
21
21
  def find_by(val, attr = 'id')
22
- each do |_key, p|
22
+ each_value do |p|
23
23
  return p if p[attr].to_s == val.to_s
24
24
  end
25
25
  nil
data/lib/ext/string.rb CHANGED
@@ -66,11 +66,11 @@ class String
66
66
  end
67
67
 
68
68
  # parse string into domain
69
- # http://owem.tuzitio.com into owem.tuzitio.com
69
+ # https://owen.camaleon.website into owen.camaleon.website
70
70
  def parse_domain
71
71
  url = self
72
72
  uri = URI.parse(url)
73
- uri = URI.parse("http://#{url}") if uri.scheme.nil?
73
+ uri = URI.parse("https://#{url}") if uri.scheme.nil?
74
74
  host = (uri.host || self).downcase
75
75
  h = host.start_with?('www.') ? host[4..] : host
76
76
  "#{h}#{":#{uri.port}" unless [80, 443].include?(uri.port)}"
@@ -10,5 +10,5 @@
10
10
  // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
11
  // about supported directives.
12
12
  //
13
- //= require jquery.js
13
+ //= require jquery2
14
14
  //= require camaleon_cms/bootstrap.min.js