camaleon_cms 2.9.1 → 2.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -5
  3. data/app/apps/plugins/front_cache/admin_controller.rb +1 -0
  4. data/app/apps/plugins/front_cache/front_cache_helper.rb +23 -14
  5. data/app/apps/plugins/visibility_post/visibility_post_helper.rb +1 -1
  6. data/app/apps/themes/default/views/category.html.erb +1 -1
  7. data/app/apps/themes/default/views/post_tag.html.erb +1 -1
  8. data/app/apps/themes/default/views/post_type.html.erb +1 -1
  9. data/app/apps/themes/default/views/search.html.erb +1 -1
  10. data/app/apps/themes/new/views/category.html.erb +1 -1
  11. data/app/apps/themes/new/views/post_tag.html.erb +1 -1
  12. data/app/apps/themes/new/views/post_type.html.erb +1 -1
  13. data/app/apps/themes/new/views/search.html.erb +1 -1
  14. data/app/controllers/camaleon_cms/admin/appearances/nav_menus_controller.rb +22 -5
  15. data/app/controllers/camaleon_cms/admin/appearances/widgets/assign_controller.rb +4 -2
  16. data/app/controllers/camaleon_cms/admin/appearances/widgets/main_controller.rb +3 -3
  17. data/app/controllers/camaleon_cms/admin/appearances/widgets/sidebar_controller.rb +2 -2
  18. data/app/controllers/camaleon_cms/admin/categories_controller.rb +9 -5
  19. data/app/controllers/camaleon_cms/admin/media_controller.rb +18 -5
  20. data/app/controllers/camaleon_cms/admin/post_tags_controller.rb +7 -4
  21. data/app/controllers/camaleon_cms/admin/posts/drafts_controller.rb +1 -1
  22. data/app/controllers/camaleon_cms/admin/posts_controller.rb +6 -3
  23. data/app/controllers/camaleon_cms/admin/sessions_controller.rb +2 -2
  24. data/app/controllers/camaleon_cms/admin/settings/custom_fields_controller.rb +33 -11
  25. data/app/controllers/camaleon_cms/admin/settings/post_types_controller.rb +13 -4
  26. data/app/controllers/camaleon_cms/admin/settings/sites_controller.rb +7 -4
  27. data/app/controllers/camaleon_cms/admin/settings_controller.rb +7 -4
  28. data/app/controllers/camaleon_cms/admin/user_roles_controller.rb +2 -2
  29. data/app/controllers/camaleon_cms/admin/users_controller.rb +16 -12
  30. data/app/controllers/camaleon_cms/admin_controller.rb +8 -0
  31. data/app/controllers/camaleon_cms/apps/plugins_admin_controller.rb +5 -0
  32. data/app/controllers/concerns/camaleon_cms/admin/custom_fields_concern.rb +29 -0
  33. data/app/decorators/camaleon_cms/post_decorator.rb +1 -1
  34. data/app/decorators/camaleon_cms/user_decorator.rb +1 -1
  35. data/app/helpers/camaleon_cms/admin/application_helper.rb +17 -17
  36. data/app/helpers/camaleon_cms/admin/post_type_helper.rb +25 -22
  37. data/app/helpers/camaleon_cms/comment_helper.rb +74 -40
  38. data/app/helpers/camaleon_cms/frontend/content_select_helper.rb +1 -1
  39. data/app/helpers/camaleon_cms/frontend/nav_menu_helper.rb +1 -1
  40. data/app/helpers/camaleon_cms/html_helper.rb +15 -1
  41. data/app/helpers/camaleon_cms/session_helper.rb +13 -1
  42. data/app/helpers/camaleon_cms/site_helper.rb +16 -3
  43. data/app/helpers/camaleon_cms/uploader_helper.rb +102 -51
  44. data/app/models/camaleon_cms/ability.rb +54 -102
  45. data/app/models/camaleon_cms/category.rb +2 -0
  46. data/app/models/camaleon_cms/custom_field.rb +14 -0
  47. data/app/models/camaleon_cms/custom_field_group.rb +38 -1
  48. data/app/models/camaleon_cms/custom_fields_relationship.rb +1 -1
  49. data/app/models/camaleon_cms/nav_menu.rb +2 -0
  50. data/app/models/camaleon_cms/nav_menu_item.rb +2 -0
  51. data/app/models/camaleon_cms/plugin.rb +2 -0
  52. data/app/models/camaleon_cms/post_tag.rb +2 -0
  53. data/app/models/camaleon_cms/post_type.rb +2 -0
  54. data/app/models/camaleon_cms/site.rb +2 -0
  55. data/app/models/camaleon_cms/term_taxonomy.rb +0 -2
  56. data/app/models/camaleon_cms/theme.rb +2 -0
  57. data/app/models/camaleon_cms/user_role.rb +13 -0
  58. data/app/models/camaleon_cms/widget/main.rb +2 -0
  59. data/app/models/camaleon_cms/widget/sidebar.rb +2 -0
  60. data/app/models/camaleon_record.rb +34 -0
  61. data/app/models/concerns/camaleon_cms/custom_fields_read.rb +4 -4
  62. data/app/models/concerns/camaleon_cms/metas.rb +1 -1
  63. data/app/models/current_request.rb +16 -0
  64. data/app/uploaders/camaleon_cms_aws_uploader.rb +8 -1
  65. data/app/validators/camaleon_cms/post_uniq_validator.rb +16 -4
  66. data/app/views/camaleon_cms/admin/appearances/nav_menus/_left_menu_items.html.erb +2 -2
  67. data/app/views/camaleon_cms/admin/appearances/widgets/main/form.html.erb +1 -1
  68. data/app/views/camaleon_cms/admin/categories/index.html.erb +1 -1
  69. data/app/views/camaleon_cms/admin/comments/index.html.erb +2 -2
  70. data/app/views/camaleon_cms/admin/comments/list.html.erb +1 -1
  71. data/app/views/camaleon_cms/admin/post_tags/index.html.erb +1 -1
  72. data/app/views/camaleon_cms/admin/posts/_sidebar.html.erb +1 -1
  73. data/app/views/camaleon_cms/admin/posts/index.html.erb +3 -3
  74. data/app/views/camaleon_cms/admin/search.html.erb +1 -1
  75. data/app/views/camaleon_cms/admin/settings/custom_fields/_render.html.erb +23 -2
  76. data/app/views/camaleon_cms/admin/settings/custom_fields/fields/_select_eval.html.erb +1 -1
  77. data/app/views/camaleon_cms/admin/settings/custom_fields/form.html.erb +1 -1
  78. data/app/views/camaleon_cms/admin/settings/custom_fields/index.html.erb +1 -1
  79. data/app/views/camaleon_cms/admin/settings/post_types/index.html.erb +1 -1
  80. data/app/views/camaleon_cms/admin/settings/sites/index.html.erb +1 -1
  81. data/app/views/camaleon_cms/admin/user_roles/form.html.erb +79 -5
  82. data/app/views/camaleon_cms/admin/user_roles/index.html.erb +1 -1
  83. data/app/views/camaleon_cms/admin/users/index.html.erb +1 -1
  84. data/app/views/layouts/camaleon_cms/admin/_flash_messages.html.erb +2 -2
  85. data/config/initializers/custom_initializers.rb +2 -2
  86. data/config/locales/camaleon_cms/admin/ar.yml +6 -2
  87. data/config/locales/camaleon_cms/admin/de.yml +6 -2
  88. data/config/locales/camaleon_cms/admin/en.yml +6 -2
  89. data/config/locales/camaleon_cms/admin/es.yml +6 -2
  90. data/config/locales/camaleon_cms/admin/fr.yml +6 -2
  91. data/config/locales/camaleon_cms/admin/it.yml +6 -2
  92. data/config/locales/camaleon_cms/admin/nl.yml +7 -2
  93. data/config/locales/camaleon_cms/admin/pt-BR.yml +6 -2
  94. data/config/locales/camaleon_cms/admin/pt.yml +6 -2
  95. data/config/locales/camaleon_cms/admin/ru.yml +6 -2
  96. data/config/locales/camaleon_cms/admin/uk.yml +6 -2
  97. data/config/locales/camaleon_cms/admin/zh-CH.yml +6 -2
  98. data/db/migrate/20150611161134_post_table_into_utf8.rb +14 -14
  99. data/db/migrate/20150926095310_rename_column_posts.rb +3 -3
  100. data/db/migrate/20151212095328_add_confirm_token_to_users.rb +3 -3
  101. data/db/migrate/20160504155652_add_feature_to_posts.rb +1 -1
  102. data/db/migrate/20160504155653_move_first_name_of_users.rb +2 -2
  103. data/db/migrate/20160609121449_add_group_to_custom_field_values.rb +1 -1
  104. data/db/migrate/20161215202255_drop_user_relationship_table.rb +1 -1
  105. data/db/migrate/20180124132318_create_media.rb +1 -1
  106. data/db/migrate/20180704211100_adjust_field_length.rb +1 -1
  107. data/lib/camaleon_cms/version.rb +1 -1
  108. data/lib/ext/string.rb +3 -3
  109. data/lib/plugin_routes.rb +3 -3
  110. data/lib/tasks/custom_fields_roles.rake +56 -0
  111. metadata +64 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6aace403e18b38c945faca659af2196ed66f130ed61e7b5454626137c59331ce
