decidim-core 0.18.1 → 0.19.0

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

Potentially problematic release.


This version of decidim-core might be problematic. Click here for more details.

Files changed (275) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/decidim_core_manifest.js +3 -0
  3. data/app/assets/javascripts/decidim/social_share.js +2 -0
  4. data/app/assets/stylesheets/decidim/extras/_social_share.css.scss +36 -0
  5. data/app/assets/stylesheets/decidim/modules/_input-gallery.scss +24 -0
  6. data/app/assets/stylesheets/decidim/modules/_navbar.scss +1 -1
  7. data/app/cells/decidim/activities_cell.rb +13 -8
  8. data/app/cells/decidim/activity_cell.rb +19 -5
  9. data/app/cells/decidim/address/details.erb +2 -2
  10. data/app/cells/decidim/amendable/amenders_list/show.erb +1 -1
  11. data/app/cells/decidim/amendable/amenders_list_cell.rb +5 -1
  12. data/app/cells/decidim/amendable/announcement_cell.rb +22 -9
  13. data/app/cells/decidim/amendable/wizard_step_form_cell.rb +121 -0
  14. data/app/cells/decidim/announcement_cell.rb +1 -0
  15. data/app/cells/decidim/author_cell.rb +7 -0
  16. data/app/cells/decidim/card_m_cell.rb +3 -1
  17. data/app/cells/decidim/coauthorships_cell.rb +3 -1
  18. data/app/cells/decidim/collapsible_authors_cell.rb +1 -0
  19. data/app/cells/decidim/collapsible_list_cell.rb +1 -0
  20. data/app/cells/decidim/content_blocks/highlighted_content_banner_cell.rb +1 -0
  21. data/app/cells/decidim/content_blocks/last_activity_cell.rb +3 -2
  22. data/app/cells/decidim/content_blocks/metrics_cell.rb +1 -0
  23. data/app/cells/decidim/content_blocks/stats_cell.rb +1 -0
  24. data/app/cells/decidim/content_blocks/sub_hero_cell.rb +1 -0
  25. data/app/cells/decidim/diff_cell.rb +1 -1
  26. data/app/cells/decidim/fingerprint/show.erb +1 -1
  27. data/app/cells/decidim/follow_button_cell.rb +3 -0
  28. data/app/cells/decidim/members_cell.rb +1 -0
  29. data/app/cells/decidim/notifications/show.erb +1 -1
  30. data/app/cells/decidim/profile_cell.rb +1 -0
  31. data/app/cells/decidim/profile_sidebar_cell.rb +4 -0
  32. data/app/cells/decidim/search_results_cell.rb +1 -0
  33. data/app/cells/decidim/search_results_section/show.erb +1 -1
  34. data/app/cells/decidim/tos_page_cell.rb +1 -0
  35. data/app/cells/decidim/user_group_pending_invitations_list_cell.rb +1 -0
  36. data/app/cells/decidim/user_group_pending_requests_list_cell.rb +1 -0
  37. data/app/cells/decidim/wizard_step_form/wizard_aside.erb +14 -0
  38. data/app/cells/decidim/wizard_step_form/wizard_header.erb +18 -0
  39. data/app/cells/decidim/wizard_step_form_cell.rb +112 -0
  40. data/app/commands/decidim/amendable/accept.rb +1 -1
  41. data/app/commands/decidim/amendable/create_draft.rb +70 -0
  42. data/app/commands/decidim/amendable/destroy_draft.rb +40 -0
  43. data/app/commands/decidim/amendable/promote.rb +13 -11
  44. data/app/commands/decidim/amendable/publish_draft.rb +76 -0
  45. data/app/commands/decidim/amendable/update_draft.rb +54 -0
  46. data/app/commands/decidim/amendable/withdraw.rb +31 -15
  47. data/app/commands/decidim/create_follow.rb +1 -0
  48. data/app/commands/decidim/create_omniauth_registration.rb +22 -4
  49. data/app/commands/decidim/create_registration.rb +5 -0
  50. data/app/commands/decidim/delete_follow.rb +1 -0
  51. data/app/commands/decidim/search.rb +1 -0
  52. data/app/controllers/concerns/decidim/action_authorization.rb +2 -0
  53. data/app/controllers/concerns/decidim/amendments_controller.rb +148 -28
  54. data/app/controllers/concerns/decidim/devise_controllers.rb +3 -2
  55. data/app/controllers/concerns/decidim/force_authentication.rb +38 -0
  56. data/app/controllers/concerns/decidim/impersonate_users.rb +1 -0
  57. data/app/controllers/concerns/decidim/locale_switcher.rb +44 -17
  58. data/app/controllers/concerns/decidim/needs_tos_accepted.rb +8 -0
  59. data/app/controllers/concerns/decidim/orderable.rb +36 -0
  60. data/app/controllers/concerns/decidim/participatory_space_context.rb +2 -0
  61. data/app/controllers/concerns/decidim/safe_redirect.rb +24 -0
  62. data/app/controllers/decidim/application_controller.rb +19 -2
  63. data/app/controllers/decidim/devise/confirmations_controller.rb +6 -0
  64. data/app/controllers/decidim/devise/invitations_controller.rb +8 -4
  65. data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +4 -1
  66. data/app/controllers/decidim/errors_controller.rb +3 -0
  67. data/app/controllers/decidim/follows_controller.rb +2 -2
  68. data/app/controllers/decidim/messaging/conversations_controller.rb +2 -2
  69. data/app/controllers/decidim/profiles_controller.rb +4 -1
  70. data/app/controllers/decidim/scopes_controller.rb +16 -4
  71. data/app/events/decidim/amendable/amendment_base_event.rb +4 -0
  72. data/app/forms/decidim/account_form.rb +1 -1
  73. data/app/forms/decidim/amendable/create_form.rb +3 -19
  74. data/app/forms/decidim/amendable/edit_form.rb +22 -0
  75. data/app/forms/decidim/amendable/form.rb +42 -20
  76. data/app/forms/decidim/amendable/promote_form.rb +4 -7
  77. data/app/forms/decidim/amendable/publish_form.rb +21 -0
  78. data/app/forms/decidim/amendable/reject_form.rb +1 -1
  79. data/app/forms/decidim/amendable/review_form.rb +9 -4
  80. data/app/forms/decidim/invite_user_form.rb +1 -0
  81. data/app/forms/decidim/notifications_settings_form.rb +1 -0
  82. data/app/forms/decidim/registration_form.rb +4 -3
  83. data/app/forms/decidim/user_group_form.rb +1 -0
  84. data/app/forms/decidim/user_interests_form.rb +1 -0
  85. data/app/helpers/decidim/amendments_helper.rb +33 -19
  86. data/app/helpers/decidim/cells_helper.rb +2 -0
  87. data/app/helpers/decidim/layout_helper.rb +1 -0
  88. data/app/helpers/decidim/map_helper.rb +1 -1
  89. data/app/helpers/decidim/meta_tags_helper.rb +1 -0
  90. data/app/helpers/decidim/resource_reference_helper.rb +1 -0
  91. data/app/jobs/decidim/event_publisher_job.rb +60 -0
  92. data/app/jobs/decidim/metric_job.rb +1 -0
  93. data/app/models/decidim/action_log.rb +12 -0
  94. data/app/models/decidim/amendment.rb +31 -2
  95. data/app/models/decidim/attachment.rb +2 -0
  96. data/app/models/decidim/authorization.rb +1 -0
  97. data/app/models/decidim/category.rb +1 -0
  98. data/app/models/decidim/component.rb +7 -0
  99. data/app/models/decidim/content_block.rb +1 -0
  100. data/app/models/decidim/follow.rb +3 -0
  101. data/app/models/decidim/identity.rb +1 -0
  102. data/app/models/decidim/impersonation_log.rb +2 -0
  103. data/app/models/decidim/newsletter.rb +1 -0
  104. data/app/models/decidim/participatory_process_user_role.rb +1 -0
  105. data/app/models/decidim/participatory_space_private_user.rb +1 -0
  106. data/app/models/decidim/permission_action.rb +2 -0
  107. data/app/models/decidim/report.rb +1 -0
  108. data/app/models/decidim/scope.rb +1 -0
  109. data/app/models/decidim/searchable_resource.rb +1 -1
  110. data/app/models/decidim/static_page.rb +1 -0
  111. data/app/models/decidim/user.rb +2 -0
  112. data/app/permissions/decidim/permissions.rb +18 -14
  113. data/app/permissions/decidim/user_manager_permissions.rb +9 -2
  114. data/app/presenters/decidim/admin_log/organization_presenter.rb +1 -0
  115. data/app/presenters/decidim/admin_log/participatory_space_private_user_presenter.rb +1 -1
  116. data/app/presenters/decidim/admin_log/user_presenter.rb +1 -1
  117. data/app/presenters/decidim/hashtag_presenter.rb +1 -1
  118. data/app/presenters/decidim/log/base_presenter.rb +1 -0
  119. data/app/presenters/decidim/log/diff_presenter.rb +1 -1
  120. data/app/presenters/decidim/log/value_types/area_presenter.rb +1 -0
  121. data/app/presenters/decidim/log/value_types/area_type_presenter.rb +1 -0
  122. data/app/presenters/decidim/log/value_types/currency_presenter.rb +1 -0
  123. data/app/presenters/decidim/log/value_types/date_presenter.rb +1 -0
  124. data/app/presenters/decidim/log/value_types/locale_presenter.rb +1 -0
  125. data/app/presenters/decidim/log/value_types/percentage_presenter.rb +1 -0
  126. data/app/presenters/decidim/log/value_types/scope_presenter.rb +1 -0
  127. data/app/presenters/decidim/log/value_types/scope_type_presenter.rb +1 -0
  128. data/app/presenters/decidim/metric_charts_presenter.rb +1 -0
  129. data/app/presenters/decidim/metric_object_presenter.rb +4 -0
  130. data/app/queries/decidim/metric_manage.rb +3 -0
  131. data/app/queries/decidim/metric_measure.rb +1 -0
  132. data/app/queries/decidim/metrics/followers_metric_manage.rb +3 -0
  133. data/app/queries/decidim/metrics/participants_metric_manage.rb +4 -0
  134. data/app/queries/decidim/similar_emendations.rb +56 -0
  135. data/app/resolvers/decidim/core/metric_resolver.rb +1 -0
  136. data/app/services/decidim/action_authorizer.rb +1 -0
  137. data/app/services/decidim/action_logger.rb +1 -0
  138. data/app/services/decidim/activity_search.rb +1 -0
  139. data/app/services/decidim/email_notification_generator.rb +4 -0
  140. data/app/services/decidim/notification_generator.rb +2 -0
  141. data/app/services/decidim/notification_generator_for_recipient.rb +0 -1
  142. data/app/services/decidim/resource_search.rb +1 -1
  143. data/app/services/decidim/traceability.rb +1 -0
  144. data/app/uploaders/decidim/application_uploader.rb +1 -0
  145. data/app/uploaders/decidim/attachment_uploader.rb +16 -0
  146. data/app/uploaders/decidim/avatar_uploader.rb +0 -2
  147. data/app/uploaders/decidim/data_portability_uploader.rb +1 -0
  148. data/app/uploaders/decidim/homepage_image_uploader.rb +0 -2
  149. data/app/uploaders/decidim/image_uploader.rb +15 -1
  150. data/app/uploaders/decidim/oauth_application_logo_uploader.rb +0 -1
  151. data/app/uploaders/decidim/official_image_footer_uploader.rb +0 -1
  152. data/app/uploaders/decidim/official_image_header_uploader.rb +0 -1
  153. data/app/uploaders/decidim/open_data_uploader.rb +1 -0
  154. data/app/validators/etiquette_validator.rb +5 -0
  155. data/app/views/decidim/account/delete.html.erb +2 -2
  156. data/app/views/decidim/account/show.html.erb +1 -1
  157. data/app/views/decidim/amendments/_edit_form_fields.html.erb +16 -13
  158. data/app/views/decidim/amendments/_similar_emendation.html.erb +24 -0
  159. data/app/views/decidim/amendments/compare_draft.html.erb +21 -0
  160. data/app/views/decidim/amendments/edit_draft.html.erb +31 -0
  161. data/app/views/decidim/amendments/new.html.erb +5 -17
  162. data/app/views/decidim/amendments/preview_draft.html.erb +32 -0
  163. data/app/views/decidim/amendments/review.html.erb +5 -3
  164. data/app/views/decidim/application/_document.html.erb +1 -1
  165. data/app/views/decidim/application/_photos.html.erb +1 -1
  166. data/app/views/decidim/data_portability/show.html.erb +1 -1
  167. data/app/views/decidim/devise/invitations/edit.html.erb +2 -2
  168. data/app/views/decidim/devise/sessions/new.html.erb +1 -1
  169. data/app/views/decidim/doorkeeper/authorizations/new.html.erb +3 -3
  170. data/app/views/decidim/export_mailer/data_portability_export.html.erb +1 -1
  171. data/app/views/decidim/searches/index.js.erb +6 -0
  172. data/app/views/decidim/shared/_address_details.html.erb +2 -2
  173. data/app/views/decidim/shared/_embed_modal.html.erb +1 -1
  174. data/app/views/decidim/shared/_share_modal.html.erb +7 -4
  175. data/app/views/layouts/decidim/_application.html.erb +0 -1
  176. data/app/views/layouts/decidim/_head.html.erb +13 -12
  177. data/app/views/layouts/decidim/_logo.html.erb +1 -1
  178. data/app/views/layouts/decidim/_social_media_links.html.erb +5 -5
  179. data/app/views/layouts/decidim/_user_menu.html.erb +1 -1
  180. data/app/views/layouts/decidim/_wrapper.html.erb +2 -2
  181. data/app/views/layouts/decidim/mailer.html.erb +2 -2
  182. data/config/locales/ar.yml +27 -17
  183. data/config/locales/ca.yml +79 -15
  184. data/config/locales/cs.yml +73 -14
  185. data/config/locales/de.yml +62 -12
  186. data/config/locales/en.yml +80 -16
  187. data/config/locales/eo-UY.yml +16 -0
  188. data/config/locales/es-MX.yml +73 -11
  189. data/config/locales/es-PY.yml +73 -11
  190. data/config/locales/es.yml +79 -15
  191. data/config/locales/eu.yml +6 -13
  192. data/config/locales/fi-plain.yml +75 -11
  193. data/config/locales/fi.yml +80 -16
  194. data/config/locales/fr.yml +70 -16
  195. data/config/locales/gl.yml +6 -13
  196. data/config/locales/hu.yml +80 -17
  197. data/config/locales/id-ID.yml +6 -12
  198. data/config/locales/it.yml +56 -14
  199. data/config/locales/nl.yml +76 -12
  200. data/config/locales/no.yml +11 -2
  201. data/config/locales/pl.yml +6 -15
  202. data/config/locales/pt-BR.yml +6 -13
  203. data/config/locales/pt.yml +6 -13
  204. data/config/locales/ru.yml +7 -2
  205. data/config/locales/sv.yml +34 -18
  206. data/config/locales/tr-TR.yml +15 -12
  207. data/config/locales/uk.yml +7 -2
  208. data/config/routes.rb +7 -0
  209. data/db/migrate/20180226140756_add_version_to_action_logs.rb +1 -0
  210. data/db/migrate/20180305132906_rename_features_to_components.rb +1 -0
  211. data/db/migrate/20190412131728_fix_user_names.rb +1 -1
  212. data/db/migrate/20190610093742_add_force_users_to_authenticate_before_access_organization.rb +10 -0
  213. data/db/migrate/20190618075906_add_confidential_to_doorkeeper_application.rb +13 -0
  214. data/db/migrate/{20190925091507_add_uniq_index_to_decidim_metrics.rb → 20190829092826_add_uniq_index_to_decidim_metrics.rb} +0 -0
  215. data/lib/decidim/amendable.rb +87 -13
  216. data/lib/decidim/attributes/localized_date.rb +5 -0
  217. data/lib/decidim/attributes/time_with_zone.rb +5 -0
  218. data/lib/decidim/authorable.rb +3 -0
  219. data/lib/decidim/authorization_form_builder.rb +2 -2
  220. data/lib/decidim/component_manifest.rb +2 -0
  221. data/lib/decidim/content_parsers.rb +2 -0
  222. data/lib/decidim/content_parsers/hashtag_parser.rb +1 -1
  223. data/lib/decidim/content_parsers/link_parser.rb +10 -0
  224. data/lib/decidim/content_parsers/newline_parser.rb +20 -0
  225. data/lib/decidim/content_parsers/user_parser.rb +1 -1
  226. data/lib/decidim/content_processor.rb +2 -0
  227. data/lib/decidim/content_renderers.rb +1 -0
  228. data/lib/decidim/content_renderers/hashtag_renderer.rb +1 -1
  229. data/lib/decidim/content_renderers/link_renderer.rb +24 -0
  230. data/lib/decidim/content_renderers/user_renderer.rb +2 -2
  231. data/lib/decidim/core.rb +11 -0
  232. data/lib/decidim/core/engine.rb +2 -28
  233. data/lib/decidim/core/test.rb +4 -1
  234. data/lib/decidim/core/test/factories.rb +35 -8
  235. data/lib/decidim/core/test/shared_examples/amendable/create_amendment_draft_examples.rb +50 -0
  236. data/lib/decidim/core/test/shared_examples/amendable/destroy_amendment_draft_examples.rb +39 -0
  237. data/lib/decidim/core/test/shared_examples/amendable/promote_amendment_examples.rb +27 -3
  238. data/lib/decidim/core/test/shared_examples/amendable/{create_amendment_examples.rb → publish_amendment_draft_examples.rb} +26 -17
  239. data/lib/decidim/core/test/shared_examples/amendable/update_amendment_draft_examples.rb +42 -0
  240. data/lib/decidim/core/test/shared_examples/amendable/withdraw_amendment_examples.rb +19 -11
  241. data/lib/decidim/core/test/shared_examples/has_attachment_collections.rb +1 -1
  242. data/lib/decidim/core/test/shared_examples/has_attachments.rb +1 -1
  243. data/lib/decidim/core/test/shared_examples/simple_event.rb +4 -0
  244. data/lib/decidim/core/version.rb +1 -1
  245. data/lib/decidim/data_portability_file_zipper.rb +3 -0
  246. data/lib/decidim/events/author_event.rb +1 -0
  247. data/lib/decidim/events/base_event.rb +12 -22
  248. data/lib/decidim/events/coauthor_event.rb +1 -0
  249. data/lib/decidim/events/simple_event.rb +3 -0
  250. data/lib/decidim/exporters/csv.rb +1 -0
  251. data/lib/decidim/fingerprintable.rb +1 -0
  252. data/lib/decidim/followable.rb +8 -0
  253. data/lib/decidim/form_builder.rb +24 -3
  254. data/lib/decidim/gamification.rb +4 -0
  255. data/lib/decidim/gamification/badge_status.rb +1 -0
  256. data/lib/decidim/has_category.rb +2 -0
  257. data/lib/decidim/has_component.rb +2 -7
  258. data/lib/decidim/has_private_users.rb +8 -1
  259. data/lib/decidim/has_settings.rb +12 -8
  260. data/lib/decidim/hashtaggable.rb +4 -0
  261. data/lib/decidim/metric_operation_manifest.rb +1 -0
  262. data/lib/decidim/nicknamizable.rb +1 -0
  263. data/lib/decidim/participable.rb +1 -0
  264. data/lib/decidim/participatory_space_resourceable.rb +1 -0
  265. data/lib/decidim/randomable.rb +20 -0
  266. data/lib/decidim/search_resource_fields_mapper.rb +2 -0
  267. data/lib/decidim/searchable.rb +2 -0
  268. data/lib/decidim/settings_manifest.rb +10 -1
  269. data/lib/decidim/stats_registry.rb +1 -0
  270. data/lib/decidim/view_model.rb +1 -1
  271. data/lib/tasks/decidim_data_portability_tasks.rake +1 -0
  272. data/lib/tasks/decidim_metrics_tasks.rake +2 -0
  273. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.no.js +12 -12
  274. metadata +140 -82
  275. data/app/commands/decidim/amendable/create.rb +0 -80
