decidim-core 0.32.1 → 0.32.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 (149) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/content_blocks/participatory_space_main_data/title.erb +1 -14
  3. data/app/cells/decidim/following_cell.rb +1 -1
  4. data/app/cells/decidim/member/show.erb +1 -1
  5. data/app/cells/decidim/nav_links/show.erb +3 -1
  6. data/app/cells/decidim/share_text_widget/modal.erb +1 -0
  7. data/app/cells/decidim/share_widget/modal.erb +1 -0
  8. data/app/cells/decidim/share_widget/qr_code_modal.erb +2 -4
  9. data/app/commands/decidim/create_omniauth_registration.rb +17 -2
  10. data/app/controllers/concerns/decidim/devise_authentication_methods.rb +4 -0
  11. data/app/controllers/concerns/decidim/devise_controllers.rb +2 -0
  12. data/app/controllers/concerns/decidim/disable_redirection_to_external_host.rb +2 -0
  13. data/app/controllers/concerns/decidim/filter_resource.rb +2 -0
  14. data/app/controllers/concerns/decidim/impersonate_users.rb +2 -2
  15. data/app/controllers/concerns/decidim/locale_switcher.rb +12 -10
  16. data/app/controllers/concerns/decidim/needs_permission.rb +22 -10
  17. data/app/controllers/concerns/decidim/onboarding_action_methods.rb +2 -0
  18. data/app/controllers/concerns/decidim/paginable.rb +7 -3
  19. data/app/controllers/concerns/decidim/payload_info.rb +2 -0
  20. data/app/controllers/concerns/decidim/resource_versions_concern.rb +14 -0
  21. data/app/controllers/decidim/application_controller.rb +0 -6
  22. data/app/controllers/decidim/authorization_modals_controller.rb +2 -0
  23. data/app/controllers/decidim/components/base_controller.rb +2 -0
  24. data/app/controllers/decidim/devise/passwords_controller.rb +8 -0
  25. data/app/controllers/decidim/favicon_controller.rb +9 -0
  26. data/app/controllers/decidim/free_resource_authorization_modals_controller.rb +2 -0
  27. data/app/controllers/decidim/gamification/badges_controller.rb +2 -0
  28. data/app/controllers/decidim/homepage_controller.rb +4 -1
  29. data/app/controllers/decidim/likes_controller.rb +1 -1
  30. data/app/controllers/decidim/links_controller.rb +2 -0
  31. data/app/controllers/decidim/manifests_controller.rb +2 -0
  32. data/app/controllers/decidim/messaging/conversations_controller.rb +10 -4
  33. data/app/controllers/decidim/newsletters_controller.rb +4 -0
  34. data/app/controllers/decidim/notifications_subscriptions_controller.rb +4 -0
  35. data/app/controllers/decidim/offline_controller.rb +5 -1
  36. data/app/controllers/decidim/open_data_controller.rb +5 -1
  37. data/app/controllers/decidim/pages_controller.rb +31 -3
  38. data/app/controllers/decidim/private_downloads_controller.rb +2 -0
  39. data/app/controllers/decidim/profiles_controller.rb +19 -1
  40. data/app/controllers/decidim/qr_controller.rb +3 -1
  41. data/app/controllers/decidim/resource_autocomplete_controller.rb +2 -0
  42. data/app/controllers/decidim/searches_controller.rb +2 -0
  43. data/app/controllers/decidim/short_links_controller.rb +4 -0
  44. data/app/controllers/decidim/static_map_controller.rb +2 -0
  45. data/app/controllers/decidim/timeouts_controller.rb +4 -0
  46. data/app/controllers/decidim/tos_controller.rb +2 -0
  47. data/app/controllers/decidim/upload_validations_controller.rb +4 -2
  48. data/app/controllers/decidim/user_activities_controller.rb +3 -0
  49. data/app/forms/decidim/upload_validation_form.rb +16 -10
  50. data/app/helpers/concerns/decidim/user_role_checker.rb +35 -10
  51. data/app/helpers/decidim/decidim_form_helper.rb +1 -1
  52. data/app/helpers/decidim/sanitize_helper.rb +11 -1
  53. data/app/jobs/decidim/application_job.rb +4 -0
  54. data/app/models/decidim/authorization.rb +24 -0
  55. data/app/models/decidim/oauth_application.rb +1 -0
  56. data/app/models/decidim/user.rb +1 -0
  57. data/app/models/decidim/user_base_entity.rb +1 -1
  58. data/app/packs/src/decidim/callout.js +10 -0
  59. data/app/packs/src/decidim/callout.test.js +32 -0
  60. data/app/packs/src/decidim/controllers/accordion/accordion.test.js +64 -0
  61. data/app/packs/src/decidim/controllers/accordion/controller.js +43 -0
  62. data/app/packs/src/decidim/controllers/autofocus/controller.js +30 -0
  63. data/app/packs/src/decidim/controllers/language_change/controller.js +21 -8
  64. data/app/packs/src/decidim/controllers/language_change/language_change.test.js +0 -1
  65. data/app/packs/src/decidim/controllers/mention/controller.js +32 -3
  66. data/app/packs/src/decidim/controllers/mention/input_mentions.test.js +8 -5
  67. data/app/packs/src/decidim/controllers/multiple_mentions/input_multiple_mentions.test.js +1 -1
  68. data/app/packs/src/decidim/datepicker/datepicker_functions.js +41 -25
  69. data/app/packs/src/decidim/datepicker/generate_datepicker.js +4 -4
  70. data/app/packs/src/decidim/datepicker/test/datepicker_functions_adjust_picker_position.test.js +64 -0
  71. data/app/packs/src/decidim/datepicker/test/time.test.js +39 -24
  72. data/app/packs/src/decidim/editor/common/suggestion.js +32 -22
  73. data/app/packs/src/decidim/editor/extensions/mention/index.js +14 -3
  74. data/app/packs/src/decidim/editor/index.js +4 -0
  75. data/app/packs/src/decidim/editor/test/extensions/mention.test.js +32 -9
  76. data/app/packs/src/decidim/refactor/implementation/autofocus.js +22 -0
  77. data/app/packs/src/decidim/refactor/implementation/autofocus.test.js +171 -0
  78. data/app/packs/src/decidim/utilities/dom.js +2 -2
  79. data/app/packs/stylesheets/decidim/_content_blocks.scss +4 -10
  80. data/app/packs/stylesheets/decidim/_conversations.scss +0 -8
  81. data/app/packs/stylesheets/decidim/_modal.scss +16 -8
  82. data/app/packs/stylesheets/decidim/_modal_share.scss +0 -22
  83. data/app/packs/stylesheets/decidim/_participatory_spaces.scss +11 -1
  84. data/app/packs/stylesheets/decidim/_rich_text.scss +12 -9
  85. data/app/packs/stylesheets/decidim/_typography.scss +5 -2
  86. data/app/packs/stylesheets/decidim/application.scss +1 -0
  87. data/app/packs/stylesheets/decidim/legacy/email.scss +0 -5
  88. data/app/permissions/decidim/permissions.rb +20 -0
  89. data/app/presenters/decidim/admin_log/component_presenter.rb +1 -1
  90. data/app/presenters/decidim/log/base_presenter.rb +10 -1
  91. data/app/presenters/decidim/log/user_presenter.rb +2 -2
  92. data/app/presenters/decidim/menu_item_presenter.rb +1 -5
  93. data/app/presenters/decidim/resource_presenter.rb +11 -0
  94. data/app/resolvers/decidim/meta_image_url_resolver.rb +7 -1
  95. data/app/serializers/decidim/exporters/open_data_blocked_user_serializer.rb +11 -2
  96. data/app/serializers/decidim/exporters/open_data_moderation_serializer.rb +25 -1
  97. data/app/services/decidim/svg_content_validator.rb +554 -0
  98. data/app/uploaders/decidim/application_uploader.rb +2 -2
  99. data/app/validators/uploader_image_content_validator.rb +276 -0
  100. data/app/views/decidim/application/_radio_accordion.html.erb +1 -5
  101. data/app/views/decidim/messaging/conversations/_add_conversation_users.html.erb +1 -1
  102. data/app/views/decidim/messaging/conversations/create.js.erb +1 -3
  103. data/app/views/decidim/shared/_login_modal.html.erb +12 -14
  104. data/app/views/layouts/decidim/_mailer_logo.html.erb +1 -1
  105. data/app/views/layouts/decidim/header/_menu_breadcrumb_desktop.html.erb +3 -2
  106. data/config/initializers/rack_attack.rb +10 -0
  107. data/config/locales/bg.yml +0 -1
  108. data/config/locales/ca-IT.yml +3 -1
  109. data/config/locales/ca.yml +10 -6
  110. data/config/locales/cs.yml +15 -1
  111. data/config/locales/de.yml +99 -3
  112. data/config/locales/en.yml +5 -1
  113. data/config/locales/es-MX.yml +5 -1
  114. data/config/locales/es-PY.yml +5 -1
  115. data/config/locales/es.yml +9 -5
  116. data/config/locales/eu.yml +161 -160
  117. data/config/locales/fi-plain.yml +3 -1
  118. data/config/locales/fi.yml +3 -1
  119. data/config/locales/fr-CA.yml +5 -1
  120. data/config/locales/fr.yml +5 -1
  121. data/config/locales/gl.yml +1485 -33
  122. data/config/locales/hu.yml +0 -1
  123. data/config/locales/ja.yml +3 -1
  124. data/config/locales/pl.yml +0 -1
  125. data/config/locales/pt-BR.yml +0 -1
  126. data/config/locales/ro-RO.yml +0 -1
  127. data/config/locales/sk.yml +2 -1
  128. data/config/locales/sv.yml +68 -12
  129. data/config/locales/tr-TR.yml +0 -2
  130. data/config/routes.rb +11 -2
  131. data/db/migrate/20260909000000_add_failed_attempts_and_locked_at_to_decidim_authorizations.rb +8 -0
  132. data/decidim-core.gemspec +1 -1
  133. data/lib/decidim/api/functions/user_entity_list.rb +1 -0
  134. data/lib/decidim/api/types/user_moderation_type.rb +2 -2
  135. data/lib/decidim/content_parsers/user_parser.rb +1 -1
  136. data/lib/decidim/content_parsers.rb +0 -1
  137. data/lib/decidim/content_renderers/mention_resource_renderer.rb +18 -4
  138. data/lib/decidim/content_renderers/user_renderer.rb +15 -4
  139. data/lib/decidim/core/test/shared_examples/participatory_space_members_page_examples.rb +77 -0
  140. data/lib/decidim/core/test/shared_examples/participatory_space_members_shared_examples.rb +58 -0
  141. data/lib/decidim/core/test/shared_examples/versions_controller_examples.rb +23 -1
  142. data/lib/decidim/core/version.rb +1 -1
  143. data/lib/decidim/core.rb +9 -0
  144. data/lib/decidim/form_builder.rb +9 -1
  145. data/lib/decidim/has_upload_validations.rb +1 -0
  146. data/lib/decidim/legacy_form_builder.rb +4 -0
  147. metadata +12 -7
  148. data/lib/decidim/content_parsers/inline_images_parser.rb +0 -68
  149. data/lib/tasks/upgrade/decidim_active_storage_migration_tasks.rake +0 -79
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c6e0e725b51232026afe0dfeb5bdf73eeaf07f88d346202d4854ef47c093908
4
- data.tar.gz: ee494f4ab056b6f6debfe4590b885178eb39351e516efb9d98f174eab52b4a1e
3
+ metadata.gz: 8290aaa3b5f8596b066ea39214624b798bc2fa4cbc2555ec74be6f0332b9356f
4
+ data.tar.gz: 1a76634eca16d14db59d3f6d61fe7e17ae5d9ca9f44497ca92ae37e09ba2b7f2
5
5
  SHA512:
6
- metadata.gz: d01d66392ab3be5f859ac9791375a83f9d810abd6ee909af6b1e8cf5d833da3a20806e8eed83c05142013d7c9166a12c31fa2ec128b6b4c9a61d8a5e34e7caba
7
- data.tar.gz: '09c6891b8ab26cde54ead3bb2f0876c4cd04c88d3309c1855c3afce7c11297bfb95cf3d07e8dbabafa67a390882503f7b0595f4574f01c90050847392b217d31'
6
+ metadata.gz: 20697b2436b43b7c2b8d239ee8d865bdc25c2b6916f741ad36398134d995dfb8139d1391cef863931a8a0be9b08a53408511f513367c5c3dec5295a428a00cbf
7
+ data.tar.gz: c1b155c89712ddfa2274c99f0965ee2cabc68385e93faf62ed069a39d2d10a87c3911d5b90872b99d44f03aeb0a2a0ddab202be2a330b43af317615d761d52d4
@@ -23,15 +23,11 @@
23
23
  <% end %>
24
24
  </div>
25
25
 
26
- <button class="button button__sm button__text-secondary mt-2" data-controls="panel-view-more-<%= seed %>" aria-expanded="false" onclick="document.querySelector('div[id^=panel-view-more]').toggleAttribute('inert')">
26
+ <button class="button button__sm button__text-secondary mt-2" data-controls="panel-view-more-<%= seed %>" aria-expanded="false">
27
27
  <span>