4
- data.tar.gz: f104182791714153a963e03ccc23dec4720cd9e7528ab378b0facf33e351e2b4
3
+ metadata.gz: 7fc3c9c70942e53b927d67366df21d19a549e0a349e8e87ca08f12977c3c5b08
4
+ data.tar.gz: d0b3948628d2c7c5d5efa55e6bc6c2ef1b90413d2a53764ac85ed281eceab630
5
5
  SHA512:
6
- metadata.gz: 28708ab09b20a2a0c78ae3f104e2a38c5560725596bc9e70e935fb3384230f0ef006523d9f56db6e3c4ee5238a066ca6e1d6ea31e710623c8b9c9b8777380fb2
7
- data.tar.gz: c7fe66386eb9b15fd988afc2ad366a1ffd16d82f923219c10b61e590e5eda7f27b66413da745cb9eca8c736284500f35d9bbd41f6c39dd99828164ba8c308544
6
+ metadata.gz: f6795ac94a6097bafa86c8336f209cb395f2b102db44da96d091ad55b5373bb6a1ed5af876f6facb72ba313d6fa803201d0605e2e55b0f699304dab2df470c6b
7
+ data.tar.gz: 6045503558fb4aa769b6d3bbd8dfac05357c9e6427134ed2670b3dc08aae94df7b865d69a80f6bdbe950492a439d79345b1f57b94808fbeb78f6acb5868ec90e
data/README.md CHANGED
@@ -173,15 +173,22 @@ Owen Peredo Diaz
173
173
  https://camaleon.website/license.html
