Skip to content

Commit 5215472

Browse files
committed
Restrict what lesson params can be updated
Previously any params could be updated in lessons which was dangerous - we don't expect many of these params to be updated to changing them could create odd behaviour or allow other data to be accessed. I've checked the frontend, and only the name and visibility can be updated. I've done this now so that users can't turn their projects into Scratch projects unexpectedly. We could add attributes back in in the future if we want to.
1 parent 55ddf92 commit 5215472

3 files changed

Lines changed: 22 additions & 13 deletions

File tree

app/controllers/api/lessons_controller.rb

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def show
3030
end
3131

3232
def create
33-
result = Lesson::Create.call(lesson_params:)
33+
result = Lesson::Create.call(lesson_params: create_params)
3434

3535
if result.success?
3636
@lesson_with_user = result[:lesson].with_user
@@ -41,7 +41,7 @@ def create
4141
end
4242

4343
def create_copy
44-
result = Lesson::CreateCopy.call(lesson: @lesson, lesson_params:)
44+
result = Lesson::CreateCopy.call(lesson: @lesson, lesson_params: create_params)
4545

4646
if result.success?
4747
@lesson_with_user = result[:lesson].with_user
@@ -54,7 +54,7 @@ def create_copy
5454
def update
5555
# TODO: Consider removing user_id from the lesson_params for update so users can update other users' lessons without changing ownership
5656
# OR consider dropping user_id on lessons and using teacher id/ids on the class instead
57-
result = Lesson::Update.call(lesson: @lesson, lesson_params:)
57+
result = Lesson::Update.call(lesson: @lesson, lesson_params: update_params)
5858

5959
if result.success?
6060
@lesson_with_user = result[:lesson].with_user
@@ -78,8 +78,8 @@ def filtered_lessons_scope
7878
end
7979

8080
def verify_school_class_belongs_to_school
81-
return if base_params[:school_class_id].blank?
82-
return if school&.classes&.pluck(:id)&.include?(base_params[:school_class_id])
81+
return if create_params[:school_class_id].blank?
82+
return if school&.classes&.pluck(:id)&.include?(create_params[:school_class_id])
8383

8484
raise ParameterError, 'school_class_id does not correspond to school_id'
8585
end
@@ -105,14 +105,20 @@ def user_remix(lesson)
105105
end
106106

107107
def scratch_project?
108-
base_params.dig(:project_attributes, :project_type) == Project::Types::CODE_EDITOR_SCRATCH
108+
create_params.dig(:project_attributes, :project_type) == Project::Types::CODE_EDITOR_SCRATCH
109109
end
110110

111-
def lesson_params
112-
base_params.merge(user_id: current_user.id)
111+
def update_params
112+
params.fetch(:lesson, {}).permit(
113+
:name,
114+
:visibility,
115+
{
116+
project_attributes: [:name]
117+
}
118+
)
113119
end
114120

115-
def base_params
121+
def create_params
116122
params.fetch(:lesson, {}).permit(
117123
:school_id,
118124
:school_class_id,
@@ -129,15 +135,15 @@ def base_params
129135
{ scratch_component: {} }
130136
]
131137
}
132-
)
138+
).merge(user_id: current_user.id)
133139
end
134140

135141
def school_owner?
136142
school && current_user.school_owner?(school)
137143
end
138144

139145
def school
140-
@school ||= @lesson&.school || School.find_by(id: base_params[:school_id]) || SchoolClass.find_by(id: params[:school_class_id])&.school
146+
@school ||= @lesson&.school || School.find_by(id: create_params[:school_id]) || SchoolClass.find_by(id: params[:school_class_id])&.school
141147
end
142148
end
143149
end

spec/features/lesson/creating_a_lesson_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
new_params = { lesson: params[:lesson].merge(user_id: 'ignored') }
9595

9696
post('/api/lessons', headers:, params: new_params)
97+
expect(response).to have_http_status(:created)
9798
data = JSON.parse(response.body, symbolize_names: true)
9899

99100
expect(data[:user_id]).to eq(teacher.id)

spec/features/lesson/updating_a_lesson_spec.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,17 @@
117117
expect(response).to have_http_status(:ok)
118118
end
119119

120-
it 'responds 422 Unprocessable Entity when trying to re-assign the lesson to a different class' do
120+
it 'does not allow re-assigning the lesson to a different class' do
121121
school = create(:school, id: SecureRandom.uuid)
122122
teacher = create(:teacher, school:)
123123
school_class = create(:school_class, school:, teacher_ids: [teacher.id])
124124

125125
new_params = { lesson: params[:lesson].merge(school_class_id: school_class.id) }
126126
put("/api/lessons/#{lesson.id}", headers:, params: new_params)
127+
expect(response).to have_http_status(:ok)
127128

128-
expect(response).to have_http_status(:unprocessable_content)
129+
lesson.reload
130+
expect(lesson.school_class_id).not_to eq(school_class.id)
129131
end
130132
end
131133
end

0 commit comments

Comments
 (0)