@@ -17,6 +17,7 @@ module Decidim
17
17
  include Decidim::LocaleSwitcher
18
18
  include ImpersonateUsers
19
19
  include NeedsPermission
20
+ include Decidim::SafeRedirect
20
21
 
21
22
  helper Decidim::TranslationsHelper
22
23
  helper Decidim::MetaTagsHelper
@@ -43,9 +44,9 @@ module Decidim
43
44
  end
44
45
 
45
46
  def store_current_location
46
- return if params[:redirect_url].blank? || !request.format.html?
47
+ return if redirect_url.blank? || !request.format.html?
47
48
 
48
- store_location_for(:user, params[:redirect_url])
49
+ store_location_for(:user, redirect_url)
49
50
  end
50
51
  end
51
52
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # Shared behaviour for force_users_to_authenticate_before_access_organization
5
+ module ForceAuthentication
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ before_action :ensure_authenticated!, unless: :allow_unauthorized_path?
10
+ end
11
+
12
+ private
13
+
14
+ # For Devise helper functions, see:
15
+ # https://github.com/plataformatec/devise#getting-started
16
+ #
17
+ # Breaks the request lifecycle, if user is not authenticated.
18
+ # Otherwise returns.
19
+ def ensure_authenticated!
20
+ return true unless current_organization.force_users_to_authenticate_before_access_organization
21
+
22
+ # Next stop: Let's check whether auth is ok
23
+ unless user_signed_in?
24
+ flash[:warning] = t("actions.login_before_access", scope: "decidim.core")
25
+ return redirect_to decidim.new_user_session_path
26
+ end
27
+ end
28
+
29
+ # Check for all paths that should be allowed even if the user is not yet
30
+ # authorized
31
+ def allow_unauthorized_path?
32
+ # Changing the locale
33
+ return true if %r{^\/locale}.match?(request.path) || %r{^\/cookies}.match?(request.path)
34
+
35
+ false
36
+ end
37
+ end
38
+ end
@@ -36,6 +36,7 @@ module Decidim
36
36
  # Returns the managed user impersonated by an admin if exists
