decidim-initiatives 0.30.1 → 0.31.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 (147) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +46 -9
  3. data/app/cells/decidim/initiatives/content_blocks/highlighted_initiatives_settings_form/show.erb +7 -2
  4. data/app/cells/decidim/initiatives/initiative_g_cell.rb +5 -1
  5. data/app/commands/decidim/initiatives/admin/publish_initiative.rb +1 -5
  6. data/app/commands/decidim/initiatives/admin/update_initiative.rb +1 -2
  7. data/app/commands/decidim/initiatives/create_initiative.rb +0 -1
  8. data/app/commands/decidim/initiatives/update_initiative.rb +1 -3
  9. data/app/commands/decidim/initiatives/vote_initiative.rb +1 -11
  10. data/app/controllers/concerns/decidim/initiatives/has_signature_workflow.rb +36 -0
  11. data/app/controllers/concerns/decidim/initiatives/needs_initiative.rb +1 -12
  12. data/app/controllers/decidim/initiatives/admin/initiatives_controller.rb +2 -2
  13. data/app/controllers/decidim/initiatives/admin/initiatives_settings_controller.rb +1 -1
  14. data/app/controllers/decidim/initiatives/admin/initiatives_type_scopes_controller.rb +2 -2
  15. data/app/controllers/decidim/initiatives/admin/initiatives_types_controller.rb +2 -2
  16. data/app/controllers/decidim/initiatives/committee_requests_controller.rb +10 -2
  17. data/app/controllers/decidim/initiatives/create_initiative_controller.rb +84 -18
  18. data/app/controllers/decidim/initiatives/initiative_signatures_controller.rb +133 -42
  19. data/app/controllers/decidim/initiatives/initiative_votes_controller.rb +3 -2
  20. data/app/controllers/decidim/initiatives/initiatives_controller.rb +21 -2
  21. data/app/forms/decidim/initiatives/admin/initiative_form.rb +0 -1
  22. data/app/forms/decidim/initiatives/initiative_form.rb +0 -3
  23. data/app/helpers/decidim/initiatives/application_helper.rb +2 -0
  24. data/app/helpers/decidim/initiatives/initiatives_helper.rb +0 -1
  25. data/app/models/decidim/initiative.rb +7 -31
  26. data/app/models/decidim/initiatives_committee_member.rb +1 -1
  27. data/app/models/decidim/initiatives_type.rb +5 -2
  28. data/app/models/decidim/initiatives_vote.rb +2 -2
  29. data/app/packs/entrypoints/decidim_initiatives.js +1 -1
  30. data/app/packs/entrypoints/decidim_initiatives_admin.scss +1 -1
  31. data/app/packs/src/decidim/initiatives/admin/initiatives_types.js +2 -11
  32. data/app/packs/src/decidim/initiatives/admin/invite_users.js +1 -1
  33. data/app/packs/src/decidim/initiatives/application.js +1 -1
  34. data/app/packs/src/decidim/initiatives/check_code.js +114 -0
  35. data/app/packs/src/decidim/initiatives/initiative_creation_wizard.js +16 -0
  36. data/app/packs/src/decidim/initiatives/scoped_type.js +1 -1
  37. data/app/packs/stylesheets/initiatives.scss +16 -2
  38. data/app/permissions/decidim/initiatives/admin/permissions.rb +4 -7
  39. data/app/permissions/decidim/initiatives/permissions.rb +26 -16
  40. data/app/presenters/decidim/initiative_presenter.rb +12 -6
  41. data/app/presenters/decidim/initiatives/admin_log/initiative_presenter.rb +1 -2
  42. data/app/queries/decidim/initiatives/initiatives_stats_followers_count.rb +14 -0
  43. data/app/queries/decidim/initiatives/initiatives_stats_participants_count.rb +14 -0
  44. data/app/serializers/decidim/initiatives/open_data_initiative_serializer.rb +0 -1
  45. data/app/services/decidim/initiatives/data_encryptor.rb +1 -1
  46. data/app/services/decidim/initiatives/legacy_signature_handler.rb +25 -0
  47. data/app/services/decidim/initiatives/progress_notifier.rb +1 -7
  48. data/app/services/decidim/initiatives/signature_handler.rb +248 -0
  49. data/app/services/decidim/initiatives/status_change_notifier.rb +1 -7
  50. data/app/views/decidim/initiatives/admin/committee_requests/index.html.erb +29 -11
  51. data/app/views/decidim/initiatives/admin/exports/_dropdown.html.erb +17 -20
  52. data/app/views/decidim/initiatives/admin/initiatives/_form.html.erb +7 -13
  53. data/app/views/decidim/initiatives/admin/initiatives/_initiative_attachments.erb +2 -2
  54. data/app/views/decidim/initiatives/admin/initiatives/index.html.erb +76 -47
  55. data/app/views/decidim/initiatives/admin/initiatives_types/_form.html.erb +13 -21
  56. data/app/views/decidim/initiatives/admin/initiatives_types/_initiative_type_scopes.html.erb +28 -12
  57. data/app/views/decidim/initiatives/admin/initiatives_types/index.html.erb +33 -15
  58. data/app/views/decidim/initiatives/create_initiative/_committee_member.html.erb +27 -0
  59. data/app/views/decidim/initiatives/create_initiative/_return_to_initiatives_button.html.erb +3 -0
  60. data/app/views/decidim/initiatives/create_initiative/_send_to_technical_validation_button.html.erb +10 -0
  61. data/app/views/decidim/initiatives/create_initiative/_share_committee_link.html.erb +5 -1
  62. data/app/views/decidim/initiatives/create_initiative/fill_data.html.erb +7 -11
  63. data/app/views/decidim/initiatives/create_initiative/finish.html.erb +16 -13
  64. data/app/views/decidim/initiatives/create_initiative/promotal_committee.html.erb +33 -6
  65. data/app/views/decidim/initiatives/create_initiative/select_initiative_type.html.erb +40 -26
  66. data/app/views/decidim/initiatives/initiative_signatures/_sms_code_form.html.erb +22 -0
  67. data/app/views/decidim/initiatives/initiative_signatures/_sms_phone_number_form.html.erb +13 -0
  68. data/app/views/decidim/initiatives/initiative_signatures/fill_personal_data.html.erb +23 -22
  69. data/app/views/decidim/initiatives/initiative_signatures/finish.html.erb +17 -5
  70. data/app/views/decidim/initiatives/initiative_signatures/sms_code.html.erb +6 -8
  71. data/app/views/decidim/initiatives/initiative_signatures/sms_phone_number.html.erb +3 -8
  72. data/app/views/decidim/initiatives/initiative_signatures/update_buttons_and_counters.js.erb +3 -14
  73. data/app/views/decidim/initiatives/initiative_votes/update_buttons_and_counters.js.erb +3 -14
  74. data/app/views/decidim/initiatives/initiatives/_committee_members.html.erb +1 -1
  75. data/app/views/decidim/initiatives/initiatives/_form.html.erb +1 -3
  76. data/app/views/decidim/initiatives/initiatives/_new_initiative_button.html.erb +10 -3
  77. data/app/views/decidim/initiatives/initiatives/_pending_initiatives.html.erb +5 -0
  78. data/app/views/decidim/initiatives/initiatives/index.html.erb +8 -0
  79. data/app/views/decidim/initiatives/initiatives/show.html.erb +2 -2
  80. data/app/views/layouts/decidim/_initiative_signature_creation_header.html.erb +20 -2
  81. data/app/views/layouts/decidim/admin/_manage_initiatives.html.erb +1 -1
  82. data/app/views/layouts/decidim/initiative_signature_creation.html.erb +3 -1
  83. data/config/assets.rb +2 -2
  84. data/config/locales/ar.yml +0 -45
  85. data/config/locales/bg.yml +0 -54
  86. data/config/locales/ca-IT.yml +99 -51
  87. data/config/locales/ca.yml +99 -51
  88. data/config/locales/cs.yml +93 -54
  89. data/config/locales/de.yml +100 -52
  90. data/config/locales/el.yml +0 -45
  91. data/config/locales/en.yml +99 -51
  92. data/config/locales/es-MX.yml +99 -51
  93. data/config/locales/es-PY.yml +99 -51
  94. data/config/locales/es.yml +99 -51
  95. data/config/locales/eu.yml +120 -72
  96. data/config/locales/fi-plain.yml +99 -51
  97. data/config/locales/fi.yml +99 -51
  98. data/config/locales/fr-CA.yml +44 -51
  99. data/config/locales/fr.yml +44 -51
  100. data/config/locales/ga-IE.yml +0 -17
  101. data/config/locales/gl.yml +0 -41
  102. data/config/locales/hu.yml +0 -54
  103. data/config/locales/id-ID.yml +0 -40
  104. data/config/locales/is-IS.yml +0 -22
  105. data/config/locales/it.yml +0 -53
  106. data/config/locales/ja.yml +98 -49
  107. data/config/locales/lb.yml +0 -50
  108. data/config/locales/lt.yml +0 -56
  109. data/config/locales/lv.yml +0 -46
  110. data/config/locales/nl.yml +0 -47
  111. data/config/locales/no.yml +0 -53
  112. data/config/locales/pl.yml +0 -56
  113. data/config/locales/pt-BR.yml +0 -53
  114. data/config/locales/pt.yml +0 -53
  115. data/config/locales/ro-RO.yml +92 -50
  116. data/config/locales/ru.yml +0 -25
  117. data/config/locales/sk.yml +0 -43
  118. data/config/locales/sl.yml +0 -1
  119. data/config/locales/sv.yml +10 -53
  120. data/config/locales/tr-TR.yml +0 -53
  121. data/config/locales/uk.yml +0 -25
  122. data/config/locales/zh-CN.yml +0 -45
  123. data/config/locales/zh-TW.yml +0 -53
  124. data/db/migrate/20250605104500_remove_hashtag_column_initiatives.rb +7 -0
  125. data/lib/decidim/api/initiative_api_type.rb +3 -0
  126. data/lib/decidim/api/initiative_type.rb +23 -4
  127. data/lib/decidim/exporters/initiative_votes_pdf.rb +1 -1
  128. data/lib/decidim/initiatives/default_signature_authorizer.rb +17 -0
  129. data/lib/decidim/initiatives/engine.rb +17 -14
  130. data/lib/decidim/initiatives/menu.rb +1 -1
  131. data/lib/decidim/initiatives/participatory_space.rb +15 -1
  132. data/lib/decidim/initiatives/seeds.rb +1 -2
  133. data/lib/decidim/initiatives/signature_workflow_manifest.rb +176 -0
  134. data/lib/decidim/initiatives/signatures.rb +12 -0
  135. data/lib/decidim/initiatives/test/factories.rb +7 -7
  136. data/lib/decidim/initiatives/test/initiatives_signatures_test_helpers.rb +19 -0
  137. data/lib/decidim/initiatives/validatable_authorizations.rb +83 -0
  138. data/lib/decidim/initiatives/version.rb +1 -1
  139. data/lib/decidim/initiatives.rb +23 -12
  140. metadata +33 -21
  141. data/app/events/decidim/initiatives/endorse_initiative_event.rb +0 -13
  142. data/app/forms/decidim/initiatives/vote_form.rb +0 -208
  143. data/app/packs/src/decidim/initiatives/identity_selector_dialog.js +0 -14
  144. data/app/services/decidim/initiatives/pdf_signature_example.rb +0 -110
  145. data/app/views/decidim/initiatives/initiative_signatures/_wizard_steps.html.erb +0 -15
  146. data/app/views/decidim/initiatives/initiatives/_interactions.html.erb +0 -10
  147. data/app/views/layouts/decidim/_initiative_header.html.erb +0 -27
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Initiatives
5
+ # Concern to search for authorizations or try to create them and
6
+ # validate their status. If the authorization cannot be created and the
7
+ # workflow sets save_authorizations to false a new invalid authorization is
8
+ # used. This validation is not performed if no action_authorizer class name
9
+ # is set in the workflow.
10
+ module ValidatableAuthorizations
11
+ extend ActiveSupport::Concern
12
+
13
+ included do
14
+ validate :valid_authorization
15
+
16
+ delegate :action_authorizer, :save_authorizations, :action_authorizer_class, to: :workflow_manifest
17
+
18
+ def authorization_status
19
+ return unless authorization && action_authorizer_class
20
+
21
+ @authorization_status ||= action_authorizer_class.new(authorization, {}).authorize
22
+ end
23
+
24
+ def authorization
25
+ return unless user && authorization_handler_form_class
26
+
27
+ persisted_authorization = authorization_query.first
28
+ @authorization ||= if persisted_authorization.present? && persisted_authorization.unique_id == authorization_handler.unique_id
29
+ persisted_authorization
30
+ elsif save_authorizations
31
+ create_authorization
32
+ else
33
+ new_authorization
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def valid_authorization
40
+ return if authorization_status.blank?
41
+ return if authorization_status.first == :ok
42
+
43
+ errors.add(:base, I18n.t("invalid_authorization", scope: "decidim.initiatives.initiative_signatures.fill_personal_data"))
44
+ end
45
+
46
+ def create_authorization
47
+ Decidim::Verifications::AuthorizeUser.call(authorization_handler, initiative.organization) do
48
+ on(:transferred) do |transfer|
49
+ self.transfer_status = transfer
50
+ end
51
+
52
+ on(:transfer_user) do |authorized_user|
53
+ self.user = authorized_user
54
+ self.transfer_status = :transfer_user
55
+ end
56
+
57
+ on(:invalid) do
58
+ return Decidim::Authorization.new
59
+ end
60
+ end
61
+
62
+ authorization_query.first
63
+ end
64
+
65
+ def authorization_query
66
+ Verifications::Authorizations.new(**authorization_params)
67
+ end
68
+
69
+ def new_authorization
70
+ Decidim::Authorization.new(created_at: Time.current, **authorization_params)
71
+ end
72
+
73
+ def authorization_params
74
+ {
75
+ organization: initiative.organization,
76
+ user:,
77
+ name: authorization_handler_form_class.handler_name
78
+ }
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -4,7 +4,7 @@ module Decidim
4
4
  # This holds the decidim-initiatives version.
