decidim-verifications 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +101 -0
- data/Rakefile +3 -0
- data/app/commands/decidim/verifications/authorize_user.rb +61 -0
- data/app/commands/decidim/verifications/confirm_user_authorization.rb +49 -0
- data/app/commands/decidim/verifications/perform_authorization_step.rb +48 -0
- data/app/controllers/decidim/verifications/authorizations_controller.rb +91 -0
- data/app/controllers/decidim/verifications/id_documents/admin/confirmations_controller.rb +48 -0
- data/app/controllers/decidim/verifications/id_documents/admin/pending_authorizations_controller.rb +28 -0
- data/app/controllers/decidim/verifications/id_documents/admin/rejections_controller.rb +37 -0
- data/app/controllers/decidim/verifications/id_documents/authorizations_controller.rb +82 -0
- data/app/controllers/decidim/verifications/postal_letter/admin/pending_authorizations_controller.rb +27 -0
- data/app/controllers/decidim/verifications/postal_letter/admin/postages_controller.rb +41 -0
- data/app/controllers/decidim/verifications/postal_letter/authorizations_controller.rb +74 -0
- data/app/forms/decidim/verifications/id_documents/information_form.rb +50 -0
- data/app/forms/decidim/verifications/id_documents/information_rejection_form.rb +15 -0
- data/app/forms/decidim/verifications/id_documents/upload_form.rb +20 -0
- data/app/forms/decidim/verifications/postal_letter/address_form.rb +28 -0
- data/app/forms/decidim/verifications/postal_letter/confirmation_form.rb +19 -0
- data/app/forms/decidim/verifications/postal_letter/postage_form.rb +34 -0
- data/app/presenters/decidim/verifications/id_documents/authorization_presenter.rb +20 -0
- data/app/presenters/decidim/verifications/postal_letter/authorization_presenter.rb +59 -0
- data/app/queries/decidim/verifications/authorizations.rb +41 -0
- data/app/services/decidim/authorization_handler.rb +112 -0
- data/app/services/decidim/dummy_authorization_handler.rb +27 -0
- data/app/uploaders/decidim/verifications/attachment_uploader.rb +16 -0
- data/app/views/decidim/verifications/authorizations/first_login.html.erb +22 -0
- data/app/views/decidim/verifications/authorizations/index.html.erb +78 -0
- data/app/views/decidim/verifications/authorizations/new.html.erb +33 -0
- data/app/views/decidim/verifications/id_documents/admin/confirmations/new.html.erb +26 -0
- data/app/views/decidim/verifications/id_documents/admin/pending_authorizations/index.html.erb +32 -0
- data/app/views/decidim/verifications/id_documents/authorizations/edit.html.erb +53 -0
- data/app/views/decidim/verifications/id_documents/authorizations/new.html.erb +35 -0
- data/app/views/decidim/verifications/postal_letter/admin/pending_authorizations/index.html.erb +50 -0
- data/app/views/decidim/verifications/postal_letter/authorizations/edit.html.erb +37 -0
- data/app/views/decidim/verifications/postal_letter/authorizations/new.html.erb +27 -0
- data/config/locales/ca.yml +126 -0
- data/config/locales/en.yml +126 -0
- data/config/locales/es.yml +126 -0
- data/config/locales/eu.yml +125 -0
- data/config/locales/fi.yml +125 -0
- data/config/locales/fr.yml +125 -0
- data/config/locales/it.yml +125 -0
- data/config/locales/nl.yml +125 -0
- data/config/locales/pl.yml +125 -0
- data/config/locales/pt.yml +125 -0
- data/config/locales/ru.yml +5 -0
- data/config/locales/uk.yml +41 -0
- data/db/migrate/20171030133426_move_authorizations_to_new_api.rb +66 -0
- data/lib/decidim/verifications.rb +26 -0
- data/lib/decidim/verifications/adapter.rb +88 -0
- data/lib/decidim/verifications/dummy.rb +5 -0
- data/lib/decidim/verifications/engine.rb +24 -0
- data/lib/decidim/verifications/id_documents.rb +6 -0
- data/lib/decidim/verifications/id_documents/admin.rb +12 -0
- data/lib/decidim/verifications/id_documents/admin_engine.rb +21 -0
- data/lib/decidim/verifications/id_documents/engine.rb +18 -0
- data/lib/decidim/verifications/id_documents/workflow.rb +6 -0
- data/lib/decidim/verifications/postal_letter.rb +6 -0
- data/lib/decidim/verifications/postal_letter/admin.rb +12 -0
- data/lib/decidim/verifications/postal_letter/admin_engine.rb +21 -0
- data/lib/decidim/verifications/postal_letter/engine.rb +18 -0
- data/lib/decidim/verifications/postal_letter/workflow.rb +6 -0
- data/lib/decidim/verifications/registry.rb +39 -0
- data/lib/decidim/verifications/version.rb +10 -0
- data/lib/decidim/verifications/workflow_manifest.rb +56 -0
- data/lib/decidim/verifications/workflows.rb +58 -0
- metadata +152 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0bcafbf13f475478c5f7f53c1c4c5493926dc09f
|
4
|
+
data.tar.gz: 86d57eecdd80590628847fcfe9d56139cc9114ad
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 19c99dd7f94b58209f0c2f7bf0a31449c739c2f555992237f9226c2bdf17703c5b58a59c1982c40237b564483b37396cb587bbee453b64e0fb99e7bef5cfce4e
|
7
|
+
data.tar.gz: f799da0090c4168632ef49a25ef6c29abf2efe6c7101895c1f4320a5ebbe00a49a41fa387ac7361d98dac4782d455cd6f851fbb0a17edd791a629cba412f9a8d
|
data/README.md
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# Decidim::Verifications
|
2
|
+
|
3
|
+
Decidim offers several methods for allowing participants to get authorization to
|
4
|
+
perform certain privileged actions. This gem implements several of those methods
|
5
|
+
and also offers a way for installation to implement their custom verification
|
6
|
+
methods.
|
7
|
+
|
8
|
+
## Introduction
|
9
|
+
|
10
|
+
Each decidim instance is in full control of its authorizations, and can customize:
|
11
|
+
|
12
|
+
* The different methods to be used by users to get verified. For example,
|
13
|
+
through a census, by uploading their identity documents, or by receiving a
|
14
|
+
verification home at their address.
|
15
|
+
|
16
|
+
* The different actions in decidim that require authorization, and which
|
17
|
+
authorization method they require. For example, a decidim instance might
|
18
|
+
choose to require census authorization to create proposals, but a fully
|
19
|
+
verified address via a verification code sent by postal mail for voting on
|
20
|
+
proposals.
|
21
|
+
|
22
|
+
## Types of authorization methods
|
23
|
+
|
24
|
+
Decidim implements two type of authorization methods:
|
25
|
+
|
26
|
+
* _Form authorizations_.
|
27
|
+
|
28
|
+
When your verification method is simple enough, you can use a `Rectify::Form`
|
29
|
+
to implement it. "Simple" here means that the authorization can be granted
|
30
|
+
with the submission of a single form. For example, to validate a user against
|
31
|
+
a census API you will need a form with some fields that your users will use to
|
32
|
+
authenticate against a census (for example, an ID and a Postal Code). You'll
|
33
|
+
implement this with a form class. See the documentation for the [parent
|
34
|
+
class][authorization handler base class] or have a look at a
|
35
|
+
[live example][live authorization handler example] in decidim-barcelona.
|
36
|
+
|
37
|
+
To register your handler, use
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
# config/initializers/decidim.rb
|
41
|
+
|
42
|
+
Decidim::Verifications.register_workflow(:census) do |workflow|
|
43
|
+
workflow.form = "<myAuthorizationHandlerClass"
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
* _Workflow authorizations_.
|
48
|
+
|
49
|
+
For more complex scenarios requiring several steps or admin intervention, you
|
50
|
+
can register a verification flow.
|
51
|
+
|
52
|
+
For example:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
# config/initializers/decidim.rb
|
56
|
+
|
57
|
+
Decidim::Verifications.register_workflow(:sms_verification) do |workflow|
|
58
|
+
workflow.engine = Decidim::Verifications::SmsVerification::Engine
|
59
|
+
workflow.admin_engine = Decidim::Verifications::SmsVerification::AdminEngine
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
Inside these engines, you can implement any steps required for the
|
64
|
+
authorization to succeed, via one or more custom controllers and views. You
|
65
|
+
can create partial `Authorization` records (with the `verified_at` column set
|
66
|
+
to `nil`) and hold partial verification data in the `verification_metadata`
|
67
|
+
column, or even a partial verification attachment in the
|
68
|
+
`verification_attachment` column.
|
69
|
+
|
70
|
+
Decidim currently requires that your main engine defines two routes:
|
71
|
+
|
72
|
+
* `new_authorization_path`: This is the entry point to start the authorization
|
73
|
+
process.
|
74
|
+
|
75
|
+
* `edit_authorization_path`: This is the entry point to resume an existing
|
76
|
+
authorization process.
|
77
|
+
|
78
|
+
## Installation
|
79
|
+
|
80
|
+
Add this line to your application's Gemfile:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
gem 'decidim-verifications'
|
84
|
+
```
|
85
|
+
|
86
|
+
And then execute:
|
87
|
+
|
88
|
+
```bash
|
89
|
+
bundle
|
90
|
+
```
|
91
|
+
|
92
|
+
## Contributing
|
93
|
+
|
94
|
+
See [Decidim](https://github.com/decidim/decidim).
|
95
|
+
|
96
|
+
## License
|
97
|
+
|
98
|
+
See [Decidim](https://github.com/decidim/decidim).
|
99
|
+
|
100
|
+
[authorization handler base class]: https://github.com/decidim/decidim/blob/master/decidim-core/app/services/decidim/authorization_handler.rb
|
101
|
+
[real authorization handler]: https://github.com/decidim/decidim-barcelona/blob/master/app/services/census_authorization_handler.rb
|
data/Rakefile
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Verifications
|
5
|
+
# A command to authorize a user with an authorization handler.
|
6
|
+
class AuthorizeUser < Rectify::Command
|
7
|
+
# Public: Initializes the command.
|
8
|
+
#
|
9
|
+
# handler - An AuthorizationHandler object.
|
10
|
+
def initialize(handler)
|
11
|
+
@handler = handler
|
12
|
+
end
|
13
|
+
|
14
|
+
# Executes the command. Broadcasts these events:
|
15
|
+
#
|
16
|
+
# - :ok when everything is valid.
|
17
|
+
# - :invalid if the handler wasn't valid and we couldn't proceed.
|
18
|
+
#
|
19
|
+
# Returns nothing.
|
20
|
+
def call
|
21
|
+
return broadcast(:invalid) unless handler.valid? && unique?
|
22
|
+
|
23
|
+
create_authorization
|
24
|
+
broadcast(:ok)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :handler
|
30
|
+
|
31
|
+
def create_authorization
|
32
|
+
authorization = Authorization.find_or_initialize_by(
|
33
|
+
user: handler.user,
|
34
|
+
name: handler.handler_name
|
35
|
+
)
|
36
|
+
|
37
|
+
authorization.attributes = {
|
38
|
+
unique_id: handler.unique_id,
|
39
|
+
metadata: handler.metadata
|
40
|
+
}
|
41
|
+
|
42
|
+
authorization.grant!
|
43
|
+
end
|
44
|
+
|
45
|
+
def unique?
|
46
|
+
return true if handler.unique_id.nil?
|
47
|
+
|
48
|
+
duplicates = Authorization.where(
|
49
|
+
user: User.where.not(id: handler.user.id).where(organization: handler.user.organization.id),
|
50
|
+
name: handler.handler_name,
|
51
|
+
unique_id: handler.unique_id
|
52
|
+
)
|
53
|
+
|
54
|
+
return true unless duplicates.any?
|
55
|
+
|
56
|
+
handler.errors.add(:base, I18n.t("decidim.authorization_handlers.errors.duplicate_authorization"))
|
57
|
+
false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Verifications
|
5
|
+
# A command to confirm a previous partial authorization.
|
6
|
+
class ConfirmUserAuthorization < Rectify::Command
|
7
|
+
# Public: Initializes the command.
|
8
|
+
#
|
9
|
+
# authorization - An Authorization to be confirmed.
|
10
|
+
# form - A form object with the verification data to confirm it.
|
11
|
+
def initialize(authorization, form)
|
12
|
+
@authorization = authorization
|
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(:already_confirmed) if authorization.granted?
|
24
|
+
|
25
|
+
return broadcast(:invalid) unless form.valid?
|
26
|
+
|
27
|
+
if confirmation_successful?
|
28
|
+
authorization.grant!
|
29
|
+
|
30
|
+
broadcast(:ok)
|
31
|
+
else
|
32
|
+
broadcast(:invalid)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def confirmation_successful?
|
39
|
+
form.verification_metadata.all? do |key, value|
|
40
|
+
authorization.verification_metadata[key] == value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
attr_reader :authorization, :form
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Verifications
|
5
|
+
# A command to create a partial authorization for a user.
|
6
|
+
class PerformAuthorizationStep < Rectify::Command
|
7
|
+
# Public: Initializes the command.
|
8
|
+
#
|
9
|
+
# authorization - An Authorization object.
|
10
|
+
# handler - An AuthorizationHandler object.
|
11
|
+
def initialize(authorization, handler)
|
12
|
+
@authorization = authorization
|
13
|
+
@handler = handler
|
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 handler.valid?
|
24
|
+
|
25
|
+
update_verification_data
|
26
|
+
|
27
|
+
broadcast(:ok)
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def update_verification_data
|
33
|
+
authorization.attributes = {
|
34
|
+
unique_id: handler.unique_id,
|
35
|
+
metadata: handler.metadata,
|
36
|
+
verification_metadata: handler.verification_metadata,
|
37
|
+
verification_attachment: handler.verification_attachment
|
38
|
+
}
|
39
|
+
|
40
|
+
authorization.save!
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
attr_reader :authorization, :handler
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Verifications
|
5
|
+
# This controller allows users to create and destroy their authorizations. It
|
6
|
+
# shouldn't be necessary to expand it to add new authorization schemes.
|
7
|
+
class AuthorizationsController < Decidim::ApplicationController
|
8
|
+
helper_method :handler, :unauthorized_methods
|
9
|
+
before_action :valid_handler, only: [:new, :create]
|
10
|
+
|
11
|
+
include Decidim::UserProfile
|
12
|
+
helper Decidim::DecidimFormHelper
|
13
|
+
helper Decidim::CtaButtonHelper
|
14
|
+
helper Decidim::AuthorizationFormHelper
|
15
|
+
|
16
|
+
layout "layouts/decidim/user_profile", only: [:index]
|
17
|
+
|
18
|
+
def new; end
|
19
|
+
|
20
|
+
def index
|
21
|
+
@granted_authorizations = granted_authorizations
|
22
|
+
@pending_authorizations = pending_authorizations
|
23
|
+
end
|
24
|
+
|
25
|
+
def first_login
|
26
|
+
if unauthorized_methods.length == 1
|
27
|
+
redirect_to(
|
28
|
+
action: :new,
|
29
|
+
handler: unauthorized_methods.first.name,
|
30
|
+
redirect_url: decidim.account_path
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def create
|
36
|
+
AuthorizeUser.call(handler) do
|
37
|
+
on(:ok) do
|
38
|
+
flash[:notice] = t("authorizations.create.success", scope: "decidim.verifications")
|
39
|
+
redirect_to params[:redirect_url] || authorizations_path
|
40
|
+
end
|
41
|
+
|
42
|
+
on(:invalid) do
|
43
|
+
flash[:alert] = t("authorizations.create.error", scope: "decidim.verifications")
|
44
|
+
render action: :new
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
protected
|
50
|
+
|
51
|
+
def handler
|
52
|
+
@handler ||= Decidim::AuthorizationHandler.handler_for(handler_name, handler_params)
|
53
|
+
end
|
54
|
+
|
55
|
+
def handler_params
|
56
|
+
(params[:authorization_handler] || {}).merge(user: current_user)
|
57
|
+
end
|
58
|
+
|
59
|
+
def handler_name
|
60
|
+
params[:handler] || params.dig(:authorization_handler, :handler_name)
|
61
|
+
end
|
62
|
+
|
63
|
+
def valid_handler
|
64
|
+
return true if handler
|
65
|
+
|
66
|
+
logger.warn "Invalid authorization handler given: #{handler_name} doesn't"\
|
67
|
+
"exist or you haven't added it to `Decidim.authorization_handlers`"
|
68
|
+
|
69
|
+
redirect_to(authorizations_path) && (return false)
|
70
|
+
end
|
71
|
+
|
72
|
+
def unauthorized_methods
|
73
|
+
@unauthorized_methods ||= available_verification_workflows.reject do |handler|
|
74
|
+
active_authorization_methods.include?(handler.key)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def active_authorization_methods
|
79
|
+
Authorizations.new(user: current_user).pluck(:name)
|
80
|
+
end
|
81
|
+
|
82
|
+
def granted_authorizations
|
83
|
+
Authorizations.new(user: current_user, granted: true)
|
84
|
+
end
|
85
|
+
|
86
|
+
def pending_authorizations
|
87
|
+
Authorizations.new(user: current_user, granted: false)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Verifications
|
5
|
+
module IdDocuments
|
6
|
+
module Admin
|
7
|
+
#
|
8
|
+
# Handles confirmations for verification by identity document upload.
|
9
|
+
#
|
10
|
+
class ConfirmationsController < Decidim::Admin::ApplicationController
|
11
|
+
layout "decidim/admin/users"
|
12
|
+
|
13
|
+
before_action :load_pending_authorization
|
14
|
+
|
15
|
+
def new
|
16
|
+
authorize! :update, @pending_authorization
|
17
|
+
|
18
|
+
@form = InformationForm.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def create
|
22
|
+
authorize! :update, @pending_authorization
|
23
|
+
|
24
|
+
@form = InformationForm.from_params(params)
|
25
|
+
|
26
|
+
ConfirmUserAuthorization.call(@pending_authorization, @form) do
|
27
|
+
on(:ok) do
|
28
|
+
flash[:notice] = t("confirmations.create.success", scope: "decidim.verifications.id_documents.admin")
|
29
|
+
redirect_to pending_authorizations_path
|
30
|
+
end
|
31
|
+
|
32
|
+
on(:invalid) do
|
33
|
+
flash.now[:alert] = t("confirmations.create.error", scope: "decidim.verifications.id_documents.admin")
|
34
|
+
render action: :new
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def load_pending_authorization
|
42
|
+
@pending_authorization = Authorization.find(params[:pending_authorization_id])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/app/controllers/decidim/verifications/id_documents/admin/pending_authorizations_controller.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Verifications
|
5
|
+
module IdDocuments
|
6
|
+
module Admin
|
7
|
+
class PendingAuthorizationsController < Decidim::Admin::ApplicationController
|
8
|
+
layout "decidim/admin/users"
|
9
|
+
|
10
|
+
def index
|
11
|
+
authorize! :index, Authorization
|
12
|
+
|
13
|
+
@pending_authorizations = pending_authorizations
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def pending_authorizations
|
19
|
+
Authorizations
|
20
|
+
.new(name: "id_documents", granted: false)
|
21
|
+
.query
|
22
|
+
.where("verification_metadata->'rejected' IS NULL")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|