37
37
  def managed_user
38
38
  return unless can_impersonate_users?
39
+
39
40
  impersonation_log&.user
40
41
  end
41
42
 
@@ -10,19 +10,18 @@ module Decidim
10
10
  included do
11
11
  around_action :switch_locale
12
12
  helper_method :current_locale, :available_locales, :default_locale
13
- before_action :set_locale
14
13
 
15
14
  # Sets the locale for the current session.
16
- #
15
+ # Saves current locale in a session variable in case some links are locale-orphaned
17
16
  # Returns nothing.
18
17
  def switch_locale(&action)
19
- locale = if params["locale"]
20
- params["locale"]
21
- elsif current_user && current_user.locale.present?
22
- current_user.locale
23
- end
24
-
25
- I18n.with_locale(available_locales.include?(locale) ? locale : default_locale, &action)
18
+ locale = detect_locale
19
+ if available_locales.include?(locale)
20
+ session[:user_locale] = locale
21
+ else
22
+ locale = default_locale
23
+ end
24
+ I18n.with_locale(locale, &action)
26
25
  end
27
26
 
28
27
  # Adds the current locale to all the URLs generated by url_for so users
@@ -57,17 +56,45 @@ module Decidim
57
56
  @default_locale ||= (current_organization || Decidim).public_send(:default_locale)