5
5
  module Initiatives
6
6
  def self.version
7
- "0.30.1"
7
+ "0.31.0.rc1"
8
8
  end
9
9
  end
10
10
  end
@@ -5,6 +5,7 @@ require "decidim/initiatives/api"
5
5
  require "decidim/initiatives/engine"
6
6
  require "decidim/initiatives/admin_engine"
7
7
  require "decidim/initiatives/participatory_space"
8
+ require "decidim/initiatives/signatures"
8
9
 
9
10
  module Decidim
10
11
  module Exporters
@@ -14,79 +15,89 @@ module Decidim
14
15
  # Base module for the initiatives engine.
15
16
  module Initiatives
16
17
  autoload :ApplicationFormPDF, "decidim/initiatives/application_form_pdf"
18
+ autoload :ValidatableAuthorizations, "decidim/initiatives/validatable_authorizations"
17
19
 
18
20
  include ActiveSupport::Configurable
19
21
 
20
22
  # Public setting that defines whether creation is allowed to any validated
21
23
  # user or not. Defaults to true.
22
24
  config_accessor :creation_enabled do
23
- true
25
+ Decidim::Env.new("INITIATIVES_CREATION_ENABLED", "auto").present?
24
26
  end
25
27
 
26
28
  # Minimum number of committee members required to pass the initiative to
