decidim-access_requests 0.15.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 (33) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE-AGPLv3.txt +661 -0
  3. data/README.md +105 -0
  4. data/Rakefile +17 -0
  5. data/app/assets/config/decidim_access_requests_manifest.css +3 -0
  6. data/app/assets/stylesheets/decidim/access_requests/verification.scss +4 -0
  7. data/app/assets/stylesheets/decidim/access_requests/verification/_step-bullets.scss +30 -0
  8. data/app/assets/stylesheets/decidim/access_requests/verification/_variables.scss +2 -0
  9. data/app/commands/decidim/access_requests/verification/admin/confirm_user_access_request.rb +67 -0
  10. data/app/commands/decidim/access_requests/verification/admin/destroy_authorization.rb +40 -0
  11. data/app/controllers/concerns/decidim/access_requests/verification/detectable_verification_manifest.rb +23 -0
  12. data/app/controllers/decidim/access_requests/verification/admin/granted_authorizations_controller.rb +117 -0
  13. data/app/controllers/decidim/access_requests/verification/admin/pending_authorizations_controller.rb +76 -0
  14. data/app/controllers/decidim/access_requests/verification/authorizations_controller.rb +68 -0
  15. data/app/events/decidim/access_requests/access_request_confirmed_event.rb +31 -0
  16. data/app/forms/decidim/access_requests/verification/request_form.rb +25 -0
  17. data/app/presenters/decidim/access_requests/verification/authorization_presenter.rb +16 -0
  18. data/app/views/decidim/access_requests/verification/admin/granted_authorizations/index.html.erb +44 -0
  19. data/app/views/decidim/access_requests/verification/admin/granted_authorizations/new.html.erb +52 -0
  20. data/app/views/decidim/access_requests/verification/admin/pending_authorizations/index.html.erb +48 -0
  21. data/app/views/decidim/access_requests/verification/authorizations/_steps.html.erb +40 -0
  22. data/app/views/decidim/access_requests/verification/authorizations/edit.html.erb +13 -0
  23. data/app/views/decidim/access_requests/verification/authorizations/new.html.erb +25 -0
  24. data/config/locales/en.yml +70 -0
  25. data/config/locales/fi.yml +68 -0
  26. data/config/locales/sv.yml +70 -0
  27. data/lib/decidim/access_requests.rb +9 -0
  28. data/lib/decidim/access_requests/verification.rb +5 -0
  29. data/lib/decidim/access_requests/verification/admin.rb +12 -0
  30. data/lib/decidim/access_requests/verification/admin_engine.rb +21 -0
  31. data/lib/decidim/access_requests/verification/engine.rb +24 -0
  32. data/lib/decidim/access_requests/version.rb +8 -0
  33. 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
@@ -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>
@@ -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}.