58
57
  end
59
58
 
60
- # Save current locale in session variable
61
- # to prevent unnecessary redirects
62
- def set_locale
63
- session[:user_locale] = params[:locale] if params[:locale].present?
64
- locale = session[:user_locale] || extract_locale_from_accept_language_header
65
- I18n.locale = available_locales.include?(locale) ? locale : I18n.default_locale
59
+ # Detects the locale priority: query string, user saved, session, browser
60
+ def detect_locale
61
+ if params[:locale].present?
62
+ params[:locale]
63
+ elsif current_user && current_user.locale.present?
64
+ current_user.locale
65
+ elsif session[:user_locale].present?
66
+ session[:user_locale]
67
+ else
68
+ extract_locale_from_accept_language_header
69
+ end
66
70
  end
67
71
 
72
+ # Finds a suitable language or returns nil
73
+ # Follows the RFC 2616 rules with this particularities:
74
+ # if no language matches, goes for the 2 chars prefixes
75
+ # i.e.: pt-BR is available locale but user requests pt, then pt-BR will be served
76
+ # pt is available locale but user requests pt-BR, then pt will be served
68
77
  def extract_locale_from_accept_language_header
69
- lang = request.env["HTTP_ACCEPT_LANGUAGE"] || I18n.locale.to_s
70
- lang.scan(/\A^[a-z]{2}\z/).first
78
+ return nil unless request.env["HTTP_ACCEPT_LANGUAGE"]
79
+
80
+ accept_langs = request.env["HTTP_ACCEPT_LANGUAGE"].gsub(/[^a-z0-9\-;,=.]/i, "")
81
+
82
+ langs_and_qs = accept_langs.split(",").each_with_index.map do |l, i|
83
+ l += ";q=1.0" unless l =~ /;q=\d+(?:\.\d+)?$/
84
+ parts = l.split(";q=")
85
+ [parts[0], parts[1].to_f - (i.to_f / 1000)]
86
+ end
87
+ langs_and_qs = langs_and_qs.sort_by { |(_l, q)| q }.reverse
88
+ lang = langs_and_qs.detect do |(locale, _q)|
89
+ locale == "*" || available_locales.map(&:to_s).include?(locale.to_s)
90
+ end
91
+
92
+ lang &&= lang.first
93
+ # if no language detected go for RFC 2616 non-compliant (check prefixes)
94
+ lang ||= available_locales.detect do |available|
95
+ langs_and_qs.any? { |locale, _q| locale.to_s[0..1] == available.to_s[0..1] }
96
+ end
97
+ lang == "*" ? nil : lang
71
98
  end
