From 8cf7d58c398277b6d9ad7df768248d5a7e66e304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Morais?= <385232+gnclmorais@users.noreply.github.com> Date: Sat, 6 Dec 2025 17:00:08 +0100 Subject: [PATCH 1/3] Scope selectable organisers on new event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only admins or organisers can create new events, so we were loading thousands of students… Not anymore. Fixes #2411 --- app/models/member.rb | 6 ++++ app/views/admin/events/_form.html.haml | 5 ++- spec/models/member_spec.rb | 44 ++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/app/models/member.rb b/app/models/member.rb index 1b823c7a9..6c62c99a8 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -51,6 +51,12 @@ class Member < ApplicationRecord scope :with_skill, ->(skill_name) { tagged_with(skill_name) } + scope :admin, -> { with_role(:admin) } + scope :organiser, -> { with_role(:organiser, :any) } + scope :manager, -> { admin.or(organiser).distinct } + + scope :sort_alphabetically, -> { order(:name, :surname) } + acts_as_taggable_on :skills attr_accessor :attendance, :newsletter diff --git a/app/views/admin/events/_form.html.haml b/app/views/admin/events/_form.html.haml index cef5ab6b0..70b8a8dc3 100644 --- a/app/views/admin/events/_form.html.haml +++ b/app/views/admin/events/_form.html.haml @@ -1,3 +1,6 @@ +:ruby + all_managers = Member.manager.sort_alphabetically + = simple_form_for [:admin, @event] do |f| .row .col-12 @@ -42,7 +45,7 @@ .col-12.col-md-6.col-lg-4 = f.association :gold_sponsors, input_html: { data: { placeholder: 'Select gold sponsors' }}, collection: Sponsor.all .col-12 - = f.input :organisers, collection: Member.all, value_method: :id, label_method: :full_name, selected: @event.organisers.map(&:id), input_html: { multiple: true } + = f.input :organisers, collection: all_managers, value_method: :id, label_method: :full_name, selected: @event.organisers.pluck(&:id), input_html: { multiple: true } .col-12 = f.input :announce_only, as: :boolean, hint: 'Events where invitations are not handled via our application' .col-12 diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 7b7ab26ae..4e6be3a96 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -164,6 +164,50 @@ expect(Member.find_members_by_name('').size).to eq(0) end end + end + + describe '.admin' do + it 'returns members with admin role' do + admin_member = Fabricate(:member) + admin_member.add_role :admin + non_admin = Fabricate(:member) + + expect(described_class.admin).to include(admin_member) + expect(described_class.admin).not_to include(non_admin) + end + end + + describe '.organiser' do + it 'returns members with organiser role' do + chapter = Fabricate(:chapter) + organiser = Fabricate(:member) + organiser.add_role :organiser, chapter + non_organiser = Fabricate(:member) + expect(described_class.organiser).to include(organiser) + expect(described_class.organiser).not_to include(non_organiser) + end + end + + describe '.manager' do + it 'returns both admins and organisers' do + admin_member = Fabricate(:member) + admin_member.add_role :admin + + chapter = Fabricate(:chapter) + organiser = Fabricate(:member) + organiser.add_role :organiser, chapter + # Add another role to test for duplicates + organiser.add_role :admin + + non_manager = Fabricate(:member) + + managers = described_class.manager + + expect(managers).to include(admin_member, organiser) + expect(managers).not_to include(non_manager) + + expect(managers.size).to eq(managers.distinct.size) + end end end From f04ad33b0109bbf2c8f0e777ec0ffef8ec5ad7e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Morais?= <385232+gnclmorais@users.noreply.github.com> Date: Sat, 6 Dec 2025 17:01:31 +0100 Subject: [PATCH 2/3] Queries sponsors only once on new event --- app/views/admin/events/_form.html.haml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/views/admin/events/_form.html.haml b/app/views/admin/events/_form.html.haml index 70b8a8dc3..8f1dcc77a 100644 --- a/app/views/admin/events/_form.html.haml +++ b/app/views/admin/events/_form.html.haml @@ -1,4 +1,5 @@ :ruby + all_sponsors = Sponsor.all all_managers = Member.manager.sort_alphabetically = simple_form_for [:admin, @event] do |f| @@ -37,13 +38,13 @@ %p %strong Please add sponsors only to either Standard level OR Gold/Silver/Bronze levels. .col-12 - = f.association :sponsors, label: 'Standard sponsors', input_html: { data: { placeholder: 'Select standard sponsors' }}, collection: Sponsor.all + = f.association :sponsors, label: 'Standard sponsors', input_html: { data: { placeholder: 'Select standard sponsors' }}, collection: all_sponsors .col-12.col-md-6.col-lg-4 - = f.association :bronze_sponsors, input_html: { data: { placeholder: 'Select bronze sponsors' }}, collection: Sponsor.all + = f.association :bronze_sponsors, input_html: { data: { placeholder: 'Select bronze sponsors' }}, collection: all_sponsors .col-12.col-md-6.col-lg-4 - = f.association :silver_sponsors, input_html: { data: { placeholder: 'Select silver sponsors' }}, collection: Sponsor.all + = f.association :silver_sponsors, input_html: { data: { placeholder: 'Select silver sponsors' }}, collection: all_sponsors .col-12.col-md-6.col-lg-4 - = f.association :gold_sponsors, input_html: { data: { placeholder: 'Select gold sponsors' }}, collection: Sponsor.all + = f.association :gold_sponsors, input_html: { data: { placeholder: 'Select gold sponsors' }}, collection: all_sponsors .col-12 = f.input :organisers, collection: all_managers, value_method: :id, label_method: :full_name, selected: @event.organisers.pluck(&:id), input_html: { multiple: true } .col-12 From c699ee712f3ae7caeb30c9275da65b75587f6558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Morais?= <385232+gnclmorais@users.noreply.github.com> Date: Sat, 6 Dec 2025 17:01:47 +0100 Subject: [PATCH 3/3] Tidy up a few helpful method for user --- app/controllers/application_controller.rb | 4 ++-- app/models/member.rb | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index fc90f2386..f41c5acd6 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -105,7 +105,7 @@ def redirect_path end def authenticate_admin! - redirect_to root_path, notice: "You can't be here" unless logged_in? && current_user.has_role?(:admin) + redirect_to root_path, notice: "You can't be here" unless logged_in? && current_user.is_admin? end def authenticate_admin_or_organiser! @@ -113,7 +113,7 @@ def authenticate_admin_or_organiser! end def manager? - logged_in? && (current_user.is_admin? || current_user.has_role?(:organiser, :any)) + logged_in? && current_user.manager? end helper_method :manager? diff --git a/app/models/member.rb b/app/models/member.rb index 6c62c99a8..c96b0fed4 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -61,6 +61,10 @@ class Member < ApplicationRecord attr_accessor :attendance, :newsletter + def manager? + is_admin? || has_role?(:organiser, :any) + end + def banned? bans.active.present? || bans.permanent.present? end