decidim-kids 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE-AGPLv3.txt +661 -0
  3. data/README.md +265 -0
  4. data/Rakefile +45 -0
  5. data/app/commands/concerns/decidim/kids/system/create_minors_default_pages.rb +20 -0
  6. data/app/commands/concerns/decidim/kids/system/register_organization_override.rb +32 -0
  7. data/app/commands/concerns/decidim/kids/system/update_organization_override.rb +30 -0
  8. data/app/commands/decidim/kids/admin/save_participatory_space_config.rb +37 -0
  9. data/app/commands/decidim/kids/authorize_minor.rb +52 -0
  10. data/app/commands/decidim/kids/close_session_managed_minor.rb +38 -0
  11. data/app/commands/decidim/kids/create_minor_account.rb +57 -0
  12. data/app/commands/decidim/kids/destroy_minor_account.rb +50 -0
  13. data/app/commands/decidim/kids/impersonate_minor.rb +64 -0
  14. data/app/commands/decidim/kids/update_minor_account.rb +45 -0
  15. data/app/controllers/concerns/decidim/kids/disable_minors_participation.rb +17 -0
  16. data/app/controllers/concerns/decidim/kids/has_decidim_kids_permissions.rb +15 -0
  17. data/app/controllers/concerns/decidim/kids/has_minor_activities_as_own.rb +17 -0
  18. data/app/controllers/concerns/decidim/kids/impersonate_minors.rb +53 -0
  19. data/app/controllers/concerns/decidim/kids/needs_adult_permission.rb +16 -0
  20. data/app/controllers/concerns/decidim/kids/needs_tutor_authorization.rb +54 -0
  21. data/app/controllers/concerns/decidim/kids/participatory_space_context_override.rb +86 -0
  22. data/app/controllers/concerns/decidim/kids/writes_minor_log.rb +28 -0
  23. data/app/controllers/decidim/assemblies/admin/minors_space_controller.rb +12 -0
  24. data/app/controllers/decidim/kids/admin/application_controller.rb +10 -0
  25. data/app/controllers/decidim/kids/admin/minors_space_controller.rb +63 -0
  26. data/app/controllers/decidim/kids/application_controller.rb +8 -0
  27. data/app/controllers/decidim/kids/authorizations_controller.rb +82 -0
  28. data/app/controllers/decidim/kids/minor_impersonations_controller.rb +57 -0
  29. data/app/controllers/decidim/kids/user_minors_controller.rb +106 -0
  30. data/app/controllers/decidim/participatory_processes/admin/minors_space_controller.rb +12 -0
  31. data/app/forms/concerns/decidim/kids/system/organization_form_override.rb +40 -0
  32. data/app/forms/decidim/kids/admin/minors_space_form.rb +20 -0
  33. data/app/forms/decidim/kids/impersonate_minor_form.rb +23 -0
  34. data/app/forms/decidim/kids/minor_account_form.rb +35 -0
  35. data/app/helpers/decidim/kids/application_helper.rb +11 -0
  36. data/app/helpers/decidim/kids/user_minors_helper.rb +57 -0
  37. data/app/jobs/decidim/kids/expire_impersonation_job.rb +16 -0
  38. data/app/mailers/decidim/kids/kids_mailer.rb +14 -0
  39. data/app/models/concerns/decidim/kids/organization_override.rb +45 -0
  40. data/app/models/concerns/decidim/kids/static_page_override.rb +17 -0
  41. data/app/models/concerns/decidim/kids/user_override.rb +53 -0
  42. data/app/models/decidim/kids/application_record.rb +10 -0
  43. data/app/models/decidim/kids/impersonation_minor_log.rb +36 -0
  44. data/app/models/decidim/kids/minor_account.rb +51 -0
  45. data/app/models/decidim/kids/minor_data.rb +28 -0
  46. data/app/models/decidim/kids/minors_space_config.rb +26 -0
  47. data/app/models/decidim/kids/organization_config.rb +13 -0
  48. data/app/overrides/decidim/devise/registrations/new/minors.html.erb.deface +2 -0
  49. data/app/overrides/decidim/system/organizations/_advanced_settings/minors.html.erb.deface +2 -0
  50. data/app/overrides/layouts/decidim/_impersonation_warning/replace_button.html.erb.deface +3 -0
  51. data/app/packs/entrypoints/decidim_kids.js +2 -0
  52. data/app/packs/images/decidim/kids/icon.svg +1 -0
  53. data/app/packs/stylesheets/decidim/kids/kids.scss +13 -0
  54. data/app/permissions/concerns/decidim/kids/admin/permissions_override.rb +38 -0
  55. data/app/permissions/decidim/kids/permissions.rb +100 -0
  56. data/app/views/decidim/kids/admin/minors_space/_form.html.erb +53 -0
  57. data/app/views/decidim/kids/admin/minors_space/index.html.erb +18 -0
  58. data/app/views/decidim/kids/authorizations/new.html.erb +29 -0
  59. data/app/views/decidim/kids/devise/registrations/_minors.html.erb +8 -0
  60. data/app/views/decidim/kids/kids_mailer/promote_minor_account.html.erb +3 -0
  61. data/app/views/decidim/kids/minor_impersonations/_impersonation_minor_button.html.erb +13 -0
  62. data/app/views/decidim/kids/minor_impersonations/new.html.erb +19 -0
  63. data/app/views/decidim/kids/system/organizations/_minors_form.html.erb +28 -0
  64. data/app/views/decidim/kids/user_minors/_form_fields.html.erb +12 -0
  65. data/app/views/decidim/kids/user_minors/_minor_tr.html.erb +58 -0
  66. data/app/views/decidim/kids/user_minors/_tos_field.html.erb +3 -0
  67. data/app/views/decidim/kids/user_minors/edit.html.erb +19 -0
  68. data/app/views/decidim/kids/user_minors/index.html.erb +30 -0
  69. data/app/views/decidim/kids/user_minors/new.html.erb +22 -0
  70. data/app/views/decidim/kids/user_minors/unverified.html.erb +10 -0
  71. data/app/views/devise/mailer/invite_minor.html.erb +15 -0
  72. data/config/assets.rb +9 -0
  73. data/config/i18n-tasks.yml +10 -0
  74. data/config/locales/ca.yml +165 -0
  75. data/config/locales/en.yml +190 -0
  76. data/config/locales/es.yml +165 -0
  77. data/db/migrate/20221017110422_create_organization_minors_configs.rb +16 -0
  78. data/db/migrate/20221024124523_create_decidim_kids_minor_accounts.rb +13 -0
  79. data/db/migrate/20221027211859_create_decidim_kids_minor_data.rb +14 -0
  80. data/db/migrate/20221127103636_create_impersonation_minor_logs.rb +15 -0
  81. data/db/migrate/20221220132306_create_decidim_kids_participatory_spaces_minors_configs.rb +13 -0
  82. data/db/seeds.rb +36 -0
  83. data/lib/decidim/kids/admin.rb +8 -0
  84. data/lib/decidim/kids/admin_engine.rb +43 -0
  85. data/lib/decidim/kids/age_methods.rb +17 -0
  86. data/lib/decidim/kids/engine.rb +86 -0
  87. data/lib/decidim/kids/templates/dummy_age_authorization_handler.rb +30 -0
  88. data/lib/decidim/kids/templates/verifications_initializer.rb +8 -0
  89. data/lib/decidim/kids/test/factories.rb +64 -0
  90. data/lib/decidim/kids/version.rb +10 -0
  91. data/lib/decidim/kids.rb +91 -0
  92. data/lib/tasks/authorization_handlers.rake +35 -0
  93. data/lib/tasks/kids.rake +8 -0
  94. data/package-lock.json +12463 -0
  95. data/package.json +50 -0
  96. metadata +213 -0
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Kids
5
+ # A command with all the business logic to impersonate a minor.
6
+ class ImpersonateMinor < Decidim::Command
7
+ # Public: Initializes the command.
8
+ #
9
+ # current_user - The user impersonating a minor
10
+ # minor_user - The user to impersonate
11
+ # form - The form with the authorization info
12
+ def initialize(minor_user, current_user, form)
13
+ @current_user = current_user
14
+ @minor_user = minor_user
15
+ @form = form
16
+ end
17
+
18
+ def call
19
+ return broadcast(:invalid) if form.invalid?
20
+
21
+ transaction do
22
+ impersonation_log = create_impersonation_log
23
+ create_action_log(impersonation_log)
24
+ end
25
+
26
+ enqueue_expire_job
27
+
28
+ broadcast(:ok)
29
+ end
30
+
31
+ private
32
+
33
+ attr :form, :minor_user, :current_user
34
+
35
+ def create_impersonation_log
36
+ Decidim::Kids::ImpersonationMinorLog.create!(
37
+ tutor: current_user,
38
+ minor: minor_user,
39
+ started_at: Time.current
40
+ )
41
+ end
42
+
43
+ def create_action_log(impersonation_log)
44
+ Decidim.traceability.perform_action!(
45
+ "manage",
46
+ impersonation_log,
47
+ current_user,
48
+ resource: {
49
+ id: minor_user.id,
50
+ name: minor_user.name,
51
+ nickname: minor_user.nickname
52
+ },
53
+ visibility: "public-only"
54
+ )
55
+ end
56
+
57
+ def enqueue_expire_job
58
+ Decidim::Kids::ExpireImpersonationJob
59
+ .set(wait: Decidim::Kids::ImpersonationMinorLog::SESSION_TIME_IN_MINUTES.minutes)
60
+ .perform_later(minor_user, current_user)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Kids
5
+ class UpdateMinorAccount < Decidim::Command
6
+ def initialize(form, minor_user)
7
+ @form = form
8
+ @minor_user = minor_user
9
+ end
10
+
11
+ def call
12
+ return broadcast(:invalid) if form.invalid?
13
+
14
+ old_minor_email = minor_user.email
15
+
16
+ update_minor
17
+
18
+ minor_user.save!
19
+
20
+ minor_user.minor_data.update!(attributes_data)
21
+
22
+ minor_user.invite!(invited_by, invitation_instructions: "invite_minor") unless old_minor_email == form.email
23
+
24
+ broadcast(:ok)
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :form, :minor_user, :invited_by
30
+
31
+ def update_minor
32
+ minor_user.skip_reconfirmation!
33
+ minor_user.email = form.email
34
+ end
35
+
36
+ def attributes_data
37
+ {
38
+ birthday: form.birthday,
39
+ email: form.email,
40
+ name: form.name
41
+ }
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Kids
5
+ # Controllers implementing this concern will be able to restrict access to user's that are not minors.
6
+ module DisableMinorsParticipation
7
+ extend ActiveSupport::Concern
8
+ include HasDecidimKidsPermissions
9
+
10
+ included do
11
+ before_action do
12
+ enforce_permission_to :all, :authorizations
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Kids
5
+ module HasDecidimKidsPermissions
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ def permission_class_chain
10
+ super + [::Decidim::Kids::Permissions]
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Kids
5
+ module HasMinorActivitiesAsOwn
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ alias_method :user_own_activities?, :own_activities?
10
+
11
+ def own_activities?
12
+ user_own_activities? || (current_organization.minors_participation_enabled? && current_user&.minors&.include?(user))
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Kids
5
+ module ImpersonateMinors
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ helper_method :impersonation_log_minor
10
+
11
+ def current_user
12
+ @current_user ||= managed_minor || managed_user || real_user
13
+ end
14
+
15
+ def impersonation_session_ends_at
16
+ @impersonation_session_ends_at ||= minor_session_ends_at || user_session_ends_at
17
+ end
18
+
19
+ private
20
+
21
+ # Returns the minor user impersonated by an tutor if exists
22
+ def managed_minor
23
+ return if impersonation_log_minor.blank?
24
+
25
+ @managed_minor ||= begin
26
+ impersonation_log_minor.ensure_not_expired!
27
+ impersonation_log_minor.minor
28
+ end
29
+ end
30
+
31
+ def impersonation_log_minor
32
+ @impersonation_log_minor ||= Decidim::Kids::ImpersonationMinorLog.where(tutor: real_user).active.first
33
+ end
34
+
35
+ def current_user_impersonated?
36
+ current_user && (impersonation_log_minor.present? || impersonation_log.present?)
37
+ end
38
+
39
+ def minor_session_ends_at
40
+ return if impersonation_log_minor.blank?
41
+
42
+ impersonation_log_minor.started_at + Decidim::Kids::ImpersonationMinorLog::SESSION_TIME_IN_MINUTES.minutes
43
+ end
44
+
45
+ def user_session_ends_at
46
+ return if impersonation_log.blank?
47
+
48
+ impersonation_log.started_at + Decidim::ImpersonationLog::SESSION_TIME_IN_MINUTES.minutes
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Kids
5
+ module NeedsAdultPermission
6
+ extend ActiveSupport::Concern
7
+ include HasDecidimKidsPermissions
8
+
9
+ included do
10
+ before_action do
11
+ enforce_permission_to :all, :authorizations
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Kids
5
+ module NeedsTutorAuthorization
6
+ extend ActiveSupport::Concern
7
+ include HasDecidimKidsPermissions
8
+
9
+ included do
10
+ before_action do
11
+ if tutor_adapter.blank?
12
+ flash[:alert] = t("user_minors.no_tutor_authorization", scope: "decidim.kids")
13
+ redirect_to decidim.account_path
14
+ end
15
+ end
16
+
17
+ before_action except: [:unverified] do
18
+ enforce_permission_to :index, :minor_accounts
19
+ redirect_to unverified_user_minors_path unless tutor_verified?
20
+ end
21
+
22
+ helper_method :minors, :tutor_adapter
23
+
24
+ private
25
+
26
+ def tutor_verified?
27
+ @tutor_verified ||= tutor_authorization.present? && !tutor_authorization.expired?
28
+ end
29
+
30
+ def tutor_adapter
31
+ @tutor_adapter ||= Decidim::Verifications::Adapter.from_element(current_organization.tutors_authorization)
32
+ rescue Decidim::Verifications::UnregisteredVerificationManifest
33
+ nil
34
+ end
35
+
36
+ def tutor_authorization
37
+ @tutor_authorization ||= granted_authorizations(current_user).find_by(name: current_organization.tutors_authorization)
38
+ end
39
+
40
+ def minor_authorization(user)
41
+ granted_authorizations(user).find_by(name: current_organization.minors_authorization)
42
+ end
43
+
44
+ def granted_authorizations(user)
45
+ Decidim::Verifications::Authorizations.new(organization: current_organization, user: user, granted: true).query
46
+ end
47
+
48
+ def minors
49
+ current_user.minors
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Kids
5
+ # This module contains all the domain logic associated to restrict operations depending on the user's age/minors configuration.
6
+ module ParticipatorySpaceContextOverride
7
+ extend ActiveSupport::Concern
8
+ include AgeMethods
9
+
10
+ included do
11
+ class ::Decidim::Kids::ActionForbidden < ::Decidim::ActionForbidden
12
+ end
13
+
14
+ rescue_from Decidim::Kids::ActionForbidden, with: :no_minor_user_has_no_permission
15
+
16
+ def no_minor_user_has_no_permission
17
+ flash[:alert] = t("actions.unauthorized", scope: "decidim.kids")
18
+ redirect_to(user_has_no_permission_referer || user_has_no_permission_path)
19
+ end
20
+
21
+ before_action do
22
+ enforce_space_for_minors! if space_minors_config.access_type == "minors"
23
+ end
24
+ end
25
+
26
+ def space_minors_config
27
+ @space_minors_config ||= MinorsSpaceConfig.for(current_participatory_space)
28
+ end
29
+
30
+ private
31
+
32
+ def enforce_space_for_minors!
33
+ return unless current_organization.minors_participation_enabled?
34
+
35
+ if current_user
36
+ # Allow admins and any other role with access to the admin dashboard
37
+ return if allowed_to?(:read, :admin_dashboard, current_participatory_space: current_participatory_space)
38
+ # Allow minors
39
+ return if current_user.minor?
40
+
41
+ return if current_user_is_a_valid_tutor?
42
+ # users with authorization to access minors spaces, check the age if possible
43
+ return if current_user_has_a_valid_authorization?
44
+ end
45
+
46
+ raise Decidim::Kids::ActionForbidden
47
+ end
48
+
49
+ def current_user_is_a_valid_tutor?
50
+ return unless current_user.tutor?
51
+ return unless current_user.confirmed?
52
+
53
+ # only tutors with readonly access are allowed
54
+ return if request.post? || request.patch? || request.put? || request.delete?
55
+
56
+ # check for having at least one minor confirmed
57
+ current_user.minors.detect(&:confirmed?)
58
+ end
59
+
60
+ def current_user_has_a_valid_authorization?
61
+ return unless space_authorization
62
+
63
+ return true if space_minors_config.max_age.blank? || space_minors_config.max_age.zero?
64
+
65
+ authorization_has_a_valid_age?
66
+ end
67
+
68
+ def authorization_has_a_valid_age?
69
+ Decidim::Kids.minor_authorization_age_attributes.detect do |attr|
70
+ age = age_from_date(space_authorization.metadata[attr.to_s])
71
+ next unless age
72
+
73
+ age <= space_minors_config.max_age
74
+ end
75
+ end
76
+
77
+ def space_authorization
78
+ @space_authorization ||= current_user_authorizations.find_by(name: space_minors_config.authorization)
79
+ end
80
+
81
+ def current_user_authorizations
82
+ Decidim::Verifications::Authorizations.new(organization: current_organization, user: current_user, granted: true).query
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Kids
5
+ module WritesMinorLog
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ before_action do
10
+ Rails.logger.tagged("MINOR-ACTIVITY").info(log_params) if current_user.present? && current_user.minor?
11
+ end
12
+
13
+ private
14
+
15
+ def log_params
16
+ {
17
+ remote_ip: request.remote_ip,
18
+ method: request.method,
19
+ path: request.fullpath,
20
+ params: request.params,
21
+ format: request.format&.to_s || "*/*",
22
+ user_id: current_user.id
23
+ }
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ module Admin
6
+ # Controller that allows managing minors limited access for assemblies
7
+ class MinorsSpaceController < Decidim::Kids::Admin::MinorsSpaceController
8
+ include Concerns::AssemblyAdmin
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Kids
5
+ module Admin
6
+ class ApplicationController < Decidim::Admin::ApplicationController
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Kids
5
+ module Admin
6
+ # Base Controller that specific participatory spaces should inherit from to limit access to minors.
7
+ class MinorsSpaceController < Decidim::Admin::ApplicationController
8
+ before_action do
9
+ enforce_permission_to :manage, :space_minors_configuration
10
+ end
11
+
12
+ helper_method :access_types, :authorization_handlers, :authorization_method_error
13
+
14
+ def index
15
+ @form = form(MinorsSpaceForm).from_model(current_participatory_space_config)
16
+ end
17
+
18
+ def create
19
+ @form = form(MinorsSpaceForm).from_params(params)
20
+
21
+ SaveParticipatorySpaceConfig.call(@form, current_participatory_space) do
22
+ on(:ok) do
23
+ flash[:notice] = I18n.t("minors_space.save.success", scope: "decidim.kids.admin")
24
+ redirect_to action: :index
25
+ end
26
+
27
+ on(:invalid) do
28
+ flash.now[:alert] = I18n.t("minors_space.save.error", scope: "decidim.kids.admin", errors: @form&.errors&.messages&.values&.flatten&.first)
29
+ render :index
30
+ end
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def current_participatory_space_config
37
+ @current_participatory_space_config ||= MinorsSpaceConfig.for(current_participatory_space)
38
+ end
39
+
40
+ def authorization_handlers
41
+ Decidim::Kids.valid_minor_workflows.pluck(:description, :name)
42
+ end
43
+
44
+ def authorization_method_error(handler)
45
+ form_class = Decidim::Verifications.find_workflow_manifest(handler)&.form&.safe_constantize
46
+ return :invalid unless form_class
47
+
48
+ dummy = form_class.new
49
+ return :metadata unless dummy.respond_to? :metadata
50
+
51
+ :metadata unless Decidim::Kids.minor_authorization_age_attributes.detect { |attr| dummy.metadata.has_key?(attr.to_sym) }
52
+ end
53
+
54
+ def access_types
55
+ {
56
+ t("minors_space.form.all", scope: "decidim.kids.admin") => "all",
57
+ t("minors_space.form.minors", scope: "decidim.kids.admin") => "minors"
58
+ }
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Kids
5
+ class ApplicationController < Decidim::ApplicationController
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Kids
5
+ class AuthorizationsController < Decidim::Verifications::AuthorizationsController
6
+ include Decidim::UserProfile
7
+ include NeedsTutorAuthorization
8
+
9
+ layout "layouts/decidim/user_profile"
10
+
11
+ helper_method :authorizations_path, :minor_user
12
+
13
+ def authorizations_path(prs = {})
14
+ decidim_kids.user_minor_authorizations_path(prs)
15
+ end
16
+
17
+ def index
18
+ if minor_authorized?
19
+ # TODO: unblock user, update personal data
20
+ flash[:notice] = t("authorizations.authorize.success", scope: "decidim.kids")
21
+ else
22
+ flash[:alert] = t("authorizations.authorize.error", scope: "decidim.kids")
23
+ end
24
+ redirect_to decidim_kids.user_minors_path
25
+ end
26
+
27
+ def new
28
+ if minor_authorized?
29
+ flash[:notice] = t("authorizations.authorize.already_authorized", scope: "decidim.kids")
30
+ redirect_to decidim_kids.user_minors_path
31
+ else
32
+ super
33
+ end
34
+ end
35
+
36
+ def create
37
+ if minor_authorized?
38
+ flash[:notice] = t("authorizations.authorize.already_authorized", scope: "decidim.kids")
39
+ return redirect_to decidim_kids.user_minors_path
40
+ end
41
+
42
+ AuthorizeMinor.call(handler) do
43
+ on(:ok) do
44
+ flash[:notice] = t("authorizations.authorize.success", scope: "decidim.kids")
45
+ redirect_to redirect_url || authorizations_path
46
+ end
47
+
48
+ on(:transferred) do
49
+ flash[:notice] = t("authorizations.authorize.success", scope: "decidim.kids")
50
+ redirect_to redirect_url || authorizations_path
51
+ end
52
+
53
+ on(:invalid_age) do
54
+ flash[:alert] = t("authorizations.create.invalid_age", scope: "decidim.kids")
55
+ render action: :new
56
+ end
57
+
58
+ on(:invalid) do
59
+ flash[:alert] = t("authorizations.authorize.error", scope: "decidim.kids")
60
+ render action: :new
61
+ end
62
+ end
63
+ end
64
+
65
+ def handler_params
66
+ (params[:authorization_handler] || {}).merge(user: minor_user)
67
+ end
68
+
69
+ def handler_name
70
+ current_organization.minors_authorization
71
+ end
72
+
73
+ def minor_user
74
+ current_user.minors.find(params[:user_minor_id])
75
+ end
76
+
77
+ def minor_authorized?
78
+ minor_authorization(minor_user).present?
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Kids
5
+ # Controller that allows impersonating managed minors.
6
+ class MinorImpersonationsController < ApplicationController
7
+ include Decidim::UserProfile
8
+
9
+ layout "layouts/decidim/user_profile"
10
+
11
+ helper_method :minor_user
12
+
13
+ def permission_class_chain
14
+ [::Decidim::Kids::Permissions] + super
15
+ end
16
+
17
+ def new
18
+ enforce_permission_to :impersonate, :minor_accounts, minor_user: minor_user
19
+
20
+ @form = form(ImpersonateMinorForm).from_params(params)
21
+ end
22
+
23
+ def create
24
+ enforce_permission_to :impersonate, :minor_accounts, minor_user: minor_user
25
+
26
+ @form = form(ImpersonateMinorForm).from_params(params)
27
+
28
+ ImpersonateMinor.call(minor_user, current_user, @form) do
29
+ on(:ok) do
30
+ flash[:notice] = I18n.t("impersonations.create.success", scope: "decidim.kids")
31
+ redirect_to decidim.root_path
32
+ end
33
+
34
+ on(:invalid) do
35
+ flash.now[:alert] = I18n.t("impersonations.create.error", scope: "decidim.kids")
36
+ render :new
37
+ end
38
+ end
39
+ end
40
+
41
+ def close_session
42
+ CloseSessionManagedMinor.call(current_user, real_user) do
43
+ on(:ok) do
44
+ flash[:notice] = I18n.t("impersonations.close_session.success", scope: "decidim.kids")
45
+ redirect_to decidim.root_path
46
+ end
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def minor_user
53
+ current_user.minors.find(params[:user_minor_id])
54
+ end
55
+ end
56
+ end
57
+ end