174
174
 
175
175
  ## Testing
176
- * Init DB
176
+ > **Note:** Since this project is a gem, Rails commands (e.g., `rails routes`, `zeitwerk:check`) MUST be run from the `spec/dummy` folder. Use subshells to ensure you return to root: `(cd spec/dummy && bin/rails ...)`
177
+
178
+ - Init DB
179
+
177
180
  ```bash
178
181
  RAILS_ENV=test bundle exec rake app:db:migrate
179
182
  RAILS_ENV=test bundle exec rake app:db:test:prepare
180
183
  ```
181
- * Run tests
182
- ```bash
183
- bundle exec rspec
184
- ```
184
+
185
+ - Run the tests: `bin/rspec`
186
+ - If the `rspec` binstub is not present, generate it: `bundle binstubs rspec-core`
187
+ - And then still run `bin/rspec`
188
+
189
+ ## Permissions (Manager roles)
190
+
191
+ See [docs/security/permissions.md](docs/security/permissions.md) for details on manager permissions, custom fields, and security considerations.
185
192
 
186
193
  ## Contributing
187
194
  * Fork it.
@@ -2,6 +2,7 @@ module Plugins
2
2
  module FrontCache
3
3
  class AdminController < CamaleonCms::Apps::PluginsAdminController
4
4
  include Plugins::FrontCache::FrontCacheHelper
5
+
5
6
  def settings
6
7
  @caches = current_site.get_meta('front_cache_elements', { paths: [] })
7
8
  @caches[:paths] << '' unless @caches[:paths].present?
@@ -1,14 +1,14 @@
1
1
  module Plugins
2
2
  module FrontCache
3
3
  module FrontCacheHelper
4
- # save as cache all pages configured on settings of this plugin for public users
4
+ # cache all pages configured in this plugin's settings for public users
5
5
  def front_cache_front_before_load
6
6
  if current_site.get_option('refresh_cache') # clear cache every restart server unless option checked in settings
7
7
  front_cache_clean unless current_site.get_meta('front_cache_elements')[:preserve_cache_on_restart]
8
8
  current_site.set_option('refresh_cache', false)
9
9
  end
10
10
 
11
- # avoid cache if current visitor is logged in or development
11
+ # avoid cache if the current visitor is logged in, or we're in the development or test environment
12
12
  return if signin? || Rails.env.development? || Rails.env.test? || !request.get?
13
13
 
14
14
  cache_key = front_cache_plugin_cache_key
@@ -45,9 +45,13 @@ module Plugins
45
45
  cache_key = front_cache_plugin_cache_key
46
46
  return unless @_plugin_do_cache && !flash.keys.present?
47
47
 