28
28
  <%= t("view_more", scope: "layouts.decidim.announcements") %>
29
29
  </span>
30
30
  <%= icon "arrow-down-s-line" %>
31
- <span>
32
- <%= t("view_less", scope: "layouts.decidim.announcements") %>
33
- </span>
34
- <%= icon "arrow-up-s-line" %>
35
31
  </button>
36
32
  <% else %>
37
33
  <% if rich_text_processors? %>
@@ -42,12 +38,3 @@
42
38
  <% end %>
43
39
  </div>
44
40
  <% end %>
45
- <script>
46
- const button = document.querySelector('button[data-controls^="panel-view-more"]')
47
- button.addEventListener('keydown', function(e){
48
- // press space or enter
49
- if (e.keyCode === 32 || e.keyCode === 13){
50
- document.querySelector('div[id^=panel-view-more]').toggleAttribute('inert')
51
- }
52
- })
53
- </script>
@@ -11,7 +11,7 @@ module Decidim
11
11
  end
12
12
 
13
13
  def public_followings
14
- @public_followings ||= Kaminari.paginate_array(model.public_users_followings).page(params[:page]).per(20)
14
+ @public_followings ||= model.public_users_followings.page(params[:page]).per(20)
15
15
  end
16
16
 
17
17
  def non_public_followings?