27
29
  # technical validation phase. Only applies to initiatives created by
28
30
  # individuals.
29
31
  config_accessor :minimum_committee_members do
30
- 2
32
+ Decidim::Env.new("INITIATIVES_MINIMUM_COMMITTEE_MEMBERS", 2).to_i
31
33
  end
32
34
 
33
35
  # Number of days available to collect supports after an initiative has been
34
36
  # published.
35
37
  config_accessor :default_signature_time_period_length do
36
- 120
38
+ Decidim::Env.new("INITIATIVES_DEFAULT_SIGNATURE_TIME_PERIOD_LENGTH", 120).to_i
37
39
  end
38
40
 
39
41
  # Components enabled for a new initiative
40
42
  config_accessor :default_components do
41
- [:pages, :meetings, :blogs]
43
+ Decidim::Env.new("INITIATIVES_DEFAULT_COMPONENTS", "pages, meetings, blogs").to_array
42
44
  end
43
45
 
44
46
  # Notifies when the given percentage of supports is reached for an
45
47
  # initiative.
46
48
  config_accessor :first_notification_percentage do
47
- 33
49
+ Decidim::Env.new("INITIATIVES_FIRST_NOTIFICATION_PERCENTAGE", 33).to_i
48
50
  end
49
51
 
50
52
  # Notifies when the given percentage of supports is reached for an
