decidim-verifications 0.30.3 → 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 +66 -21
 - 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/adapter.rb +3 -3
 - 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
         
     |