Skip to content

Commit 3aef6d2

Browse files
committed
Issue #3534 - Added server-side validation to ensure that an user can
only create plan's from templates available to their org.
1 parent 0046b36 commit 3aef6d2

File tree

1 file changed

+74
-50
lines changed

1 file changed

+74
-50
lines changed

app/controllers/plans_controller.rb

Lines changed: 74 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -29,62 +29,15 @@ def index
2929
# rubocop:enable Metrics/AbcSize
3030

3131
# GET /plans/new
32-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
3332
def new
3433
@plan = Plan.new
3534
authorize @plan
36-
@plan.org_id = current_user.org&.id
37-
# looks into the list of families of templates
38-
customizations = Template.latest_customized_version_per_org(@plan.org_id)
39-
customization_ids = customizations.select(&:published?).collect(&:customization_of)
40-
41-
# get templates of user's own org
42-
user_org_own_templates = Template.organisationally_visible
43-
.where(org_id: @plan.org_id, customization_of: nil)
44-
.published
45-
.uniq.sort_by(&:title)
46-
47-
# get templates of user's customised org
48-
user_org_custom_templates = Template.latest_customized_version_per_org(@plan.org_id)
49-
.published
50-
.uniq.sort_by(&:title)
51-
52-
# get funder templates no customised templates
53-
funder_non_customised_templates = Template.published
54-
.joins(:org)
55-
.where(orgs: { org_type: Org.org_type_values_for(:funder) })
56-
# The next line removes templates that belong to a family that
57-
# has customised templates
58-
.where.not(family_id: customization_ids)
59-
.uniq.sort_by(&:title)
60-
61-
# get global templates
62-
global_templates = Template.published
63-
.where(is_default: true)
64-
# The next line removes templates that belong to a family that
65-
# has customised templates
66-
.where.not(family_id: customization_ids)
67-
.uniq.sort_by(&:title)
68-
69-
# create templates-grouped hash
70-
@templates_grouped = {
71-
_("Your Organisation's Templates:") => user_org_own_templates.map do |t|
72-
[t.title, t.id]
73-
end,
74-
_("Your Organisation's Customised Templates:") => user_org_custom_templates.map do |t|
75-
[t.title, t.id]
76-
end,
77-
_('Global Templates:') => global_templates.map do |t|
78-
[t.title, t.id]
79-
end,
80-
_('Funder Templates:') => funder_non_customised_templates.map do |t|
81-
[t.title, t.id]
82-
end
83-
}.reject { |_, val| val.empty? }
35+
org_id = current_user.org&.id
8436

37+
# Get templates grouped hash
38+
@templates_grouped = templates_available_to_org_user(org_id)
8539
respond_to :html
8640
end
87-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
8841

8942
# POST /plans
9043
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
@@ -102,6 +55,15 @@ def create
10255
format.html { redirect_to new_plan_path }
10356
end
10457
else
58+
template_id = plan_params[:template_id].to_i
59+
unless validate_template_available_to_org_user?(template_id, current_user.org_id)
60+
respond_to do |format|
61+
flash[:alert] = _('The selected template is not available to your organisation.')
62+
format.html { redirect_to new_plan_path }
63+
end
64+
return
65+
end
66+
10567
@plan.visibility = if plan_params['visibility'].blank?
10668
Rails.configuration.x.plans.default_visibility
10769
else
@@ -568,5 +530,67 @@ def render_phases_edit(plan, phase, guidance_groups)
568530
guidance_presenter: GuidancePresenter.new(plan)
569531
})
570532
end
533+
534+
# Get templates available to org users
535+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
536+
def templates_available_to_org_user(org_id)
537+
# looks into the list of families of templates
538+
customizations = Template.latest_customized_version_per_org(org_id)
539+
customization_ids = customizations.select(&:published?).collect(&:customization_of)
540+
541+
# get templates of user's own org
542+
user_org_own_templates = Template.organisationally_visible
543+
.where(org_id: org_id, customization_of: nil)
544+
.published
545+
.uniq.sort_by(&:title)
546+
547+
# get templates of user's customised org
548+
user_org_custom_templates = Template.latest_customized_version_per_org(org_id)
549+
.published
550+
.uniq.sort_by(&:title)
551+
552+
# get funder templates no customised templates
553+
funder_non_customised_templates = Template.published
554+
.joins(:org)
555+
.where(orgs: { org_type: Org.org_type_values_for(:funder) })
556+
# The next line removes templates that belong to a family that
557+
# has customised templates
558+
.where.not(family_id: customization_ids)
559+
.uniq.sort_by(&:title)
560+
561+
# get global templates
562+
global_templates = Template.published
563+
.where(is_default: true)
564+
# The next line removes templates that belong to a family that
565+
# has customised templates
566+
.where.not(family_id: customization_ids)
567+
.uniq.sort_by(&:title)
568+
569+
# create templates-grouped hash
570+
@templates_grouped = {
571+
_("Your Organisation's Templates:") => user_org_own_templates.map do |t|
572+
[t.title, t.id]
573+
end,
574+
_("Your Organisation's Customised Templates:") => user_org_custom_templates.map do |t|
575+
[t.title, t.id]
576+
end,
577+
_('Global Templates:') => global_templates.map do |t|
578+
[t.title, t.id]
579+
end,
580+
_('Funder Templates:') => funder_non_customised_templates.map do |t|
581+
[t.title, t.id]
582+
end
583+
}.reject { |_, val| val.empty? }
584+
end
585+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
586+
587+
# Validate that a template_id is available to the org user
588+
def validate_template_available_to_org_user?(template_id, org_id)
589+
return false if template_id.blank? || org_id.blank?
590+
591+
available_templates = templates_available_to_org_user(org_id)
592+
available_template_ids = available_templates.values.flat_map { |group| group.map(&:last) }
593+
available_template_ids.include?(template_id.to_i)
594+
end
571595
end
572596
# rubocop:enable Metrics/ClassLength

0 commit comments

Comments
 (0)