72
99
  end
73
100
  end
@@ -13,6 +13,7 @@ module Decidim
13
13
  private
14
14
 
15
15
  def tos_accepted_by_user
16
+ return true unless request.format.html?
16
17
  return true unless current_user
17
18
  return if current_user.tos_accepted?
18
19
  return if permitted_paths?
@@ -40,6 +41,13 @@ module Decidim
40
41
  end
41
42
 
42
43
  def redirect_to_tos
44
+ # Store the location where the user needs to be redirected to after the
45
+ # TOS is agreed.
46
+ store_location_for(
47
+ current_user,
48
+ stored_location_for(current_user) || request.path
49
+ )
50
+
43
51
  flash[:notice] = flash[:notice] if flash[:notice]
44
52
  flash[:secondary] = t("required_review.alert", scope: "decidim.pages.terms_and_conditions")
45
53
  redirect_to tos_path
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Decidim
6
+ # Common logic to ordering resources
7
+ module Orderable
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ helper_method :order, :available_orders, :random_seed
12
+
13
+ private
14
+
15
+ # Gets how the proposals should be ordered based on the choice
16
+ # made by the user.
17
+ def order
18
+ @order ||= detect_order(params[:order]) || default_order
19
+ end
20
+
21
+ def detect_order(candidate)
22
+ available_orders.detect { |order| order == candidate }
23
+ end
24
+
25
+ def default_order
26
+ "random"
27
+ end
28
+
29
+ # Returns: A random float number between -1 and 1 to be used as a
30
+ # random seed at the database.
31
+ def random_seed
32
+ @random_seed ||= session.fetch(:random_seed, (rand * 2 - 1)).to_f
33
+ end
34
+ end
35
+ end
36
+ end
@@ -50,6 +50,7 @@ module Decidim
50
50
  )