51
53
  # initiative.
52
54
  config_accessor :second_notification_percentage do
53
- 66
55
+ Decidim::Env.new("INITIATIVES_SECOND_NOTIFICATION_PERCENTAGE", 66).to_i
54
56
  end
55
57
 
56
58
  # Sets the expiration time for the statistic data.
57
59
  config_accessor :stats_cache_expiration_time do
58
- 5.minutes
60
+ Decidim::Env.new("INITIATIVES_STATS_CACHE_EXPIRATION_TIME", 5).to_i.minutes
59
61
  end
60
62
 
61
63
  # Maximum amount of time in validating state.
62
64
  # After this time the initiative will be moved to
63
65
  # discarded state.
64
66
  config_accessor :max_time_in_validating_state do
65
- 60.days
67
+ Decidim::Env.new("INITIATIVES_MAX_TIME_IN_VALIDATING_STATE", 60).to_i.days
66
68
  end
67
69
 
68
70
  # Print functionality enabled. Allows the user to get
69
71
  # a printed version of the initiative from the administration
70
72
  # panel.
71
73
  config_accessor :print_enabled do
72
- false
74
+ Decidim::Env.new("INITIATIVES_PRINT_ENABLED", "auto").to_s == "true"
73
75
  end
74
76
 
75
77
  # Set a service to generate a timestamp on each vote. The
76
78
  # attribute is the name of a class whose instances are
77
79
  # initialized with a string containing the data to be
78
80
  # timestamped and respond to a timestamp method
79
- config_accessor :timestamp_service
81
+ config_accessor :timestamp_service do
82
+ Decidim::Env.new("DECIDIM_TIMESTAMP_SERVICE", nil).value
83
+ end
80
84
 
81
85
  # Set a service to add a signature to pdf of signatures.
82
86
  # The attribute is the name of a class whose instances are
83
87
  # initialized with the document to be signed and respond to a
84
88
  # signed_pdf method with the signature added
85
- config_accessor :pdf_signature_service
89
+ config_accessor :pdf_signature_service do
90
+ Decidim::Env.new("DECIDIM_PDF_SIGNATURE_SERVICE", nil).value
91
+ end
86
92
 
87
93
  # This flag allows creating authorizations to unauthorized users.
