decidim-verifications 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +101 -0
  3. data/Rakefile +3 -0
  4. data/app/commands/decidim/verifications/authorize_user.rb +61 -0
  5. data/app/commands/decidim/verifications/confirm_user_authorization.rb +49 -0
  6. data/app/commands/decidim/verifications/perform_authorization_step.rb +48 -0
  7. data/app/controllers/decidim/verifications/authorizations_controller.rb +91 -0
  8. data/app/controllers/decidim/verifications/id_documents/admin/confirmations_controller.rb +48 -0
  9. data/app/controllers/decidim/verifications/id_documents/admin/pending_authorizations_controller.rb +28 -0
  10. data/app/controllers/decidim/verifications/id_documents/admin/rejections_controller.rb +37 -0
  11. data/app/controllers/decidim/verifications/id_documents/authorizations_controller.rb +82 -0
  12. data/app/controllers/decidim/verifications/postal_letter/admin/pending_authorizations_controller.rb +27 -0
  13. data/app/controllers/decidim/verifications/postal_letter/admin/postages_controller.rb +41 -0
  14. data/app/controllers/decidim/verifications/postal_letter/authorizations_controller.rb +74 -0
  15. data/app/forms/decidim/verifications/id_documents/information_form.rb +50 -0
  16. data/app/forms/decidim/verifications/id_documents/information_rejection_form.rb +15 -0
  17. data/app/forms/decidim/verifications/id_documents/upload_form.rb +20 -0
  18. data/app/forms/decidim/verifications/postal_letter/address_form.rb +28 -0
  19. data/app/forms/decidim/verifications/postal_letter/confirmation_form.rb +19 -0
  20. data/app/forms/decidim/verifications/postal_letter/postage_form.rb +34 -0
  21. data/app/presenters/decidim/verifications/id_documents/authorization_presenter.rb +20 -0
  22. data/app/presenters/decidim/verifications/postal_letter/authorization_presenter.rb +59 -0
  23. data/app/queries/decidim/verifications/authorizations.rb +41 -0
  24. data/app/services/decidim/authorization_handler.rb +112 -0
  25. data/app/services/decidim/dummy_authorization_handler.rb +27 -0
  26. data/app/uploaders/decidim/verifications/attachment_uploader.rb +16 -0
  27. data/app/views/decidim/verifications/authorizations/first_login.html.erb +22 -0
  28. data/app/views/decidim/verifications/authorizations/index.html.erb +78 -0
  29. data/app/views/decidim/verifications/authorizations/new.html.erb +33 -0
  30. data/app/views/decidim/verifications/id_documents/admin/confirmations/new.html.erb +26 -0
  31. data/app/views/decidim/verifications/id_documents/admin/pending_authorizations/index.html.erb +32 -0
  32. data/app/views/decidim/verifications/id_documents/authorizations/edit.html.erb +53 -0
  33. data/app/views/decidim/verifications/id_documents/authorizations/new.html.erb +35 -0
  34. data/app/views/decidim/verifications/postal_letter/admin/pending_authorizations/index.html.erb +50 -0
  35. data/app/views/decidim/verifications/postal_letter/authorizations/edit.html.erb +37 -0
  36. data/app/views/decidim/verifications/postal_letter/authorizations/new.html.erb +27 -0
  37. data/config/locales/ca.yml +126 -0
  38. data/config/locales/en.yml +126 -0
  39. data/config/locales/es.yml +126 -0
  40. data/config/locales/eu.yml +125 -0
  41. data/config/locales/fi.yml +125 -0
  42. data/config/locales/fr.yml +125 -0
  43. data/config/locales/it.yml +125 -0
  44. data/config/locales/nl.yml +125 -0
  45. data/config/locales/pl.yml +125 -0
  46. data/config/locales/pt.yml +125 -0
  47. data/config/locales/ru.yml +5 -0
  48. data/config/locales/uk.yml +41 -0
  49. data/db/migrate/20171030133426_move_authorizations_to_new_api.rb +66 -0
  50. data/lib/decidim/verifications.rb +26 -0
  51. data/lib/decidim/verifications/adapter.rb +88 -0
  52. data/lib/decidim/verifications/dummy.rb +5 -0
  53. data/lib/decidim/verifications/engine.rb +24 -0
  54. data/lib/decidim/verifications/id_documents.rb +6 -0
  55. data/lib/decidim/verifications/id_documents/admin.rb +12 -0
  56. data/lib/decidim/verifications/id_documents/admin_engine.rb +21 -0
  57. data/lib/decidim/verifications/id_documents/engine.rb +18 -0
  58. data/lib/decidim/verifications/id_documents/workflow.rb +6 -0
  59. data/lib/decidim/verifications/postal_letter.rb +6 -0
  60. data/lib/decidim/verifications/postal_letter/admin.rb +12 -0
  61. data/lib/decidim/verifications/postal_letter/admin_engine.rb +21 -0
  62. data/lib/decidim/verifications/postal_letter/engine.rb +18 -0
  63. data/lib/decidim/verifications/postal_letter/workflow.rb +6 -0
  64. data/lib/decidim/verifications/registry.rb +39 -0
  65. data/lib/decidim/verifications/version.rb +10 -0
  66. data/lib/decidim/verifications/workflow_manifest.rb +56 -0
  67. data/lib/decidim/verifications/workflows.rb +58 -0
  68. 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,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/dev/common_rake"
@@ -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
@@ -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