decidim-decidim_awesome 0.12.0 → 0.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/README.md +24 -14
  4. data/Rakefile +12 -0
  5. data/app/cells/concerns/decidim/decidim_awesome/global_menu_cell_override.rb +14 -2
  6. data/app/cells/concerns/decidim/decidim_awesome/proposal_l_cell_override.rb +5 -4
  7. data/app/cells/decidim/decidim_awesome/voting/voting_cards_proposal/show.erb +3 -3
  8. data/app/cells/decidim/decidim_awesome/voting/voting_cards_proposal/vote_block_for.erb +1 -1
  9. data/app/controllers/concerns/decidim/decidim_awesome/admin/maintenance_context.rb +0 -28
  10. data/app/controllers/concerns/decidim/decidim_awesome/needs_hashcash.rb +41 -0
  11. data/app/controllers/concerns/decidim/decidim_awesome/not_found_redirect.rb +2 -2
  12. data/app/controllers/decidim/decidim_awesome/admin/admin_authorizations_controller.rb +2 -2
  13. data/app/controllers/decidim/decidim_awesome/admin/checks_controller.rb +0 -4
  14. data/app/controllers/decidim/decidim_awesome/admin/config_controller.rb +2 -1
  15. data/app/controllers/decidim/decidim_awesome/admin/custom_redirects_controller.rb +1 -2
  16. data/app/controllers/decidim/decidim_awesome/admin/hashcash_controller.rb +39 -0
  17. data/app/controllers/decidim/decidim_awesome/admin/menu_hacks_controller.rb +1 -1
  18. data/app/controllers/decidim/decidim_awesome/admin/{maintenance_controller.rb → private_data_controller.rb} +9 -9
  19. data/app/controllers/decidim/decidim_awesome/utils_controller.rb +17 -0
  20. data/app/forms/concerns/decidim/decidim_awesome/proposals/proposal_form_override.rb +7 -1
  21. data/app/forms/decidim/decidim_awesome/admin/config_form.rb +13 -0
  22. data/app/helpers/decidim/decidim_awesome/admin/config_constraints_helpers.rb +1 -1
  23. data/app/helpers/decidim/decidim_awesome/map_helper.rb +4 -2
  24. data/app/models/decidim/decidim_awesome/paper_trail_version.rb +1 -1
  25. data/app/overrides/decidim/devise/registrations/new/add_hashcash.html.erb.deface +3 -0
  26. data/app/overrides/decidim/devise/sessions/new/add_hashcash.html.erb.deface +3 -0
  27. data/app/overrides/layouts/decidim/_head/add_awesome_custom_styles.html.erb.deface +3 -0
  28. data/app/overrides/layouts/decidim/_head/add_awesome_tags.html.erb.deface +0 -2
  29. data/app/packs/entrypoints/decidim_decidim_awesome_hashcash.js +4 -0
  30. data/app/packs/src/decidim/decidim_awesome/admin/auto_edit.js +10 -6
  31. data/app/packs/src/decidim/decidim_awesome/admin/custom_fields_builder.js +4 -2
  32. data/app/packs/src/decidim/decidim_awesome/admin/verifications.js +6 -3
  33. data/app/packs/src/decidim/decidim_awesome/awesome_map/api/proposals_fetcher.js +1 -1
  34. data/app/packs/src/decidim/decidim_awesome/awesome_map/controllers/controller.js +1 -1
  35. data/app/packs/src/decidim/decidim_awesome/awesome_map/controllers/proposals_controller.js +1 -1
  36. data/app/packs/src/decidim/decidim_awesome/awesome_map/controls_ui.js +6 -6
  37. data/app/packs/src/decidim/decidim_awesome/awesome_map/load_map.js +1 -1
  38. data/app/packs/src/decidim/decidim_awesome/forms/autosave.js +3 -3
  39. data/app/packs/src/decidim/decidim_awesome/forms/custom_fields_renderer.js +1 -113
  40. data/app/packs/src/decidim/decidim_awesome/proposals/images.js +1 -1
  41. data/app/packs/src/vendor/form_builder_langs/ar-SA.lang +111 -0
  42. data/app/packs/src/vendor/form_builder_langs/ar-TN.lang +94 -0
  43. data/app/packs/src/vendor/form_builder_langs/ca-ES.lang +110 -0
  44. data/app/packs/src/vendor/form_builder_langs/cs-CZ.lang +105 -0
  45. data/app/packs/src/vendor/form_builder_langs/da-DK.lang +110 -0
  46. data/app/packs/src/vendor/form_builder_langs/de-DE.lang +109 -0
  47. data/app/packs/src/vendor/form_builder_langs/el-GR.lang +110 -0
  48. data/app/packs/src/vendor/form_builder_langs/en-US.lang +117 -0
  49. data/app/packs/src/vendor/form_builder_langs/es-ES.lang +103 -0
  50. data/app/packs/src/vendor/form_builder_langs/fa-IR.lang +108 -0
  51. data/app/packs/src/vendor/form_builder_langs/fi-FI.lang +107 -0
  52. data/app/packs/src/vendor/form_builder_langs/fr-FR.lang +117 -0
  53. data/app/packs/src/vendor/form_builder_langs/he-IL.lang +108 -0
  54. data/app/packs/src/vendor/form_builder_langs/hi-IN.lang +110 -0
  55. data/app/packs/src/vendor/form_builder_langs/hu-HU.lang +108 -0
  56. data/app/packs/src/vendor/form_builder_langs/id-ID.lang +110 -0
  57. data/app/packs/src/vendor/form_builder_langs/it-IT.lang +107 -0
  58. data/app/packs/src/vendor/form_builder_langs/ja-JP.lang +108 -0
  59. data/app/packs/src/vendor/form_builder_langs/my-MM.lang +108 -0
  60. data/app/packs/src/vendor/form_builder_langs/nb-NO.lang +94 -0
  61. data/app/packs/src/vendor/form_builder_langs/nl-NL.lang +94 -0
  62. data/app/packs/src/vendor/form_builder_langs/pl-PL.lang +122 -0
  63. data/app/packs/src/vendor/form_builder_langs/pt-BR.lang +110 -0
  64. data/app/packs/src/vendor/form_builder_langs/pu-IN.lang +110 -0
  65. data/app/packs/src/vendor/form_builder_langs/qz-MM.lang +108 -0
  66. data/app/packs/src/vendor/form_builder_langs/ro-RO.lang +94 -0
  67. data/app/packs/src/vendor/form_builder_langs/ru-RU.lang +110 -0
  68. data/app/packs/src/vendor/form_builder_langs/sl-SI.lang +110 -0
  69. data/app/packs/src/vendor/form_builder_langs/th-TH.lang +111 -0
  70. data/app/packs/src/vendor/form_builder_langs/tr-TR.lang +115 -0
  71. data/app/packs/src/vendor/form_builder_langs/uk-UA.lang +108 -0
  72. data/app/packs/src/vendor/form_builder_langs/vi-VN.lang +94 -0
  73. data/app/packs/src/vendor/form_builder_langs/zh-CN.lang +100 -0
  74. data/app/packs/src/vendor/form_builder_langs/zh-TW.lang +94 -0
  75. data/app/packs/src/vendor/hashcash.js +83 -0
  76. data/app/packs/src/vendor/sha1.js +143 -0
  77. data/app/packs/src/vendor/stamp.js +50 -0
  78. data/app/packs/stylesheets/decidim/decidim_awesome/forms/autosave.scss +2 -12
  79. data/app/presenters/decidim/decidim_awesome/private_data_presenter.rb +2 -2
  80. data/app/views/decidim/decidim_awesome/admin/admin_accountability/index.html.erb +4 -4
  81. data/app/views/decidim/decidim_awesome/admin/admin_authorizations/callout.html.erb +2 -2
  82. data/app/views/decidim/decidim_awesome/admin/admin_authorizations/conflict.html.erb +4 -4
  83. data/app/views/decidim/decidim_awesome/admin/admin_authorizations/edit.html.erb +6 -5
  84. data/app/views/decidim/decidim_awesome/admin/checks/index.html.erb +6 -6
  85. data/app/views/decidim/decidim_awesome/admin/config/_autoedit_box_label.html.erb +2 -2
  86. data/app/views/decidim/decidim_awesome/admin/config/_constraints.html.erb +3 -3
  87. data/app/views/decidim/decidim_awesome/admin/config/_form_admins.html.erb +4 -3
  88. data/app/views/decidim/decidim_awesome/admin/config/_form_editors.html.erb +1 -1
  89. data/app/views/decidim/decidim_awesome/admin/config/_form_proposal_custom_fields.html.erb +4 -4
  90. data/app/views/decidim/decidim_awesome/admin/config/_form_scoped_styles.html.erb +3 -3
  91. data/app/views/decidim/decidim_awesome/admin/config/_form_surveys.html.erb +40 -2
  92. data/app/views/decidim/decidim_awesome/admin/config/_form_verifications.html.erb +1 -1
  93. data/app/views/decidim/decidim_awesome/admin/hashcash/_filters.html.erb +55 -0
  94. data/app/views/decidim/decidim_awesome/admin/hashcash/index.html.erb +33 -0
  95. data/app/views/decidim/decidim_awesome/admin/hashcash/ip_addresses.html.erb +29 -0
  96. data/app/views/decidim/decidim_awesome/admin/hashcash/show.html.erb +42 -0
  97. data/app/views/decidim/decidim_awesome/admin/menu_hacks/index.html.erb +2 -2
  98. data/app/views/decidim/decidim_awesome/admin/{maintenance → private_data}/_private_data.html.erb +2 -2
  99. data/app/views/decidim/decidim_awesome/admin/{maintenance/show.html.erb → private_data/index.html.erb} +2 -3
  100. data/app/views/decidim/decidim_awesome/admin/proposals/_private_body.html.erb +1 -1
  101. data/app/views/decidim/decidim_awesome/amendments/_modal.html.erb +2 -2
  102. data/app/views/decidim/decidim_awesome/hashcash/_hidden_field.html.erb +5 -0
  103. data/app/views/layouts/decidim/decidim_awesome/_awesome_config.html.erb +2 -2
  104. data/app/views/layouts/decidim/decidim_awesome/admin/maintenance.html.erb +2 -11
  105. data/config/assets.rb +1 -0
  106. data/config/i18n-tasks.yml +1 -0
  107. data/config/locales/ca.yml +69 -30
  108. data/config/locales/cs.yml +68 -29
  109. data/config/locales/de.yml +67 -28
  110. data/config/locales/en.yml +81 -32
  111. data/config/locales/es.yml +68 -29
  112. data/config/locales/eu.yml +31 -31
  113. data/config/locales/fr.yml +82 -31
  114. data/config/locales/ja.yml +31 -31
  115. data/lib/decidim/decidim_awesome/admin_engine.rb +8 -5
  116. data/lib/decidim/decidim_awesome/awesome.rb +29 -7
  117. data/lib/decidim/decidim_awesome/checksums.yml +15 -40
  118. data/lib/decidim/decidim_awesome/engine.rb +11 -2
  119. data/lib/decidim/decidim_awesome/menu.rb +151 -138
  120. data/lib/decidim/decidim_awesome/test/initializer.rb +4 -1
  121. data/lib/decidim/decidim_awesome/test/shared_examples/config_examples.rb +1 -3
  122. data/lib/decidim/decidim_awesome/test/shared_examples/editor_examples.rb +2 -1
  123. data/lib/decidim/decidim_awesome/test/shared_examples/summary_examples.rb +8 -1
  124. data/lib/decidim/decidim_awesome/version.rb +1 -1
  125. data/lib/tasks/decidim_awesome_upgrade_tasks.rake +4 -1
  126. data/package.json +3 -4
  127. metadata +68 -10
  128. data/config/rubocop/disabled.yml +0 -11
  129. data/config/rubocop/faker.yml +0 -480
  130. data/config/rubocop/rails.yml +0 -88
  131. data/config/rubocop/rspec.yml +0 -65
  132. data/config/rubocop/ruby.yml +0 -1210
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29689a9ea7f9c930c3683f13c34ecf797b125dc8241ed704ca44174085d59a00
4
- data.tar.gz: f3552ebb84814f2f854f7a9b9bb1f80a0d8b3739cd1fd9626c3cbc4f6a7c7a6e
3
+ metadata.gz: e111d7d8a993a82615ebe5876f238141d046d140d17cc2ce8a47bd57a6e4028b
4
+ data.tar.gz: 21012c001100d7bb1fdc7555a6650b695ba990bca5b38e0014ac78082af6f15e
5
5
  SHA512:
6
- metadata.gz: a521a9f071f71436ad251a7ce20c9a7d6202fe83518e291927ce4d9affdbc138238b2e5b618b505db66882beb3af2775f90993ca501c290b7f4152990a38d456
7
- data.tar.gz: 28c137dced1adb31664299f427b55257877f56b4d06041de46a0194fb14b976adf6375dad4a17063ff155031ab4ba6ff6345b4bf2066bcfa9102a3f00a7a482a
6
+ metadata.gz: 70df95271a2b16f3510ee8fa6549ec616f9c38963b5266291acfa8ec0bf572980af1781474be44b55ee0bd4cdff04efbfb6c135ca48bafe2676ab9d8a2ffc3c6
7
+ data.tar.gz: 6e75d54f61ffde030812ff30e6f4ec58b6db4d2e1ce8168f38c58921efa3bf8a648c4c5c58801a714e0740beeabb3d16df97319badab04bae70cd6171169114b
data/CHANGELOG.md CHANGED
@@ -1,6 +1,39 @@
1
1
  CHANGELOG
2
2
  =========
3
3
 
4
+ v0.12.2
5
+ -------
6
+
7
+ Compatibility:
8
+ - Decidim 0.29.x
9
+
10
+ Features:
11
+ - Fix custom styles loading order
12
+ - Fix for awesome map no loading in a component
13
+ - Fix "other" options in checkbox/radio custom fields
14
+ - Added Mobile Menu Override
15
+
16
+ v0.12.2
17
+ -------
18
+
19
+ Compatibility:
20
+ - Decidim 0.29.x
21
+
22
+ Features:
23
+ - Added HashCash anti-bot mechanism
24
+ - Fixed multi-tenant crossover in admin accountability
25
+
26
+ v0.12.1
27
+ -------
28
+
29
+ Compatibility:
30
+ - Decidim 0.29.x
31
+
32
+ Feature:
33
+ - Added formBuilder languages controller to avoid external CDN
34
+ - Fix cache hash in the global menu override
35
+ - Fix crash on updating empty boxes for scoped admins
36
+
4
37
  v0.12.0
