From 313c6e12d5005feb70ff88b7aa3316b2fe3ddcb7 Mon Sep 17 00:00:00 2001 From: Nathan Richards Date: Wed, 19 Aug 2026 16:48:23 +0200 Subject: [PATCH 1/2] fix: allow students to view the Experience CS preview starter --- app/models/ability.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index c8463d1fa..6465ec11b 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -23,7 +23,12 @@ def initialize(user) private def define_common_non_student_abilities(user) - return if user&.student? + if user&.student? + # Allow students to view the Experience CS preview starter template. + can :show, Project, user_id: nil, school_id: nil, project_type: Project::Types::CODE_EDITOR_SCRATCH + can :show, Component, project: { user_id: nil, school_id: nil, project_type: Project::Types::CODE_EDITOR_SCRATCH } + return + end # Anyone can view projects not owned by a user or a school. can :show, Project, user_id: nil, school_id: nil From 40d4f8c41fc8dabc33446e0c4b620da113ec65ba Mon Sep 17 00:00:00 2001 From: Nathan Richards Date: Wed, 19 Aug 2026 18:13:47 +0200 Subject: [PATCH 2/2] test: cover student preview permission with persisted role --- spec/models/ability_spec.rb | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb index fb9965129..8efeb3930 100644 --- a/spec/models/ability_spec.rb +++ b/spec/models/ability_spec.rb @@ -147,6 +147,34 @@ end end + context 'with a persisted school student' do + let(:school) { create(:school) } + let(:user) { create(:user, id: user_id) } + let(:public_scratch_starter) do + build(:project, + user_id: nil, + school_id: nil, + project_type: Project::Types::CODE_EDITOR_SCRATCH) + end + let(:public_python_starter) do + build(:project, + user_id: nil, + school_id: nil, + project_type: Project::Types::PYTHON) + end + let(:public_scratch_component) { build(:component, project: public_scratch_starter) } + let(:public_python_component) { build(:component, project: public_python_starter) } + + before do + create(:student_role, user_id: user.id, school:) + end + + it { is_expected.to be_able_to(:show, public_scratch_starter) } + it { is_expected.not_to be_able_to(:show, public_python_starter) } + it { is_expected.to be_able_to(:show, public_scratch_component) } + it { is_expected.not_to be_able_to(:show, public_python_component) } + end + context 'with an experience-cs admin' do let(:user) { build(:experience_cs_admin_user, id: user_id) } let(:another_project) { build(:project) }