88
94
  config_accessor :do_not_require_authorization do
89
- false
95
+ Decidim::Env.new("INITIATIVES_DO_NOT_REQUIRE_AUTHORIZATION").present?
96
+ end
97
+
98
+ # Encryption secret to use with signatures metadata
99
+ config_accessor :signature_handler_encryption_secret do
100
+ Decidim::Env.new("INITIATIVES_SIGNATURE_HANDLER_ENCRYPTION_SECRET", "personal user metadata").to_s
90
101
  end
91
102
  end
92
103
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: decidim-initiatives
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.30.1
4
+ version: 0.31.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Salvador Perez Garcia
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-06-17 00:00:00.000000000 Z
11
+ date: 2025-09-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: decidim-admin
@@ -16,84 +16,84 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.30.1
19
+ version: 0.31.0.rc1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.30.1
26
+ version: 0.31.0.rc1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: decidim-comments
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 0.30.1
33
+ version: 0.31.0.rc1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 0.30.1
40
+ version: 0.31.0.rc1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: decidim-core
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - '='
46
46
  - !ruby/object:Gem::Version
47
- version: 0.30.1
47
+ version: 0.31.0.rc1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - '='
53
53
  - !ruby/object:Gem::Version
54
- version: 0.30.1
54
+ version: 0.31.0.rc1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: decidim-verifications
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 0.30.1
61
+ version: 0.31.0.rc1
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: 0.30.1
68
+ version: 0.31.0.rc1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: decidim-dev
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - '='
74
74
  - !ruby/object:Gem::Version
75
- version: 0.30.1
75
+ version: 0.31.0.rc1
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - '='
81
81
  - !ruby/object:Gem::Version
82
- version: 0.30.1
82
+ version: 0.31.0.rc1
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: decidim-meetings
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - '='
88
88
  - !ruby/object:Gem::Version
89
- version: 0.30.1
89
+ version: 0.31.0.rc1
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - '='
95
95
  - !ruby/object:Gem::Version
96
- version: 0.30.1
96
+ version: 0.31.0.rc1
97
97
  description: Participants initiatives plugin for decidim.
98
98
  email:
99
99
  - jsperezg@gmail.com
@@ -140,6 +140,7 @@ files:
140
140
  - app/constraints/decidim/initiatives/current_initiative.rb
141
141
  - app/controllers/concerns/decidim/initiatives/admin/filterable.rb
142
142
  - app/controllers/concerns/decidim/initiatives/admin/initiative_admin.rb
143
+ - app/controllers/concerns/decidim/initiatives/has_signature_workflow.rb
143
144
  - app/controllers/concerns/decidim/initiatives/needs_initiative.rb
144
145
  - app/controllers/concerns/decidim/initiatives/orderable.rb
145
146
  - app/controllers/concerns/decidim/initiatives/single_initiative_type.rb
@@ -177,7 +178,6 @@ files:
177
178
  - app/events/decidim/initiatives/admin/support_threshold_reached_event.rb
178
179
  - app/events/decidim/initiatives/approve_membership_request_event.rb
179
180
  - app/events/decidim/initiatives/create_initiative_event.rb
180
- - app/events/decidim/initiatives/endorse_initiative_event.rb
181
181
  - app/events/decidim/initiatives/extend_initiative_event.rb
182
182
  - app/events/decidim/initiatives/initiative_sent_to_technical_validation_event.rb
183
183
  - app/events/decidim/initiatives/milestone_completed_event.rb
@@ -191,7 +191,6 @@ files:
191
191
  - app/forms/decidim/initiatives/committee_member_form.rb
192
192
  - app/forms/decidim/initiatives/initiative_form.rb
193
193
  - app/forms/decidim/initiatives/select_initiative_type_form.rb
194
- - app/forms/decidim/initiatives/vote_form.rb
195
194
  - app/helpers/decidim/initiatives/admin/initiatives_helper.rb
196
195
  - app/helpers/decidim/initiatives/application_helper.rb
197
196
  - app/helpers/decidim/initiatives/initiative_helper.rb
@@ -215,7 +214,8 @@ files:
215
214
  - app/packs/src/decidim/initiatives/admin/initiatives_types.js
216
215
  - app/packs/src/decidim/initiatives/admin/invite_users.js
217
216
  - app/packs/src/decidim/initiatives/application.js
218
- - app/packs/src/decidim/initiatives/identity_selector_dialog.js
217
+ - app/packs/src/decidim/initiatives/check_code.js
218
+ - app/packs/src/decidim/initiatives/initiative_creation_wizard.js
219
219
  - app/packs/src/decidim/initiatives/scoped_type.js
220
220
  - app/packs/stylesheets/decidim/initiatives/admin/initiatives.scss
221
221
  - app/packs/stylesheets/initiatives.scss
