decidim-direct_verifications 0.17.8 → 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +43 -2
- data/app/assets/config/direct_verifications_admin_manifest.css +3 -0
- data/app/assets/stylesheets/decidim/direct_verifications/authorizations.scss +17 -0
- data/app/commands/decidim/direct_verifications/verification/create_import.rb +50 -0
- data/app/controllers/decidim/direct_verifications/verification/admin/authorizations_controller.rb +40 -0
- data/app/controllers/decidim/direct_verifications/verification/admin/direct_verifications_controller.rb +71 -46
- data/app/controllers/decidim/direct_verifications/verification/admin/imports_controller.rb +55 -0
- data/app/forms/decidim/direct_verifications/registration_form.rb +8 -0
- data/app/forms/decidim/direct_verifications/verification/create_import_form.rb +43 -0
- data/app/jobs/decidim/direct_verifications/authorize_users_job.rb +34 -0
- data/app/jobs/decidim/direct_verifications/base_import_job.rb +38 -0
- data/app/jobs/decidim/direct_verifications/register_users_job.rb +19 -0
- data/app/jobs/decidim/direct_verifications/revoke_users_job.rb +17 -0
- data/app/mailers/decidim/direct_verifications/import_mailer.rb +27 -0
- data/app/mailers/decidim/direct_verifications/stats.rb +23 -0
- data/app/views/decidim/direct_verifications/import_mailer/finished_processing.html.erb +7 -0
- data/app/views/decidim/direct_verifications/import_mailer/finished_processing.text.erb +7 -0
- data/app/views/decidim/direct_verifications/verification/admin/authorizations/index.html.erb +42 -0
- data/app/views/decidim/direct_verifications/verification/admin/direct_verifications/index.html.erb +18 -17
- data/app/views/decidim/direct_verifications/verification/admin/imports/new.html.erb +50 -0
- data/app/views/decidim/direct_verifications/verification/admin/stats/index.html.erb +3 -3
- data/config/initializers/mail_previews.rb +5 -0
- data/config/locales/ca.yml +25 -20
- data/config/locales/cs.yml +69 -0
- data/config/locales/en.yml +34 -2
- data/config/locales/es.yml +25 -20
- data/config/locales/fr.yml +69 -0
- data/lib/decidim/direct_verifications.rb +24 -1
- data/lib/decidim/direct_verifications/authorize_user.rb +64 -0
- data/lib/decidim/direct_verifications/instrumenter.rb +58 -0
- data/lib/decidim/direct_verifications/parsers.rb +11 -0
- data/lib/decidim/direct_verifications/parsers/base_parser.rb +37 -0
- data/lib/decidim/direct_verifications/parsers/metadata_parser.rb +54 -0
- data/lib/decidim/direct_verifications/parsers/name_parser.rb +40 -0
- data/lib/decidim/direct_verifications/register_user.rb +54 -0
- data/lib/decidim/direct_verifications/revoke_user.rb +45 -0
- data/lib/decidim/direct_verifications/tests/factories.rb +11 -0
- data/lib/decidim/direct_verifications/tests/verification_controller_examples.rb +83 -0
- data/lib/decidim/direct_verifications/user_processor.rb +18 -98
- data/lib/decidim/direct_verifications/user_stats.rb +9 -6
- data/lib/decidim/direct_verifications/verification/admin_engine.rb +6 -1
- data/lib/decidim/direct_verifications/version.rb +3 -2
- metadata +38 -9
- data/lib/decidim/direct_verifications/config.rb +0 -23
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "decidim/direct_verifications/instrumenter"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
module DirectVerifications
|
7
|
+
class AuthorizeUsersJob < BaseImportJob
|
8
|
+
class NullSession; end
|
9
|
+
|
10
|
+
def process_users
|
11
|
+
emails.each do |email, data|
|
12
|
+
AuthorizeUser.new(
|
13
|
+
email,
|
14
|
+
data,
|
15
|
+
session,
|
16
|
+
organization,
|
17
|
+
instrumenter,
|
18
|
+
authorization_handler
|
19
|
+
).call
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def type
|
24
|
+
:authorized
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def session
|
30
|
+
NullSession.new
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "decidim/direct_verifications/instrumenter"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
module DirectVerifications
|
7
|
+
# This class implements the logic to import the user entries and sending an email notification
|
8
|
+
# with the result. The specifics to process the entries are meant to be implemented by
|
9
|
+
# subclasses which must implement the `#process_users` and `#type` methods.
|
10
|
+
class BaseImportJob < ApplicationJob
|
11
|
+
queue_as :default
|
12
|
+
|
13
|
+
def perform(userslist, organization, current_user, authorization_handler)
|
14
|
+
@emails = Parsers::MetadataParser.new(userslist).to_h
|
15
|
+
@organization = organization
|
16
|
+
@current_user = current_user
|
17
|
+
@instrumenter = Instrumenter.new(current_user)
|
18
|
+
@authorization_handler = authorization_handler
|
19
|
+
|
20
|
+
process_users
|
21
|
+
send_email_notification
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_reader :emails, :organization, :current_user, :instrumenter, :authorization_handler
|
27
|
+
|
28
|
+
def send_email_notification
|
29
|
+
ImportMailer.finished_processing(
|
30
|
+
current_user,
|
31
|
+
instrumenter,
|
32
|
+
type,
|
33
|
+
authorization_handler
|
34
|
+
).deliver_now
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "decidim/direct_verifications/instrumenter"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
module DirectVerifications
|
7
|
+
class RegisterUsersJob < BaseImportJob
|
8
|
+
def process_users
|
9
|
+
emails.each do |email, data|
|
10
|
+
RegisterUser.new(email, data, organization, current_user, instrumenter).call
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def type
|
15
|
+
:registered
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module DirectVerifications
|
5
|
+
class RevokeUsersJob < BaseImportJob
|
6
|
+
def process_users
|
7
|
+
emails.each do |email, _name|
|
8
|
+
RevokeUser.new(email, organization, instrumenter, authorization_handler).call
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def type
|
13
|
+
:revoked
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module DirectVerifications
|
5
|
+
class ImportMailer < Decidim::Admin::ApplicationMailer
|
6
|
+
include LocalisedMailer
|
7
|
+
|
8
|
+
layout "decidim/mailer"
|
9
|
+
|
10
|
+
I18N_SCOPE = "decidim.direct_verifications.verification.admin.imports.mailer"
|
11
|
+
|
12
|
+
def finished_processing(user, instrumenter, type, handler)
|
13
|
+
@stats = Stats.from(instrumenter, type)
|
14
|
+
@organization = user.organization
|
15
|
+
@i18n_key = "#{I18N_SCOPE}.#{type}"
|
16
|
+
@handler = handler
|
17
|
+
|
18
|
+
with_user(user) do
|
19
|
+
mail(
|
20
|
+
to: user.email,
|
21
|
+
subject: I18n.t("#{I18N_SCOPE}.subject")
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module DirectVerifications
|
5
|
+
class Stats
|
6
|
+
attr_reader :count, :successful, :errors
|
7
|
+
|
8
|
+
def self.from(instrumenter, type)
|
9
|
+
new(
|
10
|
+
count: instrumenter.emails_count(type),
|
11
|
+
successful: instrumenter.processed_count(type),
|
12
|
+
errors: instrumenter.errors_count(type)
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(count:, successful:, errors:)
|
17
|
+
@count = count
|
18
|
+
@successful = successful
|
19
|
+
@errors = errors
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<%= stylesheet_link_tag "decidim/direct_verifications/authorizations" %>
|
2
|
+
|
3
|
+
<div class="card">
|
4
|
+
<div class="card-divider">
|
5
|
+
<h2 class="card-title">
|
6
|
+
<%= t(".title") %>
|
7
|
+
<%= link_to t("admin.index.stats", scope: "decidim.direct_verifications.verification"), stats_path, class: "button tiny button--title" %>
|
8
|
+
<%= link_to t(".new_import"), direct_verifications_path, class: "button tiny button--title" %>
|
9
|
+
</h2>
|
10
|
+
</div>
|
11
|
+
<div class="card-section">
|
12
|
+
<div class="table-scroll">
|
13
|
+
<table class="table-list">
|
14
|
+
<thead>
|
15
|
+
<tr>
|
16
|
+
<th><%= t(".name") %></th>
|
17
|
+
<th><%= t(".metadata") %></th>
|
18
|
+
<th><%= t(".user_name") %></th>
|
19
|
+
<th><%= t(".created_at") %></th>
|
20
|
+
<th> </th>
|
21
|
+
</tr>
|
22
|
+
</thead>
|
23
|
+
<tbody>
|
24
|
+
<% @authorizations.each do |authorization| %>
|
25
|
+
<tr data-authorization-id="<%= authorization.id %>">
|
26
|
+
<td><%= authorization.name %></td>
|
27
|
+
<td class="metadata">
|
28
|
+
<span class="code"><%= authorization.metadata %></span>
|
29
|
+
</td>
|
30
|
+
<td><%= authorization.user.name %></td>
|
31
|
+
<td><%= authorization.created_at %></td>
|
32
|
+
|
33
|
+
<td class="table-list__actions">
|
34
|
+
<%= icon_link_to "circle-x", authorization_path(authorization), t("actions.destroy", scope: "decidim.admin"), class: "action-icon--remove", method: :delete, data: { confirm: t("actions.confirm_destroy", scope: "decidim.admin") } %>
|
35
|
+
</td>
|
36
|
+
</tr>
|
37
|
+
<% end %>
|
38
|
+
</tbody>
|
39
|
+
</table>
|
40
|
+
</div>
|
41
|
+
</div>
|
42
|
+
</div>
|
data/app/views/decidim/direct_verifications/verification/admin/direct_verifications/index.html.erb
CHANGED
@@ -1,40 +1,41 @@
|
|
1
1
|
<div class="card">
|
2
2
|
<div class="card-divider">
|
3
3
|
<h2 class="card-title">
|
4
|
-
<%= t(
|
5
|
-
<%= link_to t("admin.index.stats", scope:
|
4
|
+
<%= t("admin.index.title", scope: "decidim.direct_verifications.verification") %>
|
5
|
+
<%= link_to t("admin.index.stats", scope: "decidim.direct_verifications.verification"), stats_path, class: "button tiny button--title" %>
|
6
|
+
<%= link_to t("admin.index.authorizations", scope: "decidim.direct_verifications.verification"), authorizations_path, class: "button tiny button--title" %>
|
6
7
|
</h2>
|
7
8
|
</div>
|
8
9
|
<div class="card-section">
|
9
|
-
<p><%= t(
|
10
|
-
<%= form_tag direct_verifications_path, multipart: true, class:
|
11
|
-
<%= label_tag :
|
12
|
-
<%= text_area_tag :
|
10
|
+
<p><%= t("decidim.direct_verifications.verification.admin.new.info_html", link: new_import_path) %></p>
|
11
|
+
<%= form_tag direct_verifications_path, multipart: true, class: "form" do %>
|
12
|
+
<%= label_tag :userslist, t("admin.new.textarea", scope: "decidim.direct_verifications.verification") %>
|
13
|
+
<%= text_area_tag :userslist, @userslist, rows: 10 %>
|
13
14
|
<label>
|
14
15
|
<%= check_box_tag :register %>
|
15
|
-
<%= t(
|
16
|
+
<%= t("admin.new.register", scope: "decidim.direct_verifications.verification") %>
|
16
17
|
<div data-alert class="callout alert hide">
|
17
|
-
<%= t(
|
18
|
+
<%= t("admin.direct_verifications.gdpr_disclaimer", scope: "decidim.direct_verifications.verification") %>
|
18
19
|
</div>
|
19
20
|
</label>
|
20
21
|
<label>
|
21
|
-
<%= radio_button_tag :authorize,
|
22
|
-
<%= t(
|
22
|
+
<%= radio_button_tag :authorize, "in" %>
|
23
|
+
<%= t("admin.new.authorize", scope: "decidim.direct_verifications.verification") %>
|
23
24
|
</label>
|
24
25
|
<label>
|
25
|
-
<%= radio_button_tag :authorize,
|
26
|
-
<%= t(
|
26
|
+
<%= radio_button_tag :authorize, "out" %>
|
27
|
+
<%= t("admin.new.revoke", scope: "decidim.direct_verifications.verification") %>
|
27
28
|
</label>
|
28
29
|
<label>
|
29
|
-
<%= radio_button_tag :authorize,
|
30
|
-
<%= t(
|
30
|
+
<%= radio_button_tag :authorize, "check", true %>
|
31
|
+
<%= t("admin.new.check", scope: "decidim.direct_verifications.verification") %>
|
31
32
|
</label>
|
32
33
|
|
33
|
-
<%= label_tag :authorization_handler, t(
|
34
|
+
<%= label_tag :authorization_handler, t("admin.new.authorization_handler", scope: "decidim.direct_verifications.verification") %>
|
34
35
|
|
35
|
-
<%= select_tag :authorization_handler, options_for_select(
|
36
|
+
<%= select_tag :authorization_handler, options_for_select(workflows, current_authorization_handler) %>
|
36
37
|
|
37
|
-
<%= submit_tag t(
|
38
|
+
<%= submit_tag t("admin.new.submit", scope: "decidim.direct_verifications.verification"), class: "button" %>
|
38
39
|
|
39
40
|
<% end %>
|
40
41
|
|
@@ -0,0 +1,50 @@
|
|
1
|
+
<div class="card">
|
2
|
+
<div class="card-divider">
|
3
|
+
<h2 class="card-title">
|
4
|
+
<%= t("admin.index.title", scope: "decidim.direct_verifications.verification") %>
|
5
|
+
<%= link_to t("admin.index.stats", scope: "decidim.direct_verifications.verification"), stats_path, class: "button tiny button--title" %>
|
6
|
+
<%= link_to t("admin.index.authorizations", scope: "decidim.direct_verifications.verification"), authorizations_path, class: "button tiny button--title" %>
|
7
|
+
</h2>
|
8
|
+
</div>
|
9
|
+
<div class="card-section">
|
10
|
+
<p><%= t("decidim.direct_verifications.verification.admin.imports.new.info") %></p>
|
11
|
+
<pre class="code-block">
|
12
|
+
<strong>email, name, membership_phone, membership_type, membership_weight</strong>
|
13
|
+
ava@example.com, Ava Hawkins, +3476318371, consumer, 1
|
14
|
+
ewan@example.com, Ewan Cooper, +34653565765, worker, 1
|
15
|
+
tilly@example.com, Tilly Jones, +34653565761, collaborator, 0.67
|
16
|
+
...
|
17
|
+
</pre>
|
18
|
+
|
19
|
+
<%= decidim_form_for(@form, url: imports_path, html: { class: "form" }) do |form| %>
|
20
|
+
<label>
|
21
|
+
<%= check_box_tag :register %>
|
22
|
+
<%= t("admin.new.register", scope: "decidim.direct_verifications.verification") %>
|
23
|
+
<div data-alert class="callout alert hide">
|
24
|
+
<%= t("admin.direct_verifications.gdpr_disclaimer", scope: "decidim.direct_verifications.verification") %>
|
25
|
+
</div>
|
26
|
+
</label>
|
27
|
+
<label>
|
28
|
+
<%= radio_button_tag :authorize, "in" %>
|
29
|
+
<%= t("admin.new.authorize", scope: "decidim.direct_verifications.verification") %>
|
30
|
+
</label>
|
31
|
+
<label>
|
32
|
+
<%= radio_button_tag :authorize, "out" %>
|
33
|
+
<%= t("admin.new.revoke", scope: "decidim.direct_verifications.verification") %>
|
34
|
+
</label>
|
35
|
+
<label>
|
36
|
+
<%= radio_button_tag :authorize, "check", true %>
|
37
|
+
<%= t("admin.new.check", scope: "decidim.direct_verifications.verification") %>
|
38
|
+
</label>
|
39
|
+
|
40
|
+
<%= label_tag :authorization_handler, t("admin.new.authorization_handler", scope: "decidim.direct_verifications.verification") %>
|
41
|
+
<%= select_tag :authorization_handler, options_for_select(workflows, current_authorization_handler) %>
|
42
|
+
|
43
|
+
<%= form.file_field :file, label: t(".file") %>
|
44
|
+
<%= form.submit t(".submit"), class: "button" %>
|
45
|
+
<% end %>
|
46
|
+
|
47
|
+
</div>
|
48
|
+
</div>
|
49
|
+
|
50
|
+
<%= javascript_include_tag "decidim/direct_verifications/verification/admin/direct_verifications_admin" %>
|
@@ -1,15 +1,15 @@
|
|
1
1
|
<div class="card">
|
2
2
|
<div class="card-divider">
|
3
3
|
<h2 class="card-title">
|
4
|
-
<%= t(
|
5
|
-
<%= link_to t("admin.index.title", scope:
|
4
|
+
<%= t("admin.index.stats", scope: "decidim.direct_verifications.verification") %>
|
5
|
+
<%= link_to t("admin.index.title", scope: "decidim.direct_verifications.verification"), direct_verifications_path, class: "button tiny button--title" %>
|
6
6
|
</h2>
|
7
7
|
</div>
|
8
8
|
<div class="card-section">
|
9
9
|
<table class="table-list">
|
10
10
|
<thead>
|
11
11
|
<tr>
|
12
|
-
<th><%= t("admin.new.authorization_handler", scope:
|
12
|
+
<th><%= t("admin.new.authorization_handler", scope: "decidim.direct_verifications.verification") %></th>
|
13
13
|
<th><%= t(".registered") %></th>
|
14
14
|
<th><%= t(".authorized") %></th>
|
15
15
|
<th><%= t(".unconfirmed") %></th>
|
data/config/locales/ca.yml
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
---
|
2
1
|
ca:
|
3
2
|
decidim:
|
4
3
|
admin:
|
@@ -11,40 +10,41 @@ ca:
|
|
11
10
|
admin:
|
12
11
|
direct_verifications:
|
13
12
|
help:
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
- 'Permet la introducció massiva d''usuaris per tal de:'
|
14
|
+
- Registrar-los directament a la organització amb l'enviament d'invitacions
|
15
|
+
- Verificar-los en qualsevol mètode de verificació actiu
|
16
|
+
- Revocar la verificació en qualsevol mètode de verificació actiu
|
18
17
|
direct_verifications:
|
19
18
|
explanation: Verificació manual per par dels administradors de l'organització
|
20
19
|
name: Verificació directa
|
21
20
|
direct_verifications:
|
22
21
|
verification:
|
23
22
|
admin:
|
23
|
+
authorizations:
|
24
|
+
index:
|
25
|
+
created_at: Data de creació
|
26
|
+
metadata: Metadades
|
27
|
+
name: Nom
|
28
|
+
title: Autoritzacions
|
29
|
+
user_name: Nom d'usuari
|
30
|
+
new_import: Nova importació
|
24
31
|
direct_verifications:
|
25
32
|
create:
|
26
|
-
authorized: S'han verificat correctament %{authorized} usuaris utilitzant
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
detectats, %{errors} errors)
|
33
|
-
revoked: S'ha revocat correctament la verificació de %{revoked} usuaris
|
34
|
-
utilitzant [%{handler}] (%{count} detectats, %{errors} errors)
|
35
|
-
gdpr_disclaimer: Feu-ho sota la vostra responsabilitat. Recordeu que heu
|
36
|
-
de tenir el consentiment explícit dels vostres usuaris per registrar-los.
|
37
|
-
En cas contrari, estareu infringint la regulació GDPR als països de
|
38
|
-
la UE.
|
33
|
+
authorized: "S'han verificat correctament %{authorized} usuaris utilitzant [%{handler}] (%{count} detectats, %{errors} errors)"
|
34
|
+
info: "S'han detectat %{count} usuaris, dels quals %{registered} estan registrats, %{authorized} autoritzats utilitzant [%{handler}] (%{unconfirmed} sense confirmar)"
|
35
|
+
missing_header: Si us plau, proporcioneu una fila d'encapçalament
|
36
|
+
registered: "S'han registrat correctament %{registered} usuaris (%{count} detectats, %{errors} errors)"
|
37
|
+
revoked: S'ha revocat correctament la verificació de %{revoked} usuaris utilitzant [%{handler}] (%{count} detectats, %{errors} errors)
|
38
|
+
gdpr_disclaimer: Feu-ho sota la vostra responsabilitat. Recordeu que heu de tenir el consentiment explícit dels vostres usuaris per registrar-los. En cas contrari, estareu infringint la regulació GDPR als països de la UE.
|
39
39
|
index:
|
40
|
+
authorizations: Usuaris autoritzats
|
40
41
|
stats: Estadístiques d'usuaris
|
41
42
|
title: Inscriu i autoritza usuaris
|
42
43
|
new:
|
43
44
|
authorization_handler: Mètode de verificació
|
44
45
|
authorize: Autoritza els usuaris
|
45
46
|
check: Comprova l'estat dels usuaris
|
46
|
-
info: Introdueix aquí els emails, un per línia. Si els emails estan precedits
|
47
|
-
per un text, s'interpretarà com el nom de l'usuari
|
47
|
+
info: Introdueix aquí els emails, un per línia. Si els emails estan precedits per un text, s'interpretarà com el nom de l'usuari
|
48
48
|
register: Registra els usuaris a la plataforma (si existeixen s'ignoraran)
|
49
49
|
revoke: Revoca l'autorització dels usuaris
|
50
50
|
submit: Envia i processa el llistat
|
@@ -59,6 +59,11 @@ ca:
|
|
59
59
|
authorizations:
|
60
60
|
new:
|
61
61
|
no_action: Aquest mètode requereix que un administrador us verifiqui
|
62
|
+
verifications:
|
63
|
+
authorizations:
|
64
|
+
first_login:
|
65
|
+
actions:
|
66
|
+
direct_verifications: Verificació directa
|
62
67
|
devise:
|
63
68
|
mailer:
|
64
69
|
direct_invite:
|