decidim-core 0.29.6 → 0.30.0.rc1

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 (607) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/activity/show.erb +6 -6
  3. data/app/cells/decidim/address/show.erb +3 -3
  4. data/app/cells/decidim/amendable/amend_button_card/show.erb +6 -4
  5. data/app/cells/decidim/amendable/amend_button_card_cell.rb +8 -0
  6. data/app/cells/decidim/amendable/amendments/show.erb +1 -1
  7. data/app/cells/decidim/amendable/promote_button_card/show.erb +2 -0
  8. data/app/cells/decidim/author/flag.erb +6 -0
  9. data/app/cells/decidim/author/flag_user.erb +14 -0
  10. data/app/cells/decidim/author/show.erb +2 -6
  11. data/app/cells/decidim/author_cell.rb +1 -11
  12. data/app/cells/decidim/card_l/extra_data.erb +1 -0
  13. data/app/cells/decidim/card_metadata_cell.rb +9 -16
  14. data/app/cells/decidim/comments_button_cell.rb +14 -2
  15. data/app/cells/decidim/content_blocks/highlighted_elements_cell.rb +2 -0
  16. data/app/cells/decidim/content_blocks/highlighted_elements_with_cell_for_list_cell.rb +1 -1
  17. data/app/cells/decidim/content_blocks/participatory_space_extra_data/extra_data.erb +2 -2
  18. data/app/cells/decidim/content_blocks/participatory_space_main_data/title.erb +2 -11
  19. data/app/cells/decidim/endorsement_block/show.erb +0 -1
  20. data/app/cells/decidim/endorsement_block_cell.rb +6 -0
  21. data/app/cells/decidim/endorsement_buttons/button_content.erb +1 -1
  22. data/app/cells/decidim/endorsement_buttons/select_identity_button.erb +1 -1
  23. data/app/cells/decidim/endorsement_buttons/show.erb +7 -7
  24. data/app/cells/decidim/endorsement_buttons/verification_modal.erb +4 -2
  25. data/app/cells/decidim/endorsers_list/empty.erb +3 -0
  26. data/app/cells/decidim/endorsers_list/full.erb +17 -5
  27. data/app/cells/decidim/endorsers_list/show.erb +19 -10
  28. data/app/cells/decidim/endorsers_list_cell.rb +19 -6
  29. data/app/cells/decidim/flag_modal/flag_user.erb +34 -0
  30. data/app/cells/decidim/flag_modal/show.erb +52 -0
  31. data/app/cells/decidim/flag_modal_cell.rb +56 -0
  32. data/app/cells/decidim/follow_button/show.erb +1 -2
  33. data/app/cells/decidim/follow_button_cell.rb +5 -0
  34. data/app/cells/decidim/footer_topics/show.erb +2 -2
  35. data/app/cells/decidim/group_admins/show.erb +1 -3
  36. data/app/cells/decidim/group_members/show.erb +2 -6
  37. data/app/cells/decidim/images_panel/show.erb +2 -5
  38. data/app/cells/decidim/map/show.erb +3 -0
  39. data/app/cells/decidim/map/template.erb +14 -0
  40. data/app/cells/decidim/map_cell.rb +39 -0
  41. data/app/cells/decidim/notification_actions/buttons_cell.rb +1 -1
  42. data/app/cells/decidim/onboarding_action_message/show.erb +15 -0
  43. data/app/cells/decidim/onboarding_action_message_cell.rb +81 -0
  44. data/app/cells/decidim/participatory_space_dropdown_metadata/metadata.erb +4 -4
  45. data/app/cells/decidim/participatory_space_dropdown_metadata/show.erb +3 -5
  46. data/app/cells/decidim/participatory_space_private_user/show.erb +23 -0
  47. data/app/cells/decidim/participatory_space_private_user_cell.rb +21 -0
  48. data/app/cells/decidim/profile/avatar.erb +2 -0
  49. data/app/cells/decidim/profile/badge.erb +3 -3
  50. data/app/cells/decidim/profile/details.erb +1 -2
  51. data/app/cells/decidim/profile_actions/show.erb +1 -1
  52. data/app/cells/decidim/profile_sidebar/show.erb +167 -0
  53. data/app/cells/decidim/profile_sidebar_cell.rb +68 -0
  54. data/app/cells/decidim/progress_bar/show.erb +2 -2
  55. data/app/cells/decidim/report_button/already_reported_modal.erb +2 -2
  56. data/app/cells/decidim/report_button/flag_modal.erb +36 -24
  57. data/app/cells/decidim/report_button_cell.rb +9 -2
  58. data/app/cells/decidim/resource_history/show.erb +20 -0
  59. data/app/cells/decidim/resource_history_cell.rb +66 -0
  60. data/app/cells/decidim/resource_types_filter/show.erb +1 -1
  61. data/app/cells/decidim/resource_types_filter_cell.rb +6 -6
  62. data/app/cells/decidim/share_button_cell.rb +0 -4
  63. data/app/cells/decidim/share_widget/modal.erb +26 -0
  64. data/app/cells/decidim/share_widget/show.erb +2 -0
  65. data/app/cells/decidim/share_widget_cell.rb +20 -0
  66. data/app/cells/decidim/tags/show.erb +7 -4
  67. data/app/cells/decidim/tags_cell.rb +11 -72
  68. data/app/cells/decidim/upload_modal/files.erb +4 -4
  69. data/app/cells/decidim/upload_modal_cell.rb +3 -5
  70. data/app/cells/decidim/user_activity/show.erb +1 -1
  71. data/app/cells/decidim/user_activity_cell.rb +1 -6
  72. data/app/commands/decidim/amendable/accept.rb +1 -2
  73. data/app/commands/decidim/amendable/create_draft.rb +2 -2
  74. data/app/commands/decidim/create_ephemeral_user.rb +52 -0
  75. data/app/commands/decidim/create_omniauth_registration.rb +21 -17
  76. data/app/commands/decidim/create_report.rb +8 -11
  77. data/app/commands/decidim/create_user_group.rb +6 -2
  78. data/app/commands/decidim/destroy_ephemeral_user.rb +47 -0
  79. data/app/commands/decidim/invite_user.rb +1 -1
  80. data/app/commands/decidim/search.rb +0 -14
  81. data/app/commands/decidim/update_account.rb +11 -3
  82. data/app/commands/decidim/update_notifications_settings.rb +1 -0
  83. data/app/commands/decidim/update_resources_taxonomies.rb +67 -0
  84. data/app/commands/decidim/update_user_group.rb +7 -1
  85. data/app/constraints/decidim/current_component.rb +1 -1
  86. data/app/controllers/concerns/decidim/ajax_permission_handler.rb +21 -0
  87. data/app/controllers/concerns/decidim/devise_authentication_methods.rb +3 -6
  88. data/app/controllers/concerns/decidim/devise_controllers.rb +2 -0
  89. data/app/controllers/concerns/decidim/disable_redirection_to_external_host.rb +1 -1
  90. data/app/controllers/concerns/decidim/ephemeral_session_checker.rb +87 -0
  91. data/app/controllers/concerns/decidim/filter_resource.rb +4 -2
  92. data/app/controllers/concerns/decidim/has_members_page.rb +25 -0
  93. data/app/controllers/concerns/decidim/locale_switcher.rb +2 -2
  94. data/app/controllers/concerns/decidim/needs_password_change.rb +0 -1
  95. data/app/controllers/concerns/decidim/needs_permission.rb +2 -1
  96. data/app/controllers/concerns/decidim/needs_tos_accepted.rb +4 -5
  97. data/app/controllers/concerns/decidim/onboarding_action_methods.rb +52 -0
  98. data/app/controllers/concerns/decidim/participatory_space_context.rb +1 -4
  99. data/app/controllers/decidim/amendments_controller.rb +3 -3
  100. data/app/controllers/decidim/application_controller.rb +9 -0
  101. data/app/controllers/decidim/authorization_modals_controller.rb +8 -2
  102. data/app/controllers/decidim/components/base_controller.rb +3 -7
  103. data/app/controllers/decidim/devise/confirmations_controller.rb +4 -0
  104. data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +8 -1
  105. data/app/controllers/decidim/devise/registrations_controller.rb +1 -1
  106. data/app/controllers/decidim/devise/sessions_controller.rb +2 -0
  107. data/app/controllers/decidim/download_your_data_controller.rb +33 -2
  108. data/app/controllers/decidim/editor_images_controller.rb +1 -11
  109. data/app/controllers/decidim/follows_controller.rb +1 -1
  110. data/app/controllers/decidim/geolocation_controller.rb +19 -0
  111. data/app/controllers/decidim/homepage_controller.rb +0 -1
  112. data/app/controllers/decidim/open_data_controller.rb +33 -8
  113. data/app/controllers/decidim/profiles_controller.rb +2 -2
  114. data/app/controllers/decidim/reports_controller.rb +2 -7
  115. data/app/controllers/decidim/user_activities_controller.rb +1 -1
  116. data/app/controllers/decidim/user_conversations_controller.rb +1 -11
  117. data/app/events/decidim/soft_delete_resource_event.rb +15 -0
  118. data/app/forms/decidim/account_form.rb +2 -5
  119. data/app/forms/decidim/amendable/form.rb +4 -2
  120. data/app/forms/decidim/ephemeral_user_form.rb +22 -0
  121. data/app/forms/decidim/notifications_settings_form.rb +1 -0
  122. data/app/forms/decidim/omniauth_registration_form.rb +15 -2
  123. data/app/forms/decidim/registration_form.rb +1 -1
  124. data/app/forms/decidim/user_group_form.rb +0 -2
  125. data/app/helpers/concerns/decidim/flash_helper_extensions.rb +17 -2
  126. data/app/helpers/decidim/action_authorization_helper.rb +75 -14
  127. data/app/helpers/decidim/amendments_helper.rb +1 -11
  128. data/app/helpers/decidim/application_helper.rb +6 -2
  129. data/app/helpers/decidim/breadcrumb_helper.rb +6 -0
  130. data/app/helpers/decidim/cache_helper.rb +1 -1
  131. data/app/helpers/decidim/check_boxes_tree_helper.rb +25 -53
  132. data/app/helpers/decidim/decidim_form_helper.rb +0 -44
  133. data/app/helpers/decidim/endorsable_helper.rb +0 -10
  134. data/app/helpers/decidim/filters_helper.rb +0 -25
  135. data/app/helpers/decidim/layout_helper.rb +6 -6
  136. data/app/helpers/decidim/map_helper.rb +1 -1
  137. data/app/helpers/decidim/menu_helper.rb +2 -2
  138. data/app/helpers/decidim/messaging/conversation_helper.rb +2 -3
  139. data/app/helpers/decidim/meta_tags_helper.rb +32 -23
  140. data/app/helpers/decidim/modal_helper.rb +23 -0
  141. data/app/helpers/decidim/omniauth_helper.rb +5 -5
  142. data/app/helpers/decidim/onboarding_action_helper.rb +13 -0
  143. data/app/helpers/decidim/orders_helper.rb +1 -2
  144. data/app/helpers/decidim/paginate_helper.rb +1 -1
  145. data/app/helpers/decidim/participatory_space_helpers.rb +1 -1
  146. data/app/helpers/decidim/passwords_helper.rb +2 -2
  147. data/app/helpers/decidim/taxonomies_helper.rb +40 -0
  148. data/app/helpers/decidim/tooltip_helper.rb +1 -4
  149. data/app/jobs/decidim/download_your_data_export_job.rb +2 -19
  150. data/app/jobs/decidim/event_publisher_job.rb +18 -9
  151. data/app/jobs/decidim/export_job.rb +5 -1
  152. data/app/jobs/decidim/export_participatory_space_job.rb +4 -1
  153. data/app/jobs/decidim/open_data_job.rb +4 -4
  154. data/app/mailers/decidim/export_mailer.rb +7 -12
  155. data/app/mailers/decidim/notifications_digest_mailer.rb +1 -7
  156. data/app/mailers/decidim/reported_mailer.rb +2 -18
  157. data/app/models/decidim/action_log.rb +20 -1
  158. data/app/models/decidim/category.rb +4 -0
  159. data/app/models/decidim/component.rb +25 -3
  160. data/app/models/decidim/metric.rb +2 -1
  161. data/app/models/decidim/moderation.rb +16 -0
  162. data/app/models/decidim/newsletter.rb +12 -8
  163. data/app/models/decidim/organization.rb +7 -3
  164. data/app/models/decidim/participatory_space_private_user.rb +20 -0
  165. data/app/models/decidim/private_export.rb +24 -0
  166. data/app/models/decidim/push_notification_message.rb +1 -1
  167. data/app/models/decidim/report.rb +1 -1
  168. data/app/models/decidim/scope.rb +4 -0
  169. data/app/models/decidim/share_token.rb +36 -10
  170. data/app/models/decidim/taxonomization.rb +23 -0
  171. data/app/models/decidim/taxonomy.rb +139 -0
  172. data/app/models/decidim/taxonomy_filter.rb +130 -0
  173. data/app/models/decidim/taxonomy_filter_item.rb +33 -0
  174. data/app/models/decidim/user.rb +13 -23
  175. data/app/models/decidim/user_base_entity.rb +12 -4
  176. data/app/models/decidim/user_moderation.rb +9 -0
  177. data/app/models/decidim/user_report.rb +4 -0
  178. data/app/packs/entrypoints/decidim_core.js +1 -0
  179. data/app/packs/entrypoints/decidim_geocoding.js +2 -0
  180. data/app/packs/images/decidim/brands/facebook.svg +10 -0
  181. data/app/packs/images/decidim/brands/google.svg +7 -1
  182. data/app/packs/images/decidim/brands/twitter-x.svg +3 -0
  183. data/app/packs/images/decidim/default-avatar.svg +1 -1
  184. data/app/packs/src/decidim/callout.js +8 -13
  185. data/app/packs/src/decidim/check_boxes_tree.js +0 -1
  186. data/app/packs/src/decidim/clipboard.js +18 -9
  187. data/app/packs/src/decidim/datepicker/datepicker_functions.js +3 -3
  188. data/app/packs/src/decidim/datepicker/generate_datepicker.js +0 -2
  189. data/app/packs/src/decidim/datepicker/generate_timepicker.js +0 -2
  190. data/app/packs/src/decidim/decidim_application.js +1 -0
  191. data/app/packs/src/decidim/direct_uploads/upload_field.js +4 -3
  192. data/app/packs/src/decidim/direct_uploads/upload_modal.js +9 -8
  193. data/app/packs/src/decidim/editor/common/suggestion.js +1 -11
  194. data/app/packs/src/decidim/form_filter.js +0 -6
  195. data/app/packs/src/decidim/geocoding/reverse_geocoding.js +60 -0
  196. data/app/packs/src/decidim/index.js +9 -5
  197. data/app/packs/src/decidim/input_character_counter.js +1 -1
  198. data/app/packs/src/decidim/map/provider/here.js +1 -1
  199. data/app/packs/src/decidim/onboarding_pending_action.js +24 -0
  200. data/app/packs/src/decidim/sticky_footer.js +29 -0
  201. data/app/packs/src/decidim/sticky_header.js +6 -31
  202. data/app/packs/src/decidim/user_registrations.js +13 -0
  203. data/app/packs/src/decidim/vendor/leaflet-tilelayer-here.js +212 -0
  204. data/app/packs/stylesheets/decidim/_accordion.scss +30 -0
  205. data/app/packs/stylesheets/decidim/_activity.scss +4 -4
  206. data/app/packs/stylesheets/decidim/_author.scss +0 -8
  207. data/app/packs/stylesheets/decidim/_buttons.scss +19 -0
  208. data/app/packs/stylesheets/decidim/_cards.scss +1 -9
  209. data/app/packs/stylesheets/decidim/_content_blocks.scss +0 -4
  210. data/app/packs/stylesheets/decidim/_dropdown.scss +1 -1
  211. data/app/packs/stylesheets/decidim/_endorsers_list.scss +26 -20
  212. data/app/packs/stylesheets/decidim/_filters.scss +1 -1
  213. data/app/packs/stylesheets/decidim/_forms.scss +2 -2
  214. data/app/packs/stylesheets/decidim/_header.scss +39 -70
  215. data/app/packs/stylesheets/decidim/_layout.scss +34 -4
  216. data/app/packs/stylesheets/decidim/_login.scss +53 -6
  217. data/app/packs/stylesheets/decidim/_modal.scss +47 -1
  218. data/app/packs/stylesheets/decidim/_modal_tos_refuse.scss +4 -0
  219. data/app/packs/stylesheets/decidim/_modal_update.scss +1 -5
  220. data/app/packs/stylesheets/decidim/_participatory_spaces.scss +46 -0
  221. data/app/packs/stylesheets/decidim/_profile.scss +7 -7
  222. data/app/packs/stylesheets/decidim/_success_image.scss +64 -0
  223. data/app/packs/stylesheets/decidim/_tribute.scss +36 -0
  224. data/app/packs/stylesheets/decidim/application.scss +1 -1
  225. data/app/packs/stylesheets/decidim/editor.scss +1 -3
  226. data/app/packs/stylesheets/decidim/geocoding_addons.scss +5 -0
  227. data/app/packs/stylesheets/decidim/map.scss +7 -10
  228. data/app/packs/stylesheets/decidim/resource_history.scss +31 -0
  229. data/app/permissions/decidim/default_permissions.rb +0 -2
  230. data/app/permissions/decidim/permissions.rb +9 -15
  231. data/app/presenters/decidim/admin_log/base_user_presenter.rb +67 -0
  232. data/app/presenters/decidim/admin_log/component_presenter.rb +32 -3
  233. data/app/presenters/decidim/admin_log/moderation_presenter.rb +30 -3
  234. data/app/presenters/decidim/admin_log/share_token_presenter.rb +39 -0
  235. data/app/presenters/decidim/admin_log/taxonomy_filter_presenter.rb +57 -0
  236. data/app/presenters/decidim/admin_log/taxonomy_presenter.rb +48 -0
  237. data/app/presenters/decidim/admin_log/user_group_presenter.rb +6 -6
  238. data/app/presenters/decidim/admin_log/user_presenter.rb +4 -18
  239. data/app/presenters/decidim/log/user_presenter.rb +0 -1
  240. data/app/presenters/decidim/log/value_types/date_presenter.rb +1 -0
  241. data/app/presenters/decidim/log/value_types/taxonomy_presenter.rb +29 -0
  242. data/app/presenters/decidim/notification_to_mailer_presenter.rb +3 -7
  243. data/app/presenters/decidim/participatory_space_private_user_presenter.rb +50 -0
  244. data/app/presenters/decidim/taxonomy_filter_presenter.rb +19 -0
  245. data/app/presenters/decidim/taxonomy_presenter.rb +14 -0
  246. data/app/presenters/decidim/user_presenter.rb +1 -1
  247. data/app/queries/decidim/last_activity.rb +0 -25
  248. data/app/queries/decidim/metrics/blocked_users_metric_manage.rb +2 -2
  249. data/app/queries/decidim/metrics/users_metric_manage.rb +2 -2
  250. data/app/queries/decidim/public_activities.rb +1 -12
  251. data/app/queries/decidim/stats_users_count.rb +2 -2
  252. data/app/resolvers/decidim/meta_image_url_resolver.rb +128 -0
  253. data/app/serializers/decidim/exporters/open_data_blocked_user_serializer.rb +25 -0
  254. data/app/serializers/decidim/exporters/open_data_metric_serializer.rb +22 -0
  255. data/app/serializers/decidim/exporters/open_data_moderation_serializer.rb +30 -0
  256. data/app/serializers/decidim/exporters/open_data_taxonomy_serializer.rb +30 -0
  257. data/app/serializers/decidim/exporters/open_data_user_group_serializer.rb +38 -0
  258. data/app/serializers/decidim/exporters/open_data_user_serializer.rb +39 -0
  259. data/app/serializers/decidim/exporters/participatory_space_serializer.rb +104 -0
  260. data/app/serializers/decidim/exporters/serializer.rb +25 -0
  261. data/app/serializers/decidim/schema_org_breadcrumb_list_serializer.rb +52 -0
  262. data/app/services/decidim/action_authorizer.rb +32 -3
  263. data/app/services/decidim/base_diff_renderer.rb +1 -3
  264. data/app/services/decidim/download_your_data_exporter.rb +58 -24
  265. data/app/services/decidim/onboarding_manager.rb +272 -0
  266. data/app/services/decidim/open_data_exporter.rb +139 -13
  267. data/app/services/decidim/static_map_generator.rb +1 -1
  268. data/app/services/decidim/traceability.rb +13 -0
  269. data/app/uploaders/decidim/application_uploader.rb +1 -1
  270. data/app/validators/etiquette_validator.rb +9 -2
  271. data/app/validators/passthru_validator.rb +1 -1
  272. data/app/validators/password_validator.rb +1 -3
  273. data/app/validators/translated_etiquette_validator.rb +32 -0
  274. data/app/views/decidim/account/_password_fields.html.erb +2 -2
  275. data/app/views/decidim/application/_accordion_section.html.erb +14 -0
  276. data/app/views/decidim/application/_collection.html.erb +30 -18
  277. data/app/views/decidim/application/_document.html.erb +2 -2
  278. data/app/views/decidim/devise/omniauth_registrations/new.html.erb +5 -1
  279. data/app/views/decidim/devise/omniauth_registrations/new_tos_fields.html.erb +29 -0
  280. data/app/views/decidim/devise/registrations/new.html.erb +10 -22
  281. data/app/views/decidim/devise/sessions/new.html.erb +24 -29
  282. data/app/views/decidim/devise/shared/_omniauth_buttons.html.erb +2 -4
  283. data/app/views/decidim/devise/shared/_tos_fields.html.erb +16 -0
  284. data/app/views/decidim/download_your_data/_export.html.erb +15 -0
  285. data/app/views/decidim/download_your_data/show.html.erb +51 -5
  286. data/app/views/decidim/endorsements/update_buttons_and_counters.js.erb +16 -19
  287. data/app/views/decidim/errors/internal_server_error.html.erb +1 -1
  288. data/app/views/decidim/errors/not_found.html.erb +1 -1
  289. data/app/views/decidim/export_mailer/download_your_data_export.html.erb +2 -2
  290. data/app/views/decidim/export_mailer/export.html.erb +5 -1
  291. data/app/views/decidim/last_activities/index.html.erb +1 -1
  292. data/app/views/decidim/messaging/conversations/_reply_form.html.erb +2 -1
  293. data/app/views/decidim/messaging/conversations/_start.html.erb +1 -1
  294. data/app/views/decidim/newsletters/unsubscribe.html.erb +4 -16
  295. data/app/views/decidim/notifications_settings/show.html.erb +22 -0
  296. data/app/views/decidim/open_data/_how_to_open_accordion_section.html.erb +15 -0
  297. data/app/views/decidim/open_data/index.html.erb +108 -0
  298. data/app/views/decidim/pages/show.html.erb +2 -1
  299. data/app/views/decidim/participatory_space_private_users/_participatory_space_private_user.html.erb +1 -0
  300. data/app/views/decidim/reported_mailer/hide.html.erb +9 -0
  301. data/app/views/decidim/reported_mailer/report.html.erb +1 -1
  302. data/app/views/decidim/searches/_count.html.erb +1 -1
  303. data/app/views/decidim/searches/_filters.html.erb +39 -76
  304. data/app/views/decidim/shared/_component_announcement.html.erb +1 -1
  305. data/app/views/decidim/shared/_confirm_modal.html.erb +5 -3
  306. data/app/views/decidim/shared/_filters.html.erb +5 -7
  307. data/app/views/decidim/shared/_login_modal.html.erb +26 -20
  308. data/app/views/decidim/shared/_orders.html.erb +2 -2
  309. data/app/views/decidim/shared/_resource_actions.html.erb +21 -0
  310. data/app/views/decidim/shared/_results_per_page.html.erb +1 -1
  311. data/app/views/decidim/shared/filters/_check_boxes_tree.html.erb +1 -2
  312. data/app/views/decidim/shared/filters/_collection.html.erb +1 -1
  313. data/app/views/decidim/shared/filters/_dropdown_label.html.erb +7 -4
  314. data/app/views/kaminari/decidim/_page.html.erb +1 -1
  315. data/app/views/kaminari/decidim/_paginator.html.erb +1 -1
  316. data/app/views/layouts/decidim/_application.html.erb +1 -2
  317. data/app/views/layouts/decidim/_logo.html.erb +2 -2
  318. data/app/views/layouts/decidim/_logo_mobile.html.erb +1 -1
  319. data/app/views/layouts/decidim/_meta_tags_config.html.erb +6 -11
  320. data/app/views/layouts/decidim/_schema_org_breadcrumb_list.html.erb +3 -0
  321. data/app/views/layouts/decidim/_wrapper.html.erb +15 -9
  322. data/app/views/layouts/decidim/footer/_main.html.erb +1 -1
  323. data/app/views/layouts/decidim/footer/_main_intro.html.erb +1 -1
  324. data/app/views/layouts/decidim/footer/_main_legal.html.erb +1 -1
  325. data/app/views/layouts/decidim/footer/_main_links.html.erb +1 -1
  326. data/app/views/layouts/decidim/footer/_mini.html.erb +2 -2
  327. data/app/views/layouts/decidim/header/_close_ephemeral_session.html.erb +25 -0
  328. data/app/views/layouts/decidim/header/_main.html.erb +14 -10
  329. data/app/views/layouts/decidim/header/_main_links_desktop.html.erb +0 -6
  330. data/app/views/layouts/decidim/header/_main_links_dropdown.html.erb +0 -2
  331. data/app/views/layouts/decidim/header/_main_links_mobile_account.html.erb +1 -1
  332. data/app/views/layouts/decidim/header/_menu_breadcrumb_items.html.erb +2 -0
  333. data/app/views/layouts/decidim/header/_menu_breadcrumb_main_dropdown_desktop.html.erb +11 -5
  334. data/app/views/layouts/decidim/header/_menu_breadcrumb_mobile_tablet.html.erb +5 -5
  335. data/app/views/layouts/decidim/header/_mobile_language_choose.html.erb +1 -1
  336. data/app/views/layouts/decidim/shared/_layout_item.html.erb +1 -1
  337. data/config/assets.rb +2 -1
  338. data/config/locales/ar.yml +38 -74
  339. data/config/locales/bg-BG.yml +2 -2
  340. data/config/locales/bg.yml +38 -74
  341. data/config/locales/bs-BA.yml +0 -2
  342. data/config/locales/ca.yml +382 -138
  343. data/config/locales/cs.yml +379 -121
  344. data/config/locales/de.yml +370 -133
  345. data/config/locales/el.yml +26 -58
  346. data/config/locales/en.yml +354 -110
  347. data/config/locales/eo.yml +0 -4
  348. data/config/locales/es-MX.yml +368 -127
  349. data/config/locales/es-PY.yml +373 -132
  350. data/config/locales/es.yml +374 -130
  351. data/config/locales/eu.yml +491 -245
  352. data/config/locales/fi-plain.yml +367 -130
  353. data/config/locales/fi.yml +372 -132
  354. data/config/locales/fr-CA.yml +180 -125
  355. data/config/locales/fr-LU.yml +3 -3
  356. data/config/locales/fr.yml +180 -122
  357. data/config/locales/ga-IE.yml +4 -25
  358. data/config/locales/gl.yml +23 -58
  359. data/config/locales/hu.yml +35 -62
  360. data/config/locales/id-ID.yml +24 -57
  361. data/config/locales/is-IS.yml +6 -25
  362. data/config/locales/it.yml +39 -218
  363. data/config/locales/ja.yml +235 -141
  364. data/config/locales/lb-LU.yml +2 -2
  365. data/config/locales/lb.yml +31 -76
  366. data/config/locales/lt.yml +29 -64
  367. data/config/locales/lv.yml +24 -58
  368. data/config/locales/nl.yml +26 -75
  369. data/config/locales/no.yml +26 -70
  370. data/config/locales/pl.yml +35 -72
  371. data/config/locales/pt-BR.yml +44 -63
  372. data/config/locales/pt.yml +26 -70
  373. data/config/locales/ro-RO.yml +118 -183
  374. data/config/locales/ru.yml +16 -43
  375. data/config/locales/sk-SK.yml +3 -3
  376. data/config/locales/sk.yml +27 -72
  377. data/config/locales/sl.yml +0 -4
  378. data/config/locales/sr-CS.yml +0 -2
  379. data/config/locales/sv.yml +141 -133
  380. data/config/locales/tr-TR.yml +32 -75
  381. data/config/locales/uk.yml +8 -29
  382. data/config/locales/zh-CN.yml +24 -68
  383. data/config/locales/zh-TW.yml +28 -62
  384. data/config/routes.rb +4 -10
  385. data/db/migrate/20171212103803_create_unique_nicknames.rb +1 -1
  386. data/db/migrate/20180221101934_fix_nickname_index.rb +1 -1
  387. data/db/migrate/20180706104107_add_nickname_to_managed_users.rb +1 -1
  388. data/db/migrate/20181001124950_move_users_groups_to_users_table.rb +1 -1
  389. data/db/migrate/20181025082245_add_timestamps_to_components.rb +2 -0
  390. data/db/migrate/20190412131728_fix_user_names.rb +1 -1
  391. data/db/migrate/20240628111905_add_visible_to_components.rb +7 -0
  392. data/db/migrate/20240704115429_create_decidim_taxonomies.rb +23 -0
  393. data/db/migrate/20240717093514_add_registered_only_to_decidim_share_tokens.rb +7 -0
  394. data/db/migrate/20240722215500_change_object_changes_on_versions.rb +39 -0
  395. data/db/migrate/20240806065417_create_decidim_taxonomy_filters.rb +23 -0
  396. data/db/migrate/20240822161348_add_deleted_at_to_decidim_components.rb +8 -0
  397. data/db/migrate/20240906162524_add_part_of_to_taxonomies.rb +26 -0
  398. data/db/migrate/20241001135825_add_role_to_participatory_space_private_users.rb +7 -0
  399. data/db/migrate/20241001140408_add_published_to_participatory_space_private_users.rb +7 -0
  400. data/db/migrate/20241022002600_create_private_exports.rb +18 -0
  401. data/db/migrate/20241028114430_add_component_counter_to_taxonomy_filters.rb +7 -0
  402. data/db/migrate/20241111104357_add_names_and_space_boolean_to_taxonomy_filters.rb +9 -0
  403. data/db/migrate/20241127093708_add_taxonomy_to_metrics.rb +7 -0
  404. data/db/migrate/20241204121445_add_participatory_space_manifests_from_taxonomy_filters.rb +9 -0
  405. data/decidim-core.gemspec +14 -17
  406. data/lib/decidim/action_authorization.rb +3 -2
  407. data/lib/decidim/amendable.rb +1 -1
  408. data/lib/decidim/api/input_filters/category_input_filter.rb +5 -3
  409. data/lib/decidim/api/input_filters/component_input_filter.rb +33 -20
  410. data/lib/decidim/api/input_filters/user_entity_input_filter.rb +53 -44
  411. data/lib/decidim/api/input_sorts/component_input_sort.rb +15 -13
  412. data/lib/decidim/api/input_sorts/user_entity_input_sort.rb +4 -4
  413. data/lib/decidim/api/interfaces/author_interface.rb +3 -2
  414. data/lib/decidim/api/interfaces/coauthorable_interface.rb +5 -5
  415. data/lib/decidim/api/interfaces/endorsable_interface.rb +2 -2
  416. data/lib/decidim/api/interfaces/participatory_space_interface.rb +5 -10
  417. data/lib/decidim/api/interfaces/taxonomizable_interface.rb +13 -0
  418. data/lib/decidim/api/types/amendment_type.rb +5 -7
  419. data/lib/decidim/api/types/area_api_type.rb +3 -3
  420. data/lib/decidim/api/types/attachment_type.rb +3 -3
  421. data/lib/decidim/api/types/category_type.rb +2 -2
  422. data/lib/decidim/api/types/decidim_type.rb +5 -1
  423. data/lib/decidim/api/types/fingerprint_type.rb +1 -1
  424. data/lib/decidim/api/types/localized_string_type.rb +1 -1
  425. data/lib/decidim/api/types/metric_history_type.rb +2 -0
  426. data/lib/decidim/api/types/metric_type.rb +1 -1
  427. data/lib/decidim/api/types/organization_type.rb +5 -0
  428. data/lib/decidim/api/types/participatory_space_link_type.rb +2 -2
  429. data/lib/decidim/api/types/participatory_space_manifest_type.rb +1 -1
  430. data/lib/decidim/api/types/quantifiable_translated_field_type.rb +1 -1
  431. data/lib/decidim/api/types/scope_api_type.rb +2 -3
  432. data/lib/decidim/api/types/session_type.rb +1 -2
  433. data/lib/decidim/api/types/taxonomy_type.rb +15 -0
  434. data/lib/decidim/api/types/trace_version_type.rb +2 -2
  435. data/lib/decidim/api/types/translated_field_type.rb +3 -5
  436. data/lib/decidim/api/types/user_group_type.rb +7 -20
  437. data/lib/decidim/api/types/user_type.rb +7 -20
  438. data/lib/decidim/asset_router/storage.rb +10 -15
  439. data/lib/decidim/assets/tailwind/tailwind.config.js.erb +3 -3
  440. data/lib/decidim/attachment_attributes.rb +1 -1
  441. data/lib/decidim/attribute_encryptor.rb +1 -1
  442. data/lib/decidim/attribute_object/nested_validator.rb +1 -1
  443. data/lib/decidim/attributes/integer_with_units.rb +27 -0
  444. data/lib/decidim/attributes/time_with_zone.rb +1 -5
  445. data/lib/decidim/attributes.rb +2 -0
  446. data/lib/decidim/authorization_form_builder.rb +0 -7
  447. data/lib/decidim/coauthorable.rb +1 -1
  448. data/lib/decidim/command.rb +3 -3
  449. data/lib/decidim/commands/destroy_resource.rb +5 -1
  450. data/lib/decidim/commands/resource_handler.rb +2 -2
  451. data/lib/decidim/commands/restore_resource.rb +45 -0
  452. data/lib/decidim/commands/soft_delete_resource.rb +63 -0
  453. data/lib/decidim/component_manifest.rb +7 -0
  454. data/lib/decidim/content_parsers/blob_parser.rb +8 -10
  455. data/lib/decidim/content_parsers/user_parser.rb +1 -1
  456. data/lib/decidim/core/api.rb +2 -0
  457. data/lib/decidim/core/engine.rb +21 -7
  458. data/lib/decidim/core/menu.rb +0 -5
  459. data/lib/decidim/core/seeds.rb +42 -2
  460. data/lib/decidim/core/test/factories.rb +107 -4
  461. data/lib/decidim/core/test/shared_examples/admin_resource_gallery_examples.rb +85 -0
  462. data/lib/decidim/core/test/shared_examples/announcements_examples.rb +0 -4
  463. data/lib/decidim/core/test/shared_examples/comments_examples.rb +393 -38
  464. data/lib/decidim/core/test/shared_examples/components_controller_hide_shared_examples.rb +11 -0
  465. data/lib/decidim/core/test/shared_examples/components_controller_reorder_shared_examples.rb +21 -0
  466. data/lib/decidim/core/test/shared_examples/download_open_data_shared_context.rb +36 -0
  467. data/lib/decidim/core/test/shared_examples/download_open_data_shared_examples.rb +45 -0
  468. data/lib/decidim/core/test/shared_examples/download_your_data_shared_examples.rb +17 -0
  469. data/lib/decidim/core/test/shared_examples/etiquette_validator_examples.rb +25 -0
  470. data/lib/decidim/core/test/shared_examples/follows_examples.rb +43 -0
  471. data/lib/decidim/core/test/shared_examples/has_taxonomies.rb +94 -0
  472. data/lib/decidim/core/test/shared_examples/manage_share_tokens_examples.rb +237 -0
  473. data/lib/decidim/core/test/shared_examples/map_examples.rb +2 -0
  474. data/lib/decidim/core/test/shared_examples/open_data_exporter_examples.rb +102 -0
  475. data/lib/decidim/core/test/shared_examples/participatory_space_members_page_examples.rb +46 -0
  476. data/lib/decidim/core/test/shared_examples/participatory_space_search_examples.rb +98 -0
  477. data/lib/decidim/core/test/shared_examples/permissions.rb +7 -7
  478. data/lib/decidim/core/test/shared_examples/preview_with_share_token_examples.rb +94 -0
  479. data/lib/decidim/core/test/shared_examples/reports_examples.rb +15 -53
  480. data/lib/decidim/core/test/shared_examples/resource_endorsed_event_examples.rb +2 -2
  481. data/lib/decidim/core/test/shared_examples/resource_search_examples.rb +75 -69
  482. data/lib/decidim/core/test/shared_examples/searchable_resources_shared_context.rb +1 -1
  483. data/lib/decidim/core/test/shared_examples/simple_event.rb +33 -19
  484. data/lib/decidim/core/test/shared_examples/social_share_examples.rb +7 -14
  485. data/lib/decidim/core/test/shared_examples/softdeleteable_components_examples.rb +173 -0
  486. data/lib/decidim/core/test/shared_examples/system_endorse_resource_examples.rb +54 -8
  487. data/lib/decidim/core/test/shared_examples/taxonomizable_interface_examples.rb +20 -0
  488. data/lib/decidim/core/test/shared_examples/taxonomizable_resource_examples.rb +37 -0
  489. data/lib/decidim/core/test/shared_examples/taxonomy_settings.rb +49 -0
  490. data/lib/decidim/core/test/shared_examples/translated_event_examples.rb +1 -1
  491. data/lib/decidim/core/test/shared_examples/uncommentable_component_examples.rb +0 -26
  492. data/lib/decidim/core/test/shared_examples/versions_controller_examples.rb +2 -28
  493. data/lib/decidim/core/test/shared_examples/with_endorsable_permissions_examples.rb +1 -1
  494. data/lib/decidim/core/test.rb +9 -5
  495. data/lib/decidim/core/version.rb +1 -1
  496. data/lib/decidim/core.rb +58 -0
  497. data/lib/decidim/download_your_data_serializers/download_your_data_identity_serializer.rb +0 -4
  498. data/lib/decidim/download_your_data_serializers/download_your_data_participatory_space_private_user_serializer.rb +3 -1
  499. data/lib/decidim/download_your_data_serializers/download_your_data_report_serializer.rb +2 -1
  500. data/lib/decidim/download_your_data_serializers/download_your_data_user_serializer.rb +6 -7
  501. data/lib/decidim/download_your_data_serializers.rb +19 -0
  502. data/lib/decidim/exporters/csv.rb +6 -0
  503. data/lib/decidim/exporters/export_manifest.rb +14 -0
  504. data/lib/decidim/exporters/pdf.rb +26 -22
  505. data/lib/decidim/filter_form_builder.rb +12 -15
  506. data/lib/decidim/form_builder.rb +7 -144
  507. data/lib/decidim/has_category.rb +5 -1
  508. data/lib/decidim/has_private_users.rb +4 -0
  509. data/lib/decidim/has_taxonomy_settings.rb +47 -0
  510. data/lib/decidim/has_upload_validations.rb +1 -1
  511. data/lib/decidim/legacy_form_builder.rb +118 -0
  512. data/lib/decidim/maintenance/import_models/application_record.rb +93 -0
  513. data/lib/decidim/maintenance/import_models/area.rb +82 -0
  514. data/lib/decidim/maintenance/import_models/area_type.rb +12 -0
  515. data/lib/decidim/maintenance/import_models/assembly_type.rb +49 -0
  516. data/lib/decidim/maintenance/import_models/categorization.rb +14 -0
  517. data/lib/decidim/maintenance/import_models/category.rb +107 -0
  518. data/lib/decidim/maintenance/import_models/participatory_process_type.rb +21 -0
  519. data/lib/decidim/maintenance/import_models/scope.rb +163 -0
  520. data/lib/decidim/maintenance/import_models.rb +19 -0
  521. data/lib/decidim/maintenance/taxonomy_importer.rb +132 -0
  522. data/lib/decidim/maintenance/taxonomy_plan.rb +78 -0
  523. data/lib/decidim/maintenance.rb +12 -0
  524. data/lib/decidim/map/autocomplete.rb +52 -8
  525. data/lib/decidim/map/dynamic_map.rb +1 -1
  526. data/lib/decidim/map/provider/dynamic_map/here.rb +40 -1
  527. data/lib/decidim/map/provider/geocoding/here.rb +9 -3
  528. data/lib/decidim/map/provider/static_map/here.rb +0 -34
  529. data/lib/decidim/map.rb +3 -6
  530. data/lib/decidim/moderation_tools.rb +16 -19
  531. data/lib/decidim/newsletter_encryptor.rb +1 -1
  532. data/lib/decidim/nicknamizable.rb +9 -6
  533. data/lib/decidim/paddable.rb +1 -1
  534. data/lib/decidim/participable.rb +10 -10
  535. data/lib/decidim/participatory_space_user.rb +10 -0
  536. data/lib/decidim/private_download_helper.rb +15 -0
  537. data/lib/decidim/record_encryptor.rb +51 -46
  538. data/lib/decidim/reportable.rb +2 -6
  539. data/lib/decidim/resourceable.rb +16 -0
  540. data/lib/decidim/seeds.rb +18 -20
  541. data/lib/decidim/settings_manifest.rb +34 -1
  542. data/lib/decidim/soft_deletable.rb +17 -0
  543. data/lib/decidim/taxonomizable.rb +72 -0
  544. data/lib/decidim/translatable_attributes.rb +1 -5
  545. data/lib/decidim/view_model.rb +0 -1
  546. data/lib/tasks/decidim_download_your_data_tasks.rake +2 -4
  547. data/lib/tasks/decidim_procfile.rake +6 -0
  548. data/lib/tasks/decidim_tasks.rake +1 -0
  549. data/lib/tasks/decidim_taxonomies.rake +155 -0
  550. data/lib/tasks/upgrade/{decidim_fix_categorization.rake → clean.rake} +25 -18
  551. data/lib/tasks/upgrade/decidim_active_storage_migration_tasks.rake +1 -1
  552. data/lib/tasks/upgrade/decidim_fix_nickname_uniqueness.rake +20 -23
  553. data/lib/tasks/upgrade/migrations.rake +91 -0
  554. metadata +201 -114
  555. data/app/cells/decidim/amendable/amenders_list/show.erb +0 -0
  556. data/app/cells/decidim/author/badge.erb +0 -6
  557. data/app/cells/decidim/content_blocks/base/content.erb +0 -0
  558. data/app/cells/decidim/endorsers_list/full_endorsers_list.erb +0 -3
  559. data/app/cells/decidim/endorsers_list_button/content.erb +0 -1
  560. data/app/cells/decidim/endorsers_list_button_cell.rb +0 -15
  561. data/app/cells/decidim/report_user_button/already_reported_modal.erb +0 -11
  562. data/app/cells/decidim/report_user_button/flag_modal.erb +0 -47
  563. data/app/cells/decidim/report_user_button/show.erb +0 -2
  564. data/app/cells/decidim/report_user_button_cell.rb +0 -59
  565. data/app/cells/decidim/scopes_picker/scope_picker_prompt.erb +0 -3
  566. data/app/cells/decidim/scopes_picker/scope_picker_values.erb +0 -5
  567. data/app/cells/decidim/scopes_picker/show.erb +0 -14
  568. data/app/cells/decidim/scopes_picker_cell.rb +0 -92
  569. data/app/commands/decidim/update_user_interests.rb +0 -41
  570. data/app/controllers/decidim/scopes_controller.rb +0 -84
  571. data/app/controllers/decidim/user_interests_controller.rb +0 -30
  572. data/app/forms/decidim/user_interest_scope_form.rb +0 -25
  573. data/app/forms/decidim/user_interests_form.rb +0 -17
  574. data/app/helpers/decidim/categories_helper.rb +0 -26
  575. data/app/helpers/decidim/scopes_helper.rb +0 -105
  576. data/app/jobs/decidim/hide_child_resources_job.rb +0 -24
  577. data/app/packs/images/decidim/vendor/leaflet/layers-2x.png +0 -0
  578. data/app/packs/images/decidim/vendor/leaflet/layers.png +0 -0
  579. data/app/packs/images/decidim/vendor/leaflet/marker-icon-2x.png +0 -0
  580. data/app/packs/images/decidim/vendor/leaflet/marker-icon.png +0 -0
  581. data/app/packs/images/decidim/vendor/leaflet/marker-shadow.png +0 -0
  582. data/app/packs/src/decidim/dropdown_menu.js +0 -18
  583. data/app/packs/stylesheets/decidim/_hashtags.scss +0 -5
  584. data/app/packs/stylesheets/decidim/legacy/MarkerCluster.Default.scss +0 -67
  585. data/app/packs/stylesheets/decidim/legacy/MarkerCluster.scss +0 -18
  586. data/app/packs/stylesheets/decidim/legacy/leaflet.scss +0 -705
  587. data/app/validators/scope_belongs_to_component_validator.rb +0 -16
  588. data/app/views/decidim/account/_user_groups.html.erb +0 -0
  589. data/app/views/decidim/reported_mailer/hidden_automatically.html.erb +0 -25
  590. data/app/views/decidim/reported_mailer/hidden_manually.html.erb +0 -25
  591. data/app/views/decidim/scopes/_scopes_picker_input.html.erb +0 -19
  592. data/app/views/decidim/scopes/picker.html.erb +0 -53
  593. data/app/views/decidim/shared/_comments.html.erb +0 -0
  594. data/app/views/decidim/shared/_share_modal.html.erb +0 -26
  595. data/app/views/decidim/shared/_tags.html.erb +0 -1
  596. data/app/views/decidim/user_interests/_areas.html.erb +0 -14
  597. data/app/views/decidim/user_interests/_scopes.html.erb +0 -22
  598. data/app/views/decidim/user_interests/show.html.erb +0 -22
  599. data/config/initializers/foundation_rails_helper.rb +0 -4
  600. data/config/locales/ca-IT.yml +0 -2146
  601. data/lib/decidim/core/test/shared_examples/has_category.rb +0 -38
  602. data/lib/decidim/core/test/shared_examples/has_scope.rb +0 -11
  603. data/lib/decidim/core/test/shared_examples/manage_component_share_tokens.rb +0 -83
  604. data/lib/decidim/core/test/shared_examples/preview_component_with_share_token_examples.rb +0 -49
  605. data/lib/decidim/core/test/shared_examples/scope_helper_examples.rb +0 -93
  606. data/lib/decidim/seven_zip_wrapper.rb +0 -29
  607. data/lib/tasks/upgrade/clean_hidden_resources.rake +0 -33
