decidim-direct_verifications 0.17.8 → 1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +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:
|