decidim-kids 0.1.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 +265 -0
- data/Rakefile +45 -0
- data/app/commands/concerns/decidim/kids/system/create_minors_default_pages.rb +20 -0
- data/app/commands/concerns/decidim/kids/system/register_organization_override.rb +32 -0
- data/app/commands/concerns/decidim/kids/system/update_organization_override.rb +30 -0
- data/app/commands/decidim/kids/admin/save_participatory_space_config.rb +37 -0
- data/app/commands/decidim/kids/authorize_minor.rb +52 -0
- data/app/commands/decidim/kids/close_session_managed_minor.rb +38 -0
- data/app/commands/decidim/kids/create_minor_account.rb +57 -0
- data/app/commands/decidim/kids/destroy_minor_account.rb +50 -0
- data/app/commands/decidim/kids/impersonate_minor.rb +64 -0
- data/app/commands/decidim/kids/update_minor_account.rb +45 -0
- data/app/controllers/concerns/decidim/kids/disable_minors_participation.rb +17 -0
- data/app/controllers/concerns/decidim/kids/has_decidim_kids_permissions.rb +15 -0
- data/app/controllers/concerns/decidim/kids/has_minor_activities_as_own.rb +17 -0
- data/app/controllers/concerns/decidim/kids/impersonate_minors.rb +53 -0
- data/app/controllers/concerns/decidim/kids/needs_adult_permission.rb +16 -0
- data/app/controllers/concerns/decidim/kids/needs_tutor_authorization.rb +54 -0
- data/app/controllers/concerns/decidim/kids/participatory_space_context_override.rb +86 -0
- data/app/controllers/concerns/decidim/kids/writes_minor_log.rb +28 -0
- data/app/controllers/decidim/assemblies/admin/minors_space_controller.rb +12 -0
- data/app/controllers/decidim/kids/admin/application_controller.rb +10 -0
- data/app/controllers/decidim/kids/admin/minors_space_controller.rb +63 -0
- data/app/controllers/decidim/kids/application_controller.rb +8 -0
- data/app/controllers/decidim/kids/authorizations_controller.rb +82 -0
- data/app/controllers/decidim/kids/minor_impersonations_controller.rb +57 -0
- data/app/controllers/decidim/kids/user_minors_controller.rb +106 -0
- data/app/controllers/decidim/participatory_processes/admin/minors_space_controller.rb +12 -0
- data/app/forms/concerns/decidim/kids/system/organization_form_override.rb +40 -0
- data/app/forms/decidim/kids/admin/minors_space_form.rb +20 -0
- data/app/forms/decidim/kids/impersonate_minor_form.rb +23 -0
- data/app/forms/decidim/kids/minor_account_form.rb +35 -0
- data/app/helpers/decidim/kids/application_helper.rb +11 -0
- data/app/helpers/decidim/kids/user_minors_helper.rb +57 -0
- data/app/jobs/decidim/kids/expire_impersonation_job.rb +16 -0
- data/app/mailers/decidim/kids/kids_mailer.rb +14 -0
- data/app/models/concerns/decidim/kids/organization_override.rb +45 -0
- data/app/models/concerns/decidim/kids/static_page_override.rb +17 -0
- data/app/models/concerns/decidim/kids/user_override.rb +53 -0
- data/app/models/decidim/kids/application_record.rb +10 -0
- data/app/models/decidim/kids/impersonation_minor_log.rb +36 -0
- data/app/models/decidim/kids/minor_account.rb +51 -0
- data/app/models/decidim/kids/minor_data.rb +28 -0
- data/app/models/decidim/kids/minors_space_config.rb +26 -0
- data/app/models/decidim/kids/organization_config.rb +13 -0
- data/app/overrides/decidim/devise/registrations/new/minors.html.erb.deface +2 -0
- data/app/overrides/decidim/system/organizations/_advanced_settings/minors.html.erb.deface +2 -0
- data/app/overrides/layouts/decidim/_impersonation_warning/replace_button.html.erb.deface +3 -0
- data/app/packs/entrypoints/decidim_kids.js +2 -0
- data/app/packs/images/decidim/kids/icon.svg +1 -0
- data/app/packs/stylesheets/decidim/kids/kids.scss +13 -0
- data/app/permissions/concerns/decidim/kids/admin/permissions_override.rb +38 -0
- data/app/permissions/decidim/kids/permissions.rb +100 -0
- data/app/views/decidim/kids/admin/minors_space/_form.html.erb +53 -0
- data/app/views/decidim/kids/admin/minors_space/index.html.erb +18 -0
- data/app/views/decidim/kids/authorizations/new.html.erb +29 -0
- data/app/views/decidim/kids/devise/registrations/_minors.html.erb +8 -0
- data/app/views/decidim/kids/kids_mailer/promote_minor_account.html.erb +3 -0
- data/app/views/decidim/kids/minor_impersonations/_impersonation_minor_button.html.erb +13 -0
- data/app/views/decidim/kids/minor_impersonations/new.html.erb +19 -0
- data/app/views/decidim/kids/system/organizations/_minors_form.html.erb +28 -0
- data/app/views/decidim/kids/user_minors/_form_fields.html.erb +12 -0
- data/app/views/decidim/kids/user_minors/_minor_tr.html.erb +58 -0
- data/app/views/decidim/kids/user_minors/_tos_field.html.erb +3 -0
- data/app/views/decidim/kids/user_minors/edit.html.erb +19 -0
- data/app/views/decidim/kids/user_minors/index.html.erb +30 -0
- data/app/views/decidim/kids/user_minors/new.html.erb +22 -0
- data/app/views/decidim/kids/user_minors/unverified.html.erb +10 -0
- data/app/views/devise/mailer/invite_minor.html.erb +15 -0
- data/config/assets.rb +9 -0
- data/config/i18n-tasks.yml +10 -0
- data/config/locales/ca.yml +165 -0
- data/config/locales/en.yml +190 -0
- data/config/locales/es.yml +165 -0
- data/db/migrate/20221017110422_create_organization_minors_configs.rb +16 -0
- data/db/migrate/20221024124523_create_decidim_kids_minor_accounts.rb +13 -0
- data/db/migrate/20221027211859_create_decidim_kids_minor_data.rb +14 -0
- data/db/migrate/20221127103636_create_impersonation_minor_logs.rb +15 -0
- data/db/migrate/20221220132306_create_decidim_kids_participatory_spaces_minors_configs.rb +13 -0
- data/db/seeds.rb +36 -0
- data/lib/decidim/kids/admin.rb +8 -0
- data/lib/decidim/kids/admin_engine.rb +43 -0
- data/lib/decidim/kids/age_methods.rb +17 -0
- data/lib/decidim/kids/engine.rb +86 -0
- data/lib/decidim/kids/templates/dummy_age_authorization_handler.rb +30 -0
- data/lib/decidim/kids/templates/verifications_initializer.rb +8 -0
- data/lib/decidim/kids/test/factories.rb +64 -0
- data/lib/decidim/kids/version.rb +10 -0
- data/lib/decidim/kids.rb +91 -0
- data/lib/tasks/authorization_handlers.rake +35 -0
- data/lib/tasks/kids.rake +8 -0
- data/package-lock.json +12463 -0
- data/package.json +50 -0
- 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,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,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
|