decidim-access_requests 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE-AGPLv3.txt +661 -0
- data/README.md +105 -0
- data/Rakefile +17 -0
- data/app/assets/config/decidim_access_requests_manifest.css +3 -0
- data/app/assets/stylesheets/decidim/access_requests/verification.scss +4 -0
- data/app/assets/stylesheets/decidim/access_requests/verification/_step-bullets.scss +30 -0
- data/app/assets/stylesheets/decidim/access_requests/verification/_variables.scss +2 -0
- data/app/commands/decidim/access_requests/verification/admin/confirm_user_access_request.rb +67 -0
- data/app/commands/decidim/access_requests/verification/admin/destroy_authorization.rb +40 -0
- data/app/controllers/concerns/decidim/access_requests/verification/detectable_verification_manifest.rb +23 -0
- data/app/controllers/decidim/access_requests/verification/admin/granted_authorizations_controller.rb +117 -0
- data/app/controllers/decidim/access_requests/verification/admin/pending_authorizations_controller.rb +76 -0
- data/app/controllers/decidim/access_requests/verification/authorizations_controller.rb +68 -0
- data/app/events/decidim/access_requests/access_request_confirmed_event.rb +31 -0
- data/app/forms/decidim/access_requests/verification/request_form.rb +25 -0
- data/app/presenters/decidim/access_requests/verification/authorization_presenter.rb +16 -0
- data/app/views/decidim/access_requests/verification/admin/granted_authorizations/index.html.erb +44 -0
- data/app/views/decidim/access_requests/verification/admin/granted_authorizations/new.html.erb +52 -0
- data/app/views/decidim/access_requests/verification/admin/pending_authorizations/index.html.erb +48 -0
- data/app/views/decidim/access_requests/verification/authorizations/_steps.html.erb +40 -0
- data/app/views/decidim/access_requests/verification/authorizations/edit.html.erb +13 -0
- data/app/views/decidim/access_requests/verification/authorizations/new.html.erb +25 -0
- data/config/locales/en.yml +70 -0
- data/config/locales/fi.yml +68 -0
- data/config/locales/sv.yml +70 -0
- data/lib/decidim/access_requests.rb +9 -0
- data/lib/decidim/access_requests/verification.rb +5 -0
- data/lib/decidim/access_requests/verification/admin.rb +12 -0
- data/lib/decidim/access_requests/verification/admin_engine.rb +21 -0
- data/lib/decidim/access_requests/verification/engine.rb +24 -0
- data/lib/decidim/access_requests/version.rb +8 -0
- metadata +132 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module AccessRequests
|
5
|
+
module Verification
|
6
|
+
class AuthorizationsController < Decidim::ApplicationController
|
7
|
+
helper_method :authorization
|
8
|
+
|
9
|
+
before_action :load_authorization
|
10
|
+
|
11
|
+
def new
|
12
|
+
enforce_permission_to :create, :authorization, authorization: @authorization
|
13
|
+
|
14
|
+
@form = RequestForm.new(handler_handle: authorization_handle)
|
15
|
+
end
|
16
|
+
|
17
|
+
def create
|
18
|
+
enforce_permission_to :create, :authorization, authorization: @authorization
|
19
|
+
|
20
|
+
@form = RequestForm.from_params(
|
21
|
+
params.merge(user: current_user)
|
22
|
+
).with_context(current_organization: current_organization)
|
23
|
+
|
24
|
+
Decidim::Verifications::PerformAuthorizationStep.call(@authorization, @form) do
|
25
|
+
on(:ok) do
|
26
|
+
flash[:notice] = t("authorizations.create.success", scope: "decidim.access_requests.verification")
|
27
|
+
redirect_to decidim_verifications.authorizations_path
|
28
|
+
end
|
29
|
+
|
30
|
+
on(:invalid) do
|
31
|
+
flash.now[:alert] = t("authorizations.create.error", scope: "decidim.access_requests.verification")
|
32
|
+
render :new
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def edit
|
38
|
+
enforce_permission_to :create, :authorization, authorization: @authorization
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# rubocop:disable Naming/MemoizedInstanceVariableName
|
44
|
+
def authorization
|
45
|
+
@authorization_presenter ||= AuthorizationPresenter.new(@authorization)
|
46
|
+
end
|
47
|
+
# rubocop:enable Naming/MemoizedInstanceVariableName
|
48
|
+
|
49
|
+
def load_authorization
|
50
|
+
@authorization = Decidim::Authorization.find_or_initialize_by(
|
51
|
+
user: current_user,
|
52
|
+
name: authorization_handle
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
def authorization_handle
|
57
|
+
# In case the form is posted, the authorization handle is not
|
58
|
+
# available from the request path.
|
59
|
+
tmpform = RequestForm.from_params(params)
|
60
|
+
return tmpform.handler_name unless tmpform.handler_name.nil?
|
61
|
+
|
62
|
+
# Determine the handle from the request path
|
63
|
+
request.path.split("/").last
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen-string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module AccessRequests
|
5
|
+
class AccessRequestConfirmedEvent < Decidim::Events::SimpleEvent
|
6
|
+
delegate :url_helpers, to: "Decidim::Core::Engine.routes"
|
7
|
+
|
8
|
+
i18n_attributes :verification_name
|
9
|
+
|
10
|
+
def resource_url
|
11
|
+
url_helpers.profile_url(
|
12
|
+
user_nickname,
|
13
|
+
host: user.organization.host
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
def resource_path
|
18
|
+
url_helpers.profile_path(user_nickname)
|
19
|
+
end
|
20
|
+
|
21
|
+
def verification_name
|
22
|
+
handler_name = extra.dig("handler_name")
|
23
|
+
I18n.t("#{handler_name}.name", scope: "decidim.authorization_handlers")
|
24
|
+
end
|
25
|
+
|
26
|
+
def user_nickname
|
27
|
+
extra.dig("user_nickname")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module AccessRequests
|
5
|
+
module Verification
|
6
|
+
# A form object to be used when public users want to get verified by
|
7
|
+
# access requests.
|
8
|
+
class RequestForm < AuthorizationHandler
|
9
|
+
attribute :handler_handle, String
|
10
|
+
|
11
|
+
validates :handler_handle,
|
12
|
+
presence: true,
|
13
|
+
inclusion: {
|
14
|
+
in: proc { |form|
|
15
|
+
form.current_organization.available_authorizations
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
def handler_name
|
20
|
+
handler_handle
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module AccessRequests
|
5
|
+
module Verification
|
6
|
+
#
|
7
|
+
# Decorator for access request authorizations.
|
8
|
+
#
|
9
|
+
class AuthorizationPresenter < SimpleDelegator
|
10
|
+
def self.for_collection(authorizations)
|
11
|
+
authorizations.map { |authorization| new(authorization) }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/app/views/decidim/access_requests/verification/admin/granted_authorizations/index.html.erb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
<div class="card">
|
2
|
+
<div class="card-divider">
|
3
|
+
<h2 class="card-title">
|
4
|
+
<%= t(".title") %>
|
5
|
+
<%= link_to t(".pending_authorizations"), pending_authorizations_path, class: "button tiny button--title" %>
|
6
|
+
<%= link_to t(".new"), new_granted_authorization_path, class: "button tiny button--title" %>
|
7
|
+
</h2>
|
8
|
+
</div>
|
9
|
+
<div class="card-section">
|
10
|
+
<table class="table-list">
|
11
|
+
<thead>
|
12
|
+
<tr>
|
13
|
+
<th><%= t(".name") %></th>
|
14
|
+
<th><%= t(".nickname") %></th>
|
15
|
+
<th></th>
|
16
|
+
</tr>
|
17
|
+
</thead>
|
18
|
+
<tbody>
|
19
|
+
<% @granted_authorizations.each do |authorization| %>
|
20
|
+
<tr>
|
21
|
+
<td>
|
22
|
+
<%= authorization.user.name %>
|
23
|
+
</td>
|
24
|
+
<td>
|
25
|
+
<%= authorization.user.nickname %>
|
26
|
+
</td>
|
27
|
+
<td class="table-list__actions">
|
28
|
+
<%= icon_link_to "person",
|
29
|
+
decidim.profile_path(authorization.user.nickname),
|
30
|
+
t("layouts.decidim.user_profile.account"),
|
31
|
+
class:"action-icon--show",
|
32
|
+
target: "_blank" %>
|
33
|
+
<%= icon_link_to "circle-x",
|
34
|
+
granted_authorization_path(authorization.id),
|
35
|
+
t(".remove_access"),
|
36
|
+
method: :delete,
|
37
|
+
class: "action-icon--delete" %>
|
38
|
+
</td>
|
39
|
+
</tr>
|
40
|
+
<% end %>
|
41
|
+
</tbody>
|
42
|
+
</table>
|
43
|
+
</div>
|
44
|
+
</div>
|
@@ -0,0 +1,52 @@
|
|
1
|
+
<div class="filters row">
|
2
|
+
<div class="column medium-4">
|
3
|
+
<%= form_tag "", method: :get do %>
|
4
|
+
<div class="filters__search">
|
5
|
+
<div class="input-group">
|
6
|
+
<%= search_field_tag :q, @query,label: false, class: "input-group-field", placeholder: t(".search") %>
|
7
|
+
<%= hidden_field_tag :state, @state %>
|
8
|
+
<div class="input-group-button">
|
9
|
+
<button type="submit" class="button button--muted">
|
10
|
+
<%= icon "magnifying-glass", aria_label: t(".search") %>
|
11
|
+
</button>
|
12
|
+
</div>
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
<% end %>
|
16
|
+
</div>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<div class="card" id='user-groups'>
|
20
|
+
<div class="card-divider">
|
21
|
+
<h2 class="card-title"><%= t ".users" %></h2>
|
22
|
+
</div>
|
23
|
+
<div class="card-section">
|
24
|
+
<div class="table-scroll">
|
25
|
+
<table class="table-list">
|
26
|
+
<thead>
|
27
|
+
<tr>
|
28
|
+
<th><%= t(".name") %></th>
|
29
|
+
<th><%= t(".nickname") %></th>
|
30
|
+
<th><%= t(".created_at") %></th>
|
31
|
+
<th><%= t(".actions") %></th>
|
32
|
+
</tr>
|
33
|
+
</thead>
|
34
|
+
<tbody>
|
35
|
+
<% @users.each do |user| %>
|
36
|
+
<tr data-user-id="<%= user.id %>">
|
37
|
+
<td><%= link_to user.name, decidim.profile_path(user.nickname) %></td>
|
38
|
+
<td><%= link_to user.nickname, decidim.profile_path(user.nickname) %></td>
|
39
|
+
<td><%= l user.created_at, format: :short %></td>
|
40
|
+
|
41
|
+
<td class="table-list__actions">
|
42
|
+
<%= icon_link_to "envelope-closed", current_or_new_conversation_path_with(user), t("decidim.contact"), class:"action-icon--new" %>
|
43
|
+
<%= icon_link_to "circle-check", granted_authorizations_path(user_id: user.id), t(".grant_access"), class: "action-icon--verify", method: :post %>
|
44
|
+
</td>
|
45
|
+
</tr>
|
46
|
+
<% end %>
|
47
|
+
</tbody>
|
48
|
+
</table>
|
49
|
+
<%= paginate @users, theme: "decidim" %>
|
50
|
+
</div>
|
51
|
+
</div>
|
52
|
+
</div>
|
data/app/views/decidim/access_requests/verification/admin/pending_authorizations/index.html.erb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
<div class="card">
|
2
|
+
<div class="card-divider">
|
3
|
+
<h2 class="card-title">
|
4
|
+
<%= t(".title") %>
|
5
|
+
<%= link_to t(".granted_authorizations"), granted_authorizations_path, class: "button tiny button--title" %>
|
6
|
+
</h2>
|
7
|
+
</div>
|
8
|
+
<div class="card-section">
|
9
|
+
<table class="table-list">
|
10
|
+
<thead>
|
11
|
+
<tr>
|
12
|
+
<th><%= t(".name") %></th>
|
13
|
+
<th><%= t(".nickname") %></th>
|
14
|
+
<th></th>
|
15
|
+
</tr>
|
16
|
+
</thead>
|
17
|
+
<tbody>
|
18
|
+
<% @pending_authorizations.each do |authorization| %>
|
19
|
+
<tr>
|
20
|
+
<td>
|
21
|
+
<%= authorization.user.name %>
|
22
|
+
</td>
|
23
|
+
<td>
|
24
|
+
<%= authorization.user.nickname %>
|
25
|
+
</td>
|
26
|
+
<td class="table-list__actions">
|
27
|
+
<%= icon_link_to "person",
|
28
|
+
decidim.profile_path(authorization.user.nickname),
|
29
|
+
t("layouts.decidim.user_profile.account"),
|
30
|
+
class:"action-icon--show",
|
31
|
+
target: "_blank" %>
|
32
|
+
<%= icon_link_to "circle-check",
|
33
|
+
pending_authorization_path(authorization.id),
|
34
|
+
t(".approve_request"),
|
35
|
+
method: :patch,
|
36
|
+
class: "action-icon--verify" %>
|
37
|
+
<%= icon_link_to "circle-x",
|
38
|
+
pending_authorization_path(authorization.id),
|
39
|
+
t(".reject_request"),
|
40
|
+
method: :delete,
|
41
|
+
class: "action-icon--reject" %>
|
42
|
+
</td>
|
43
|
+
</tr>
|
44
|
+
<% end %>
|
45
|
+
</tbody>
|
46
|
+
</table>
|
47
|
+
</div>
|
48
|
+
</div>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<%
|
2
|
+
active ||= []
|
3
|
+
steps = [
|
4
|
+
{
|
5
|
+
icon: "envelope-closed",
|
6
|
+
title: t(".step1.title"),
|
7
|
+
description: t(".step1.description")
|
8
|
+
},
|
9
|
+
{
|
10
|
+
icon: "check",
|
11
|
+
title: t(".step2.title"),
|
12
|
+
description: t(".step2.description")
|
13
|
+
},
|
14
|
+
{
|
15
|
+
icon: "bell",
|
16
|
+
title: t(".step3.title"),
|
17
|
+
description: t(".step3.description")
|
18
|
+
}
|
19
|
+
]
|
20
|
+
%>
|
21
|
+
|
22
|
+
<div class="row small-up-1 medium-up-3 step-bullets">
|
23
|
+
<% steps.each_with_index do |step, i| %>
|
24
|
+
<%
|
25
|
+
cls = "step-bullet text-center"
|
26
|
+
cls << " completed" if active.include?(i)
|
27
|
+
%>
|
28
|
+
<div class="column">
|
29
|
+
<div class="<%= cls %>">
|
30
|
+
<div class="step-bullet__icon">
|
31
|
+
<%= icon step[:icon] %>
|
32
|
+
</div>
|
33
|
+
<div class="step-bullet__desc">
|
34
|
+
<h4 class="heading6"><%= step[:title] %></h4>
|
35
|
+
<p><%= step[:description] %></p>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
</div>
|
39
|
+
<% end %>
|
40
|
+
</div>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<div 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(".title") %></h1>
|
6
|
+
</div>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<%= render "steps", active: [0, 1] %>
|
10
|
+
</div>
|
11
|
+
</div>
|
12
|
+
|
13
|
+
<%= stylesheet_link_tag "decidim/access_requests/verification" %>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<div 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(".title") %></h1>
|
6
|
+
</div>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<%= render "steps", active: [0] %>
|
10
|
+
|
11
|
+
<div class="row">
|
12
|
+
<div class="columns large-6 medium-centered">
|
13
|
+
<%= decidim_form_for(@form, url: authorization_path) do |form| %>
|
14
|
+
<%= form.hidden_field :handler_handle %>
|
15
|
+
|
16
|
+
<div class="actions">
|
17
|
+
<%= form.submit t(".send"), class: "button expanded", "data-disable-with" => "#{t('.send')}..." %>
|
18
|
+
</div>
|
19
|
+
<% end %>
|
20
|
+
</div>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<%= stylesheet_link_tag "decidim/access_requests/verification" %>
|
@@ -0,0 +1,70 @@
|
|
1
|
+
en:
|
2
|
+
activemodel:
|
3
|
+
models:
|
4
|
+
decidim/access_requests/access_request_confirmed_event: Access request confirmed
|
5
|
+
decidim:
|
6
|
+
access_requests:
|
7
|
+
verification:
|
8
|
+
admin:
|
9
|
+
granted_authorizations:
|
10
|
+
destroy:
|
11
|
+
error: There was an error deleting the verification.
|
12
|
+
success: Verification was deleted successfully.
|
13
|
+
index:
|
14
|
+
name: Name
|
15
|
+
new: New
|
16
|
+
nickname: Nickname
|
17
|
+
pending_authorizations: Pending requests
|
18
|
+
remove_access: Remove access
|
19
|
+
title: Granted requests
|
20
|
+
username: Username
|
21
|
+
new:
|
22
|
+
actions: Actions
|
23
|
+
created_at: Created at
|
24
|
+
grant_access: Grant access
|
25
|
+
name: Name
|
26
|
+
nickname: Nickname
|
27
|
+
search: Search
|
28
|
+
users: Users
|
29
|
+
pending_authorizations:
|
30
|
+
destroy:
|
31
|
+
error: There was an error rejecting the access request.
|
32
|
+
success: Access request was rejected successfully.
|
33
|
+
index:
|
34
|
+
approve_request: Grant access
|
35
|
+
granted_authorizations: Granted requests
|
36
|
+
name: Name
|
37
|
+
nickname: Nickname
|
38
|
+
reject_request: Reject access
|
39
|
+
title: Pending requests
|
40
|
+
update:
|
41
|
+
error: There was an error verifying access for the user.
|
42
|
+
success: Access successfully granted for the user.
|
43
|
+
authorizations:
|
44
|
+
create:
|
45
|
+
error: There was an error creating the access request.
|
46
|
+
success: Access request successfully created.
|
47
|
+
edit:
|
48
|
+
title: Your request is pending
|
49
|
+
new:
|
50
|
+
title: Request access
|
51
|
+
send: Send request
|
52
|
+
steps:
|
53
|
+
step1:
|
54
|
+
title: Step 1
|
55
|
+
description: Send access request.
|
56
|
+
step2:
|
57
|
+
title: Step 2
|
58
|
+
description: Wait for review of the request.
|
59
|
+
step3:
|
60
|
+
title: Step 3
|
61
|
+
description: >
|
62
|
+
You will get notified once the request review has been
|
63
|
+
completed.
|
64
|
+
events:
|
65
|
+
access_requests:
|
66
|
+
confirmed:
|
67
|
+
email_intro: Congratulations! You have been granted access to %{verification_name}.
|
68
|
+
email_outro: You have received this notification because your access request has been approved.
|
69
|
+
email_subject: You have been granted access to %{verification_name}!
|
70
|
+
notification_title: You have been granted access to %{verification_name}.
|