decidim-file_authorization_handler 0.27.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +661 -0
  3. data/README.md +137 -0
  4. data/Rakefile +3 -0
  5. data/app/controllers/decidim/file_authorization_handler/admin/censuses_controller.rb +34 -0
  6. data/app/jobs/decidim/file_authorization_handler/application_job.rb +8 -0
  7. data/app/jobs/decidim/file_authorization_handler/remove_duplicates_job.rb +30 -0
  8. data/app/models/decidim/file_authorization_handler/application_record.rb +9 -0
  9. data/app/models/decidim/file_authorization_handler/census_datum.rb +70 -0
  10. data/app/models/decidim/file_authorization_handler/csv_data.rb +40 -0
  11. data/app/models/decidim/file_authorization_handler/status.rb +27 -0
  12. data/app/permissions/decidim/file_authorization_handler/admin/permissions.rb +27 -0
  13. data/app/services/file_authorization_handler.rb +59 -0
  14. data/app/views/decidim/file_authorization_handler/admin/censuses/show.html.erb +39 -0
  15. data/app/views/layouts/file_authorization_handler/application.html.erb +14 -0
  16. data/config/locales/ca.yml +50 -0
  17. data/config/locales/en.yml +50 -0
  18. data/config/locales/es.yml +50 -0
  19. data/db/migrate/20171110120821_create_decidim_file_authorization_handler_census_datum.rb +15 -0
  20. data/db/migrate/20221207143742_add_extras_to_census_datum.rb +7 -0
  21. data/lib/decidim/file_authorization_handler/admin.rb +10 -0
  22. data/lib/decidim/file_authorization_handler/admin_engine.rb +23 -0
  23. data/lib/decidim/file_authorization_handler/engine.rb +22 -0
  24. data/lib/decidim/file_authorization_handler/version.rb +12 -0
  25. data/lib/decidim/file_authorization_handler.rb +11 -0
  26. data/spec/controllers/decidim/file_authorization_handler/admin/censuses_controller_spec.rb +57 -0
  27. data/spec/factories/census_datum.rb +14 -0
  28. data/spec/factories/factories.rb +3 -0
  29. data/spec/fixtures/files/data-with_extras.csv +5 -0
  30. data/spec/fixtures/files/data1.csv +4 -0
  31. data/spec/fixtures/files/with-errors.csv +7 -0
  32. data/spec/helpers/decidim/file_authorization_handler/encoding_helper.rb +11 -0
  33. data/spec/jobs/decidim/file_authorization_handler/remove_duplicates_job_spec.rb +20 -0
  34. data/spec/models/decidim/file_authorization_handler/census_datum_spec.rb +75 -0
  35. data/spec/models/decidim/file_authorization_handler/csv_data_spec.rb +41 -0
  36. data/spec/models/decidim/file_authorization_handler/status_spec.rb +21 -0
  37. data/spec/permissions/decidim/file_authorization_handler/admin/permissions_spec.rb +58 -0
  38. data/spec/services/decidim/file_authorization_handler/file_authorization_handler_spec.rb +77 -0
  39. data/spec/spec_helper.rb +23 -0
  40. metadata +196 -0
