Skip to content

Commit c75c8a3

Browse files
author
Scott Adams
committed
trial either checking for owner role or if project has associations
1 parent e0e4faf commit c75c8a3

File tree

4 files changed

+33
-21
lines changed

4 files changed

+33
-21
lines changed

app/controllers/api/lessons_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def create_copy
4242
end
4343

4444
def update
45-
result = Lesson::Update.call(lesson: @lesson, lesson_params:)
45+
result = Lesson::Update.call(lesson: @lesson, lesson_params:, current_user:)
4646

4747
if result.success?
4848
@lesson_with_user = result[:lesson].with_user

app/models/project.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# frozen_string_literal: true
22

33
class Project < ApplicationRecord
4+
attr_accessor :current_user
5+
46
belongs_to :school, optional: true
57
belongs_to :lesson, optional: true
68
belongs_to :parent, optional: true, class_name: :Project, foreign_key: :remixed_from_id, inverse_of: :remixes
@@ -17,7 +19,7 @@ class Project < ApplicationRecord
1719
validate :identifier_cannot_be_taken_by_another_user
1820
validates :locale, presence: true, unless: :user_id
1921
validate :user_has_a_role_within_the_school
20-
validate :user_is_a_member_or_the_owner_of_the_lesson
22+
validate :user_is_a_member_or_the_owner_of_the_lesson_or_school
2123

2224
scope :internal_projects, -> { where(user_id: nil) }
2325

@@ -79,9 +81,14 @@ def user_has_a_role_within_the_school
7981
errors.add(:user, msg)
8082
end
8183

82-
def user_is_a_member_or_the_owner_of_the_lesson
84+
def user_is_a_member_or_the_owner_of_the_lesson_or_school
8385
return if !lesson || user_id == lesson.user_id || lesson.school_class&.members&.exists?(student_id: user_id)
8486

87+
# either we explicitly check the user is an owner of the school
88+
return if current_user&.school_owner?(lesson.school)
89+
# or we bypass if the lesson is associated with a school but not a school class
90+
return if lesson.school && !lesson.school_class && !lesson.school_class&.members&.any?
91+
8592
errors.add(:user, "'#{user_id}' is not the owner or a member of the lesson '#{lesson_id}'")
8693
end
8794
end

lib/concepts/lesson/operations/update.rb

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
class Lesson
44
class Update
55
class << self
6-
def call(lesson:, lesson_params:)
6+
def call(lesson:, lesson_params:, current_user:)
77
response = OperationResponse.new
88
response[:lesson] = lesson
99
response[:lesson].assign_attributes(lesson_params)
1010
response[:lesson].save!
1111
if lesson_params[:name].present?
12-
rename_lesson_project(lesson: response[:lesson], name: lesson_params[:name])
13-
rename_lesson_remixes(lesson: response[:lesson], name: lesson_params[:name])
12+
rename_lesson_project(current_user:, lesson: response[:lesson], name: lesson_params[:name])
13+
rename_lesson_remixes(current_user:, lesson: response[:lesson], name: lesson_params[:name])
1414
end
1515
response
1616
rescue StandardError => e
@@ -20,20 +20,20 @@ def call(lesson:, lesson_params:)
2020
response
2121
end
2222

23-
def rename_lesson_project(lesson:, name:)
23+
def rename_lesson_project(current_user:, lesson:, name:)
2424
return unless lesson.project
2525

26+
lesson.project.current_user = current_user
2627
lesson.project.assign_attributes(name:)
27-
# TODO: determine school owner mechanism for project model validation rather than skipping validation
28-
lesson.project.save!(validate: false)
28+
lesson.project.save!
2929
end
3030

31-
def rename_lesson_remixes(lesson:, name:)
31+
def rename_lesson_remixes(current_user:, lesson:, name:)
3232
lesson_remixes = Project.where(remixed_from_id: lesson.project.id)
3333
lesson_remixes.each do |remix|
34+
remix.current_user = current_user
3435
remix.assign_attributes(name:)
35-
# TODO: determine school owner mechanism for project model validation rather than skipping validation
36-
remix.save!(validate: false)
36+
remix.save!
3737
end
3838
end
3939
end

spec/concepts/lesson/update_spec.rb

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,38 @@
88
let(:student) { create(:student, school:) }
99
let(:lesson) { create(:lesson, name: 'Test Lesson', user_id: teacher.id) }
1010
let!(:student_project) { create(:project, remixed_from_id: lesson.project.id, user_id: student.id) }
11+
let(:current_user) { authenticated_user }
1112

1213
let(:lesson_params) do
1314
{ name: 'New Name' }
1415
end
1516

17+
before do
18+
authenticated_in_hydra_as(teacher)
19+
end
20+
1621
it 'returns a successful operation response' do
17-
response = described_class.call(lesson:, lesson_params:)
22+
response = described_class.call(lesson:, lesson_params:, current_user:)
1823
expect(response.success?).to be(true)
1924
end
2025

2126
it 'updates the lesson' do
22-
response = described_class.call(lesson:, lesson_params:)
27+
response = described_class.call(lesson:, lesson_params:, current_user:)
2328
expect(response[:lesson].name).to eq('New Name')
2429
end
2530

2631
it 'updates the project name' do
27-
described_class.call(lesson:, lesson_params:)
32+
described_class.call(lesson:, lesson_params:, current_user:)
2833
expect(lesson.project.name).to eq('New Name')
2934
end
3035

3136
it 'updates the student project name' do
32-
described_class.call(lesson:, lesson_params:)
37+
described_class.call(lesson:, lesson_params:, current_user:)
3338
expect(student_project.reload.name).to eq('New Name')
3439
end
3540

3641
it 'returns the lesson in the operation response' do
37-
response = described_class.call(lesson:, lesson_params:)
42+
response = described_class.call(lesson:, lesson_params:, current_user:)
3843
expect(response[:lesson]).to be_a(Lesson)
3944
end
4045

@@ -46,22 +51,22 @@
4651
end
4752

4853
it 'does not update the lesson' do
49-
response = described_class.call(lesson:, lesson_params:)
54+
response = described_class.call(lesson:, lesson_params:, current_user:)
5055
expect(response[:lesson].reload.name).to eq('Test Lesson')
5156
end
5257

5358
it 'returns a failed operation response' do
54-
response = described_class.call(lesson:, lesson_params:)
59+
response = described_class.call(lesson:, lesson_params:, current_user:)
5560
expect(response.failure?).to be(true)
5661
end
5762

5863
it 'returns the error message in the operation response' do
59-
response = described_class.call(lesson:, lesson_params:)
64+
response = described_class.call(lesson:, lesson_params:, current_user:)
6065
expect(response[:error]).to match(/Error updating lesson/)
6166
end
6267

6368
it 'sent the exception to Sentry' do
64-
described_class.call(lesson:, lesson_params:)
69+
described_class.call(lesson:, lesson_params:, current_user:)
6570
expect(Sentry).to have_received(:capture_exception).with(kind_of(StandardError))
6671
end
6772
end

0 commit comments

Comments
 (0)