@@ -15,7 +15,7 @@
15
15
  <% end %>
16
16
 
17
17
  <div class="mt-3">
18
- <span class="text-gray-2 capitalize font-semibold">
18
+ <span class="text-gray-2 font-semibold">
19
19
  <%= role_translated %>
20
20
  </span>
21
21
  </div>
@@ -8,7 +8,9 @@
8
8
  <% model.each do |item| %>
9
9
  <li>
10
10
  <%= link_to item[:url], class: "participatory-space__nav-item" do %>
11
- <%= decidim_escape_translated(item[:name]) %>
11
+ <span class="participatory-space__nav-label">
12
+ <%= decidim_escape_translated(item[:name]) %>
13
+ </span>
12
14
  <%= icon "arrow-right-line" %>
13
15
  <% end %>
14
16
  </li>
@@ -1,5 +1,6 @@
1
1
  <%= decidim_modal id: "socialShare", class: "share-modal" do %>
2
2
  <div data-dialog-container>
3
+ <%= icon "share-line" %>
3
4
  <h2 id="dialog-title-socialShare" tabindex="-1" data-dialog-title><%= t("share", scope: "decidim.shared.share_modal") %></h2>
4
5
 
5
6
  <div>
@@ -1,5 +1,6 @@
1
1
  <%= decidim_modal id: "socialShare", class: "share-modal" do %>
2
2
  <div data-dialog-container>
3
+ <%= icon "share-line" %>
3
4
  <h2 id="dialog-title-social-share-modal" tabindex="-1" data-dialog-title><%= t("share", scope: "decidim.shared.share_modal") %></h2>
4
5
 
5
6
  <div>
@@ -1,9 +1,7 @@
1
1
  <%= decidim_modal id: "QRCodeDialog", class: "qr-modal" do %>
2
2
  <div data-dialog-container>
3
- <div data-dialog-title>
4
- <%= icon "qr-code-line" %>
5
- <h2 id="dialog-title-qr-code-dialog" tabindex="-1"><%= t("decidim.share_widget.qr_code") %></h2>
6
- </div>
3
+ <%= icon "qr-code-line" %>
4
+ <h2 id="dialog-title-qr-code-dialog" tabindex="-1" data-dialog-title><%= t("decidim.share_widget.qr_code") %></h2>
7
5
  <div class="content">
8
6
  <div>
9
7
  <% if current_organization.logo.attached? %>
@@ -30,9 +30,9 @@ module Decidim
30
30
  end
31
31
  return broadcast(:invalid) if form.invalid?
32
32
 
33
+ initialize_user
33
34
  transaction do
34
- create_or_find_user
35
- @identity = create_identity
35
+ @identity = existing_identity || create_identity
36
36
  end
37
37
  trigger_omniauth_event
38
38
 
@@ -50,6 +50,21 @@ module Decidim
50
50
 
