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
@@ -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>
|