48
- args = { data: response.body
49
- .gsub(/csrf-token" content="(.*?)"/, 'csrf-token" content="{{form_authenticity_token}}"')
50
- .gsub(/name="authenticity_token" value="(.*?)"/, 'name="authenticity_token" value="{{form_authenticity_token}}"') }
48
+ body =
49
+ response
50
+ .body.gsub(/csrf-token" content="(.*?)"/, 'csrf-token" content="{{form_authenticity_token}}"')
51
+ .gsub(
52
+ /name="authenticity_token" value="(.*?)"/, 'name="authenticity_token" value="{{form_authenticity_token}}"'
53
+ )
54
+ args = { data: body }
51
55
  hooks_run('front_cache_writing_cache', args)
52
56
  front_cache_plugin_cache_create(cache_key, args[:data])
53
57
  Rails.logger.info "Camaleon CMS - cache saved as: #{front_cache_plugin_get_path(cache_key)}"
@@ -57,22 +61,27 @@ module Plugins
57
61
  def front_cache_on_active(_plugin)
58
62
  return if current_site.get_meta('front_cache_elements', nil).present?
59
63
 
60
- current_site.set_meta('front_cache_elements', { paths: [],
61
- posts: [],
62
- post_types: [current_site.post_types.where(slug: 'page').first.id],
63
- skip_posts: [],
64
- home: true,
65
- cache_login: true,
66
- cache_counter: 0 })
64
+ current_site.set_meta(
65
+ 'front_cache_elements',
66
+ {
67
+ paths: [],
68
+ posts: [],
69
+ post_types: [current_site.post_types.where(slug: 'page').first.id],
70
+ skip_posts: [],
71
+ home: true,
72
+ cache_login: true,
73
+ cache_counter: 0
74
+ }
75
+ )
67
76
  end
68
77
 
69
78
  # on uninstall plugin
70
- def front_cache_on_inactive(plugin)
79
+ def front_cache_on_inactive(_plugin)
71
80
  # current_site.delete_meta("front_cache_elements")
72
81
  end
73
82
 
74
83
  # cache actions (for logged users)
75
- def front_cache_on_render(args); end
84
+ def front_cache_on_render(_args); end
76
85
 
77
86
  # expire cache for a page after comment registered or updated
78
87
  def front_cache_before_load; end
@@ -57,7 +57,7 @@ module Plugins
57
57
  if ActiveRecord::Base.connection.adapter_name.downcase.include?('mysql')
58
58
  args[:active_record].where("visibility != 'private' or (visibility = 'private' and FIND_IN_SET(?, #{CamaleonCms::Post.table_name}.visibility_value))", current_site.visitor_role)
59
59
  else
60
- args[:active_record].where("visibility != 'private' or (visibility = 'private' and (',' || #{CamaleonCms::Post.table_name}.visibility_value || ',') LIKE '%,#{current_site.visitor_role},%')")
60
+ args[:active_record].where("visibility != 'private' or (visibility = 'private' and (',' || #{CamaleonCms::Post.table_name}.visibility_value || ',') LIKE ?)", "%,#{current_site.visitor_role},%")
61
61
  end
62
62
  else
63
63
  args[:active_record].where("visibility != 'private'")
@@ -8,7 +8,7 @@
8
8
  <% end %>
9
9
  </div>
10
10
  <%= content_tag("div", raw(ct('no_contents_found', default: 'No contents found')), class: "alert alert-warning") if @posts.empty? %>
11
- <%= raw cama_do_pagination(@posts) %>
11
+ <%= cama_do_pagination(@posts) %>
12
12
  </div>
13
13
  </div>
14
14
  </article>
@@ -8,7 +8,7 @@
8
8
  <% end %>
9
9
  </div>
10
10
  <%= content_tag("div", raw(ct('no_contents_found', default: 'No contents found')), class: "alert alert-warning") if @posts.empty? %>
11
- <%= raw cama_do_pagination(@posts) %>
11
+ <%= cama_do_pagination(@posts) %>
12
12
  </div>
13
13
  </div>
14
14
  </article>
@@ -24,7 +24,7 @@
24
24
  <% end %>
25
25
  </div>
26
26
  <%= content_tag("div", raw(ct('no_contents_found', default: 'No contents found')), class: "alert alert-warning") if @posts.empty? %>
27
- <%= raw cama_do_pagination(@posts) %>
27
+ <%= cama_do_pagination(@posts) %>
28
28
  </div>
29
29
  </div>
30
30
 
@@ -11,7 +11,7 @@
11
11
  <% end %>
12
12
  </div>
13
13
  <%= content_tag("div", raw(ct('no_contents_found', default: 'No contents found')), class: "alert alert-warning") if @posts.empty? %>
14
- <%= raw cama_do_pagination(@posts) %>
14
+ <%= cama_do_pagination(@posts) %>
15
15
  </div>
16
16
  </div>
17
17
  </article>
@@ -24,7 +24,7 @@
24
24
  <% end %>
25
25
  </div>
26
26
  <%= content_tag("div", raw(ct('no_contents_found', default: 'No contents found')), class: "alert alert-warning") if @posts.empty? %>
27
- <%= raw cama_do_pagination(@posts) %>
27
+ <%= cama_do_pagination(@posts) %>
28
28
  </div>
29
29
  </div>
30
30
 
@@ -15,7 +15,7 @@
15
15
  <% end %>
16
16
  </div>
17
17
  <%= content_tag("div", raw(ct('no_contents_found', default: 'No contents found')), class: "alert alert-warning") if @posts.empty? %>
18
- <%= raw cama_do_pagination(@posts) %>
18
+ <%= cama_do_pagination(@posts) %>
19
19
  </div>
20
20
  </div>
21
21
 
@@ -24,7 +24,7 @@
24
24
  <% end %>
25
25
  </div>
26
26
  <%= content_tag("div", raw(ct('no_contents_found', default: 'No contents found')), class: "alert alert-warning") if @posts.empty? %>
27
- <%= raw cama_do_pagination(@posts) %>
27
+ <%= cama_do_pagination(@posts) %>
28
28
  </div>
29
29
  </div>
30
30
 
@@ -12,7 +12,7 @@
12
12
  <% end %>
13
13
  </div>
14
14
  <%= content_tag("div", raw(ct('no_contents_found', default: 'No contents found')), class: "alert alert-warning") if @posts.empty? %>
15
- <%= raw cama_do_pagination(@posts) %>
15
+ <%= cama_do_pagination(@posts) %>
16
16
  </div>
17
17
  </div>
18
18
  </article>
@@ -2,6 +2,7 @@ module CamaleonCms
2
2
  module Admin
3
3
  module Appearances
4
4
  class NavMenusController < CamaleonCms::AdminController
5
+ include CamaleonCms::Admin::CustomFieldsConcern
5
6
  include CamaleonCms::Frontend::NavMenuHelper
6
7
 
7
8
  add_breadcrumb I18n.t('camaleon_cms.admin.sidebar.appearance')
@@ -27,7 +28,7 @@ module CamaleonCms
27
28
  end
28
29
 
29
30
  def create
30
- nav_menu = current_site.nav_menus.new(params.require(:nav_menu).permit!)
31
+ nav_menu = current_site.nav_menus.new(nav_menu_params)
31
32
  nav_menu.save
32
33
  flash[:notice] = t('.created_menu', default: 'Created Menu')
33
34
  redirect_to action: :index, id: nav_menu.id
@@ -35,7 +36,7 @@ module CamaleonCms
35
36
 
36
37
  def update
37
38
  nav_menu = current_site.nav_menus.find(params[:id])
38
- nav_menu.update(params.require(:nav_menu).permit!)
39
+ nav_menu.update(nav_menu_params)
39
40
  flash[:notice] = t('.updated_menu', default: 'Menu updated')
40
41
  redirect_to action: :index, id: nav_menu.id
41
42
  end
@@ -59,7 +60,7 @@ module CamaleonCms
59
60
 
60
61
  def save_custom_settings
61
62
  @nav_menu_item = current_site.nav_menu_items.find(params[:id])
62
- @nav_menu_item.set_field_values(params.require(:field_options).permit!)
63
+ @nav_menu_item.set_field_values(cama_permitted_field_options('NavMenuItem'))
63
64
  head :ok
64
65
  end
65
66
 
@@ -77,7 +78,7 @@ module CamaleonCms
77
78
  @nav_menu = current_site.nav_menus.find(params[:nav_menu_id])
78
79
  item = current_site.nav_menu_items.find(params[:id])
79
80
  item.update_menu_item(parse_external_menu(params))
80
- item.set_options(params.require(:options).permit!) if params[:options].present?
81
+ item.set_options(permitted_external_options) if params[:options].present?
81
82
  render partial: 'menu_items', locals: { items: [item], nav_menu: @nav_menu }
82
83
  end
83
84
 
@@ -106,7 +107,7 @@ module CamaleonCms
106
107
  external_params = params[:external]
107
108
  if external_params.present?
108
109
  external_item = @nav_menu.append_menu_item(parse_external_menu(external_params))
109
- external_item.set_options(external_params.require(:options).permit!) if external_params[:options].present?
110
+ external_item.set_options(permitted_external_options(external_params)) if external_params[:options].present?
110
111
  items << external_item
111
112
  end
112
113
 
@@ -136,6 +137,22 @@ module CamaleonCms
136
137
  def parse_external_menu(_params)
137
138
  { label: _params[:external_label], link: _params[:external_url], type: 'external', target: _params[:target] }
138
139
  end
140
+
141
+ # Strong parameters for nav_menu
142
+ def nav_menu_params
143
+ params.require(:nav_menu).permit(:name, :slug)
144
+ end
145
+
146
+ # Only permit external menu options that match registered custom field slug
147
+ def permitted_external_options(external_params = nil)
148
+ opts = external_params ? external_params[:options] : params[:options]
149
+ return {} unless opts.present?
150
+
151
+ allowed_keys = cama_custom_field_allowed_slugs('NavMenuItem')
152
+ return {} if allowed_keys.blank?
153
+
154
+ opts.permit(*allowed_keys).to_h
155
+ end
139
156
  end
140
157
  end
141
158
  end
@@ -3,6 +3,8 @@ module CamaleonCms
3
3
  module Appearances
4
4
  module Widgets
5
5
  class AssignController < CamaleonCms::AdminController
6
+ include CamaleonCms::Admin::CustomFieldsConcern
7
+
6
8
  before_action :check_permission_role
7
9
  before_action :find_sidebar
8
10
  before_action :find_assigned_sidebar, only: %i[update destroy]
@@ -15,8 +17,8 @@ module CamaleonCms
15
17
  end
16
18
 
17
19
  def update
18
- if @assigned.update(params.require(:assign).permit!)
19
- @assigned.set_field_values(params[:field_options])
20
+ if @assigned.update(params.require(:assign).permit(:title, :content, :widget_id, :sidebar_id, :item_order))
21
+ @assigned.set_field_values(cama_permitted_field_options('Widget::Main'))
20
22
  flash[:notice] = t('camaleon_cms.admin.widgets.assign.updated')
21
23
  else
22
24
  flash[:error] = t('camaleon_cms.admin.widgets.assign.error_updated')
@@ -22,8 +22,8 @@ module CamaleonCms
22
22
  end
23
23
 
24
24
  def create
25
- params[:widget_main][:status] = 'simple'
26
- @widget = current_site.widgets.new(params.require(:widget_main).permit!)
25
+ @widget = current_site.widgets.new(params.require(:widget_main).permit(:name, :slug, :description, :excerpt, :renderer))
26
+ @widget.status = 'simple'
27
27
  if @widget.save!
28
28
  flash[:notice] = t('camaleon_cms.admin.widgets.message.created')
29
29
  else
@@ -33,7 +33,7 @@ module CamaleonCms
33
33
  end
34
34
 
35
35
  def update
36
- if @widget.update!(params.require(:widget_main).permit!)
36
+ if @widget.update!(params.require(:widget_main).permit(:name, :slug, :description, :excerpt, :renderer))
37
37
  flash[:notice] = t('camaleon_cms.admin.widgets.message.updated')
38
38
  else
39
39
  flash[:error] = t('camaleon_cms.admin.widgets.message.error_updated')
@@ -12,7 +12,7 @@ module CamaleonCms
12
12
  end
13
13
 
14
14
  def create
15
- @sidebar = current_site.sidebars.new(params.require(:widget_sidebar).permit!)
15
+ @sidebar = current_site.sidebars.new(params.require(:widget_sidebar).permit(:name, :slug, :description))
16
16
  if @sidebar.save
17
17
  flash[:notice] = t('camaleon_cms.admin.widgets.sidebar.created')
18
18
  else
@@ -26,7 +26,7 @@ module CamaleonCms
26
26
  end
27
27
 
28
28
  def update
29
- if @sidebar.update(params.require(:widget_sidebar).permit!)
29
+ if @sidebar.update(params.require(:widget_sidebar).permit(:name, :slug, :description))
30
30
  flash[:notice] = t('camaleon_cms.admin.widgets.sidebar.updated')
31
31
  else
32
32
  flash[:error] = t('camaleon_cms.admin.widgets.sidebar.error_updated')
@@ -1,7 +1,10 @@
1
1
  module CamaleonCms
2
2
  module Admin
3
3
  class CategoriesController < CamaleonCms::AdminController
4
+ include CamaleonCms::Admin::CustomFieldsConcern
5
+
4
6
  add_breadcrumb I18n.t('camaleon_cms.admin.sidebar.contents')
7
+
5
8
  before_action :set_post_type
6
9
  before_action :set_category, only: %w[show edit update destroy]
7
10
 
@@ -20,9 +23,9 @@ module CamaleonCms
20
23
  def update
21
24
  hooks_run('update_category', { category: @category, post_type: @post_type })
22
25
 
23
- if @category.update(params.require(:category).permit!)
26
+ if @category.update(params.require(:category).permit(:name, :slug, :description, :parent_id))
24
27
  @category.set_options(params[:meta])
25
- @category.set_field_values(params[:field_options])
28
+ @category.set_field_values(cama_permitted_field_options('PostType_Category'))
26
29
  hooks_run('updated_category', { category: @category, post_type: @post_type })
27
30
  flash[:notice] = t('camaleon_cms.admin.post_type.message.updated')
28
31
  redirect_to action: :index
@@ -32,12 +35,12 @@ module CamaleonCms
32
35
  end
33
36
 
34
37
  def create
35
- @category = @post_type.categories.new(params.require(:category).permit!)
38
+ @category = @post_type.categories.new(params.require(:category).permit(:name, :slug, :description, :parent_id))
36
39
  hooks_run('create_category', { category: @category, post_type: @post_type })
37
40
 
38
41
  if @category.save
39
42
  @category.set_options(params[:meta])
40
- @category.set_field_values(params[:field_options])
43
+ @category.set_field_values(cama_permitted_field_options('PostType_Category'))
41
44
  hooks_run('created_category', { category: @category, post_type: @post_type })
42
45
  flash[:notice] = t('camaleon_cms.admin.post_type.message.created')
43
46
  redirect_to action: :index
@@ -73,7 +76,8 @@ module CamaleonCms
73
76
  end
74
77
 
75
78
  def set_category
76
- @category = CamaleonCms::Category.find_by_id(params[:id])
79
+ @category = @post_type.categories.find_by_id(params[:id])
80
+ render_404 unless @category
77
81
  rescue StandardError
78
82
  flash[:error] = t('camaleon_cms.admin.post_type.message.error')
79
83
  redirect_to cama_admin_path
@@ -5,10 +5,10 @@ module CamaleonCms
5
5
  skip_before_action :admin_logged_actions, except: %i[index download_private_file], raise: false
6
6
  skip_before_action :verify_authenticity_token, only: :upload, raise: false
7
7
  before_action :init_media_vars, except: :download_private_file
8
+ before_action :verify_media_authorization
8
9
 
9
10
  # render media section
10
11
  def index
11
- authorize! :manage, :media
12
12
  @show_file_actions = true
13
13
  @files = @tree.paginate(page: params[:page], per_page: 100)
14
14
  @next_page = @files.current_page < @files.total_pages ? @files.current_page + 1 : nil
@@ -28,11 +28,14 @@ module CamaleonCms
28
28
  def download_private_file
29
29
  cama_uploader.enable_private_mode!
30
30
 
31
- file = cama_uploader.fetch_file("private/#{params[:file]}")
31
+ sanitize_private_filename!
32
+ return render(plain: 'Invalid file', status: :forbidden) unless @private_file_path
33
+
34
+ fetched = cama_uploader.fetch_file(@private_file_path)
32
35
 
33
- return render plain: helpers.sanitize(file[:error]) if file.is_a?(Hash) && file[:error].present?
36
+ return render plain: helpers.sanitize(fetched[:error]) if fetched.is_a?(Hash) && fetched[:error].present?
34
37
 
35
- send_file file, disposition: 'inline'
38
+ send_file fetched, disposition: 'inline'
36
39
  end
37
40
 
38
41
  # render media for modal content
@@ -51,7 +54,6 @@ module CamaleonCms
51
54
 
52
55
  # do background actions in fog
53
56
  def actions
54
- authorize! :manage, :media if params[:media_action] != 'crop_url'
55
57
  params[:folder] = params[:folder].gsub('//', '/') if params[:folder].present?
56
58
 
57
59
  case params[:media_action]
@@ -105,6 +107,17 @@ module CamaleonCms
105
107
 
106
108
  private
107
109
 
110
+ def verify_media_authorization
111
+ authorize! :manage, :media
112
+ end
113
+
114
+ # Sanitizes the private file parameter to prevent path traversal.
115
+ # Sets @private_file_path if valid, nil otherwise.
116
+ def sanitize_private_filename!
117
+ name = File.basename(params[:file].to_s)
118
+ @private_file_path = ("private/#{name}" if name.present? && name == params[:file].to_s)
119
+ end
120
+
108
121
  # init basic media variables
109
122
  def init_media_vars
110
123
  # @cama_uploader = CamaleonCmsLocalUploader.new({current_site: current_site, private: true})
@@ -1,7 +1,10 @@
1
1
  module CamaleonCms
2
2
  module Admin
3
3
  class PostTagsController < CamaleonCms::AdminController
4
+ include CamaleonCms::Admin::CustomFieldsConcern
5
+
4
6
  add_breadcrumb I18n.t('camaleon_cms.admin.sidebar.contents')
7
+
5
8
  before_action :set_post_type
6
9
  before_action :set_post_tag, only: %w[show edit update destroy]
7
10
 
@@ -27,9 +30,9 @@ module CamaleonCms
27
30
  def update
28
31
  args = { post_tag: @post_tag, post_type: @post_type }
29
32
  hooks_run('before_update_post_tag', args)
30
- if @post_tag.update(params.require(:post_tag).permit!)
33
+ if @post_tag.update(params.require(:post_tag).permit(:name, :slug, :description, :parent_id))
31
34
  @post_tag.set_options(params[:meta]) if params[:meta].present?
32
- @post_tag.set_field_values(params[:field_options])
35
+ @post_tag.set_field_values(cama_permitted_field_options('PostType_PostTag'))
33
36
  hooks_run('after_update_post_tag', args)
34
37
  flash[:notice] = t('camaleon_cms.admin.post_type.message.updated')
35
38
  redirect_to action: :index
@@ -40,12 +43,12 @@ module CamaleonCms
40
43
 
41
44
  # render post tag create form
42
45
  def create
43
- @post_tag = @post_type.post_tags.new(params.require(:post_tag).permit!)
46
+ @post_tag = @post_type.post_tags.new(params.require(:post_tag).permit(:name, :slug, :description, :parent_id))
44
47
  args = { post_tag: @post_tag, post_type: @post_type }
45
48
  hooks_run('before_create_post_tag', args)
46
49
  if @post_tag.save
47
50
  @post_tag.set_options(params[:meta]) if params[:meta].present?
48
- @post_tag.set_field_values(params[:field_options])
51
+ @post_tag.set_field_values(cama_permitted_field_options('PostType_PostTag'))
49
52
  hooks_run('after_create_post_tag', args)
50
53
  flash[:notice] = t('camaleon_cms.admin.post_type.message.created')
51
54
  redirect_to action: :index
@@ -52,7 +52,7 @@ module CamaleonCms
52
52
  private
53
53
 
54
54
  def set_post_data_params
55
- post_data = params.require(:post).permit!
55
+ post_data = params.require(:post).permit(:title, :slug, :content, :excerpt, :status, :comment_status, :post_parent, :visibility, :visibility_value, :post_order, :published_at).to_h
56
56
  post_data.delete(:created_at) unless params[:post][:created_at].present?
57
57
  post_data.delete(:updated_at) unless params[:post][:updated_at].present?
58
58
  post_data[:status] = 'draft_child'
@@ -1,7 +1,10 @@
1
1
  module CamaleonCms
2
2
  module Admin
3
3
  class PostsController < CamaleonCms::AdminController
4
+ include CamaleonCms::Admin::CustomFieldsConcern
5
+
4
6
  add_breadcrumb I18n.t('camaleon_cms.admin.sidebar.contents')
7
+
5
8
  before_action :set_post_type, except: [:ajax]
6
9
  before_action :set_post, only: %w[show edit update destroy]
7
10
  skip_before_action :admin_logged_actions, only: %i[trash restore destroy ajax], raise: false
@@ -87,7 +90,7 @@ module CamaleonCms
87
90
  @post = r[:post]
88
91
  if @post.save
89
92
  @post.set_metas(params[:meta])
90
- @post.set_field_values(params[:field_options])
93
+ @post.set_field_values(cama_permitted_field_options('PostType_Post'))
91
94
  @post.set_options(params[:options])
92
95
  flash[:notice] = t('camaleon_cms.admin.post.message.created', post_type: @post_type.decorate.the_title)
93
96
  r = { post: @post, post_type: @post_type }
@@ -129,7 +132,7 @@ module CamaleonCms
129
132
  # delete drafts only on successful update operation
130
133
  @post.drafts.destroy_all if delete_drafts
131
134
  @post.set_metas(params[:meta])
132
- @post.set_field_values(params[:field_options])
135
+ @post.set_field_values(cama_permitted_field_options('PostType_Post'))
133
136
  @post.set_options(params[:options])
134
137
  hooks_run('updated_post', { post: @post, post_type: @post_type })
135
138
  flash[:notice] = t('camaleon_cms.admin.post.message.updated', post_type: @post_type.decorate.the_title)
@@ -213,7 +216,7 @@ module CamaleonCms
213
216
  # return common params data for posts
214
217
  # is_create: indicate if this info is for create a new post
215
218
  def get_post_data(is_create = false)
216
- post_data = params.require(:post).permit!
219
+ post_data = params.require(:post).permit(:title, :slug, :content, :excerpt, :status, :comment_status, :post_parent, :visibility, :visibility_value, :post_order, :published_at).to_h
217
220
  post_data[:user_id] = cama_current_user.id if is_create
218
221
  post_data[:status] = 'pending' if post_data[:status] == 'published' && cannot?(:publish_post, @post_type)
219
222
  post_data[:data_tags] = params[:tags].to_s
@@ -113,7 +113,7 @@ module CamaleonCms
113
113
  params[:user][:role] = PluginRoutes.system_info['default_user_role']
114
114
  params[:user][:is_valid_email] = false if current_site.need_validate_email?
115
115
  user_data = user_permit_data
116
- result = cama_register_user(user_data, params[:meta])
116
+ result = cama_register_user(user_data, nil)
117
117
  if result[:result] == false && result[:type] == :captcha_error
118
118
  @user.errors.add(:captcha, t('camaleon_cms.admin.users.message.error_captcha'))
119
119
  render 'register'
@@ -171,7 +171,7 @@ module CamaleonCms
171
171
  end
172
172
 
173
173
  def user_permit_data
174
- params.require(:user).permit!
174
+ params.require(:user).permit(:first_name, :last_name, :email, :username, :password, :password_confirmation, :is_valid_email)
175
175
  end
176
176
  end
177
177
  end
@@ -3,6 +3,8 @@ module CamaleonCms
3
3
  module Settings
4
4
  class CustomFieldsController < CamaleonCms::Admin::SettingsController
5
5
  add_breadcrumb I18n.t('camaleon_cms.admin.sidebar.custom_fields'), :cama_admin_settings_custom_fields_path
6
+
7
+ before_action :validate_role, only: %i[create update destroy]
6
8
  before_action :set_custom_field_group, only: %i[show edit update destroy]
7
9
  before_action :set_post_data, only: %i[create update]
8
10
 
@@ -66,15 +68,15 @@ module CamaleonCms
66
68
  end
67
69
 
68
70
  def list
69
- p = params.permit(:post_type, :post_id, categories: [])
70
- args = {}
71
- if p[:post_id].present?
72
- post = @current_site.the_post(p[:post_id].to_i)
73
- post.update_categories(p[:categories])
71
+ p = params.permit(:post_type, :post_id)
72
+ cat_ids = current_site.full_categories.where(id: params[:categories]).pluck(:id)
73
+ if p[:post_id].present? && (post = current_site.the_post(p[:post_id].to_i)).present?
74
+ post.update_categories(cat_ids)
75
+ args = {}
74
76
  else
75
77
  post = CamaleonCms::Post.new
76
- post.taxonomy_id = p[:post_type].to_i
77
- args[:cat_ids] = p[:categories]
78
+ post.taxonomy_id = current_site.the_post_type(p[:post_type].to_i)&.id
79
+ args = { cat_ids: cat_ids }
78
80
  end
79
81
  render partial: 'camaleon_cms/admin/settings/custom_fields/render',
80
82
  locals: { record: post, field_groups: post.get_field_groups(args),
@@ -84,11 +86,15 @@ module CamaleonCms
84
86
  private
85
87
 
86
88
  def set_post_data
87
- @post_data = params.require(:custom_field_group).permit!
88
- @post_data[:object_class], @post_data[:objectid] = @post_data.delete(:assign_group).split(',')
89
+ @post_data = params.require(:custom_field_group).permit(:name, :description, :assign_group, :caption)
90
+ @post_data[:object_class], @post_data[:objectid] = @post_data.delete(:assign_group).to_s.split(',')
89
91
  @caption = @post_data.delete(:caption)
90
92
  end
91
93
 
94
+ def validate_role
95
+ authorize! :manage, :custom_fields
96
+ end
97
+
92
98
  def set_custom_field_group
93
99
  @field_group = current_site.custom_field_groups.find(params[:id])
94
100
  rescue StandardError
@@ -96,10 +102,26 @@ module CamaleonCms
96
102
  redirect_to cama_admin_path
97
103
  end
98
104
 
105
+ def permitted_fields
106
+ return {} unless params[:fields].present?
107
+
108
+ params.require(:fields).permit(params[:fields].keys.index_with do
109
+ %i[id name slug description field_order]
110
+ end).to_h
111
+ end
112
+
113
+ def permitted_field_options
114
+ return {} unless params[:field_options].present?
115
+
116
+ params.require(:field_options).permit(params[:field_options].keys.index_with do
117
+ [:field_key, :multiple, :required, :translate, :default_value, :dimension, :width, :height, :class, :placeholder,
118
+ { default_values: [], multiple_options: %i[title value default] }]
119
+ end).to_h
120
+ end
121
+
99
122
  # return boolean: true if all fields were saved successfully
100
123
  def _save_fields(group)
101
- errors_saved, _all_fields = group.add_fields(params[:fields] ? params.require(:fields).permit! : {},
102
- params[:field_options] ? params.require(:field_options).permit! : {})
124
+ errors_saved, _all_fields = group.add_fields(permitted_fields, permitted_field_options)
103
125
  group.set_option('caption', @caption)
104
126
  if errors_saved.present?
105
127
  flash[:error] = "<b>#{t('camaleon_cms.errors_found_msg', default: 'Several errors were found, please check.')}</b><br>#{errors_saved.map do |field|