decidim-file_authorization_handler 0.27.1.5
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 +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
|