decidim-initiatives 0.30.2 → 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.
- checksums.yaml +4 -4
- data/README.md +46 -9
- data/app/cells/decidim/initiatives/content_blocks/highlighted_initiatives_settings_form/show.erb +7 -2
- data/app/cells/decidim/initiatives/initiative_g_cell.rb +5 -1
- data/app/commands/decidim/initiatives/admin/publish_initiative.rb +1 -5
- data/app/commands/decidim/initiatives/admin/update_initiative.rb +1 -2
- data/app/commands/decidim/initiatives/create_initiative.rb +0 -1
- data/app/commands/decidim/initiatives/update_initiative.rb +1 -3
- data/app/commands/decidim/initiatives/vote_initiative.rb +1 -11
- data/app/controllers/concerns/decidim/initiatives/has_signature_workflow.rb +36 -0
- data/app/controllers/concerns/decidim/initiatives/needs_initiative.rb +1 -12
- data/app/controllers/decidim/initiatives/admin/initiatives_controller.rb +2 -2
- data/app/controllers/decidim/initiatives/admin/initiatives_settings_controller.rb +1 -1
- data/app/controllers/decidim/initiatives/admin/initiatives_type_scopes_controller.rb +2 -2
- data/app/controllers/decidim/initiatives/admin/initiatives_types_controller.rb +2 -2
- data/app/controllers/decidim/initiatives/committee_requests_controller.rb +10 -2
- data/app/controllers/decidim/initiatives/create_initiative_controller.rb +84 -18
- data/app/controllers/decidim/initiatives/initiative_signatures_controller.rb +133 -42
- data/app/controllers/decidim/initiatives/initiative_votes_controller.rb +3 -2
- data/app/controllers/decidim/initiatives/initiatives_controller.rb +21 -2
- data/app/forms/decidim/initiatives/admin/initiative_form.rb +0 -1
- data/app/forms/decidim/initiatives/initiative_form.rb +0 -3
- data/app/helpers/decidim/initiatives/application_helper.rb +2 -0
- data/app/helpers/decidim/initiatives/initiatives_helper.rb +0 -1
- data/app/models/decidim/initiative.rb +7 -31
- data/app/models/decidim/initiatives_committee_member.rb +1 -1
- data/app/models/decidim/initiatives_type.rb +5 -2
- data/app/models/decidim/initiatives_vote.rb +2 -2
- data/app/packs/entrypoints/decidim_initiatives.js +1 -1
- data/app/packs/entrypoints/decidim_initiatives_admin.scss +1 -1
- data/app/packs/src/decidim/initiatives/admin/initiatives_types.js +2 -11
- data/app/packs/src/decidim/initiatives/admin/invite_users.js +1 -1
- data/app/packs/src/decidim/initiatives/application.js +1 -1
- data/app/packs/src/decidim/initiatives/check_code.js +114 -0
- data/app/packs/src/decidim/initiatives/initiative_creation_wizard.js +16 -0
- data/app/packs/src/decidim/initiatives/scoped_type.js +1 -1
- data/app/packs/stylesheets/initiatives.scss +16 -2
- data/app/permissions/decidim/initiatives/admin/permissions.rb +1 -4
- data/app/permissions/decidim/initiatives/permissions.rb +26 -16
- data/app/presenters/decidim/initiative_presenter.rb +12 -6
- data/app/presenters/decidim/initiatives/admin_log/initiative_presenter.rb +1 -2
- data/app/queries/decidim/initiatives/initiatives_stats_followers_count.rb +14 -0
- data/app/queries/decidim/initiatives/initiatives_stats_participants_count.rb +14 -0
- data/app/serializers/decidim/initiatives/open_data_initiative_serializer.rb +0 -1
- data/app/services/decidim/initiatives/data_encryptor.rb +1 -1
- data/app/services/decidim/initiatives/legacy_signature_handler.rb +25 -0
- data/app/services/decidim/initiatives/progress_notifier.rb +1 -7
- data/app/services/decidim/initiatives/signature_handler.rb +248 -0
- data/app/services/decidim/initiatives/status_change_notifier.rb +1 -7
- data/app/views/decidim/initiatives/admin/committee_requests/index.html.erb +29 -11
- data/app/views/decidim/initiatives/admin/exports/_dropdown.html.erb +17 -20
- data/app/views/decidim/initiatives/admin/initiatives/_form.html.erb +7 -13
- data/app/views/decidim/initiatives/admin/initiatives/_initiative_attachments.erb +2 -2
- data/app/views/decidim/initiatives/admin/initiatives/index.html.erb +76 -47
- data/app/views/decidim/initiatives/admin/initiatives_types/_form.html.erb +13 -21
- data/app/views/decidim/initiatives/admin/initiatives_types/_initiative_type_scopes.html.erb +28 -12
- data/app/views/decidim/initiatives/admin/initiatives_types/index.html.erb +33 -15
- data/app/views/decidim/initiatives/create_initiative/_committee_member.html.erb +27 -0
- data/app/views/decidim/initiatives/create_initiative/_return_to_initiatives_button.html.erb +3 -0
- data/app/views/decidim/initiatives/create_initiative/_send_to_technical_validation_button.html.erb +10 -0
- data/app/views/decidim/initiatives/create_initiative/_share_committee_link.html.erb +5 -1
- data/app/views/decidim/initiatives/create_initiative/fill_data.html.erb +7 -11
- data/app/views/decidim/initiatives/create_initiative/finish.html.erb +16 -13
- data/app/views/decidim/initiatives/create_initiative/promotal_committee.html.erb +33 -6
- data/app/views/decidim/initiatives/create_initiative/select_initiative_type.html.erb +40 -26
- data/app/views/decidim/initiatives/initiative_signatures/_sms_code_form.html.erb +22 -0
- data/app/views/decidim/initiatives/initiative_signatures/_sms_phone_number_form.html.erb +13 -0
- data/app/views/decidim/initiatives/initiative_signatures/fill_personal_data.html.erb +23 -22
- data/app/views/decidim/initiatives/initiative_signatures/finish.html.erb +17 -5
- data/app/views/decidim/initiatives/initiative_signatures/sms_code.html.erb +6 -8
- data/app/views/decidim/initiatives/initiative_signatures/sms_phone_number.html.erb +3 -8
- data/app/views/decidim/initiatives/initiative_signatures/update_buttons_and_counters.js.erb +3 -14
- data/app/views/decidim/initiatives/initiative_votes/update_buttons_and_counters.js.erb +3 -14
- data/app/views/decidim/initiatives/initiatives/_committee_members.html.erb +1 -1
- data/app/views/decidim/initiatives/initiatives/_form.html.erb +1 -3
- data/app/views/decidim/initiatives/initiatives/_new_initiative_button.html.erb +10 -3
- data/app/views/decidim/initiatives/initiatives/_pending_initiatives.html.erb +5 -0
- data/app/views/decidim/initiatives/initiatives/index.html.erb +8 -0
- data/app/views/decidim/initiatives/initiatives/show.html.erb +2 -2
- data/app/views/layouts/decidim/_initiative_signature_creation_header.html.erb +20 -2
- data/app/views/layouts/decidim/admin/_manage_initiatives.html.erb +1 -1
- data/app/views/layouts/decidim/initiative_signature_creation.html.erb +3 -1
- data/config/assets.rb +2 -2
- data/config/locales/ar.yml +0 -45
- data/config/locales/bg.yml +0 -54
- data/config/locales/ca-IT.yml +99 -51
- data/config/locales/ca.yml +99 -51
- data/config/locales/cs.yml +93 -54
- data/config/locales/de.yml +99 -51
- data/config/locales/el.yml +0 -45
- data/config/locales/en.yml +99 -51
- data/config/locales/es-MX.yml +99 -51
- data/config/locales/es-PY.yml +99 -51
- data/config/locales/es.yml +99 -51
- data/config/locales/eu.yml +99 -51
- data/config/locales/fi-plain.yml +99 -51
- data/config/locales/fi.yml +99 -51
- data/config/locales/fr-CA.yml +44 -51
- data/config/locales/fr.yml +44 -51
- data/config/locales/ga-IE.yml +0 -17
- data/config/locales/gl.yml +0 -41
- data/config/locales/hu.yml +0 -54
- data/config/locales/id-ID.yml +0 -40
- data/config/locales/is-IS.yml +0 -22
- data/config/locales/it.yml +0 -53
- data/config/locales/ja.yml +98 -49
- data/config/locales/lb.yml +0 -50
- data/config/locales/lt.yml +0 -56
- data/config/locales/lv.yml +0 -46
- data/config/locales/nl.yml +0 -47
- data/config/locales/no.yml +0 -53
- data/config/locales/pl.yml +0 -56
- data/config/locales/pt-BR.yml +0 -53
- data/config/locales/pt.yml +0 -53
- data/config/locales/ro-RO.yml +92 -50
- data/config/locales/ru.yml +0 -25
- data/config/locales/sk.yml +0 -43
- data/config/locales/sl.yml +0 -1
- data/config/locales/sv.yml +10 -53
- data/config/locales/tr-TR.yml +0 -53
- data/config/locales/uk.yml +0 -25
- data/config/locales/zh-CN.yml +0 -45
- data/config/locales/zh-TW.yml +0 -53
- data/db/migrate/20250605104500_remove_hashtag_column_initiatives.rb +7 -0
- data/lib/decidim/api/initiative_api_type.rb +3 -0
- data/lib/decidim/api/initiative_type.rb +23 -4
- data/lib/decidim/exporters/initiative_votes_pdf.rb +1 -1
- data/lib/decidim/initiatives/default_signature_authorizer.rb +17 -0
- data/lib/decidim/initiatives/engine.rb +17 -14
- data/lib/decidim/initiatives/participatory_space.rb +15 -1
- data/lib/decidim/initiatives/seeds.rb +1 -2
- data/lib/decidim/initiatives/signature_workflow_manifest.rb +176 -0
- data/lib/decidim/initiatives/signatures.rb +12 -0
- data/lib/decidim/initiatives/test/factories.rb +7 -7
- data/lib/decidim/initiatives/test/initiatives_signatures_test_helpers.rb +19 -0
- data/lib/decidim/initiatives/validatable_authorizations.rb +83 -0
- data/lib/decidim/initiatives/version.rb +1 -1
- data/lib/decidim/initiatives.rb +23 -12
- metadata +33 -21
- data/app/events/decidim/initiatives/endorse_initiative_event.rb +0 -13
- data/app/forms/decidim/initiatives/vote_form.rb +0 -208
- data/app/packs/src/decidim/initiatives/identity_selector_dialog.js +0 -14
- data/app/services/decidim/initiatives/pdf_signature_example.rb +0 -110
- data/app/views/decidim/initiatives/initiative_signatures/_wizard_steps.html.erb +0 -15
- data/app/views/decidim/initiatives/initiatives/_interactions.html.erb +0 -10
- data/app/views/layouts/decidim/_initiative_header.html.erb +0 -27
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.
|
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-09-
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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/
|
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/
|
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/
|
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
|
-
})
|
@@ -1,110 +0,0 @@
|
|
1
|
-
# frozen_string_literal: false
|
2
|
-
|
3
|
-
require "hexapdf"
|
4
|
-
require "tempfile"
|
5
|
-
|
6
|
-
module Decidim
|
7
|
-
module Initiatives
|
8
|
-
# Example of service to add a signature to a pdf
|
9
|
-
class PdfSignatureExample
|
10
|
-
attr_accessor :pdf
|
11
|
-
|
12
|
-
# Public: Initializes the service.
|
13
|
-
# pdf - The pdf document to be signed
|
14
|
-
def initialize(args = {})
|
15
|
-
@pdf = args.fetch(:pdf)
|
16
|
-
end
|
17
|
-
|
18
|
-
# Public: PDF signed using a new certificate generated by the service
|
19
|
-
def signed_pdf
|
20
|
-
signed_file = Tempfile.new("signed_pdf")
|
21
|
-
|
22
|
-
doc = HexaPDF::Document.new(io: StringIO.new(pdf))
|
23
|
-
|
24
|
-
# Prepare the document for embedding of the digital signature
|
25
|
-
data = nil # Used for storing the to-be-signed data
|
26
|
-
signing_mechanism = lambda do |io, byte_range|
|
27
|
-
# Store the to-be-signed data in the local variable data
|
28
|
-
io.pos = byte_range[0]
|
29
|
-
data = io.read(byte_range[1])
|
30
|
-
io.pos = byte_range[2]
|
31
|
-
data << io.read(byte_range[3])
|
32
|
-
""
|
33
|
-
end
|
34
|
-
doc.sign(signed_file.path, signature: signature_widget(doc), reason: caption, signature_size: 10_000, external_signing: signing_mechanism)
|
35
|
-
|
36
|
-
signature = OpenSSL::PKCS7.sign(certificate, key, data,
|
37
|
-
# [HexaPDF.demo_cert.sub_ca, HexaPDF.demo_cert.root_ca],
|
38
|
-
[],
|
39
|
-
OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY).to_der
|
40
|
-
|
41
|
-
# Embed the signature
|
42
|
-
HexaPDF::DigitalSignature::Signing.embed_signature(File.open(signed_file.path, "rb+"), signature)
|
43
|
-
|
44
|
-
File.binread(signed_file.path)
|
45
|
-
ensure
|
46
|
-
signed_file.close
|
47
|
-
signed_file.unlink
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
def signature_widget(doc)
|
53
|
-
form = doc.acro_form(create: true)
|
54
|
-
form.signature_flag(:append_only)
|
55
|
-
|
56
|
-
sig_field = form.create_signature_field("signature")
|
57
|
-
|
58
|
-
widget = sig_field.create_widget(doc.pages[doc.pages.length - 1], Rect: [60, 50, 250, 620])
|
59
|
-
widget.flag(:print)
|
60
|
-
xobject = (widget[:AP] ||= {})[:N] ||= doc.add({ Type: :XObject, Subtype: :Form }) # Create the appearance for the widget
|
61
|
-
xobject[:BBox] = [0, 0, widget[:Rect].width, widget[:Rect].height]
|
62
|
-
xobject.canvas
|
63
|
-
.font("Helvetica", size: 10)
|
64
|
-
.text(caption, at: [10, 30])
|
65
|
-
|
66
|
-
sig = doc.add({ Type: :Sig }) # set an empty signature and apply it to the field
|
67
|
-
sig_field.field_value = sig
|
68
|
-
sig
|
69
|
-
end
|
70
|
-
|
71
|
-
def certificate
|
72
|
-
@certificate ||= OpenSSL::X509::Certificate.new.tap do |cert|
|
73
|
-
cert.not_before = Time.current
|
74
|
-
cert.not_after = 10.years.from_now
|
75
|
-
|
76
|
-
cert.public_key = key.public_key
|
77
|
-
cert.sign(key, OpenSSL::Digest.new("SHA256"))
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def key
|
82
|
-
@key ||= OpenSSL::PKey::RSA.new(2048)
|
83
|
-
end
|
84
|
-
|
85
|
-
def caption
|
86
|
-
@caption ||= "Digitally Signed By: #{signedby}\nContact: #{contact}\nLocation: #{location}\nDate: #{date.iso8601}"
|
87
|
-
end
|
88
|
-
|
89
|
-
def signedby
|
90
|
-
"Test"
|
91
|
-
end
|
92
|
-
|
93
|
-
def location
|
94
|
-
"Barcelona"
|
95
|
-
end
|
96
|
-
|
97
|
-
def contact
|
98
|
-
"test@example.org"
|
99
|
-
end
|
100
|
-
|
101
|
-
def issuer
|
102
|
-
"Decidim"
|
103
|
-
end
|
104
|
-
|
105
|
-
def date
|
106
|
-
Time.current
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
<% scope = "layouts.decidim.initiative_signature_creation_header" %>
|
2
|
-
<ol id="wizard-steps" class="wizard-steps">
|
3
|
-
<% options = { data: { active: false }, aria: { current: "step" } } %>
|
4
|
-
|
5
|
-
<% if fill_personal_data_step? %>
|
6
|
-
<%= content_tag :li, t("fill_personal_data", scope: ),
|
7
|
-
%w(fill_personal_data update_fill_personal_data).include?(action_name) ? options : {} %>
|
8
|
-
<% end %>
|
9
|
-
<% if sms_step? %>
|
10
|
-
<%= content_tag :li, t("sms_phone_number", scope: ),
|
11
|
-
%w(sms_phone_number update_sms_phone_number).include?(action_name) ? options : {} %>
|
12
|
-
<%= content_tag :li, t("sms_code", scope: ), %w(sms_code update_sms_code).include?(action_name) ? options : {} %>
|
13
|
-
<% end %>
|
14
|
-
<%= content_tag :li, t("finish", scope: ), action_name == "finish" ? options : {} %>
|
15
|
-
</ol>
|
@@ -1,10 +0,0 @@
|
|
1
|
-
<div class="row collapse">
|
2
|
-
<div class="column collapse">
|
3
|
-
<%= link_to "#comments", class: "button small compact hollow button--nomargin expanded" do %>
|
4
|
-
<%= icon "chat-1-line", class: "icon--small", role: "img", "aria-hidden": true %>
|
5
|
-
<%= stats.comments_count %>
|
6
|
-
<%= t(".comments_count.count", count: stats.comments_count) %>
|
7
|
-
<% end %>
|
8
|
-
</button>
|
9
|
-
</div>
|
10
|
-
</div>
|
@@ -1,27 +0,0 @@
|
|
1
|
-
<div class="process-header">
|
2
|
-
<div>
|
3
|
-
<div class="row column"
|
4
|
-
style="background-image:url('<%= current_participatory_space.type.attached_uploader(:banner_image).url %>');">
|
5
|
-
</div>
|
6
|
-
<div class="row collapse column">
|
7
|
-
<div class="columns">
|
8
|
-
<div>
|
9
|
-
<h1>
|
10
|
-
<%= participatory_space_helpers.translated_attribute(current_participatory_space.title) %>
|
11
|
-
</h1>
|
12
|
-
</div>
|
13
|
-
<div>
|
14
|
-
<p>
|
15
|
-
<% if current_participatory_space.hashtag.present? %>
|
16
|
-
<span>
|
17
|
-
<%= link_to "##{current_participatory_space.hashtag}", twitter_hashtag_url(current_participatory_space.hashtag), target: "_blank" %>
|
18
|
-
</span>
|
19
|
-
<% end %>
|
20
|
-
<%= strip_tags participatory_space_helpers.translated_attribute(current_participatory_space.type.title) %>
|
21
|
-
</p>
|
22
|
-
</div>
|
23
|
-
</div>
|
24
|
-
</div>
|
25
|
-
</div>
|
26
|
-
<%= extended_navigation_bar(initiative_nav_items(current_participatory_space)) %>
|
27
|
-
</div>
|