5
38
  -------
6
39
  Compatibility:
data/README.md CHANGED
@@ -121,21 +121,8 @@ Technically, the content is stored in the database as an XML document compatible
121
121
  ![Custom fields screenshot](examples/custom-fields-2.png)
122
122
  ![Custom fields screenshot](examples/custom-fields-1.gif)
123
123
 
124
- Note that the custom fields are build using the jQuery library [formBuilder](https://formbuilder.online). This package is included in Decidim Awesome but the i18n translations are not. By default they are dynamically downloaded from the CDN https://cdn.jsdelivr.net/npm/formbuilder-languages@1.1.0/.
125
- If you wish to provide an alternative place for those files, you can configure the variable `form_builder_langs_location` in an initializer:
126
124
 
127
- ```ruby
128
- # config/initializers/awesome_defaults.rb
129
-
130
- # A URL where to obtain the translations for the FormBuilder component
131
- # you can a custom place if you are worried about the CDN geolocation
132
- # Download them from https://github.com/kevinchappell/formBuilder-languages
133
-
134
- # For instance, copy them to your /public/fb_locales/ directory and set the path here:
135
- Decidim::DecidimAwesome.configure do |config|
136
- config.form_builder_langs_location = "/fb_locales/"
137
- end
138
- ```
125
+ Translations for this feature are extracted from the [NPM formBuilder-languages](https://github.com/kevinchappell/formBuilder-languages).
139
126
 
140
127
  ##### 11.1. GraphQL types for custom fields
141
128
 
@@ -425,6 +412,19 @@ System configuration:
425
412
  ![Removing an authorization](examples/manual_verifications_2.png)
426
413
  ![Creating an authorization](examples/manual_verifications_3.png)
427
414
 
415
+ #### 22. HashCash Anti-Bot login/registration
416
+
417
+ This feature adds a HashCash-based anti-bot mechanism to the login and registration forms. HashCash is a proof-of-work system originally designed to limit email spam and denial-of-service attacks. When enabled, users must solve a computational puzzle (a "stamp") before submitting the form, making automated attacks significantly harder.
418
+
419
+ The integration leverages the [ActiveHashcash](https://github.com/BaseSecrete/active_hashcash) gem to generate and verify HashCash stamps (although with some customizations). For more details on the HashCash protocol, see the [official documentation](http://www.hashcash.org/docs/hashcash.html).
420
+
421
+ When this feature is active, each login or registration attempt requires a valid HashCash stamp, effectively reducing the risk of automated bot submissions.
422
+
423
+ Note this feature is **disabled by default**, admins can enabled it under the "Surveys & Forms" menu in the Decidim Awesome admin dashboard.
424
+
425
+ ![Hashcash admin config](examples/haschcash_admin.png)
426
+ ![Hashcash public rendering](examples/hashcash_public.png)
427
+
428
428
  #### To be continued...
429
429
 
430
430
  We're not done! Please check the [issues](/decidim-ice/decidim-module-decidim_awesome/issues) (and participate) to see what's on our mind
@@ -567,6 +567,16 @@ can add the environment variables to the root directory of the project in a file
567
567
  named `.rbenv-vars`. If these are defined for the environment, you can omit
568
568
  defining these in the commands shown above.
569
569
 
570
+ ### Updating formBuilder languages
571
+
572
+ There's a rake task to update the translations of the custom field's form builder interface:
573
+
574
+ ```
575
+ bundle exec rake update_form_builder_i18n
576
+ ```
577
+
578
+ This updates the `app/packs/src/vendor/form_builder_langs` folder.
579
+
570
580
  ### Code Styling
571
581
 
572
582
  Please follow the code styling defined by the different linters that ensure we
data/Rakefile CHANGED
@@ -6,6 +6,7 @@ require "fileutils"
6
6
  def install_module(path)
7
7
  Dir.chdir(path) do
8
8
  system("bundle exec rake decidim_decidim_awesome:install:migrations")
9
+ system("bundle exec rake active_hashcash:install:migrations")
9
10
  system("bundle exec rake db:migrate")
10
11
  end
11
12
  end
@@ -55,3 +56,14 @@ task :development_app do
55
56
  override_webpacker_config_files("development_app")
56
57
  seed_db("development_app")
57
58
  end
59
+
60
+ desc "Update languages for custom fields"
61
+ task :update_form_builder_i18n do
62
+ puts "Updating languages for custom fields from formbuilder-languages NPM package..."
63
+ system("npm install formbuilder-languages")
64
+ puts "Copying files..."
65
+
66
+ Dir.glob("node_modules/formbuilder-languages/*.lang").each do |file_lang|
67
+ FileUtils.cp(file_lang, "app/packs/src/vendor/form_builder_langs", verbose: true)
68
+ end
69
+ end
@@ -6,14 +6,26 @@ module Decidim
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  included do
9
+ private
10
+
9
11
  def cache_hash
10
- [
12
+ @decidim_awesome_cache_hash ||= [
11
13
  "decidim/content_blocks/global_menu",
12
14
  current_organization.cache_key_with_version,
13
15
  I18n.locale,
14
- awesome_config[:home_content_block_menu].to_s
16
+ *extra_cache_keys
15
17
  ].join(Decidim.cache_key_separator)
16
18
  end
19
+
20
+ def extra_cache_keys
21
+ [].tap do |array|
22
+ array << awesome_config[:home_content_block_menu].to_s
23
+ if defined?(current_user) && current_user
24
+ array << current_user.id
25
+ array << Decidim::Authorization.find_by(user: current_user)&.cache_key_with_version
26
+ end
27
+ end
28
+ end
17
29
  end
18
30
  end
19
31
  end
@@ -15,10 +15,11 @@ module Decidim
15
15
  end
16
16
 
17
17
  def cache_hash
18
- all_extra_fields = memoize("extra_fields")
19
- extra_fields = all_extra_fields ? all_extra_fields[resource.id] : resource.extra_fields
20
-
21
- @cache_hash ||= "#{decidim_original_cache_hash}#{Decidim.cache_key_separator}#{extra_fields&.vote_weight_totals}"
18
+ @decidim_awesome_cache_hash ||= begin
19
+ all_extra_fields = memoize("extra_fields")
20
+ extra_fields = all_extra_fields ? all_extra_fields[resource.id] : resource.extra_fields
21
+ "#{decidim_original_cache_hash}#{Decidim.cache_key_separator}#{extra_fields&.vote_weight_totals}"
22
+ end
22
23
  end
23
24
  end
24
25
  end
@@ -12,9 +12,9 @@
12
12
  voted_for?(0) ? t("decidim.decidim_awesome.voting.voting_cards.abstained") : proposal.manifest.label_for(0),
13
13
  proposal_vote_path(0),
14
14
  link_options(0).merge({
15
- title: t("decidim.decidim_awesome.voting.voting_cards.voting_for", proposal: sanitized_title, type: proposal.manifest.label_for(0)),
16
- class: "button button__sm button__transparent-secondary mb-4 vote-action abstain-button #{classes_for(0)}"
17
- }) %>
15
+ title: t("decidim.decidim_awesome.voting.voting_cards.voting_for", proposal: sanitized_title, type: proposal.manifest.label_for(0)),
16
+ class: "button button__sm button__transparent-secondary mb-4 vote-action abstain-button #{classes_for(0)}"
17
+ }) %>
18
18
  <% end %>
19
19
 
20
20
  <% if voted_for_any? && !current_settings.votes_blocked? %>
@@ -9,7 +9,7 @@
9
9
  <span class="vote-label"><%= proposal.manifest.label_for(weight) %></span>
10
10
  <%= content_tag :svg, role: "img" do
11
11
  content_tag(:title, t("decidim.decidim_awesome.voting.voting_cards.voting_for", proposal: sanitized_title, type: proposal.manifest.label_for(weight))) +
12
- content_tag(:use, "", "href" => svg_path(weight))
12
+ content_tag(:use, "", "href" => svg_path(weight))
13
13
  end %>
14
14
  <% end %>
15
15
  </div>
@@ -8,34 +8,6 @@ module Decidim
8
8
 
9
9
  included do
10
10
  layout "decidim/decidim_awesome/admin/maintenance"
11
- helper_method :current_view, :available_views, :present_private_data
12
-
13
- private
14
-
15
- def present_private_data(model)
16
- PrivateDataPresenter.new(model)
17
- end
18
-
19
- def current_view
20
- return params[:id] if available_views.include?(params[:id])
21
-
22
- available_views.keys.first
23
- end
24
-
25
- def available_views
26
- {
27
- "private_data" => {
28
- title: I18n.t("private_data", scope: "decidim.decidim_awesome.admin.menu.maintenance"),
29
- icon: "spy-line",
30
- path: decidim_admin_decidim_awesome.maintenance_path("private_data")
31
- },
32
- "checks" => {
33
- title: I18n.t("checks", scope: "decidim.decidim_awesome.admin.menu.maintenance"),
34
- icon: "pulse",
35
- path: decidim_admin_decidim_awesome.checks_maintenance_index_path
36
- }
37
- }
38
- end
39
11
  end
40
12
  end
41
13
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DecidimAwesome
5
+ module NeedsHashcash
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ include AwesomeHelpers
10
+ include ActiveHashcash
11
+
12
+ helper_method :awesome_hashcash_bits
13
+ before_action :set_hashcash_bits
14
+ before_action :awesome_check_hashcash, only: :create # rubocop:disable Rails/LexicallyScopedActionFilter
15
+ end
16
+
17
+ private
18
+
19
+ def awesome_hashcash_bits(zone)
20
+ return false unless awesome_config["hashcash_#{zone}".to_sym]
21
+
22
+ awesome_config["hashcash_#{zone}_bits".to_sym]
23
+ end
24
+
25
+ def awesome_check_hashcash
26
+ return unless set_hashcash_bits
27
+
28
+ check_hashcash
29
+ end
30
+
31
+ # Dynamically configures the gem https://github.com/BaseSecrete/active_hashcash
32
+ def set_hashcash_bits
33
+ if controller_name == "sessions"
34
+ ActiveHashcash.bits = awesome_hashcash_bits(:login)
35
+ elsif controller_name == "registrations"
36
+ ActiveHashcash.bits = awesome_hashcash_bits(:signup)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -14,9 +14,9 @@ module Decidim
14
14
  return unless Decidim::User.respond_to? :awesome_admins_for_current_scope
15
15
  return unless Decidim::User.respond_to? :awesome_potential_admins
16
16
  return unless defined? current_user
17
- return unless Decidim::User.awesome_potential_admins.include? current_user.id
17
+ return unless Decidim::User.awesome_potential_admins.include? current_user&.id
18
18
 
19
- # assiging a flash message here does not work after redirection due the order of middleware in Rails
19
+ # assigning a flash message here does not work after redirection due the order of middleware in Rails
20
20
  # as a workaround, send a message through a get parameter
21
21
  path = "/admin/?unauthorized"
22
22
  referer = request.headers["Referer"]
@@ -32,8 +32,8 @@ module Decidim
32
32
  if force_verification.present?
33
33
  create_forced_authorization
34
34
  else
35
- message = render_to_string("callout", locals: { i18n_key: "user_not_authorized", klass: "alert" })
36
- message += render_to_string("edit", locals: { with_override: true })
35
+ callout = render_to_string("callout", locals: { i18n_key: "user_not_authorized", klass: "alert" }, layout: false)
36
+ message = render_to_string("edit", locals: { with_override: true, callout: })
37
37
  end
38
38
  end
39
39
  on(:ok) do
@@ -52,10 +52,6 @@ module Decidim
52
52
  rescue ActionView::Template::Error => e
53
53
  flash.now[:alert] = "Partial [#{partial}] has thrown an error: #{e.message}"
54
54
  end
55
-
56
- def current_view
57
- "checks"
58
- end
59
55
  end
60
56
  end
61
57
  end
@@ -16,8 +16,9 @@ module Decidim
16
16
 
17
17
  def show
18
18
  @form = form(ConfigForm).from_params(organization_awesome_config)
19
+ path = main_path_for(config_var)
19
20
 
20
- redirect_to decidim_admin_decidim_awesome.checks_maintenance_index_path unless config_var
21
+ redirect_to decidim_admin_decidim_awesome.send(path[0], *path[1]) unless path[0] == :config_path
21
22
  end
22
23
 
23
24
  def update
@@ -3,13 +3,12 @@
3
3
  module Decidim
4
4
  module DecidimAwesome
5
5
  module Admin
6
- # Editing menu items
7
6
  class CustomRedirectsController < DecidimAwesome::Admin::ApplicationController
8
7
  include NeedsAwesomeConfig
9
8
  include ConfigConstraintsHelpers
10
9
 
11
10
  before_action do
12
- enforce_permission_to :edit_config, :menu
11
+ enforce_permission_to :edit_config, :custom_redirects
13
12
  end
14
13
 
15
14
  helper ConfigConstraintsHelpers
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/decidim_awesome/version"
4
+
5
+ module Decidim
6
+ module DecidimAwesome
7
+ module Admin
8
+ # System compatibility analyzer
9
+ class HashcashController < DecidimAwesome::Admin::ApplicationController
10
+ include NeedsAwesomeConfig
11
+ include MaintenanceContext
12
+ helper ConfigConstraintsHelpers
13
+
14
+ helper_method :stamps, :stamp, :addresses
15
+ before_action do
16
+ enforce_permission_to :edit_config, [:hashcash_login, :hashcash_signup]
17
+ end
18
+
19
+ def ip_addresses
20
+ render "ip_addresses"
21
+ end
22
+
23
+ private
24
+
25
+ def stamps
26
+ @stamps ||= ActiveHashcash::Stamp.filter_by(params).order(created_at: :desc).limit(1000)
27
+ end
28
+
29
+ def stamp
30
+ @stamp ||= ActiveHashcash::Stamp.find_by(id: params[:id])
31
+ end
32
+
33
+ def addresses
34
+ @addresses ||= ActiveHashcash::Stamp.filter_by(params).group(:ip_address).order(count_all: :desc).limit(1000).count
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -12,7 +12,7 @@ module Decidim
12
12
  helper_method :current_items, :visibility_options, :target_options
13
13
 
14
14
  before_action do
15
- enforce_permission_to :edit_config, :menu
15
+ enforce_permission_to :edit_config, current_menu_name
16
16
  end
17
17
 
18
18
  def index; end
@@ -6,7 +6,7 @@ module Decidim
6
6
  module DecidimAwesome
7
7
  module Admin
8
8
  # System compatibility analyzer
9
- class MaintenanceController < DecidimAwesome::Admin::ApplicationController
9
+ class PrivateDataController < DecidimAwesome::Admin::ApplicationController
10
10
  include NeedsAwesomeConfig
11
11
  include MaintenanceContext
12
12
  include Decidim::Admin::Filterable
@@ -19,36 +19,36 @@ module Decidim
19
19
  enforce_permission_to :edit_config, :private_data, private_data:
20
20
  end
21
21
 
22
- def show
22
+ def index
23
23
  respond_to do |format|
24
24
  format.json do
25
25
  render json: private_data_finder.for(params[:resources].to_s.split(",")).map { |resource| present(resource) }
26
26
  end
27
27
  format.all do
28
- render :show
28
+ render :index
29
29
  end
30
30
  end
31
31
  end
32
32
 
33
- def destroy_private_data
33
+ def destroy
34
34
  if private_data && private_data.total.to_i.positive?
35
35
  Decidim::ActionLogger.log("destroy_private_data", current_user, resource, nil, count: private_data.total)
36
36
 
37
37
  Lock.new(current_organization).get!(resource)
38
38
  DestroyPrivateDataJob.set(wait: 1.second).perform_later(resource)
39
39
  end
40
- redirect_to decidim_admin_decidim_awesome.maintenance_path("private_data"),
41
- notice: I18n.t("destroying_private_data", scope: "decidim.decidim_awesome.admin.maintenance.private_data", title: present_private_data(resource).name)
40
+ redirect_to decidim_admin_decidim_awesome.private_data_path,
41
+ notice: I18n.t("destroying", scope: "decidim.decidim_awesome.admin.private_data.private_data", title: present(resource).name)
42
42
  end
43
43
 
44
44
  private
45
45
 
46
46
  def resource
47
- @resource ||= Component.find_by(id: params[:resource_id])
47
+ @resource ||= Component.find_by(id: params[:id])
48
48
  end
49
49
 
50
50
  def private_data
51
- @private_data ||= present_private_data(resource) if resource
51
+ @private_data ||= present(resource) if resource
52
52
  end
53
53
 
54
54
  def collection
@@ -60,7 +60,7 @@ module Decidim
60
60
  end
61
61
 
62
62
  def present(resource)
63
- present_private_data(resource)
63
+ PrivateDataPresenter.new(resource)
64
64
  end
65
65
 
66
66
  def private_data_finder
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DecidimAwesome
5
+ # Abstract component class for components without any admin controllers (only settings)
6
+ class UtilsController < DecidimAwesome::ApplicationController
7
+ def form_builder_i18n
8
+ lang = I18n.locale
9
+ folder = "app/packs/src/vendor/form_builder_langs/"
10
+ file = Decidim::DecidimAwesome::Engine.root.join(folder, "#{lang}.lang")
11
+ file = Dir[Decidim::DecidimAwesome::Engine.root.join(folder, "#{lang}-*.lang")].first unless File.exist?(file)
12
+ file = Decidim::DecidimAwesome::Engine.root.join(folder, "en-US.lang") unless file && File.exist?(file)
13
+ render plain: File.read(file)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -8,7 +8,13 @@ module Decidim
8
8
 
9
9
  included do
10
10
  alias_method :decidim_original_map_model, :map_model
11
- attribute :private_body, String
11
+ attribute :private_body, Decidim::Attributes::RichText
12
+
13
+ if name == "Decidim::Proposals::ProposalForm"
14
+ # the original decidim uses CleanString, as no images are allowed for non admins
15
+ # The RichText attribute transforms signed_id blobs to ObjectIDs
16
+ attribute :body, Decidim::Attributes::RichText
17
+ end
12
18
 
13
19
  def map_model(model)
14
20
  decidim_original_map_model(model)
@@ -20,6 +20,10 @@ module Decidim
20
20
  attribute :user_timezone, Boolean
21
21
  attribute :force_authorization_after_login, Array
22
22
  attribute :force_authorization_with_any_method, Boolean
23
+ attribute :hashcash_signup, Boolean
24
+ attribute :hashcash_signup_bits, Integer, default: Decidim::DecidimAwesome.hashcash_signup_bits
25
+ attribute :hashcash_login, Boolean
26
+ attribute :hashcash_login_bits, Integer, default: Decidim::DecidimAwesome.hashcash_login_bits
23
27
  translatable_attribute :force_authorization_help_text, String
24
28
  attribute :scoped_admins, Hash
25
29
  attribute :menu, [MenuForm]
@@ -49,6 +53,8 @@ module Decidim
49
53
  validates :validate_body_min_length, presence: true, numericality: { greater_than_or_equal_to: 0 }
50
54
  validates :validate_body_max_caps_percent, presence: true, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 100 }
51
55
  validates :validate_body_max_marks_together, presence: true, numericality: { greater_than_or_equal_to: 1 }
56
+ validates :hashcash_signup_bits, presence: true, numericality: { greater_than_or_equal_to: 10, less_than_or_equal_to: 50 }
57
+ validates :hashcash_login_bits, presence: true, numericality: { greater_than_or_equal_to: 10, less_than_or_equal_to: 50 }
52
58
  validate :force_authorization_after_login_is_valid
53
59
  # TODO: validate non general admins are here
54
60
 
@@ -57,6 +63,7 @@ module Decidim
57
63
  instance.force_authorization_after_login = instance.force_authorization_after_login.compact_blank if instance.force_authorization_after_login.present?
58
64
  instance.valid_keys = extract_valid_keys_from_params(params)
59
65
  instance.sanitize_labels!
66
+ instance.sanitize_arrays!
60
67
  instance
61
68
  end
62
69
 
@@ -135,6 +142,12 @@ module Decidim
135
142
  end
136
143
  end
137
144
 
145
+ def sanitize_arrays!
146
+ scoped_admins.transform_values! do |code|
147
+ code.is_a?(Array) ? code.compact_blank : code
148
+ end
149
+ end
150
+
138
151
  private
139
152
 
140
153
  def force_authorization_after_login_is_valid
@@ -8,7 +8,7 @@ module Decidim
8
8
 
9
9
  include Decidim::TranslatableAttributes
10
10
 
11
- delegate :menus, :config_enabled?, to: "Decidim::DecidimAwesome::Menu"
11
+ delegate :menus, :main_path_for, :config_enabled?, to: "Decidim::DecidimAwesome::Menu"
12
12
 
13
13
  def check(status)
14
14
  content_tag(:span, icon(status ? "check-line" : "close-line", class: "inline-block", aria_label: status, role: "img"), class: "fill-#{status ? "success" : "alert"}")
@@ -10,7 +10,7 @@ module Decidim
10
10
  end
11
11
 
12
12
  # rubocop:disable Metrics/CyclomaticComplexity
13
- # rubocop:disable Metrics/PerceivedComplexity:
13
+ # rubocop:disable Metrics/PerceivedComplexity
14
14
  def awesome_map_for(components, &)
15
15
  return unless map_utility_dynamic
16
16
 
@@ -57,7 +57,7 @@ module Decidim
57
57
  end
58
58
  end
59
59
  # rubocop:enable Metrics/CyclomaticComplexity
60
- # rubocop:enable Metrics/PerceivedComplexity:
60
+ # rubocop:enable Metrics/PerceivedComplexity
61
61
 
62
62
  def step_settings
63
63
  settings_source.try(:current_settings)
@@ -71,6 +71,7 @@ module Decidim
71
71
  try(:current_component) || self
72
72
  end
73
73
 
74
+ # rubocop:disable Rails/HelperInstanceVariable
74
75
  def current_categories(categories)
75
76
  return @current_categories if @current_categories
76
77
 
@@ -114,6 +115,7 @@ module Decidim
114
115
  color: format("#%02x%02x%02x", r, g, b)
115
116
  )