@@ -88,23 +88,32 @@ module Decidim
88
88
  def unauthorized?
89
89
  @code == :unauthorized
90
90
  end
91
+
92
+ def ephemeral?
93
+ @authorization_handler.ephemeral?
94
+ end
91
95
  end
92
96
 
93
97
  class AuthorizationStatusCollection
94
98
  attr_reader :statuses
95
99
 
96
100
  def initialize(authorization_handlers, user, component, resource)
101
+ @ephemeral_user = user&.ephemeral?
97
102
  @authorization_handlers = authorization_handlers
98
- @statuses = authorization_handlers&.map do |name, opts|
103
+ @statuses = authorization_handlers&.filter_map do |name, opts|
99
104
  handler = Verifications::Adapter.from_element(name)
105
+ next if @ephemeral_user && !handler.ephemeral?
106
+
100
107
  authorization = user ? Verifications::Authorizations.new(organization: user.organization, user:, name:).first : nil
101
108
  status_code, data = handler.authorize(authorization, opts["options"], component, resource)
102
109
  AuthorizationStatus.new(status_code, handler, data)
103
- end
110
+ end || []
104
111
  end
105
112
 
106
113
  def ok?
107
- return true if statuses.blank?
114
+ # When no statuses are present for the action ephemeral users
115
+ # are not allowed to perform the action
116
+ return !@ephemeral_user if statuses.blank?
108
117
 