51
51
  REGEXP_SANITIZER = /[<>?%&\^*#@()\[\]=+:;"{}\\|]/
52
52
 
53
+ def initialize_user
54
+ create_or_find_user
55
+ rescue ActiveRecord::RecordNotUnique
56
+ @create_retries ||= 0
57
+
58
+ # This may happen if the callback endpoint is called several times in a
59
+ # row which some Omniauth providers may allow (e.g. through a double
60
+ # click). This should ensure that the user will not get an error even if
61
+ # the authentication service sent the callback request several times.
62
+ raise if @create_retries >= 2
63
+
64
+ @create_retries += 1
65
+ retry
66
+ end
67
+
53
68
  def create_or_find_user
54
69
  @user = User.find_or_initialize_by(
55
70
  email: verified_email,
@@ -9,6 +9,8 @@ module Decidim
9
9
  include Decidim::OnboardingActionMethods
10
10
 
11
11
  included do
12
+ protected
13
+
12
14
  def after_sign_in_path_for(user)
13
15
  if user.present? && user.blocked?
14
16
  check_user_block_status(user)
@@ -21,6 +23,8 @@ module Decidim
21
23
  end
22
24
  end
23
25
 
26
+ private
27
+
24
28
  # Calling the `stored_location_for` method removes the key, so in order
25
29
  # to check if there is any pending redirect after login I need to call
26
30
  # this method and use the value to set a pending redirect. This is the
@@ -49,6 +49,8 @@ module Decidim
49
49
  # right page.
50
50
  before_action :store_current_location
51
51
 
52
+ protected
53
+
52
54
  def permission_class_chain
53
55
  PermissionsRegistry.chain_for(DeviseControllers)
54
56
  end
@@ -7,6 +7,8 @@ module Decidim
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  included do
10
+ private
11
+
10
12
  def redirect_back(fallback_location:, allow_other_host: true, **args) # rubocop:disable Lint/UnusedMethodArgument
11
13
  super(fallback_location:, allow_other_host: Decidim.allow_open_redirects, **args)
12
14
  end
@@ -11,6 +11,8 @@ module Decidim
11
11
  # this way we can use Rails' form helpers and have automatically checked checkboxes and
12
12
  # radio buttons in the view, for example.
13
13
  class Filter
14
+ private
15
+
14
16
  def initialize(filter)
15
17
  @filter = filter
16
18
  end
@@ -26,6 +26,8 @@ module Decidim
26
26
  @current_user ||= managed_user || real_user
27
27
  end
28
28
 
29
+ private
30
+
29
31
  # Clear the `@real_user` instance variable because otherwise that would be
30
32
  # the return value for any `current_user` calls after the user has already
31
33
  # signed out.
@@ -47,8 +49,6 @@ module Decidim
47
49
  ((impersonation_session_ends_at - Time.current) / 60).round
48
50
  end
49
51
 
50
- private
51
-
52
52
  def current_user_impersonated?
53
53
  current_user && impersonation_log.present?
54
54
  end
@@ -25,16 +25,6 @@ module Decidim
25
25
  I18n.with_locale(locale, &)
26
26
  end
27
27
 
28
- # Adds the current locale to all the URLs generated by url_for so users
29
- # experience a consistent behaviour if they copy or share links.
30
- #
31
- # Returns a Hash.
32
- def default_url_options
33
- return {} if locale_in_script_name?
34
-
35
- { locale: current_locale }
36
- end
37
-
38
28
  # The current locale for the user. Available as a helper for the views.
39
29
  #
40
30
  # Returns a String.
@@ -142,6 +132,18 @@ module Decidim
142
132
  uri.to_s
143
133
  end
144
134
 
135
+ private
136
+
137
+ # Adds the current locale to all the URLs generated by url_for so users
138
+ # experience a consistent behaviour if they copy or share links.
139
+ #
140
+ # Returns a Hash.
141
+ def default_url_options
142
+ return {} if locale_in_script_name?
143
+
144
+ { locale: current_locale }
145
+ end
146
+
145
147
  def locale_in_script_name?
146
148
  script_name = request&.script_name.to_s
147
149
  return false if script_name.blank?
@@ -41,19 +41,11 @@ module Decidim
41
41
  component_settings: try(:component_settings),
42
42
  current_organization: try(:current_organization),
43
43
  current_component: try(:current_component),
44
- share_token: try(:store_share_token)
44
+ share_token: store_share_token
45
45
  }
46
46
  end
47
47
 
48
- def enforce_permission_to(action, subject, extra_context = {})
49
- if Rails.env.development?
50
- Rails.logger.debug "==========="
51
- Rails.logger.debug [permission_scope, action, subject, permission_class_chain].map(&:inspect).join("\n")
52
- Rails.logger.debug "==========="
53
- end
54
-
55
- raise Decidim::ActionForbidden unless allowed_to?(action, subject, extra_context)
56
- end
48
+ public
57
49
 
58
50
  # rubocop:disable Metrics/ParameterLists
59
51
  def allowed_to?(action, subject, extra_context = {}, chain = permission_class_chain, user = current_user, scope = nil)
@@ -76,6 +68,18 @@ module Decidim
76
68
  allowed_to?(action, subject, extra_context, chain, user, :admin)
77
69
  end
78
70
 
71
+ protected
72
+
73
+ def enforce_permission_to(action, subject, extra_context = {})
74
+ if Rails.env.development?
75
+ Rails.logger.debug "==========="
76
+ Rails.logger.debug [permission_scope, action, subject, permission_class_chain].map(&:inspect).join("\n")
77
+ Rails.logger.debug "==========="
78
+ end
79
+
80
+ raise Decidim::ActionForbidden unless allowed_to?(action, subject, extra_context)
81
+ end
82
+
79
83
  def permission_class_chain
80
84
  raise "Please, make this method return an array of permission classes"
81
85
  end
@@ -83,6 +87,14 @@ module Decidim
83
87
  def permission_scope
84
88
  raise "Please, make this method return a symbol"
85
89
  end
90
+
91
+ private
92
+
93
+ def store_share_token
94
+ session[:share_token] = params[:share_token] if params.has_key?(:share_token)
95
+
96
+ session[:share_token].presence
97
+ end
86
98
  end
87
99
  end
88
100
  end
@@ -21,6 +21,8 @@ module Decidim
21
21
  OnboardingManager.new(user).pending_action?
22
22
  end
23
23
 
24
+ private
25
+
24
26
  def store_onboarding_cookie_data!(user)
25
27
  data = onboarding_cookie_data
26
28
  return if data.nil?
@@ -13,9 +13,7 @@ module Decidim
13
13
  helper_method :per_page, :page_offset
14
14
  helper Decidim::PaginateHelper
15
15
 
16
- def paginate(resources)
17
- resources.page(params[:page]).per(per_page)
18
- end
16
+ protected
19
17
 
20
18
  def per_page
21
19
  if OPTIONS.include?(params[:per_page])
@@ -31,6 +29,12 @@ module Decidim
31
29
  def page_offset
32
30
  [params[:page].to_i - 1, 0].max * per_page
33
31
  end
32
+
33
+ private
34
+
35
+ def paginate(resources)
36
+ resources.page(params[:page]).per(per_page)
37
+ end
34
38
  end
35
39
  end
36
40
  end
@@ -8,6 +8,8 @@ module Decidim
8
8
  include Decidim::TranslatableAttributes
9
9
 
10
10
  included do
11
+ private
12
+
11
13
  def append_info_to_payload(payload)
12
14
  super
13
15
  payload[:user_id] = try(:current_user).try(:id)
@@ -11,11 +11,25 @@ module Decidim
11
11
  helper_method :current_version, :versioned_resource
12
12
 
13
13
  def show
14
+ enforce_permission_to(*versioned_resource_permission)
15
+
14
16
  raise ActionController::RoutingError, "Not found" unless current_version
15
17
  end
16
18
 
17
19
  private
18
20
 
21
+ # The versions must honour the same `:read` permission as their resource,
22
+ # so a resource that is hidden, private, deleted or unpublished (and
23
+ # therefore cannot be read on its own) cannot be reached through its
24
+ # versions either.
25
+ def versioned_resource_permission
26
+ resource = versioned_resource
27
+ raise ActionController::RoutingError, "Not found" unless resource
28
+
29
+ subject = resource.model_name.element.to_sym
30
+ [:read, subject, { subject => resource }]
31
+ end
32
+
19
33
  # Overwrite this method in your controller to define how to find the
20
34
  # versioned resource.
21
35
  def versioned_resource
@@ -59,12 +59,6 @@ module Decidim
59
59
 
60
60
  skip_before_action :disable_http_caching, unless: :user_signed_in?
61
61
 
62
- def store_share_token
63
- session[:share_token] = params[:share_token] if params.has_key?(:share_token)
64
-
65
- session[:share_token].presence
66
- end
67
-
68
62
  private
69
63
 
70
64
  def allow_browser(**); end
@@ -6,6 +6,8 @@ module Decidim
6
6
  layout false
7
7
 
8
8
  def show
9
+ enforce_permission_to :read, :authorization
10
+
9
11
  store_onboarding_cookie_data!(current_user)
10
12
  end
11
13
 
@@ -67,6 +67,8 @@ module Decidim
67
67
  raise ActionController::RoutingError, "Not Found" unless current_user_can_visit_space?
68
68
  end
69
69
 
70
+ protected
71
+
70
72
  def set_breadcrumb_items
71
73
  context_breadcrumb_items << add_current_component
72
74
  context_breadcrumb_items << add_parent_breadcrumb_item
@@ -14,6 +14,8 @@ module Decidim
14
14
  before_action :check_sign_in_enabled
15
15
 
16
16
  def change_password
17
+ enforce_permission_to(:update, :user, current_user:)
18
+
17
19
  self.resource = current_user
18
20
  @send_path = apply_password_path
19
21
 
@@ -22,6 +24,8 @@ module Decidim
22
24
  end
23
25
 
24
26
  def apply_password
27
+ enforce_permission_to(:update, :user, current_user:)
28
+
25
29
  self.resource = current_user
26
30
  @send_path = apply_password_path
27
31
 
@@ -43,6 +47,10 @@ module Decidim
43
47
 
44
48
  private
45
49
 
50
+ def user_has_no_permission_path
51
+ new_user_session_path
52
+ end
53
+
46
54
  def check_sign_in_enabled
47
55
  redirect_to new_user_session_path unless current_organization.sign_in_enabled?
48
56
  end
@@ -12,6 +12,7 @@ module Decidim
12
12
  class FaviconController < ::DecidimController
13
13
  include ActionController::DataStreaming # For Rails 7, check out `ActiveStorage::Streaming`.
14
14
  include NeedsOrganization
15
+ include NeedsPermission
15
16
 
16
17
  skip_before_action :verify_authenticity_token, :verify_organization
17
18
  skip_after_action :verify_same_origin_request
@@ -52,5 +53,13 @@ module Decidim
52
53
 
53
54
  @favicon_blob ||= current_organization.favicon_ico&.blob
54
55
  end
56
+
57
+ def permission_class_chain
58
+ [Decidim::Permissions]
59
+ end
60
+
61
+ def permission_scope
62
+ :public
63
+ end
55
64
  end
56
65
  end
@@ -6,6 +6,8 @@ module Decidim
6
6
  layout false
7
7
 
8
8
  def show
9
+ enforce_permission_to :read, :authorization
10
+
9
11
  render template: "decidim/authorization_modals/show"
10
12
  end
11
13
 
@@ -6,6 +6,8 @@ module Decidim
6
6
  include HasSpecificBreadcrumb
7
7
 
8
8
  def index
9
+ enforce_permission_to :read, :badges
10
+
9
11
  @badges = Decidim::Gamification.badges.sort_by(&:name)
10
12
  end
11
13
 
@@ -3,6 +3,9 @@
3
3
  module Decidim
4
4
  class HomepageController < Decidim::ApplicationController
5
5
  skip_before_action :store_current_location
6
- def show; end
6
+
7
+ def show
8
+ enforce_permission_to :read, :homepage
9
+ end
7
10
  end
8
11
  end
@@ -9,7 +9,7 @@ module Decidim
9
9
  helper_method :like_button
10
10
  # we need to declare with +helper+ to be able to call :render_like_identity from the views
11
11
  helper Decidim::LikeableHelper
12
- helper_method :resource
12
+ helper_method :resource, :current_component
13
13
 
14
14
  before_action :authenticate_user!
15
15
 
@@ -15,6 +15,8 @@ module Decidim
15
15
  rescue_from URI::InvalidURIError, with: :modal
16
16
 
17
17
  def new
18
+ enforce_permission_to :read, :link
19
+
18
20
  headers["X-Robots-Tag"] = "none"
19
21
  headers["Link"] = %(<#{url_for}>; rel="canonical")
20
22
  end
@@ -4,6 +4,8 @@ module Decidim
4
4
  # A controller to serve the manifest file for PWA
5
5
  class ManifestsController < Decidim::ApplicationController
6
6
  def show
7
+ enforce_permission_to :read, :manifest
8
+
7
9
  organization_presenter = OrganizationPresenter.new(current_organization)
8
10
  render layout: false, locals: { organization_params: organization_presenter }, content_type: "application/manifest+json"
9
11
  end
@@ -43,10 +43,7 @@ module Decidim
43
43
 
44
44
  StartConversation.call(@form) do
45
45
  on(:ok) do |conversation|
46
- render action: :create, locals: {
47
- conversation:,
48
- form: MessageForm.new
49
- }
46
+ render action: :create, locals: { conversation: }
50
47
  end
51
48
 
52
49
  on(:invalid) do |messages|
@@ -96,6 +93,15 @@ module Decidim
96
93
 
97
94
  def check_multiple
98
95
  @form = form(ConversationForm).from_params(params, sender: current_user)
96
+
97
+ conversation = conversation_between_multiple(@form.recipient.to_a.prepend(current_user))
98
+
99
+ if conversation
100
+ enforce_permission_to :read, :conversation, conversation:
101
+ else
102
+ enforce_permission_to :create, :conversation, conversation: new_conversation(@form.recipient)
103
+ end
104
+
99
105
  redirect_link = current_or_new_conversation_path_with_multiple(@form.recipient, nickname: params[:nickname])
100
106
  redirect_to redirect_link
101
107
  end
@@ -11,6 +11,8 @@ module Decidim
11
11
  helper_method :newsletter
12
12
 
13
13
  def show
14
+ enforce_permission_to :read, :newsletter
15
+
14
16
  @user = current_user
15
17
  @organization = current_organization
16
18
 
@@ -20,6 +22,8 @@ module Decidim
20
22
  end
21
23
 
22
24
  def unsubscribe
25
+ enforce_permission_to :unsubscribe, :newsletter
26
+
23
27
  encryptor = Decidim::NewsletterEncryptor
24
28
 
25
29
  decrypted_string = encryptor.sent_at_decrypted(params[:u])
@@ -6,11 +6,15 @@ module Decidim
6
6
  rescue_from Decidim::NotificationsSubscriptionsPersistor::UnsupportedPushSubscriptionEndpointError, with: :unsupported_browser
7
7
 
8
8
  def create
9
+ enforce_permission_to(:update, :user, current_user:)
10
+
9
11
  Decidim::NotificationsSubscriptionsPersistor.new(current_user).add_subscription(params)
10
12
  head :ok
11
13
  end
12
14
 
13
15
  def destroy
16
+ enforce_permission_to(:update, :user, current_user:)
17
+
14
18
  Decidim::NotificationsSubscriptionsPersistor.new(current_user).delete_subscription(params[:auth])
15
19
  head :ok
16
20
  end
@@ -4,7 +4,11 @@ module Decidim
4
4
  class OfflineController < Decidim::ApplicationController
5
5
  include HasSpecificBreadcrumb
6
6
 
7
- def show; end
7
+ def show
8
+ enforce_permission_to :read, :offline
9
+ end
10
+
11
+ private
8
12
 
9
13
  def breadcrumb_item
10
14
  {
@@ -4,9 +4,13 @@ module Decidim
4
4
  class OpenDataController < Decidim::ApplicationController
5
5
  helper_method :open_data_component_manifests, :open_data_participatory_space_manifests, :open_data_core_manifests
6
6
 
7
- def index; end
7
+ def index
8
+ enforce_permission_to :read, :open_data
9
+ end
8
10
 
9
11
  def download
12
+ enforce_permission_to :read, :open_data
13
+
10
14
  resource = params[:resource] || nil
11
15
 
12
16
  if open_data_file_for_resource(resource)
@@ -10,6 +10,10 @@ module Decidim
10
10
 
11
11
  before_action :legacy_redirect, :set_default_request_format
12
12
 
13
+ # Included after the legacy redirect so its before_action does not look the
14
+ # page up (and 404) before the redirect happens.
15
+ include HasSpecificBreadcrumb
16
+
13
17
  def index
14
18
  enforce_permission_to :read, :public_page
15
19
  @topics = StaticPageTopic.where(organization: current_organization)
@@ -17,14 +21,38 @@ module Decidim
17
21
  end
18
22
 
19
23
  def show
20
- @page = current_organization.static_pages.find_by!(slug: params[:id])
21
- enforce_permission_to :read, :public_page, page: @page
22
- @topic = @page.topic
24
+ enforce_permission_to :read, :public_page, page:
25
+
26
+ @topic = page.topic
23
27
  @pages = @topic&.pages
24
28
  end
25
29
 
26
30
  private
27
31
 
32
+ def page
33
+ @page ||= current_organization.static_pages.find_by!(slug: params.expect(:id))
34
+ end
35
+
36
+ def breadcrumb_item
37
+ items = [
38
+ {
39
+ label: t("decidim.pages.index.title"),
40
+ active: action_name == "index",
41
+ url: pages_path
42
+ }
43
+ ]
44
+
45
+ if action_name == "show"
46
+ items << {
47
+ label: page.title,
48
+ active: true,
49
+ url: page_path(page)
50
+ }
51
+ end
52
+
53
+ items
54
+ end
55
+
28
56
  def legacy_redirect
29
57
  return redirect_to decidim.page_path("terms-of-service") if params[:id] == "terms-and-conditions"
30
58
  end