116
117
  end
118
+ # rubocop:enable Rails/HelperInstanceVariable
117
119
 
118
120
  # HSV values in [0..1[
119
121
  # returns [r, g, b] values from 0 to 255
@@ -20,7 +20,7 @@ module Decidim
20
20
  # add users that might have been completly destroyed in any organization
21
21
  relevant_user_ids += user_ids_from_object_changes - Decidim::User.select("id").where(id: user_ids_from_object_changes).pluck(:id)
22
22
 
23
- role_changes.where("object_changes ~ ANY (array[?])", relevant_user_ids.map { |id| "decidim_user_id:\n- ?\n- #{id}" })
23
+ role_changes.where("object_changes ~ ANY (array[?])", relevant_user_ids.map { |id| "decidim_user_id:\n- ?\n- #{id}(?!\\d)" })
24
24
  }
25
25
 
26
26
  scope :in_organization, lambda { |organization|
@@ -0,0 +1,3 @@
1
+ <!-- insert_top ".login__links" -->
2
+
3
+ <%= render partial: "decidim/decidim_awesome/hashcash/hidden_field", locals: { zone: :signup } %>
@@ -0,0 +1,3 @@
1
+ <!-- insert_top ".login__links" -->
2
+
3
+ <%= render partial: "decidim/decidim_awesome/hashcash/hidden_field", locals: { zone: :login } %>
@@ -0,0 +1,3 @@
1
+ <!-- insert_after "erb[loud]:contains('content_for :header_snippets')" -->
2
+
3
+ <%= render(partial: "layouts/decidim/decidim_awesome/custom_styles") if awesome_scoped_styles.present? %>
@@ -1,7 +1,5 @@
1
1
  <!-- insert_after "erb[loud]:contains('append_stylesheet_pack_tag')" -->
2
2
 
3
3
  <% append_stylesheet_pack_tag "decidim_decidim_awesome", media: "all" %>
4
- <%= render(partial: "layouts/decidim/decidim_awesome/custom_styles") if awesome_scoped_styles.present? %>
5
-
6
4
  <% append_javascript_pack_tag "decidim_decidim_awesome", defer: false %>
7
5
  <% append_javascript_pack_tag("decidim_decidim_awesome_custom_fields") if Decidim::DecidimAwesome.enabled?(:proposal_custom_fields) %>
@@ -0,0 +1,4 @@
1
+ import Hashcash from "src/vendor/hashcash";
2
+
3
+ Hashcash.setup();
4
+