decidim-direct_verifications 0.17.5 → 0.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +67 -5
- data/app/assets/config/direct_verifications_admin_manifest.js +1 -0
- data/app/assets/javascripts/decidim/direct_verifications/verification/admin/direct_verifications_admin.js.es6 +7 -0
- data/app/controllers/decidim/direct_verifications/verification/admin/direct_verifications_controller.rb +84 -49
- data/app/controllers/decidim/direct_verifications/verification/admin/stats_controller.rb +38 -0
- data/app/views/decidim/direct_verifications/verification/admin/direct_verifications/index.html.erb +22 -18
- data/app/views/decidim/direct_verifications/verification/admin/stats/index.html.erb +35 -0
- data/config/locales/ca.yml +25 -3
- data/config/locales/en.yml +23 -3
- data/config/locales/es.yml +25 -3
- data/lib/decidim/direct_verifications.rb +2 -0
- data/lib/decidim/direct_verifications/config.rb +23 -0
- data/lib/decidim/direct_verifications/tests/verification_controller_examples.rb +78 -0
- data/lib/decidim/direct_verifications/user_processor.rb +4 -19
- data/lib/decidim/direct_verifications/user_stats.rb +76 -0
- data/lib/decidim/direct_verifications/verification/admin_engine.rb +6 -1
- data/lib/decidim/direct_verifications/version.rb +3 -2
- metadata +17 -11
- data/app/permissions/decidim/direct_verifications/verification/admin/permissions.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cbf6bc3adf56db3268520dc976ecf5e24791667d27d41e43f43be7a1de122b15
|
4
|
+
data.tar.gz: 63bc2221b993503c21037f62195021967eed48f3d0d35ce1f25ceb2bd27e899a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c90a4d69fd3640640efb62102de8a218ba2f57e01725bb89f81a6c7adc384c0e937ded80f8049b2448cc2b60eedfa37c71f24bdf74288c9d4efe63c69a5dccb1
|
7
|
+
data.tar.gz: fee38887199f7a345e64a62f7389262785435d6686aef02ee39a75359314dbc9b9d43465689d122c3b539811c2fde2abce0917e08584a73be4077e33c6cdfd22
|
data/README.md
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
# Decidim::DirectVerifications
|
2
2
|
|
3
|
-
|
3
|
+
![[CI] Test](https://github.com/Platoniq/decidim-verifications-direct_verifications/workflows/%5BCI%5D%20Test/badge.svg)
|
4
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/2195deb4de6c6354a6bc/maintainability)](https://codeclimate.com/github/Platoniq/decidim-verifications-direct_verifications/maintainability)
|
5
|
+
[![codecov](https://codecov.io/gh/Platoniq/decidim-verifications-direct_verifications/branch/master/graph/badge.svg?token=FR1zkV71S2)](https://codecov.io/gh/Platoniq/decidim-verifications-direct_verifications)
|
4
6
|
|
5
7
|
A [Decidim](https://github.com/decidim/decidim) that provides a verification method called `Direct verification`. Works only on the admin side, final users do not intervene in the verification process.
|
6
8
|
|
7
9
|
This plugin allows to verify users against the `Direct verification` method by default, but it is not limited to it, it can be used to directly verify users against any other method registered for the organization.
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
**Other features include:**
|
11
|
+
**Features:**
|
12
12
|
|
13
13
|
1. Allows to massively register users directly in the platform prior (or independently) to verify them by sending them invite emails.
|
14
14
|
> **IMPORTANT:**<br>
|
15
15
|
> You must only use this feature if you have explicit consent from your users, otherwise you might be violating the [GDPR](https://eugdpr.org/) regulation in EU.
|
16
|
-
2.
|
16
|
+
2. Massive authroizations of users using any verification method registered for the organization **if configured**.
|
17
|
+
3. It can massively revoke authorizations given to any user with any verification method available.
|
18
|
+
4. Shows user's statuses per verification method in a simple stats table.
|
17
19
|
|
18
20
|
## Screenshot
|
19
21
|
|
@@ -48,6 +50,66 @@ And then execute:
|
|
48
50
|
bundle
|
49
51
|
```
|
50
52
|
|
53
|
+
## Using additional verification methods
|
54
|
+
|
55
|
+
You can manage other verification methods (or workflow) a part from `Direct verification`. You need to configure it in a new file in the `config/initializers` folder.
|
56
|
+
For instance, you can use this same engine to have 2 levels of permissions in the platform.
|
57
|
+
|
58
|
+
Create a file like `config/initializers/decidim_verifications.rb` with content as:
|
59
|
+
|
60
|
+
**`config/initializers/decidim_verifications.rb`:**
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
# frozen_string_literal: true
|
64
|
+
|
65
|
+
# We are using the same DirectVerifications engine without the admin part to
|
66
|
+
# create a custom verification method called "direct_verifications_managers"
|
67
|
+
Decidim::Verifications.register_workflow(:direct_verifications_managers) do |workflow|
|
68
|
+
workflow.engine = Decidim::DirectVerifications::Verification::Engine
|
69
|
+
end
|
70
|
+
|
71
|
+
# We need to tell the plugin to handle this method in addition to the default "Direct verification". Any registered workflow is valid.
|
72
|
+
Decidim::DirectVerifications.configure do |config|
|
73
|
+
config.manage_workflows = %w(direct_verifications_managers)
|
74
|
+
end
|
75
|
+
|
76
|
+
```
|
77
|
+
|
78
|
+
You will need the locales entries corresponding to your custom workflow, create as many files as languages you have in your application in `config/locales`:
|
79
|
+
|
80
|
+
**`config/locales/en.yml`:**
|
81
|
+
|
82
|
+
```yaml
|
83
|
+
en:
|
84
|
+
decidim:
|
85
|
+
authorization_handlers:
|
86
|
+
direct_verifications_managers:
|
87
|
+
name: Organization managers
|
88
|
+
explanation: Direct Verifications Subgroup explanation
|
89
|
+
verifications:
|
90
|
+
authorizations:
|
91
|
+
first_login:
|
92
|
+
actions:
|
93
|
+
direct_verifications_managers: Organization managers
|
94
|
+
```
|
95
|
+
|
96
|
+
Similarly, you can also overwrite the default title "Direct verification" by creating the key again in your locales:
|
97
|
+
|
98
|
+
```yaml
|
99
|
+
en:
|
100
|
+
decidim:
|
101
|
+
authorization_handlers:
|
102
|
+
direct_verifications:
|
103
|
+
name: Generic organization members
|
104
|
+
explanation: Direct Verifications Subgroup explanation
|
105
|
+
verifications:
|
106
|
+
authorizations:
|
107
|
+
first_login:
|
108
|
+
actions:
|
109
|
+
direct_verifications: Generic organization members
|
110
|
+
```
|
111
|
+
|
112
|
+
|
51
113
|
## Contributing
|
52
114
|
|
53
115
|
See [Decidim](https://github.com/decidim/decidim).
|
@@ -0,0 +1 @@
|
|
1
|
+
//= link decidim/direct_verifications/verification/admin/direct_verifications_admin.js
|
@@ -6,71 +6,106 @@ module Decidim
|
|
6
6
|
module Admin
|
7
7
|
class DirectVerificationsController < Decidim::Admin::ApplicationController
|
8
8
|
include NeedsPermission
|
9
|
+
helper_method :workflows, :current_authorization_handler
|
9
10
|
|
10
11
|
layout "decidim/admin/users"
|
11
12
|
|
12
13
|
def index
|
13
|
-
enforce_permission_to :index,
|
14
|
+
enforce_permission_to :index, :authorization
|
14
15
|
end
|
15
16
|
|
16
17
|
def create
|
17
|
-
enforce_permission_to :create,
|
18
|
-
|
19
|
-
@
|
20
|
-
processor = UserProcessor.new(current_organization, current_user)
|
21
|
-
processor.emails = extract_emails_to_hash @
|
22
|
-
processor.authorization_handler =
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
flash[:notice] = t(".authorized", handler: t("#{processor.authorization_handler}.name", scope: "decidim.authorization_handlers"),
|
32
|
-
count: processor.emails.count,
|
33
|
-
authorized: processor.processed[:authorized].count,
|
34
|
-
errors: processor.errors[:authorized].count)
|
35
|
-
elsif params[:authorize] == "out"
|
36
|
-
processor.revoke_users
|
37
|
-
flash[:notice] = t(".revoked", handler: t("#{processor.authorization_handler}.name", scope: "decidim.authorization_handlers"),
|
38
|
-
count: processor.emails.count,
|
39
|
-
revoked: processor.processed[:revoked].count,
|
40
|
-
errors: processor.errors[:revoked].count)
|
41
|
-
else
|
42
|
-
flash[:info] = t(".info", handler: t("#{processor.authorization_handler}.name", scope: "decidim.authorization_handlers"),
|
43
|
-
count: processor.emails.count,
|
44
|
-
authorized: processor.total(:authorized),
|
45
|
-
unconfirmed: processor.total(:unconfirmed),
|
46
|
-
registered: processor.total(:registered))
|
47
|
-
render(action: :index) && return
|
48
|
-
end
|
18
|
+
enforce_permission_to :create, :authorization
|
19
|
+
|
20
|
+
@userslist = params[:userlist]
|
21
|
+
@processor = UserProcessor.new(current_organization, current_user)
|
22
|
+
@processor.emails = extract_emails_to_hash @userslist
|
23
|
+
@processor.authorization_handler = current_authorization_handler
|
24
|
+
@stats = UserStats.new(current_organization)
|
25
|
+
@stats.authorization_handler = @processor.authorization_handler
|
26
|
+
register_users
|
27
|
+
authorize_users
|
28
|
+
revoke_users
|
29
|
+
|
30
|
+
render(action: :index) && return if show_users_info
|
31
|
+
|
49
32
|
redirect_to direct_verifications_path
|
50
33
|
end
|
51
34
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
35
|
+
private
|
36
|
+
|
37
|
+
def register_users
|
38
|
+
return unless params[:register]
|
39
|
+
|
40
|
+
@processor.register_users
|
41
|
+
flash[:warning] = t(".registered", count: @processor.emails.count,
|
42
|
+
registered: @processor.processed[:registered].count,
|
43
|
+
errors: @processor.errors[:registered].count)
|
58
44
|
end
|
59
45
|
|
60
|
-
def
|
61
|
-
:
|
46
|
+
def authorize_users
|
47
|
+
return unless params[:authorize] == "in"
|
48
|
+
|
49
|
+
@processor.authorize_users
|
50
|
+
flash[:notice] = t(".authorized", handler: t("#{@processor.authorization_handler}.name", scope: "decidim.authorization_handlers"),
|
51
|
+
count: @processor.emails.count,
|
52
|
+
authorized: @processor.processed[:authorized].count,
|
53
|
+
errors: @processor.errors[:authorized].count)
|
62
54
|
end
|
63
55
|
|
64
|
-
|
56
|
+
def revoke_users
|
57
|
+
return unless params[:authorize] == "out"
|
58
|
+
|
59
|
+
@processor.revoke_users
|
60
|
+
flash[:notice] = t(".revoked", handler: t("#{@processor.authorization_handler}.name", scope: "decidim.authorization_handlers"),
|
61
|
+
count: @processor.emails.count,
|
62
|
+
revoked: @processor.processed[:revoked].count,
|
63
|
+
errors: @processor.errors[:revoked].count)
|
64
|
+
end
|
65
|
+
|
66
|
+
def show_users_info
|
67
|
+
return if params[:authorize]
|
68
|
+
|
69
|
+
@stats.emails = @processor.emails.keys
|
70
|
+
flash.now[:info] = t(".info", handler: t("#{@processor.authorization_handler}.name", scope: "decidim.authorization_handlers"),
|
71
|
+
count: @processor.emails.count,
|
72
|
+
authorized: @stats.authorized,
|
73
|
+
unconfirmed: @stats.unconfirmed,
|
74
|
+
registered: @stats.registered)
|
75
|
+
true
|
76
|
+
end
|
65
77
|
|
66
78
|
def extract_emails_to_hash(txt)
|
67
|
-
reg = /([
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
m[0]
|
72
|
-
|
73
|
-
|
79
|
+
reg = /([A-Z0-9+._-]+@[A-Z0-9._-]+\.[A-Z0-9_-]+)\b/i
|
80
|
+
emails = {}
|
81
|
+
txt.split(/[\r\n;,]/).each do |line|
|
82
|
+
reg.match line do |m|
|
83
|
+
n = line.split(m[0]).first
|
84
|
+
emails[m[0]] = (n.presence || "").gsub(/[^[:print:]]|[\"\$\<\>\|\\]/, "").strip
|
85
|
+
end
|
86
|
+
end
|
87
|
+
emails
|
88
|
+
end
|
89
|
+
|
90
|
+
def authorization_handler(authorization_handler)
|
91
|
+
@authorization_handler = authorization_handler.presence || :direct_verifications
|
92
|
+
end
|
93
|
+
|
94
|
+
def current_authorization_handler
|
95
|
+
authorization_handler(params[:authorization_handler])
|
96
|
+
end
|
97
|
+
|
98
|
+
def configured_workflows
|
99
|
+
return Decidim::DirectVerifications.config.manage_workflows if Decidim::DirectVerifications.config
|
100
|
+
|
101
|
+
["direct_verifications"]
|
102
|
+
end
|
103
|
+
|
104
|
+
def workflows
|
105
|
+
workflows = configured_workflows & current_organization.available_authorizations.map.to_a
|
106
|
+
workflows.map do |a|
|
107
|
+
[t("#{a}.name", scope: "decidim.authorization_handlers"), a]
|
108
|
+
end
|
74
109
|
end
|
75
110
|
end
|
76
111
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module DirectVerifications
|
5
|
+
module Verification
|
6
|
+
module Admin
|
7
|
+
class StatsController < Decidim::Admin::ApplicationController
|
8
|
+
include NeedsPermission
|
9
|
+
|
10
|
+
layout "decidim/admin/users"
|
11
|
+
|
12
|
+
def index
|
13
|
+
enforce_permission_to :index, :authorization
|
14
|
+
stats = UserStats.new(current_organization)
|
15
|
+
@stats = {
|
16
|
+
t(".global") => stats_hash(stats)
|
17
|
+
}
|
18
|
+
current_organization.available_authorizations.map do |a|
|
19
|
+
stats.authorization_handler = a
|
20
|
+
@stats[t("#{a}.name", scope: "decidim.authorization_handlers")] = stats_hash(stats)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def stats_hash(stats)
|
27
|
+
{
|
28
|
+
registered: stats.registered,
|
29
|
+
authorized: stats.authorized,
|
30
|
+
unconfirmed: stats.unconfirmed,
|
31
|
+
authorized_unconfirmed: stats.authorized_unconfirmed
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/app/views/decidim/direct_verifications/verification/admin/direct_verifications/index.html.erb
CHANGED
@@ -1,40 +1,44 @@
|
|
1
|
-
|
2
1
|
<div class="card">
|
3
2
|
<div class="card-divider">
|
4
3
|
<h2 class="card-title">
|
5
|
-
<%= t(
|
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
6
|
</h2>
|
7
7
|
</div>
|
8
8
|
<div class="card-section">
|
9
|
-
<p><%= t(
|
10
|
-
<%= form_tag direct_verifications_path, multipart: true, class:
|
11
|
-
<%= label_tag :userlist, t(
|
12
|
-
<%= text_area_tag :userlist, @
|
9
|
+
<p><%= t("decidim.direct_verifications.verification.admin.new.info") %></p>
|
10
|
+
<%= form_tag direct_verifications_path, multipart: true, class: "form" do %>
|
11
|
+
<%= label_tag :userlist, t("admin.new.textarea", scope: "decidim.direct_verifications.verification") %>
|
12
|
+
<%= text_area_tag :userlist, @userslist, rows: 10 %>
|
13
13
|
<label>
|
14
14
|
<%= check_box_tag :register %>
|
15
|
-
<%= t(
|
15
|
+
<%= t("admin.new.register", scope: "decidim.direct_verifications.verification") %>
|
16
|
+
<div data-alert class="callout alert hide">
|
17
|
+
<%= t("admin.direct_verifications.gdpr_disclaimer", scope: "decidim.direct_verifications.verification") %>
|
18
|
+
</div>
|
16
19
|
</label>
|
17
20
|
<label>
|
18
|
-
<%= radio_button_tag :authorize,
|
19
|
-
<%= t(
|
21
|
+
<%= radio_button_tag :authorize, "in" %>
|
22
|
+
<%= t("admin.new.authorize", scope: "decidim.direct_verifications.verification") %>
|
20
23
|
</label>
|
21
24
|
<label>
|
22
|
-
<%= radio_button_tag :authorize,
|
23
|
-
<%= t(
|
25
|
+
<%= radio_button_tag :authorize, "out" %>
|
26
|
+
<%= t("admin.new.revoke", scope: "decidim.direct_verifications.verification") %>
|
24
27
|
</label>
|
25
28
|
<label>
|
26
|
-
<%= radio_button_tag :authorize,
|
27
|
-
<%= t(
|
29
|
+
<%= radio_button_tag :authorize, "check", true %>
|
30
|
+
<%= t("admin.new.check", scope: "decidim.direct_verifications.verification") %>
|
28
31
|
</label>
|
29
32
|
|
30
|
-
<%= label_tag :
|
31
|
-
|
32
|
-
|
33
|
-
}, :direct_verifications) %>
|
33
|
+
<%= label_tag :authorization_handler, t("admin.new.authorization_handler", scope: "decidim.direct_verifications.verification") %>
|
34
|
+
|
35
|
+
<%= select_tag :authorization_handler, options_for_select(workflows, current_authorization_handler) %>
|
34
36
|
|
35
|
-
<%= submit_tag t(
|
37
|
+
<%= submit_tag t("admin.new.submit", scope: "decidim.direct_verifications.verification"), class: "button" %>
|
36
38
|
|
37
39
|
<% end %>
|
38
40
|
|
39
41
|
</div>
|
40
42
|
</div>
|
43
|
+
|
44
|
+
<%= javascript_include_tag "decidim/direct_verifications/verification/admin/direct_verifications_admin" %>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<div class="card">
|
2
|
+
<div class="card-divider">
|
3
|
+
<h2 class="card-title">
|
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
|
+
</h2>
|
7
|
+
</div>
|
8
|
+
<div class="card-section">
|
9
|
+
<table class="table-list">
|
10
|
+
<thead>
|
11
|
+
<tr>
|
12
|
+
<th><%= t("admin.new.authorization_handler", scope: "decidim.direct_verifications.verification") %></th>
|
13
|
+
<th><%= t(".registered") %></th>
|
14
|
+
<th><%= t(".authorized") %></th>
|
15
|
+
<th><%= t(".unconfirmed") %></th>
|
16
|
+
<th><%= t(".authorized_unconfirmed") %></th>
|
17
|
+
<th></th>
|
18
|
+
</tr>
|
19
|
+
</thead>
|
20
|
+
<tbody>
|
21
|
+
<% @stats.each do |a, s| %>
|
22
|
+
<tr>
|
23
|
+
<td>
|
24
|
+
<%= a %>
|
25
|
+
</td>
|
26
|
+
<td><%= s[:registered] %></td>
|
27
|
+
<td><%= s[:authorized] %></td>
|
28
|
+
<td><%= s[:unconfirmed] %></td>
|
29
|
+
<td><%= s[:authorized_unconfirmed] %></td>
|
30
|
+
</tr>
|
31
|
+
<% end %>
|
32
|
+
</tbody>
|
33
|
+
</table>
|
34
|
+
</div>
|
35
|
+
</div>
|
data/config/locales/ca.yml
CHANGED
@@ -26,15 +26,21 @@ ca:
|
|
26
26
|
authorized: S'han verificat correctament %{authorized} usuaris utilitzant
|
27
27
|
[%{handler}] (%{count} detectats, %{errors} errors)
|
28
28
|
info: S'han detectat %{count} usuaris, dels quals %{registered} estan
|
29
|
-
registrats, %{authorized} autoritzats utilitzant [%{handler}] (%{unconfirmed}
|
29
|
+
registrats, %{authorized} autoritzats utilitzant [%{handler}] (%{unconfirmed}
|
30
|
+
sense confirmar)
|
30
31
|
registered: S'han registrat correctament %{registered} usuaris (%{count}
|
31
32
|
detectats, %{errors} errors)
|
32
33
|
revoked: S'ha revocat correctament la verificació de %{revoked} usuaris
|
33
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.
|
34
39
|
index:
|
40
|
+
stats: Estadístiques d'usuaris
|
35
41
|
title: Inscriu i autoritza usuaris
|
36
42
|
new:
|
37
|
-
authorization_handler:
|
43
|
+
authorization_handler: Mètode de verificació
|
38
44
|
authorize: Autoritza els usuaris
|
39
45
|
check: Comprova l'estat dels usuaris
|
40
46
|
info: Introdueix aquí els emails, un per línia. Si els emails estan precedits
|
@@ -42,7 +48,23 @@ ca:
|
|
42
48
|
register: Registra els usuaris a la plataforma (si existeixen s'ignoraran)
|
43
49
|
revoke: Revoca l'autorització dels usuaris
|
44
50
|
submit: Envia i processa el llistat
|
45
|
-
textarea:
|
51
|
+
textarea: Llista d''emails
|
52
|
+
stats:
|
53
|
+
index:
|
54
|
+
authorized: Verificats
|
55
|
+
authorized_unconfirmed: Verificats però no confirmats
|
56
|
+
global: "- Qualsevol mètode de verificació -"
|
57
|
+
registered: Registrats
|
58
|
+
unconfirmed: No confirmats
|
46
59
|
authorizations:
|
47
60
|
new:
|
48
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
|
67
|
+
devise:
|
68
|
+
mailer:
|
69
|
+
direct_invite:
|
70
|
+
subject: Instruccions d'invitació
|
data/config/locales/en.yml
CHANGED
@@ -26,15 +26,19 @@ en:
|
|
26
26
|
authorized: "%{authorized} users have been successfully verified using
|
27
27
|
[%{handler}] (%{count} detected, %{errors} errors)"
|
28
28
|
info: "%{count} users detected, of which %{registered} are registered,
|
29
|
-
|
29
|
+
%{authorized} authorized using [%{handler}] (%{unconfirmed} unconfirmed)"
|
30
30
|
registered: "%{registered} users have been successfully registered (%{count}
|
31
31
|
detected, %{errors} errors) "
|
32
32
|
revoked: Verification from %{revoked} users have been revoked using
|
33
33
|
[%{handler}] (%{count} detected, %{errors} errors)
|
34
|
+
gdpr_disclaimer: Do this under your responsibility. Remember that you
|
35
|
+
need to have explicit consent from your users in order to register them.
|
36
|
+
Otherwise you will be infringing the GDPR regulation in EU countries.
|
34
37
|
index:
|
38
|
+
stats: User stats
|
35
39
|
title: Register and authorize users
|
36
40
|
new:
|
37
|
-
authorization_handler:
|
41
|
+
authorization_handler: Verification method
|
38
42
|
authorize: Authorize users
|
39
43
|
check: Check users status
|
40
44
|
info: Enter the emails here, one per line. If the emails are preceded
|
@@ -42,7 +46,23 @@ en:
|
|
42
46
|
register: Register users in the platform (if they exist they will be ignored)
|
43
47
|
revoke: Revoke authorization from users
|
44
48
|
submit: Send and process the list
|
45
|
-
textarea:
|
49
|
+
textarea: Emails list
|
50
|
+
stats:
|
51
|
+
index:
|
52
|
+
authorized: Authorized
|
53
|
+
authorized_unconfirmed: Authorized but unconfirmed
|
54
|
+
global: "- Any verification method -"
|
55
|
+
registered: Registered
|
56
|
+
unconfirmed: Unconfirmed
|
46
57
|
authorizations:
|
47
58
|
new:
|
48
59
|
no_action: This method requires an administrator that verifies you
|
60
|
+
verifications:
|
61
|
+
authorizations:
|
62
|
+
first_login:
|
63
|
+
actions:
|
64
|
+
direct_verifications: Direct verification
|
65
|
+
devise:
|
66
|
+
mailer:
|
67
|
+
direct_invite:
|
68
|
+
subject: Invitation instructions
|
data/config/locales/es.yml
CHANGED
@@ -26,15 +26,21 @@ es:
|
|
26
26
|
authorized: Se han verificado correctamente %{authorized} usuarios usando
|
27
27
|
[%{handler}] (%{count} detectados, %{errors} errores)
|
28
28
|
info: Se han detectado %{count} usuarios, de los cuales %{registered}
|
29
|
-
están registrados, %{authorized} autorizados usando [%{handler}] (%{unconfirmed}
|
29
|
+
están registrados, %{authorized} autorizados usando [%{handler}] (%{unconfirmed}
|
30
|
+
sin confirmar)
|
30
31
|
registered: Se han registrado correctamente %{registered} usuarios (%{count}
|
31
32
|
detectados, %{errors} errores)
|
32
33
|
revoked: Se ha revocado correctament la verificación de %{revoked} usuarios
|
33
34
|
usando [%{handler}] (%{count} detectados, %{errors} errores)
|
35
|
+
gdpr_disclaimer: Haga esto bajo su responsabilidad. Recuerde que debe
|
36
|
+
contar con el consentimiento explícito de sus usuarios para poder registrarlos.
|
37
|
+
De lo contrario, estará infringiendo la regulación GDPR en los países
|
38
|
+
de la UE.
|
34
39
|
index:
|
40
|
+
stats: Estadísticas de usuarios
|
35
41
|
title: Inscribe y autoriza usuarios
|
36
42
|
new:
|
37
|
-
authorization_handler:
|
43
|
+
authorization_handler: Método de verificación
|
38
44
|
authorize: Autoriza los usuarios
|
39
45
|
check: Comprueba el estado de los usuarios
|
40
46
|
info: Introduce aquí los emails, uno por linea. Si los emails están precedidos
|
@@ -42,7 +48,23 @@ es:
|
|
42
48
|
register: Registra los usuarios a la plataforma (si existen se ignorarán)
|
43
49
|
revoke: Revoca la autorización de los usuarios
|
44
50
|
submit: Envía y procesa el listado
|
45
|
-
textarea:
|
51
|
+
textarea: Lista de emails
|
52
|
+
stats:
|
53
|
+
index:
|
54
|
+
authorized: Verificados
|
55
|
+
authorized_unconfirmed: Verificados pero sin confirmar
|
56
|
+
global: "- Cualquier método de verificación -"
|
57
|
+
registered: Registrados
|
58
|
+
unconfirmed: Sin confirmar
|
46
59
|
authorizations:
|
47
60
|
new:
|
48
61
|
no_action: Este método requiere que un administrador os verifique
|
62
|
+
verifications:
|
63
|
+
authorizations:
|
64
|
+
first_login:
|
65
|
+
actions:
|
66
|
+
direct_verifications: Verificación directa
|
67
|
+
devise:
|
68
|
+
mailer:
|
69
|
+
direct_invite:
|
70
|
+
subject: Instrucciones de invitación
|
@@ -1,7 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "direct_verifications/version"
|
4
|
+
require_relative "direct_verifications/config"
|
4
5
|
require_relative "direct_verifications/user_processor"
|
6
|
+
require_relative "direct_verifications/user_stats"
|
5
7
|
require_relative "direct_verifications/verification"
|
6
8
|
|
7
9
|
module Decidim
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module DirectVerifications
|
5
|
+
class << self
|
6
|
+
attr_accessor :config
|
7
|
+
def configure
|
8
|
+
yield self.config ||= Config.new
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Config
|
13
|
+
attr_reader :manage_workflows
|
14
|
+
def manage_workflows=(manage_workflows)
|
15
|
+
@manage_workflows.concat(manage_workflows).uniq!
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@manage_workflows = ["direct_verifications"]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
shared_examples_for "checking users" do |params|
|
4
|
+
context "when check without mails" do
|
5
|
+
it "renders the index with info message" do
|
6
|
+
params[:userlist] = ""
|
7
|
+
perform_enqueued_jobs do
|
8
|
+
post :create, params: params
|
9
|
+
expect(flash[:info]).not_to be_empty
|
10
|
+
expect(flash[:info]).to include("0 users detected")
|
11
|
+
expect(subject).to render_template("decidim/direct_verifications/verification/admin/direct_verifications/index")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when check with mails" do
|
17
|
+
it "renders the index with info message" do
|
18
|
+
params[:userlist] = "mail@example.com"
|
19
|
+
perform_enqueued_jobs do
|
20
|
+
post :create, params: params
|
21
|
+
expect(flash[:info]).not_to be_empty
|
22
|
+
expect(flash[:info]).to include("1 users detected")
|
23
|
+
expect(subject).to render_template("decidim/direct_verifications/verification/admin/direct_verifications/index")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
shared_examples_for "registering users" do |params|
|
30
|
+
context "when there are valid emails" do
|
31
|
+
it "creates warning message" do
|
32
|
+
perform_enqueued_jobs do
|
33
|
+
post :create, params: params
|
34
|
+
expect(flash[:warning]).not_to be_empty
|
35
|
+
expect(flash[:warning]).to include("1 detected")
|
36
|
+
expect(flash[:warning]).to include("0 errors")
|
37
|
+
expect(flash[:warning]).to include("1 users")
|
38
|
+
expect(flash[:warning]).to include("registered")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
shared_examples_for "authorizing users" do |params|
|
45
|
+
context "when there are valid emails" do
|
46
|
+
it "creates notice message" do
|
47
|
+
perform_enqueued_jobs do
|
48
|
+
post :create, params: params
|
49
|
+
expect(flash[:notice]).not_to be_empty
|
50
|
+
expect(flash[:notice]).to include("1 detected")
|
51
|
+
expect(flash[:notice]).to include("0 errors")
|
52
|
+
expect(flash[:notice]).to include("1 users")
|
53
|
+
expect(flash[:notice]).to include("verified")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
shared_examples_for "revoking users" do |params|
|
60
|
+
context "when there are valid emails" do
|
61
|
+
it "creates notice message" do
|
62
|
+
create(
|
63
|
+
:authorization,
|
64
|
+
:granted,
|
65
|
+
name: verification_type,
|
66
|
+
user: authorized_user
|
67
|
+
)
|
68
|
+
perform_enqueued_jobs do
|
69
|
+
post :create, params: params
|
70
|
+
expect(flash[:notice]).not_to be_empty
|
71
|
+
expect(flash[:notice]).to include("1 detected")
|
72
|
+
expect(flash[:notice]).to include("0 errors")
|
73
|
+
expect(flash[:notice]).to include("1 users")
|
74
|
+
expect(flash[:notice]).to include("revoked")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -22,6 +22,7 @@ module Decidim
|
|
22
22
|
def register_users
|
23
23
|
@emails.each do |email, name|
|
24
24
|
next if find_user(email)
|
25
|
+
|
25
26
|
form = register_form(email, name)
|
26
27
|
begin
|
27
28
|
InviteUser.call(form) do
|
@@ -43,7 +44,8 @@ module Decidim
|
|
43
44
|
@emails.each do |email, _name|
|
44
45
|
if (u = find_user(email))
|
45
46
|
auth = authorization(u)
|
46
|
-
next
|
47
|
+
next unless !auth.granted? || auth.expired?
|
48
|
+
|
47
49
|
Verification::ConfirmUserAuthorization.call(auth, authorize_form(u)) do
|
48
50
|
on(:ok) do
|
49
51
|
add_processed :authorized, email
|
@@ -63,6 +65,7 @@ module Decidim
|
|
63
65
|
if (u = find_user(email))
|
64
66
|
auth = authorization(u)
|
65
67
|
next unless auth.granted?
|
68
|
+
|
66
69
|
Verification::DestroyUserAuthorization.call(auth) do
|
67
70
|
on(:ok) do
|
68
71
|
add_processed :revoked, email
|
@@ -77,24 +80,6 @@ module Decidim
|
|
77
80
|
end
|
78
81
|
end
|
79
82
|
|
80
|
-
def total(type)
|
81
|
-
if type == :registered
|
82
|
-
return User.where(email: @emails.keys, decidim_organization_id: @organization.id)
|
83
|
-
.count
|
84
|
-
end
|
85
|
-
if type == :unconfirmed
|
86
|
-
return User.where(email: @emails.keys, decidim_organization_id: @organization.id)
|
87
|
-
.where(confirmed_at: nil).count
|
88
|
-
end
|
89
|
-
if type == :authorized
|
90
|
-
return Decidim::Authorization.joins(:user)
|
91
|
-
.where(name: authorization_handler)
|
92
|
-
.where("decidim_users.email IN (:emails) AND decidim_users.decidim_organization_id=:org",
|
93
|
-
emails: @emails.keys, org: @organization.id).count
|
94
|
-
end
|
95
|
-
0
|
96
|
-
end
|
97
|
-
|
98
83
|
private
|
99
84
|
|
100
85
|
def find_user(email)
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module DirectVerifications
|
5
|
+
class UserStats
|
6
|
+
def initialize(organization)
|
7
|
+
@organization = organization
|
8
|
+
@authorization_handler = ""
|
9
|
+
@emails = []
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :organization, :authorization_handler
|
13
|
+
attr_accessor :emails
|
14
|
+
|
15
|
+
def authorization_handler=(name)
|
16
|
+
@workflow_manifest = nil
|
17
|
+
@authorization_handler = name
|
18
|
+
end
|
19
|
+
|
20
|
+
def registered
|
21
|
+
registered_users.count
|
22
|
+
end
|
23
|
+
|
24
|
+
def unconfirmed
|
25
|
+
registered_users.where("decidim_users.confirmed_at IS NULL").count
|
26
|
+
end
|
27
|
+
|
28
|
+
def authorized
|
29
|
+
authorized_users.count
|
30
|
+
end
|
31
|
+
|
32
|
+
def authorized_unconfirmed
|
33
|
+
authorized_users.where("decidim_users.confirmed_at IS NULL").count
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def registered_users
|
39
|
+
if authorization_handler.empty?
|
40
|
+
filter = { decidim_organization_id: organization.id }
|
41
|
+
filter[:email] = emails unless emails.empty?
|
42
|
+
return User.where(filter).where.not(email: "")
|
43
|
+
end
|
44
|
+
authorized_users(false)
|
45
|
+
end
|
46
|
+
|
47
|
+
def authorized_users(strict = true)
|
48
|
+
q = Decidim::Authorization.joins(:user)
|
49
|
+
unless authorization_handler.empty?
|
50
|
+
q = q.where(name: authorization_handler)
|
51
|
+
if strict
|
52
|
+
q = q.where.not(granted_at: nil)
|
53
|
+
q = q.where("decidim_authorizations.granted_at >= :date", date: Time.current - expires_in) if expires_in
|
54
|
+
end
|
55
|
+
end
|
56
|
+
q = q.where("decidim_users.decidim_organization_id=:org and decidim_users.email!=''", org: organization.id)
|
57
|
+
return q if emails.empty?
|
58
|
+
|
59
|
+
q.where("decidim_users.email IN (:emails)", emails: emails)
|
60
|
+
end
|
61
|
+
|
62
|
+
def expires_in
|
63
|
+
return unless workflow_manifest
|
64
|
+
return if workflow_manifest.expires_in.zero?
|
65
|
+
|
66
|
+
workflow_manifest.expires_in
|
67
|
+
end
|
68
|
+
|
69
|
+
def workflow_manifest
|
70
|
+
return if authorization_handler.empty?
|
71
|
+
|
72
|
+
@workflow_manifest ||= Decidim::Verifications.find_workflow_manifest(authorization_handler)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -8,10 +8,15 @@ module Decidim
|
|
8
8
|
paths["db/migrate"] = nil
|
9
9
|
|
10
10
|
routes do
|
11
|
-
resources :direct_verifications, only: [:index, :create]
|
11
|
+
resources :direct_verifications, only: [:index, :create, :stats]
|
12
|
+
resources :stats, only: [:index]
|
12
13
|
|
13
14
|
root to: "direct_verifications#index"
|
14
15
|
end
|
16
|
+
|
17
|
+
initializer "decidim_direct_verifications.admin_assets" do |app|
|
18
|
+
app.config.assets.precompile += %w(direct_verifications_admin_manifest.js)
|
19
|
+
end
|
15
20
|
end
|
16
21
|
end
|
17
22
|
end
|
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: decidim-direct_verifications
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.21'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Vergés
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-11-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: decidim-admin
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.21.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.21.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: decidim-core
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.
|
33
|
+
version: 0.21.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.
|
40
|
+
version: 0.21.0
|
41
41
|
description: Provides a verification method that also registers users directly in
|
42
42
|
the platform. Can be used to mass verificate user with other verification handlers
|
43
43
|
email:
|
@@ -49,20 +49,26 @@ files:
|
|
49
49
|
- LICENSE-AGPLv3.txt
|
50
50
|
- README.md
|
51
51
|
- Rakefile
|
52
|
+
- app/assets/config/direct_verifications_admin_manifest.js
|
53
|
+
- app/assets/javascripts/decidim/direct_verifications/verification/admin/direct_verifications_admin.js.es6
|
52
54
|
- app/commands/decidim/direct_verifications/verification/confirm_user_authorization.rb
|
53
55
|
- app/commands/decidim/direct_verifications/verification/destroy_user_authorization.rb
|
54
56
|
- app/controllers/decidim/direct_verifications/verification/admin/direct_verifications_controller.rb
|
57
|
+
- app/controllers/decidim/direct_verifications/verification/admin/stats_controller.rb
|
55
58
|
- app/controllers/decidim/direct_verifications/verification/authorizations_controller.rb
|
56
59
|
- app/forms/decidim/direct_verifications/verification/direct_verifications_form.rb
|
57
|
-
- app/permissions/decidim/direct_verifications/verification/admin/permissions.rb
|
58
60
|
- app/views/decidim/direct_verifications/verification/admin/direct_verifications/index.html.erb
|
61
|
+
- app/views/decidim/direct_verifications/verification/admin/stats/index.html.erb
|
59
62
|
- app/views/devise/mailer/direct_invite.html.erb
|
60
63
|
- app/views/devise/mailer/direct_invite.text.erb
|
61
64
|
- config/locales/ca.yml
|
62
65
|
- config/locales/en.yml
|
63
66
|
- config/locales/es.yml
|
64
67
|
- lib/decidim/direct_verifications.rb
|
68
|
+
- lib/decidim/direct_verifications/config.rb
|
69
|
+
- lib/decidim/direct_verifications/tests/verification_controller_examples.rb
|
65
70
|
- lib/decidim/direct_verifications/user_processor.rb
|
71
|
+
- lib/decidim/direct_verifications/user_stats.rb
|
66
72
|
- lib/decidim/direct_verifications/verification.rb
|
67
73
|
- lib/decidim/direct_verifications/verification/admin.rb
|
68
74
|
- lib/decidim/direct_verifications/verification/admin_engine.rb
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Decidim
|
4
|
-
module DirectVerifications
|
5
|
-
module Verification
|
6
|
-
module Admin
|
7
|
-
# Defines the abilities related to direct_verifications for a logged in admin user.
|
8
|
-
class Permissions < Decidim::DefaultPermissions
|
9
|
-
def permissions
|
10
|
-
return permission_action if permission_action.scope != :admin
|
11
|
-
if user.organization.available_authorizations.include?("direct_verifications")
|
12
|
-
allow! if permission_action.subject == Decidim::DirectVerifications::UserProcessor
|
13
|
-
permission_action
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|