109
118
  statuses.all?(&:ok?)
110
119
  end
@@ -126,6 +135,26 @@ module Decidim
126
135
  def codes
127
136
  @codes ||= statuses.map(&:code)
128
137
  end
138
+
139
+ def pending_authorizations_count
140
+ return 0 if @statuses.blank?
141
+
142
+ @statuses.count
143
+ end
144
+
145
+ def single_authorization_required?
146
+ pending_authorizations_count == 1 && [:ok, :unauthorized].exclude?(global_code)
147
+ end
148
+
149
+ def ephemeral?
150
+ return if statuses.blank?
151
+
152
+ statuses.all?(&:ephemeral?)
153
+ end
154
+
155
+ def user_pending?
156
+ !global_code && statuses.any? { |status| [:missing, :expired, :incomplete].include?(status.code) }
157
+ end
129
158
  end
130
159
 
131
160
  class AuthorizationError < StandardError; end
@@ -41,14 +41,12 @@ module Decidim
41
41
  end
42
42
 
43
43
  def parse_i18n_changeset(attribute, values, type, diff)
44
- return diff unless values.last.is_a?(Hash)
45
-
46
44
  (values.last.keys - ["machine_translations"]).each do |locale, _value|
47
45
  first_value = values.first.try(:[], locale)