51
51
 
52
52
  raise NotImplementedError unless manifest
53
+
53
54
  manifest
54
55
  end
55
56
 
@@ -72,6 +73,7 @@ module Decidim
72
73
 
73
74
  def check_current_user_can_visit_space
74
75
  return if current_user_can_visit_space?
76
+
75
77
  flash[:alert] = I18n.t("participatory_space_private_users.not_allowed", scope: "decidim")
76
78
  redirect_to action: "index"
77
79
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Decidim
6
+ # This concern groups methods and helpers related to redirecting the user from URL params.
7
+ module SafeRedirect
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ helper_method :redirect_url
12
+
13
+ # Sanitizes the redirect url only allowing relative paths or absolute URLs
14
+ # that match the current organization.
15
+ def redirect_url
16
+ return if params[:redirect_url].blank?
17
+ return params[:redirect_url] unless params[:redirect_url].start_with?("http")
18
+ return if URI.parse(params[:redirect_url]).host != current_organization.host
19
+
20
+ params[:redirect_url]
21
+ end
22
+ end
23
+ end
24
+ end
@@ -11,6 +11,8 @@ module Decidim
11
11
  include NeedsTosAccepted
12
12
  include HttpCachingDisabler
13
13
  include ActionAuthorization
14
+ include ForceAuthentication
15
+ include SafeRedirect
14
16
 