@@ -232,6 +232,8 @@ files:
232
232
  - app/queries/decidim/initiatives/initiative_types.rb
233
233
  - app/queries/decidim/initiatives/initiatives_created.rb
234
234
  - app/queries/decidim/initiatives/initiatives_promoted.rb
235
+ - app/queries/decidim/initiatives/initiatives_stats_followers_count.rb
236
+ - app/queries/decidim/initiatives/initiatives_stats_participants_count.rb
235
237
  - app/queries/decidim/initiatives/organization_prioritized_initiatives.rb
236
238
  - app/queries/decidim/initiatives/outdated_validating_initiatives.rb
237
239
  - app/queries/decidim/initiatives/support_period_finished_initiatives.rb
@@ -243,8 +245,9 @@ files:
243
245
  - app/services/decidim/initiatives/diff_renderer.rb
244
246
  - app/services/decidim/initiatives/dummy_timestamp.rb
245
247
  - app/services/decidim/initiatives/initiative_search.rb
246
- - app/services/decidim/initiatives/pdf_signature_example.rb
248
+ - app/services/decidim/initiatives/legacy_signature_handler.rb
247
249
  - app/services/decidim/initiatives/progress_notifier.rb
250
+ - app/services/decidim/initiatives/signature_handler.rb
248
251
  - app/services/decidim/initiatives/status_change_notifier.rb
249
252
  - app/views/decidim/initiatives/_initiative.html.erb
250
253
  - app/views/decidim/initiatives/_modal.html.erb
@@ -267,12 +270,16 @@ files:
267
270
  - app/views/decidim/initiatives/admin/initiatives_types/index.html.erb
268
271
  - app/views/decidim/initiatives/admin/initiatives_types/new.html.erb
269
272
  - app/views/decidim/initiatives/committee_requests/new.html.erb
273
+ - app/views/decidim/initiatives/create_initiative/_committee_member.html.erb
274
+ - app/views/decidim/initiatives/create_initiative/_return_to_initiatives_button.html.erb
275
+ - app/views/decidim/initiatives/create_initiative/_send_to_technical_validation_button.html.erb
270
276
  - app/views/decidim/initiatives/create_initiative/_share_committee_link.html.erb
271
277
  - app/views/decidim/initiatives/create_initiative/fill_data.html.erb
272
278
  - app/views/decidim/initiatives/create_initiative/finish.html.erb
273
279
  - app/views/decidim/initiatives/create_initiative/promotal_committee.html.erb
274
280
  - app/views/decidim/initiatives/create_initiative/select_initiative_type.html.erb
275
- - app/views/decidim/initiatives/initiative_signatures/_wizard_steps.html.erb
281
+ - app/views/decidim/initiatives/initiative_signatures/_sms_code_form.html.erb
282
+ - app/views/decidim/initiatives/initiative_signatures/_sms_phone_number_form.html.erb
276
283
  - app/views/decidim/initiatives/initiative_signatures/error_on_vote.js.erb
277
284
  - app/views/decidim/initiatives/initiative_signatures/fill_personal_data.html.erb
278
285
  - app/views/decidim/initiatives/initiative_signatures/finish.html.erb
@@ -285,9 +292,9 @@ files:
285
292
  - app/views/decidim/initiatives/initiatives/_initiative_badge.html.erb
286
293
  - app/views/decidim/initiatives/initiatives/_initiative_hero.html.erb
287
294
  - app/views/decidim/initiatives/initiatives/_initiatives.html.erb
288
- - app/views/decidim/initiatives/initiatives/_interactions.html.erb
289
295
  - app/views/decidim/initiatives/initiatives/_new_initiative_button.html.erb
290
296
  - app/views/decidim/initiatives/initiatives/_no_initiatives_yet.html.erb
297
+ - app/views/decidim/initiatives/initiatives/_pending_initiatives.html.erb
291
298
  - app/views/decidim/initiatives/initiatives/_progress_bar.html.erb
292
299
  - app/views/decidim/initiatives/initiatives/_result.html.erb
293
300
  - app/views/decidim/initiatives/initiatives/_tags_type.html.erb
@@ -305,7 +312,6 @@ files:
305
312
  - app/views/decidim/initiatives/initiatives_type_signature_types/search.html.erb
306
313
  - app/views/decidim/initiatives/versions/show.html.erb
307
314
  - app/views/layouts/decidim/_initiative_creation_header.html.erb
308
- - app/views/layouts/decidim/_initiative_header.html.erb
309
315
  - app/views/layouts/decidim/_initiative_header_steps.html.erb
310
316
  - app/views/layouts/decidim/_initiative_signature_creation_header.html.erb
311
317
  - app/views/layouts/decidim/admin/_manage_initiatives.html.erb
@@ -459,6 +465,7 @@ files:
459
465
  - db/migrate/20220518053612_add_comments_enabled_to_initiative_types.rb
