decidim-verifications 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 +5 -5
- data/app/commands/decidim/verifications/csv_census/admin/create_census_data.rb +5 -4
- data/app/commands/decidim/verifications/csv_census/admin/create_census_record.rb +23 -0
- data/app/commands/decidim/verifications/csv_census/admin/update_census_record.rb +15 -0
- data/app/controllers/concerns/decidim/verifications/admin/filterable.rb +26 -0
- data/app/controllers/decidim/verifications/authorizations_controller.rb +1 -2
- data/app/controllers/decidim/verifications/csv_census/admin/census_controller.rb +58 -14
- data/app/controllers/decidim/verifications/csv_census/admin/census_records_controller.rb +63 -0
- data/app/controllers/decidim/verifications/id_documents/admin/config_controller.rb +1 -1
- data/app/controllers/decidim/verifications/id_documents/admin/confirmations_controller.rb +1 -1
- data/app/controllers/decidim/verifications/id_documents/admin/offline_confirmations_controller.rb +1 -1
- data/app/controllers/decidim/verifications/id_documents/authorizations_controller.rb +2 -2
- data/app/controllers/decidim/verifications/postal_letter/authorizations_controller.rb +2 -2
- data/app/controllers/decidim/verifications/sms/authorizations_controller.rb +2 -2
- data/app/forms/decidim/verifications/csv_census/admin/census_data_form.rb +29 -3
- data/app/forms/decidim/verifications/csv_census/admin/census_form.rb +29 -0
- data/app/forms/decidim/verifications/sms/mobile_phone_form.rb +2 -2
- data/app/jobs/decidim/verifications/csv_census/process_census_data_job.rb +49 -0
- data/app/models/decidim/verifications/csv_census/data.rb +13 -1
- data/app/models/decidim/verifications/csv_datum.rb +21 -0
- data/app/packs/entrypoints/decidim_verifications.js +3 -0
- data/app/packs/src/csv_census.js +47 -0
- data/app/presenters/decidim/verifications/admin_log/csv_datum_presenter.rb +45 -0
- data/app/services/decidim/authorization_handler.rb +1 -1
- data/app/views/decidim/verifications/authorizations/new.html.erb +1 -1
- data/app/views/decidim/verifications/authorizations/onboarding_pending.html.erb +1 -1
- data/app/views/decidim/verifications/csv_census/admin/census/_csv_census_drawer.html.erb +5 -0
- data/app/views/decidim/verifications/csv_census/admin/census/index.html.erb +73 -51
- data/app/views/decidim/verifications/csv_census/admin/census/new_import.html.erb +27 -0
- data/app/views/decidim/verifications/csv_census/admin/census_records/_form.html.erb +9 -0
- data/app/views/decidim/verifications/csv_census/admin/census_records/edit_record.html.erb +14 -0
- data/app/views/decidim/verifications/csv_census/admin/census_records/new_record.html.erb +14 -0
- data/app/views/decidim/verifications/postal_letter/admin/pending_authorizations/index.html.erb +33 -17
- data/config/assets.rb +2 -2
- data/config/locales/ar.yml +0 -5
- data/config/locales/bg.yml +0 -12
- data/config/locales/ca-IT.yml +62 -17
- data/config/locales/ca.yml +62 -17
- data/config/locales/cs.yml +42 -16
- data/config/locales/de.yml +61 -17
- data/config/locales/el.yml +0 -5
- data/config/locales/en.yml +62 -17
- data/config/locales/es-MX.yml +62 -17
- data/config/locales/es-PY.yml +62 -17
- data/config/locales/es.yml +62 -17
- data/config/locales/eu.yml +62 -17
- data/config/locales/fi-plain.yml +62 -17
- data/config/locales/fi.yml +62 -17
- data/config/locales/fr-CA.yml +5 -12
- data/config/locales/fr.yml +5 -12
- data/config/locales/gl.yml +0 -5
- data/config/locales/hu.yml +0 -12
- data/config/locales/id-ID.yml +0 -5
- data/config/locales/it.yml +0 -5
- data/config/locales/ja.yml +62 -17
- data/config/locales/lt.yml +0 -12
- data/config/locales/lv.yml +0 -5
- data/config/locales/nl.yml +0 -5
- data/config/locales/no.yml +0 -5
- data/config/locales/pl.yml +0 -12
- data/config/locales/pt-BR.yml +0 -5
- data/config/locales/pt.yml +0 -5
- data/config/locales/ro-RO.yml +40 -8
- data/config/locales/sk.yml +0 -5
- data/config/locales/sv.yml +61 -17
- data/config/locales/tr-TR.yml +0 -5
- data/config/locales/zh-CN.yml +0 -5
- data/config/locales/zh-TW.yml +0 -12
- data/lib/decidim/verifications/csv_census/admin_engine.rb +10 -2
- data/lib/decidim/verifications/engine.rb +1 -1
- data/lib/decidim/verifications/version.rb +1 -1
- data/lib/decidim/verifications/workflows.rb +3 -58
- data/lib/decidim/verifications.rb +1 -1
- data/lib/tasks/revoke.rake +16 -0
- metadata +22 -10
- data/app/jobs/decidim/verifications/csv_census/remove_duplicates_job.rb +0 -30
- data/lib/decidim/verifications/registry.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f5e445b04ef228652e17ed056aa508198045f6f2a8709a06e6f918ae32e31a2
|
4
|
+
data.tar.gz: e1ef5356582bcab1d2eadb41a71fde9c3980751ee08495c54e175410f10c83ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a46cbde1f71b5818775a8ef8b6f741945fd2b7bc5c3368ae849aa93e66cccf2e963cec21e7c7118616f294cd5f9b028d9c853433870fa942a8e8d2995f7976d
|
7
|
+
data.tar.gz: 78f7b084de6123dfd783f868d9ef674b25e9f35a0f2beba5150f18153fc635ca25dcf6edaa06379ad8bcbda46ba5ecdf7d4fa3e50e6cede99ce01b3ebca7da7c
|
data/README.md
CHANGED
@@ -59,7 +59,7 @@ Decidim implements two type of authorization methods:
|
|
59
59
|
To register your handler, use
|
60
60
|
|
61
61
|
```ruby
|
62
|
-
# config/initializers/
|
62
|
+
# config/initializers/decidim_verifications.rb
|
63
63
|
|
64
64
|
Decidim::Verifications.register_workflow(:census) do |workflow|
|
65
65
|
workflow.form = "<myAuthorizationHandlerClass>"
|
@@ -74,7 +74,7 @@ Decidim implements two type of authorization methods:
|
|
74
74
|
For example:
|
75
75
|
|
76
76
|
```ruby
|
77
|
-
# config/initializers/
|
77
|
+
# config/initializers/decidim_verifications.rb
|
78
78
|
|
79
79
|
Decidim::Verifications.register_workflow(:my_verification) do |workflow|
|
80
80
|
workflow.engine = Decidim::Verifications::MyVerification::Engine
|
@@ -103,7 +103,7 @@ Decidim implements two type of authorization methods:
|
|
103
103
|
Optionally to change the renew modal content part of the data stored, you can set a new value for the cell used to render the metadata.
|
104
104
|
|
105
105
|
```ruby
|
106
|
-
# config/initializers/
|
106
|
+
# config/initializers/decidim_verifications.rb
|
107
107
|
|
108
108
|
Decidim::Verifications.register_workflow(:census) do |workflow|
|
109
109
|
workflow.form = "myAuthorizationHandlerClass"
|
@@ -146,7 +146,7 @@ SMS code using your preferred provider.
|
|
146
146
|
In order to setup Decidim with SMS verification you need to:
|
147
147
|
|
148
148
|
1. Create a class that accepts two parameters when initializing it (mobile phone and code) and a method named `deliver_code` that will send an SMS and return a truthy or falsey value if the delivery was OK or not.
|
149
|
-
1. Set the `sms_gateway_service` configuration variable to the name of the class that you just created (use a String, not the actual class)
|
149
|
+
1. Set the `sms_gateway_service` configuration variable to the name of the class that you just created (use a String, not the actual class) using the `DECIDIM_SMS_GATEWAY_SERVICE` environment variable
|
150
150
|
|
151
151
|
Keep in mind that Decidim will not store a free text version of the mobile phone, only a hashed
|
152
152
|
version so we can avoid duplicates and guarantee the users' privacy.
|
@@ -217,7 +217,7 @@ To be used by the verification method, this class should be referenced by name i
|
|
217
217
|
its workflow manifest:
|
218
218
|
|
219
219
|
```ruby
|
220
|
-
# config/initializers/
|
220
|
+
# config/initializers/decidim_verifications.rb
|
221
221
|
|
222
222
|
Decidim::Verifications.register_workflow(:my_verification) do |workflow|
|
223
223
|
workflow.engine = Decidim::Verifications::MyVerification::Engine
|
@@ -7,9 +7,10 @@ module Decidim
|
|
7
7
|
# A command with the business logic to create census data for a
|
8
8
|
# organization.
|
9
9
|
class CreateCensusData < Decidim::Command
|
10
|
-
def initialize(form,
|
10
|
+
def initialize(form, current_user)
|
11
11
|
@form = form
|
12
|
-
@
|
12
|
+
@current_user = current_user
|
13
|
+
@organization = current_user.organization
|
13
14
|
end
|
14
15
|
|
15
16
|
# Executes the command. Broadcast this events:
|
@@ -21,13 +22,13 @@ module Decidim
|
|
21
22
|
return broadcast(:invalid) unless @form.file
|
22
23
|
|
23
24
|
data = @form.data
|
24
|
-
return broadcast(:invalid)
|
25
|
+
return broadcast(:invalid) if data.blank? || data.values.empty?
|
25
26
|
|
26
27
|
# rubocop:disable Rails/SkipsModelValidations
|
27
28
|
CsvDatum.insert_all(@organization, data.values)
|
28
29
|
# rubocop:enable Rails/SkipsModelValidations
|
29
|
-
RemoveDuplicatesJob.perform_later(@organization)
|
30
30
|
|
31
|
+
ProcessCensusDataJob.perform_later(data.values, @current_user)
|
31
32
|
broadcast(:ok)
|
32
33
|
end
|
33
34
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Verifications
|
5
|
+
module CsvCensus
|
6
|
+
module Admin
|
7
|
+
# A command with the business logic to create census data for a
|
8
|
+
# organization.
|
9
|
+
class CreateCensusRecord < Decidim::Commands::CreateResource
|
10
|
+
fetch_form_attributes :email, :organization
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def resource_class = Decidim::Verifications::CsvDatum
|
15
|
+
|
16
|
+
def run_after_hooks
|
17
|
+
@resource.authorize!
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Verifications
|
5
|
+
module CsvCensus
|
6
|
+
module Admin
|
7
|
+
# A command with the business logic to create census data for a
|
8
|
+
# organization.
|
9
|
+
class UpdateCensusRecord < Decidim::Commands::UpdateResource
|
10
|
+
fetch_form_attributes :email
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
module Verifications
|
7
|
+
module Admin
|
8
|
+
module Filterable
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
included do
|
12
|
+
include Decidim::Admin::Filterable
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def base_query
|
17
|
+
CsvDatum
|
18
|
+
.where(organization: current_organization)
|
19
|
+
.page(params[:page])
|
20
|
+
.per(15)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -15,7 +15,6 @@ module Decidim
|
|
15
15
|
include Decidim::HtmlSafeFlash
|
16
16
|
include Decidim::Verifications::Renewable
|
17
17
|
helper Decidim::DecidimFormHelper
|
18
|
-
helper Decidim::CtaButtonHelper
|
19
18
|
helper Decidim::AuthorizationFormHelper
|
20
19
|
helper Decidim::TranslationsHelper
|
21
20
|
|
@@ -87,7 +86,7 @@ module Decidim
|
|
87
86
|
|
88
87
|
on(:invalid) do
|
89
88
|
flash[:alert] = t("authorizations.create.error", scope: "decidim.verifications")
|
90
|
-
render action: :new
|
89
|
+
render action: :new, status: :unprocessable_entity
|
91
90
|
end
|
92
91
|
end
|
93
92
|
end
|
@@ -10,41 +10,69 @@ module Decidim
|
|
10
10
|
before_action :show_instructions,
|
11
11
|
unless: :csv_census_active?
|
12
12
|
|
13
|
+
include Decidim::Verifications::Admin::Filterable
|
13
14
|
include Decidim::Admin::WorkflowsBreadcrumb
|
15
|
+
include Decidim::Paginable
|
14
16
|
|
15
17
|
add_breadcrumb_item_from_menu :workflows_menu
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
-
|
19
|
+
helper_method :csv_census_data, :last_login
|
20
|
+
|
21
|
+
def index; end
|
22
|
+
|
23
|
+
def destroy
|
24
|
+
Decidim::Commands::DestroyResource.call(census_data, current_user) do
|
25
|
+
on(:ok) do
|
26
|
+
flash[:notice] = I18n.t("census.destroy.success", scope: "decidim.verifications.csv_census.admin")
|
27
|
+
redirect_to census_logs_path
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def new_import
|
33
|
+
@form = form(CensusDataForm).from_params(params)
|
20
34
|
@status = Status.new(current_organization)
|
21
35
|
end
|
22
36
|
|
23
|
-
def
|
37
|
+
def create_import
|
24
38
|
enforce_permission_to :create, :authorization
|
25
39
|
@form = form(CensusDataForm).from_params(params)
|
26
40
|
@status = Status.new(current_organization)
|
27
|
-
|
41
|
+
|
42
|
+
@form.validate_csv
|
43
|
+
|
44
|
+
if @form.errors.any?
|
45
|
+
error_messages = @form.errors.full_messages.map { |msg| "<li>#{msg}</li>" }.join
|
46
|
+
flash[:alert] = "<ul>#{error_messages}</ul>"
|
47
|
+
redirect_to(census_logs_path) && return
|
48
|
+
end
|
49
|
+
|
50
|
+
CreateCensusData.call(@form, current_user) do
|
28
51
|
on(:ok) do
|
29
|
-
flash[:notice] = t(".success",
|
30
|
-
redirect_to
|
52
|
+
flash[:notice] = I18n.t("census.create_import.success", scope: "decidim.verifications.csv_census.admin", count: @form.data.values.count)
|
53
|
+
redirect_to census_logs_path
|
31
54
|
end
|
32
55
|
|
33
56
|
on(:invalid) do
|
34
|
-
flash[:alert] = t(".error")
|
35
|
-
|
57
|
+
flash[:alert] = I18n.t("census.create_import.error", scope: "decidim.verifications.csv_census.admin")
|
58
|
+
redirect_to census_logs_path
|
36
59
|
end
|
37
60
|
end
|
38
61
|
end
|
39
62
|
|
40
|
-
|
41
|
-
enforce_permission_to :destroy, :authorization
|
42
|
-
CsvDatum.clear(current_organization)
|
63
|
+
private
|
43
64
|
|
44
|
-
|
65
|
+
def census_data
|
66
|
+
@census_data ||= CsvDatum.where(organization: current_organization).find(params[:id])
|
45
67
|
end
|
46
68
|
|
47
|
-
|
69
|
+
def csv_census_data
|
70
|
+
@csv_census_data ||= filtered_collection
|
71
|
+
end
|
72
|
+
|
73
|
+
def collection
|
74
|
+
@collection ||= CsvDatum.where(organization: current_organization)
|
75
|
+
end
|
48
76
|
|
49
77
|
def show_instructions
|
50
78
|
enforce_permission_to :index, :authorization
|
@@ -54,6 +82,22 @@ module Decidim
|
|
54
82
|
def csv_census_active?
|
55
83
|
current_organization.available_authorizations.include?("csv_census")
|
56
84
|
end
|
85
|
+
|
86
|
+
def last_login(data)
|
87
|
+
user = current_organization.users.available.find_by(email: data.email)
|
88
|
+
|
89
|
+
return { icon: nil, text: t(".no_user"), last_sign_in: nil } unless user
|
90
|
+
|
91
|
+
authorized = Decidim::Authorization.where(name: "csv_census", user:)
|
92
|
+
.where.not(granted_at: nil)
|
93
|
+
.exists?
|
94
|
+
|
95
|
+
icon = authorized ? "checkbox-circle-line" : "close-circle-line"
|
96
|
+
text = authorized ? t("index.authorized", scope: "decidim.verifications.csv_census.admin") : t("index.no_authorized", scope: "decidim.verifications.csv_census.admin")
|
97
|
+
last_sign_in = user.last_sign_in_at ? l(user.last_sign_in_at, format: :decidim_short) : t(".no_sign_in")
|
98
|
+
|
99
|
+
{ icon:, text:, last_sign_in: }
|
100
|
+
end
|
57
101
|
end
|
58
102
|
end
|
59
103
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Verifications
|
5
|
+
module CsvCensus
|
6
|
+
module Admin
|
7
|
+
class CensusRecordsController < Decidim::Admin::ApplicationController
|
8
|
+
layout false
|
9
|
+
|
10
|
+
helper_method :csv_census_data
|
11
|
+
|
12
|
+
def new_record
|
13
|
+
@form = form(Admin::CensusForm).instance
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_record
|
17
|
+
@form = form(Admin::CensusForm).from_params(params)
|
18
|
+
Admin::CreateCensusRecord.call(@form) do
|
19
|
+
on(:ok) do
|
20
|
+
flash[:notice] = I18n.t("census_records.create_record.success", scope: "decidim.verifications.csv_census.admin")
|
21
|
+
render json: { redirect_url: census_logs_path }, status: :ok
|
22
|
+
end
|
23
|
+
|
24
|
+
on(:invalid) do
|
25
|
+
render :new_record, status: :unprocessable_entity
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def edit_record
|
31
|
+
@form = form(Admin::CensusForm).from_model(census_data)
|
32
|
+
end
|
33
|
+
|
34
|
+
def update_record
|
35
|
+
@form = form(Admin::CensusForm).from_params(params)
|
36
|
+
|
37
|
+
Admin::UpdateCensusRecord.call(@form, census_data) do
|
38
|
+
on(:ok) do
|
39
|
+
flash[:notice] = I18n.t("census_records.update_record.success", scope: "decidim.verifications.csv_census.admin")
|
40
|
+
render json: { redirect_url: census_logs_path }, status: :ok
|
41
|
+
end
|
42
|
+
|
43
|
+
on(:invalid) do
|
44
|
+
flash.now[:alert] = I18n.t("census_records.update_record.invalid", scope: "decidim.verifications.csv_census.admin")
|
45
|
+
render action: "edit_record", status: :unprocessable_entity
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def census_data
|
53
|
+
@census_data ||= CsvDatum.where(organization: current_organization).find_by(id: params[:id])
|
54
|
+
end
|
55
|
+
|
56
|
+
def csv_census_data
|
57
|
+
@csv_census_data ||= CsvDatum.where(organization: current_organization)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -42,7 +42,7 @@ module Decidim
|
|
42
42
|
|
43
43
|
on(:invalid) do
|
44
44
|
flash.now[:alert] = t("authorizations.create.error", scope: "decidim.verifications.id_documents")
|
45
|
-
render action: :new
|
45
|
+
render action: :new, status: :unprocessable_entity
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
@@ -72,7 +72,7 @@ module Decidim
|
|
72
72
|
|
73
73
|
on(:invalid) do
|
74
74
|
flash.now[:alert] = t("authorizations.update.error", scope: "decidim.verifications.id_documents")
|
75
|
-
render action: :edit
|
75
|
+
render action: :edit, status: :unprocessable_entity
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end
|
@@ -29,7 +29,7 @@ module Decidim
|
|
29
29
|
|
30
30
|
on(:invalid) do
|
31
31
|
flash.now[:alert] = t("authorizations.create.error", scope: "decidim.verifications.postal_letter")
|
32
|
-
render :new
|
32
|
+
render :new, status: :unprocessable_entity
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -53,7 +53,7 @@ module Decidim
|
|
53
53
|
|
54
54
|
on(:invalid) do
|
55
55
|
flash.now[:alert] = t("authorizations.update.error", scope: "decidim.verifications.postal_letter")
|
56
|
-
render :edit
|
56
|
+
render :edit, status: :unprocessable_entity
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
@@ -27,7 +27,7 @@ module Decidim
|
|
27
27
|
end
|
28
28
|
on(:invalid) do
|
29
29
|
flash.now[:alert] = t("authorizations.create.error", scope: "decidim.verifications.sms")
|
30
|
-
render :new
|
30
|
+
render :new, status: :unprocessable_entity
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
@@ -52,7 +52,7 @@ module Decidim
|
|
52
52
|
|
53
53
|
on(:invalid) do
|
54
54
|
flash.now[:alert] = t("authorizations.update.error", scope: "decidim.verifications.sms")
|
55
|
-
render :edit
|
55
|
+
render :edit, status: :unprocessable_entity
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
@@ -6,16 +6,42 @@ module Decidim
|
|
6
6
|
module Admin
|
7
7
|
# A form to temporarily upload csv census data
|
8
8
|
class CensusDataForm < Form
|
9
|
+
include Decidim::HasUploadValidations
|
10
|
+
include Decidim::ProcessesFileLocally
|
9
11
|
mimic :census_data
|
10
12
|
|
11
|
-
attribute :file
|
13
|
+
attribute :file, Decidim::Attributes::Blob
|
14
|
+
|
15
|
+
validates :file, presence: true, file_content_type: { allow: ["text/csv"] }
|
12
16
|
|
13
17
|
def data
|
14
|
-
|
18
|
+
@data ||= process_data
|
19
|
+
end
|
20
|
+
|
21
|
+
def process_data
|
22
|
+
process_file_locally(file) do |file_path|
|
23
|
+
CsvCensus::Data.new(file_path)
|
24
|
+
end
|
15
25
|
rescue CSV::MalformedCSVError
|
16
26
|
errors.add(:file, :malformed)
|
27
|
+
end
|
28
|
+
|
29
|
+
def validate_csv
|
30
|
+
return unless data
|
31
|
+
|
32
|
+
errors.add(:base, I18n.t("decidim.verifications.errors.wrong_number_columns", expected: 1, actual: data.count)) if data.count != 1
|
33
|
+
|
34
|
+
errors.add(:base, I18n.t("decidim.verifications.errors.no_emails")) if data.values.empty?
|
35
|
+
|
36
|
+
data.values.each do |value|
|
37
|
+
errors.add(:base, I18n.t("decidim.verifications.errors.invalid_emails", invalid_emails: value)) unless valid_email?(value)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
17
42
|
|
18
|
-
|
43
|
+
def valid_email?(email)
|
44
|
+
URI::MailTo::EMAIL_REGEXP.match?(email)
|
19
45
|
end
|
20
46
|
end
|
21
47
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Verifications
|
5
|
+
module CsvCensus
|
6
|
+
module Admin
|
7
|
+
# A form to temporarily upload csv census data
|
8
|
+
class CensusForm < Form
|
9
|
+
attribute :email
|
10
|
+
|
11
|
+
validates :email, presence: true, "valid_email_2/email": { disposable: true }
|
12
|
+
validate :unique_email
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def unique_email
|
17
|
+
return true if CsvDatum.where(
|
18
|
+
organization: context.current_organization,
|
19
|
+
email:
|
20
|
+
).empty?
|
21
|
+
|
22
|
+
errors.add :email, :taken
|
23
|
+
false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -17,7 +17,7 @@ module Decidim
|
|
17
17
|
|
18
18
|
# A mobile phone can only be verified once but it should be private.
|
19
19
|
def unique_id
|
20
|
-
Digest::
|
20
|
+
Digest::SHA256.hexdigest(
|
21
21
|
"#{mobile_phone_number}-#{Rails.application.secret_key_base}"
|
22
22
|
)
|
23
23
|
end
|
@@ -57,7 +57,7 @@ module Decidim
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def generated_code
|
60
|
-
@generated_code ||= SecureRandom.random_number(1_000_000)
|
60
|
+
@generated_code ||= format("%06d", SecureRandom.random_number(1_000_000))
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Verifications
|
5
|
+
module CsvCensus
|
6
|
+
class ProcessCensusDataJob < ApplicationJob
|
7
|
+
queue_as :default
|
8
|
+
attr_reader :imported_records, :failed, :user
|
9
|
+
|
10
|
+
def perform(data, user)
|
11
|
+
@user = user
|
12
|
+
@imported_records = []
|
13
|
+
@failed = []
|
14
|
+
|
15
|
+
data.each do |email|
|
16
|
+
record = CsvDatum.find_or_create_by(email:, organization: user.organization)
|
17
|
+
if record && record.valid?
|
18
|
+
@imported_records << record
|
19
|
+
else
|
20
|
+
@failed << email
|
21
|
+
Rails.logger.warn(I18n.t("census.new_import.errors.email_exists", scope: "decidim.verifications.csv_census.admin", email:, organization: user.organization.id))
|
22
|
+
end
|
23
|
+
|
24
|
+
record.authorize!
|
25
|
+
end
|
26
|
+
|
27
|
+
log_import_action
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def log_import_action
|
33
|
+
return if imported_records.blank?
|
34
|
+
|
35
|
+
Decidim::ActionLogger.log(
|
36
|
+
"import",
|
37
|
+
user,
|
38
|
+
imported_records.first,
|
39
|
+
nil,
|
40
|
+
extra: {
|
41
|
+
imported_records:,
|
42
|
+
failed_count: failed.count
|
43
|
+
}
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -14,20 +14,32 @@ module Decidim
|
|
14
14
|
#
|
15
15
|
# Returns nothing
|
16
16
|
class Data
|
17
|
-
attr_reader :errors, :values
|
17
|
+
attr_reader :errors, :values, :file
|
18
18
|
|
19
19
|
def initialize(file)
|
20
20
|
@file = file
|
21
21
|
@values = []
|
22
22
|
@errors = []
|
23
|
+
@column_count = nil
|
23
24
|
|
24
25
|
CSV.foreach(@file, encoding: "BOM|UTF-8") do |row|
|
25
26
|
process_row(row)
|
27
|
+
@column_count ||= row.size
|
26
28
|
end
|
29
|
+
|
30
|
+
@errors << I18n.t("decidim.verifications.errors.wrong_number_columns", expected: 1, actual: @column_count) if @column_count && @column_count > 1
|
31
|
+
end
|
32
|
+
|
33
|
+
def count
|
34
|
+
@column_count || 0
|
27
35
|
end
|
28
36
|
|
29
37
|
private
|
30
38
|
|
39
|
+
def valid_email?(email)
|
40
|
+
URI::MailTo::EMAIL_REGEXP.match?(email)
|
41
|
+
end
|
42
|
+
|
31
43
|
def process_row(row)
|
32
44
|
user_mail = row.first
|
33
45
|
if user_mail.present? && user_mail.match?(::Devise.email_regexp)
|
@@ -3,10 +3,14 @@
|
|
3
3
|
module Decidim
|
4
4
|
module Verifications
|
5
5
|
class CsvDatum < ApplicationRecord
|
6
|
+
include Decidim::Traceable
|
7
|
+
|
6
8
|
belongs_to :organization, foreign_key: :decidim_organization_id,
|
7
9
|
class_name: "Decidim::Organization"
|
8
10
|
|
9
11
|
validates :email, format: { with: ::Devise.email_regexp }
|
12
|
+
validates :email, presence: true
|
13
|
+
validates :email, uniqueness: { scope: :decidim_organization_id }
|
10
14
|
|
11
15
|
def self.inside(organization)
|
12
16
|
where(organization:)
|
@@ -26,6 +30,23 @@ module Decidim
|
|
26
30
|
def self.clear(organization)
|
27
31
|
inside(organization).delete_all
|
28
32
|
end
|
33
|
+
|
34
|
+
def self.log_presenter_class_for(_log)
|
35
|
+
Decidim::Verifications::AdminLog::CsvDatumPresenter
|
36
|
+
end
|
37
|
+
|
38
|
+
def authorize!
|
39
|
+
user = organization.users.available.find_by(email:)
|
40
|
+
|
41
|
+
return unless user
|
42
|
+
|
43
|
+
authorization = Decidim::Authorization.find_or_initialize_by(
|
44
|
+
user:,
|
45
|
+
name: "csv_census"
|
46
|
+
)
|
47
|
+
|
48
|
+
authorization.grant! unless authorization.granted?
|
49
|
+
end
|
29
50
|
end
|
30
51
|
end
|
31
52
|
end
|