48
46
  last_value = values.last.try(:[], locale)
49
47
  next if first_value == last_value
50
48
 
51
- attribute_locale = "#{attribute}_#{locale}".to_sym
49
+ attribute_locale = :"#{attribute}_#{locale}"
52
50
  diff.update(
53
51
  attribute_locale => {
54
52
  type:,
@@ -1,41 +1,52 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "decidim/seven_zip_wrapper"
4
-
5
3
  module Decidim
6
- # Public: Generates a 7z(seven zip) file with data files ready to be persisted
4
+ # Public: Generates a zip archive with data files ready to be persisted
7
5
  # somewhere so users can download their data.
8
6
  #
9
- # In fact, the 7z file wraps a ZIP file which finally contains the data files.
10
7
  class DownloadYourDataExporter
11
8
  DEFAULT_EXPORT_FORMAT = "CSV"
12
9
  ZIP_FILE_NAME = "download-your-data.zip"
13
10
 
11
+ include Decidim::TranslatableAttributes
12
+
14
13
  # Public: Initializes the class.
15
14
  #
16
15
  # user - The user to export the data from.
17
- # path - The String path where to write the zip file.
18
- # password - The password to protect the zip file.
16
+ # name - The name of the export in private area
19
17
  # export_format - The format of the data files inside the zip file. (CSV by default)
20
- def initialize(user, path, password, export_format = DEFAULT_EXPORT_FORMAT)
18
+ def initialize(user, name, export_format = DEFAULT_EXPORT_FORMAT)
21
19
  @user = user
22
- @path = File.expand_path path
23
20
  @export_format = export_format
24
- @password = password
21
+ @name = name
25
22
  end
26
23
 
24
+ # i18n-tasks-use t("decidim.download_your_data.show.download_your_data")
27
25
  def export
28
- tmpdir = Dir.mktmpdir("temporary-download-your-data-dir")
29
- user_data, user_attachments = data_and_attachments_for_user
30
- save_user_data(tmpdir, user_data)
31
- save_user_attachments(tmpdir, user_attachments)
32
-
33
- SevenZipWrapper.compress_and_encrypt(filename: @path, password: @password, input_directory: tmpdir)
26
+ user_export = user.private_exports.build
27
+ user_export.export_type = name
28
+ user_export.file.attach(io: data, filename: "#{name}.zip", content_type: "application/zip")
29
+ user_export.expires_at = Decidim.download_your_data_expiry_time.from_now
30
+ user_export.metadata = {}
31
+ user_export.save!
32
+ user_export
34
33
  end
35
34
 
36
35
  private
37
36
 
38
- attr_reader :user, :export_format
37
+ attr_reader :user, :export_format, :name
38
+
39
+ def data
40
+ user_data, user_attachments = data_and_attachments_for_user
41
+ buffer = Zip::OutputStream.write_buffer do |out|
42
+ save_user_data(out, user_data)
43
+ save_user_attachments(out, user_attachments)
44
+ save_readme(out)
45
+ end
46
+
47
+ buffer.rewind
48
+ buffer
49
+ end
39
50
 
40
51
  def data_and_attachments_for_user
41
52
  export_data = []
@@ -43,7 +54,8 @@ module Decidim
43
54
 
44
55
  download_your_data_entities.each do |object|
45
56
  klass = Object.const_get(object)
46
- export_data << [klass.model_name.name.parameterize.pluralize, Exporters.find_exporter(export_format).new(klass.user_collection(user), klass.export_serializer).export]
57
+ exporter = Exporters.find_exporter(export_format).new(klass.user_collection(user), klass.export_serializer)
58
+ export_data << [klass.model_name.name.parameterize.pluralize, exporter.export]
47
59
  attachments = klass.download_your_data_images(user)
48
60
  export_attachments << [klass.model_name.name.parameterize.pluralize, attachments.flatten] unless attachments.nil?
49
61
  end
@@ -55,30 +67,52 @@ module Decidim
55
67
  @download_your_data_entities ||= DownloadYourDataSerializers.data_entities
56
68
  end
57
69
 
58
- def save_user_data(tmpdir, user_data)
70
+ def save_user_data(output, user_data)
59
71
  user_data.each do |entity, exporter_data|
60
72
  next if exporter_data.read == "\n"
61
73
 
62
- file_name = File.join(tmpdir, "#{entity}-#{exporter_data.filename}")
63
- File.write(file_name, exporter_data.read)
74
+ output.put_next_entry("#{entity}-#{exporter_data.filename}")
75
+ output.write exporter_data.read
64
76
  end
65
77
  end
66
78
 
67
- def save_user_attachments(tmpdir, user_attachments)
79
+ def save_user_attachments(output, user_attachments)
68
80
  user_attachments.each do |entity, attachment_block|
69
81
  attachment_block.each do |attachment|
70
82
  next unless attachment.attached?
71
83
 
72
84
  blobs = attachment.is_a?(ActiveStorage::Attached::One) ? [attachment.blob] : attachment.blobs
73
85
  blobs.each do |blob|
74
- Dir.mkdir(File.join(tmpdir, entity.parameterize))
75
- file_name = File.join(tmpdir, entity.parameterize, blob.filename.to_s)
76
86
  blob.open do |blob_file|
77
- File.write(file_name, blob_file.read.force_encoding("UTF-8"))
87
+ output.put_next_entry("#{entity.parameterize}/#{blob.filename}")
88
+ output.write blob_file.read.force_encoding("UTF-8")
78
89
  end
79
90
  end
80
91
  end
81
92
  end
82
93
  end
94
+
95
+ def save_readme(output)
96
+ output.put_next_entry("README.md")
97
+ output.write readme
98
+ end
99
+
100
+ def readme
101
+ readme_file = "# #{I18n.t("decidim.download_your_data.help.core.title", organization: translated_attribute(user.organization.name))}\n\n"
102
+ readme_file << "#{I18n.t("decidim.download_your_data.help.core.description", user_name: "#{user.name} (#{user.nickname})")}\n\n"
103
+ help_definition = DownloadYourDataSerializers.help_definitions_for(user)
104
+
105
+ help_definition.each do |entity, headers|
106
+ next if headers.empty?
107
+
108
+ readme_file << "\n\n## #{entity}\n\n"
109
+
110
+ headers.each do |header, help_value|
111
+ readme_file << "* #{header}: #{help_value}\n"
112
+ end
113
+ end
114
+
115
+ readme_file
116
+ end
83
117
  end
84
118
  end
@@ -0,0 +1,272 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # This class is used to manage the onboarding funnel for users that
5
+ # intended to perform an action in the platform but it requires some
6
+ # verification steps to be completed.
7
+ #
8
+ # The flow is as follows:
9
+ #
10
+ # 1. A visitor (logged out) tries to perform an action that requires to be logged in
11
+ # 2. The intended action is stored in a cookie (onboarding key)
12
+ # 3. The visitor logs in and the onboarding cookie data is merged into the User#extended_data column.
13
+ # 4. After logging in, the user is redirected to the onboarding pending authorizations page
14
+ # if there is any pending action stored in the User#extended_data column
15
+ # 5. The user completes the required authorizations
16
+ # 6. When the onboarding authorizations page detects that all the verification steps have been
17
+ # completed, it will remove the pending action from the User#extended_data column and redirect
18
+ # the user to the intended action.
19
+ #
20
+ class OnboardingManager
21
+ # The same key is set in onboarding_pending_action js file to manage the
22
+ # onboarding data in the cookie
23
+ DATA_KEY = "onboarding"
24
+
25
+ attr_reader :user
26
+
27
+ def initialize(user)
28
+ @user = user
29
+ end
30
+
31
+ delegate :ephemeral?, to: :user
32
+
33
+ # Checks if the onboarding data has an action and a model.
34
+ #
35
+ # Returns a boolean
36
+ def valid?
37
+ return if action.blank?
38
+
39
+ permissions_holder.present?
40
+ end
41
+
42
+ # Returns the action to be performed.
43
+ #
44
+ # Returns a string
45
+ def action
46
+ onboarding_action
47
+ end
48
+
49
+ # Returns the translation of the action to be performed if translation
50
+ # is found, otherwise the untranslated literal action key
51
+ #
52
+ # Returns a string
53
+ def action_text
54
+ @action_text ||= if component && I18n.exists?("#{component.manifest.name}.actions.#{action}", scope: "decidim.components")
55
+ I18n.t("#{component.manifest.name}.actions.#{action}", scope: "decidim.components")
56
+ elsif permissions_holder.respond_to?(:resource_manifest) &&
57
+ I18n.exists?("#{permissions_holder.resource_manifest.name}.actions.#{action}", scope: "decidim.resources")
58
+ I18n.t("#{permissions_holder.resource_manifest.name}.actions.#{action}", scope: "decidim.resources")
59
+ else
60
+ action
61
+ end
62
+ end
63
+
64
+ # Checks if there is any pending action for the user.
65
+ #
66
+ # Returns a boolean
67
+ def pending_action?
68
+ onboarding_data.present?
69
+ end
70
+
71
+ # Checks if the user has completed all the required authorizations.
72
+ #
73
+ # active_authorization_methods - A list of the active authorization methods for the user.
74
+ #
75
+ # Returns a boolean
76
+ def finished_verifications?(authorization_methods = active_authorization_methods)
77
+ (authorization_handlers - authorization_methods).empty?
78
+ end
79
+
80
+ # Returns the model related to the action in the onboarding process.
81
+ #
82
+ # Returns an ActiveRecord model
83
+ def model
84
+ return if onboarding_model.blank?
85
+
86
+ @model ||= GlobalID::Locator.locate(onboarding_model)
87
+ end
88
+
89
+ # Returns the permissions_holder if present related to the action in the
90
+ # onboarding process.
91
+ #
92
+ # Returns an ActiveRecord model
93
+ def permissions_holder
94
+ return model if onboarding_permissions_holder.blank?
95
+
96
+ @permissions_holder ||= GlobalID::Locator.locate(onboarding_permissions_holder)
97
+ end
98
+
99
+ # Returns the model name related to the action in the onboarding process.
100
+ #
101
+ # Returns a string
102
+ def model_name
103
+ return unless valid?
104
+
105
+ @model_name ||= (model.presence || permissions_holder).class.model_name
106
+ end
107
+
108
+ # Returns the resource title associated to the action. If the model is defined
109
+ # its title is used, if not the permissions holder title
110
+ #
111
+ # Returns a translations Hash or a String
112
+ def model_title
113
+ return unless valid?
114
+
115
+ @model_title ||= begin
116
+ resource = model.presence || permissions_holder
117
+
118
+ method = [:title, :name].find { |m| resource.respond_to?(m) }
119
+
120
+ resource.send(method) if method
121
+ end
122
+ end
123
+
124
+ # Filters the given authorizations that are required for the onboarding process.
125
+ #
126
+ # authorizations - An array of Decidim::Authorization objects
127
+ #
128
+ # Returns an array of Decidim::Authorization objects
129
+ def filter_authorizations(authorizations)
130
+ filtered_authorizations = authorizations.select { |authorization| authorization_handlers.include?(authorization.name) }
131
+
132
+ # By calling authorize on each authorization the path generated for each
133
+ # one will include the specific options of the action if available
134
+ filtered_authorizations.each do |authorization|
135
+ next unless authorization.is_a? Decidim::Verifications::Adapter
136
+
137
+ authorization.authorize(nil, permissions.dig("authorization_handlers", authorization.name, "options") || {}, model, permissions_holder)
138
+ end
139
+ filtered_authorizations
140
+ end
141
+
142
+ # Returns a hash which can be passed to action_authorized_to helper method
143
+ # to determine the permissions status of the action
144
+ #
145
+ # Returns a Hash
146
+ def action_authorized_resources
147
+ return {} unless valid?
148
+
149
+ {
150
+ resource: model,
151
+ permissions_holder: onboarding_permissions_holder.presence && permissions_holder
152
+ }
153
+ end
154
+
155
+ # Returns the path to redirect after finishing the verification process. The path
156
+ # can be obtained from the user onboarding redirect_path data or if a resource is
157
+ # present using a ResourceLocatorPresenter
158
+ #
159
+ # Returns a String
160
+ def finished_redirect_path
161
+ @finished_redirect_path ||= onboarding_data["redirect_path"].presence || model_path
162
+ end
163
+
164
+ def root_path
165
+ component_path || Decidim::Core::Engine.routes.url_helpers.root_path
166
+ end
167
+
168
+ def component_path
169
+ return if component.blank?
170
+
171
+ EngineRouter.main_proxy(component).root_path
172
+ end
173
+
174
+ def expired?
175
+ return unless ephemeral?
176
+
177
+ session_duration > Decidim.config.expire_session_after.to_i
178
+ end
179
+
180
+ # Time in seconds since the last login or creation of the user
181
+ #
182
+ # Returns an Integer
183
+ def session_duration
184
+ Time.current.to_i - (user.last_sign_in_at || user.created_at).to_i
185
+ end
186
+
187
+ # This method is used to determine if an ephemeral user has an onboarding
188
+ # page to be redirected or only an authorization is required to complete the
189
+ # verification
190
+ #
191
+ # Returns a Boolean
192
+ def available_authorization_selection_page?
193
+ return true unless valid? && ephemeral?
194
+
195
+ authorization_handlers.count > 1
196
+ end
197
+
198
+ private
199
+
200
+ def active_authorization_methods
201
+ @active_authorization_methods ||= Verifications::Authorizations.new(organization: user.organization, user:).pluck(:name)
202
+ end
203
+
204
+ # Returns the permissions for the action and model in the onboarding process.
205
+ #
206
+ # Returns a hash
207
+ def permissions
208
+ @permissions ||= permissions_holder&.permissions&.fetch(action, nil) || component&.permissions&.fetch(action, nil)
209
+ end
210
+
211
+ # Returns the authorization handlers for the action and model in the onboarding process.
212
+ #
213
+ # Returns an array of strings
214
+ def authorization_handlers
215
+ return [] unless permissions
216
+
217
+ permissions["authorization_handlers"]&.keys&.map(&:to_s) || []
218
+ end
219
+
220
+ # Returns the model component or the permissions holder when it is a component.
221
+ #
222
+ # Returns a Decidim::Component
223
+ def component
224
+ return permissions_holder if permissions_holder.is_a?(Decidim::Component)
225
+ return if model.blank?
226
+ return unless model.respond_to?(:component)
227
+
228
+ model.component
229
+ end
230
+
231
+ # Returns the onboarding data from the user's extended_data related to the model in gid format.
232
+ #
233
+ # Returns a string
234
+ def onboarding_model
235
+ onboarding_data["model"]
236
+ end
237
+
238
+ # Returns the onboarding data from the user's extended_data related to the permissions_holder
239
+ # in gid format. This attribute is optional and may not be present
240
+ #
241
+ # Returns a string
242
+ def onboarding_permissions_holder
243
+ onboarding_data["permissions_holder"]
244
+ end
245
+
246
+ # Returns the onboarding data from the user's extended_data related to the action.
247
+ #
248
+ # Returns a string
249
+ def onboarding_action
250
+ onboarding_data["action"]
251
+ end
252
+
253
+ # Returns the onboarding data from the user's extended_data.
254
+ #
255
+ # Returns a hash
256
+ def onboarding_data
257
+ user.extended_data[DATA_KEY] || {}
258
+ end
259
+
260
+ # Returns the path associated to the model using ResourceLocatorPresenter. If model is not
261
+ # present returns the root path
262
+ #
263
+ # Returns a String
264
+ def model_path
265
+ return Decidim::Core::Engine.routes.url_helpers.root_path if model.blank?
266
+
267
+ ResourceLocatorPresenter.new(model).url
268
+ rescue NoMethodError
269
+ Decidim::Core::Engine.routes.url_helpers.root_path
270
+ end
271
+ end
272
+ end