460
466
  - db/migrate/20220527130640_create_decidim_initiatives_settings.rb
461
467
  - db/migrate/20241127104718_add_taxonomy_to_initiatives_type_scope.rb
468
+ - db/migrate/20250605104500_remove_hashtag_column_initiatives.rb
462
469
  - decidim-initiatives.gemspec
463
470
  - lib/decidim/api/initiative_api_type.rb
464
471
  - lib/decidim/api/initiative_committee_member_type.rb
@@ -472,13 +479,18 @@ files:
472
479
  - lib/decidim/initiatives/application_form_pdf.rb
473
480
  - lib/decidim/initiatives/content_blocks/registry_manager.rb
474
481
  - lib/decidim/initiatives/current_locale.rb
482
+ - lib/decidim/initiatives/default_signature_authorizer.rb
475
483
  - lib/decidim/initiatives/engine.rb
476
484
  - lib/decidim/initiatives/initiative_slug.rb
477
485
  - lib/decidim/initiatives/menu.rb
478
486
  - lib/decidim/initiatives/participatory_space.rb
479
487
  - lib/decidim/initiatives/query_extensions.rb
480
488
  - lib/decidim/initiatives/seeds.rb
489
+ - lib/decidim/initiatives/signature_workflow_manifest.rb
490
+ - lib/decidim/initiatives/signatures.rb
481
491
  - lib/decidim/initiatives/test/factories.rb
492
+ - lib/decidim/initiatives/test/initiatives_signatures_test_helpers.rb
493
+ - lib/decidim/initiatives/validatable_authorizations.rb
482
494
  - lib/decidim/initiatives/version.rb
483
495
  - lib/tasks/decidim_initiatives.rake
