decidim-direct_verifications 0.17.5 → 0.21
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 +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
|
+
[](https://codeclimate.com/github/Platoniq/decidim-verifications-direct_verifications/maintainability)
|
5
|
+
[](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
|