decidim-verifications 0.15.2 → 0.16.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 +37 -7
- data/app/commands/decidim/verifications/id_documents/admin/confirm_user_offline_authorization.rb +74 -0
- data/app/commands/decidim/verifications/id_documents/admin/update_config.rb +39 -0
- data/app/controllers/decidim/verifications/id_documents/admin/config_controller.rb +40 -0
- data/app/controllers/decidim/verifications/id_documents/admin/offline_confirmations_controller.rb +40 -0
- data/app/controllers/decidim/verifications/id_documents/admin/pending_authorizations_controller.rb +13 -2
- data/app/controllers/decidim/verifications/id_documents/authorizations_controller.rb +30 -2
- data/app/controllers/decidim/verifications/sms/authorizations_controller.rb +76 -0
- data/app/forms/decidim/verifications/id_documents/admin/config_form.rb +42 -0
- data/app/forms/decidim/verifications/id_documents/admin/offline_confirmation_form.rb +16 -0
- data/app/forms/decidim/verifications/id_documents/information_form.rb +12 -1
- data/app/forms/decidim/verifications/id_documents/upload_form.rb +2 -1
- data/app/forms/decidim/verifications/sms/confirmation_form.rb +19 -0
- data/app/forms/decidim/verifications/sms/mobile_phone_form.rb +59 -0
- data/app/views/decidim/verifications/id_documents/admin/config/edit.html.erb +26 -0
- data/app/views/decidim/verifications/id_documents/admin/confirmations/new.html.erb +1 -0
- data/app/views/decidim/verifications/id_documents/admin/offline_confirmations/new.html.erb +24 -0
- data/app/views/decidim/verifications/id_documents/admin/pending_authorizations/index.html.erb +3 -1
- data/app/views/decidim/verifications/id_documents/authorizations/_form.html.erb +17 -0
- data/app/views/decidim/verifications/id_documents/authorizations/choose.html.erb +21 -0
- data/app/views/decidim/verifications/id_documents/authorizations/edit.html.erb +14 -23
- data/app/views/decidim/verifications/id_documents/authorizations/new.html.erb +6 -13
- data/app/views/decidim/verifications/sms/authorizations/edit.html.erb +27 -0
- data/app/views/decidim/verifications/sms/authorizations/new.html.erb +27 -0
- data/config/locales/ca.yml +51 -1
- data/config/locales/de.yml +50 -0
- data/config/locales/en.yml +51 -1
- data/config/locales/es-PY.yml +50 -0
- data/config/locales/es.yml +51 -1
- data/config/locales/eu.yml +50 -0
- data/config/locales/fi-pl.yml +51 -1
- data/config/locales/fi.yml +51 -1
- data/config/locales/fr.yml +50 -0
- data/config/locales/gl.yml +50 -0
- data/config/locales/hu.yml +50 -0
- data/config/locales/id-ID.yml +51 -1
- data/config/locales/it.yml +50 -0
- data/config/locales/nl.yml +50 -0
- data/config/locales/pl.yml +50 -0
- data/config/locales/pt-BR.yml +50 -0
- data/config/locales/pt.yml +50 -0
- data/config/locales/sv.yml +50 -0
- data/config/locales/tr-TR.yml +51 -1
- data/lib/decidim/verifications.rb +1 -0
- data/lib/decidim/verifications/id_documents/admin_engine.rb +3 -0
- data/lib/decidim/verifications/id_documents/engine.rb +6 -2
- data/lib/decidim/verifications/sms.rb +4 -0
- data/lib/decidim/verifications/sms/engine.rb +29 -0
- data/lib/decidim/verifications/sms/example_gateway.rb +21 -0
- data/lib/decidim/verifications/version.rb +1 -1
- metadata +27 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3f72535ac2342a5548bc109d27133bdbbc04ea5d31bf75e6bea9388129cfd962
|
4
|
+
data.tar.gz: 65a300dbe94c86dc4a185946617608e78cf912879df40aca37b72e4eb08504a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8aea64e88a8f1ec983ee81e4ccdaab8c6788077ef171aac9ba432710eddbbf2d595e9a8200c0b5cff2735fc1b3659d4d4384c77d8c73cb6a369c33f4d0be550
|
7
|
+
data.tar.gz: 27e690f78d70610141648ec4acc0551401aa904476caeb842de371a57586cdd812ea2c5ab3dc23c27328a6f220deb5a4210b4b515305ce860c890304cfd57af0
|
data/README.md
CHANGED
@@ -76,9 +76,9 @@ Decidim implements two type of authorization methods:
|
|
76
76
|
```ruby
|
77
77
|
# config/initializers/decidim.rb
|
78
78
|
|
79
|
-
Decidim::Verifications.register_workflow(:
|
80
|
-
workflow.engine = Decidim::Verifications::
|
81
|
-
workflow.admin_engine = Decidim::Verifications::
|
79
|
+
Decidim::Verifications.register_workflow(:my_verification) do |workflow|
|
80
|
+
workflow.engine = Decidim::Verifications::MyVerification::Engine
|
81
|
+
workflow.admin_engine = Decidim::Verifications::MyVerification::AdminEngine
|
82
82
|
end
|
83
83
|
```
|
84
84
|
|
@@ -97,6 +97,24 @@ Decidim implements two type of authorization methods:
|
|
97
97
|
* `edit_authorization_path`: This is the entry point to resume an existing
|
98
98
|
authorization process.
|
99
99
|
|
100
|
+
### SMS verification
|
101
|
+
|
102
|
+
Decidim comes with a verification workflow designed to verify users by sending
|
103
|
+
an SMS to their mobile phone.
|
104
|
+
|
105
|
+
Much like a Census verification you just need to implement a class that sends an
|
106
|
+
SMS code using your preferred provider.
|
107
|
+
|
108
|
+
In order to setup Decidim with SMS verification you need to:
|
109
|
+
|
110
|
+
1. Create a class that accepts two parameters when initializing it (mobile phone and code) and a method named `deliver_code` that will send an SMS and return a truthy or falsey value if the delivery was OK or not.
|
111
|
+
1. Set the `sms_gateway_service` configuration variable to the name of the class that you just created (use a String, not the actual class) at `config/initializers/decidim.rb`.
|
112
|
+
|
113
|
+
Keep in mind that Decidim won't store a free text version of the mobile phone, only a hashed
|
114
|
+
version so we can avoid duplicates and guarantee the users' privacy.
|
115
|
+
|
116
|
+
You can find an example [here][example SMS gateway].
|
117
|
+
|
100
118
|
## Authorization options
|
101
119
|
|
102
120
|
Sometimes you want to scope authorizations only to users that meet certain
|
@@ -163,10 +181,10 @@ its workflow manifest:
|
|
163
181
|
```ruby
|
164
182
|
# config/initializers/decidim.rb
|
165
183
|
|
166
|
-
Decidim::Verifications.register_workflow(:
|
167
|
-
workflow.engine = Decidim::Verifications::
|
168
|
-
workflow.admin_engine = Decidim::Verifications::
|
169
|
-
workflow.action_authorizer = "Decidim::Verifications::
|
184
|
+
Decidim::Verifications.register_workflow(:my_verification) do |workflow|
|
185
|
+
workflow.engine = Decidim::Verifications::MyVerification::Engine
|
186
|
+
workflow.admin_engine = Decidim::Verifications::MyVerification::AdminEngine
|
187
|
+
workflow.action_authorizer = "Decidim::Verifications::MyVerification::ActionAuthorizer"
|
170
188
|
end
|
171
189
|
```
|
172
190
|
|
@@ -174,6 +192,17 @@ Check the [example authorization handler](https://github.com/decidim/decidim/blo
|
|
174
192
|
and the [DefaultActionAuthorizer class](https://github.com/decidim/decidim/blob/master/decidim-verifications/lib/decidim/verifications/default_action_authorizer.rb)
|
175
193
|
for additional technical details.
|
176
194
|
|
195
|
+
## How Handlers work
|
196
|
+
|
197
|
+
For a workflow to be visible in the user's profile, the organization must have
|
198
|
+
it in it's `available_authorizations` and the given handler must exist.
|
199
|
+
The name of the handler must match the authorization name plus the "Hander"
|
200
|
+
suffix. It also has to be in the `Decidim::Verifications` namespace.
|
201
|
+
|
202
|
+
The handler is both the Form object that the user must fill in order to be
|
203
|
+
verified, but also the validator of the filled information in order to grant the
|
204
|
+
authorization.
|
205
|
+
|
177
206
|
## Installation
|
178
207
|
|
179
208
|
Add this line to your application's Gemfile:
|
@@ -197,6 +226,7 @@ See [Decidim](https://github.com/decidim/decidim).
|
|
197
226
|
See [Decidim](https://github.com/decidim/decidim).
|
198
227
|
|
199
228
|
[authorization handler base class]: https://github.com/decidim/decidim/blob/master/decidim-core/app/services/decidim/authorization_handler.rb
|
229
|
+
[example SMS gateway]: https://github.com/decidim/decidim/blob/master/decidim-verifications/lib/decidim/verifications/sms/example_gateway.rb
|
200
230
|
|
201
231
|
[Decidim Barcelona]: https://github.com/AjuntamentdeBarcelona/decidim-barcelona/blob/master/app/services/census_authorization_handler.rb
|
202
232
|
[Decidim Terrassa]: https://github.com/AjuntamentDeTerrassa/decidim-terrassa/blob/master/app/services/census_authorization_handler.rb
|
data/app/commands/decidim/verifications/id_documents/admin/confirm_user_offline_authorization.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Verifications
|
5
|
+
module IdDocuments
|
6
|
+
module Admin
|
7
|
+
# A command to confirm a previous partial offline authorization.
|
8
|
+
class ConfirmUserOfflineAuthorization < Rectify::Command
|
9
|
+
# Public: Initializes the command.
|
10
|
+
#
|
11
|
+
# form - A form object with the verification data to confirm it.
|
12
|
+
def initialize(form)
|
13
|
+
@form = form
|
14
|
+
end
|
15
|
+
|
16
|
+
# Executes the command. Broadcasts these events:
|
17
|
+
#
|
18
|
+
# - :ok when everything is valid.
|
19
|
+
# - :invalid if the handler wasn't valid and we couldn't proceed.
|
20
|
+
#
|
21
|
+
# Returns nothing.
|
22
|
+
def call
|
23
|
+
return broadcast(:invalid) unless form.valid?
|
24
|
+
return broadcast(:invalid) unless authorization
|
25
|
+
|
26
|
+
if confirmation_successful?
|
27
|
+
grant_authorization
|
28
|
+
broadcast(:ok)
|
29
|
+
else
|
30
|
+
broadcast(:invalid)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def confirmation_successful?
|
37
|
+
form.verification_metadata.all? do |key, value|
|
38
|
+
authorization.verification_metadata[key] == value
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
attr_reader :form
|
45
|
+
|
46
|
+
def grant_authorization
|
47
|
+
Decidim.traceability.perform_action!(
|
48
|
+
:grant_id_documents_offline_verification,
|
49
|
+
authorization_user,
|
50
|
+
form.current_user
|
51
|
+
) do
|
52
|
+
authorization.grant!
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def authorization
|
57
|
+
@authorization ||= Authorizations
|
58
|
+
.new(organization: form.current_organization, name: "id_documents", granted: false)
|
59
|
+
.query
|
60
|
+
.where("verification_metadata->'rejected' IS NULL")
|
61
|
+
.where("verification_metadata->>'verification_type' = 'offline'")
|
62
|
+
.find_by(user: authorization_user)
|
63
|
+
end
|
64
|
+
|
65
|
+
def authorization_user
|
66
|
+
@authorization_user ||= Decidim::User
|
67
|
+
.where(organization: form.current_organization)
|
68
|
+
.find_by(email: form.email)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Verifications
|
5
|
+
module IdDocuments
|
6
|
+
module Admin
|
7
|
+
class UpdateConfig < Rectify::Command
|
8
|
+
def initialize(form)
|
9
|
+
@form = form
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
return broadcast(:invalid) if form.invalid?
|
14
|
+
|
15
|
+
update_config
|
16
|
+
|
17
|
+
broadcast(:ok)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :form
|
23
|
+
|
24
|
+
def update_config
|
25
|
+
Decidim.traceability.perform_action!(
|
26
|
+
:update_id_documents_config,
|
27
|
+
form.current_organization,
|
28
|
+
form.current_user
|
29
|
+
) do
|
30
|
+
form.current_organization.id_documents_methods = form.selected_methods
|
31
|
+
form.current_organization.id_documents_explanation_text = form.offline_explanation
|
32
|
+
form.current_organization.save!
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Verifications
|
5
|
+
module IdDocuments
|
6
|
+
module Admin
|
7
|
+
#
|
8
|
+
# Handles the configuration for the ID documents verification
|
9
|
+
#
|
10
|
+
class ConfigController < Decidim::Admin::ApplicationController
|
11
|
+
layout "decidim/admin/users"
|
12
|
+
|
13
|
+
def edit
|
14
|
+
enforce_permission_to :update, :organization, organization: current_organization
|
15
|
+
|
16
|
+
@form = form(ConfigForm).from_model(current_organization)
|
17
|
+
end
|
18
|
+
|
19
|
+
def update
|
20
|
+
enforce_permission_to :update, :organization, organization: current_organization
|
21
|
+
|
22
|
+
@form = form(ConfigForm).from_params(params)
|
23
|
+
|
24
|
+
UpdateConfig.call(@form) do
|
25
|
+
on(:ok) do
|
26
|
+
flash[:notice] = t("config.update.success", scope: "decidim.verifications.id_documents.admin")
|
27
|
+
redirect_to pending_authorizations_path
|
28
|
+
end
|
29
|
+
|
30
|
+
on(:invalid) do
|
31
|
+
flash.now[:alert] = t("config.update.error", scope: "decidim.verifications.id_documents.admin")
|
32
|
+
render action: :edit
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/app/controllers/decidim/verifications/id_documents/admin/offline_confirmations_controller.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Verifications
|
5
|
+
module IdDocuments
|
6
|
+
module Admin
|
7
|
+
#
|
8
|
+
# Handles confirmations for offline verification by identity document.
|
9
|
+
#
|
10
|
+
class OfflineConfirmationsController < Decidim::Admin::ApplicationController
|
11
|
+
layout "decidim/admin/users"
|
12
|
+
|
13
|
+
def new
|
14
|
+
enforce_permission_to :update, :authorization
|
15
|
+
|
16
|
+
@form = form(OfflineConfirmationForm).instance
|
17
|
+
end
|
18
|
+
|
19
|
+
def create
|
20
|
+
enforce_permission_to :update, :authorization
|
21
|
+
|
22
|
+
@form = form(OfflineConfirmationForm).from_params(params)
|
23
|
+
|
24
|
+
ConfirmUserOfflineAuthorization.call(@form) do
|
25
|
+
on(:ok) do
|
26
|
+
flash[:notice] = t("offline_confirmations.create.success", scope: "decidim.verifications.id_documents.admin")
|
27
|
+
redirect_to pending_authorizations_path
|
28
|
+
end
|
29
|
+
|
30
|
+
on(:invalid) do
|
31
|
+
flash.now[:alert] = t("offline_confirmations.create.error", scope: "decidim.verifications.id_documents.admin")
|
32
|
+
render action: :new
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/app/controllers/decidim/verifications/id_documents/admin/pending_authorizations_controller.rb
CHANGED
@@ -7,19 +7,30 @@ module Decidim
|
|
7
7
|
class PendingAuthorizationsController < Decidim::Admin::ApplicationController
|
8
8
|
layout "decidim/admin/users"
|
9
9
|
|
10
|
+
helper_method :has_offline_method?
|
11
|
+
|
10
12
|
def index
|
11
13
|
enforce_permission_to :index, :authorization
|
12
14
|
|
13
|
-
@
|
15
|
+
@pending_online_authorizations = pending_online_authorizations
|
14
16
|
end
|
15
17
|
|
16
18
|
private
|
17
19
|
|
18
|
-
def
|
20
|
+
def pending_online_authorizations
|
19
21
|
Authorizations
|
20
22
|
.new(organization: current_organization, name: "id_documents", granted: false)
|
21
23
|
.query
|
22
24
|
.where("verification_metadata->'rejected' IS NULL")
|
25
|
+
.where("verification_metadata->>'verification_type' = 'online'")
|
26
|
+
end
|
27
|
+
|
28
|
+
def has_offline_method?
|
29
|
+
available_methods.include?("offline")
|
30
|
+
end
|
31
|
+
|
32
|
+
def available_methods
|
33
|
+
@available_methods ||= current_organization.id_documents_methods
|
23
34
|
end
|
24
35
|
end
|
25
36
|
end
|
@@ -7,14 +7,20 @@ module Decidim
|
|
7
7
|
# Handles verification by identity document upload
|
8
8
|
#
|
9
9
|
class AuthorizationsController < ApplicationController
|
10
|
-
helper_method :authorization
|
10
|
+
helper_method :authorization, :verification_type, :using_offline?, :using_online?, :available_methods
|
11
11
|
|
12
12
|
before_action :load_authorization
|
13
13
|
|
14
|
+
def choose
|
15
|
+
return redirect_to action: :new, using: verification_type if available_methods.count == 1
|
16
|
+
render :choose
|
17
|
+
end
|
18
|
+
|
14
19
|
def new
|
20
|
+
raise ActionController::RoutingError, "Method not available" unless available_methods.include?(verification_type)
|
15
21
|
enforce_permission_to :create, :authorization, authorization: @authorization
|
16
22
|
|
17
|
-
@form = UploadForm.
|
23
|
+
@form = UploadForm.from_params(id_document_upload: { verification_type: verification_type })
|
18
24
|
end
|
19
25
|
|
20
26
|
def create
|
@@ -47,6 +53,7 @@ module Decidim
|
|
47
53
|
@form = UploadForm.from_params(
|
48
54
|
params.merge(
|
49
55
|
user: current_user,
|
56
|
+
verification_type: verification_type,
|
50
57
|
verification_attachment: params[:id_document_upload][:verification_attachment] || @authorization.verification_attachment
|
51
58
|
)
|
52
59
|
)
|
@@ -78,6 +85,27 @@ module Decidim
|
|
78
85
|
name: "id_documents"
|
79
86
|
)
|
80
87
|
end
|
88
|
+
|
89
|
+
def verification_type
|
90
|
+
params[:using] || authorization_verification_type || available_methods.first
|
91
|
+
end
|
92
|
+
|
93
|
+
def authorization_verification_type
|
94
|
+
return unless @authorization
|
95
|
+
@authorization.verification_metadata["verification_type"]
|
96
|
+
end
|
97
|
+
|
98
|
+
def using_online?
|
99
|
+
verification_type == "online"
|
100
|
+
end
|
101
|
+
|
102
|
+
def using_offline?
|
103
|
+
verification_type == "offline"
|
104
|
+
end
|
105
|
+
|
106
|
+
def available_methods
|
107
|
+
@available_methods ||= current_organization.id_documents_methods
|
108
|
+
end
|
81
109
|
end
|
82
110
|
end
|
83
111
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Verifications
|
5
|
+
module Sms
|
6
|
+
class AuthorizationsController < ApplicationController
|
7
|
+
helper_method :authorization
|
8
|
+
|
9
|
+
before_action :load_authorization
|
10
|
+
|
11
|
+
def new
|
12
|
+
enforce_permission_to :create, :authorization, authorization: @authorization
|
13
|
+
|
14
|
+
@form = MobilePhoneForm.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def create
|
18
|
+
enforce_permission_to :create, :authorization, authorization: @authorization
|
19
|
+
|
20
|
+
@form = MobilePhoneForm.from_params(params.merge(user: current_user))
|
21
|
+
|
22
|
+
PerformAuthorizationStep.call(@authorization, @form) do
|
23
|
+
on(:ok) do
|
24
|
+
flash[:notice] = t("authorizations.create.success", scope: "decidim.verifications.sms")
|
25
|
+
authorization_method = Decidim::Verifications::Adapter.from_element(authorization.name)
|
26
|
+
redirect_to authorization_method.resume_authorization_path
|
27
|
+
end
|
28
|
+
on(:invalid) do
|
29
|
+
flash.now[:alert] = t("authorizations.create.error", scope: "decidim.verifications.sms")
|
30
|
+
render :new
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def edit
|
36
|
+
enforce_permission_to :update, :authorization, authorization: @authorization
|
37
|
+
|
38
|
+
@form = ConfirmationForm.from_params(params)
|
39
|
+
end
|
40
|
+
|
41
|
+
def update
|
42
|
+
enforce_permission_to :update, :authorization, authorization: @authorization
|
43
|
+
|
44
|
+
@form = ConfirmationForm.from_params(params)
|
45
|
+
|
46
|
+
ConfirmUserAuthorization.call(@authorization, @form) do
|
47
|
+
on(:ok) do
|
48
|
+
flash[:notice] = t("authorizations.update.success", scope: "decidim.verifications.sms")
|
49
|
+
redirect_to decidim_verifications.authorizations_path
|
50
|
+
end
|
51
|
+
|
52
|
+
on(:invalid) do
|
53
|
+
flash.now[:alert] = t("authorizations.update.error", scope: "decidim.verifications.sms")
|
54
|
+
render :edit
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
# rubocop:disable Naming/MemoizedInstanceVariableName
|
62
|
+
def authorization
|
63
|
+
@authorization_presenter ||= AuthorizationPresenter.new(@authorization)
|
64
|
+
end
|
65
|
+
# rubocop:enable Naming/MemoizedInstanceVariableName
|
66
|
+
|
67
|
+
def load_authorization
|
68
|
+
@authorization = Decidim::Authorization.find_or_initialize_by(
|
69
|
+
user: current_user,
|
70
|
+
name: "sms"
|
71
|
+
)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|