484
496
  - lib/tasks/initiatives/upgrade/decidim_initiatives_upgrade_tasks.rake
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Decidim
4
- module Initiatives
5
- class EndorseInitiativeEvent < Decidim::Events::SimpleEvent
6
- include Decidim::Events::AuthorEvent
7
-
8
- def i18n_scope
9
- "decidim.initiatives.events.endorse_initiative_event"
10
- end
11
- end
12
- end
13
- end
@@ -1,208 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Decidim
4
- module Initiatives
5
- # A form object used to collect the data for a new initiative.
6
- class VoteForm < Form
7
- include TranslatableAttributes
8
-
9
- mimic :initiatives_vote
10
-
11
- attribute :name_and_surname, String
12
- attribute :document_number, String
13
- attribute :date_of_birth, Date
14
-
15
- attribute :postal_code, String
16
- attribute :encrypted_metadata, String
17
- attribute :hash_id, String
18
-
19
- attribute :initiative, Decidim::Initiative
20
- attribute :signer, Decidim::User
21
-
22
- validates :initiative, :signer, presence: true
23
-
24
- validates :authorized_scopes, presence: true
25
-
26
- with_options if: :required_personal_data? do
27
- validates :name_and_surname, :document_number, :date_of_birth, :postal_code, :encrypted_metadata, :hash_id, presence: true
28
- validate :document_number_authorized?
29
- validate :already_voted?
30
- end
31
-
32
- delegate :scope, to: :initiative
33
-
34
- def encrypted_metadata
35
- return unless required_personal_data?
36
-
37
- @encrypted_metadata ||= encryptor.encrypt(metadata)
38
- end
39
-
40
- # Public: The hash to uniquely identify an initiative vote. It uses the
41
- # initiative scope as a default.
42
- #
43
- # Returns a String.
44
- def hash_id
45
- return unless initiative && (document_number || signer)
46
-
47
- @hash_id ||= Digest::MD5.hexdigest(
48
- [
49
- initiative.id,
50
- document_number || signer.id,
51
- Rails.application.secret_key_base
52
- ].compact.join("-")
53
- )
54
- end
55
-
56
- # Public: Builds the list of scopes where the user is authorized to vote in. This is used when
57
- # the initiative allows also voting on child scopes, not only the main scope.
58
- #
59
- # Instead of just listing the children of the main scope, we just want to select the ones that
60
- # have been added to the InitiativeType with its voting settings.
61
- #
62
- def authorized_scopes
63
- initiative.votable_initiative_type_scopes.select do |initiative_type_scope|
64
- initiative_type_scope.global_scope? ||
65
- initiative_type_scope.scope == user_authorized_scope ||
66
- initiative_type_scope.scope.ancestor_of?(user_authorized_scope)
67
- end.flat_map(&:scope)
68
- end
69
-
70
- # Public: Finds the scope the user has an authorization for, this way the user can vote
71
- # on that scope and its parents.
72
- #
73
- # This is can be used to allow users that are authorized with a children
74
- # scope to sign an initiative with a parent scope.
75
- #
76
- # As an example: A city (global scope) has many districts (scopes with
77
- # parent nil), and each district has different neighbourhoods (with its
78
- # parent as a district). If we setup the authorization handler to match
79
- # a neighbourhood, the same authorization can be used to participate
80
- # in district, neighbourhoods or city initiatives.
81
- #
82
- # Returns a Decidim::Scope.
83
- def user_authorized_scope
84
- return scope if handler_name.blank?
85
- return unless authorized?
86
- return if authorization.metadata.blank?
87
-
88
- @user_authorized_scope ||= authorized_scope_candidates.find do |scope|
89
- scope&.id == authorization.metadata.symbolize_keys[:scope_id]
90
- end
91
- end
92
-
93
- # Public: Builds a list of Decidim::Scopes where the user could have a
94
- # valid authorization.
95
- #
96
- # If the initiative is set with a global scope (meaning the scope is nil),
97
- # all the scopes in the organization are valid.
98
- #
99
- # Returns an array of Decidim::Scopes.
100
- def authorized_scope_candidates
101
- authorized_scope_candidates = [initiative.scope]
102
- authorized_scope_candidates += if initiative.scope.present?
103
- initiative.scope.descendants
104
- else
105
- initiative.organization.scopes
106
- end
107
- authorized_scope_candidates.uniq
108
- end
109
-
110
- def metadata
111
- {
112
- name_and_surname:,
113
- document_number:,
114
- date_of_birth:,
115
- postal_code:
116
- }
117
- end
118
-
119
- protected
120
-
121
- # Private: Whether the personal data given when signing the initiative should
122
- # be stored together with the vote or not.
123
- #
124
- # Returns a Boolean.
125
- def required_personal_data?
126
- @required_personal_data ||= initiative&.type&.collect_user_extra_fields?
127
- end
128
-
129
- # Private: Checks that the unique hash computed from the authorization
130
- # and the user provided data match.
131
- #
132
- # This prevents users that know partial data from another user to sign
133
- # initiatives with someone elses identity.
134
- def document_number_authorized?
135
- return if initiative.document_number_authorization_handler.blank?
136
-
137
- errors.add(:document_number, :invalid) unless authorized? && authorization_handler && authorization.unique_id == authorization_handler.unique_id
138
- end
139
-
140
- # Private: Checks if there is any existing vote that matches the user's data.
141
- def already_voted?
142
- errors.add(:document_number, :taken) if initiative.votes.exists?(hash_id:, scope:)
143
- end
144
-
145
- def author
146
- @author ||= current_organization.users.find_by(id: author_id)
147
- end
148
-
149
- # Private: Finds an authorization for the user signing the initiative and
150
- # the configured handler.
151
- def authorization
152
- return unless signer && handler_name
153
-
154
- @authorization ||= Verifications::Authorizations.new(
155
- organization: signer.organization,
156
- user: signer,
157
- name: handler_name
158
- ).first
159
- end
160
-
161
- # Private: Checks if the authorization has not expired or is invalid.
162
- def authorized?
163
- authorization_status&.first == :ok
164
- end
165
-
166
- # Private: Builds an authorization handler with the data the user provided
167
- # when signing the initiative.
168
- #
169
- # This is currently tied to authorization handlers that have, at least, these attributes:
170
- # * document_number
171
- # * name_and_surname
172
- # * date_of_birth
173
- # * postal_code
174
- #
175
- # Once we have the authorization handler we can use is to compute the
176
- # unique_id and compare it to an existing authorization.
177
- #
178
- # Returns a Decidim::AuthorizationHandler.
179
- def authorization_handler
180
- return unless document_number && handler_name
181
-
182
- @authorization_handler ||= Decidim::AuthorizationHandler.handler_for(handler_name,
183
- document_number:,
184
- name_and_surname:,
185
- date_of_birth:,
186
- postal_code:)
187
- end
188
-
189
- # Private: The AuthorizationHandler name used to verify the user's
190
- # document number.
191
- #
192
- # Returns a String.
193
- def handler_name
194
- initiative.document_number_authorization_handler
195
- end
196
-
197
- def authorization_status
198
- return unless authorization
199
-
200
- Decidim::Verifications::Adapter.from_element(handler_name).authorize(authorization, {}, nil, nil)
201
- end
202
-
203
- def encryptor
204
- @encryptor ||= DataEncryptor.new(secret: "personal user metadata")
205
- end
206
- end
207
- end
208
- end
@@ -1,14 +0,0 @@
1
- $(() => {
2
- let button = $("#select-identity-button"),
3
- userIdentitiesDialog = $("#user-identities");
4
-
5
- if (userIdentitiesDialog.length) {
6
- let refreshUrl = userIdentitiesDialog.data("refresh-url");
7
-
8
- button.click(function () {
9
- $.ajax(refreshUrl).done(function(response) {
10
- userIdentitiesDialog.html(response).foundation("open");
11
- });
12
- });
13
- }
14
- })