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.
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
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Verifications
5
+ module PostalLetter
6
+ #
7
+ # Decorator for postal letter authorizations.
8
+ #
9
+ class AuthorizationPresenter < SimpleDelegator
10
+ def self.for_collection(authorizations)
11
+ authorizations.map { |authorization| new(authorization) }
12
+ end
13
+
14
+ #
15
+ # The address where the verification code will be sent
16
+ #
17
+ def verification_address
18
+ verification_metadata["address"]
19
+ end
20
+
21
+ #
22
+ # The verification code to be sent. It's kept in a different metadata
23
+ # key according to whether it has already been sent or not
24
+ #
25
+ def verification_code
26
+ if letter_sent?
27
+ verification_metadata["verification_code"]
28
+ else
29
+ verification_metadata["pending_verification_code"]
30
+ end
31
+ end
32
+
33
+ #
34
+ # Whether the letter with the verification code has already been sent or
35
+ # not
36
+ #
37
+ def letter_sent?
38
+ verification_metadata["verification_code"].present?
39
+ end
40
+
41
+ #
42
+ # Formatted time when the postal letter was sent. Or an informational
43
+ # string if not yet sent
44
+ #
45
+ def letter_sent_at
46
+ unless letter_sent?
47
+ return I18n.t("pending_authorizations.index.not_yet_sent",
48
+ scope: "decidim.verifications.postal_letter.admin")
49
+ end
50
+
51
+ I18n.l(
52
+ Time.zone.parse(verification_metadata["letter_sent_at"]),
53
+ format: :short
54
+ )
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Verifications
5
+ # Finds authorizations by different criteria
6
+ class Authorizations < Rectify::Query
7
+ # Initializes the class.
8
+ #
9
+ # @param name [String] The name of an authorization method
10
+ # @param user [User] A user to find authorizations for
11
+ # @param granted [Boolean] Whether the authorization is granted or not
12
+ def initialize(user: nil, name: nil, granted: nil)
13
+ @user = user
14
+ @name = name
15
+ @granted = granted
16
+ end
17
+
18
+ # Finds the Authorizations for the given method
19
+ #
20
+ # Returns an ActiveRecord::Relation.
21
+ def query
22
+ scope = Decidim::Authorization.where(nil)
23
+
24
+ scope = scope.where(name: name) unless name.nil?
25
+ scope = scope.where(user: user) unless user.nil?
26
+
27
+ if granted == true
28
+ scope = scope.where.not(granted_at: nil)
29
+ elsif granted == false
30
+ scope = scope.where(granted_at: nil)
31
+ end
32
+
33
+ scope
34
+ end
35
+
36
+ private
37
+
38
+ attr_reader :user, :name, :granted
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # This is the base class for authorization handlers, all implementations
5
+ # should inherit from it.
6
+ # Each AuthorizationHandler is a form that will be used to check if the
7
+ # authorization is valid or not. When it is valid a new authorization will
8
+ # be created for the user.
9
+ #
10
+ # Feel free to use validations to assert fields against a remote API,
11
+ # local database, or whatever.
12
+ #
13
+ # It also sets two default attributes, `user` and `handler_name`.
14
+ class AuthorizationHandler < Form
15
+ # The user that is trying to authorize, it's initialized with the
16
+ # `current_user` from the controller.
17
+ attribute :user, Decidim::User
18
+
19
+ # The String name of the handler, should not be modified since it's used to
20
+ # infer the class name of the authorization handler.
21
+ attribute :handler_name, String
22
+
23
+ # A unique ID to be implemented by the authorization handler that ensures
24
+ # no duplicates are created. This uniqueness check will be skipped if
25
+ # unique_id returns nil.
26
+ def unique_id
27
+ nil
28
+ end
29
+
30
+ # THe attributes of the handler that should be exposed as form input when
31
+ # rendering the handler in a form.
32
+ #
33
+ # Returns an Array of Strings.
34
+ def form_attributes
35
+ attributes.except(:id, :user).keys
36
+ end
37
+
38
+ # The String partial path so Rails can render the handler as a form. This
39
+ # is useful if you want to have a custom view to render the form instead of
40
+ # the default view.
41
+ #
42
+ # Example:
43
+ #
44
+ # A handler named Decidim::CensusHandler would look for its partial in:
45
+ # decidim/census/form
46
+ #
47
+ # Returns a String.
48
+ def to_partial_path
49
+ handler_name.sub!(/_handler$/, "") + "/form"
50
+ end
51
+
52
+ # Any data that the developer would like to inject to the `metadata` field
53
+ # of an authorization when it's created. Can be useful if some of the
54
+ # params the user sent with the authorization form want to be persisted for
55
+ # future use.
56
+ #
57
+ # Returns a Hash.
58
+ def metadata
59
+ {}
60
+ end
61
+
62
+ #
63
+ # Any data to be injected in the `verification_metadata` field of an
64
+ # authorization when it's created. This data will be used for multi-step
65
+ # verificaton workflows in order to confirm the authorization.
66
+ #
67
+ # Returns a Hash.
68
+ def verification_metadata
69
+ {}
70
+ end
71
+
72
+ #
73
+ # An optional attachment to help out with verification.
74
+ #
75
+ def verification_attachment
76
+ nil
77
+ end
78
+
79
+ # A serialized version of the handler's name.
80
+ #
81
+ # Returns a String.
82
+ def self.handler_name
83
+ name.demodulize.underscore
84
+ end
85
+
86
+ # Same as the class method but accessible from the instance.
87
+ #
88
+ # Returns a String.
89
+ def handler_name
90
+ self.class.handler_name
91
+ end
92
+
93
+ # Finds a handler class from a String. This is necessary when processing
94
+ # the form data. It will only look for valid handlers that have also been
95
+ # configured in `Decidim.authorization_handlers`.
96
+ #
97
+ # name - The String name of the class to find, usually in the same shape as
98
+ # the one returned by `handler_name`.
99
+ # params - An optional Hash with params to initialize the handler.
100
+ #
101
+ # Returns an AuthorizationHandler descendant.
102
+ # Returns nil when no handlers could be found.
103
+ def self.handler_for(name, params = {})
104
+ return unless name
105
+
106
+ manifest = Decidim.authorization_handlers.find { |m| m.name == name }
107
+ return unless manifest
108
+
109
+ manifest.form.constantize.from_params(params || {})
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # An example implementation of an AuthorizationHandler to be used in tests.
5
+ class DummyAuthorizationHandler < AuthorizationHandler
6
+ attribute :document_number, String
7
+ attribute :postal_code, String
8
+ attribute :birthday, Date
9
+
10
+ validates :document_number, presence: true
11
+ validate :valid_document_number
12
+
13
+ def metadata
14
+ super.merge(document_number: document_number)
15
+ end
16
+
17
+ def unique_id
18
+ document_number
19
+ end
20
+
21
+ private
22
+
23
+ def valid_document_number
24
+ errors.add(:document_number, :invalid) unless document_number.to_s.end_with?("X")
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Verifications
5
+ # This class deals with uploading identity documents.
6
+ class AttachmentUploader < ImageUploader
7
+ version :thumbnail do
8
+ process resize_to_limit: [90, nil]
9
+ end
10
+
11
+ version :big do
12
+ process resize_to_limit: [600, nil]
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ <main class="wrapper">
2
+ <div class="row collapse">
3
+ <div class="row collapse">
4
+ <div class="columns large-8 large-centered text-center">
5
+ <h1 class="heading1 page-title"><%= t(".title") %></h1>
6
+ <p class="heading5"><%= t(".verify_with_these_options") %></p>
7
+ </div>
8
+ </div>
9
+ <div class="row">
10
+ <div class="columns medium-7 large-5 medium-centered">
11
+ <div class="card">
12
+ <div class="card__content">
13
+ <% unauthorized_methods.each do |unauthorized_method| %>
14
+ <%= link_to t(".actions.#{unauthorized_method.key}"), unauthorized_method.root_path, class: "button expanded" %>
15
+ <% end %>
16
+ <p class="text-center skip"><%= t("decidim.verifications.authorizations.skip_verification", link: link_to(t("decidim.verifications.authorizations.start_exploring"), cta_button_path).html_safe).html_safe %>.</p>
17
+ </div>
18
+ </div>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ </main>
@@ -0,0 +1,78 @@
1
+ <div class="row column authorizations-list">
2
+ <section class="section">
3
+ <% if @granted_authorizations.any? %>
4
+ <div class="card card--list">
5
+ <% @granted_authorizations.each do |authorization| %>
6
+ <div class="card--list__item">
7
+ <div class="card--list__text">
8
+ <%= icon "lock-unlocked", class: "card--list__icon" %>
9
+ <div>
10
+ <h5 class="card--list__heading">
11
+ <%= t("#{authorization.name}.name", scope: "decidim.authorization_handlers") %>
12
+ </h5>
13
+ <span class="text-small">
14
+ <%= t("granted_at", scope: "decidim.authorization_handlers", timestamp: l(authorization.granted_at, format: :long)) %>
15
+ </span>
16
+ </div>
17
+ </div>
18
+ </div>
19
+ <% end %>
20
+ </div>
21
+ <% end %>
22
+
23
+ <% if @pending_authorizations.any? %>
24
+ <div class="card card--list">
25
+ <% @pending_authorizations.each do |authorization| %>
26
+ <% authorization_method = Decidim::Verifications::Adapter.from_element(authorization.name) %>
27
+ <%= link_to authorization_method.resume_authorization_path do %>
28
+ <div class="card--list__item">
29
+ <div class="card--list__text">
30
+ <%= icon "reload", class: "card--list__icon" %>
31
+ <div>
32
+ <h5 class="card--list__heading">
33
+ <%= t("#{authorization.name}.name", scope: "decidim.authorization_handlers") %>
34
+ </h5>
35
+ <span class="text-small">
36
+ <%= t("started_at", scope: "decidim.authorization_handlers", timestamp: l(authorization.updated_at, format: :long)) %>
37
+ </span>
38
+ </div>
39
+ </div>
40
+ <div class="card--list__data">
41
+ <span class="card--list__data__icon">
42
+ <%= icon "chevron-right" %>
43
+ </span>
44
+ </div>
45
+ </div>
46
+ <% end %>
47
+ <% end %>
48
+ </div>
49
+ <% end %>
50
+
51
+ <% if unauthorized_methods.any? %>
52
+ <div class="card card--list">
53
+ <% unauthorized_methods.each do |unauthorized_method| %>
54
+ <%= link_to unauthorized_method.root_path do %>
55
+ <div class="card--list__item">
56
+ <div class="card--list__text">
57
+ <%= icon "lock-locked", class: "card--list__icon" %>
58
+ <div>
59
+ <h5 class="card--list__heading">
60
+ <%= t("#{unauthorized_method.key}.name", scope: "decidim.authorization_handlers") %>
61
+ </h5>
62
+ <span class="text-small">
63
+ <%= t("#{unauthorized_method.key}.explanation", scope: "decidim.authorization_handlers") %>
64
+ </span>
65
+ </div>
66
+ </div>
67
+ <div class="card--list__data">
68
+ <span class="card--list__data__icon">
69
+ <%= icon "chevron-right" %>
70
+ </span>
71
+ </div>
72
+ </div>
73
+ <% end %>
74
+ <% end %>
75
+ </div>
76
+ <% end %>
77
+ </section>
78
+ </div>
@@ -0,0 +1,33 @@
1
+ <main class="wrapper">
2
+ <div class="row collapse">
3
+ <div class="row collapse">
4
+ <div class="columns large-8 large-centered text-center page-title">
5
+ <h1><%= t(".authorize_with", authorizer: t("#{params[:handler]}.name", scope: "decidim.authorization_handlers")) %></h1>
6
+ </div>
7
+ </div>
8
+
9
+ <div class="row">
10
+ <div class="columns large-6 medium-centered">
11
+ <div class="card">
12
+ <div class="card__content">
13
+ <%= authorization_form_for(handler, url: authorizations_path(redirect_url: params[:redirect_url])) do |form| %>
14
+ <%= form.error_for(:base) %>
15
+
16
+ <% if lookup_context.exists?(handler.to_partial_path, [], true) %>
17
+ <%= render partial: handler.to_partial_path, locals: { handler: handler, form: form } %>
18
+ <% else %>
19
+ <%= form.all_fields %>
20
+ <div class="actions">
21
+ <%= form.submit t(".authorize"), class: "button expanded" %>
22
+ </div>
23
+ <% end %>
24
+ <% end %>
25
+ <p class="text-center skip">
26
+ <%= t("decidim.verifications.authorizations.skip_verification", link: link_to(t("decidim.verifications.authorizations.start_exploring"), cta_button_path).html_safe).html_safe %>.
27
+ </p>
28
+ </div>
29
+ </div>
30
+ </div>
31
+ </div>
32
+ </div>
33
+ </main>
@@ -0,0 +1,26 @@
1
+ <%= decidim_form_for(@form, url: pending_authorization_confirmation_path(@pending_authorization),
2
+ html: { class: "form" }) do |form| %>
3
+ <div class="card">
4
+ <div class="card-divider">
5
+ <h2 class="card-title">
6
+ <%= t(".introduce_user_data") %>
7
+ <%= link_to t(".reject"), pending_authorization_rejection_path(@pending_authorization), method: :post, class: "button alert tiny button--title destroy" %>
8
+ </h2>
9
+ </div>
10
+
11
+ <div class="card-section">
12
+ <div class="row column">
13
+ <%= image_tag @pending_authorization.verification_attachment.url(:big), class: "thumbnail" %>
14
+ </div>
15
+
16
+ <div class="row column">
17
+ <%= form.select :document_type, @form.document_types_for_select, prompt: true, selected: nil %>
18
+ <%= form.text_field :document_number, value: nil %>
19
+ </div>
20
+ </div>
21
+ </div>
22
+
23
+ <div class="button--double form-general-submit">
24
+ <%= form.submit t(".verify") %>
25
+ </div>
26
+ <% end %>
@@ -0,0 +1,32 @@
1
+ <div class="card">
2
+ <div class="card-divider">
3
+ <h2 class="card-title">
4
+ <%= t(".title") %>
5
+ </h2>
6
+ </div>
7
+ <div class="card-section">
8
+ <table class="table-list">
9
+ <thead>
10
+ <tr>
11
+ <th><%= t("activemodel.attributes.id") %></th>
12
+ <th><%= t("activemodel.attributes.id_document_upload.verification_attachment") %></th>
13
+ </tr>
14
+ </thead>
15
+ <tbody>
16
+ <tr>
17
+ <% @pending_authorizations.each do |authorization| %>
18
+ <td>
19
+ <%= link_to t(".verification_number", n: authorization.id),
20
+ new_pending_authorization_confirmation_path(authorization.id) %>
21
+ </td>
22
+ <td>
23
+ <%= link_to new_pending_authorization_confirmation_path(authorization.id) do %>
24
+ <%= image_tag authorization.verification_attachment.url(:thumbnail), class: "thumbnail-list" %>
25
+ <% end %>
26
+ </td>
27
+ <% end %>
28
+ </tr>
29
+ </tbody>
30
+ </table>
31
+ </div>
32
+ </div>