decidim-direct_verifications 0.17.8 → 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +43 -2
- data/app/assets/config/direct_verifications_admin_manifest.css +3 -0
- data/app/assets/stylesheets/decidim/direct_verifications/authorizations.scss +17 -0
- data/app/commands/decidim/direct_verifications/verification/create_import.rb +50 -0
- data/app/controllers/decidim/direct_verifications/verification/admin/authorizations_controller.rb +40 -0
- data/app/controllers/decidim/direct_verifications/verification/admin/direct_verifications_controller.rb +71 -46
- data/app/controllers/decidim/direct_verifications/verification/admin/imports_controller.rb +55 -0
- data/app/forms/decidim/direct_verifications/registration_form.rb +8 -0
- data/app/forms/decidim/direct_verifications/verification/create_import_form.rb +43 -0
- data/app/jobs/decidim/direct_verifications/authorize_users_job.rb +34 -0
- data/app/jobs/decidim/direct_verifications/base_import_job.rb +38 -0
- data/app/jobs/decidim/direct_verifications/register_users_job.rb +19 -0
- data/app/jobs/decidim/direct_verifications/revoke_users_job.rb +17 -0
- data/app/mailers/decidim/direct_verifications/import_mailer.rb +27 -0
- data/app/mailers/decidim/direct_verifications/stats.rb +23 -0
- data/app/views/decidim/direct_verifications/import_mailer/finished_processing.html.erb +7 -0
- data/app/views/decidim/direct_verifications/import_mailer/finished_processing.text.erb +7 -0
- data/app/views/decidim/direct_verifications/verification/admin/authorizations/index.html.erb +42 -0
- data/app/views/decidim/direct_verifications/verification/admin/direct_verifications/index.html.erb +18 -17
- data/app/views/decidim/direct_verifications/verification/admin/imports/new.html.erb +50 -0
- data/app/views/decidim/direct_verifications/verification/admin/stats/index.html.erb +3 -3
- data/config/initializers/mail_previews.rb +5 -0
- data/config/locales/ca.yml +25 -20
- data/config/locales/cs.yml +69 -0
- data/config/locales/en.yml +34 -2
- data/config/locales/es.yml +25 -20
- data/config/locales/fr.yml +69 -0
- data/lib/decidim/direct_verifications.rb +24 -1
- data/lib/decidim/direct_verifications/authorize_user.rb +64 -0
- data/lib/decidim/direct_verifications/instrumenter.rb +58 -0
- data/lib/decidim/direct_verifications/parsers.rb +11 -0
- data/lib/decidim/direct_verifications/parsers/base_parser.rb +37 -0
- data/lib/decidim/direct_verifications/parsers/metadata_parser.rb +54 -0
- data/lib/decidim/direct_verifications/parsers/name_parser.rb +40 -0
- data/lib/decidim/direct_verifications/register_user.rb +54 -0
- data/lib/decidim/direct_verifications/revoke_user.rb +45 -0
- data/lib/decidim/direct_verifications/tests/factories.rb +11 -0
- data/lib/decidim/direct_verifications/tests/verification_controller_examples.rb +83 -0
- data/lib/decidim/direct_verifications/user_processor.rb +18 -98
- data/lib/decidim/direct_verifications/user_stats.rb +9 -6
- data/lib/decidim/direct_verifications/verification/admin_engine.rb +6 -1
- data/lib/decidim/direct_verifications/version.rb +3 -2
- metadata +38 -9
- data/lib/decidim/direct_verifications/config.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 46d0f12ed4661879a4cdec82f1482875823fe9c5f4fba39c129e2a020d3c7f19
|
4
|
+
data.tar.gz: 5cf039fb0a1b3474082dbf7acc28013d8d0034c6d959c7c7ad589aca85c1fdf8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f960edacf1528f9801d6cfd82aa6898a5bffbf9233a2386a57cdb0c55c0a3d5ef45ddf501d1775db1ab325dbcd61925b012dcc3ab8bf83bedbd4630abbf3b03
|
7
|
+
data.tar.gz: 909e8c8be3368861bc6fe75c1290f820a4d697e20bf4ded85d9e91ec9a5b7a27d3aa65953d749460d3fe0efbfe132fd8aa586ac27e032782127463be98476a61
|
data/README.md
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# Decidim::DirectVerifications
|
2
2
|
|
3
|
-
[![
|
3
|
+
[![Test](https://github.com/Platoniq/decidim-verifications-direct_verifications/actions/workflows/test.yml/badge.svg)](https://github.com/Platoniq/decidim-verifications-direct_verifications/actions/workflows/test.yml)
|
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/main/graph/badge.svg?token=FR1zkV71S2)](https://codecov.io/gh/Platoniq/decidim-verifications-direct_verifications)
|
6
|
+
|
7
|
+
|
4
8
|
|
5
9
|
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
10
|
|
@@ -34,6 +38,23 @@ With the detected list of emails admin have different options available:
|
|
34
38
|
3. Revoke the authorization for the list of users using any verification method available.
|
35
39
|
4. Check the status of the users in order to know if they are verified or registered.
|
36
40
|
|
41
|
+
### Metadata mode
|
42
|
+
|
43
|
+
This mode provides extra capabilities over the default processing:
|
44
|
+
|
45
|
+
* Reads CSV format with header (copy and paste it from your spreadsheet)
|
46
|
+
* Stores all columns except the email as authorization metadata
|
47
|
+
|
48
|
+
This enables querying the authorization metadata however fits you best.
|
49
|
+
|
50
|
+
To enable it create a new initializer, for instance `config/initializers/decidim_direct_verifications.rb` with the following contents
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
Decidim::DirectVerifications.configure do |config|
|
54
|
+
config.input_parser = :metadata_parser
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
37
58
|
## Installation
|
38
59
|
|
39
60
|
Add this line to your application's Gemfile:
|
@@ -48,6 +69,13 @@ And then execute:
|
|
48
69
|
bundle
|
49
70
|
```
|
50
71
|
|
72
|
+
Depending on your Decidim version, you might want to specify the version to ensure compatibility:
|
73
|
+
|
74
|
+
| Direct Verifications version | Compatible Decidim versions |
|
75
|
+
|---|---|
|
76
|
+
| 1.0 | >= 0.23.x |
|
77
|
+
| 0.22.x | 0.22.x |
|
78
|
+
|
51
79
|
## Using additional verification methods
|
52
80
|
|
53
81
|
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.
|
@@ -68,7 +96,10 @@ end
|
|
68
96
|
|
69
97
|
# We need to tell the plugin to handle this method in addition to the default "Direct verification". Any registered workflow is valid.
|
70
98
|
Decidim::DirectVerifications.configure do |config|
|
71
|
-
config.manage_workflows = %w(direct_verifications_managers)
|
99
|
+
config.manage_workflows = %w(direct_verifications direct_verifications_managers)
|
100
|
+
|
101
|
+
# change the to the metadata_parser if you want it
|
102
|
+
# config.input_parser = :metadata_parser
|
72
103
|
end
|
73
104
|
|
74
105
|
```
|
@@ -84,6 +115,11 @@ en:
|
|
84
115
|
direct_verifications_managers:
|
85
116
|
name: Organization managers
|
86
117
|
explanation: Direct Verifications Subgroup explanation
|
118
|
+
verifications:
|
119
|
+
authorizations:
|
120
|
+
first_login:
|
121
|
+
actions:
|
122
|
+
direct_verifications_managers: Organization managers
|
87
123
|
```
|
88
124
|
|
89
125
|
Similarly, you can also overwrite the default title "Direct verification" by creating the key again in your locales:
|
@@ -95,6 +131,11 @@ en:
|
|
95
131
|
direct_verifications:
|
96
132
|
name: Generic organization members
|
97
133
|
explanation: Direct Verifications Subgroup explanation
|
134
|
+
verifications:
|
135
|
+
authorizations:
|
136
|
+
first_login:
|
137
|
+
actions:
|
138
|
+
direct_verifications: Generic organization members
|
98
139
|
```
|
99
140
|
|
100
141
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
@import "decidim/admin/utils/settings";
|
2
|
+
|
3
|
+
$code-color: $black;
|
4
|
+
$code-font-family: $font-family-monospace;
|
5
|
+
$code-font-weight: $global-weight-normal;
|
6
|
+
$code-background: $light-gray;
|
7
|
+
$code-border: 1px solid $medium-gray;
|
8
|
+
$code-padding: rem-calc(2 5 1);
|
9
|
+
|
10
|
+
.code {
|
11
|
+
background: $code-background;
|
12
|
+
color: $code-color;
|
13
|
+
font-family: $code-font-family;
|
14
|
+
font-weight: $code-font-weight;
|
15
|
+
border: $code-border;
|
16
|
+
padding: $code-padding;
|
17
|
+
}
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module DirectVerifications
|
5
|
+
module Verification
|
6
|
+
class CreateImport < Rectify::Command
|
7
|
+
def initialize(form)
|
8
|
+
@form = form
|
9
|
+
@file = form.file
|
10
|
+
@organization = form.organization
|
11
|
+
@user = form.user
|
12
|
+
@action = form.action
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
return broadcast(:invalid) unless form.valid?
|
17
|
+
|
18
|
+
case action
|
19
|
+
when :register
|
20
|
+
register_users_async
|
21
|
+
when :register_and_authorize
|
22
|
+
register_users_async
|
23
|
+
file.rewind
|
24
|
+
authorize_users_async
|
25
|
+
when :revoke
|
26
|
+
revoke_users_async
|
27
|
+
end
|
28
|
+
|
29
|
+
broadcast(:ok)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
attr_reader :form, :file, :organization, :user, :action
|
35
|
+
|
36
|
+
def register_users_async
|
37
|
+
RegisterUsersJob.perform_later(file.read, organization, user, form.authorization_handler)
|
38
|
+
end
|
39
|
+
|
40
|
+
def revoke_users_async
|
41
|
+
RevokeUsersJob.perform_later(file.read, organization, user, form.authorization_handler)
|
42
|
+
end
|
43
|
+
|
44
|
+
def authorize_users_async
|
45
|
+
AuthorizeUsersJob.perform_later(file.read, organization, user, form.authorization_handler)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/app/controllers/decidim/direct_verifications/verification/admin/authorizations_controller.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module DirectVerifications
|
5
|
+
module Verification
|
6
|
+
module Admin
|
7
|
+
class AuthorizationsController < Decidim::Admin::ApplicationController
|
8
|
+
layout "decidim/admin/users"
|
9
|
+
|
10
|
+
def index
|
11
|
+
enforce_permission_to :index, :authorization
|
12
|
+
@authorizations = collection.includes(:user)
|
13
|
+
end
|
14
|
+
|
15
|
+
def destroy
|
16
|
+
if authorization.destroy
|
17
|
+
flash[:notice] = "successfully"
|
18
|
+
redirect_to authorizations_path
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def collection
|
25
|
+
# Decidim::Verifications::Authorizations Query
|
26
|
+
Decidim::Verifications::Authorizations.new(
|
27
|
+
organization: current_organization,
|
28
|
+
name: "direct_verifications",
|
29
|
+
granted: true
|
30
|
+
).query
|
31
|
+
end
|
32
|
+
|
33
|
+
def authorization
|
34
|
+
@authorization ||= collection.find_by(id: params[:id])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -6,75 +6,100 @@ 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
14
|
enforce_permission_to :index, :authorization
|
14
|
-
@authorization_handler = :direct_verifications
|
15
|
-
@workflows = workflows
|
16
15
|
end
|
17
16
|
|
18
17
|
def create
|
19
18
|
enforce_permission_to :create, :authorization
|
20
19
|
|
21
|
-
@
|
22
|
-
|
23
|
-
processor = UserProcessor.new(current_organization, current_user)
|
24
|
-
processor.emails =
|
25
|
-
processor.authorization_handler =
|
26
|
-
|
27
|
-
stats
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
errors: processor.errors[:authorized].count)
|
40
|
-
elsif params[:authorize] == "out"
|
41
|
-
processor.revoke_users
|
42
|
-
flash[:notice] = t(".revoked", handler: t("#{processor.authorization_handler}.name", scope: "decidim.authorization_handlers"),
|
43
|
-
count: processor.emails.count,
|
44
|
-
revoked: processor.processed[:revoked].count,
|
45
|
-
errors: processor.errors[:revoked].count)
|
46
|
-
else
|
47
|
-
stats.emails = processor.emails.keys
|
48
|
-
flash[:info] = t(".info", handler: t("#{processor.authorization_handler}.name", scope: "decidim.authorization_handlers"),
|
49
|
-
count: processor.emails.count,
|
50
|
-
authorized: stats.authorized,
|
51
|
-
unconfirmed: stats.unconfirmed,
|
52
|
-
registered: stats.registered)
|
53
|
-
render(action: :index) && return
|
54
|
-
end
|
20
|
+
@userslist = params[:userslist]
|
21
|
+
|
22
|
+
@processor = UserProcessor.new(current_organization, current_user, session, instrumenter)
|
23
|
+
@processor.emails = parser_class.new(@userslist).to_h
|
24
|
+
@processor.authorization_handler = current_authorization_handler
|
25
|
+
|
26
|
+
@stats = UserStats.new(current_organization)
|
27
|
+
@stats.authorization_handler = @processor.authorization_handler
|
28
|
+
|
29
|
+
register_users
|
30
|
+
authorize_users
|
31
|
+
revoke_users
|
32
|
+
|
33
|
+
render(action: :index) && return if show_users_info
|
34
|
+
|
35
|
+
redirect_to direct_verifications_path
|
36
|
+
rescue InputParserError => e
|
37
|
+
flash[:error] = e.message
|
55
38
|
redirect_to direct_verifications_path
|
56
39
|
end
|
57
40
|
|
58
41
|
private
|
59
42
|
|
60
|
-
def
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
43
|
+
def instrumenter
|
44
|
+
@instrumenter ||= Instrumenter.new(current_user)
|
45
|
+
end
|
46
|
+
|
47
|
+
def register_users
|
48
|
+
return unless params[:register]
|
49
|
+
|
50
|
+
@processor.register_users
|
51
|
+
flash[:warning] = t(".registered", count: @processor.emails.count,
|
52
|
+
registered: instrumenter.processed_count(:registered),
|
53
|
+
errors: instrumenter.errors_count(:registered))
|
54
|
+
end
|
55
|
+
|
56
|
+
def authorize_users
|
57
|
+
return unless params[:authorize] == "in"
|
58
|
+
|
59
|
+
@processor.authorize_users
|
60
|
+
flash[:notice] = t(".authorized", handler: t("#{@processor.authorization_handler}.name", scope: "decidim.authorization_handlers"),
|
61
|
+
count: @processor.emails.count,
|
62
|
+
authorized: instrumenter.processed_count(:authorized),
|
63
|
+
errors: instrumenter.errors_count(:authorized))
|
64
|
+
end
|
65
|
+
|
66
|
+
def revoke_users
|
67
|
+
return unless params[:authorize] == "out"
|
68
|
+
|
69
|
+
@processor.revoke_users
|
70
|
+
flash[:notice] = t(".revoked", handler: t("#{@processor.authorization_handler}.name", scope: "decidim.authorization_handlers"),
|
71
|
+
count: @processor.emails.count,
|
72
|
+
revoked: instrumenter.processed_count(:revoked),
|
73
|
+
errors: instrumenter.errors_count(:revoked))
|
74
|
+
end
|
75
|
+
|
76
|
+
def show_users_info
|
77
|
+
return if params[:authorize].in? %w(in out)
|
78
|
+
|
79
|
+
@stats.emails = @processor.emails.keys
|
80
|
+
flash.now[:info] = t(".info", handler: t("#{@processor.authorization_handler}.name", scope: "decidim.authorization_handlers"),
|
81
|
+
count: @processor.emails.count,
|
82
|
+
authorized: @stats.authorized,
|
83
|
+
unconfirmed: @stats.unconfirmed,
|
84
|
+
registered: @stats.registered)
|
85
|
+
true
|
86
|
+
end
|
87
|
+
|
88
|
+
def parser_class
|
89
|
+
Decidim::DirectVerifications.find_parser_class(Decidim::DirectVerifications.input_parser)
|
70
90
|
end
|
71
91
|
|
72
92
|
def authorization_handler(authorization_handler)
|
73
93
|
@authorization_handler = authorization_handler.presence || :direct_verifications
|
74
94
|
end
|
75
95
|
|
96
|
+
def current_authorization_handler
|
97
|
+
authorization_handler(params[:authorization_handler])
|
98
|
+
end
|
99
|
+
|
76
100
|
def configured_workflows
|
77
101
|
return Decidim::DirectVerifications.config.manage_workflows if Decidim::DirectVerifications.config
|
102
|
+
|
78
103
|
["direct_verifications"]
|
79
104
|
end
|
80
105
|
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module DirectVerifications
|
5
|
+
module Verification
|
6
|
+
module Admin
|
7
|
+
class ImportsController < Decidim::Admin::ApplicationController
|
8
|
+
layout "decidim/admin/users"
|
9
|
+
helper_method :workflows, :current_authorization_handler
|
10
|
+
|
11
|
+
def new
|
12
|
+
enforce_permission_to :create, :authorization
|
13
|
+
@form = form(CreateImportForm).instance
|
14
|
+
end
|
15
|
+
|
16
|
+
def create
|
17
|
+
enforce_permission_to :create, :authorization
|
18
|
+
|
19
|
+
defaults = { organization: current_organization, user: current_user }
|
20
|
+
form = form(CreateImportForm).from_params(params.merge(defaults))
|
21
|
+
|
22
|
+
CreateImport.call(form) do
|
23
|
+
on(:ok) do
|
24
|
+
flash[:notice] = t(".success")
|
25
|
+
end
|
26
|
+
|
27
|
+
on(:invalid) do
|
28
|
+
flash[:alert] = t(".error")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
redirect_to new_import_path
|
33
|
+
end
|
34
|
+
|
35
|
+
def workflows
|
36
|
+
workflows = configured_workflows & current_organization.available_authorizations.map.to_a
|
37
|
+
workflows.map do |workflow|
|
38
|
+
[t("#{workflow}.name", scope: "decidim.authorization_handlers"), workflow]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def configured_workflows
|
43
|
+
return Decidim::DirectVerifications.config.manage_workflows if Decidim::DirectVerifications.config
|
44
|
+
|
45
|
+
["direct_verifications"]
|
46
|
+
end
|
47
|
+
|
48
|
+
def current_authorization_handler
|
49
|
+
params[:authorization_handler]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module DirectVerifications
|
5
|
+
module Verification
|
6
|
+
class CreateImportForm < Form
|
7
|
+
ACTIONS = {
|
8
|
+
"in" => :authorize,
|
9
|
+
"out" => :revoke,
|
10
|
+
"check" => :check
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
attribute :file
|
14
|
+
attribute :organization, Decidim::Organization
|
15
|
+
attribute :user, Decidim::User
|
16
|
+
attribute :authorize, String
|
17
|
+
attribute :register, Boolean
|
18
|
+
attribute :authorization_handler, String
|
19
|
+
|
20
|
+
validates :file, :organization, :user, :authorize, :authorization_handler, presence: true
|
21
|
+
validates :authorize, inclusion: { in: ACTIONS.keys }
|
22
|
+
|
23
|
+
validate :available_authorization_handler
|
24
|
+
|
25
|
+
def available_authorization_handler
|
26
|
+
return if authorization_handler.in?(organization.available_authorizations)
|
27
|
+
|
28
|
+
errors.add(:authorization_handler, :inclusion)
|
29
|
+
end
|
30
|
+
|
31
|
+
def action
|
32
|
+
if register && authorize == "in"
|
33
|
+
:register_and_authorize
|
34
|
+
elsif register
|
35
|
+
:register
|
36
|
+
else
|
37
|
+
ACTIONS[authorize]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|