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.
- checksums.yaml +7 -0
- data/LICENSE +661 -0
- data/README.md +137 -0
- data/Rakefile +3 -0
- data/app/controllers/decidim/file_authorization_handler/admin/censuses_controller.rb +34 -0
- data/app/jobs/decidim/file_authorization_handler/application_job.rb +8 -0
- data/app/jobs/decidim/file_authorization_handler/remove_duplicates_job.rb +30 -0
- data/app/models/decidim/file_authorization_handler/application_record.rb +9 -0
- data/app/models/decidim/file_authorization_handler/census_datum.rb +70 -0
- data/app/models/decidim/file_authorization_handler/csv_data.rb +40 -0
- data/app/models/decidim/file_authorization_handler/status.rb +27 -0
- data/app/permissions/decidim/file_authorization_handler/admin/permissions.rb +27 -0
- data/app/services/file_authorization_handler.rb +59 -0
- data/app/views/decidim/file_authorization_handler/admin/censuses/show.html.erb +39 -0
- data/app/views/layouts/file_authorization_handler/application.html.erb +14 -0
- data/config/locales/ca.yml +50 -0
- data/config/locales/en.yml +50 -0
- data/config/locales/es.yml +50 -0
- data/db/migrate/20171110120821_create_decidim_file_authorization_handler_census_datum.rb +15 -0
- data/db/migrate/20221207143742_add_extras_to_census_datum.rb +7 -0
- data/lib/decidim/file_authorization_handler/admin.rb +10 -0
- data/lib/decidim/file_authorization_handler/admin_engine.rb +23 -0
- data/lib/decidim/file_authorization_handler/engine.rb +22 -0
- data/lib/decidim/file_authorization_handler/version.rb +12 -0
- data/lib/decidim/file_authorization_handler.rb +11 -0
- data/spec/controllers/decidim/file_authorization_handler/admin/censuses_controller_spec.rb +57 -0
- data/spec/factories/census_datum.rb +14 -0
- data/spec/factories/factories.rb +3 -0
- data/spec/fixtures/files/data-with_extras.csv +5 -0
- data/spec/fixtures/files/data1.csv +4 -0
- data/spec/fixtures/files/with-errors.csv +7 -0
- data/spec/helpers/decidim/file_authorization_handler/encoding_helper.rb +11 -0
- data/spec/jobs/decidim/file_authorization_handler/remove_duplicates_job_spec.rb +20 -0
- data/spec/models/decidim/file_authorization_handler/census_datum_spec.rb +75 -0
- data/spec/models/decidim/file_authorization_handler/csv_data_spec.rb +41 -0
- data/spec/models/decidim/file_authorization_handler/status_spec.rb +21 -0
- data/spec/permissions/decidim/file_authorization_handler/admin/permissions_spec.rb +58 -0
- data/spec/services/decidim/file_authorization_handler/file_authorization_handler_spec.rb +77 -0
- data/spec/spec_helper.rb +23 -0
- 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,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,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,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
|