decidim-verifications 0.8.0
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 +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
|