15
17
  helper Decidim::MetaTagsHelper
16
18
  helper Decidim::DecidimFormHelper
@@ -50,12 +52,26 @@ module Decidim
50
52
  # In Devise controllers we only store the URL if it's from the params, we don't
51
53
  # want to overwrite the stored URL for a Devise one.
52
54
  def store_current_location
53
- return if (devise_controller? && params[:redirect_url].blank?) || !request.format.html?
55
+ return if skip_store_location?
54
56
 
55
- value = params[:redirect_url] || request.url
57
+ value = redirect_url || request.url
56
58
  store_location_for(:user, value)
57
59
  end
58
60
 
61
+ def skip_store_location?
62
+ # Skip if Devise already handles the redirection
63
+ return true if devise_controller? && redirect_url.blank?
64
+ # Skip for all non-HTML requests"
65
+ return true unless request.format.html?
66
+ # Skip if a signed in user requests the TOS page without having agreed to
67
+ # the TOS. Most of the times this is because of a redirect to the TOS
68
+ # page (in which case the desired location is somewhere else after the
69
+ # TOS is agreed).
70
+ return true if current_user && !current_user.tos_accepted? && request.path == tos_path
71
+
72
+ false
73
+ end
74
+
59
75
  def user_has_no_permission_path
60
76
  decidim.root_path
61
77
  end
@@ -77,6 +93,7 @@ module Decidim
77
93
 
78
94
  def track_continuity_badge
79
95
  return unless current_user
96
+
80
97
  Decidim::ContinuityBadgeTracker.new(current_user).track!(Time.zone.today)
81
98
  end
82
99
  end
@@ -8,6 +8,12 @@ module Decidim
8
8
 
9
9
  helper_method :new_user_group_session_path
10
10
 
11
+ def create
12
+ super do |resource|
13
+ resource.errors.delete(:decidim_organization_id) if resource.errors.any?
14
+ end
15
+ end
16
+
11
17
  # Since we're using a single Devise installation for multiple
12
18
  # organizations, and user emails can be repeated across organizations,
13
19
  # we need to identify the user by both the email and the organization.
@@ -25,10 +25,14 @@ module Decidim
25
25
  # When a managed user accepts the invitation is promoted to non-managed user.
26
26
  def accept_resource
27
27
  resource = resource_class.accept_invitation!(update_resource_params)
28
- resource.update!(newsletter_notifications_at: Time.current) if update_resource_params[:newsletter_notifications]
29
- resource.update!(managed: false) if resource.managed?
30
- resource.update!(accepted_tos_version: resource.organization.tos_version)
31
- Decidim::Gamification.increment_score(resource.invited_by, :invitations) if resource.invited_by
28
+
29
+ if resource.valid? && resource.invitation_accepted?
30
+ resource.update!(newsletter_notifications_at: Time.current) if update_resource_params[:newsletter_notifications]
31
+ resource.update!(managed: false) if resource.managed?
32
+ resource.update!(accepted_tos_version: resource.organization.tos_version)
33
+ Decidim::Gamification.increment_score(resource.invited_by, :invitations) if resource.invited_by
34
+ end
35
+
32
36
  resource
33
37
  end
34
38
 
@@ -24,7 +24,8 @@ module Decidim
24
24
  set_flash_message :notice, :success, kind: @form.provider.capitalize
25
25
  else
26
26
  expire_data_after_sign_in!
27
- redirect_to root_path
27
+ user.resend_confirmation_instructions unless user.confirmed?
28
+ redirect_to decidim.root_path
28
29
  flash[:notice] = t("devise.registrations.signed_up_but_unconfirmed")
29
30
  end
30
31
  end
@@ -66,6 +67,7 @@ module Decidim
66
67
 
67
68
  def action_missing(action_name)
68
69
  return send(:create) if devise_mapping.omniauthable? && User.omniauth_providers.include?(action_name.to_sym)
70
+
69
71
  raise AbstractController::ActionNotFound, "The action '#{action_name}' could not be found for Decidim::Devise::OmniauthCallbacksController"
70
72
  end
71
73
 
