camaleon_cms 2.9.2 → 2.9.3
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.
- checksums.yaml +4 -4
- data/README.md +17 -4
- data/Rakefile +3 -16
- data/app/apps/plugins/attack/admin_controller.rb +9 -6
- data/app/apps/plugins/attack/attack_helper.rb +35 -25
- data/app/apps/plugins/authoring_post/authoring_post_helper.rb +23 -16
- data/app/apps/plugins/front_cache/admin_controller.rb +15 -10
- data/app/apps/plugins/front_cache/config/initializer.rb +1 -1
- data/app/apps/plugins/front_cache/front_cache_helper.rb +33 -9
- data/app/apps/plugins/visibility_post/config/config.json +1 -0
- data/app/apps/plugins/visibility_post/config/routes_front.txt +1 -0
- data/app/apps/plugins/visibility_post/front_controller.rb +23 -0
- data/app/apps/plugins/visibility_post/visibility_post_helper.rb +141 -70
- data/app/apps/themes/camaleon_first/main_helper.rb +18 -12
- data/app/apps/themes/default/assets/css/style.css.scss +24 -0
- data/app/apps/themes/default/assets/genericons/genericons.css +3 -8
- data/app/apps/themes/default/default_helper.rb +2 -1
- data/app/apps/themes/default/views/layouts/index.html.erb +3 -1
- data/app/apps/themes/new/assets/css/styles.css.scss +24 -0
- data/app/apps/themes/new/custom_helper.rb +5 -9
- data/app/apps/themes/new/views/layouts/_header.html.erb +3 -1
- data/app/assets/javascripts/camaleon_cms/admin/_data.js +16 -0
- data/app/assets/javascripts/camaleon_cms/admin/_post.js +5 -2
- data/app/assets/javascripts/camaleon_cms/admin/nav_menu.js +14 -3
- data/app/assets/javascripts/camaleon_cms/admin/uploader/_media_manager.js +5 -0
- data/app/controllers/camaleon_cms/admin/appearances/nav_menus_controller.rb +8 -6
- data/app/controllers/camaleon_cms/admin/appearances/themes_controller.rb +8 -5
- data/app/controllers/camaleon_cms/admin/appearances/widgets/assign_controller.rb +7 -2
- data/app/controllers/camaleon_cms/admin/appearances/widgets/main_controller.rb +2 -1
- data/app/controllers/camaleon_cms/admin/categories_controller.rb +19 -4
- data/app/controllers/camaleon_cms/admin/comments_controller.rb +0 -1
- data/app/controllers/camaleon_cms/admin/installers_controller.rb +32 -1
- data/app/controllers/camaleon_cms/admin/media_controller.rb +66 -14
- data/app/controllers/camaleon_cms/admin/plugins_controller.rb +1 -3
- data/app/controllers/camaleon_cms/admin/post_tags_controller.rb +10 -4
- data/app/controllers/camaleon_cms/admin/posts/drafts_controller.rb +40 -11
- data/app/controllers/camaleon_cms/admin/posts_controller.rb +55 -22
- data/app/controllers/camaleon_cms/admin/sessions_controller.rb +237 -44
- data/app/controllers/camaleon_cms/admin/settings/custom_fields_controller.rb +76 -13
- data/app/controllers/camaleon_cms/admin/settings/post_types_controller.rb +5 -2
- data/app/controllers/camaleon_cms/admin/settings/sites_controller.rb +26 -3
- data/app/controllers/camaleon_cms/admin/settings_controller.rb +5 -3
- data/app/controllers/camaleon_cms/admin/user_roles_controller.rb +7 -5
- data/app/controllers/camaleon_cms/admin/users_controller.rb +78 -11
- data/app/controllers/camaleon_cms/admin_controller.rb +136 -26
- data/app/controllers/camaleon_cms/camaleon_controller.rb +37 -92
- data/app/controllers/camaleon_cms/frontend_controller.rb +140 -70
- data/app/controllers/concerns/camaleon_cms/admin/custom_fields_concern.rb +20 -5
- data/app/controllers/concerns/camaleon_cms/frontend_concern.rb +46 -17
- data/app/controllers/concerns/camaleon_cms/frontend_visited_state_concern.rb +72 -0
- data/app/controllers/concerns/camaleon_cms/hook_lifecycle_concern.rb +104 -0
- data/app/controllers/concerns/camaleon_cms/request_context_concern.rb +113 -0
- data/app/controllers/concerns/camaleon_cms/runtime_admin_menu_concern.rb +237 -0
- data/app/controllers/concerns/camaleon_cms/runtime_captcha_image_concern.rb +13 -0
- data/app/controllers/concerns/camaleon_cms/runtime_html_content_concern.rb +143 -0
- data/app/controllers/concerns/camaleon_cms/runtime_shortcode_theme_concern.rb +246 -0
- data/app/controllers/concerns/camaleon_cms/runtime_state_concern.rb +13 -0
- data/app/controllers/concerns/camaleon_cms/runtime_uploader_concern.rb +54 -0
- data/app/controllers/concerns/camaleon_cms/session_captcha_runtime_concern.rb +19 -0
- data/app/controllers/concerns/camaleon_cms/session_runtime_concern.rb +40 -0
- data/app/decorators/camaleon_cms/application_decorator.rb +11 -8
- data/app/decorators/camaleon_cms/category_decorator.rb +3 -2
- data/app/decorators/camaleon_cms/post_comment_decorator.rb +13 -5
- data/app/decorators/camaleon_cms/post_decorator.rb +66 -50
- data/app/decorators/camaleon_cms/post_type_decorator.rb +1 -1
- data/app/decorators/camaleon_cms/site_decorator.rb +29 -23
- data/app/decorators/camaleon_cms/term_taxonomy_decorator.rb +21 -10
- data/app/decorators/camaleon_cms/theme_decorator.rb +3 -3
- data/app/decorators/camaleon_cms/user_decorator.rb +26 -5
- data/app/helpers/camaleon_cms/admin/application_helper.rb +5 -8
- data/app/helpers/camaleon_cms/admin/breadcrumb_helper.rb +1 -1
- data/app/helpers/camaleon_cms/admin/custom_fields_helper.rb +24 -23
- data/app/helpers/camaleon_cms/admin/menus_helper.rb +249 -139
- data/app/helpers/camaleon_cms/admin/post_type_helper.rb +34 -17
- data/app/helpers/camaleon_cms/camaleon_helper.rb +31 -39
- data/app/helpers/camaleon_cms/captcha_helper.rb +73 -53
- data/app/helpers/camaleon_cms/comment_helper.rb +19 -7
- data/app/helpers/camaleon_cms/content_helper.rb +13 -6
- data/app/helpers/camaleon_cms/email_helper.rb +7 -3
- data/app/helpers/camaleon_cms/frontend/content_select_helper.rb +34 -20
- data/app/helpers/camaleon_cms/frontend/nav_menu_helper.rb +143 -66
- data/app/helpers/camaleon_cms/frontend/seo_helper.rb +39 -28
- data/app/helpers/camaleon_cms/frontend/site_helper.rb +32 -12
- data/app/helpers/camaleon_cms/hooks_helper.rb +14 -4
- data/app/helpers/camaleon_cms/html_helper.rb +58 -37
- data/app/helpers/camaleon_cms/plugins_helper.rb +23 -24
- data/app/helpers/camaleon_cms/session_helper.rb +188 -44
- data/app/helpers/camaleon_cms/short_code_helper.rb +181 -85
- data/app/helpers/camaleon_cms/site_helper.rb +34 -13
- data/app/helpers/camaleon_cms/theme_helper.rb +35 -19
- data/app/helpers/camaleon_cms/uploader_helper.rb +19 -473
- data/app/helpers/camaleon_cms/user_roles_helper.rb +5 -4
- data/app/mailers/camaleon_cms/html_mailer.rb +4 -4
- data/app/models/camaleon_cms/ability.rb +15 -7
- data/app/models/camaleon_cms/category.rb +6 -6
- data/app/models/camaleon_cms/custom_field.rb +15 -6
- data/app/models/camaleon_cms/custom_field_group.rb +39 -22
- data/app/models/camaleon_cms/custom_fields_relationship.rb +133 -2
- data/app/models/camaleon_cms/media.rb +8 -2
- data/app/models/camaleon_cms/meta.rb +2 -2
- data/app/models/camaleon_cms/nav_menu.rb +5 -3
- data/app/models/camaleon_cms/nav_menu_item.rb +16 -8
- data/app/models/camaleon_cms/plugin.rb +3 -4
- data/app/models/camaleon_cms/post.rb +113 -27
- data/app/models/camaleon_cms/post_comment.rb +10 -6
- data/app/models/camaleon_cms/post_default.rb +42 -12
- data/app/models/camaleon_cms/post_relationship.rb +6 -4
- data/app/models/camaleon_cms/post_tag.rb +4 -5
- data/app/models/camaleon_cms/post_type.rb +21 -13
- data/app/models/camaleon_cms/site.rb +39 -29
- data/app/models/camaleon_cms/term_relationship.rb +10 -7
- data/app/models/camaleon_cms/term_taxonomy.rb +52 -4
- data/app/models/camaleon_cms/theme.rb +2 -4
- data/app/models/camaleon_cms/user.rb +17 -5
- data/app/models/camaleon_cms/user_role.rb +66 -6
- data/app/models/camaleon_cms/widget/assigned.rb +11 -6
- data/app/models/camaleon_cms/widget/main.rb +12 -8
- data/app/models/camaleon_cms/widget/sidebar.rb +3 -8
- data/app/models/camaleon_record.rb +89 -5
- data/app/models/concerns/camaleon_cms/categories_tags_for_posts.rb +20 -38
- data/app/models/concerns/camaleon_cms/common_relationships.rb +18 -5
- data/app/models/concerns/camaleon_cms/custom_fields_read.rb +111 -54
- data/app/models/concerns/camaleon_cms/metas.rb +31 -6
- data/app/models/concerns/camaleon_cms/normalize_attrs.rb +2 -8
- data/app/models/concerns/camaleon_cms/site_default_settings.rb +120 -16
- data/app/models/concerns/camaleon_cms/user_methods.rb +44 -19
- data/app/models/current_request.rb +8 -1
- data/app/uploaders/camaleon_cms_aws_uploader.rb +31 -10
- data/app/uploaders/camaleon_cms_local_uploader.rb +76 -19
- data/app/uploaders/camaleon_cms_uploader.rb +23 -10
- data/app/validators/camaleon_cms/post_uniq_validator.rb +5 -4
- data/app/validators/camaleon_cms/uniq_validator.rb +1 -1
- data/app/validators/camaleon_cms/user_url_validator.rb +215 -36
- data/app/views/camaleon_cms/admin/categories/index.html.erb +2 -2
- data/app/views/camaleon_cms/admin/installers/form.html.erb +5 -0
- data/app/views/camaleon_cms/admin/installers/welcome.html.erb +30 -6
- data/app/views/camaleon_cms/admin/plugins/_plugins_list.html.erb +2 -2
- data/app/views/camaleon_cms/admin/post_tags/index.html.erb +2 -2
- data/app/views/camaleon_cms/admin/posts/_sidebar.html.erb +1 -1
- data/app/views/camaleon_cms/admin/posts/form.html.erb +3 -2
- data/app/views/camaleon_cms/admin/posts/index.html.erb +5 -5
- data/app/views/camaleon_cms/admin/sessions/back_to_parent.html.erb +39 -0
- data/app/views/camaleon_cms/admin/sessions/logout_confirm.html.erb +27 -0
- data/app/views/camaleon_cms/admin/settings/_email_settings.html.erb +4 -1
- data/app/views/camaleon_cms/admin/settings/custom_fields/_get_items.html.erb +1 -1
- data/app/views/camaleon_cms/admin/settings/custom_fields/_render.html.erb +19 -4
- data/app/views/camaleon_cms/admin/settings/custom_fields/_render_category_simple.html.erb +1 -1
- data/app/views/camaleon_cms/admin/settings/custom_fields/form.html.erb +4 -3
- data/app/views/camaleon_cms/admin/settings/shortcodes.html.erb +4 -4
- data/app/views/camaleon_cms/admin/settings/site.html.erb +1 -1
- data/app/views/camaleon_cms/admin/settings/sites/form.html.erb +1 -1
- data/app/views/camaleon_cms/admin/user_roles/form.html.erb +24 -3
- data/app/views/camaleon_cms/admin/users/form.html.erb +8 -4
- data/app/views/camaleon_cms/admin/users/index.html.erb +1 -1
- data/app/views/camaleon_cms/default_theme/partials/_render_custom_field.html.erb +8 -2
- data/app/views/camaleon_cms/default_theme/sitemap.html.erb +1 -1
- data/app/views/camaleon_cms/default_theme/sitemap.xml.builder +1 -1
- data/app/views/layouts/camaleon_cms/admin/_header.html.erb +1 -1
- data/config/initializers/action_view.rb +42 -5
- data/config/initializers/active_record_extension.rb +13 -27
- data/config/initializers/assets.rb +52 -23
- data/config/initializers/custom_initializers.rb +1 -1
- data/config/locales/camaleon_cms/admin/ar.yml +1 -0
- data/config/locales/camaleon_cms/admin/de.yml +1 -0
- data/config/locales/camaleon_cms/admin/en.yml +33 -0
- data/config/locales/camaleon_cms/admin/es.yml +1 -0
- data/config/locales/camaleon_cms/admin/fr.yml +1 -0
- data/config/locales/camaleon_cms/admin/it.yml +1 -0
- data/config/locales/camaleon_cms/admin/nl.yml +1 -0
- data/config/locales/camaleon_cms/admin/pt-BR.yml +1 -0
- data/config/locales/camaleon_cms/admin/pt.yml +1 -0
- data/config/locales/camaleon_cms/admin/ru.yml +1 -0
- data/config/locales/camaleon_cms/admin/uk.yml +1 -0
- data/config/locales/camaleon_cms/admin/zh-CH.yml +1 -0
- data/config/routes/admin.rb +33 -15
- data/config/routes/frontend.rb +21 -15
- data/lib/camaleon_cms/assets_precompile.rb +86 -0
- data/lib/camaleon_cms/captcha_image_generation.rb +65 -0
- data/lib/camaleon_cms/content_security.rb +158 -0
- data/lib/camaleon_cms/engine.rb +47 -9
- data/lib/camaleon_cms/media_security_headers.rb +27 -0
- data/lib/camaleon_cms/setup_token.rb +69 -0
- data/lib/camaleon_cms/svg_content_checker.rb +123 -0
- data/lib/camaleon_cms/task_reporter.rb +14 -0
- data/lib/camaleon_cms/unsafe_markup.rb +207 -0
- data/lib/camaleon_cms/uploader_content_security.rb +248 -0
- data/lib/camaleon_cms/uploader_image_processing.rb +166 -0
- data/lib/camaleon_cms/uploader_path_security.rb +146 -0
- data/lib/camaleon_cms/uploader_pipeline.rb +350 -0
- data/lib/camaleon_cms/uploader_support.rb +86 -0
- data/lib/camaleon_cms/version.rb +1 -1
- data/lib/camaleon_cms.rb +11 -0
- data/lib/ext/hash.rb +28 -2
- data/lib/ext/string.rb +10 -5
- data/lib/ext/translator.rb +10 -2
- data/lib/generators/camaleon_cms/gem_plugin_template/app/controllers/plugins/my_plugin/admin_controller.rb +5 -1
- data/lib/generators/camaleon_cms/install_generator.rb +7 -4
- data/lib/generators/camaleon_cms/install_template/plugin_routes.rb +5 -12
- data/lib/generators/camaleon_cms/theme_generator.rb +5 -10
- data/lib/generators/camaleon_cms/theme_template/views/layouts/index.html.erb +3 -1
- data/lib/plugin_routes.rb +412 -368
- data/lib/tasks/camaleon_cms/camaleon_tasks.rake +2 -1
- data/lib/tasks/cross_site_field_groups.rake +74 -0
- data/lib/tasks/custom_fields_roles.rake +15 -13
- data/lib/tasks/orphaned_comments.rake +42 -0
- data/lib/tasks/private_upload_acls.rake +31 -0
- data/lib/tasks/site_custom_field_groups.rake +36 -0
- data/lib/tasks/unsafe_stored_content.rake +42 -0
- data/lib/tasks/unsafe_stored_uploads.rake +70 -0
- data/lib/tasks/user_field_groups.rake +27 -0
- metadata +123 -4
|
@@ -4,7 +4,8 @@ module CamaleonCms
|
|
|
4
4
|
# visiting sitemap.xml
|
|
5
5
|
# With hook "on_render_sitemap" you can skip post_types, categories, tags or posts
|
|
6
6
|
# you can change render file and layout
|
|
7
|
-
# you can add custom sitemap elements in the attr "custom",
|
|
7
|
+
# you can add custom sitemap elements in the attr "custom",
|
|
8
|
+
# like: https://github.com/owen2345/camaleon-cms/issues/106#issuecomment-146232211
|
|
8
9
|
# you can customize your content for html or xml format
|
|
9
10
|
def sitemap
|
|
10
11
|
r = { layout: (params[:format] == 'html' ? nil : false), render: 'sitemap', custom: {}, format: params[:format],
|
|
@@ -31,21 +32,33 @@ module CamaleonCms
|
|
|
31
32
|
# save comment from a post
|
|
32
33
|
def save_comment
|
|
33
34
|
flash[:comment_submit] = {}
|
|
34
|
-
|
|
35
|
+
# Security (audit Low): this is a public endpoint. A post id naming no post used to reach
|
|
36
|
+
# `.decorate` on nil (500), and the anonymous branch indexed a missing post_comment param.
|
|
37
|
+
# Fail closed with a graceful error instead of a 500 an attacker can trigger at will.
|
|
38
|
+
@post = current_site.posts.find_by(id: params[:post_id])&.decorate
|
|
35
39
|
user = cama_current_user
|
|
36
40
|
comment_data = {}
|
|
37
|
-
|
|
38
|
-
flash[:comment_submit][:error] =
|
|
39
|
-
|
|
41
|
+
if @post.nil?
|
|
42
|
+
flash[:comment_submit][:error] = t('.post_not_found', default: 'Post not found')
|
|
43
|
+
elsif !@post.can_commented?
|
|
44
|
+
flash[:comment_submit][:error] = t('.comments_not_enabled', default: 'This post can not be commented')
|
|
40
45
|
end
|
|
46
|
+
|
|
47
|
+
# Security (audit Low): params[:post_comment] is attacker-controlled and may arrive as a scalar
|
|
48
|
+
# or array, not the expected hash. `|| {}` only covered nil; indexing a String/Array with a
|
|
49
|
+
# symbol key raises TypeError (500). Coerce anything not hash-shaped to an empty hash so every
|
|
50
|
+
# post_comment[...] read below is safe.
|
|
51
|
+
post_comment = params[:post_comment]
|
|
52
|
+
post_comment = {} unless post_comment.is_a?(ActionController::Parameters) || post_comment.is_a?(Hash)
|
|
53
|
+
|
|
41
54
|
if user.present?
|
|
42
55
|
comment_data[:author] = user.fullname
|
|
43
56
|
comment_data[:author_email] = user.email
|
|
44
57
|
elsif current_site.get_option('permit_anonimos_comment', false)
|
|
45
58
|
user = current_site.get_anonymous_user
|
|
46
59
|
comment_data[:is_anonymous] = true
|
|
47
|
-
comment_data[:author] =
|
|
48
|
-
comment_data[:author_email] =
|
|
60
|
+
comment_data[:author] = post_comment[:name]
|
|
61
|
+
comment_data[:author_email] = post_comment[:email]
|
|
49
62
|
if current_site.is_enable_captcha_for_comments? && !cama_captcha_verified?
|
|
50
63
|
flash[:comment_submit][:error] =
|
|
51
64
|
t('camaleon_cms.admin.users.message.error_captcha',
|
|
@@ -56,24 +69,40 @@ module CamaleonCms
|
|
|
56
69
|
unless flash[:comment_submit][:error]
|
|
57
70
|
if user.present?
|
|
58
71
|
comment_data[:user_id] = user.id
|
|
59
|
-
comment_data[:author_url] =
|
|
72
|
+
comment_data[:author_url] = post_comment[:url] || ''
|
|
60
73
|
comment_data[:author_IP] = request.remote_ip.to_s
|
|
61
74
|
comment_data[:approved] = current_site.front_comment_status
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
75
|
+
# Browsers always send a User-Agent but API clients/bots may not; record it nil-safely
|
|
76
|
+
# and without mutating the request's header string in place.
|
|
77
|
+
comment_data[:agent] = request.user_agent.to_s.encode('UTF-8', 'ISO-8859-1')
|
|
78
|
+
comment_data[:content] = post_comment[:content]
|
|
79
|
+
# Security (audit Low): a crafted parent_id naming no comment on this post made find_by
|
|
80
|
+
# return nil and the chained `.children` raise (500). Resolve the parent first and fail
|
|
81
|
+
# closed with a graceful error when a supplied parent_id matches nothing.
|
|
82
|
+
parent_id = post_comment[:parent_id]
|
|
83
|
+
parent = @post.comments.find_by(id: parent_id) if parent_id.present?
|
|
84
|
+
if parent_id.present? && parent.nil?
|
|
85
|
+
flash[:comment_submit][:error] = t('.parent_comment_not_found', default: 'Parent comment not found')
|
|
67
86
|
else
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
87
|
+
@comment = parent ? parent.children.new(comment_data) : @post.comments.main.new(comment_data)
|
|
88
|
+
if @comment.save
|
|
89
|
+
flash[:comment_submit][:notice] = t('camaleon_cms.admin.comments.message.created')
|
|
90
|
+
else
|
|
91
|
+
base = t('camaleon_cms.common.comment_error', default: 'An error was occurred on save comment')
|
|
92
|
+
flash[:comment_submit][:error] = "#{base}:<br> #{@comment.errors.full_messages.join(', ')}"
|
|
93
|
+
end
|
|
71
94
|
end
|
|
72
95
|
else
|
|
73
96
|
flash[:comment_submit][:error] = t('camaleon_cms.admin.message.unauthorized')
|
|
74
97
|
end
|
|
75
98
|
end
|
|
76
|
-
|
|
99
|
+
|
|
100
|
+
return render(json: flash.discard(:comment_submit).to_hash) if params[:format] == 'json'
|
|
101
|
+
|
|
102
|
+
# Security (audit Low): the Referer header is attacker-controlled; redirecting to it raw is an
|
|
103
|
+
# open redirect (Rails < 7) or an UnsafeRedirectError 500 (Rails >= 7). Vet it through the shared
|
|
104
|
+
# same-host/allowlist redirect helper, falling back to the post URL (or root).
|
|
105
|
+
cama_safe_redirect(request.referer, @post&.the_url(as_path: true) || '/')
|
|
77
106
|
end
|
|
78
107
|
end
|
|
79
108
|
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module CamaleonCms
|
|
2
|
+
module FrontendVisitedStateConcern
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
LEGACY_VISITED_IVAR_BY_ATTR = {
|
|
6
|
+
frontend_visited_home: :@cama_visited_home,
|
|
7
|
+
frontend_visited_post: :@cama_visited_post,
|
|
8
|
+
frontend_visited_ajax: :@cama_visited_ajax,
|
|
9
|
+
frontend_visited_search: :@cama_visited_search,
|
|
10
|
+
frontend_visited_post_type: :@cama_visited_post_type,
|
|
11
|
+
frontend_visited_tag: :@cama_visited_tag,
|
|
12
|
+
frontend_visited_category: :@cama_visited_category,
|
|
13
|
+
frontend_visited_profile: :@cama_visited_profile
|
|
14
|
+
}.freeze
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def mark_frontend_home_visited
|
|
19
|
+
set_frontend_visited_state(:frontend_visited_home, true)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def mark_frontend_post_visited(post)
|
|
23
|
+
set_frontend_visited_state(:frontend_visited_post, post)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def mark_frontend_ajax_visited
|
|
27
|
+
set_frontend_visited_state(:frontend_visited_ajax, true)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def mark_frontend_search_visited
|
|
31
|
+
set_frontend_visited_state(:frontend_visited_search, true)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def mark_frontend_post_type_visited(post_type)
|
|
35
|
+
set_frontend_visited_state(:frontend_visited_post_type, post_type)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def mark_frontend_tag_visited(post_tag)
|
|
39
|
+
set_frontend_visited_state(:frontend_visited_tag, post_tag)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def mark_frontend_category_visited(category)
|
|
43
|
+
set_frontend_visited_state(:frontend_visited_category, category)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def mark_frontend_profile_visited(user = nil)
|
|
47
|
+
set_frontend_visited_state(:frontend_visited_profile, true)
|
|
48
|
+
CurrentRequest.frontend_user = user if user.present?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def set_frontend_visited_state(current_request_attr, value)
|
|
52
|
+
CurrentRequest.public_send("#{current_request_attr}=", value)
|
|
53
|
+
legacy_ivar = LEGACY_VISITED_IVAR_BY_ATTR[current_request_attr]
|
|
54
|
+
return if legacy_ivar.blank?
|
|
55
|
+
|
|
56
|
+
instance_variable_set(legacy_ivar, value)
|
|
57
|
+
warn_frontend_legacy_visited_ivar(legacy_ivar, current_request_attr)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def warn_frontend_legacy_visited_ivar(legacy_ivar, current_request_attr)
|
|
61
|
+
warned_legacy_ivars = self.class.instance_variable_get(:@_warned_frontend_legacy_visited_ivars) || {}
|
|
62
|
+
return if warned_legacy_ivars[legacy_ivar]
|
|
63
|
+
|
|
64
|
+
ActiveSupport::Deprecation._instance.warn(
|
|
65
|
+
"Controller compatibility ivar #{legacy_ivar} is deprecated and will be removed in a future major release. " \
|
|
66
|
+
"Use CurrentRequest.#{current_request_attr} instead."
|
|
67
|
+
)
|
|
68
|
+
warned_legacy_ivars[legacy_ivar] = true
|
|
69
|
+
self.class.instance_variable_set(:@_warned_frontend_legacy_visited_ivars, warned_legacy_ivars)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
module CamaleonCms
|
|
2
|
+
module HookLifecycleConcern
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
def hook_run(plugin, hook_key, params = nil)
|
|
6
|
+
_do_hook(plugin, hook_key, params)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def hooks_run(hook_key, params = nil)
|
|
10
|
+
theme_slug = current_theme&.slug.presence || current_site.get_theme_slug
|
|
11
|
+
PluginRoutes.enabled_apps(current_site, theme_slug).each do |plugin|
|
|
12
|
+
_do_hook(plugin, hook_key, params)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
PluginRoutes.get_anonymous_hooks(hook_key).each do |_hook|
|
|
16
|
+
_hook.call(params)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def hook_skip(hook_function_name)
|
|
21
|
+
hook_skip_list << hook_function_name
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def initialize_hook_skip_list
|
|
27
|
+
hooks_skip = []
|
|
28
|
+
CurrentRequest.hooks_helper_state ||= {}
|
|
29
|
+
CurrentRequest.hooks_helper_state[:hooks_skip] = hooks_skip
|
|
30
|
+
@_hooks_skip = hooks_skip
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def run_hook_lifecycle(hook_name, payload = nil)
|
|
34
|
+
payload.nil? ? hooks_run(hook_name) : hooks_run(hook_name, payload)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def run_app_before_load_hooks
|
|
38
|
+
run_hook_lifecycle('app_before_load')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def run_app_after_load_hooks
|
|
42
|
+
run_hook_lifecycle('app_after_load')
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def _do_hook(plugin, hook_key, params = nil)
|
|
46
|
+
return if plugin.blank? || plugin['hooks'].blank? || plugin['hooks'][hook_key].blank?
|
|
47
|
+
|
|
48
|
+
plugin['hooks'][hook_key].each do |hook|
|
|
49
|
+
next if hook_skip_list.include?(hook)
|
|
50
|
+
|
|
51
|
+
begin
|
|
52
|
+
if params.nil?
|
|
53
|
+
send(hook)
|
|
54
|
+
else
|
|
55
|
+
send(hook, params)
|
|
56
|
+
end
|
|
57
|
+
Rails.logger.debug "Camaleon CMS - Hook \"#{hook_key}\" executed from dependency #{begin
|
|
58
|
+
plugin['key']
|
|
59
|
+
rescue StandardError
|
|
60
|
+
''
|
|
61
|
+
end}".cama_log_style(:light_blue)
|
|
62
|
+
rescue StandardError
|
|
63
|
+
plugin_load_helpers(plugin)
|
|
64
|
+
next unless respond_to?(hook, true)
|
|
65
|
+
|
|
66
|
+
if params.nil?
|
|
67
|
+
send(hook)
|
|
68
|
+
else
|
|
69
|
+
send(hook, params)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def hook_skip_list
|
|
76
|
+
state = camaleon_hooks_state
|
|
77
|
+
return state[:hooks_skip] if state[:hooks_skip]
|
|
78
|
+
|
|
79
|
+
# back-compat: legacy plugins/themes may seed @_hooks_skip directly on the
|
|
80
|
+
# controller. Honored here (controller concern) only as initial input so the
|
|
81
|
+
# shared view helper stays ivar-free.
|
|
82
|
+
existing_hooks_skip = @_hooks_skip
|
|
83
|
+
state[:hooks_skip] = existing_hooks_skip.is_a?(Array) ? existing_hooks_skip : []
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def camaleon_hooks_state
|
|
87
|
+
CurrentRequest.hooks_helper_state ||= {}
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def plugin_load_helpers(plugin)
|
|
91
|
+
return if plugin.blank? || plugin['helpers'].blank?
|
|
92
|
+
|
|
93
|
+
plugin['helpers'].each do |h|
|
|
94
|
+
next if self.class.include?(h.constantize)
|
|
95
|
+
|
|
96
|
+
self.class.class_eval { include h.constantize }
|
|
97
|
+
rescue StandardError => e
|
|
98
|
+
Rails.logger.debug do
|
|
99
|
+
"Camaleon CMS - App loading error for #{h}: #{e.message}. Please check the plugins and themes presence"
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
module CamaleonCms
|
|
2
|
+
# Wires per-request site/theme resolution and Camaleon's before-action
|
|
3
|
+
# housekeeping into the runtime controller stack. The `current_site` /
|
|
4
|
+
# `current_theme` implementations live in `CamaleonCms::SiteHelper` (single
|
|
5
|
+
# source of truth shared with views); this concern only adds controller-only
|
|
6
|
+
# hooks like view-path setup and site-existence guards.
|
|
7
|
+
module RequestContextConcern
|
|
8
|
+
extend ActiveSupport::Concern
|
|
9
|
+
|
|
10
|
+
include CamaleonCms::SiteHelper
|
|
11
|
+
|
|
12
|
+
# Back-compat: expose the resolved site as the `@current_site` controller
|
|
13
|
+
# ivar for legacy templates/plugins. The helper logic itself stays ivar-free
|
|
14
|
+
# (it reads/writes `CurrentRequest.site`); only this controller concern
|
|
15
|
+
# bridges the value into an instance variable so views/plugins keep working.
|
|
16
|
+
def current_site(site = nil)
|
|
17
|
+
result = super
|
|
18
|
+
@current_site = CurrentRequest.site
|
|
19
|
+
result
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def configure_runtime_request_context
|
|
25
|
+
sanitize_forwarded_host_header
|
|
26
|
+
configure_runtime_view_paths
|
|
27
|
+
sync_runtime_defaults
|
|
28
|
+
assign_template_compatibility_state
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def sanitize_forwarded_host_header
|
|
32
|
+
request.env.except!('HTTP_X_FORWARDED_HOST') if request.env['HTTP_X_FORWARDED_HOST']
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def configure_runtime_view_paths
|
|
36
|
+
views_dir = 'app/apps/'
|
|
37
|
+
prepend_view_path(CamaleonCms::Engine.root.join(views_dir).to_s)
|
|
38
|
+
prepend_view_path(Rails.root.join(views_dir).to_s)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def sync_runtime_defaults
|
|
42
|
+
CamaleonCms::PostDefault.current_user = cama_current_user
|
|
43
|
+
CamaleonCms::PostDefault.current_site = current_site
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def assign_template_compatibility_state
|
|
47
|
+
@current_site = current_site
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# check if current site exist, if not, this will be redirected to main domain
|
|
51
|
+
# Also, check current site status
|
|
52
|
+
def cama_site_check_existence
|
|
53
|
+
if current_site.blank?
|
|
54
|
+
redirect_when_site_missing
|
|
55
|
+
elsif (cama_current_user.present? && !cama_current_user.admin?) || cama_current_user.blank?
|
|
56
|
+
handle_inactive_site_access
|
|
57
|
+
handle_maintenance_site_access
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def redirect_when_site_missing
|
|
62
|
+
if Cama::Site.main_site.present?
|
|
63
|
+
url = Cama::Site.main_site.decorate.the_url
|
|
64
|
+
# TODO: Remove this condition when Rails 6.x won't be supported
|
|
65
|
+
if Rails.gem_version >= Gem::Version.new('7.0.0')
|
|
66
|
+
redirect_to url, allow_other_host: true
|
|
67
|
+
else
|
|
68
|
+
redirect_to url
|
|
69
|
+
end
|
|
70
|
+
else
|
|
71
|
+
redirect_to cama_admin_installers_path
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def handle_inactive_site_access
|
|
76
|
+
return unless current_site.is_inactive?
|
|
77
|
+
|
|
78
|
+
if request.original_url.to_s.match?(%r{\A#{current_site.the_url}admin(/|\z)})
|
|
79
|
+
if cama_current_user.present?
|
|
80
|
+
cama_logout_user
|
|
81
|
+
flash[:error] = 'Site is Inactive'
|
|
82
|
+
end
|
|
83
|
+
else
|
|
84
|
+
post = current_site.posts.find_by(id: current_site.get_option('page_inactive')).try(:decorate)
|
|
85
|
+
if post
|
|
86
|
+
redirect_to(post.the_url) unless params == {
|
|
87
|
+
'controller' => 'camaleon_cms/frontend',
|
|
88
|
+
'action' => 'post',
|
|
89
|
+
'slug' => post.the_slug
|
|
90
|
+
}
|
|
91
|
+
else
|
|
92
|
+
render html: 'This site was inactivated. Please contact to administrator.'
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def handle_maintenance_site_access
|
|
98
|
+
return unless current_site.is_maintenance?
|
|
99
|
+
return if current_site.get_option('maintenance_ips', '').split(',').include?(request.remote_ip)
|
|
100
|
+
|
|
101
|
+
post = current_site.posts.find_by(id: current_site.get_option('page_maintenance')).try(:decorate)
|
|
102
|
+
if post
|
|
103
|
+
redirect_to(post.the_url) if params != {
|
|
104
|
+
'controller' => 'camaleon_cms/frontend',
|
|
105
|
+
'action' => 'post',
|
|
106
|
+
'slug' => post.the_slug
|
|
107
|
+
}
|
|
108
|
+
else
|
|
109
|
+
render html: 'This site is in maintenance mode. Please contact to administrator.'
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# rubocop:disable Metrics/AbcSize
|
|
2
|
+
module CamaleonCms
|
|
3
|
+
module RuntimeAdminMenuConcern
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
def admin_menus_add_commons
|
|
7
|
+
admin_menu_add_menu(
|
|
8
|
+
'dashboard',
|
|
9
|
+
{ icon: 'dashboard', title: t('camaleon_cms.admin.sidebar.dashboard'), url: cama_admin_dashboard_path }
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
items = []
|
|
13
|
+
current_site.post_types.eager_load(:metas).visible_menu.find_each do |pt|
|
|
14
|
+
pt = pt.decorate
|
|
15
|
+
items_i = []
|
|
16
|
+
if can? :posts, pt
|
|
17
|
+
items_i << { icon: 'list', title: t('camaleon_cms.admin.post_type.all').to_s,
|
|
18
|
+
url: cama_admin_post_type_posts_path(pt.id) }
|
|
19
|
+
end
|
|
20
|
+
if can? :create_post, pt
|
|
21
|
+
items_i << { icon: 'plus', title: t('camaleon_cms.admin.post_type.add_new', type_title: pt.the_title).to_s,
|
|
22
|
+
url: new_cama_admin_post_type_post_path(pt.id) }
|
|
23
|
+
end
|
|
24
|
+
if pt.manage_categories? && (can? :categories, pt)
|
|
25
|
+
items_i << { icon: 'folder-open', title: t('camaleon_cms.admin.post_type.categories'),
|
|
26
|
+
url: cama_admin_post_type_categories_path(pt.id) }
|
|
27
|
+
end
|
|
28
|
+
if pt.manage_tags? && (can? :post_tags, pt)
|
|
29
|
+
items_i << { icon: 'tags', title: t('camaleon_cms.admin.post_type.tags'),
|
|
30
|
+
url: cama_admin_post_type_post_tags_path(pt.id) }
|
|
31
|
+
end
|
|
32
|
+
if items_i.present?
|
|
33
|
+
items << { icon: pt.get_option('icon', 'copy'), title: pt.the_title, url: '', items: items_i }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
if items.present?
|
|
38
|
+
admin_menu_add_menu(
|
|
39
|
+
'content',
|
|
40
|
+
{
|
|
41
|
+
icon: 'database', title: t('camaleon_cms.admin.sidebar.contents'), url: '', items: items,
|
|
42
|
+
datas: "data-intro='#{t('camaleon_cms.admin.intro.content')}' data-position='right' data-wait='600'"
|
|
43
|
+
}
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
if can? :manage, :media
|
|
48
|
+
admin_menu_add_menu(
|
|
49
|
+
'media',
|
|
50
|
+
{
|
|
51
|
+
icon: 'picture-o', title: t('camaleon_cms.admin.sidebar.media'), url: cama_admin_media_path,
|
|
52
|
+
datas: "data-intro='#{t('camaleon_cms.admin.intro.media')}' data-position='right'"
|
|
53
|
+
}
|
|
54
|
+
)
|
|
55
|
+
end
|
|
56
|
+
if can? :manage, :comments
|
|
57
|
+
admin_menu_add_menu(
|
|
58
|
+
'comments',
|
|
59
|
+
{
|
|
60
|
+
icon: 'comments', title: t('camaleon_cms.admin.sidebar.comments'), url: cama_admin_comments_path,
|
|
61
|
+
datas: "data-intro='#{t('camaleon_cms.admin.intro.comments')}' data-position='right'"
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
items = []
|
|
67
|
+
if can? :manage, :themes
|
|
68
|
+
items << {
|
|
69
|
+
icon: 'desktop', title: t('camaleon_cms.admin.sidebar.themes'), url: cama_admin_appearances_themes_path,
|
|
70
|
+
datas: "data-intro='#{t('camaleon_cms.admin.intro.themes')}' data-position='right'"
|
|
71
|
+
}
|
|
72
|
+
end
|
|
73
|
+
if can? :manage, :widgets
|
|
74
|
+
items << {
|
|
75
|
+
icon: 'archive', title: t('camaleon_cms.admin.sidebar.widgets'),
|
|
76
|
+
url: cama_admin_appearances_widgets_main_index_path,
|
|
77
|
+
datas: "data-intro='#{t('camaleon_cms.admin.intro.widgets')}' data-position='right'"
|
|
78
|
+
}
|
|
79
|
+
end
|
|
80
|
+
if can? :manage, :nav_menu
|
|
81
|
+
intro_menus_data =
|
|
82
|
+
t('camaleon_cms.admin.intro.menus', image: helpers.asset_path('camaleon_cms/admin/intro/menus.png'))
|
|
83
|
+
items << {
|
|
84
|
+
icon: 'list', title: t('camaleon_cms.admin.sidebar.menus'), url: cama_admin_appearances_nav_menus_path,
|
|
85
|
+
datas: "data-intro='#{intro_menus_data}' data-position='right'"
|
|
86
|
+
}
|
|
87
|
+
end
|
|
88
|
+
if can? :manage, :shortcodes
|
|
89
|
+
items << {
|
|
90
|
+
icon: 'code', title: t('camaleon_cms.admin.sidebar.shortcodes', default: 'Shortcodes'),
|
|
91
|
+
url: cama_admin_settings_shortcodes_path,
|
|
92
|
+
datas: "data-intro='#{t('camaleon_cms.admin.intro.shortcodes')}' data-position='right'"
|
|
93
|
+
}
|
|
94
|
+
end
|
|
95
|
+
if items.present?
|
|
96
|
+
admin_menu_add_menu(
|
|
97
|
+
'appearance',
|
|
98
|
+
{
|
|
99
|
+
icon: 'paint-brush', title: t('camaleon_cms.admin.sidebar.appearance'), url: '', items: items,
|
|
100
|
+
datas: "data-intro='#{t('camaleon_cms.admin.intro.appearance')}' data-position='right' data-wait='500'"
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
if can? :manage, :plugins
|
|
106
|
+
plugin_count = PluginRoutes.all_plugins.count do |plugin|
|
|
107
|
+
!(plugin[:domain].present? && !plugin[:domain].split(',').include?(current_site.the_slug))
|
|
108
|
+
end
|
|
109
|
+
admin_menu_add_menu(
|
|
110
|
+
'plugins',
|
|
111
|
+
{
|
|
112
|
+
icon: 'plug',
|
|
113
|
+
title: helpers.safe_join([
|
|
114
|
+
t('camaleon_cms.admin.sidebar.plugins'),
|
|
115
|
+
' ',
|
|
116
|
+
helpers.content_tag(:small, plugin_count, class: 'label label-primary')
|
|
117
|
+
]),
|
|
118
|
+
url: cama_admin_plugins_path,
|
|
119
|
+
datas: "data-intro='#{t('camaleon_cms.admin.intro.plugins')}' data-position='right'"
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
if can? :manage, :users
|
|
125
|
+
items = []
|
|
126
|
+
items << { icon: 'list', title: t('camaleon_cms.admin.users.all_users'), url: cama_admin_users_path }
|
|
127
|
+
items << { icon: 'plus', title: t('camaleon_cms.admin.users.add_user'), url: new_cama_admin_user_path }
|
|
128
|
+
items << { icon: 'group', title: t('camaleon_cms.admin.users.user_roles'), url: cama_admin_user_roles_path }
|
|
129
|
+
admin_menu_add_menu(
|
|
130
|
+
'users',
|
|
131
|
+
{
|
|
132
|
+
icon: 'users', title: t('camaleon_cms.admin.sidebar.users'), url: '', items: items,
|
|
133
|
+
datas: "data-intro='#{t('camaleon_cms.admin.intro.users')}' data-position='right' data-wait='500'"
|
|
134
|
+
}
|
|
135
|
+
)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
items = []
|
|
139
|
+
if can? :manage, :settings
|
|
140
|
+
items << {
|
|
141
|
+
icon: 'desktop', title: t('camaleon_cms.admin.sidebar.general_site'),
|
|
142
|
+
url: cama_admin_settings_site_path,
|
|
143
|
+
datas: "data-intro='#{t('camaleon_cms.admin.intro.gral_site')}' data-position='right'"
|
|
144
|
+
}
|
|
145
|
+
if current_site.manage_sites?
|
|
146
|
+
items << {
|
|
147
|
+
icon: 'cog', title: t('camaleon_cms.admin.sidebar.sites'),
|
|
148
|
+
url: cama_admin_settings_sites_path,
|
|
149
|
+
datas: "data-intro='#{t('camaleon_cms.admin.intro.sites')}' data-position='right'"
|
|
150
|
+
}
|
|
151
|
+
end
|
|
152
|
+
items << {
|
|
153
|
+
icon: 'files-o', title: t('camaleon_cms.admin.sidebar.content_groups'),
|
|
154
|
+
url: cama_admin_settings_post_types_path,
|
|
155
|
+
datas: "data-intro='#{t('camaleon_cms.admin.intro.post_type')}' data-position='right'"
|
|
156
|
+
}
|
|
157
|
+
items << {
|
|
158
|
+
icon: 'cog', title: t('camaleon_cms.admin.sidebar.custom_fields'),
|
|
159
|
+
url: cama_admin_settings_custom_fields_path,
|
|
160
|
+
datas: "data-intro='#{t('camaleon_cms.admin.intro.custom_fields')}' data-position='right'"
|
|
161
|
+
}
|
|
162
|
+
items << {
|
|
163
|
+
icon: 'language', title: t('camaleon_cms.admin.sidebar.languages'),
|
|
164
|
+
url: cama_admin_settings_languages_path,
|
|
165
|
+
datas: "data-intro='#{t('camaleon_cms.admin.intro.languages')}' data-position='right'"
|
|
166
|
+
}
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
if can? :manage, :theme_settings
|
|
170
|
+
items << {
|
|
171
|
+
icon: 'windows', title: t('camaleon_cms.admin.settings.theme_setting', default: 'Theme Settings'),
|
|
172
|
+
url: cama_admin_settings_theme_path
|
|
173
|
+
}
|
|
174
|
+
end
|
|
175
|
+
return if items.blank?
|
|
176
|
+
|
|
177
|
+
admin_menu_add_menu(
|
|
178
|
+
'settings',
|
|
179
|
+
{
|
|
180
|
+
icon: 'cogs', title: t('camaleon_cms.admin.sidebar.settings'), url: '', items: items,
|
|
181
|
+
datas: "data-intro='#{t('camaleon_cms.admin.intro.settings')}' data-position='right' data-wait='500'"
|
|
182
|
+
}
|
|
183
|
+
)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def admin_menu_add_menu(key, menu)
|
|
187
|
+
CurrentRequest.admin_menu_items ||= {}
|
|
188
|
+
CurrentRequest.admin_menu_items[key] = menu
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def admin_menu_append_menu_item(key, menu)
|
|
192
|
+
CurrentRequest.admin_menu_items ||= {}
|
|
193
|
+
return if CurrentRequest.admin_menu_items[key].blank?
|
|
194
|
+
|
|
195
|
+
CurrentRequest.admin_menu_items[key][:items] = [] unless CurrentRequest.admin_menu_items[key].key?(:items)
|
|
196
|
+
CurrentRequest.admin_menu_items[key][:items] << menu
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def admin_menu_prepend_menu_item(key, menu)
|
|
200
|
+
CurrentRequest.admin_menu_items ||= {}
|
|
201
|
+
return if CurrentRequest.admin_menu_items[key].blank?
|
|
202
|
+
|
|
203
|
+
CurrentRequest.admin_menu_items[key][:items] = [] unless CurrentRequest.admin_menu_items[key].key?(:items)
|
|
204
|
+
CurrentRequest.admin_menu_items[key][:items] = [menu] + CurrentRequest.admin_menu_items[key][:items]
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def admin_menu_insert_menu_before(key_target, key_menu, menu)
|
|
208
|
+
CurrentRequest.admin_menu_items ||= {}
|
|
209
|
+
res = CurrentRequest.admin_menu_items.each_with_object({}) do |(key, val), hsh|
|
|
210
|
+
hsh[key_menu] = menu if key == key_target
|
|
211
|
+
hsh[key] = val
|
|
212
|
+
end
|
|
213
|
+
CurrentRequest.admin_menu_items.replace(res) # mutate in place so @_admin_menus stays a live alias (M19)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def admin_menu_insert_menu_after(key_target, key_menu, menu)
|
|
217
|
+
CurrentRequest.admin_menu_items ||= {}
|
|
218
|
+
res = CurrentRequest.admin_menu_items.each_with_object({}) do |(key, val), hsh|
|
|
219
|
+
hsh[key] = val
|
|
220
|
+
hsh[key_menu] = menu if key == key_target
|
|
221
|
+
end
|
|
222
|
+
CurrentRequest.admin_menu_items.replace(res) # mutate in place so @_admin_menus stays a live alias (M19)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def cama_comments_get_common_data
|
|
226
|
+
comment_data = {}
|
|
227
|
+
comment_data[:user_id] = cama_current_user.id
|
|
228
|
+
comment_data[:author] = cama_current_user.the_name
|
|
229
|
+
comment_data[:author_email] = cama_current_user.email
|
|
230
|
+
comment_data[:author_IP] = request.remote_ip.to_s
|
|
231
|
+
comment_data[:approved] = 'approved'
|
|
232
|
+
comment_data[:agent] = request.user_agent.force_encoding('ISO-8859-1').encode('UTF-8')
|
|
233
|
+
comment_data
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
# rubocop:enable Metrics/AbcSize
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module CamaleonCms
|
|
2
|
+
# Controller-stack entry point for captcha image generation: GET /captcha
|
|
3
|
+
# (CamaleonController#captcha) resolves cama_captcha_build through this concern.
|
|
4
|
+
# The implementation lives in CamaleonCms::CaptchaImageGeneration, shared with
|
|
5
|
+
# CamaleonCms::CaptchaHelper, so a captcha hardening fix cannot land in one entry
|
|
6
|
+
# point and not the other (parity is guarded by
|
|
7
|
+
# spec/lib/camaleon_cms/captcha_implementation_parity_spec.rb).
|
|
8
|
+
module RuntimeCaptchaImageConcern
|
|
9
|
+
extend ActiveSupport::Concern
|
|
10
|
+
|
|
11
|
+
include CamaleonCms::CaptchaImageGeneration
|
|
12
|
+
end
|
|
13
|
+
end
|