data/README.md ADDED
@@ -0,0 +1,137 @@
1
+ # Decidim File Authorization Handler
2
+
3
+ > A plugin to add a csv based authorization handler to the Decidim platform
4
+
5
+ Allows admin users to upload a CSV file containing Document IDs and birthdates
6
+ to a given organization.
7
+ This information is used by a Decidim authorization handler to authorize real
8
+ users.
9
+
10
+ ## Usage
11
+
12
+ This module provides a model `Decidim::FileAuthorizationHandler::CensusDatum`
13
+ to store census information (identity document and birth date) in a hashed way
14
+ (real data is never stored).
15
+
16
+ It has an admin controller to upload CSV files with the information. When
17
+ importing files all records are inserted and the duplicates are removed in a
18
+ background job for performance reasons.
19
+
20
+ To keep the plugin simple the uploaded file is processed when the file is
21
+ uploaded.
22
+ Uploading the file to a temporary storage system and processing it in
23
+ background is kept out of the scope for the first release.
24
+
25
+ ### CSV file format
26
+
27
+ The CSV file format is not configurable, but is extendable. The plugin expects a comma separated
28
+ CSV with headers:
29
+
30
+ ```console
31
+ ID_NUMBER,BIRTH_DATE
32
+ 00000000Z,07/03/2014
33
+ ```
34
+
35
+ - ID_NUMBER: No format restrictions
36
+ - BIRTHDATE: `dd/mm/YYYY` format
37
+
38
+ The CSV separator can be overriden at installation level by using an
39
+ initializer:
40
+
41
+ ```ruby
42
+ # config/initializers/file_authorization_handler.rb
43
+ Decidim::FileAuthorizationHandler::CsvData.col_sep= ";"
44
+ ```
45
+
46
+ #### Extra columns
47
+
48
+ Sometimes extra fields must be provided in order for Authorizers to do some census segmentation. This, for example,
49
+ happens when a specific authorizer checks for the district of the citizen.
50
+
51
+ Since v0.26.2.5 this module supports a variable number of extra columns for each user. These columns are then persisted
52
+ in the `CensusDatum#extras` column as a hash of fields.
53
+
54
+ Take, for example, the following CSV file
55
+
56
+ ```console
57
+ ID_NUMBER,BIRTH_DATE,DISTRICT
58
+ 00000000Z,07/03/2014,17600
59
+ ```
60
+
61
+ it will be imported into the `CensusDatum` as `{"district" => "17600"}`.
62
+
63
+ Then, once the user is verified, all `CensusDaum#extras` will be added to the `Authorization#metadata` together with the `birthdate`. This way, custom authorizers will be able to make use of this information.
64
+
65
+ Implementors and administrators must respect User Privacy and be aware of the corresponding Rules.
66
+
67
+ ### Overriding Authorization Handler name
68
+
69
+ The authorization handler name is a default one not suitable for end users.
70
+ Depending on the use case of the gem needs to be overriden accordingly.
71
+
72
+ Override the following keys to modify the name of the authorization handler and
73
+ its description:
74
+
75
+ `decidim.authorization_handlers.file_authorization_handler.name`
76
+ `decidim.authorization_handlers.file_authorization_handler.description`
77
+
78
+ You can also override the name of the ID document and birthdate fields:
79
+
80
+ `activemodel.attributes.file_authorization_handler.id_document`
81
+ `activemodel.attributes.file_authorization_handler.birthdate`
82
+
83
+ ## Installation
84
+
85
+ Add this line to your application's Gemfile:
86
+
87
+ ```ruby
88
+ gem 'decidim-file_authorization_handler'
89
+ ```
90
+
91
+ And then execute:
92
+
93
+ ```bash
94
+ bundle
95
+ bin/rails decidim_file_authorization_handler:install:migrations
96
+ bin/rails db:migrate
97
+ ```
98
+
99
+ Finally, add the following line to your `config/routes.rb` file:
100
+
101
+ ```ruby
102
+ mount Decidim::FileAuthorizationHandler::AdminEngine => '/admin'
103
+ ```
104
+
105
+ ## Run tests
106
+
107
+ Node 16.9.1 is required!
108
+
109
+ Create a dummy app in your application (if not present):
110
+
111
+ ```bash
112
+ bin/rails decidim:generate_external_test_app
113
+ cd spec/decidim_dummy_app/
114
+ bundle exec rails decidim_file_authorization_handler:install:migrations
115
+ RAILS_ENV=test bundle exec rails db:migrate
116
+ ```
117
+
118
+ And run tests:
119
+
120
+ ```bash
121
+ bundle exec rspec spec
122
+ ```
123
+
124
+ ## Troubleshooting
125
+
126
+ If you find the following error after you have installed the engine:
127
+
128
+ ```
129
+ undefined method 'decidim_file_authorization_handler_admin_path'
130
+ for module#<Module:0x00007fa2aa4e2a10>
131
+ ```
132
+
133
+ review if you have mounted the Engine routes into your application routes.
134
+
135
+ ## License
136
+
137
+ AGPLv3 (same as Decidim)
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/dev/common_rake"
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module FileAuthorizationHandler
5
+ module Admin
6
+ class CensusesController < Decidim::Admin::ApplicationController
7
+ def show
8
+ enforce_permission_to :show, :authorization
9
+ @status = Status.new(current_organization)
10
+ end
11
+
12
+ def create
13
+ enforce_permission_to :create, :authorization
14
+ if params[:file]
15
+ data = CsvData.new(params[:file].path)
16
+ # rubocop: disable Rails/SkipsModelValidations
17
+ CensusDatum.insert_all(current_organization, data.values, data.headers[2..])
18
+ # rubocop: enable Rails/SkipsModelValidations
19
+ RemoveDuplicatesJob.perform_later(current_organization)
20
+ flash[:notice] = t(".success", count: data.values.count,
21
+ errors: data.errors.count)
22
+ end
23
+ redirect_to censuses_path
24
+ end
25
+
26
+ def destroy
27
+ enforce_permission_to :destroy, :authorization, organization: current_organization
28
+ CensusDatum.clear(current_organization)
29
+ redirect_to censuses_path, notice: t(".success")
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module FileAuthorizationHandler
5
+ class ApplicationJob < ActiveJob::Base
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module FileAuthorizationHandler
5
+ class RemoveDuplicatesJob < ApplicationJob
6
+ queue_as :default
7
+
8
+ # rubocop:disable Style/HashSyntax
9
+ def perform(organization)
10
+ duplicated_census(organization).pluck(:id_document).each do |id_document|
11
+ CensusDatum.inside(organization)
12
+ .where(id_document: id_document)
13
+ .order(id: :desc)
14
+ .all[1..]
15
+ .each(&:delete)
16
+ end
17
+ end
18
+ # rubocop:enable Style/HashSyntax
19
+
20
+ private
21
+
22
+ def duplicated_census(organization)
23
+ CensusDatum.inside(organization)
24
+ .select(:id_document)
25
+ .group(:id_document)
26
+ .having("count(id_document)>1")
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module FileAuthorizationHandler
5
+ class ApplicationRecord < ActiveRecord::Base
6
+ self.abstract_class = true
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module FileAuthorizationHandler
5
+ class CensusDatum < ApplicationRecord
6
+ belongs_to :organization, foreign_key: :decidim_organization_id,
7
+ class_name: "Decidim::Organization"
8
+ # An organzation scope
9
+ def self.inside(organization)
10
+ where(decidim_organization_id: organization.id)
11
+ end
12
+
13
+ # Search for a specific document id inside a organization
14
+ def self.search_id_document(organization, id_document)
15
+ CensusDatum.inside(organization)
16
+ .where(id_document: normalize_and_encode_id_document(id_document))
17
+ .order(created_at: :desc, id: :desc)
18
+ .first
19
+ end
20
+
21
+ # Normalizes a id document string (remove invalid characters) and encode it
22
+ # to conform with Decidim privacy guidelines.
23
+ def self.normalize_and_encode_id_document(id_document)
24
+ return "" unless id_document
25
+
26
+ id_document = id_document.gsub(/[^A-z0-9]/, "").upcase
27
+ return "" if id_document.blank?
28
+
29
+ Digest::SHA256.hexdigest(
30
+ "#{id_document}-#{Rails.application.secrets.secret_key_base}"
31
+ )
32
+ end
33
+
34
+ # Convert a date from string to a Date object
35
+ def self.parse_date(string)
36
+ Date.strptime((string || "").strip, "%d/%m/%Y")
37
+ rescue StandardError
38
+ nil
39
+ end
40
+
41
+ # Insert a collection of values
42
+ def self.insert_all(organization, values, extra_headers = nil)
43
+ return if values.empty?
44
+
45
+ table_name = CensusDatum.table_name
46
+ columns = %w(id_document birthdate decidim_organization_id created_at).join(",")
47
+ columns = "#{columns},extras" if extra_headers.present?
48
+ now = Time.current
49
+ values = values.map do |row|
50
+ vals = "('#{row[0]}', '#{row[1]}', '#{organization.id}', '#{now}'"
51
+ if extra_headers.present?
52
+ extras = {}
53
+ extra_headers.present? && extra_headers.each_with_index do |header, idx|
54
+ extras[header.downcase] = row[2 + idx]
55
+ end
56
+ vals += ", '#{extras.to_json}'"
57
+ end
58
+ "#{vals})"
59
+ end
60
+ sql = "INSERT INTO #{table_name} (#{columns}) VALUES #{values.join(",")}"
61
+ ActiveRecord::Base.connection.execute(sql)
62
+ end
63
+
64
+ # Clear all census data for a given organization
65
+ def self.clear(organization)
66
+ CensusDatum.inside(organization).delete_all
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "csv"
4
+
5
+ module Decidim
6
+ module FileAuthorizationHandler
7
+ class CsvData
8
+ @col_sep = ","
9
+ class << self; attr_accessor :col_sep end
10
+
11
+ attr_reader :errors, :values, :headers
12
+
13
+ def initialize(file)
14
+ @file = file
15
+ @errors = []
16
+ @values = []
17
+
18
+ Rails.logger.info "CsvData.col_sep: #{CsvData.col_sep}"
19
+ CSV.foreach(@file, headers: true, col_sep: CsvData.col_sep) do |row|
20
+ @headers = row.headers
21
+ process_row(row)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def process_row(row)
28
+ id_document = CensusDatum.normalize_and_encode_id_document(row[0])
29
+ date = CensusDatum.parse_date(row[1])
30
+
31
+ if id_document.present? && !date.nil?
32
+ data = [id_document, date] + row[2..]
33
+ values << data
34
+ else
35
+ errors << row
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module FileAuthorizationHandler
5
+ # Provides information about the current status of the census data
6
+ # for a given organization
7
+ class Status
8
+ def initialize(organization)
9
+ @organization = organization
10
+ end
11
+
12
+ # Returns the date of the last import
13
+ def last_import_at
14
+ @last ||= CensusDatum.inside(@organization)
15
+ .order(created_at: :desc).first
16
+ @last ? @last.created_at : nil
17
+ end
18
+
19
+ # Returns the number of unique census
20
+ def count
21
+ @count ||= CensusDatum.inside(@organization)
22
+ .distinct.count(:id_document)
23
+ @count
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module FileAuthorizationHandler
5
+ module Admin
6
+ # Defines the abilities related to surveys for a logged in admin user.
7
+ class Permissions < Decidim::DefaultPermissions
8
+ def permissions
9
+ return permission_action if permission_action.scope != :admin
10
+
11
+ if user.organization.available_authorizations.include?("file_authorization_handler") &&
12
+ permission_action_in?(:show, :create, :destroy) &&
13
+ permission_action.subject == Decidim::FileAuthorizationHandler::CensusDatum
14
+ allow!
15
+ end
16
+ permission_action
17
+ end
18
+
19
+ private
20
+
21
+ def permission_action_in?(*actions)
22
+ actions.any? { |action| permission_action.action == action }
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ # An AuthorizationHandler that uses information uploaded from a CSV file
4
+ # to authorize against the age of the user
5
+ class FileAuthorizationHandler < Decidim::AuthorizationHandler
6
+ # This is the input (from the user) to validate against
7
+ attribute :id_document, String
8
+ attribute :birthdate, Decidim::Attributes::LocalizedDate
9
+
10
+ # This is the validation to perform
11
+ # If passed, an authorization is created
12
+ validates :id_document, presence: true
13
+ validates :birthdate, presence: true
14
+ validate :censed
15
+
16
+ def metadata
17
+ @metadata ||= begin
18
+ meta = { birthdate: census_for_user&.birthdate&.strftime("%Y/%m/%d") }
19
+ census_for_user&.extras&.each_pair do |key, value|
20
+ meta[key.to_sym] = value
21
+ end
22
+ meta
23
+ end
24
+ end
25
+
26
+ # This is required in new 0.8.4 version of decicim
27
+ # however, there's a bug and this doesn't work
28
+ def handler_name
29
+ +"file_authorization_handler"
30
+ end
31
+
32
+ # Checks if the id_document belongs to the census
33
+ def censed
34
+ return if census_for_user&.birthdate == birthdate
35
+
36
+ errors.add(:id_document, I18n.t("decidim.file_authorization_handler.errors.messages.not_censed"))
37
+ end
38
+
39
+ def authorized?
40
+ return true if census_for_user
41
+ end
42
+
43
+ def unique_id
44
+ return nil unless organization
45
+
46
+ Digest::SHA256.hexdigest("#{census_for_user&.id_document}-#{organization.id}-#{Rails.application.secrets.secret_key_base}")
47
+ end
48
+
49
+ def census_for_user
50
+ return unless organization
51
+
52
+ @census_for_user ||= Decidim::FileAuthorizationHandler::CensusDatum
53
+ .search_id_document(organization, id_document)
54
+ end
55
+
56
+ def organization
57
+ current_organization || user&.organization
58
+ end
59
+ end
@@ -0,0 +1,39 @@
1
+
2
+ <div class="card">
3
+ <div class="card-divider">
4
+ <h2 class="card-title">
5
+ <%= t('admin.show.title', scope: 'decidim.file_authorization_handler') %>
6
+ </h2>
7
+ </div>
8
+ <div class="card-section">
9
+ <% if @status.count > 0 %>
10
+ <p><%= t('decidim.file_authorization_handler.admin.show.data', count: @status.count,
11
+ due_date: l(@status.last_import_at, format: :long)) %>
12
+ </p>
13
+ <%= link_to t('decidim.file_authorization_handler.admin.destroy.title'),
14
+ censuses_path,
15
+ method: :delete,
16
+ class: 'button alert',
17
+ data: { confirm: t('decidim.file_authorization_handler.admin.destroy.confirm') } %>
18
+ <% else %>
19
+ <p><%= t('admin.show.empty', scope: 'decidim.file_authorization_handler') %></p>
20
+ <% end %>
21
+ </div>
22
+ </div>
23
+
24
+
25
+ <div class="card">
26
+ <div class="card-divider">
27
+ <h2 class="card-title">
28
+ <%= t('admin.new.title', scope: 'decidim.file_authorization_handler') %>
29
+ </h2>
30
+ </div>
31
+ <div class="card-section">
32
+ <p><%= t('decidim.file_authorization_handler.admin.new.info') %></p>
33
+ <%= form_tag censuses_path, multipart: true, class: 'form' do %>
34
+ <%= label_tag :name, t('admin.new.file', scope: 'decidim.file_authorization_handler') %>
35
+ <%= file_field_tag :file %>
36
+ <%= submit_tag t('admin.new.submit', scope: 'decidim.file_authorization_handler'), class: 'button' %>
37
+ <% end %>
38
+ </div>
39
+ </div>
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Census</title>
5
+ <%= stylesheet_link_tag "census/application", media: "all" %>
6
+ <%= javascript_include_tag "census/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,50 @@
1
+ ca:
2
+ activemodel:
3
+ attributes:
4
+ file_authorization_handler:
5
+ id_document: Document d'identitat (DNI, NIF, Passaport o Targeta de Residència)
6
+ birthdate: Data de naixement
7
+ census_authorization:
8
+ form:
9
+ date_select:
10
+ day: Dia
11
+ month: Mes
12
+ year: Any
13
+ decidim:
14
+ authorization_handlers:
15
+ file_authorization_handler:
16
+ name: Cens Organització
17
+ explanation: Autoritza el teu compte d'usuari contra el cens de la Organització
18
+ type: CSV
19
+ fields:
20
+ birthdate: Data de naixement
21
+ file_authorization_handler:
22
+ errors:
23
+ messages:
24
+ not_censed: No hem pogut trobar el teu document d'identitat amb aquesta data de naixement al padró municipal. Si les dades són correctes i el problema persisteix, siusplau, posa't en contacte amb un administrador.
25
+ younger_than_minimum_age: Hauries de ser major de %{age} anys
26
+ admin:
27
+ destroy:
28
+ title: Esborrar totes les dades del cens
29
+ confirm: Aquesta acció no es pot desfer. Estàs segur/a que voleu continuar?
30
+ censuses:
31
+ create:
32
+ success: S'han importat amb èxit %{count} elements (%{errors} errors)
33
+ destroy:
34
+ success: S'han esborrat totes les dades censals
35
+ menu:
36
+ census: Pujar cens
37
+ show:
38
+ title: Dades del cens carregat
39
+ data: Hi ha un total de %{count} registres carregats. La última càrrega va ser el dia %{due_date}
40
+ empty: Encara no hi ha dades censals carregades. Utilitza el següent formulari per importar-lo utilitzant un fitxer CSV.
41
+ new:
42
+ info: "Ha de ser un fitxer generat en excel i exportat en CSV amb dues columnes: document d'identitat i data de naixement"
43
+ title: Pujar un nou cens
44
+ file: Arxiu excel .csv amb les dades del cens
45
+ submit: Carrega
46
+ verifications:
47
+ authorizations:
48
+ first_login:
49
+ actions:
50
+ file_authorization_handler: Verifica't amb el cens de l'organització
@@ -0,0 +1,50 @@
1
+ en:
2
+ activemodel:
3
+ attributes:
4
+ file_authorization_handler:
5
+ id_document: Identification document (DNI, NIF, Password or Residence Card)
6
+ birthdate: Date of birth
7
+ census_authorization:
8
+ form:
9
+ date_select:
10
+ day: Day
11
+ month: Month
12
+ year: Year
13
+ decidim:
14
+ authorization_handlers:
15
+ file_authorization_handler:
16
+ name: Organization's Census
17
+ explanation: Authorize your user account against Organization's Census
18
+ type: CSV
19
+ fields:
20
+ birthdate: Birthdate
21
+ file_authorization_handler:
22
+ errors:
23
+ messages:
24
+ not_censed: We could not find your document ID matching with this birthdate in our Census. If the data entered is correct and the problem persists, please, contact an administrator.
25
+ younger_than_minimum_age: You should be older than %{age} years
26
+ admin:
27
+ destroy:
28
+ title: Delete all census data
29
+ confirm: Delete all the census can not be undone. Are you sure you want to continue?
30
+ censuses:
31
+ create:
32
+ success: Successfully imported %{count} items (%{errors} errors)
33
+ destroy:
34
+ success: All census data have been deleted
35
+ menu:
36
+ census: Upload census
37
+ show:
38
+ title: Current census data
39
+ data: There are %{count} records loaded in total. Last upload date was on %{due_date}
40
+ empty: There are no census data. Use the form below to import it using a CSV file.
41
+ new:
42
+ info: 'Must be a file generated by excel and exported with CSV format with two columns: identity document and date of birth'
43
+ title: Upload a new census
44
+ file: Excel .csv file with census data
45
+ submit: Upload file
46
+ verifications:
47
+ authorizations:
48
+ first_login:
49
+ actions:
50
+ file_authorization_handler: Get verified by organization's census
@@ -0,0 +1,50 @@
1
+ es:
2
+ activemodel:
3
+ attributes:
4
+ file_authorization_handler:
5
+ id_document: Documento de identidad (DNI, NIF, Pasaporte o Targeta de Residencia)
6
+ birthdate: Fecha de nacimiento
7
+ census_authorization:
8
+ form:
9
+ date_select:
10
+ day: Día
11
+ month: Mes
12
+ year: Año
13
+ decidim:
14
+ authorization_handlers:
15
+ file_authorization_handler:
16
+ name: Censo de la Organización
17
+ explanation: Autoriza tu cuenta de usuario contra el Censo de la Organización
18
+ type: CSV
19
+ fields:
20
+ birthdate: Fecha de nacimiento
21
+ file_authorization_handler:
22
+ errors:
23
+ messages:
24
+ not_censed: No hemos podido encontrar tu documento de identidad con esta fecha de nacimiento en el padrón municipal. Si tus datos son correctos y el problema persiste, por favor, ponte en contacto con un administrador
25
+ younger_than_minimum_age: Deberías ser mayor de %{age} años
26
+ admin:
27
+ destroy:
28
+ title: Borrar todos los datos de censo
29
+ confirm: Borrar el censo no se puede deshacer. ¿Estás seguro/a que deseas continuar?
30
+ censuses:
31
+ create:
32
+ success: Se han importado con éxito %{count} elementos (%{errors} errores)
33
+ destroy:
34
+ success: Se han borrado todos los datos censales
35
+ menu:
36
+ census: Subir censo
37
+ show:
38
+ title: Datos de censo actuales
39
+ data: Hay un total de %{count} registros cargados. La última carga fue el día %{due_date}
40
+ empty: No hay datos censales. Usa el formulario a continuación para importar usando un fichero CSV.
41
+ new:
42
+ info: 'Debe ser un fichero generado por excel y exportado en formato CSV con dos columnas: documento de identidad y fecha de nacimiento'
43
+ title: Subir un nuevo censo
44
+ file: Archivo excel .csv con los datos del censo
45
+ submit: Subir archivo
46
+ verifications:
47
+ authorizations:
48
+ first_login:
49
+ actions:
50
+ file_authorization_handler: Verifícate con el censo de la organización
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateDecidimFileAuthorizationHandlerCensusDatum < ActiveRecord::Migration[5.1]
4
+ def change
5
+ create_table :decidim_file_authorization_handler_census_data do |t|
6
+ t.references :decidim_organization, index: { name: "decidim_census_data_org_id_index" }
7
+ t.string :id_document
8
+ t.date :birthdate
9
+
10
+ # The rows in this table are immutable (insert or delete, not update)
11
+ # To explicitly reflect this fact there is no `updated_at` column
12
+ t.datetime "created_at", null: false
13
+ end
14
+ end
15
+ end