@@ -79,6 +81,7 @@ module Decidim
79
81
  # Since we are using trusted omniauth data we are generating a valid signature.
80
82
  def user_params_from_oauth_hash
81
83
  return nil if oauth_data.empty?
84
+
82
85
  {
83
86
  provider: oauth_data[:provider],
84
87
  uid: oauth_data[:uid],
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Decidim
4
4
  class ErrorsController < Decidim::ApplicationController
5
+ skip_before_action :verify_authenticity_token
6
+ skip_after_action :verify_same_origin_request
7
+
5
8
  def not_found
6
9
  render status: :not_found
7
10
  end
@@ -17,7 +17,7 @@ module Decidim
17
17
  end
18
18
 
19
19
  on(:invalid) do
20
- render json: { error: I18n.t("follows.destroy.error", scope: "decidim") }, status: 422
20
+ render json: { error: I18n.t("follows.destroy.error", scope: "decidim") }, status: :unprocessable_entity
21
21
  end
22
22
  end
23
23
  end
@@ -33,7 +33,7 @@ module Decidim
33
33
  end
34
34
 
35
35
  on(:invalid) do
36
- render json: { error: I18n.t("follows.create.error", scope: "decidim") }, status: 422
36
+ render json: { error: I18n.t("follows.create.error", scope: "decidim") }, status: :unprocessable_entity
37
37
  end
38
38
  end
39
39
  end
@@ -37,7 +37,7 @@ module Decidim
37
37
  end
38
38
 
39
39
  on(:invalid) do
40
- render json: { error: I18n.t("messaging.conversations.create.error", scope: "decidim") }, status: 422
40
+ render json: { error: I18n.t("messaging.conversations.create.error", scope: "decidim") }, status: :unprocessable_entity
41
41
  end
42
42
  end
43
43
  end
@@ -67,7 +67,7 @@ module Decidim
67
67
  end
68
68
 
69
69
  on(:invalid) do
70
- render json: { error: I18n.t("messaging.conversations.update.error", scope: "decidim") }, status: 422
70
+ render json: { error: I18n.t("messaging.conversations.update.error", scope: "decidim") }, status: :unprocessable_entity
71
71
  end
72
72
  end
73
73
  end
@@ -16,6 +16,7 @@ module Decidim
16
16
  def show
17
17
  return redirect_to profile_timeline_path(nickname: params[:nickname]) if profile_holder == current_user
18
18
  return redirect_to profile_members_path if profile_holder.is_a?(Decidim::UserGroup)
19
+
19
20
  redirect_to profile_activity_path(nickname: params[:nickname])
20
21
  end
21
22
 
@@ -64,10 +65,12 @@ module Decidim
64
65
  end
65
66
 
66
67
  def ensure_profile_holder
67
- raise ActionController::RoutingError, "No user or user group with the given nickname" unless profile_holder
68
+ raise ActionController::RoutingError, "No user or user group with the given nickname" if !profile_holder || profile_holder.nickname.blank?
68
69
  end
69
70
 
70
71
  def profile_holder
72
+ return if params[:nickname].blank?
73
+
71
74
  @profile_holder ||= Decidim::User.find_by(
72
75
  nickname: params[:nickname],
73
76
  organization: current_organization
@@ -8,12 +8,11 @@ module Decidim
8
8
  def picker
9
9
  enforce_permission_to :pick, :scope
10
10
 
11
- title = params[:title] || t("decidim.scopes.picker.title", field: params[:field]&.downcase)
12
- root = current_organization.scopes.find(params[:root]) if params[:root]
13
11
  context = root ? { root: root.id, title: title } : { title: title }
14
12
  required = params[:required] && params[:required] != "false"
15
- if params[:current]
16
- current = (root&.descendants || current_organization.scopes).find_by(id: params[:current]) || root
13
+ current = (root&.descendants || current_organization.scopes).find_by(id: params[:current]) if params[:current].present?
14
+
15
+ if current
17
16
  scopes = current.children
18
17
  parent_scopes = current.part_of_scopes(root)
19
18
  else
@@ -21,8 +20,21 @@ module Decidim
21
20
  scopes = root&.children || current_organization.scopes.top_level
22
21
  parent_scopes = [root].compact
23
22
  end
23
+
24
24
  render :picker, layout: nil, locals: { required: required, title: title, root: root, current: current, scopes: scopes.order(name: :asc),
25
25
  parent_scopes: parent_scopes, global_value: params[:global_value], context: context }
26
26
  end
27
+
28
+ private
29
+
30
+ def title
31
+ @title ||= params[:title] || t("decidim.scopes.picker.title", field: params[:field]&.downcase)
32
+ end
33
+
34
+ def root
35
+ return if params[:root].blank?
36
+
37
+ @root ||= current_organization.scopes.find(params[:root])
38
+ end
27
39
  end
28
40
  end